运行 几次SwingWorker
Run SwingWorker several times
我想生成一个随机数 5 次并重复 6 次。每次生成随机数时,我都会用该数字和进度条更新 GUI。
为此,我想到了一个 SwingWorker,它在 doInBackground() 方法上生成随机数,并使用 publish() 方法在 GUI 上显示该数字。我这样做完全没有问题,当我尝试这样做 6 次时,问题就来了,因为在 done() 方法中,我在用于显示所有数字的 TextField 上添加了一个空白 space
我如何运行 SwingWorker 的 6 倍,并且它在 SwingWorker 的 done() 方法完成后启动?
谢谢!
编辑:代码片段
public class SwingWorkerEjemplo extends SwingWorker<Void, Integer> {
private JProgressBar pBar;
private JTextField txtSalida;
private JTextArea txtArea;
public SwingWorkerEjemplo(JProgressBar pBar,JTextField txt, JTextArea txtArea) {
this.pBar = pBar;
addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())){
pBar.setValue((Integer)evt.getNewValue());
}
}
});
this.pBar.setVisible(true);
this.pBar.setStringPainted(true);
this.pBar.setValue(0);
setProgress(0);
this.txtSalida = txt;
this.txtArea = txtArea;
}
@Override
protected Void doInBackground() throws Exception {
int num;
for (int i=0;i<5;i++){
num = ThreadLocalRandom.current().nextInt(1, 7);
publish(num);
setProgress(i+1);
Thread.sleep(100);
}
return null;
}
@Override
protected void done() {
try {
txtSalida.setText(txtSalida.getText()+" ");
Thread.sleep(0);
txtArea.append("");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected void process(List<Integer> chunks) {
Integer valor = chunks.get(chunks.size()-1);
txtSalida.setText(txtSalida.getText()+String.valueOf(valor));
}
}
并且在 MainWindow.java
SwingWorkerEjemplo swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 1");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 2");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 3");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 4");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 5");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 6");
结果首先是所有
工人 1
工人 2
工人 3
工人 4
工人 5
工人 6
然后像 xxxxxyyyyyzzzzzaaaaabbbbbcccccdddd
How can I do to run 6 times that SwingWorker, and that it starts after the done() method of the SwingWorker is completed?
你不能。根据 SwingWorker API documentation:
SwingWorker is only designed to be executed once. Executing a SwingWorker more than once will not result in invoking the doInBackground method twice.
因此,如果您需要延迟重复某个动作,请在您的 worker 中使用 while 循环执行此操作,然后通过 SwingWorker 的 publish/process 对将结果输出到您的 GUI。如果你走这条路,你会创建一个 SwingWorker<Void, Integer>
(如果它需要产生 int 输出)。另一方面,如果您想 运行 工人 6 次,每次都响应一个事件,那么每次需要时只需创建一个新工人。
我想知道您是否只需要更简单的 Swing Timer。
编辑
I haven't seen what the Swing Timer does, so I can't answer that.
如果您需要间歇性地延迟完成某些事情,那么 Swing Timer(请参阅 link)是最佳选择。当您创建一个时,您会传入 2 个参数,一个表示延迟时间的 int 和一个 ActionListener - 其 actionPerformed 方法将被重复调用,延迟 大致 分开。因此,如果您需要每秒生成一个随机整数,您将传入 1000(1000 毫秒 = 1 秒)和一个 ActionListener,并在侦听器的 actionPerformed 方法中生成随机整数并将其传递给任何需要它的人。请注意,actionPerformed 方法中的所有代码都是在 Swing 事件线程上调用的。
另一方面,如果您需要 运行 一些需要很长时间执行的代码,例如数据库查找、从套接字读取、从文件读取或写入,然后您将使用 SwingWorker,因为通过这样做您可以 运行 后台线程和事件线程中的长代码安全地将信息提取回 GUI。
And a quick question, by worker you mean the GUI?
不,工人= SwingWorker。
因此,对于您发布的代码,如果这就是您想要做的全部 - 延迟更新 JProgressBar,然后使用 Swing 计时器。另一方面,如果您想要执行一个长 运行ning 的进程并希望在进程 运行ning 期间更新 JProgressBar,那么请使用 SwingWorker。注意,如果你有后一种需求,则不需要使用 publish/process 方法对。 SwingWorker 有一个 属性 的进度 "bound" 属性,这意味着如果您通过调用 setProgress(...)
更改它,SwingWorker 将通知可能附加到它的任何 PropertyChangeListeners。我用这个 lot.
例如:
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class ProgressExampleGui {
private JPanel mainPanel = new JPanel();
private JProgressBar progressBar = new JProgressBar();
private JButton pressMeBtn = new JButton(new MyAction("Press Me", KeyEvent.VK_P, this));
public ProgressExampleGui() {
progressBar.setStringPainted(true);
progressBar.setString("");
mainPanel.add(pressMeBtn);
mainPanel.add(progressBar);
}
public void setProgress(int progress) {
progressBar.setValue(progress);
progressBar.setString(progress + "%");
}
public JComponent getMainComponent() {
return mainPanel;
}
public void setEnabled(boolean enabled) {
pressMeBtn.setEnabled(enabled);
}
private static void createAndShowGui() {
ProgressExampleGui progExampleGui = new ProgressExampleGui();
JFrame frame = new JFrame("Progress Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(progExampleGui.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class MyAction extends AbstractAction {
private ProgressExampleGui gui;
public MyAction(String name, int mnemonic, ProgressExampleGui gui) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.gui = gui;
}
@Override
public void actionPerformed(ActionEvent e) {
AbstractButton source = (AbstractButton) e.getSource();
gui.setProgress(0);
source.setEnabled(false);
MyWorker myWorker = new MyWorker();
myWorker.addPropertyChangeListener(new WorkerPropChngListener(gui));
myWorker.execute();
}
}
class WorkerPropChngListener implements PropertyChangeListener {
private ProgressExampleGui gui;
public WorkerPropChngListener(ProgressExampleGui gui) {
this.gui = gui;
}
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
MyWorker myWorker = (MyWorker) pcEvt.getSource();
if ("progress".equals(pcEvt.getPropertyName())) {
int progress = ((Integer)pcEvt.getNewValue()).intValue();
gui.setProgress(progress);
}
if (SwingWorker.StateValue.DONE.equals(pcEvt.getNewValue())) {
try {
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
gui.setEnabled(true);
}
}
}
class MyWorker extends SwingWorker<Void, Void> {
private static final int MAX_INCR = 8;
private static final long SLEEP_TIME = 200;
private static final int MAX_VALUE = 100;
private int value = 0;
private Random random = new Random();
@Override
protected Void doInBackground() throws Exception {
while (value < MAX_VALUE) {
value += random.nextInt(MAX_INCR);
value = Math.min(value, MAX_VALUE);
Thread.sleep(SLEEP_TIME);
setProgress(value);
}
return null;
}
}
我想生成一个随机数 5 次并重复 6 次。每次生成随机数时,我都会用该数字和进度条更新 GUI。
为此,我想到了一个 SwingWorker,它在 doInBackground() 方法上生成随机数,并使用 publish() 方法在 GUI 上显示该数字。我这样做完全没有问题,当我尝试这样做 6 次时,问题就来了,因为在 done() 方法中,我在用于显示所有数字的 TextField 上添加了一个空白 space
我如何运行 SwingWorker 的 6 倍,并且它在 SwingWorker 的 done() 方法完成后启动?
谢谢!
编辑:代码片段
public class SwingWorkerEjemplo extends SwingWorker<Void, Integer> {
private JProgressBar pBar;
private JTextField txtSalida;
private JTextArea txtArea;
public SwingWorkerEjemplo(JProgressBar pBar,JTextField txt, JTextArea txtArea) {
this.pBar = pBar;
addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())){
pBar.setValue((Integer)evt.getNewValue());
}
}
});
this.pBar.setVisible(true);
this.pBar.setStringPainted(true);
this.pBar.setValue(0);
setProgress(0);
this.txtSalida = txt;
this.txtArea = txtArea;
}
@Override
protected Void doInBackground() throws Exception {
int num;
for (int i=0;i<5;i++){
num = ThreadLocalRandom.current().nextInt(1, 7);
publish(num);
setProgress(i+1);
Thread.sleep(100);
}
return null;
}
@Override
protected void done() {
try {
txtSalida.setText(txtSalida.getText()+" ");
Thread.sleep(0);
txtArea.append("");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
protected void process(List<Integer> chunks) {
Integer valor = chunks.get(chunks.size()-1);
txtSalida.setText(txtSalida.getText()+String.valueOf(valor));
}
}
并且在 MainWindow.java
SwingWorkerEjemplo swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 1");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 2");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 3");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 4");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 5");
swe = new SwingWorkerEjemplo(pBar, txtNumeros, txtSalida);
swe.execute();
System.out.println("Worker 6");
结果首先是所有 工人 1 工人 2 工人 3 工人 4 工人 5 工人 6 然后像 xxxxxyyyyyzzzzzaaaaabbbbbcccccdddd
How can I do to run 6 times that SwingWorker, and that it starts after the done() method of the SwingWorker is completed?
你不能。根据 SwingWorker API documentation:
SwingWorker is only designed to be executed once. Executing a SwingWorker more than once will not result in invoking the doInBackground method twice.
因此,如果您需要延迟重复某个动作,请在您的 worker 中使用 while 循环执行此操作,然后通过 SwingWorker 的 publish/process 对将结果输出到您的 GUI。如果你走这条路,你会创建一个 SwingWorker<Void, Integer>
(如果它需要产生 int 输出)。另一方面,如果您想 运行 工人 6 次,每次都响应一个事件,那么每次需要时只需创建一个新工人。
我想知道您是否只需要更简单的 Swing Timer。
编辑
I haven't seen what the Swing Timer does, so I can't answer that.
如果您需要间歇性地延迟完成某些事情,那么 Swing Timer(请参阅 link)是最佳选择。当您创建一个时,您会传入 2 个参数,一个表示延迟时间的 int 和一个 ActionListener - 其 actionPerformed 方法将被重复调用,延迟 大致 分开。因此,如果您需要每秒生成一个随机整数,您将传入 1000(1000 毫秒 = 1 秒)和一个 ActionListener,并在侦听器的 actionPerformed 方法中生成随机整数并将其传递给任何需要它的人。请注意,actionPerformed 方法中的所有代码都是在 Swing 事件线程上调用的。
另一方面,如果您需要 运行 一些需要很长时间执行的代码,例如数据库查找、从套接字读取、从文件读取或写入,然后您将使用 SwingWorker,因为通过这样做您可以 运行 后台线程和事件线程中的长代码安全地将信息提取回 GUI。
And a quick question, by worker you mean the GUI?
不,工人= SwingWorker。
因此,对于您发布的代码,如果这就是您想要做的全部 - 延迟更新 JProgressBar,然后使用 Swing 计时器。另一方面,如果您想要执行一个长 运行ning 的进程并希望在进程 运行ning 期间更新 JProgressBar,那么请使用 SwingWorker。注意,如果你有后一种需求,则不需要使用 publish/process 方法对。 SwingWorker 有一个 属性 的进度 "bound" 属性,这意味着如果您通过调用 setProgress(...)
更改它,SwingWorker 将通知可能附加到它的任何 PropertyChangeListeners。我用这个 lot.
例如:
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class ProgressExampleGui {
private JPanel mainPanel = new JPanel();
private JProgressBar progressBar = new JProgressBar();
private JButton pressMeBtn = new JButton(new MyAction("Press Me", KeyEvent.VK_P, this));
public ProgressExampleGui() {
progressBar.setStringPainted(true);
progressBar.setString("");
mainPanel.add(pressMeBtn);
mainPanel.add(progressBar);
}
public void setProgress(int progress) {
progressBar.setValue(progress);
progressBar.setString(progress + "%");
}
public JComponent getMainComponent() {
return mainPanel;
}
public void setEnabled(boolean enabled) {
pressMeBtn.setEnabled(enabled);
}
private static void createAndShowGui() {
ProgressExampleGui progExampleGui = new ProgressExampleGui();
JFrame frame = new JFrame("Progress Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(progExampleGui.getMainComponent());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class MyAction extends AbstractAction {
private ProgressExampleGui gui;
public MyAction(String name, int mnemonic, ProgressExampleGui gui) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.gui = gui;
}
@Override
public void actionPerformed(ActionEvent e) {
AbstractButton source = (AbstractButton) e.getSource();
gui.setProgress(0);
source.setEnabled(false);
MyWorker myWorker = new MyWorker();
myWorker.addPropertyChangeListener(new WorkerPropChngListener(gui));
myWorker.execute();
}
}
class WorkerPropChngListener implements PropertyChangeListener {
private ProgressExampleGui gui;
public WorkerPropChngListener(ProgressExampleGui gui) {
this.gui = gui;
}
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
MyWorker myWorker = (MyWorker) pcEvt.getSource();
if ("progress".equals(pcEvt.getPropertyName())) {
int progress = ((Integer)pcEvt.getNewValue()).intValue();
gui.setProgress(progress);
}
if (SwingWorker.StateValue.DONE.equals(pcEvt.getNewValue())) {
try {
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
gui.setEnabled(true);
}
}
}
class MyWorker extends SwingWorker<Void, Void> {
private static final int MAX_INCR = 8;
private static final long SLEEP_TIME = 200;
private static final int MAX_VALUE = 100;
private int value = 0;
private Random random = new Random();
@Override
protected Void doInBackground() throws Exception {
while (value < MAX_VALUE) {
value += random.nextInt(MAX_INCR);
value = Math.min(value, MAX_VALUE);
Thread.sleep(SLEEP_TIME);
setProgress(value);
}
return null;
}
}