让JButtons在循环的每个循环期间刷新标签

时间:2011-08-10 23:44:45

标签: java swing

好的,所以这个程序的目标是将红色x从“桥”的一侧(由7个JButton组成)到窗口的另一侧。我想在循环的每个循环之后让按钮刷新显示在它们上面的文本,这样看起来红色x穿过桥。根据以下代码提供的任何帮助都不会令人难以置信。

感谢您的时间

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().deriveFont(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);
        }
      });
    }
  }
}

3 个答案:

答案 0 :(得分:3)

Thread.sleep(1000); // do nothing for 1000 miliseconds (1 second)

在Event Dispatch Thread上执行代码时,切勿使用Thread.sleep()。这可以防止GUI响应事件和重新绘制自己。

该代码需要移出invokeLater()代码。

有关EDT的详细信息,请参阅Concurrency in Swing

答案 1 :(得分:0)

偏离主题,但不适合评论:

  • 使用循环来初始化相等的组件。
  • 使用“褐色”等名称代替评论,大多重复代码
  • 使用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]);
    }
    

这可以节省30行代码。

答案 2 :(得分:-1)

首先,swing不是线程安全的。

使用Swing Timer

而不是使用Thread.sleep()并使用EDT(事件派发线程)拧紧

其次,在修改$ {JComponent}后立即尝试添加一个$ {JComponent} .revalidate()和$ {JComponent} .repaint()

例如

// 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();