简体   繁体   English

尝试在JProgressBar中使用线程

[英]Trying to use a thread with JProgressBar

So I'm trying to learn how to use threads so I decided to make a program that adds one then waits for 1/2 a sec. 因此,我试图学习如何使用线程,所以我决定制作一个程序,添加一个线程,然后等待1/2秒。 while the thread (that I think I made correctly) refreshes the value of the progress bar. 而线程(我认为我做对了)刷新进度条的值。 So I'm not sure if I've made the program wrong or if it's getting stuck somewhere. 因此,我不确定是否将程序弄错了,或者是否卡在某个地方。 So I put a println in the Thread and this is what I get: 所以我在线程中放入了一个println ,这就是我得到的:

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

Here is my frame code: 这是我的框架代码:

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);
        }

    }

}

And this is what I think is my thread class: 这就是我的线程类:

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);
        }
    }
}

You are blocking Event Dispatching Thread. 您正在阻止事件调度线程。 This is responsible for, amongst other things, processing paint updates. 除其他事项外,这负责处理油漆更新。 While you block the thread, there is no way the updates can occur, meaning it looks like you program has come to a stand still... 当您阻止线程时,无法进行更新,这意味着您的程序似乎停滞不前...

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);
    }

}

The other problem you have is the fact that Swing (for the most part) is not thread-safe. 您遇到的另一个问题是,Swing(大多数情况下)不是线程安全的事实。 That is, it is expected that all updates and interactions with the UI will occur only from within the context of the EDT. 也就是说,期望所有与UI的更新和交互将仅在EDT的上下文中发生。

While there are a number of ways to get around it, the simplest would be to use a SwingWorker , which is designed to allow you to execute code in a background thread and re-sync updates back to the UI safely. 尽管有多种解决方法,但最简单的方法是使用SwingWorker ,它旨在允许您在后台线程中执行代码并将更新安全地重新同步到UI。

Take a look at... 看一眼...

For some examples. 对于一些例子。

You may also want to take a look at Concurrency in Swing for more details 您可能还想看看Swing中的并发以了解更多详细信息

UI programming with threads is tricky, and you can end up with serious problems if multiple threads try to modify UI elements simultaneously. 使用线程进行UI编程非常棘手,如果多个线程尝试同时修改UI元素,则可能会遇到严重的问题。 In Swing applications, all updates to the UI should take place on the Swing/AWT event thread. 在Swing应用程序中,对UI的所有更新都应在Swing / AWT事件线程上进行。 The usual way of doing this is to use EventQueue#invokeLater to schedule a Runnable to execute on the thread; 通常的方法是使用EventQueue#invokeLater安排一个Runnable在线程上执行。 in this case, you'd wrap f.bar.setValue(p); 在这种情况下,将包装f.bar.setValue(p); in a Runnable and pass that to invokeLater . Runnable并将其传递给invokeLater Here's a useful tutorial on the basics of the event thread. 这是有关事件线程基础的有用教程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM