Java 如何阻止JButton执行无止境循环
基本上,我试图做的是当用户单击按钮时,不断地将一个文本字符串附加到JTextPane中。只有当用户再次单击按钮时,循环才会停止。这是我的按钮的actionPerformed方法:Java 如何阻止JButton执行无止境循环,java,loops,jbutton,Java,Loops,Jbutton,基本上,我试图做的是当用户单击按钮时,不断地将一个文本字符串附加到JTextPane中。只有当用户再次单击按钮时,循环才会停止。这是我的按钮的actionPerformed方法: StyledDocument xpInfo = txtXPInfo.getStyledDocument(); if (btnGo.getText().equals("Go Adventure!")) { btnGo.setText("Stop Adventure"); try { do
StyledDocument xpInfo = txtXPInfo.getStyledDocument();
if (btnGo.getText().equals("Go Adventure!")) {
btnGo.setText("Stop Adventure");
try {
do {
xpInfo.insertString(xpInfo.getLength(), "Some string\n", 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!");
}
我写的代码似乎是一个无止境的循环。我想这可能是因为我在button的actionPerformed方法中做了所有这些,但我不知道如何做。如果这是个愚蠢的问题,我很抱歉。我提前向任何愿意回答这个问题的人表示感谢 我认为您的问题是您正在阻止
事件线程
。在Swing中,操作系统只使用一个线程来调度UI事件(如按下按钮)
在您的例子中,您似乎在该线程上无限循环。如果是,则其他按钮将永远不会注册,因为该线程正忙于执行do/while
循环
您真正想要做的是启动一个不同的线程(有很多这样的例子)来执行追加循环,并留下
事件线程来调度UI事件。我认为您的问题是您正在阻止事件线程。在Swing中,操作系统只使用一个线程来调度UI事件(如按下按钮)
在您的例子中,您似乎在该线程上无限循环。如果是,则其他按钮将永远不会注册,因为该线程正忙于执行do/while
循环
您真正想要做的是启动另一个执行追加循环的线程(有很多这样的例子),并将事件线程
留给调度UI事件。您可以使用ScheduledExecutorService
,因为它的主要目的是在具有指定时间间隔的单独线程上执行任务。但是您需要记住,所有与UI相关的操作都必须从EDT完成,因此您应该将txtXPInfo
更新操作包装为SwingUtilities.invokeLater()
:
private final scheduledexecutor服务xpInfoScheduledExecutor=Executors.newSingleThreadScheduledExecutor();
私有计划未来xpinfoupdatefuture;
已执行的公共无效操作(){
StyledDocument xpInfo=txtXPInfo.getStyledDocument();
if(btnGo.getText().equals(“Go Adventure!”){
btnGo.setText(“停止冒险”);
xpinfoupdatefuture=xpInfoScheduledExecutor.scheduleAtFixedRate(
新的XpInfoUpdater(),0,1,TimeUnit.SECONDS);
}else if(btnGo.getText().equals(“停止冒险”)){
xpinfoupdatefuture.cancel(true);
btnGo.setText(“去冒险!”);
}
}
私有类XpInfoUpdater实现可运行{
@凌驾
公开募捐{
SwingUtilities.invokeLater(()->{
试一试{
xpInfo.insertString(xpInfo.getLength(),“某些字符串\n”,null);
txtXPInfo.update(txtXPInfo.getGraphics());
}捕获(错误位置异常e){
系统输出打印ln(e);
}
});
}
}
您可以使用ScheduledExecutorService
,因为它的主要用途是在具有指定时间间隔的单独线程上执行任务。但是您需要记住,所有与UI相关的操作都必须从EDT完成,因此您应该将txtXPInfo
更新操作包装为SwingUtilities.invokeLater()
:
private final scheduledexecutor服务xpInfoScheduledExecutor=Executors.newSingleThreadScheduledExecutor();
私有计划未来xpinfoupdatefuture;
已执行的公共无效操作(){
StyledDocument xpInfo=txtXPInfo.getStyledDocument();
if(btnGo.getText().equals(“Go Adventure!”){
btnGo.setText(“停止冒险”);
xpinfoupdatefuture=xpInfoScheduledExecutor.scheduleAtFixedRate(
新的XpInfoUpdater(),0,1,TimeUnit.SECONDS);
}else if(btnGo.getText().equals(“停止冒险”)){
xpinfoupdatefuture.cancel(true);
btnGo.setText(“去冒险!”);
}
}
私有类XpInfoUpdater实现可运行{
@凌驾
公开募捐{
SwingUtilities.invokeLater(()->{
试一试{
xpInfo.insertString(xpInfo.getLength(),“某些字符串\n”,null);
txtXPInfo.update(txtXPInfo.getGraphics());
}捕获(错误位置异常e){
系统输出打印ln(e);
}
});
}
}
我不在事件线程上这样做Swing、Sleep或循环是个坏主意@沃尔特:我查过了,我可能会把它改成计时器。除了使用Thread.sleep()之外,我不知道如何延迟,所以我使用了Thread.sleep()。我知道循环是个坏主意,我只是不知道如何让它工作。无论如何,谢谢你的推荐!虽然我不在事件线程上做这样的摆动、睡眠或循环是个坏主意@沃尔特:我查过了,我可能会把它改成计时器。除了使用Thread.sleep()之外,我不知道如何延迟,所以我使用了Thread.sleep()。我知道循环是个坏主意,我只是不知道如何让它工作。无论如何,谢谢你的推荐!恐怕我不懂事件线索。你有没有建议我应该在哪里读这本书?不幸的是,我已经试着读了,但有太多的东西我不明白。我以后可能会再读一次。无论如何谢谢你的推荐,学习新东西很好!恐怕我不懂事件线索。你有没有建议我应该在哪里读这本书?不幸的是,我已经试着读了,但有太多的东西我不明白。我以后可能会再读一次。无论如何谢谢你的推荐,学习新东西很好!
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 string\n", null);
txtXPInfo.update(txtXPInfo.getGraphics());
} catch (BadLocationException e) {
System.out.println(e);
}
});
}
}