# Simpler Timer zum warten



## derSoerrn (6. Aug 2012)

Hallo zusammen,

ich versage gerade daran mein Java-Programm für 100 Millisekunden zu pausieren. Ich habe nämlich ein JPanel, was bei Knopfdruck ausfährt. Allerdings möchte ich nicht, dass es mit einem Mal da ist sonder fände es schöner, wenn es geschmeidig in meinem Fenster heruntergleitet. Ich hab' bereits versucht mit 
	
	
	
	





```
Thread.sleep(100);
```
 zu arbeiten aber das hat aus irgendeinem Grund nicht funktioniert. Vielleicht "verträgt" sich dies ja nicht mit javax.swing. Aber ich habe keine Ahnung..

Hier der Code mit dem Thread-Versuch:


```
private void raus(){
            int hoeheAnfang = 10;
            Ausfahren.this.setSize(breiteNachher, hoheNachher + knopfRaus.getHeight());
            c.setLocation(0, knopfRaus.getHeight());
            c.setSize(breiteNachher, hoeheAnfang);
            Ausfahren.this.add(c);
            while(hoeheAnfang <= hoheNachher){
                c.setSize(breiteNachher, hoeheAnfang);
                try{
                    Thread.sleep(100);
                }
                catch(Exception e){
                    System.out.println("warten fehlgeschlagen");
                }
                hoeheAnfang = hoeheAnfang + 70;
            }
            c.setSize(breiteNachher, hoheNachher);
        }
```

P.S. das "c." ist in diesem Fall ein JPanel.

Ich hoffe Ihr könnt mir helfen


----------



## bERt0r (6. Aug 2012)

Dann schlage ich vor, du probiersts mal mit einem Timer


----------



## André Uhres (6. Aug 2012)

bERt0r hat gesagt.:


> Dann schlage ich vor, du probiersts mal mit einem Timer



Oder besser noch mit einem Swing Timer. Alle Callbacks laufen dann auf dem Event Dispatch Thread (EDT). Das ist nützlich für Swing Anwendungen, weil alle GUI Operationen auf dem EDT laufen müssen.

Gruß,
André


----------



## derSoerrn (8. Aug 2012)

Wenn ich einen der beiden Timer benutzen würde, dann sieht das meiner Meinung nach nicht so schön aus  Gibt es nicht eine Methode die einfach nur sagt, dass das Programm 100 ms wartet?


----------



## VfL_Freak (8. Aug 2012)

Moin,



derSoerrn hat gesagt.:


> Wenn ich einen der beiden Timer benutzen würde, dann sieht das meiner Meinung nach nicht so schön aus


Was bitte "_sieht daran nicht schön_" aus ???:L



derSoerrn hat gesagt.:


> Gibt es nicht eine Methode die einfach nur sagt, dass das Programm 100 ms wartet?


Doch: eben *Thread.sleep(100);*
Was genau klappt denn dabei nicht ???:L
Bekommst Du Deine Exception geworfen  ???:L

Gruß
Klaus


----------



## derSoerrn (8. Aug 2012)

```
try{
                    Thread.sleep(100);
                }
                catch(Exception e){
                    System.out.println("warten fehlgeschlagen");
                }
```

Der wirft mir dann den catch part entgegen.


----------



## Michael... (8. Aug 2012)

derSoerrn hat gesagt.:


> Wenn ich einen der beiden Timer benutzen würde, dann sieht das meiner Meinung nach nicht so schön aus


Was sieht nicht so schön aus bzw. wie sieht es aus und wie sollte es aussehen?
Wie sieht Dein Code dazu aus? Evtl. liegt ja hier die Ursache,

Möglichkeiten sind Timer, Timer oder Threads - aber nicht so wie im ersten Post den EDT einfach schlafen legen...


----------



## derSoerrn (8. Aug 2012)

Vielleicht liegt es auch daran, dass ich das nicht so ganz verstehe was André Uhres meinte.


> Oder besser noch mit einem Swing Timer. Alle Callbacks laufen dann auf dem Event Dispatch Thread (EDT). Das ist nützlich für Swing Anwendungen, weil alle GUI Operationen auf dem EDT laufen müssen.


----------



## VfL_Freak (8. Aug 2012)

Moin,



derSoerrn hat gesagt.:


