[英]Extending JPanel to draw Image. But on the same Panel added to JFrame
更新 :正如Dmich所指出的,因為我在我的面板類之外進行繪制,所以這導致對MyPanel和Animation類的初始化進行遞歸調用。 因此,如何仍然可以在Animation類的MyPanel上完成繪制,但是沒有這個問題。
我的代碼有一個非常具體的問題,我不知道如何描述正在發生的事情,但是我會盡力而為。 我嘗試搜索stackOverFLow,但問題是我什至不知道要搜索什么 。
我來啦:
為了盡力組織起來,我將首先編寫我要處理的所有類。
public class MyPanel extends JPanel implements Runnable{
private Animation anim = new Animation();
}
public class Animation extends ??? implements KeyListener{}
因此,我有一個名為MyPanel的類,該類擴展了JPanel。 我已經使用add(new MyPanel())
此類添加到了JFrame中,我在MyPanel中使用了一個線程,該線程調用@Overrid @Overrid public void paintComponent(Graphics g)
paintComponent調用了Animation中的方法,這是我在屏幕上繪制圖像的方法g2d.drawImage(image, int, int, ImageObserver)
問題是使用此方法時,我需要一個ImageObserver,如果Animation擴展了JPanel,則可以獲取它。 但是,如果我擴展JPanel,則不會在我的JFrame上繪制任何內容,因為這是一個未添加到JFrame的新jPanel。
但是,如果我擴展MyPanel(添加到我的JFrame中),則會遇到很多錯誤。
Eclipse錯誤:
Exception in thread "main" java.lang.StackOverflowError
at java.awt.Component.setBackground(Unknown Source)
at javax.swing.JComponent.setBackground(Unknown Source)
at javax.swing.LookAndFeel.installColors(Unknown Source)
at javax.swing.LookAndFeel.installColorsAndFont(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JPanel.setUI(Unknown Source)
at javax.swing.JPanel.updateUI(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
在此錯誤消息下,這兩行一直持續到被月食終止為止。
at MyPanel.<init>(MyPanel.java:9)
at Animation.<init>(Animation.java:9)
任何幫助將不勝感激。
更新2根據建議添加代碼示例:
import javax.swing.JFrame;
public class Simulation extends JFrame {
private MyPanel panel = new MyPanel();
public Simulation() {
initUI();
}
private void initUI() {
add(panel);
setResizable(false);
pack();
setTitle("Simulation");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); // centers
}
public static void main(String[] args) {
Simulation ex = new Simulation();
ex.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
public class MyPanel extends JPanel implements Runnable {
private Animation anim;
public MyPanel() {
anim = new Animation();
initPanel();
}
private void initPanel() {
//other customizables
}
@Override
public void run() {
//Thread that calls repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
anim.step(g2D, this);
}
}
import java.awt.Graphics2D;
public class Animation {
private Sprite player;
private KeyBinder kB;
public Animation() {
player = new Sprite();
kB = new KeyBinder(player);
}
public void step(Graphics2D g2d, JPanel p) {
player.move();
drawSprite(g2d, p);
}
private void drawSprite(Graphics2D g2d, JPanel p) {
g2d.drawImage(player.getImage(), player.getX(), player.getY(), p);
}
}
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
public class Sprite {
private final String PLAYER_IMAGE_FILE = "Image location";
private Image image;
private int width, height;
private int x, y, dx, dy;
public Sprite() {
x = 0;
y = 0;
loadImage();
}
private void loadImage() {
ImageIcon ii = new ImageIcon(PLAYER_IMAGE_FILE);
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
}
public void move() {
x += dx;
y += dy;
}
public void keyPressed(KeyEvent e) {
//assings meaning to keypressed
}
public void keyReleased(KeyEvent e) {
//assings meaning to keyReleased
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getW() {
return width;
}
public int getH() {
return height;
}
public Image getImage() {
return image;
}
}
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class KeyBinder extends MyPanel implements KeyListener {
Sprite p;
public KeyBinder(Sprite player) {
p = player;
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
@Override
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
@Override
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
@Override
public void keyTyped(KeyEvent e) {
}
}
通過嘗試對代碼進行故障排除,我對代碼進行了更改,主要是通過嘗試將JPanel傳遞給Animation.step方法,並嘗試創建一個單獨的類來進行鍵偵聽。
新的錯誤列表大致相同:
Exception in thread "main" java.lang.StackOverflowError
at java.awt.Component.setBackground(Unknown Source)
at javax.swing.JComponent.setBackground(Unknown Source)
at javax.swing.LookAndFeel.installColors(Unknown Source)
at javax.swing.LookAndFeel.installColorsAndFont(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installDefaults(Unknown Source)
at javax.swing.plaf.basic.BasicPanelUI.installUI(Unknown Source)
at javax.swing.JComponent.setUI(Unknown Source)
at javax.swing.JPanel.setUI(Unknown Source)
at javax.swing.JPanel.updateUI(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
at javax.swing.JPanel.<init>(Unknown Source)
然后無限循環,直到以下三行終止:
at MyPanel.<init>(MyPanel.java:10)
at KeyBinder.<init>(KeyBinder.java:6)
at Animation.<init>(Animation.java:11)
因此,我有一個名為Panel的類,該類擴展了JPanel。 我已經使用add(new Panel())將此類添加到了JFrame中,我在Panel中使用了一個線程,該線程調用@Overrid public void paintComponent(Graphics g)
首先,Swing不是線程安全的,您不應從事件調度線程的上下文外部更新UI。
其次,決不應該存在直接調用paintComponent
情況,也不需要public
它,因為沒有別的東西可以調用它。
有關更多詳細信息,請參見Swing中的並發。
paintComponent在Animation中調用一個方法,在該方法中,我將圖像繪制到屏幕上g2d.drawImage(image,int,int,ImageObserver)。 問題是使用此方法時,我需要一個ImageObserver,如果Animation擴展了JPanel,則可以獲取它。
為什么不讓Animation
“可繪畫的”,從而提供一種方法,該方法要求調用者傳遞您所需的信息才能完成工作?
public class Animation {
public void paint(Graphics2D g2d, ImageObserver observer) {
//...
}
}
您還可以將其他可能需要的信息傳遞給paint
方法,例如對當前狀態建模的模型。
這基本上是一個委派模型-在這里,您將特定任務的責任“委托”給另一個班級
那么
KeyListener
呢?
我聽到你問。
好吧,首先,處理它可能不是Animation
的責任。 相反,控制器應該響應事件來修改狀態,該狀態最終由渲染器繪制
另外,您應該改用Key bindings API ,它將解決與KeyListener
相關的不可靠性問題
我不建議使類擴展JPanel,而是在實例化時使用JPanel參數:
public class Panel implements Runnable{
private JPanel panel;
public Panel(JPanel panel){
this.panel = panel;
}
}
另外,我認為使Panel類具有Extend Component是明智的,以便在將其添加到標題中提到的現有面板時進行無縫集成:
public class Panel extends Component implements Runnable{
private JPanel panel;
public Panel(JPanel panel){
this.panel = panel;
}
}
如果這不起作用,或者您對此還有其他疑問,請告訴我!
這是繼承不良小伙子的另一起案件。 我通過在MYPanel類中實現KeyListener並將MyPanel作為Animation的參數傳遞來修復了它。 對我來說,嘗試從另一個類實現JPanel的keyListener是不好的做法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.