如何异步触发JProgressBar?
How to asynchronous trigger JProgressBar?
我在 JPanel
中有一个 JButton
(swing
),如果按下它,我将在其 [=13] 中的列表上执行 for 循环任务=].在这样做的同时,我需要更新 JProgressBar
。
问题是,当我按下 JButton 时,任务是在事件调度线程 (EDT) 中执行的。所以我无法更新在主线程或 UI 线程中触发的 JProgressBar
。
现在源代码对我来说不可用,因为我完全更改了它并尝试将 Eclipse SWT 用于 JProgressBar
当触发 Swing JButton
时,它变得混乱。
现在我得到 invalid thread access
错误,因为 Display 对象在单独的 UI 线程中运行。一次,只会显示 Swing JPanel
或 Eclipse SWT Shell
。
我正在使用 JOptionPane
触发 JPanel
。
您需要在 EDT
的单独线程中完成冗长的 运行 工作并更新进度条值。大多数时候 SwingWorker
是一个很好的方法。因此,在该按钮的 ActionListener
中,您应该将长 运行 线程与 EDT 分开。你可以用 bare Thread
来做到这一点,但是 Workers 和特别是 SwingWorker
是为这种情况设计的:
package graphics;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class GraphicDev extends JFrame{
private static final long serialVersionUID = 679207429168581441L;
//
private static final int FRAME_WIDTH = 300;
private static final int FRAME_HEIGHT = 100;
private int percent;
private JProgressBar progress;
public GraphicDev() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(dim.width/2-FRAME_WIDTH/2, dim.height/2-FRAME_HEIGHT/2, FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//
setLayout(new FlowLayout());
//
progress = new JProgressBar(0, 100);
progress.setStringPainted(true);
//
JButton actButton = new JButton("Start!");
actButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
for (long i = 0; i < 10000000000000L; i++) {
System.out.println(i);
if(i%200000 == 0){
progress.setValue(percent++);
}
if(percent >= 100){
break;
}
}
return null;
}
@Override
protected void done() {
JOptionPane.showMessageDialog(GraphicDev.this, "Done!");
}
}.execute();
}
});
//
add(actButton);
add(progress);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
GraphicDev g = new GraphicDev();
g.setVisible(true);
}
});
}
}
希望这会有所帮助。
Asynchronously
使用 SwingWorker
处理 JProgressBar
进度,详细使用两个 Swing JButton btnStart and btnStop
.
我们在这里获取源代码-
package com.practice;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class ProgressExample {
private static JFrame frame;
private static JButton btnStart;
private static JButton btnStop;
private static JProgressBar progress;
private static Integer currValue;
private static boolean swingWorkerHelper;
private static SwingWorker<Integer, Void> swingWorker;
public static void main(String[] args) {
// Scheduling Swing app for the event dispatch thread(EDT) Asynchronously
SwingUtilities.invokeLater(new Runnable() {
public void run() {
runSwingAsynchronousApp();
}
});
}
private static void runSwingAsynchronousApp() {
currValue = new Integer(0);
btnStart = new JButton("Start");
btnStop = new JButton("Stop");
progress = new JProgressBar();
progress.setMinimum(0);
progress.setMaximum(100);
progress.setStringPainted(true);
btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (btnStart.getText().equals("Pause")) {
// interrupting swingWorker method doInBackground() implicitly safely.
swingWorkerHelper = false;
btnStart.setText("Resume");
} else {
if (btnStart.getText().equals("Start") || btnStart.getText().equals("Resume"))
btnStart.setText("Pause");
showProgress();
}
}
});
btnStop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
// checking swingWorker Object is initialized or not
if (swingWorker != null) {
// checking is swingWorker doing process in background or not
if (swingWorker.getState() == SwingWorker.StateValue.STARTED) {
btnStart.setText("Start");
// interrupting swingWorker method doInBackground() explicitly
swingWorker.cancel(true);
currValue = new Integer(0);
}
}
}
});
frame = new JFrame();
frame.setTitle("Asynchronously trigger JProgressBar");
frame.getContentPane().setLayout(new GridLayout(3, 2));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(400, 250, 400, 300);
frame.getContentPane().add(btnStart);
frame.getContentPane().add(btnStop);
frame.getContentPane().add(progress);
frame.setVisible(true);
}
private static void showProgress() {
swingWorker = new SwingWorker<Integer, Void>() {
@Override
protected Integer doInBackground() throws Exception {
if (!swingWorkerHelper)
swingWorkerHelper = true;
while (currValue < progress.getMaximum() && swingWorkerHelper) {
try {
progress.setValue(++currValue);
if (isCancelled())
return currValue;
Thread.sleep(70);
} catch (InterruptedException iex) {
swingWorkerHelper = false;
System.out.println("Stop Button interrupted SwingWorker process...");
}
}
return currValue;
}
@Override
public void done() {
System.out.printf("Progress ends with value %s " +
(isCancelled() ? "with" : "without") + " interruption.\n", currValue);
if (currValue >= progress.getMaximum()) {
btnStart.setText("Start");
currValue = new Integer(0);
}
}
};
swingWorker.execute();
}
}
希望对您有所帮助。
我在 JPanel
中有一个 JButton
(swing
),如果按下它,我将在其 [=13] 中的列表上执行 for 循环任务=].在这样做的同时,我需要更新 JProgressBar
。
问题是,当我按下 JButton 时,任务是在事件调度线程 (EDT) 中执行的。所以我无法更新在主线程或 UI 线程中触发的 JProgressBar
。
现在源代码对我来说不可用,因为我完全更改了它并尝试将 Eclipse SWT 用于 JProgressBar
当触发 Swing JButton
时,它变得混乱。
现在我得到 invalid thread access
错误,因为 Display 对象在单独的 UI 线程中运行。一次,只会显示 Swing JPanel
或 Eclipse SWT Shell
。
我正在使用 JOptionPane
触发 JPanel
。
您需要在 EDT
的单独线程中完成冗长的 运行 工作并更新进度条值。大多数时候 SwingWorker
是一个很好的方法。因此,在该按钮的 ActionListener
中,您应该将长 运行 线程与 EDT 分开。你可以用 bare Thread
来做到这一点,但是 Workers 和特别是 SwingWorker
是为这种情况设计的:
package graphics;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class GraphicDev extends JFrame{
private static final long serialVersionUID = 679207429168581441L;
//
private static final int FRAME_WIDTH = 300;
private static final int FRAME_HEIGHT = 100;
private int percent;
private JProgressBar progress;
public GraphicDev() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setBounds(dim.width/2-FRAME_WIDTH/2, dim.height/2-FRAME_HEIGHT/2, FRAME_WIDTH, FRAME_HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//
setLayout(new FlowLayout());
//
progress = new JProgressBar(0, 100);
progress.setStringPainted(true);
//
JButton actButton = new JButton("Start!");
actButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
for (long i = 0; i < 10000000000000L; i++) {
System.out.println(i);
if(i%200000 == 0){
progress.setValue(percent++);
}
if(percent >= 100){
break;
}
}
return null;
}
@Override
protected void done() {
JOptionPane.showMessageDialog(GraphicDev.this, "Done!");
}
}.execute();
}
});
//
add(actButton);
add(progress);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
GraphicDev g = new GraphicDev();
g.setVisible(true);
}
});
}
}
希望这会有所帮助。
Asynchronously
使用 SwingWorker
处理 JProgressBar
进度,详细使用两个 Swing JButton btnStart and btnStop
.
我们在这里获取源代码-
package com.practice;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class ProgressExample {
private static JFrame frame;
private static JButton btnStart;
private static JButton btnStop;
private static JProgressBar progress;
private static Integer currValue;
private static boolean swingWorkerHelper;
private static SwingWorker<Integer, Void> swingWorker;
public static void main(String[] args) {
// Scheduling Swing app for the event dispatch thread(EDT) Asynchronously
SwingUtilities.invokeLater(new Runnable() {
public void run() {
runSwingAsynchronousApp();
}
});
}
private static void runSwingAsynchronousApp() {
currValue = new Integer(0);
btnStart = new JButton("Start");
btnStop = new JButton("Stop");
progress = new JProgressBar();
progress.setMinimum(0);
progress.setMaximum(100);
progress.setStringPainted(true);
btnStart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
if (btnStart.getText().equals("Pause")) {
// interrupting swingWorker method doInBackground() implicitly safely.
swingWorkerHelper = false;
btnStart.setText("Resume");
} else {
if (btnStart.getText().equals("Start") || btnStart.getText().equals("Resume"))
btnStart.setText("Pause");
showProgress();
}
}
});
btnStop.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
// checking swingWorker Object is initialized or not
if (swingWorker != null) {
// checking is swingWorker doing process in background or not
if (swingWorker.getState() == SwingWorker.StateValue.STARTED) {
btnStart.setText("Start");
// interrupting swingWorker method doInBackground() explicitly
swingWorker.cancel(true);
currValue = new Integer(0);
}
}
}
});
frame = new JFrame();
frame.setTitle("Asynchronously trigger JProgressBar");
frame.getContentPane().setLayout(new GridLayout(3, 2));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(400, 250, 400, 300);
frame.getContentPane().add(btnStart);
frame.getContentPane().add(btnStop);
frame.getContentPane().add(progress);
frame.setVisible(true);
}
private static void showProgress() {
swingWorker = new SwingWorker<Integer, Void>() {
@Override
protected Integer doInBackground() throws Exception {
if (!swingWorkerHelper)
swingWorkerHelper = true;
while (currValue < progress.getMaximum() && swingWorkerHelper) {
try {
progress.setValue(++currValue);
if (isCancelled())
return currValue;
Thread.sleep(70);
} catch (InterruptedException iex) {
swingWorkerHelper = false;
System.out.println("Stop Button interrupted SwingWorker process...");
}
}
return currValue;
}
@Override
public void done() {
System.out.printf("Progress ends with value %s " +
(isCancelled() ? "with" : "without") + " interruption.\n", currValue);
if (currValue >= progress.getMaximum()) {
btnStart.setText("Start");
currValue = new Integer(0);
}
}
};
swingWorker.execute();
}
}
希望对您有所帮助。