当通过事件从另一个窗口打开时,Java图形窗口不会绘制

当通过事件从另一个窗口打开时,Java图形窗口不会绘制,java,swing,jframe,jpanel,graphics2d,Java,Swing,Jframe,Jpanel,Graphics2d,我有三个班,第一个是主窗口 public class Starter extends JFrame{ JButton b=new JButton("Game"); Starter(){ setSize(200,200); add(b); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ TryGraph gg=

我有三个班,第一个是主窗口

public class Starter extends JFrame{
JButton b=new JButton("Game");
Starter(){

    setSize(200,200);
    add(b);
    b.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e){
            TryGraph gg=new TryGraph();
        }
    });
    setVisible(true);

}
public static void main(String [] args){
    Starter g= new Starter();

}
}

第二个类是一个窗口,它有一个面板,图形将在上面绘制

public class TryGraph {
static int w=640,h=480;
TryGraph(){
    JFrame mF=new JFrame();
    GPan pan=new GPan();

    mF.setLocationRelativeTo(null);
    mF.setResizable(false);
    mF.setSize(w,h);

    mF.add(pan);

    mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mF.setVisible(true);

    pan.playGame();
}

public static void main(String []args){
    TryGraph t=new TryGraph();
}
}

最后是绘制图形的panel类

public class GPan extends JPanel{

private boolean running;
private BufferedImage image;
private Graphics2D g;
int x,y;

public GPan(){
    x=TryGraph.w;
    y=TryGraph.h;
    init();
}

public void init(){
    running=true;
    image=new BufferedImage(x,y,BufferedImage.TYPE_INT_RGB);
    g=(Graphics2D)image.getGraphics();
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}

public void playGame(){
    while(running){
         g.setColor(new Color(102,102,102));
        g.fillRect(0,0,x,y);
        g.setColor(new Color(255,0,0));
        g.fillOval(0, 0, 100,100);
        repaint();
    }
}

public void paintComponent(Graphics g){
    Graphics2D g2 = (Graphics2D)g;
    g2.drawImage(image,0,0,x,y,null);

    g2.dispose();
}
}


问题是,如果我使用从Starter类窗口到TryGraph类窗口的事件,GPan面板在循环通过play game方法时不会绘制图形。但是当TryGraph类直接执行时,它工作得很好

我注意到了几个问题

在TryGraph中调用main时,将创建一个新实例。但当按下按钮时,您已经有了TryGraph的实例

不要扩展JFrame。这是个坏习惯。只需创建它的一个实例

仅使用一个静态主入口点

最大的问题是你把重绘放在一个紧密的循环中。不要那样做。只需重新油漆。请记住,重新绘制是在事件分派线程上运行的。因此,如果这根线被绑住了,其他的就没用了

不要丢弃图形上下文。如果你创建了一个新的,你就可以这样做,但是不要放弃它

最后,将super.paintComponent作为JPanel paintComponent方法中的第一条语句

我建议你读一读关于绘画和EDT的书

这是修改后的代码,全部放在一个文件中

导入java.awt.Color; 导入java.awt.Graphics; 导入java.awt.Graphics2D; 导入java.awt.RenderingHints; 导入java.awt.event.ActionEvent; 导入java.awt.event.ActionListener; 导入java.awt.image.buffereImage; 导入javax.swing.JButton; 导入javax.swing.JFrame; 导入javax.swing.JPanel; 公开课初学者{ JButton b=新JButtonGame; JFrame frame=新JFrame; 起动器{ frame.setSize200,200; frame.addb; frame.setDefaultCloseOperationJFrame.EXIT_ON_CLOSE; b、 AddActionListener新建ActionListener{ 公共无效诉讼执行事件e{ TryGraph gg=新TryGraph; } }; frame.setVisibletrue; } 公共静态无效字符串[]args{ 启动器g=新启动器; } } 类图{ 静态int w=640,h=480; 录像机{ JFrame mF=新JFrame; GPan-pan=新的GPan; mF.setLocationRelativeTonull; mF.setresizeablefalse; mF.setSizew,h; 艾德潘博士; mF.setDefaultCloseOperationJFrame.EXIT_ON_CLOSE; mF.setVisibletrue; 泛游戏; } } 类GPan扩展了JPanel{ 私有布尔运行; 私有缓冲图像; 私有图形2dg; int x,y; 公共GPan{ x=TryGraph.w; y=TryGraph.h; 初始化; } 公共无效初始{ 运行=真; 图像=新的BuffereImage x,y,BuffereImage.TYPE\u INT\u RGB; g=Graphics2D image.getGraphics; g、 setRenderingHintRenderingHints.KEY\u抗锯齿, RenderingHints.VALUE_ANTIALIAS_ON; } 公开游戏{ 重新油漆; } 公共空间组件图形{ 超级油漆组件; Graphics2D g2=Graphics2D g.create; g2.setColornew Color102、102、102; g2.0,0,x,y; g2.setColornew Color255,0,0; g2.fillOval0,01000; //g2.drawImageimage,0,0,x,y,null; g2.1处置; } }
另一项建议。在您的原始代码中,我相信您是通过在私有类中实现接口来实现侦听器的。好主意,不过您应该为给定接口扩展适配器类。例如,对于mouseListener,扩展MouseAdapter。它提供了虚拟方法,因此您不必自己创建它们。它有助于提高代码的可读性。当然,单一方法接口没有或不需要适配器。

这里的代码太多了。你能提供一个例子来说明你的问题吗?@WJS我将用一个较短版本的code@WJS现在检查一下。这是代码的基本框架,在底部解释的问题循环是必要的,因为我试图在游戏中使用它。我需要循环来不断更新图像,但不要使用循环。还有其他选择。例如,当有人在游戏中做了一些重要的事情时,让他们调用重新绘制。使重绘调用成为事件驱动。或者您可以设置一个计时器,请参阅Java Swing timer类。经常打电话重画。但是如果你把它重新刷一遍,它会锁定EDT,没有任何东西能正常工作。谢谢,我试过之后会给你回复