我有一个扩展JLabel的类叫做Cell:Inside Cell有两种方法,kill()
和revive()
。当一个Cell恢复时,它会使用setBackground()
更改其颜色。我有一个名为LifePanel
的JPanel,其中包含这些Cell的矩阵。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class LifeDriver {
public static void main(String[] args) {
System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
SwingUtilities.invokeLater( new Runnable() {
public void run()
{
JFrame frame = new JFrame("Life");
frame.setSize(950, 800);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new MainPanel(80, 100));
frame.setVisible(true);
}
} );
}
}
class MainPanel extends JPanel {
private LifePanel p;
private ControlPanel c;
private JScrollPane pane;
public MainPanel(int ro, int co) {
setLayout(new BorderLayout());
p = new LifePanel(ro, co);
p.setPreferredSize(new Dimension(740, 740));
pane = new JScrollPane(p);
pane.setBorder(null);
pane.setAutoscrolls(true);
add(pane, BorderLayout.CENTER);
c = new ControlPanel(p);
add(c, BorderLayout.NORTH);
}
}
class ControlPanel extends JPanel {
private JButton random;
private LifePanel lp;
public ControlPanel(LifePanel p) {
lp = p;
random = new JButton("Random");
random.addActionListener(new Listener());
add(random);
}
private class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
try {
double prob = Double.parseDouble(JOptionPane
.showInputDialog("Percentage Probability?"));
lp.randomize(prob);
} catch (Exception f) {
}
}
}
}
class LifePanel extends JPanel {
private Cell[][] grid;
private Timer t;
private static int nR, nC;
public LifePanel(int row, int column) {
nR = row;
nC = column;
setLayout(new GridLayout(nR, nC, 1, 1));
grid = new Cell[nR][nC];
for (int r = 0; r < nR; r++)
for (int c = 0; c < nC; c++) {
grid[r][c] = new Cell();
add(grid[r][c]);
}
}
public void randomize(double percent) {
for (int r = 0; r < nR; r++)
for (int c = 0; c < nC; c++)
if (Math.random() < percent / 100)
grid[r][c].revive();
else
grid[r][c].kill(false);
}
}
class Cell extends JLabel {
private Color deadCellColor = new Color(245, 245, 245);
public Cell() {
this.setBackground(deadCellColor);
this.setOpaque(true);
this.setAlive(false);
}
public void kill(boolean removeCell) {
this.setAlive(false);
}
public void revive() {
this.setAlive(true);
}
public void setAlive(boolean arg) {
if (arg) {
this.changeColor();
} else {
this.setBackground(deadCellColor);
}
}
private void changeColor() {
setBackground(Color.RED);
}
}
当我调用randomize时,它可以工作(随机设置每个JLabel的颜色),但不是我期望它的方式。每个标签的颜色不是一次只出现,而是以随机方式出现(类似于powerpoint中的溶解效果?)。颜色甚至不是逐列逐列显示,正如for循环可能建议的那样。它看起来完全随机,即使订单是预先确定的。关于它为什么这样做的任何想法?
答案 0 :(得分:3)
要在更改单元格状态时避免更新,您只需更改父面板LifePanel
的可见性即可。像这样:
public void randomize(double percent) {
// No updates while we change state
setVisible(false);
for (int r = 0; r < nR; r++) {
for (int c = 0; c < nC; c++) {
if (Math.random() < percent / 100)
grid[r][c].revive();
else
grid[r][c].kill(false);
}
}
// Update now
setVisible(true);
}
我怀疑无论是跟踪脏矩形(即需要在屏幕上重新绘制的东西)都没有按照预期的方式排序实际的重新绘制更新。这似乎是这种情况,因为在更新所有单元格之后要求重新绘制LifePanel
似乎也可以按预期工作:
public void randomize(double percent) {
for (int r = 0; r < nR; r++) {
for (int c = 0; c < nC; c++) {
if (Math.random() < percent / 100)
grid[r][c].revive();
else
grid[r][c].kill(false);
}
}
// Force redraw of whole panel
this.repaint();
}