java - 动画不添加到 JFrame

标签 java swing graphics

我是 java swing 的新手,如果我的错误非常明显,请原谅我。我的代码在这里应该做的是创建一个 JFrame 并为两个并排向上移动穿过框架的盒子设置动画。但是,我只看到一个框(由 ElevatorOne 类创建的蓝色框)。绿色框(来自 ElevatorTwo)没有出现。这是我的代码:

Execute 类(使用 main 方法):

public class Execute {

public static void main (String[ ] args) {

    Thread thread1 = new Thread() {
        public void run() {
            ElevatorOne e1 = new ElevatorOne();
            e1.createFrame(800, 600);
            e1.addElevatorOne();
        }
    };

    Thread thread2 = new Thread() {
        public void run() {
            ElevatorTwo e2 = new ElevatorTwo();
            e2.addElevatorTwo();
        }
    };

    thread1.start();
    thread2.start();

}

}

ElevatorOne 类(绘制蓝色框的类):

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

public class ElevatorOne extends GUI{

int y = 400;

public void addElevatorOne() {

    DrawElevatorOne drawE1 = new DrawElevatorOne();
    frame.getContentPane().add(drawE1);

    for(int i = 0; i < 300; i++) {
        y--;

        drawE1.repaint();

        try {
            Thread.sleep(20);
        } catch (Exception ex) { }
    }

}

@SuppressWarnings("serial")
class DrawElevatorOne extends JPanel{
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());

        g.setColor(Color.BLUE);
        g.drawRect(200,y,80,120);
    }
}

}

ElevatorTwo 类(绘制绿色框的类,没有出现在我的 JFrame 中):

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

public class ElevatorTwo extends GUI{

int y = 400;

public void addElevatorTwo() {
    DrawElevatorTwo drawE2 = new DrawElevatorTwo();
    frame.getContentPane().add(drawE2);

    for(int i = 0; i < 300; i++) {
        y--;

        drawE2.repaint();

        try {
            Thread.sleep(20);
        } catch (Exception ex) { }
    }
}

@SuppressWarnings("serial")
class DrawElevatorTwo extends JPanel{
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.GREEN);
        g.drawRect(600,y,80,120);
    }
}

}

最后,GUI 类(创建 frame 的地方):

import javax.swing.JFrame;

public class GUI {

JFrame frame = new JFrame();

public void createFrame(int x, int y) {
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.setSize(x, y);
    frame.setVisible(true);
}

}

最佳答案

正如您在 previous question 中评论的那样...

Your addElevatorOne is likely going to block the EDT, meaning it I'll only paint the last position after a short delay. Consider using a Swing Timer instead to do the animation...

正如你所问的......

in the swing timer, would I call the repaint() method every time it repeats itself?

是的。 Swing Timer 将作为一个 psudo 循环,每次它滴答作响时,您将更新 y 变量,检查它是否超出您的要求并停止 Timer 如果它执行并调用 repaint

看看Concurrency in SwingHow to use Swing Timers了解更多详情

此外,Swing 不是线程安全的,这意味着您永远不应该从 EDT 上下文之外以任何方式修改 UI。我们建议使用 Swing Timer 的原因是因为它会在 EDT 的上下文中调用已注册的 ActionListener,从而可以安全地修改 UI

让我们重新考虑这个问题。你的代码有点复杂,很难理解。与其使用所有“多个”框架,不如集中精力制作一个知道如何移动的 Elevator...

public class Elevator extends JPanel {

    private int y = 0;
    private int delta = 1;
    private Color fillColor;

    public Elevator(Color color, boolean goingDown) {
        fillColor = color;

        if (goingDown) {
            y = 0;
            delta = 1;
        } else {
            y = getPreferredSize().height - 120;
            delta = -1;
        }

        Timer timer = new Timer(40, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                y += delta;
                if (y + 120 > getHeight()) {
                    y = getHeight() - 120;
                    delta *= -1;
                } else if (y < 0) {
                    y = 0;
                    delta *= -1;
                }
                repaint();
            }
        });
        timer.start();
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(81, 120 * 3);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(fillColor);
        g.drawRect(0, y, 80, 120);
    }

}

非常简单,它是 JPanel,具有自定义绘画来绘制实际的电梯,它设置了电梯轿厢宽度的首选尺寸,但高度是电梯轿厢的三倍(三层楼)和有自己的 Timer 来移动汽车。

构造函数允许您自定义颜色和初始移动方向

这是一个独立的工作单元。只要您不必同时运行许多电梯,就可以正常工作。如果您需要很多电梯,那么您将需要一个中央 Timer,所有电梯都会从中收到“计时器”事件的通知,但这是另一个问题的讨论。

现在,您只需要向他们展示...

Going up or down

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setLayout(new GridLayout(0, 2));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new Elevator(Color.GREEN, true));
                frame.add(new Elevator(Color.BLUE, false));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

关于java - 动画不添加到 JFrame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30904426/

相关文章:

带有 VB.NET 客户端的 Java 套接字服务器?

java - 缩放图像的 Swing 滚动条

javascript - 在 html5 canvas 中填充圆弧轮廓

graphics - "renderInContext:"和 CATransform3D

cocoa - 如何绘制模糊的形状?

java - 在 Maven 项目的模块内共享类

java - 找不到符号类 KeyEvent

java - 如何设置字段的值以便我可以从另一个类调用它?

java - 在 Java swing 中制作第二个框架

java - 将值从 java GUI 插入到 postgresql 数据库中