2013-08-01 33 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更多细节