2017-05-12 43 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