frame.repaint()无法正常工作

时间:2013-02-03 18:45:06

标签: java swing

我正在尝试创建一个Java应用程序,在单击按钮时,在面板中显示特定持续时间的随机颜色。

但我的问题是,点击按钮后,框架的颜色只会改变一次,而按钮的标题也不会改为“U Clicked me”。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

class MyDrawPanel extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        // g.fillRect(0, 0, this.getWidth(), this.getHeight())
        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);
        Color randomizecolor = new Color(red, green, blue);
        g.setColor(randomizecolor);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }
}

public class CustomWidget implements ActionListener {

    JButton button;
    JFrame frame;

    public void Gui() {
        frame = new JFrame();
        MyDrawPanel pan = new MyDrawPanel();
        button = new JButton("-- Click Me to Change Me --");
        frame.add(BorderLayout.SOUTH, button);
        frame.add(BorderLayout.CENTER, pan);
        button.addActionListener(this);
        frame.setSize(500, 500);
        frame.setTitle("Random Color GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public void asd() {
        button.setText("U clicked Me");
        for (int i = 0; i < 150; i++) {
            frame.repaint();
            try {
                Thread.sleep(10);
            } catch (Exception x) {
            }
        }
        button.setText("Again Click me");
    }

    public static void main(String[] args) {
        CustomWidget obj = new CustomWidget();
        obj.Gui();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        this.asd();
        // this.button.setText("-- Click Me to Change Me --");
    }
}

1 个答案:

答案 0 :(得分:4)

不要在Swing事件线程上调用Thread.sleep(...),因为所有这一切都会使整个GUI处于休眠状态,包括它的绘制能力。而是使用Swing Timer。查看教程的链接。顺便提一下,10毫秒非常短,可能对于时间片太短或者人们没有注意到。另外,我会在Swing Timer的ActionListener中随机化并创建新的Color,而不是paintComponent(...)方法本身。

编辑:
请注意,Swing使用单个线程(事件调度线程或EDT)来更新所有图形并执行所有用户交互。如果通过调用Thread.sleep(...)或通过在此线程上调用长时间运行的代码将此线程置于休眠状态,则整个Swing应用程序将进入休眠状态,并且在睡眠之前不会发生用户交互或Swing绘图结束。解决方案的关键是在后台线程上执行所有长时间运行的任务。 Swing Timer将为您完成此操作,教程将向您展示如何。

编辑2:
在半伪代码中:

  button.setText(BTN_CLICKED_TEXT);
  // TIMER_DELAY is some constant int
  Timer myTimer = new Timer(TIMER_DELAY, new ActionListener() {
     private int count = 0;

     @Override
     public void actionPerformed(ActionEvent timerActionEvt) {
        if the count variable is >= some maximum count
          // stop the timer by calling stop on it
          // I'll show you this one since it is a bit complex
          ((Timer)timerActionEvt.getSource()).stop();
          // set the button text to its original state
          // return from this method

        else 
          // randomize pan's color and repaint it
          count++; // increment the counter variable
     }
  });

  myTimer.start();

请注意,pan变量必须在Gui类中声明,而不是在其构造函数中声明,以便Timer能够访问它。