更改帧的显示,每隔一段时间,就像动画一样。

huangapple go评论106阅读模式
英文:

Changing the frame's display after every interval, like an animation

问题

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);
    }
}

Specifically not repaint, if there are other components that I can use and meet my requirements will be most welcome.

Thank you.


<details>
<summary>英文:</summary>
How can I use repaint here, that it changes the display after some interval, like an animation?
Ouput: 
(Like initially and randomly it is) [this-1][1] (after some short interval and randomly it changes to) [this-2][2] and continued...

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 &lt; 300; i += this.sqW) {
for (int j = 0; j &lt; 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(&quot;GenerationLabel&quot;);
generationLabel.setText(&quot;Generation #&quot;);
generationLabel.setFont(new Font(&quot;Comic Sans MS&quot;, Font.PLAIN, 14));
generationLabel.setBounds(10, 5, 300, 20);
/*Label - 2*/
JLabel aliveLabel = new JLabel(&quot;AliveLabel&quot;);
aliveLabel.setText(&quot;Alive: &quot;);
aliveLabel.setFont(new Font(&quot;Comic Sans MS&quot;, 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);
}

}


Specifically not repaint, if there are other components that I can use and meet my requirements will be most welcome.
Thank you.
[1]: https://i.stack.imgur.com/8Mxsz.png
[2]: https://i.stack.imgur.com/FpP1D.png
</details>
# 答案1
**得分**: 0
你不希望执行以下操作:
```java
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对象中创建图像。BufferedImage提供图形上下文,因此您可以使用与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);
    // 图像观察器不需要,因此可以设置为null。
    g.drawImage(image, 0, 0, null);
}

最后,您需要将MatrixPanel的大小设置为足够大,以容纳图像。可能是300 x 300

英文:

You don't want to do the following:

    public void paintComponent(Graphics g) {
Random rand = new Random();
for (int i = 0; i &lt; 300; i += this.sqW) {
for (int j = 0; j &lt; 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);
}
}
}

Since painting is done on the EDT, you need to keep your processing to a minimum, otherwise performance will suffer and you may even lock up your application.

Use a Swing timer and create the image in a BufferedImage object. BufferedImages provide a graphics context so you can use the same methods you are using in paintComponent.

You can set the timer interval to whatever works for you and then issue a repaint when the image is created. So it could look similar to the following:

final BufferedImage image = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
...		
Timer timer = new Timer(0, ae-&gt;createImage());
timer.setDelay(300);
timer.start();
...	 
public void createImage(BufferedImage image) {
Random rand = new Random();
Graphics g = image.getGraphics();
for (int i = 0; i &lt; 300; i += this.sqW) {
for (int j = 0; j &lt; 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);
}

Finally, you need to set your MatrixPanel size large enough to hold the image. Probably 300 x 300.

huangapple
  • 本文由 发表于 2020年8月25日 20:58:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63579388.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定