简体   繁体   English

摇摆动画不起作用

[英]Swing animation not working

So, for a personal project, I've been trying to create a program in Java that can make a rudimentary animation appear on a Swing application. 因此,对于一个个人项目,我一直试图用Java创建一个程序,该程序可以使基本的动画出现在Swing应用程序中。 As far as I know, I've done everything right, and as far as I know it's working, but when I run the application, it does not let me close the application without Task Manager, and when I force quit the app IntelliJ tells me "process finished with exit code 1". 据我所知,我已正确完成了所有事情,并且据我所知它正在运行,但是当我运行该应用程序时,它不允许我在没有任务管理器的情况下关闭该应用程序,并且当我强制退出该应用程序时,IntelliJ会告诉您我“进程完成,退出代码为1”。 It's also not displaying my animation on the screen despite displaying normal Graphics things such as lines. 尽管显示了诸如线条之类的常规Graphics内容,但它也没有在屏幕上显示我的动画。

Here is my JFrame code: 这是我的JFrame代码:

package animtest;

import javax.swing.*;

public class AnimTest extends JFrame {

    public void addComponents() {
        AnimPanel panel = new AnimPanel();
        setContentPane(panel);
    }

    public AnimTest(String string) {
        super(string);
    }

    public static void main(String[] args) {
        AnimTest frame = new AnimTest("Animation Test");

        frame.addComponents();
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

}

Here is my JPanel code: 这是我的JPanel代码:

package animtest;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class AnimPanel extends JPanel {

    Image[] marsExploding = new Image[3];

    public AnimPanel() {
        try {
            marsExploding[0] = ImageIO.read(new File("res/MarsExploding.png"));
            marsExploding[1] = ImageIO.read(new File("res/MarsExploding2.png"));
            marsExploding[2] = ImageIO.read(new File("res/MarsExploding3.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void paintComponent(Graphics g2) {
        Graphics2D g = (Graphics2D) g2.create();
        g.setColor(Color.white);

        for (int i = 0; i < marsExploding.length; i++) {
            g.drawImage(marsExploding[i], (getWidth() / 2) - 128, (getHeight() / 2) - 128, 256, 256, null);

            try {
                TimeUnit.SECONDS.sleep(500);
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }

            g.fillRect(0, 0, getWidth(), getHeight());
        }

        g.dispose();
        repaint();
    }

}

Any help is greatly appreciated, thank you! 任何帮助,不胜感激,谢谢!

EDIT 1 编辑1

OK, so this is my new panel code, which should honor Swing's contract and concurrency: 好的,这是我的新面板代码,应该遵守Swing的合同和并发性:

package animtest;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
public class AnimPanel extends JPanel {

    Image[] marsExploding = new Image[3];

    Graphics2D g;

    int currentFrame = 0;

    public AnimPanel() {
        try {
            marsExploding[0] = ImageIO.read(new File("res/MarsExploding.png"));
            marsExploding[1] = ImageIO.read(new File("res/MarsExploding2.png"));
            marsExploding[2] = ImageIO.read(new File("res/MarsExploding3.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

        Timer timer = new Timer(500, null);
        timer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                displayNewFrame(currentFrame);

                if (currentFrame < 2) {
                    currentFrame++;
                } else {
                    currentFrame = 0;
                }
            }
        });
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g2) {
        super.paintComponent(g2);

        g = (Graphics2D) g2.create();
    }

    public void displayNewFrame(int frame) {
        g.fillRect(0, 0, getWidth(), getHeight());

        g.drawImage(marsExploding[frame], (getWidth() / 2) - 128, (getHeight() / 2) - 128, 256, 256, null);
    }

}

However this doesn't actually display anything to the screen. 但是,这实际上并没有在屏幕上显示任何内容。

Swing is a single threaded framework, this means, that any call which is long running or blocking made from within the context of the Event Dispatching Thread will prevent the UI from been updated or allow the user to interact with it, making your UI appear as if it's hung (because it essentially has). Swing是一个单线程框架,这意味着任何长时间运行或在事件调度线程的上下文内进行的调用都将阻止UI的更新或允许用户与其交互,从而使您的UI显示为如果已挂起(因为它实际上已经挂了)。

See Concurrency in Swing for more details. 有关更多详细信息,请参见Swing中的并发

Instead of trying to use TimeUnit.SECONDS.sleep(500); 而不是尝试使用TimeUnit.SECONDS.sleep(500); inside a paint method, you should have some background thread which ticks at a regular interval and allows you to update the UI accordingly. paint方法内部,您应该有一些背景线程,该线程每隔固定的时间间隔滴答一声,并允许您相应地更新UI。 The problem is, Swing is also not thread safe, meaning that you should never try and create or update the UI from outside the context of the Event Dispatching Thread. 问题是,Swing也不是线程安全的,这意味着您永远不要尝试从事件调度线程的上下文外部创建或更新UI。

For a basic solution, you can, however, use a Swing Timer , which will trigger a ActionListener on a regular bases within the context of the EDT, making it safe to use with the UI. 但是,对于基本解决方案,您可以使用Swing Timer ,它将在EDT上下文内的常规基础上触发ActionListener ,从而可以安全地与UI一起使用。

See How to use Swing Timers for more details. 有关更多详细信息,请参见如何使用Swing计时器

Painting in Swing is performed by a series of chained method calls, custom painting requires you to insert your code within on of these links, paintComponent been the most preferred. Swing中的绘制是通过一系列链接的方法调用执行的,自定义绘制需要您在这些链接中的其中一个中插入代码, paintComponent是最优选的。

However, you are expected to honor the contract of these links by calling the super paint method you are overriding. 但是,您应该通过调用您要覆盖的super paint方法来履行这些链接的约定。

See Painting in AWT and Swing and Performing Custom Painting for more details 有关更多详细信息,请参见AWT中的绘画和摇摆执行自定义绘画

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM