2013-02-03 48 views
1

我正在尝试制作一个Java应用程序,它在单击一个按钮时,在面板上显示随机颜色持续特定的时间。frame.repaint()无法正常工作

但我的问题是,点击按钮后,框架的颜色只改变一次,并且按钮的标题也不会更改为“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 --"); 
    } 
} 
+0

[使用睡眠()为单个线程](http://stackoverflow.com/questions/14074329/using-sleep-for-a-single-线程) –

回答

4

不要叫Swing事件线程上Thread.sleep(...)因为这一切都被置于整个GUI睡觉包括其作画能力。请使用Swing Timer。检查教程链接。顺便提一句,10毫秒非常短,可能对于时间片或者人们注意到太短。另外,我会随机化并在Swing Timer的ActionListener中创建新的颜色,而不是在方法本身中使用paintComponent(...)

编辑:
请注意,Swing使用单个线程Event Event Dispatch Thread或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(); 

注意,泛变量必须在桂类中声明,而不是在它的构造函数的计时器才能够得到它。

+0

+1 yup thats it –

+1

非常好咨询。然而,OP的代码显然在主线程上运行。这使我们能够:在EDT上运行Swing代码(!!) –

+0

@SoboLAN:当然是正确的,谢谢! –