2016-12-27 4 views
0

Ich erstelle ein einfaches Java-Programm mit einer GUI mit Hilfe von Fenster Builder erstellt. Die GUI besteht nur aus einer Schaltfläche.Java-Thread Start-Stop-Start auf die gleiche Schaltfläche klicken

Starten Sie auf Knopfdruck einen Thread, der bis zur Beendigung der Zufallszahl endlos drucken soll, indem Sie erneut auf die gleiche Schaltfläche klicken.

Hier ist mein Code

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(){ 

    } 
} 

Vielen Dank im Voraus.

+0

Was ist Ihre Frage? Sie können einen Thread nicht stoppen, indem Sie einfach "Ihre Referenz darauf ersetzen". 'Start' stoppt nie aufgrund der externen (nutzlosen) Schleife. Bitte stellen Sie eine selbsterklärende Frage, möglicherweise eine [mvce]. –

Antwort

1

Ihr Code bricht Swing-Threading-Regeln ab, während Sie Mutationsänderungen an Swing-Komponenten aus dem Swing-Ereignisthread vornehmen. Vorschläge:

  • Niemals Thread erweitern. Es ist fast immer besser, Runnable zu implementieren und das Runnable in einem Thread zu verwenden.
  • Vermeiden Sie Swing-Aufrufe außer repaint() vom Swing-Event-Thread.
  • Ihre while (true) ist eine "enge" Schleife - es hat keine Thread.sleep in sich, und das bedeutet, dass es Gefahr läuft, die CPU in seiner engen Schleife zu tippen, etwas, das Ihr Programm und Ihren Computer behindern kann.
  • Am besten vermeiden Sie die Verwendung von direktem Hintergrund-Threading, da Ihr Code-Problem mit Hilfe eines Swing-Timers viel einfacher und sauberer gelöst werden kann. Bitte überprüfen Sie die Swing Timer Tutorial
  • Sie können diesen Timer einfach durch Aufruf seiner start() und stop() Methoden starten und stoppen.
  • Ich würde auch eine JList bevorzugt über eine JTextArea verwenden, da es größere Datenmengen leichter behandeln kann.
  • Ich mag auch lieber AbstractActions als ActionListeners für meine JButton, und dieses Problem eignet sich gut für ihre Verwendung. Sie können eine Aktion für den Start und eine für den Stopp erstellen und einfach die Aktionen der Schaltfläche austauschen.

Zum Beispiel:

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()); 
    } 
} 
Verwandte Themen