2013-07-07 14 views
5

Dobrze, więc stworzyłem prosty program, który dodaje wartość do liczenia za każdym razem, gdy kliknięto przycisk. Teraz chciałbym dodać funkcję przycisku "Auto", aby zwiększyć wartość licznika po kliknięciu przycisku "Auto". Mam problemy z nim, ponieważ nie uczyni każdą wartość licznika na ekranie, zamiast dostawać wartość, gdy pętla jest zrobione .. Oto mój kod:Przycisk ActionListener

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.TimeUnit; 
import javax.swing.JButton; 
import javax.swing.JFrame; 


public class Gui extends JFrame{ 

    private static final long serialVersionUID = 1L; 

    private JButton uselesButton; 

    private JButton autoButton; 

    private FlowLayout layout; 
    private long counter = 0; 

    public Gui() { 
     super("Button"); 
     layout = new FlowLayout(FlowLayout.CENTER); 
     this.setLayout(layout); 

     uselesButton = new JButton(String.format("Pressed %d times", counter)); 
     add(uselesButton); 
     uselesButton.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       counter++; 
       uselesButton.setText(String.format("Pressed %d times", counter)); 
      } 

     }); 

     autoButton = new JButton("Auto"); 
     add(autoButton); 
     autoButton.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
         for(long i =0; i < 99999999;i++) { 
         try { 
          TimeUnit.MILLISECONDS.sleep(10); 
         } catch (InterruptedException e1) { 
          System.out.println("ERROR"); 
         } 
         counter = i; 
         uselesButton.setText(String.format("Pressed %d times", counter)); 
        } 
        } 
     }); 
    } 
} 

Należy pamiętać, że jestem początkujący ... Cała pomoc doceniona :)

+0

Jakie jest pytanie? – Sello

+1

Co * dokładnie * oznacza przycisk automatyczny? –

+3

Myślę, że [Swing Timer] (http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) rozwiąże to. – Azad

Odpowiedz

4

spójrz na samouczek na temat sposobu korzystania Swing Timer a następnie spojrzeć na moje rozwiązanie:

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 

public class Gui extends JFrame { 

    private static final long serialVersionUID = 1L; 
    private JButton uselesButton; 
    private JButton autoButton; 
    private FlowLayout layout; 
    private long counter = 0; 
    private javax.swing.Timer timer; 

    public Gui() { 
     super("Button"); 
     layout = new FlowLayout(FlowLayout.CENTER); 
     setLayout(layout); 
     setDefaultCloseOperation(3); 
     setSize(300, 300); 
     setLocationRelativeTo(null); 

     //initialing swing timer 
     timer = new javax.swing.Timer(100, getButtonAction()); 

     autoButton = new JButton("Auto"); 
     add(autoButton); 
     autoButton.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (!timer.isRunning()) { 
        timer.start(); 
       } else { 
        timer.stop(); 
       } 
      } 
     }); 
    } 

    private ActionListener getButtonAction() { 
     ActionListener action = new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       autoButton.setText(String.format("Pressed %d times", ++counter)); 
       if (counter > 1000) { 
        timer.stop(); 
       } 
      } 
     }; 
     return action; 
    } 

    public static void main(String... args) { 
     javax.swing.SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Gui().setVisible(true); 
      } 
     }); 
    } 
} 
0

Problem polega na tym, że system jest w pętli, więc nie może malować zmian. Aby to zrobić, musisz otworzyć nowy wątek. nowy wątek zrobi pętlę, a główny wątek odświeży formularz.

Jeszcze jedno, nie powinieneś spać w głównym wątku. można użyć Timer, która co 10 milisekund zamiast sleep(10) here jest przykładem

+2

Czy Swing Timer nie byłby lepszym rozwiązaniem? –

+1

Czy przetestowałeś swoje zalecenia? 'repaint()' nie zrobi nic w przypadku pętli wiążącej EDT. Usuń to zalecenie, aby usunąć możliwość głosowania w dół. –

+0

Również wątek malarski nie jest głównym wątkiem. To wątek wysyłki zdarzeń. –

0

Twój blok kodu wątek GUI (EDT), gdy wchodzi wewnątrz tej pętli (GUI zawiśnie, przycisk nie zostanie zaktualizowany do momentu zakończenia), więc należy dodać kod wewnątrz innego wątku roboczego:

autoButton.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
        new Thread(new Runnable() { 
         @Override 
         public void run() { 
          for(long i =0; i < 99999999;i++) { 
           try { 
            TimeUnit.MILLISECONDS.sleep(10); 
           } catch (InterruptedException e1) { 
            System.out.println("ERROR"); 
           } 
           counter = i; 

           java.awt.EventQueue.invokeLater(new Runnable() { 
             public void run() { 
             uselesButton.setText(String.format("Pressed %d times", counter)); 
             } 
           }); 
          } 
         } 
        }).start(); 
      } 
     }); 
Powiązane problemy