2012-03-24 6 views
2

Ich versuche zu:seltsamer Fehler - Wie pausiert man ein Java-Programm?

  1. Anzeige ein Text in einem JLabel,
  2. warten zwei Sekunden
  3. dann einen neuen Text in der

JLabel schreiben sollte so einfach sein , aber ich bekomme einen seltsamen Fehler: der erste Text wird nie geschrieben, die Anwendung wartet nur für 2 Sekunden und zeigt dann den endgültigen Text. Hier ist der Beispielcode: "Clicked"


private void testButtonActionPerformed(java.awt.event.ActionEvent evt) {  
    displayLabel.setText("Clicked!"); 

    // first method with System timer 

    /* 
    long t0= System.currentTimeMillis(); 
    long t1= System.currentTimeMillis(); 
      do{ 
       t1 = System.currentTimeMillis(); 
      } 
      while ((t1 - t0) < (2000)); 
    */  

    // second method with thread.sleep() 

    try { 
     Thread.currentThread().sleep(2000); 
    } catch (InterruptedException e) {} 

    displayLabel.setText("STOP"); 
} 

mit diesem Code, der Text wird nie angezeigt. Ich bekomme nur 2 Sekunden - Pause und dann den "STOP" -Text. Ich habe versucht, System-Timer mit einer Schleife oder Thread.sleep() zu verwenden, aber beide Methoden geben das gleiche Ergebnis.

+14

(seufz) Den EDT (Event Dispatch Thread) nicht blockieren. Anstatt 'Thread.sleep (n)' aufzurufen, implementieren Sie einen Swing 'Timer' oder verwenden Sie einen' SwingWorker', um lange laufende Aufgaben auszuführen. Weitere Informationen finden Sie unter [Parallelität in Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/). –

Antwort

2

Um mehr Hintergrundinformationen zu Andrew Thompsons Kommentar zu geben: Der EDT ist verantwortlich für die Handhabung von GUI-Updates. Wenn Sie es mit Thread.sleep(...) blockieren, werden diese Updates ebenfalls blockiert. Deshalb sehen Sie den ersten Text nicht - der EDT kann das Update auf dem Etikett einfach nicht machen.

2

Hier ist ein ausführbares Beispiel, das das tut, wonach Sie suchen. Wie Andrew Thompson bemerkte, ist eine SwingWorker eine gute Möglichkeit, dieses Problem anzugehen.

Das grundlegende Prinzip besteht darin, den Event Dispatch Thread niemals zu blockieren. Das ist der Thread, der dafür verantwortlich ist, die GUI neu zu streichen und auf die Benutzerinteraktion zu reagieren. Wenn Sie also im EDT etwas rechenintensives tun, reagiert Ihre GUI nicht mehr.

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.concurrent.ExecutionException; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.SwingWorker; 

public class ButtonTest { 
    public static void main(String[] args) { 

     // create a frame and a button 
     JFrame frame = new JFrame(); 
     final JButton button = new JButton("Button"); 
     frame.add(button); 

     // add an action listener to the button 
     button.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 

       // change the button text right away 
       button.setText("Clicked"); 

       // create a SwingWorker which simply waits 2000 milliseconds 
       // simulating a computation being performed 
       SwingWorker<String, Object> worker = new SwingWorker<String, Object>() { 
        @Override 
        public String doInBackground() { 

         // it's safe to call Thread.sleep() here 
         // doInBackground is executed on a separate worker 
         // thread 
         try { 
          Thread.sleep(2000); 
         } catch (InterruptedException e) { 
         } 

         return "Done"; 
        } 

        @Override 
        protected void done() { 

         // done() is executed back on the Swing thread 
         // so it's safe to updated the state of the button 
         try { 
          button.setText(get()); 
         } catch (Exception e) { } 
        } 
       }; 

       // run the worker 
       worker.execute(); 
      } 
     }); 

     frame.setSize(300, 300); 
     frame.setVisible(true); 
    } 
} 
+0

Vielen Dank Andrew Thompson, Ringträger, Hovercraft voller Aale und ulmangt. Endlich habe ich SwingWorker benutzt und es hat das Problem gelöst. – TerraNova993

2

Sie sind mit dem Event-Dispatcher-Thread unordentlich. Das wird unerwartetes Verhalten der Benutzeroberfläche verursachen, wie Sie sehen. Wenn Sie diese Art von Animationen tun mögen, stellen Sie sicher, dass auf lesen, was @ Andrew Thompson vorgeschlagen und auch, ob Sie dies lesen können - Filthy rich clients

Bessere Timer eine Schaukel zu verwenden, wie unten in curde-Beispiel zeigt: (ja, ist es grob, ich habe dir keine Sorgen über anhalten der Timer usw.):

public class DelayTest extends JPanel{ 
    JLabel messageLabel = new JLabel(); 
    JButton actionButton = new JButton("Click Me"); 
    String[] messages = {"Clicked", "Stop!"}; 
    int i=0; 
    public DelayTest(){ 
     super(); 
     add(messageLabel); 
     add(actionButton); 
     actionButton.addActionListener(new ActionListener() { 

      @Override 
      public void actionPerformed(ActionEvent arg0) { 
       Timer timer = new Timer(1000, new ActionListener() { 

        @Override 
        public void actionPerformed(ActionEvent arg0) { 
         if(i<=1) 
          messageLabel.setText(messages[i++]); 
        } 
       }); 
       timer.start(); 

      } 

     }); 
    } 

} 

bearbeiten
Warum die Timer nicht stoppen:

  @Override 
      public void actionPerformed(ActionEvent evt) { 
       if (i <= 1) { 
       messageLabel.setText(messages[i++]); 
       } else { 
       ((Timer)evt.getSource()).stop(); 
       } 
      } 
     }); 
+0

@ TerraNova993 dies ist der einfachste Weg, warum Swing Timer gibt es +1 – mKorbel

+0

Wenn Code hinzufügen, um den Timer zu stoppen? Code in Bearbeitung hinzugefügt. –

+0

@HovercraftFullOfEels - es wird nicht - ich erwähnte in meinem Beispiel .. es ist eine grobe. Ich möchte keine maßgeschneiderte Lösung geben, ich möchte lieber, dass TerraNova993 die Grundlagen versteht und es richtig macht. –

Verwandte Themen