gpt4 book ai didi

java - 更快地通知 PropertyChangeListener

转载 作者:行者123 更新时间:2023-11-30 05:58:39 27 4
gpt4 key购买 nike

因此,我正在创建一个 JProgressBar,它显示 CSV 操作的进度,其中读取每一行并检查强制(NOT NULL)列中是否没有空值。为此,我创建了一个 SwingWorker 任务,用于将文件中的行数转换为最大进度值的 100%,并以正确的速率累加进度。

这就是 SwingWorker:

public static class Task extends SwingWorker<String, Object> {

private int counter;
private double rate;

public Task(int max) {
// Adds the PropertyChangeListener to the ProgressBar
addPropertyChangeListener(
ViewHandler.getExportDialog().getProgressBar());
rate = (float)100/max;
setProgress(0);
counter = 0;
}

/** Increments the progress in 1 times the rate based on maximum */
public void step() {
counter++;
setProgress((int)Math.round(counter*rate));
}

@Override
public String doInBackground() throws IOException {
return null;
}
@Override
public void done() {
Toolkit.getDefaultToolkit().beep();
System.out.println("Progress done.");
}
}

我的PropertyChangeListener由 JProgressBar 包装器实现:

@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
progressBar.setIndeterminate(false);
progressBar.setValue((Integer) evt.getNewValue());
}
}

然后,在实际使用它的地方,我使用所需的处理重写 doInBackground() 方法,在每次迭代时调用 step()

    Task read = new Task(lines) {
@Override
public String doInBackground() throws IOException {
while(content.hasNextValue()) {
step();
// Processing
}
return output.toString();
}
};
read.execute();
return read.get();

所以发生了什么:处理工作并成功,然后调用 done() ,紧接着 propertyChange()注册两个“状态”事件和一个“进度”事件,将 ProgressBar 的进度设置为从 0% 到 100%。

发生了什么 我认为发生了什么(check Hovercraft's answer 用于澄清)在 JavaDocs 中进行了描述:

由于 PropertyChangeListener 是在事件分派(dispatch)线程上异步通知的,因此在调用任何 PropertyChangeListener 之前可能会发生对 setProgress 方法的多次调用。出于性能目的,所有这些调用都合并为一个调用,仅包含最后一个调用参数。

所以,毕竟,我的问题是:我做错了什么吗?如果没有,有没有办法让事件调度线程在 onProgress() 发生时通知 PropertyChangeListeners,或者至少不时通知?

观察:我正在测试的处理时间为 3~5 秒。

最佳答案

您的问题在这里:

read.execute();
return read.get();

get() 是一个阻塞调用,因此在执行工作线程后立即从事件线程调用它会阻塞事件线程和 GUI

相反,应该从回调方法(例如 done() 方法)调用它,或者在工作线程将其状态属性更改为 SwingWorker.StateValue 后从属性更改监听器调用它.完成.

<小时/>

例如

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import javax.swing.*;

@SuppressWarnings("serial")
public class TestSwingWorkerGui extends JPanel {
private JProgressBar progressBar = new JProgressBar(0, 100);
private Action myAction = new MyAction("Do It!");

public TestSwingWorkerGui() {
progressBar.setStringPainted(true);
add(progressBar);
add(new JButton(myAction));
}

private class MyAction extends AbstractAction {
public MyAction(String name) {
super(name);
}

@Override
public void actionPerformed(ActionEvent e) {
myAction.setEnabled(false);
Task read = new Task(30) {
@Override
public String doInBackground() throws Exception {
int counter = getCounter();
int max = getMax();
while (counter < max) {
counter = getCounter();
step();
TimeUnit.MILLISECONDS.sleep(200);
}
return "Worker is Done";
}
};
read.addPropertyChangeListener(new MyPropListener());
read.execute();
}
}

private class MyPropListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if ("progress".equals(name)) {
progressBar.setIndeterminate(false);
progressBar.setValue((Integer) evt.getNewValue());
} else if ("state".equals(name)) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
myAction.setEnabled(true);
@SuppressWarnings("unchecked")
SwingWorker<String, Void> worker = (SwingWorker<String, Void>) evt.getSource();
try {
String text = worker.get();
System.out.println("worker returns: " + text);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
}

private static void createAndShowGui() {
TestSwingWorkerGui mainPanel = new TestSwingWorkerGui();

JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}

class Task extends SwingWorker<String, Void> {

private int counter;
// private double rate;
private int max;

public Task(int max) {
// Adds the PropertyChangeListener to the ProgressBar
// addPropertyChangeListener(gui);
// !!rate = (float)100/max;
this.max = max;
setProgress(0);
counter = 0;
}

/** Increments the progress in 1 times the rate based on maximum */
public void step() {
counter++;
int progress = (100 * counter) / max;
progress = Math.min(100, progress);
setProgress(progress);
// setProgress((int)Math.round(counter*rate));
}

public int getCounter() {
return counter;
}

public int getMax() {
return max;
}

@Override
public String doInBackground() throws Exception {
return null;
}

@Override
public void done() {
Toolkit.getDefaultToolkit().beep();
System.out.println("Progress done.");
}
}

关于java - 更快地通知 PropertyChangeListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52672462/

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