2017-05-12 41 views
1

基本上我试图做的是不断追加一个字符串文本到用户单击按钮时JTextPane。只有当用户再次点击按钮时,循环才会停止。这是在我的按钮的actionPerformed方法:如何阻止JButton执行无限循环

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!"); 
} 

我写的代码似乎是一个无限循环。我认为这可能是因为我在按钮的actionPerformed方法中完成了所有这些操作,但我不知道如何实现它。如果这是一个愚蠢的问题,我很抱歉。我事先感谢任何愿意回答这个问题的人!

+1

虽然我不做摇摆,睡觉,或像循环这在事件线程上是一个坏主意。 [你也许应该看看定时器。](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) – WalterM

+0

@WalterM我研究过它,我可能会把它变成一个定时器。我不知道如何延迟使用Thread.sleep(),这是我使用的。而且我知道循环是一个糟糕的主意,我不知道如何才能使其工作。无论如何感谢您的建议! – Grandevox

回答

0

您可以使用ScheduledExecutorService作为其主要目的是在具有指定时间间隔的单独线程上执行任务。但是你要记住,所有UI相关的操作必须从EDT来完成,所以你应该换txtXPInfo更新操作与SwingUtilities.invokeLater()

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); 
      } 
     }); 
    } 
} 
+0

这实际上工作!非常感谢! – Grandevox

0

我认为你的问题是你阻止Event Thread。在Swing中,操作系统只用一个线程来调度UI事件(如按下按钮)。

在你的情况下,它出现,你无限循环在该线程上。如果是,那么其他按钮将不会注册,因为该线程正忙于您的循环。

你真正想要做的是启动一个不同的线程(这里有很多这样的例子),它们执行追加循环,并且保留Event Thread来分派UI事件。

+0

恐怕我不明白事件线程。你有建议我应该在哪里阅读它? – Grandevox

+0

https://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html – Kylar

+0

谢谢!我现在会读它,希望我能理解它。 – Grandevox