Java paintComponent()仅在最小化屏幕时调用

Java paintComponent()仅在最小化屏幕时调用,java,swing,paintcomponent,repaint,event-dispatch-thread,Java,Swing,Paintcomponent,Repaint,Event Dispatch Thread,我正在尝试开发一个游戏,在其中我需要画一个网格。为此,我使用了paintComponent(Graphics g)方法,该方法由repaint()方法调用 问题是repaint方法在无限While循环中,除非最小化和最大化屏幕,否则它从不调用paintComponent()方法。之后,它工作正常,并在while循环中完美地调用paintComponent() 简而言之,我需要通过最小化最大化屏幕来触发它 有人能帮我吗 在代码中可以看到3个类,即Frame.java、MenuHandler.jav

我正在尝试开发一个游戏,在其中我需要画一个网格。为此,我使用了
paintComponent(Graphics g)
方法,该方法由
repaint()
方法调用

问题是repaint方法在无限While循环中,除非最小化和最大化屏幕,否则它从不调用
paintComponent()
方法。之后,它工作正常,并在while循环中完美地调用
paintComponent()

简而言之,我需要通过最小化最大化屏幕来触发它

有人能帮我吗

在代码中可以看到3个类,即Frame.java、MenuHandler.java和Screen.java。代码从Frame类中的main方法开始,并在Screen扩展JPanel时将Screen类添加到自身中。但是,只有当用户在菜单上选择“创建地图”时,控件才会转到Screen类。然后MenuHandler类将控件传递给Screen类,在createMap方法中调用run方法,我在这个run方法中调用repaint方法。 如此包装

public class Screen extends JPanel implements Runnable {
    Frame frame;

    public Screen(Frame frame) {
        this.frame = frame;
    }

    public void createMap() {

        thread.start();
    }

    public void paintComponent(Graphics g) {
        g.setColor(Color.BLUE);

    }

    @Override
    public void run() {

        System.out.println("Success******");

        long lastFrame = System.currentTimeMillis();

        int frames = 0;
        running = true;
        scene = 0;

        // the map grid would be refreshed every 2 ms so that we don't get the
        // flickering effect
        while (running) {

            frames++;

            if (System.currentTimeMillis() - 1000 >= lastFrame) {
                fps = frames;
                frames = 0;
                lastFrame = System.currentTimeMillis();
            }

            // to draw stuff all the time on the screen : goes around 2 millions
            // frames per second. Which is of no use.
            repaint();

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }
}
运行方法中的计时器代码:

 public void run() {

    System.out.println("Success");

    long lastFrame = System.currentTimeMillis();

    int frames = 0;
    running = true;
    scene = 0;

    // the map grid would be refreshed every 2 ms so that we don't get the
    // flickering effect
    while (running) {

        frames++;

        if (System.currentTimeMillis() - 1000 >= lastFrame) {
            fps = frames;
            frames = 0;
            lastFrame = System.currentTimeMillis();
        }
        System.out.println("before repaint");
        // to draw stuff all the time on the screen : goes around 2 millions
        // frames per second. Which is of no use.
        ActionListener taskPerformer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                repaint();
            }
        };

        new Timer(200, taskPerformer).start();
        System.out.println("after repaint");

        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.exit(0);
 }

我解决了这个问题。这只是一行代码,我必须添加它来触发paintComponent方法,而不是通过最小化最大化窗口来实现

Frame是我的顶级容器,我正在向Frame添加Screen组件(它扩展了JPanel并实现了paintComponent)。所以,在添加时,早些时候我正在做

frame.add(screen);
我将此更改为:

frame.getContentPane().add(screen);
frame.getContentPane().validate();
添加后调用validate方法为我做到了这一点。我不知道这是否有意义,但是的,这是唯一一条适合我的路线


希望有帮助。

“repaint()方法在无限While循环中”
repaint()
应该由Swing
计时器触发。这代码似乎阻止了EDT。但是为了更快地获得更好的帮助,发布一个(最小完整可验证示例)。我已经用代码和解释更新了问题。好的,因为它使用了另一个线程,所以它没有阻止EDT,但是它正在尝试从EDT更新GUI,这是另一个禁忌。使用
定时器
可确保在EDT上执行更新。我无法编译代码。首先,Frame类中的
menubar
变量是什么?它来自哪里?请按照Andrew的建议发布MCVE,并验证即将发布的代码将按原样编译和运行。最好使用Timer,但也可以尝试在SwingUtilities.invokeAndWait()中包装repaint()调用