- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我创建了一个 GUI 应用程序,其中有 4 个独立的 SwingWorker 线程正在执行。他们的进度由单独的进度条和旁边的数字表示(动态更新)。底部还有一个“Grand Total”标签,它应该是所有 4 个线程进度的总和。然而,由于比赛条件,总总数无法正确计算。到目前为止,我已经尝试使用 syncrhonized
关键字并利用 SwingWorker 的 publish()
和 process()
方法。什么都没起作用。还有一个“暂停”和“恢复”按钮可以使用,但会在“GrandTotal”数字中造成更大的差异。
这是我的对话框代码:
public class ThreadTestDialog extends JDialog {
private JPanel contentPane;
private JButton buttonStart;
private JButton buttonPause;
private JProgressBar progressBar1;
private JProgressBar progressBar2;
private JProgressBar progressBar3;
private JProgressBar progressBar4;
private JButton buttonResume;
private JLabel labelThread1;
private JLabel labelThread2;
private JLabel labelThread3;
private JLabel labelThread4;
private JLabel labelThread1Total;
private JLabel labelThread2Total;
private JLabel labelThread3Total;
private JLabel labelThread4Total;
private JLabel labelGrandTotal;
private JLabel labelGrandTotalValue;
public AppThread thread1 = new AppThread(labelThread1Total, progressBar1, 30, labelGrandTotalValue);
public AppThread thread2 = new AppThread(labelThread2Total, progressBar2, 75, labelGrandTotalValue);
public AppThread thread3 = new AppThread(labelThread3Total, progressBar3, 50, labelGrandTotalValue);
public AppThread thread4 = new AppThread(labelThread4Total, progressBar4, 20, labelGrandTotalValue);
public ThreadTestDialog() {
setContentPane(contentPane);
setModal(true);
getRootPane().setDefaultButton(buttonStart);
buttonStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onStart();
}
});
buttonPause.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onPause();
}
});
buttonResume.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onResume();
}
});
// call dispose() when cross is clicked
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
});
// call dispose() on ESCAPE
contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
private void onStart() {
thread1.execute();
thread2.execute();
thread3.execute();
thread4.execute();
}
private void onPause() {
thread1.setFlag(false);
thread2.setFlag(false);
thread3.setFlag(false);
thread4.setFlag(false);
}
private void onResume() {
int tempValue;
tempValue = thread1.getValue();
thread1 = new AppThread(tempValue, labelThread1Total, progressBar1, 30, labelGrandTotalValue);
thread1.execute();
tempValue = thread2.getValue();
thread2 = new AppThread(tempValue, labelThread2Total, progressBar2, 75, labelGrandTotalValue);
thread2.execute();
tempValue = thread3.getValue();
thread3 = new AppThread(tempValue, labelThread3Total, progressBar3, 50, labelGrandTotalValue);
thread3.execute();
tempValue = thread4.getValue();
thread4 = new AppThread(tempValue, labelThread4Total, progressBar4, 20, labelGrandTotalValue);
thread4.execute();
}
public static void main(String[] args) {
ThreadTestDialog dialog = new ThreadTestDialog();
dialog.pack();
dialog.setVisible(true);
System.exit(0);
}
}
这是我的 SwingWorker 自定义类:
import javax.swing.*;
import java.util.List;
public class AppThread extends SwingWorker<Void, Integer> {
private int value=0;
private int sleepTime;
private JLabel label;
private JProgressBar progressBar;
private JLabel grandTotal;
private boolean flag=true;
public AppThread (JLabel label, JProgressBar progressBar, int sleepTime, JLabel grandTotal) {
this.sleepTime = sleepTime;
this.label = label;
this.progressBar = progressBar;
this.grandTotal = grandTotal;
}
public AppThread (int value, JLabel label, JProgressBar progressBar, int sleepTime, JLabel grandTotal) {
this.value = value;
this.sleepTime = sleepTime;
this.label = label;
this.progressBar = progressBar;
this.grandTotal = grandTotal;
}
public Void doInBackground() {
for (int i = value; i <= 100; i++) {
if (!flag) break;
this.value = i;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
label.setText(Integer.toString(value));
progressBar.setValue(value);
progressBar.setStringPainted(true);
grandTotal.setText(Integer.toString(Integer.parseInt(grandTotal.getText()) + 1));
}
return null;
}
public void done() {
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public int getValue() {
return value;
}
}
}
我将非常感谢任何有关如何同步工作线程以便它们正确更新“GrandTotal”标签的建议。
最佳答案
您违反了 Swing 的线程规则,从事件调度线程的上下文之外更新 UI,而 SwingWorker
应该可以帮助您。
避免将 UI 对象的引用传递给 SwingWorker
,而是使用其 process
方法来更新某些状态模型或其 PropertyChangeListener
支持间接更新 UI。
下面是一个简单的示例,它使用 PropertyChangeListener
支持来更新进度条。
请注意,我已将 AppThread
与 UI 解耦,因此 UI 现在接管了更新 UI 的责任。该示例还可以动态扩展,因此您只需更新创建 AppThread 的 for-loop
即可增加 AppThread 的数量
ThreadTestDialog
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ThreadTestDialog extends JDialog {
private JButton buttonStart;
private Map<AppThread, JProgressBar> progressBars = new HashMap<>(4);
private JProgressBar pbGrandTotal;
public ThreadTestDialog() {
setModal(true);
getRootPane().setDefaultButton(buttonStart);
buttonStart = new JButton("Start");
buttonStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onStart();
}
});
// call dispose() when cross is clicked
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
Random rnd = new Random();
for (int index = 0; index < 4; index++) {
AppThread appThread = new AppThread(rnd.nextInt(1000));
appThread.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
AppThread worker = (AppThread)evt.getSource();
String name = evt.getPropertyName();
if (name.equals("progress")) {
JProgressBar pb = progressBars.get(worker);
pb.setValue(worker.getProgress());
} else if (name.equals("done")) {
// Now you can do something when the worker completes...
}
updateTotalProgress();
}
});
JProgressBar pb = new JProgressBar(0, 100);
progressBars.put(appThread, pb);
add(pb, gbc);
}
pbGrandTotal = new JProgressBar(0, progressBars.size() * 100);
add(pbGrandTotal, gbc);
add(buttonStart, gbc);
}
protected void updateTotalProgress() {
int totalProgress = 0;
for (Map.Entry<AppThread, JProgressBar> entry : progressBars.entrySet()) {
totalProgress += entry.getKey().getProgress();
}
pbGrandTotal.setValue(totalProgress);
}
private void onStart() {
for (Map.Entry<AppThread, JProgressBar> entry : progressBars.entrySet()) {
entry.getKey().execute();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
ThreadTestDialog dialog = new ThreadTestDialog();
dialog.pack();
dialog.setVisible(true);
}
});
}
}
AppThread
import javax.swing.SwingWorker;
public class AppThread extends SwingWorker<Void, Integer> {
private int value = 0;
private int sleepTime;
public AppThread(int sleepTime) {
this.sleepTime = sleepTime;
}
public Void doInBackground() {
for (int i = value; i <= 100; i++) {
this.value = i;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
setProgress(value);
}
return null;
}
}
关于java - SwingWorker线程同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54498841/
我有一个 SwingWorker 如下: public class MainWorker extends SwingWorker(Void, MyObject) { : : } 我从
我正在尝试从另一个 SwingWorker (MainWorker) 执行 SwingWorker (SubWorker),然后我希望 MainWorker 等待 SubWorker 完成。同时,Ma
我试图在 SO 上找到我的问题的答案,但由于它们的丰富性和多样性,我有点困惑。这是我的问题:我的应用程序比较两个文件并在 Swing.JTextPane 中打印结果。我使用按钮调用处理文件的代码,为了
我使用一个扩展 SwingWorker 的类,如下所示: public class Analyzer extends SwingWorker { String source; public A
我有一个作为 Java SwingWorker 运行的套接字服务器。 SwingWorker 接收传入的连接,并在连接后将套接字移交给负责连接的执行器。 Executor 调用将通过 run() 方法
我需要运行两个 SwingWorker。其中一个只能在另一个完成后才能运行。我可以像这样运行它们吗? class TestWorker { private FirstWorker worker
我对SwingWorker有疑问它是done()方法。我有一个通过 SPI 支持插件的应用程序,所以我基本上无法更改插件的行为。这些插件必须实现的接口(interface)包含方法 List getC
jList 模型中包含的数据由 swingworker 更新。问题是我在独立的 *.java 文件中对 SwingWorker 类进行了子类化。所以我无法访问 GUI 组件(在本例中为模型和 jLis
我正在创建一个进度条来监控图像下载。图像下载不起作用 - 它会生成一个大小为 0 字节的文件。如果我将代码移至没有 SwingWorker 的独立类,则图像下载可以正常工作。我已经玩了一段时间了,但我
首先,我需要通知您,我正在尽最大努力学习如何使用 Java 编写代码。这有点困难,但是,我相信我做到了。我过去曾提交过几个关于 SwingWorkers 等的问题。每一个我都以为我拥有它,但后来发现我
假设一个应用程序读取数据文件,从用户获取一些输入(通过 GUI),从大型数据库获取附加数据并执行冗长的分析。 按照建议,我将耗时的部分(数据库管理和实际分析)删除到了 SwingWorker 实例中。
我有几个 SwingWorker 正在运行,它们都需要 OpenNLP 进行计算。OpenNLP 需要一些时间进行初始化,所以我想知道最好的方法是什么?我想在每个 SwingWorker 中启动一个
我有一个小 gui 程序,它在启动时从 Excel 文件中读取数据,其中一些数据需要转到相关的组合框。我知道如何通过为每个组合框使用单独的 SwingWorker 来做到这一点: public cla
有人能告诉我为什么在这个使用 SwingWorker 的简单演示中,屏幕闪烁,好像按钮不断跳跃一样? (关于改进多线程部分的反馈也值得赞赏)。 import java.awt.EventQueue;
在 Netbeans 中,我创建了一个 GUI 项目,该项目使用框架前端,我可以添加组件并双击以编辑其事件。我指的是具有“源”、“设计”和“历史”选项卡的窗口。 以下是组件和关系: 1- 打开文件选择
有没有办法在调用“swingWorker.execute”之前将数据(例如对象)传递给 swingWorker? 最佳答案 通常,我通过使 SwingWorker 的构造函数需要所需的对象来处理此问题
我有这样的代码 try { ServerSocket serverSocket = null; try { serverSocket = new
如何获取代码当前运行的SwingWorker?您可以使用 Thread.currentThread() 来获取 Thread 实例,但我需要 SwingWorker 实例。 代码来自评论 privat
我有一个扩展 SwingWorker 的类。在它的后台线程中,如果成功更改布局并向框架添加新面板,我应该登录。因此 Swing Worker 执行以下 3 项任务: 登录 更改布局 添加/删除面板。
我有一个 swingworker,我想用它从 doInBackground() swingworker 方法中调用另一个对象的大型且复杂的方法。 看起来像这样: public class HostGa
我是一名优秀的程序员,十分优秀!