> ```
> try
> {
> Thread.sleep(100);
> ...


aha - und welche Exception?
So sagt das doch gar nichts aus ....

Schreib' da doch wenigstens mal ein *e.printStackTrace()* rein !

Gruß
Klaus


----------



## derSoerrn (8. Aug 2012)

[WR]java.lang.IllegalMonitorStateException[/WR]
die bekomme ich. Sie endet mit einem Fehler in.

[WR]java.awt.EventDispatchThread.run(EventDispatchThread.java:97)[/WR]


----------



## VfL_Freak (8. Aug 2012)

na, dann hast Du es doch ..... 

http://openbook.galileocomputing.dejavainsel9javainsel_14_006.htm#mj136bf82444e4726887b78ff7e2940dcb

Gruß
Klaus


----------



## Michael... (8. Aug 2012)

Ich bleibe dabei:


Michael... hat gesagt.:


> Wie sieht Dein Code dazu aus?


Ohne Code (und evtl. der komplette Stacktrace der Fehlermeldung) kann man nicht viel dazu sagen.


----------



## derSoerrn (8. Aug 2012)

Dein Link funktioniert leider nicht


----------



## derSoerrn (8. Aug 2012)

```
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.Timer;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
/**
 * @author 
 * @version 
 */
public class Ausfahren extends JPanel{
    // Bezugsobjekte
    JPictureButton knopfRaus, knopfRein;
    Linie linie;
    JLabel text;
    // Attribute
    private int x, y, breite, breiteNachher, hoheNachher;
    private String aufschrift;
    private long warte;
    private Component c;
    // Konstruktor
    public Ausfahren(int x, int y, int breite, long zeit, String aufschrift, Component c){
        u = new Uhr();
        this.setLayout(null);
        this.x = x;
        this.y = y;
        if(breite != 0){
            this.breite = breite;
        }
        this.hoheNachher = c.getHeight();
        this.breiteNachher = c.getWidth()-x;
        this.c = c;
        this.warte = zeit;

        knopfRaus = new JPictureButton(0, 0, "Bilder\\Ausklappen1.png", "Bilder\\Ausklappen2.png", "Bilder\\Ausklappen3.png");
        knopfRaus.addActionListener(new ActionHandler());
        knopfRein = new JPictureButton(0, 0, "Bilder\\Einklappen1.png", "Bilder\\Einklappen2.png", "Bilder\\Einklappen3.png");
        knopfRein.addActionListener(new ActionHandler());

        text = new JLabel();
        text.setLayout(null);

        linie = new Linie();
        linie.setBounds((knopfRaus.getWidth()), 0, (breite - knopfRaus.getWidth()-x), 20);
        linie.setBackground(Color.GREEN);

        if(aufschrift != null){
            text.setLayout(null);
            text.setBounds(knopfRaus.getWidth()+20, 0, (breite - knopfRaus.getWidth()-x), 20);
            text.setFont(new Font("Arial", Font.BOLD, 20));
            text.setText(aufschrift);
        }

        this.setBounds(x, y, breite, knopfRaus.getHeight());
        this.add(linie);
        this.add(knopfRaus);
        this.setComponentZOrder(text, 0);
        this.add(c);
        this.remove(c);
    }

    // Dienste
    /**
     * Setzt einen Text an die gewünschte Position neben den Knopf zum ausfahren des neuen Componenten
     */
    public void setzeSchrift(int x, String aufschrift, Font f, Color c){
        text.setForeground(c);
        text.setFont(f);
        text.setBounds(knopfRaus.getWidth()+20, 0, (breite - knopfRaus.getWidth()-x), 10);
        text.setText(aufschrift);
        text.setHorizontalAlignment(x);
        this.add(text);

    }

    /**
     * "Repaintet alle Objekte in dieser Klasse
     */
    public void repaintPanels(){
        c.repaint();
        linie.repaint();
        this.repaint();
    }

