Java中的简单动画

Nat*_*han 1 java graphics animation swing netbeans

我正在尝试在 Java Swing 应用程序中编写一个简单的动画或物理示例。我已经打开并运行了实际的 Windows 应用程序,但我无法弄清楚如何实际绘制我的形状,以及如何格式化用于帧之间计算的代码,诸如此类的东西。

我读过一些关于重写绘制方法的内容,但我不知道这意味着什么,而且我不相信我在现在使用的代码中使用它。这是我的代码:

public class Physics extends JFrame{

public Physics() {

    initUI();
}

private void initUI() {
    JPanel panel = new JPanel();
    getContentPane().add(panel);

    panel.setLayout(null);

    final JLabel label = new JLabel("Hi, press the button to do something");
    label.setBounds(20, 0, 2000, 60);


    final JButton submitButton = new JButton("Start");
    submitButton.setBounds(20, 150, 80, 20);
    submitButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            //Put button code here later
        }
    });

    panel.add(label);
    panel.add(submitButton);

    setTitle("Program");
    setSize(300, 250);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            Physics ex = new Physics();
            ex.setVisible(true);
        }
    });
}

}
Run Code Online (Sandbox Code Playgroud)

因此,我的按钮上方有一些空白区域,我想在其中画一个在屏幕上移动的正方形或圆形作为开始,一旦我把它记下来,我就可以开始进入更高级的东西。任何关于如何做到这一点的提示将被采纳:D

谢谢!

Pau*_*tha 6

“我读过一些关于超越绘制方法的内容,但我不知道这意味着什么”

所以你已经重写了actionPerformed,所以你知道 an@Override是什么。正如您从 中注意到的ActionListener,您实际上从未显式调用actionPerformed,但无论您在其中放入什么,仍然会被使用。那是因为ActionListener它隐式地为你调用它。

绘画也是如此。在 Swing 绘制过程中,有一个 Swing 用于绘制组件的绘制链。一路上paint有一个地方叫。因此,就像一样actionPerformed,您可以覆盖它paint,它会被隐式调用。

@Override
public void paint(Graphics g) {
    super.paint(g);
}
Run Code Online (Sandbox Code Playgroud)

传递给该方法的对象Graphics是 Swing 将用于绘制的图形上下文。您可以查看 来Graphics API了解可以使用的方法。你可以用它drawOval来画一个圆

@Override
public void paint(Graphics g) {
    super.paint(g);
    g.drawOval(x, y, width, height);
}
Run Code Online (Sandbox Code Playgroud)

现在事情是这样的。您实际上并不想覆盖paint. 在上面链接的教程中,一些示例将使用小程序和 override paint,但您不应该在顶级容器(例如JFrame或 )上进行绘制JAppletJPanel相反,在or上绘制JComponent,然后将其添加到JFrame. 当您在or上进行绘制时,您将覆盖(它也会沿着绘制链被调用),而不是JPanelJComponentpaintComponentpaint

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawOval(x, y, width, height);
}
Run Code Online (Sandbox Code Playgroud)

您会看到我如何在该方法中使用变量drawOval。是x距屏幕顶部的 x 位置,yy 点。widthheight是圆的宽度和高度。使用变量的好处是它们的值可以在运行时更改。

这就是动画发挥作用的地方。正如所指出的,您可以使用javax.swing.Timer

基本构造是

public Timer(int delay, ActionListener listener) {
}
Run Code Online (Sandbox Code Playgroud)

delay每次调用侦听器时延迟的毫秒数。侦听器将收到您的actionPerformed回调,该回调将每毫秒执行一次内部操作delay。所以你能做的就是改变x和,它就会有动画效果。就像是drawOvalrepaint()

Timer timer = new Timer(40, new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        x += 5;
        repaint();
    }
});
timer.start();
Run Code Online (Sandbox Code Playgroud)

您可以将计时器代码放入构造函数中。这可能是我能给出的最简单的解释。希望能帮助到你。

不要忘记查看自定义绘画Grapics2D以获取有关图形的更多高级主题。另请参阅此处此处以及此处此处此处的一些计时器和动画示例


还要避免使用空布局。请参阅在容器内布局组件以了解如何使用布局管理器,就像使用 Swing 应用程序一样。