while(true) lässt GUI einfrieren

Jens B.

Erfahrenes Mitglied
Hallo!
Ich arbeite grad an meinem ersten Java-Projekt. Ich habe eine while(true)-Schleife, um ein paar Objekte auf einer Art Bühne zu bewegen. Das funktioniert auch, aber dann friert die GUI ein (ein paar Buttons usw). Wie kann ich erreichen, dass die GUI weiter neu gezeichnet und auch die ActionListener weiterhin funktionieren, während eine while(true)-Schleife läuft?

Mein GUI besteht aus einem JPanel-Objekt, welchem alle anderen GUI-Objekte per add angehängt sind. Gezeichnet wird in ein weiteres Panel innerhalb diesem JPanel.

Den Weg über ein Timer-Objekt wollte ich eigentlcih nicht gehen.
Danke euch
jens
 
Hallo!
Danke schonmal! Habe das jetzt gemacht, jetzt gibt es Probeme beim wiederholten Starten und stoppen. Mein Code sieht jetzt so aus:

Code:
(...)          
  } else if(source == btnPlay) {
                run.start();

            } else if(source == btnStop) {
                run.stop();
            } 
        }
    }

    public class RunningThread extends Thread {
        @Override
        public void run() {
            while(true) {
                // update von einem Frame
            }
        }
    }
}

Das funktioniert auch prächtig, aber wenn ich den Thread einmal gestoppt habe und dann wieder starten möchte kommt ein Fehler:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:612)
at infpp.OceanGUI$Actions.actionPerformed(OceanGUI.java:358)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:253)
at java.awt.Component.processMouseEvent(Component.java:6108)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3267)
at java.awt.Component.processEvent(Component.java:5873)
at java.awt.Container.processEvent(Container.java:2105)
at java.awt.Component.dispatchEventImpl(Component.java:4469)
at java.awt.Container.dispatchEventImpl(Container.java:2163)
at java.awt.Component.dispatchEvent(Component.java:4295)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4461)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4125)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4055)
at java.awt.Container.dispatchEventImpl(Container.java:2149)
at java.awt.Window.dispatchEventImpl(Window.java:2478)
at java.awt.Component.dispatchEvent(Component.java:4295)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:604)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)

Wie kann ich das verhindern?
Danke und grüße
jens

/Edit: Hab's herrausgefunden. Hinter dem stop() muss einfach ein run = new RunningThread(); stehen und es funktioniert. Das scheint mir aber nicht die beste Lösung zu sein - wenn jemand weiß, wie es riochtig geht, wär klasse.
 
Zuletzt bearbeitet:
Hi!
Einmal gestoppte Threads lassen sich nicht wieder starten. Du kannst aber den Thread schlafenlegen.

Wenn du den Thread aber am Ende doch stoppen möchtest, dann solltest du auch nicht die stop()- Methode (Deprecated, kann zu Problemen führen) nutzen, sondern über interrupt arbeiten.
PseudoCode:
Code:
if(source == btnStop) {
                run.interrupt()
            } 
            else if(source = btnPause)
                run.pause();    
             }

}

    public class RunningThread extends Thread {
        private boolean sleeping = false;
         public function pause(){
           sleeping = !sleeping; 
        }
        @Override
        public void run() {
            while(!interrupted()) {
               if(!sleeping){
                // update von einem Frame
               
              }
              else{  
                  sleep(1000);  // legt den Thread eine Sekunde schlafen
             }
            }
        }


Das jetzt aber nur zum Thread Verhalten. Generell ist es eine bessere Idee mit dem SwingWorker zu arbeiten, wenn irgendwelche GUI Sachen geupdatet werden sollen.
http://java.sun.com/javase/6/docs/api/javax/swing/SwingWorker.html

*grüssle*
 

Neue Beiträge

Zurück