首页 > 解决方案 > 在每个间隔后更改帧的显示,就像动画一样

问题描述

我如何在这里使用重绘,它会在一段时间后改变显示,就像动画一样?

输出:

(就像最初和随机一样)this-1(经过一段时间后随机变为)this-2并继续......

import java.awt.*;
import java.util.Random;
import javax.swing.*;

class MatrixPanel extends JPanel {

    private final int sqW = 15;
    private final int sqH = 15; 

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 300);
    }

    @Override
    public void paintComponent(Graphics g) {
        Random rand = new Random();
        for (int i = 0; i < 300; i += this.sqW) {
            for (int j = 0; j < 300; j += this.sqH) {
                if (rand.nextInt(2) == 1) {
                    g.setColor(Color.BLACK);
                } else {
                    g.setColor(Color.GRAY);
                }
                g.fillRect(i, j, this.sqW, this.sqH);
                g.setColor(Color.BLACK);
                g.drawRect(i, j, this.sqW, this.sqH);
            }
        }
    }
}

class GameOfLifeGUI extends JFrame {

    public GameOfLifeGUI() {

        JSplitPane splitPane = new JSplitPane();

        /*Panels*/
        JPanel topPanel = new JPanel();
        JPanel bottomPanel = new JPanel();
        
        /*Label - 1*/
        JLabel generationLabel = new JLabel("GenerationLabel");
        generationLabel.setText("Generation #");
        generationLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
        generationLabel.setBounds(10, 5, 300, 20);

        /*Label - 2*/
        JLabel aliveLabel = new JLabel("AliveLabel");
        aliveLabel.setText("Alive: ");
        aliveLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 14));
        aliveLabel.setBounds(10, 25, 300, 20);

        topPanel.setLayout(null);
        topPanel.add(generationLabel);
        topPanel.add(aliveLabel);

        bottomPanel.add(new MatrixPanel());

        setPreferredSize(new Dimension(315, 405));

        getContentPane().setLayout(new GridLayout());

        getContentPane().add(splitPane);

        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        splitPane.setDividerLocation(50);
        splitPane.setTopComponent(topPanel);
        splitPane.setBottomComponent(bottomPanel);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        pack();
    }

    public static void main(String[] args) {
        new GameOfLifeGUI().setVisible(true);
    }
}

具体不重绘,如果有其他我可以使用并满足我的要求的组件将是最受欢迎的。

谢谢你。

标签: javaswing

解决方案


您不想执行以下操作:

    public void paintComponent(Graphics g) {
        Random rand = new Random();
        for (int i = 0; i < 300; i += this.sqW) {
            for (int j = 0; j < 300; j += this.sqH) {
                if (rand.nextInt(2) == 1) {
                    g.setColor(Color.BLACK);
                } else {
                    g.setColor(Color.GRAY);
                }
                g.fillRect(i, j, this.sqW, this.sqH);
                g.setColor(Color.BLACK);
                g.drawRect(i, j, this.sqW, this.sqH);
            }
        }
    }

由于绘画是在 EDT 上完成的,因此您需要将处理保持在最低限度,否则性能会受到影响,甚至可能会锁定您的应用程序。

使用Swing 计时器并在BufferedImage对象中创建图像。BufferedImages 提供了一个图形上下文,因此您可以使用您在paintComponent.

您可以将计时器间隔设置为适合您的任何时间,然后在创建图像时发出重绘。所以它可能类似于以下内容:

final BufferedImage image = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
...     
Timer timer = new Timer(0, ae->createImage());
timer.setDelay(300);
timer.start();
...  
    
public void createImage(BufferedImage image) {
    Random rand = new Random();
    Graphics g = image.getGraphics();
    for (int i = 0; i < 300; i += this.sqW) {
        for (int j = 0; j < 300; j += this.sqH) {
            if (rand.nextInt(2) == 1) {
                g.setColor(Color.BLACK);
            } else {
                g.setColor(Color.GRAY);
            }
            g.fillRect(i, j, this.sqW, this.sqH);
            g.setColor(Color.BLACK);
            g.drawRect(i, j, this.sqW, this.sqH);
        }
    }
    repaint();
}
    
    
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    // Image observer not required so it can be set to null.
    g.drawImage(image, 0,0, null);
}

最后,您需要将MatrixPanel尺寸设置为足够大以容纳图像。大概300 x 300


推荐阅读