2016-12-27 58 views
0

我正在用窗口構建器的幫助下構建的GUI創建一個簡單的java程序。 GUI由一個按鈕組成。Java線程啓動 - 停止 - 在同一個按鈕上點擊開始

點擊按鈕後,啓動一個線程,該線程將無限次地打印到隨機數,直到再次單擊相同的按鈕而停止爲止。

這裏是我的代碼

LoopTest.java

import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 
public class LoopTest extends JFrame implements ActionListener {//****** 
    private JButton startB, stopB; 
    private JTextArea oa; 
    Start sta; 

    public LoopTest(){ 
     super("Final Exam: Question "); 

     Container c = getContentPane(); 
     c.setLayout(new FlowLayout()); 

     startB = new JButton("START"); c.add(startB); 

     stopB = new JButton("STOP"); c.add(stopB); 

     oa = new JTextArea(5,20); c.add(oa); 
     c.add(new JScrollPane(oa)); 

     registerEvents(); 
     sta = new Start("Loop", oa); 

    } 
    public void registerEvents(){ 
     startB.addActionListener(
       new ActionListener(){ 
        public void actionPerformed(ActionEvent ae){ 
         if(startB.isEnabled() == true) 
          sta.setLoopFlag(true); 
         if(!sta.isAlive()) 
          sta.start(); 
         startB.setEnabled(false); 

        } 
       } 
     ); 

     stopB.addActionListener(
       new ActionListener(){ 
        public void actionPerformed(ActionEvent ae){ 
         if(stopB.isEnabled()==true){ 
          sta.setLoopFlag(false); 

         } 

        } 

     } 

     ); 
    } 
    @Override 
    public void actionPerformed(ActionEvent e) { 
     // TODO Auto-generated method stub 

    } 
    public static void main(String[] args){ 
     LoopTest app = new LoopTest(); 
     app.setSize(300,300); 
     app.setLocationRelativeTo(null); 
     app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     app.setVisible(true); 
    } 

} 

Start.java

public class Start extends Thread { 

private JTextArea ta; 
    private boolean loopFlag; 

    public Start(String name, JTextArea ta){ 
     super(name); 
     this.ta = ta; 
     ta.setText(""); 
     loopFlag = true; 
    } 
    public void run(){ 
     int num=0; 
     while(true) 
      while(loopFlag){ 
       num = 1+ (int)(Math.random()*100); 
       ta.append(num + "\n"); 
      } 
    } 


    public void setLoopFlag(boolean value){ 
     loopFlag = value; 
    } 

} 

Stop.java

public class Stop extends Thread { 
    public Stop(String name){ 
     super(name); 
    } 
    public void run(){ 

    } 
} 

在此先感謝。

+0

什麼是你的問題?您無法通過簡單地「替換您的引用」來阻止該線程。由於外部(無用)循環,「開始」永遠不會停止。請提出一個不言自明的問題,可能是[mvce]。 –

回答

1

當您正在對Swing事件線程中的Swing組件進行突變更改時,您的代碼會打破Swing線程規則。 建議:

  • 永不延長線程。實現Runnable並在線程中使用Runnable幾乎總是更好。
  • 避免在SWing事件線程之外進行除repaint()之外的Swing調用。
  • 您的while (true)是一個「緊密」的循環 - 它內部沒有Thread.sleep,這意味着它有可能在緊密循環中鍵入CPU,這會妨礙程序和計算機。
  • 最好避免在這裏完全使用直接後臺線程,因爲您的代碼問題可以通過使用Swing Timer來更容易和乾淨地解決。請檢查Swing Timer Tutorial
  • 您可以通過調用它的start()stop()方法輕鬆啓動和停止此計時器。
  • 我也會優先使用JList,而不是JTextArea,因爲它可以更輕鬆地處理大量的數據。
  • 我也喜歡在我的JButton中使用AbstractActions而不是ActionListeners,並且這個問題很好地適用於它們的使用。您可以創建一個用於開始的動作和一個用於停止的動作,並簡單地換出按鈕的動作。

例如:

import java.awt.BorderLayout; 
import java.awt.event.*; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class StartStop extends JPanel { 
    private static final int TIMER_DELAY = 300; 
    private StartAction startAction = new StartAction(); 
    private StopAction stopAction = new StopAction(); 
    private JButton button = new JButton(startAction); 
    private DefaultListModel<Integer> model = new DefaultListModel<>(); 
    private JList<Integer> jList = new JList<>(model); 
    private Timer timer = new Timer(TIMER_DELAY, new TimerListener()); 

    public StartStop() { 
     JPanel btnPanel = new JPanel(); 
     btnPanel.add(button); 

     jList.setFocusable(false); 
     jList.setVisibleRowCount(10); 
     jList.setPrototypeCellValue(100000); 
     JScrollPane scrollPane = new JScrollPane(jList); 

     setLayout(new BorderLayout()); 
     add(scrollPane, BorderLayout.CENTER); 
     add(btnPanel, BorderLayout.PAGE_END); 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
      int num = 1 + (int) (Math.random() * 100); 
      model.addElement(num); 
     } 
    } 

    private class StartAction extends AbstractAction { 
     public StartAction() { 
      super("Start"); 
      putValue(MNEMONIC_KEY, KeyEvent.VK_S); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      timer.start(); 
      button.setAction(stopAction); 
     } 
    } 

    private class StopAction extends AbstractAction { 
     public StopAction() { 
      super("Stop"); 
      putValue(MNEMONIC_KEY, KeyEvent.VK_S); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      timer.stop(); 
      button.setAction(startAction); 
     } 
    } 


    private static void createAndShowGui() { 
     JFrame frame = new JFrame("Start Stop"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(new StartStop()); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
}