如何刷新 JFrame 中包含的按钮的颜色? [英] how to refresh the colors of button contained in a JFrame?

查看:29
本文介绍了如何刷新 JFrame 中包含的按钮的颜色?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am coding a little game in which i have taken a grid of JButtons in a JFrame and i want to refresh the colors of the buttons contained in a JFrame,which is already visible.As explained below

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

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

Result i am getting is not as expected and my screen gets freeze .Isn't it the right way to achieve what i wanted? EDIT ok i am explaining it in detail what i want to achieve.i have a class,as:-

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

}

请帮我看看出路是什么?

Please Help me what is the way out?

推荐答案

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

Your problem is in code not shown here:

//color update code for the buttons.

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

You're likely running a loop that never ends on the Swing event thread, possibly a never-ending while loop that polls the state of something(a guess), freezing your GUI. Solution: don't do this; don't use a continuous polling loop. Instead, change the colors based on responses to events as Swing is event-driven.

要获得更好更具体的帮助,请显示有问题的代码并告诉我们有关您程序的更多信息.

For better more specific help, please show the offending code and tell us more about your program.

编辑

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

If you're trying to show colored rows, one by one marching down the board, then my guess is right, you'll want to use a Swing Timer, one that uses an int index to indicate which row is being displayed in color. You'd increment the index inside of the Timer's ActionPerformed class, and then when all rows have been displayed stop the Timer. For example something like so:

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 计时器教程

编辑 2
你问:

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

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

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

Your delay method does nothing but busy calculations on the Swing event thread:

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

     }
  }
}

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

It's little different from a crude attempt at calling Thread.sleep(...), and is crude because you can't explicitly control how long it will run as you can with thread sleep. Again, the problem is that you're making these calls on the Swing event dispatch thread or EDT, the single thread that is responsible for all Swing drawing and user interactions. Blocking this thread will block your program making it non-running or frozen.

这篇关于如何刷新 JFrame 中包含的按钮的颜色?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