2013-08-01 69 views
0

所以我想學習如何使用線程,所以我決定做一個程序,增加一個然後等待1/2秒。而線程(我認爲我是正確的)刷新了進度條的值。所以我不確定我是否犯了這個錯誤的程序,或者它是否被卡住了。所以,我在Thread把println,這就是我得到:試圖使用JProgressBar的線程

thred 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 (ect...) 

這裏是我的框架代碼:

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.JProgressBar; 
import javax.swing.border.EmptyBorder; 

public class frame extends JFrame implements ActionListener{ 

    private static final long serialVersionUID = 1L; 
    private JPanel contentPane; 

    public static void main(String[] args) { 
     frame f = new frame(); 
     f.setVisible(true); 
     f.setSize(450,120); 
    } 

    /** 
    * Create the frame. 
    */ 

    public JProgressBar bar; 

    public frame() { 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setBounds(100, 100, 449, 120); 
     contentPane = new JPanel(); 
     contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); 
     setContentPane(contentPane); 
     contentPane.setLayout(null); 

     bar = new JProgressBar(); 
     bar.setStringPainted(true); 
     bar.setBounds(6, 50, 438, 32); 
     contentPane.add(bar); 

     JLabel lblNewLabel = new JLabel(
       "Percent of for loop completion"); 
     lblNewLabel.setBounds(6, 6, 279, 16); 
     contentPane.add(lblNewLabel); 

     JButton btnStart = new JButton("START"); 
     btnStart.setBounds(327, 1, 117, 29); 
     btnStart.addActionListener(this); 
     contentPane.add(btnStart); 
    } 

    public int i, progress; 
    public void actionPerformed(ActionEvent e) { 
     updater u = new updater(); 

     u.start(); 
     for(i =0; i < 100; i++){ 
      progress = i; 
      try { 
       Thread.sleep(500); 
      } catch (InterruptedException e1) { 
       e1.printStackTrace(); 
      } 
      System.out.println(i); 
     } 

    } 

} 

這是我認爲是我的線程類:

public class updater extends Thread { 

    public void run() { 
     System.out.println("thred"); 
     frame f = new frame(); 

     int p = f.progress; 
     while (p != 100) { 

      f.bar.setValue(p); 
     } 
    } 
} 
+2

你的「更新」類將是非常,非常忙;) – paulsm4

+3

嘗試堅持Java約定,並開始你的類名稱以大寫字母。小寫字母表示方法和變量。 –

+0

Daniel對此很抱歉,我只是很快就寫出了習慣。 – Col1107

回答

0

使用線程進行UI編程非常棘手,如果多個線程嘗試同時修改UI元素,最終會出現嚴重問題。在Swing應用程序中,UI的所有更新應該在Swing/AWT事件線程上進行。執行此操作的常用方法是使用EventQueue#invokeLater安排在線程上執行Runnable;在這種情況下,您會將f.bar.setValue(p);換成Runnable並將其傳遞給invokeLater。這裏的 a useful tutorial關於事件線程的基礎知識。

1

您正在阻止事件調度線程。除其他外,這負責處理塗料更新。當你阻塞線程,沒有辦法更新,可能會發生,這意味着它看起來像你的程序已經到了站在原地......

public void actionPerformed(ActionEvent e) { 
    updater u = new updater(); 
    u.start(); 
    // Now blocking, no more repaints or event notifications until you finish... 
    for(i =0; i < 100; i++){ 
     progress = i; 
     try { 
      Thread.sleep(500); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 
     System.out.println(i); 
    } 

} 

你有另外一個問題是,搖擺(爲大部分)不是線程安全的。也就是說,預計所有的更新和與用戶界面的交互只會發生在EDT的上下文中。

雖然有多種方式來解決它,最簡單的是使用一個SwingWorker,其目的是讓你在後臺線程中執行代碼並重新進行同步更新回到UI安全。

看一看......

對於一些例子。

您可能還需要看一看Concurrency in Swing更多細節