2013-08-01 1 views
0

Итак, я пытаюсь научиться использовать потоки, поэтому решил создать программу, которая добавит ее, а затем ждет 1/2 секунды. в то время как поток (который, я думаю, я сделал правильно) обновляет значение индикатора выполнения. Поэтому я не уверен, неправильно ли я сделал программу или если она где-то застряла. Так что я положил 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

сожалею о том, что Даниэль, я просто писал быстро и капитализировал по привычке. – Col1107

ответ

0

Программирование пользовательского интерфейса с помощью потоков является сложным, и вы можете столкнуться с серьезными проблемами, если несколько потоков пытаются изменить элементы интерфейса одновременно. В приложениях Swing все обновления пользовательского интерфейса должны выполняться в потоке событий Swing/AWT. Обычный способ сделать это - использовать EventQueue#invokeLater, чтобы запланировать Runnable для выполнения в потоке; в этом случае вы обернете f.bar.setValue(p); в Runnable и передадите это invokeLater. Вот a useful tutorial об основах потока событий.

1

Вы блокируете событие Dispatching Event. Это, в частности, отвечает за обработку обновлений красок. В то время как вы блокируете нить, нет никакого способа может происходить обновления, то есть, похоже, вы программируете пришел к стенду еще ...

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, который предназначен для того, чтобы вы могли выполнять код в фоновом потоке и повторно синхронизировать обновления обратно в пользовательский интерфейс.

Посмотрите на ...

Для некоторых примеров.

Вы также можете взглянуть на Concurrency in Swing для получения более подробной информации