2016-12-27 3 views
0

Я создаю простую java-программу с графическим интерфейсом, созданным с помощью построителя окон. GUI состоит из одной кнопки.Java Thread Start-Stop-Start на той же кнопке мыши

Нажав кнопку, запустите поток, который будет бесконечно печатать на случайное число до его остановки, снова нажав на ту же кнопку.

Вот мой код

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. Предложения:

  • Никогда не распространяйте нить. Почти всегда лучше реализовать Runnable и использовать Runnable в потоке.
  • Избегайте создания вызовов Swing, отличных от repaint(), от потока событий Swing.
  • Ваш while (true) - это «плотный» цикл - в нем нет Thread.sleep, и это означает, что он рискует набрать процессор в его жесткой петле, что может помешать вашей программе и вашему компьютеру.
  • Лучше всего избегать использования прямой фоновой резьбы здесь, поскольку проблема с кодом может быть решена гораздо проще и чище с помощью таймера Swing. Пожалуйста, проверьте
  • Вы можете легко запустить и остановить этот таймер, позвонив по его методам и stop().
  • Я бы также использовал JList преимущественно над JTextArea, поскольку он может более легко обрабатывать большие объемы данных.
  • Мне также нравится использовать AbstractActions, а не ActionListeners для моего JButton, и эта проблема хорошо поддается их использованию. Вы можете создать Action для начала и один для остановки и просто поменять действия кнопки.

Например:

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()); 
    } 
} 
Смежные вопросы