    private class ActionHandler implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource().equals(knopfRaus)){
                Ausfahren.this.remove(knopfRaus);
                Ausfahren.this.add(knopfRein);
                ausklappen();
                Ausfahren.this.repaint();
            }else if(e.getSource().equals(knopfRein)){
                Ausfahren.this.remove(knopfRein);
                Ausfahren.this.add(knopfRaus);
                einklappen();
                Ausfahren.this.repaint();
            }
        }

        private void ausklappen(){
            int hoeheAnfang = 10;
            Ausfahren.this.setSize(breiteNachher, hoheNachher + knopfRaus.getHeight());
            c.setLocation(0,knopfRaus.getHeight());
            c.setSize(breiteNachher, hoeheAnfang);
            Ausfahren.this.add(c);
            while(hoeheAnfang <= hoheNachher){
                c.setSize(breiteNachher, hoeheAnfang);
                try{
                    this.wait(100);
                }
                catch(Exception e){
                    e.printStackTrace();
                }
                hoeheAnfang = hoeheAnfang + 70;
            }
            c.setSize(breiteNachher, hoheNachher);
        }

        private void einklappen(){
            int hoeheEnde = hoheNachher;
            while(hoeheEnde >= 0){
                c.setSize(breiteNachher, hoeheEnde);

                try{
                    Thread.sleep(warte);
                }
                catch(Exception e){
                    System.out.println("warten fehlgeschlagen");
                }
                hoeheEnde = hoeheEnde - 70;
            }
            c.setSize(0, 0);
            Ausfahren.this.setSize(breiteNachher, knopfRaus.getHeight());
            Ausfahren.this.remove(c);
        }
    }
    private class Linie extends JLabel{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            if(breite != 0){
                this.setForeground(Color.BLACK);
                g.drawLine(0, (this.getHeight()/2), this.getWidth()-x, (this.getHeight()/2));
            }
        }
    }
}
```

Die Namen der Methoden, Attribute etc. sind vielleicht nicht so gut gewählt


----------



## Michael... (8. Aug 2012)

In dem Code ist aber nichts von einem Timer oder Thread zu sehen. Ich dachte Du hättest es bereits mit einem Timer implementiert? Oder worauf bezog sich: "dann sieht das ... nicht so schön aus"


----------



## jamesv (9. Aug 2012)

derSoerrn: Du hättest ja wenigstens eigenständig die Slashes einfügen können.
Hier der vollständige Link:
Galileo Computing :: Java ist auch eine Insel – 14.6 Synchronisation über Warten und Benachrichtigen


----------



## VfL_Freak (9. Aug 2012)

hmm, kA, was da beim Kopieren schief gelaufen war ...


----------



## André Uhres (9. Aug 2012)

derSoerrn hat gesagt.:


> Vielleicht liegt es auch daran, dass ich das nicht so ganz verstehe was André Uhres meinte.



Der EDT ist sehr wichtig, weil er alle Events der Swing Komponenten weiterleitet und die Malmethoden aufruft. Es ist der Thread, auf dem wir mit Swing zusammenarbeiten. Wenn wir zum Beispiel eine Taste in einem JTextField drücken, leitet der EDT dieses Event weiter an den KeyListener der Komponente. Die Komponente aktualisiert dann ihr Model und schickt einen Malantrag fort. Der EDT verarbeitet diesen Malantrag und sagt wiederum der Komponente, dass es Zeit ist, sich neu zu malen. Kurz gesagt: in Swing geschieht alles auf dem EDT!

Übrigens, wenn wir eine langwierige Operation auf dem EDT ausführen, wie das Lesen einer Datei, blockieren wir die ganze Benutzeroberfläche: keine Events werden weitergeleitet und keine Bildschirmaktualisierung wird durchgeführt solange die zeitaufwendige Operation andauert. Aus Benutzersicht scheint dann die Anwendung zu hängen oder zumindest sehr langsam zu sein.

In Java gibt es den util.Timer und den swing.Timer. Der swing.Timer bietet eine API, die an eine Swing Umgebung besser angepasst ist als der util.Timer. Er macht es äußerst einfach, periodische Aktionen durchzuführen und stellt sicher, dass alles auf dem EDT durchgeführt wird. Ein Timer, der die Benutzeroberfläche aktualisiert, ist daher gewöhnlich ein swing.Timer. Ein Timer dagegen, der Hintergrundoperationen durchführt, ist gewöhnlich ein util.Timer.

sleep() ist nützlich, wenn wir nur einen einzigen Aufwachbefehl brauchen. Wenn wir diesen jedoch immer wieder benötigen, ist ein Timer besser geeignet: wir brauchen uns dann nicht mehr um den Aufwachbefehl zu kümmern und werden bei der eigentlichen Sache, die zu tun ist, nicht durch einen sleep() blockiert. Die Benutzeroberfläche wird dadurch insgesamt leistungsfähiger.

Gruß,
André


----------



## derSoerrn (9. Aug 2012)

```
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.Timer;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
/**
 * @author 
 * @version 
 */
