2013-02-03 75 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:當然是正確的,謝謝! –