Getting JButtons to refresh labels during each cycle of loop
Ok so the goal of this program is to get the red x from one side of the "bridge" (made up of 7 JButtons) to the otherside of the window. I'm trying to get the buttons to refresh the text displayed on them after each cycle of the loop so that it looks like the red x crosses the bridge. Any help on to why it isn't refreshing based on the following code would be incredible.
Thanks for your time
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GeorgeBridge extends JApplet implements ActionListener{
// Create a frame to hold the contents of application
JFrame frame = new JFrame ("George's Big Bridge Crossing");
// Panel to hold the bridge
JPanel bridgePanel = new JPanel(new GridLayout(1,7));
/* The following JLabels are used for spacing of the panels in the frame to make the window look more like a bridge
* crossing over a river
*/
JLabel northLabel = new JLabel(" ");
JLabel eastLabel = new JLabel(" ");
JLabel westLabel = new JLabel(" ");
// Asks the user whether or not they would like George to cross the bridge
JLabel southLabel = new JLabel("Would you like George to cross the Bridge?");
// George is represented by a red X
String george = "X";
// An array of 7 JButtons to act as the bridge
JButton [] bridge = new JButton [7];
int spot;
public void init() {
bridge[0] = new JButton ("");
bridge[1] = new JButton ("");
bridge[2] = new JButton ("");
bridge[3] = new JButton ("");
bridge[4] = new JButton ("");
bridge[5] = new JButton ("");
bridge[6] = new JButton ("");
// Set the program to exit when the JFrame is closed
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
//set a border layout manager to the frame
frame.setLayout(new BorderLayout());
// Background set to look like water under the bridge
bridgePanel.setBackground (new Color(0,191,246));
// Panel to make it look like the bridge is crossing a river
JPanel northPanel = new JPanel();
northPanel.setBackground (new Color (0,191,246));
// Panel to make it look like the bridge is crossing a river
JPanel eastPanel = new JPanel();
eastPanel.setBackground (new Color (0,184,48));
// Panel to make it look like the bridge is crossing a river
JPanel southPanel = new JPanel();
southPanel.setBackground (new Color (0,191,246));
// Panel to make it look like the bridge is crossing a river
JPanel westPanel = new JPanel();
westPanel.setBackground (new Color(0,184,48));
// JButton to let the user choose when George crosses the bridge
JButton cross = new JButton("Make George cross!");
cross.setActionCommand("cross");
cross.addActionListener(this);
// Starts George standing on the West Bank
westLabel.setText(george);
// Makes George red so he is more visible
westLabel.setForeground(new Color(255,0,0));
// Makes George size 24 font so he is more visible
westLabel.setFont(westPanel.getFont().deriveFont(24.0f));
// Initiates the first button that represents a foot of the bridge
// bridge[0] = new JButton ("");
bridge[0].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[0].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[0].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Initiates the second button that represents a foot of the bridge
// bridge[1] = new JButton ("");
bridge[1].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[1].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[1].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Initiates the third button that represents a foot of the bridge
// bridge[2] = new JButton ("");
bridge[2].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[2].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[2].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Initiates the fourth button that represents a foot of the bridge
// bridge[3] = new JButton ("");
bridge[3].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[3].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[3].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Initiates the fifth button that represents a foot of the bridge
// bridge[4] = new JButton ("");
bridge[4].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[4].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[4].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Initiates the sixth button that represents a foot of the bridge
// bridge[5] = new JButton ("");
bridge[5].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[5].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[5].setFont(bridge[0].getFont().deri开发者_如何转开发veFont(24.0f));// Set the font for George to 24
// Initiates the seventh button that represents a foot of the bridge
// bridge[6] = new JButton ("");
bridge[6].setBackground(new Color(143,66,19));// Set the background to a brown to make the bridge look like a wooden bridge
bridge[6].setForeground(new Color(255,0,0));// Set the colour of George to red
bridge[6].setFont(bridge[0].getFont().deriveFont(24.0f));// Set the font for George to 24
// Add the bridge buttons to the bridge panel
bridgePanel.add(bridge[0]);
bridgePanel.add(bridge[1]);
bridgePanel.add(bridge[2]);
bridgePanel.add(bridge[3]);
bridgePanel.add(bridge[4]);
bridgePanel.add(bridge[5]);
bridgePanel.add(bridge[6]);
// Add the labels and buttons to the 4 border panels
northPanel.add(northLabel);
eastPanel.add(eastLabel);
southPanel.add(southLabel);
southPanel.add(cross);
westPanel.add(westLabel);
// Add all the panels to the JFrame
frame.getContentPane().add(northPanel, BorderLayout.NORTH);
frame.getContentPane().add(eastPanel, BorderLayout.EAST);
frame.getContentPane().add(bridgePanel, BorderLayout.CENTER);
frame.getContentPane().add(southPanel, BorderLayout.SOUTH);
frame.getContentPane().add(westPanel, BorderLayout.WEST);
// Set the JFrame size and visibility
frame.setSize(450,150);
frame.setVisible(true);
}
public void actionPerformed (ActionEvent event) {
new Thread (new Runnable() {
public void run() {
moveGeorge();
}
}).start();
}
public void moveGeorge() {
for(int i=0; i<7; i++) {
spot = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
if (spot > 0) {
bridge[spot].setText(george);
bridge[spot-1].setText("");
}
else {
westLabel.setText("");
bridge[spot].setText(george);
}
try
{
Thread.sleep(1000); // do nothing for 1000 miliseconds (1 second)
}
catch(InterruptedException e)
{
e.printStackTrace();
}
frame.setVisible(true);
}
});
}
}
}
Thread.sleep(1000); // do nothing for 1000 miliseconds (1 second)
Never use Thread.sleep() while code is executing on the Event Dispatch Thread. Thats prevents the GUI from responding to events and from repainting itself.
That code needs to be moved outside of the invokeLater() code.
See Concurrency in Swing for more information about the EDT.
Off topic, but it won't fit into a comment:
- Use a loop, to initialize equal components.
- Use names like 'brown' instead of comments, mostly repeating the code
Use defined values like Color.RED
Color brown = new Color (143,66,19); for (int i = 0; i < 7; ++i) { bridge[i] = new JButton (""); bridge[i].setBackground (brown); bridge[i].setForeground (Color.RED); bridge[i].setFont (bridge [0].getFont ().deriveFont (24.0f)); bridgePanel.add (bridge[i]); }
This saves you 30 lines of code.
First of all, swing is not thread safe.
Instead of using Thread.sleep() and screwing with the EDT (event dispatch thread) use the Swing Timer
Secondly, try adding a couple ${JComponent}.revalidate() and ${JComponent}.repaint() right after you modify ${JComponent}
For Example
// Starts George standing on the West Bank
westLabel.setText(george);
// Makes George red so he is more visible
westLabel.setForeground(new Color(255,0,0));
// Makes George size 24 font so he is more visible
westLabel.setFont(westPanel.getFont().deriveFont(24.0f));
//VVVV NOW ADD THIS VVVV
westLabel.revalidate();
westLabel.repaint();
精彩评论