Reputation: 417
I have a class that extends JLabel called Cell: Inside Cell are two methods, kill()
and revive()
. When a Cell is revived, it changes its color using setBackground()
. I have a JPanel called LifePanel
containing a matrix of these Cells.
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);
}
}
When I call randomize, it works (randomly setting the color of each JLabel), but not the way I expect it to. Rather than just appearing all at once, the colors of each label appear in a random fashion (similar to the dissolve effect in powerpoint?). The colors don't even appear row by row, column by column, as the for loop might suggest. It looks completely random, even though the order is predetermined. Any ideas as to why it's doing this?
Upvotes: 3
Views: 172
Reputation: 14829
To avoid the updates while changing the status of the cells, you could just change the visibility of the parent panel LifePanel
. Something like so:
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);
}
I suspect that whatever is keeping track of the dirty rectangles (ie the stuff that needs repainting on the screen) is not ordering the actual repainting updates in the way that might be expected. This seems to be the case, as asking for a repaint of the LifePanel
after updating all the cells appears to also work as might be expected:
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();
}
Upvotes: 3