如何刷新JFrame中包含的按钮的颜色?

Old*_*ool 1 java swing

我正在编写一个小游戏,其中我在JFrame中采用了JButtons网格,我想刷新JFrame中包含的按钮的颜色,这已经可见.如下所述

 void foo(){
     mainFrame.setVisible(true);//mainFrame is defined at class level.
     //color update code for the buttons.
     mainFrame.setVisible(true);
 }
Run Code Online (Sandbox Code Playgroud)

我得到的结果不如预期,我的屏幕被冻结.这不是实现我想要的正确方法吗? 编辑 确定我正在详细解释我想要实现的目标.我有一个类,如: -

import javax.swing.*;
import java.awt.*;
import java.util.*;
class Brick extends JButton{
      public void setRandomColors(){
            int random = (int) (Math.random()*50);
            if(random%13==0){
                this.setBackground(Color.MAGENTA);
            }
            else if(random%10==0){
                this.setBackground(Color.red);
            }
            else if(random%9==0){

                this.setBackground(Color.yellow);
            }
            else if(random%7==0){
                this.setBackground(Color.orange);
            }
            else if(random%2==0){
                this.setBackground(Color.cyan);
            }
            else{
                this.setBackground(Color.PINK);
            }
    }
    public void setBlackColor(){
            this.setBackground(Color.black);
    }
}
class Grid {
    JFrame mainGrid = new JFrame();
    ArrayList<Brick> bunchOfBricks = new ArrayList<>();
    int gridLength = 8;//gridlenth is equals to gridweight as i have considered a Square grid.
    int totalBricks = gridLength*gridLength;
    public void formBunchOfBricks(){
            for(int i=0;i<totalBricks;i++){
                      bunchOfBricks.add(new Brick());
            }
    }
    public void formColoredGrid(){
            Brick aBrick;
            mainGrid.setLayout(new GridLayout(8,8));
            for(int i=0;i<totalBricks;++i){
                      aBrick = (bunchOfBricks.get(i));
                      aBrick.setRandomColors();
                      mainGrid.add(aBrick);
            }
            mainGrid.setVisible(true);//its ok upto here iam getting randomly colored Frame of Bricks or so called JButtons.
            delay(15);//Sorry for this one,i warn you not to laugh after looking its defination.

    }
 /*
 I want following function to do following things:-
 1.it should firstly display the Grid whose all buttons are black Colored.
 2.After some time the original colored,first Row of grid formed by formColoredGrid should be                         displayed and all the rest Rows should be black.
 3.Then second row turns colored and all other rows should be black......and so on upto last row of Grid.
 */
   public void movingRows(){
          setGridBlack();
          delay(1);//see in upper method,for this horrible thing.
          for(int i=0;i<gridLength;++i){
                setGridBlack();
                for (int j=0;j<gridLength;++j){
                     Brick aBrick = bunchOfBricks.get((gridLength*i)+j);
                     aBrick.setRandomColors();//Bricks are colored Row by Row.
                }
          delay(5);//already commented this nonsense.
          mainGrid.setVisible(true);//using setVisible again,although this frame is already visible,when i called formColoredGrid.

          setGridBlack();
        }
 //oh! disappointing,i have almost broken my arm slamming it on table that why the function result in a  screen full of black buttons.
    }
   public void setGridBlack(){
          for(int i=0;i<totalBricks;i++){
                   bunchOfBricks.get(i).setBlackColor();
          }
   }
   public void delay(int a){
        for ( int i=0;i<90000000;++i){
            for(int j=0;j<a;++j){

            }
        }
   }
   public static void main(String args[]){
          Grid g1 = new Grid();
          g1.formBunchOfBricks();
          g1.formColoredGrid();
          g1.movingRows();
}
Run Code Online (Sandbox Code Playgroud)

}

请帮我解决问题?

Hov*_*els 5

您的问题是代码未显示在此处:

//color update code for the buttons.
Run Code Online (Sandbox Code Playgroud)

您可能正在运行一个永远不会在Swing事件线程上结束的循环,可能是一个永不停止的while循环,它会轮询某事物的状态(猜测),冻结您的GUI.解决方案:不要这样做; 不要使用连续的轮询循环.相反,根据对事件的响应更改颜色,因为Swing是事件驱动的.

有关更具体的帮助,请显示违规代码并告诉我们有关您的计划的更多信息.


编辑

如果你试图显示彩色的行,一个接一个地沿着棋盘行进,那么我的猜测是正确的,你会想要使用一个Swing Timer,一个使用int索引来指示哪一行以彩色显示.您将在Timer的ActionPerformed类中增加索引,然后在显示所有行时停止Timer.例如:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.swing.*;

@SuppressWarnings("serial")
public class MyGrid extends JPanel {
   private static final int GRID_LENGTH = 8;
   private static final Color BTN_BACKGROUND = Color.BLACK;
   private static final Color[] COLORS = { Color.MAGENTA, Color.CYAN,
         Color.RED, Color.YELLOW, Color.ORANGE, Color.PINK, Color.BLUE,
         Color.GREEN };
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final int TIMER_DELAY = 800;
   private JButton[][] buttonGrid = new JButton[GRID_LENGTH][GRID_LENGTH];
   private Map<JButton, Color> btnColorMap = new HashMap<>();
   private Random random = new Random();

   public MyGrid() {
      setLayout(new GridLayout(GRID_LENGTH, GRID_LENGTH));
      for (int row = 0; row < buttonGrid.length; row++) {
         for (int col = 0; col < buttonGrid[row].length; col++) {
            JButton btn = new JButton();
            btn.setBackground(BTN_BACKGROUND);
            // !! add action listener here?

            add(btn);
            buttonGrid[row][col] = btn;
         }
      }

      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   public void resetAllBtns() {
      for (JButton[] row : buttonGrid) {
         for (JButton btn : row) {
            btn.setBackground(BTN_BACKGROUND);
         }
      }
   }

   private class TimerListener implements ActionListener {
      private int row = 0;

      @Override
      public void actionPerformed(ActionEvent e) {
         resetAllBtns(); // make all buttons black

         if (row != buttonGrid.length) {
            for (int c = 0; c < buttonGrid[row].length; c++) {
               int colorIndex = random.nextInt(COLORS.length);
               Color randomColor = COLORS[colorIndex];
               buttonGrid[row][c].setBackground(randomColor);

               // !! not sure if you need this
               btnColorMap.put(buttonGrid[row][c], randomColor);
            }

            row++;
         } else {
            // else we've run out of rows -- stop the timer
            ((Timer) e.getSource()).stop();
         }
      }
   }

   private static void createAndShowGui() {
      MyGrid mainPanel = new MyGrid();

      JFrame frame = new JFrame("MyGrid");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Run Code Online (Sandbox Code Playgroud)

请查看Swing Timer教程.


在此输入图像描述


编辑2
你问:

但是这个程序失败的原因是什么,它是无用的延迟功能吗?

您的延迟方法只对Swing事件线程上的繁忙计算做了什么:

public void delay(int a) {
  for (int i = 0; i < 90000000; ++i) {
     for (int j = 0; j < a; ++j) {

     }
  }
}
Run Code Online (Sandbox Code Playgroud)

它与粗略的调用尝试略有不同Thread.sleep(...),并且是粗略的,因为你不能明确地控制线程睡眠的运行时间.同样,问题是您在Swing事件调度线程或EDT上进行这些调用,该线程负责所有Swing绘图和用户交互.阻止此线程将阻止您的程序使其无法运行或冻结.