我有一个名为 ItemGUI 的类,它处理与用户界面相关的所有内容。用户能够添加一些链接,这些链接是项目,因此当他插入链接并单击“添加”按钮时,它应该创建一个 Item 类的新对象并开始运行一个名为 getPrice() 的函数,类似于那:
Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
newItem.getPrice()
这应该在单击添加按钮后完成。然后我将该项目打印到 table 上。问题是 getPrice() 方法应该每 5 秒运行一次,而不会阻塞我的 GUI,所以我应该实现线程。
我的问题是:如何实现一个线程,该线程每 5 秒运行一次该函数(针对列表中的每个项目),直到我单击停止按钮?我正在考虑使用带有时钟的观察者可观察类,每 5 秒通知观察者一次。这会是最好的选择吗? 另外,我是否能够从 ItemGUI 类中检索项目变量?
谢谢!
最佳答案
更新
MadProgrammer 建议的最清晰的解决方案是使用 swing Timers ,像这样:
protected javax.swing.Timer refresherTimer = null;
protected void stopRefreshing() {
if (refresherTimer != null) {
refresherTimer.stop();
refresherTimer = null;
}
}
protected void startRefreshing() {
stopRefreshing();
refresherTimer = new Timer(500, e -> {
newItem.getPrice()
});
refresherTimer.start();
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// here newItem should be added to a list of items which should be in the ItemGUI class
startRefreshing();
}
public void onStopButtonClicked() {
stopRefreshing();
}
原始答案
如果有一些名为例如的实用程序,那就太好了GuiTimer
这将使您的任务变得简单:
protected GuiThread.Task refresherTask = null;
protected void cancelRefreshing() {
if (refresherTask != null) {
refresherTask.cancel();
refresherTask = null;
}
}
public void onStartButtonClicked() {
Item newItem = new Item(newItemField.getText());
// should also be added to a list of items which should be in the ItemGUI class
cancelRefreshing();
refresherTask = GuiThread.scheduleAtFixedRate(() -> {
newItem.getPrice()
}, 0, 5, TimeUnit.SECONDS);
}
public void onStopButtonClicked() {
cancelRefreshing();
}
常规计时器的问题是它们在自己的线程上调用回调函数,而不是在 gui 线程上,因此需要开发人员确保正确的线程。不幸的是,内置的java EventQueue不支持调度延迟任务。
出于这个原因,我喜欢使用以下名为 GuiTimer
的实用程序,它将充当纯 gui 线程计时器:
public class GuiTimer {
public static final ScheduledThreadPoolExecutor executor =
new ScheduledThreadPoolExecutor(1);
public static interface Task {
public void cancel();
}
private static class CancelStateTask implements Task {
public volatile boolean canceled = false;
@Override
public void cancel() {
this.canceled = true;
}
}
public static Task schedule(final Runnable action) {
CancelStateTask task = new CancelStateTask();
EventQueue.invokeLater(() -> {
if (!task.canceled)
action.run();
});
return task;
}
public static Task schedule(final Runnable command, long delay,
TimeUnit unit) {
ScheduledFuture<?> future = executor.schedule(
() -> EventQueue.invokeLater(command), delay, unit);
return () -> future.cancel(false);
}
public static Task scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay,
period, unit);
return () -> future.cancel(false);
}
public static Task scheduleWithFixedDelay(Runnable command,
long initialDelay, long delay, TimeUnit unit) {
ScheduledFuture<?> future = executor.scheduleAtFixedRate(
() -> EventQueue.invokeLater(command), initialDelay, delay,
unit);
return () -> future.cancel(false);
}
public static void shutdown() {
executor.shutdown();
}
}
关于java - 每 x 次调用函数而不阻塞 GUI Java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34240070/