gpt4 book ai didi

java - Java 中带有 GUI 的多线程

转载 作者:行者123 更新时间:2023-12-02 11:38:29 26 4
gpt4 key购买 nike

我正在为一个计算密集型程序开发 GUI,并且需要一段时间才能完成计算。我想在 GUI 上显示和更新处理时间,既可以作为引用,也可以向用户表明程序正在运行。我创建了一个工作线程来处理单独线程上的处理时间,如下所示:

public class Worker extends SwingWorker<String, String>{

JLabel label;
boolean run;

public Worker(JLabel label)
{
this.label = label;
this.run = true;
}

@Override
protected String doInBackground() throws Exception {
//This is what's called in the .execute method
long startTime = System.nanoTime();
while(run)
{
//This sends the results to the .process method
publish(String.valueOf(System.nanoTime() - startTime));
Thread.sleep(100);
}
return null;
}

public void stop()
{
run = false;
}

@Override
protected void process(List<String> item) {
double seconds = Long.parseLong(item.get(item.size()-1))/1000000000.0;
String secs = String.format("%.2f", seconds);
//This updates the UI
label.setText("Processing Time: " + secs + " secs");
label.repaint();
}
}

我将一个 JLabel 传递给 Worker,它会在其上显示处理时间。以下代码创建 Worker 并执行一个可执行主要计算的可运行程序。

Worker worker = new Worker(jLabelProcessTime);
worker.execute();
//Check for results truncation
boolean truncate = !jCheckBoxTruncate.isSelected();
long startTime = System.nanoTime();
String[] args = {fileName};
//run solution and draw graph
SpeciesSelection specSel = new SpeciesSelection(args, truncate);
Thread t = new Thread(specSel);
t.start();
t.join();
ArrayList<Double> result = specSel.getResult();
drawGraph(result);
worker.stop();

我的问题是,直到计算完成后,GUI 上的处理时间才会更新。我想我已经非常接近了,因为没有 't.join();'计时器更新正常,但处理从未完成。我真的很感激一些帮助来找出问题所在。

最佳答案

您的代码没有像您想象的那样工作...

我创建了MVCE为你...

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class SwingWorkerTest extends JFrame {

public SwingWorkerTest() {
this.setLayout(new FlowLayout());
JButton button = new JButton("run");
JLabel label = new JLabel("time: -");
button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
Worker worker = new Worker(label);
worker.execute();
//Check for results truncation
// boolean truncate = !jCheckBoxTruncate.isSelected();
// long startTime = System.nanoTime();
// String[] args = {fileName};
//run solution and draw graph
// SpeciesSelection specSel = new SpeciesSelection(args, truncate);
// Thread t = new Thread(specSel);
// t.start();
// t.join();
// ArrayList<Double> result = specSel.getResult();
// drawGraph(result);
worker.stop();

System.out.println("button's actionPerformed finished");
}
});

this.getContentPane().add(button);
this.getContentPane().add(label);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}

public static void main(String[] args) {
new SwingWorkerTest();
}
}

class Worker extends SwingWorker<String, String>{

JLabel label;
boolean run;

public Worker(JLabel label)
{
this.label = label;
this.run = true;
}

@Override
protected String doInBackground() throws Exception {
System.out.println("doInBackground..., run=" + run);
//This is what's called in the .execute method
long startTime = System.nanoTime();
// while(run)
// {
System.out.println("running...");
//This sends the results to the .process method
publish(String.valueOf(System.nanoTime() - startTime));
Thread.sleep(100);
// }
System.out.println("worker finished...");
return null;
}

public void stop()
{
// System.out.println("stop");
// run = false;
}

@Override
protected void process(List<String> item) {
System.out.println("processed");
double seconds = Long.parseLong(item.get(item.size()-1))/1000000000.0;
String secs = String.format("%.2f", seconds);
//This updates the UI
System.out.println("updating");
label.setText("Processing Time: " + secs + " secs");
// label.repaint();
}
}

简而言之,我发现,在 doInBackground 之前调用了 Worker.stop(),因此,您的运行是错误的,因此 publish从未被调用过。

上面的“固定”代码打印(启动后我调整了大小并单击了运行按钮):

button's actionPerformed finished
doInBackground..., run=true
running...
processed
updating
worker finished...

它显示:

enter image description here

<小时/>

使用计时器的新方法

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.JLabel;
import javax.swing.SwingWorker;
import javax.swing.SwingWorker.StateValue;
import javax.swing.Timer;

public class SwingWorkerTestNew extends JFrame {

int progress = 0;

public SwingWorkerTestNew() {
GridLayout layout = new GridLayout(2, 1);
JButton button = new JButton("run");
JLabel label = new JLabel("progress: -");
WorkerNew worker = new WorkerNew(label);
button.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
worker.execute();
System.out.println("button's actionPerformed finished");
}
});

this.getContentPane().setLayout(layout);
this.getContentPane().add(button);
this.getContentPane().add(label);

this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);

Timer timer = new Timer(100, new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
if (worker.getState() == StateValue.STARTED) {
++progress;
label.setText(Integer.toString(progress));
}
if (worker.getState() == StateValue.DONE) {
label.setText("done");
}
}
});
timer.start();
}

public static void main(String[] args) {
new SwingWorkerTestNew();
}
}

class WorkerNew extends SwingWorker<String, String> {

JLabel label;

public WorkerNew(JLabel label) {
this.label = label;
}

@Override
protected String doInBackground() throws Exception {
System.out.println("background");
Thread.sleep(2000);
System.out.println("done");
return null;
}

}

关于java - Java 中带有 GUI 的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48743234/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com