gpt4 book ai didi

java - 暂停和恢复 SwingWorker.doInBackground()

转载 作者:行者123 更新时间:2023-12-03 23:14:54 25 4
gpt4 key购买 nike

我有一个带有标记为“播放”的单个按钮的基本 Swing UI。按下按钮时,标签变为“暂停”。现在按下按钮时,它会变为“恢复”。

在“播放”时,我正在实例化并执行一个 SwingWorker。我想要的是能够暂停这个线程(而不是取消它)并根据上面描述的按钮恢复它。但是,我不想在 doInBackground() 中使用 Thread.sleep()。这似乎有点骇人听闻。运行doInBackground的线程有什么办法阻塞吗?

最佳答案

Pause and Resume SwingWorker.doInBackground()

首先你必须确保正在执行的后台任务可以暂停,否则这个问题没有意义。所以假设任务可以暂停,那么你可以扩展SwingWorker使用一个简单的标志变量来控制后台线程状态:pausednot paused

public abstract class PausableSwingWorker<K, V> extends SwingWorker<K, V> {

private volatile boolean isPaused;

public final void pause() {
if (!isPaused() && !isDone()) {
isPaused = true;
firePropertyChange("paused", false, true);
}
}

public final void resume() {
if (isPaused() && !isDone()) {
isPaused = false;
firePropertyChange("paused", true, false);
}
}

public final boolean isPaused() {
return isPaused;
}
}

子类可能会检查 isPaused() 状态,以便有效地继续执行任务。例如:

PausableSwingWorker<Void, String> worker = new PausableSwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
if (!isPaused()) {
// proceed with background task
} else {
Thread.sleep(200); // Optional sleep to avoid check status continuously
}
}
return null;
}
};

您也可以添加 PropertyChangeListener到工作人员并监听 paused 属性变化:

worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("paused".equals(evt.getPropertyName())) {
System.out.println("Old status: " + evt.getOldValue());
System.out.println("New status: " + evt.getNewValue());
}
}
});

示例(更新为使用 PropertyChangeListener)

这是一个完整的例子。请注意,如果 worker 被停止,那么它就不能被暂停或恢复。

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Demo {

private void createAndShowGUI() {

final JTextArea textArea = new JTextArea(20, 50);

final PausableSwingWorker<Void, String> worker = new PausableSwingWorker<Void, String>() {
@Override
protected Void doInBackground() throws Exception {
while (!isCancelled()) {
if (!isPaused()) {
publish("Writing...");
} else {
Thread.sleep(200);
}
}
return null;
}

@Override
protected void process(List<String> chunks) {
String text = String.format("%s%n", chunks.get(chunks.size() - 1));
textArea.append(text);
}
};

worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("paused".equals(evt.getPropertyName())) {
String text = (Boolean)evt.getNewValue() ? "Paused..." : "Resumed...";
textArea.append(String.format("%s%n", text));
}
}
});

Action pause = new AbstractAction("Pause") {
@Override
public void actionPerformed(ActionEvent e) {
worker.pause();
}
};

Action resume = new AbstractAction("Resume") {
@Override
public void actionPerformed(ActionEvent e) {
worker.resume();
}
};

Action stop = new AbstractAction("Stop") {
@Override
public void actionPerformed(ActionEvent e) {
worker.cancel(true);
}
};

JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
buttonsPanel.add(new JButton(pause));
buttonsPanel.add(new JButton(resume));
buttonsPanel.add(new JButton(stop));

JPanel content = new JPanel(new BorderLayout(8, 8));
content.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
content.add(new JScrollPane(textArea), BorderLayout.CENTER);
content.add(buttonsPanel, BorderLayout.SOUTH);

JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if (!worker.isDone()) {
worker.cancel(true);
}
e.getWindow().dispose();
}
});

frame.add(content);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);

worker.execute();
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Demo().createAndShowGUI();
}
});
}

abstract class PausableSwingWorker<K, V> extends SwingWorker<K, V> {

private volatile boolean isPaused;

public final void pause() {
if (!isPaused() && !isDone()) {
isPaused = true;
firePropertyChange("paused", false, true);
}
}

public final void resume() {
if (isPaused() && !isDone()) {
isPaused = false;
firePropertyChange("paused", true, false);
}
}

public final boolean isPaused() {
return isPaused;
}
}
}

关于java - 暂停和恢复 SwingWorker.doInBackground(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26265002/

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