基本上,我试图做的是在用户单击按钮时连续将文本字符串附加到JTextPane中。仅当用户再次单击按钮时,循环才会停止。这是我按钮的动作执行方法:
StyledDocument xpInfo = txtXPInfo.getStyledDocument();
if (btnGo.getText().equals("Go Adventure!")) {
btnGo.setText("Stop Adventure");
try {
do {
xpInfo.insertString(xpInfo.getLength(), "Some stringn", null);
txtXPInfo.update(txtXPInfo.getGraphics());
Thread.sleep(1000);
} while (btnGo.getText().equals("Stop Adventure"));
} catch (BadLocationException e) {
System.out.println(e);
} catch (InterruptedException ex) {
Logger.getLogger(FrmPlay.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (btnGo.getText().equals("Stop Adventure")) {
btnGo.setText("Go Adventure!");
}
我写的代码似乎是一个无限循环。我想这可能是因为我在按钮的 actionPerforming 方法中做了所有这些,但我不知道如何做到这一点。如果这是一个如此愚蠢的问题,我很抱歉。我提前感谢任何愿意回答这个问题的人!
ScheduledExecutorService
,因为它的主要目的是以一定的指定时间间隔在单独的线程上执行任务。但是您需要记住,所有与 UI 相关的操作都必须从 EDT 完成,因此您应该使用 SwingUtilities.invokeLater()
包装txtXPInfo
更新操作:
private final ScheduledExecutorService xpInfoScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
private ScheduledFuture<?> xpInfoUpdatingFuture;
public void actionPerformed() {
StyledDocument xpInfo = txtXPInfo.getStyledDocument();
if (btnGo.getText().equals("Go Adventure!")) {
btnGo.setText("Stop Adventure");
xpInfoUpdatingFuture = xpInfoScheduledExecutor.scheduleAtFixedRate(
new XpInfoUpdater(), 0, 1, TimeUnit.SECONDS);
} else if (btnGo.getText().equals("Stop Adventure")) {
xpInfoUpdatingFuture.cancel(true);
btnGo.setText("Go Adventure!");
}
}
private class XpInfoUpdater implements Runnable {
@Override
public void run() {
SwingUtilities.invokeLater(() -> {
try {
xpInfo.insertString(xpInfo.getLength(), "Some stringn", null);
txtXPInfo.update(txtXPInfo.getGraphics());
} catch (BadLocationException e) {
System.out.println(e);
}
});
}
}
我认为您的问题是您阻止了Event Thread
。在 Swing 中,OS 只使用一个线程来调度 UI 事件(如按下按钮(。
在您的情况下,您似乎在该线程上无限循环。如果是,则其他按钮按下将永远不会注册,因为该线程正忙于您的do/while
循环。
您真正想做的是启动一个执行追加循环的不同线程(有很多示例(,并保留调度 UI 事件的Event Thread
。