Java 动画和SwingUtilities.invokeLater

Java 动画和SwingUtilities.invokeLater,java,swing,animation,event-dispatch-thread,invokelater,Java,Swing,Animation,Event Dispatch Thread,Invokelater,我想使用方法SwingUtilities.invokeLater,这样我的程序的所有Swing组件都会由事件调度线程更新,因为这是一种很好的做法 但是如果我将main方法的所有代码包装在SwingUtilities.invokeLater(新的Runnable{public void run(){/*code*/})中窗口冻结(这是正常的,因为我的代码有一个动画循环,需要几秒钟才能完成)。我应该把SwingUtilities.invokeLater方法放在哪里 程序代码(不带SwingUtili

我想使用方法
SwingUtilities.invokeLater
,这样我的程序的所有Swing组件都会由事件调度线程更新,因为这是一种很好的做法

但是如果我将
main
方法的所有代码包装在
SwingUtilities.invokeLater(新的Runnable{public void run(){/*code*/})中窗口冻结(这是正常的,因为我的代码有一个动画循环,需要几秒钟才能完成)。我应该把
SwingUtilities.invokeLater
方法放在哪里

程序代码(不带
SwingUtilities.invokeLater
方法)
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.geom.Rectangle2D;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.image.buffereImage;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公开课考试{
公共静态void main(字符串[]args){
整数宽度=854;
内部高度=480;
字符串title=“Test”;
BuffereImage BuffereImage=新的BuffereImage(宽度、高度、BuffereImage.TYPE_INT_RGB);
JFrame=新JFrame();
JPanel面板=新的JPanel(){
受保护的空心油漆组件(图形){
super.paintComponent(图形);
Graphics2D Graphics2D=(Graphics2D)图形;
graphics2D.drawImage(BuffereImage,0,0,null);
}
};
框架。添加(面板);
frame.getContentPane().setPreferredSize(新维度(宽度、高度));
frame.pack();
frame.setTitle(标题);
frame.setLocationRelativeTo(空);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
内部尺寸=高度/3;
int x=-大小;

而(x这是一个自包含的代码(顺便说一句,发布该代码很好)更新为使用@MadProgrammer建议的
计时器
。为了访问
x
变量,它被移动到为计时器定义的操作侦听器中。为了从操作侦听器中访问
计时器
,它被移动为类属性。后者意味着更容易移动大部分将代码转换为对象实例的构造函数

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Test {

    Timer timer;

    Test() {
        int width = 854;
        int height = 480;
        String title = "Test";
        BufferedImage bufferedImage = new BufferedImage(
                width, height, BufferedImage.TYPE_INT_RGB);
        JFrame frame = new JFrame();
        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics graphics) {
                super.paintComponent(graphics);
                Graphics2D graphics2D = (Graphics2D) graphics;
                // when you have an ImageObserver, may as well use it
                //graphics2D.drawImage(bufferedImage, 0, 0, null);
                graphics2D.drawImage(bufferedImage, 0, 0, this);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(width,height);
            }
        };
        frame.add(panel);
        frame.pack();
        frame.setTitle(title);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        int size = height / 3;

        ActionListener animationListener = new ActionListener() {

            int x = -size;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (x <= width) {
                    Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();
                    graphics2D.setColor(Color.RED);
                    graphics2D.fill(new Rectangle2D.Double(x, 0, size, size));
                    graphics2D.setColor(Color.GREEN);
                    graphics2D.fill(new Rectangle2D.Double(x, size, size, size));
                    graphics2D.setColor(Color.BLUE);
                    graphics2D.fill(new Rectangle2D.Double(x, 2 * size, size, size));
                    graphics2D.dispose();
                    panel.repaint();
                    ++x;
                } else {
                    timer.stop();
                    frame.dispose();
                }
            }
        };
        timer = new Timer(10, animationListener);
        timer.start();
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            new Test();
        };
        SwingUtilities.invokeLater(r);
    }
}
import java.awt.*;
导入java.awt.event.*;
导入java.awt.geom.Rectangle2D;
导入java.awt.image.buffereImage;
导入javax.swing.*;
公开课考试{
定时器;
测试(){
整数宽度=854;
内部高度=480;
字符串title=“Test”;
BuffereImage BuffereImage=新的BuffereImage(
宽度、高度、缓冲区图像。类型\u INT\u RGB);
JFrame=新JFrame();
JPanel面板=新的JPanel(){
@凌驾
受保护的空心油漆组件(图形){
super.paintComponent(图形);
Graphics2D Graphics2D=(Graphics2D)图形;
//如果你有ImageObserver,不妨使用它
//graphics2D.drawImage(BuffereImage,0,0,null);
graphics2D.drawImage(BuffereImage,0,0,this);
}
@凌驾
公共维度getPreferredSize(){
返回新尺寸(宽度、高度);
}
};
框架。添加(面板);
frame.pack();
frame.setTitle(标题);
frame.setLocationRelativeTo(空);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
内部尺寸=高度/3;
ActionListener animationListener=新建ActionListener(){
int x=-大小;
@凌驾
已执行的公共无效操作(操作事件e){
if(x){
新测试();
};
SwingUtilities.invokeLater(r);
}
}

while loop
正在阻止EDT,从而阻止更新。Swing
计时器
可能是您正在寻找的解决方案。请先看一下启动程序。您需要将计时器视为一个伪循环,每次它滴答作响时,它都充当循环的迭代。因为它在EDT的上下文中更新,所以可以安全地使用来更新UIC,你的主静态方法中的代码太多了。事实上,你的程序只是一个大的静态主方法。相反,你的代码应该更符合OOPs,你的主方法应该只用于创建主类,将它们连接在一起,启动它们运行,就这样。动画,嗯嗯…哦,你听说过JavaFX吗?Swing是为动画非常繁重的旧系统设计的。现在有更强的CPU能力,加上硬件加速,Swing有些过时了。JavaFX让动画很容易使用。因为,@MadProgrammer有些人是混血儿。我总是喜欢你的答案。这是我的一个小小的“放纵”nce给出了一个很好的自我包含的例子——我就是忍不住。如果人们想否决投票,他们可以破产。)我在回答这样的问题时也有一些被否决的答案,但正如你所做的,当我看到自我包含的代码中有一些努力和一个很好的解释时,我也忍不住回答(1+btw)谢谢,这正是我想要的。现在我明白了
定时器
课程的目的。欢迎光临。很高兴我能提供帮助,请继续发布可运行代码和明确问题的工作。:)
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Test {

    Timer timer;

    Test() {
        int width = 854;
        int height = 480;
        String title = "Test";
        BufferedImage bufferedImage = new BufferedImage(
                width, height, BufferedImage.TYPE_INT_RGB);
        JFrame frame = new JFrame();
        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics graphics) {
                super.paintComponent(graphics);
                Graphics2D graphics2D = (Graphics2D) graphics;
                // when you have an ImageObserver, may as well use it
                //graphics2D.drawImage(bufferedImage, 0, 0, null);
                graphics2D.drawImage(bufferedImage, 0, 0, this);
            }

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(width,height);
            }
        };
        frame.add(panel);
        frame.pack();
        frame.setTitle(title);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        int size = height / 3;

        ActionListener animationListener = new ActionListener() {

            int x = -size;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (x <= width) {
                    Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics();
                    graphics2D.setColor(Color.RED);
                    graphics2D.fill(new Rectangle2D.Double(x, 0, size, size));
                    graphics2D.setColor(Color.GREEN);
                    graphics2D.fill(new Rectangle2D.Double(x, size, size, size));
                    graphics2D.setColor(Color.BLUE);
                    graphics2D.fill(new Rectangle2D.Double(x, 2 * size, size, size));
                    graphics2D.dispose();
                    panel.repaint();
                    ++x;
                } else {
                    timer.stop();
                    frame.dispose();
                }
            }
        };
        timer = new Timer(10, animationListener);
        timer.start();
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            new Test();
        };
        SwingUtilities.invokeLater(r);
    }
}