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

标签 java swing

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

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

我得到的结果与预期不符,我的屏幕卡住了。这不是实现我想要的目标的正确方法吗? 编辑 好的,我正在详细解释我想要实现的目标。我有一个类,因为:-

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

请帮我看看出路在哪里?

最佳答案

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

//color update code for the buttons.

您可能正在运行一个在 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();
         }
      });
   }
}

请看Swing Timer Tutorial


enter image description here


编辑2
你问:

but what is the reason of failure of this program,is it the useless delay function?

您的延迟方法除了在 Swing 事件线程上进行繁忙的计算之外什么都不做:

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

     }
  }
}

这与调用 Thread.sleep(...) 的粗略尝试略有不同,并且是粗略的,因为您无法像使用线程 sleep 那样显式控制它将运行多长时间。同样,问题是您在 Swing 事件分派(dispatch)线程或 EDT 上进行这些调用,EDT 是负责所有 Swing 绘图和用户交互的单个线程。阻止此线程将阻止您的程序,使其无法运行或卡住。

关于java - 如何刷新 JFrame 中包含的按钮的颜色?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24578458/

相关文章:

java - 如何使 Android Google 登录按钮仅登录而不使用 FirebaseAuth 注册?

java - 无法解析 onActivityResult 方法

java - 如何从同一类的另一个对象调用变量

java - 如何在java中的jtable中的特定行添加复选框?

java - 带有无用堆栈跟踪的异常

Java GUI 更好地删除或 setVisible(false)?

java - Thread.sleep(1000) 在 Swing 中不起作用

java - 对具有重复条目的数组进行排序后获取唯一索引

java - 如何从JDialog中完全删除图标?

java - 使用 jpanel 变量在 Jframe 中加载图像