英文:
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 < 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.
[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 < 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);
}
}
}
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->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);
}
Finally, you need to set your MatrixPanel
size large enough to hold the image. Probably 300 x 300
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论