public class Ausfahren extends JPanel{
    // Bezugsobjekte
    JPictureButton knopfRaus, knopfRein;
    Linie linie;
    JLabel text;
    Timer t;
    // Attribute
    private int x, y, breite, breiteNachher, hoheNachher;
    private String aufschrift;
    private long warte;
    private Component c;
    // Konstruktor
    public Ausfahren(int x, int y, int breite, long zeit, String aufschrift, Component c){
        this.setLayout(null);
        this.x = x;
        this.y = y;
        if(breite != 0){
            this.breite = breite;
        }
        this.hoheNachher = c.getHeight();
        this.breiteNachher = c.getWidth()-x;
        this.c = c;
        this.warte = zeit;

        knopfRaus = new JPictureButton(0, 0, "Bilder\\Ausklappen1.png", "Bilder\\Ausklappen2.png", "Bilder\\Ausklappen3.png");
        knopfRaus.addActionListener(new ActionHandler());
        knopfRein = new JPictureButton(0, 0, "Bilder\\Einklappen1.png", "Bilder\\Einklappen2.png", "Bilder\\Einklappen3.png");
        knopfRein.addActionListener(new ActionHandler());

        text = new JLabel();
        text.setLayout(null);

        linie = new Linie();
        linie.setBounds((knopfRaus.getWidth()), 0, (breite - knopfRaus.getWidth()-x), 20);
        linie.setBackground(Color.GREEN);

        if(aufschrift != null){
            text.setLayout(null);
            text.setBounds(knopfRaus.getWidth()+20, 0, (breite - knopfRaus.getWidth()-x), 20);
            text.setFont(new Font("Arial", Font.BOLD, 20));
            text.setText(aufschrift);
        }
        this.setBounds(x, y, breite, knopfRaus.getHeight());
        this.add(linie);
        this.add(knopfRaus);
        this.setComponentZOrder(text, 0);
        this.add(c);
        this.remove(c);
    }

    // Dienste
    /**
     * Setzt einen Text an die gewünschte Position neben den Knopf zum ausfahren des neuen Componenten
     */
    public void setzeSchrift(int x, String aufschrift, Font f, Color c){
        text.setForeground(c);
        text.setFont(f);
        text.setBounds(knopfRaus.getWidth()+20, 0, (breite - knopfRaus.getWidth()-x), 10);
        text.setText(aufschrift);
        text.setHorizontalAlignment(x);
        this.add(text);

    }

    /**
     * "Repaintet alle Objekte in dieser Klasse
     */
    public void repaintPanels(){
        c.repaint();
        linie.repaint();
        this.repaint();
    }

    private class ActionHandler implements ActionListener{
        private int hoeheAnfang = 10;
        private int hoeheEnde = hoheNachher;
        @Override
        public void actionPerformed(ActionEvent e) {
            if(e.getSource().equals(knopfRaus)){
                Ausfahren.this.remove(knopfRaus);
                Ausfahren.this.add(knopfRein);
                ausklappen();
                Ausfahren.this.repaint();
            }else if(e.getSource().equals(knopfRein)){
                Ausfahren.this.remove(knopfRein);
                Ausfahren.this.add(knopfRaus);
                einklappen();
                Ausfahren.this.repaint();
            }
        }

        private void ausklappen(){
            Ausfahren.this.setSize(breiteNachher, hoheNachher + knopfRaus.getHeight());
            c.setLocation(0,knopfRaus.getHeight());
            c.setSize(breiteNachher, hoeheAnfang);
            Ausfahren.this.add(c);
            while(hoeheAnfang <= hoheNachher){
                t = new Timer(100, new ActionListener()
                    {
                        @Override
                        public void actionPerformed(ActionEvent e){
                            c.setSize(breiteNachher, hoeheAnfang);
                            hoeheAnfang = hoeheAnfang + 70;
                        }
                    }
                );
            }
            c.setSize(breiteNachher, hoheNachher);
        }

        private void einklappen(){
            while(hoeheEnde >= 0){
                t = new Timer(100, new ActionListener()
                    {
                        @Override
                        public void actionPerformed(ActionEvent e){
                            c.setSize(breiteNachher, hoeheEnde);
                            hoeheEnde = hoeheEnde - 70;
                        }
                    }
                );
            }
            c.setSize(0, 0);
            Ausfahren.this.setSize(breiteNachher, knopfRaus.getHeight());
            Ausfahren.this.remove(c);
        }
    }

    private class Linie extends JLabel{
        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            if(breite != 0){
                this.setForeground(Color.BLACK);
                g.drawLine(0, (this.getHeight()/2), this.getWidth()-x, (this.getHeight()/2));
            }
        }
    }
}
```

... sorry Jungs hab euch aus Versehen das alte geschickt ^^ Tut mir leid! Aber ich glaube ich habe es eh falsch implementiert 

Danke André das hat mir so einiges verdeutlicht


----------



## André Uhres (9. Aug 2012)

Du hast anscheinend noch nicht richtig verstanden, wie ein Timer funktioniert. Ich sehe zu Beispiel in Deinem Code nirgends, wo Du den Timer startest. Zudem erzeugst Du mehrere Timer in einer Schleife! Vielleicht hilft diese Seite Dir weiter: 
How to Use Swing Timers (The Java™ Tutorials > Creating a GUI With JFC/Swing > Using Other Swing Features)

Gruß,
André


----------

