Springender Ball, Thread.sleep(i)?

hahawall

Mitglied
Hallo, ich möchte ein Programm das folgendes tut:

Ich habe dieses Fenster


Drückt man nun auf "Hüpf!" soll der Ball kurz in die Luft springen.

Dazu habe ich folgenden Code:

Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Test {
JFrame frame;

    JButton buttonA = new JButton("Ball");

    JPanel panelUnten = new JPanel();
    JPanel panelMitte = new JPanel();
    JPanel panelMitteLeer = new JPanel();

    CardLayout cardMitte = new CardLayout();

    Kreis kreis = new Kreis();

    int frameheight = 400;
    int framewidth = 400;

    int x=175;
    int y=270;

    int dicke = 50;

    public static void main (String[] args) {
        Test test = new Test();
        test.los();
    }

    public void los() {
        frame = new JFrame();

        frame.setSize(frameheight, framewidth);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonA.addActionListener(new ButtonAListener());

        panelUnten.setBackground(Color.red);
        panelMitteLeer.setBackground(Color.black);

        panelMitte.setLayout(cardMitte);

        panelMitte.add(panelMitteLeer, "Leer");
        panelMitte.add(kreis, "Kreis");

        panelUnten.add(buttonA);

        frame.getContentPane().add(BorderLayout.SOUTH, panelUnten);
        frame.getContentPane().add(BorderLayout.CENTER, panelMitte);

        frame.setVisible(true);
    }

    class Kreis extends JPanel {
        public void paintComponent(Graphics g) {
            g.setColor(Color.black);
            g.fillRect(0, 0, this.getWidth(), this.getHeight());

            g.setColor(Color.red);
            g.fillOval(x, y, dicke, dicke);
        }
    }

    class ButtonAListener implements ActionListener {
        public void actionPerformed (ActionEvent e) {

            cardMitte.show(panelMitte, "Kreis");

            if(buttonA.getText().equals("Hüpf!")) {
                for (int i=0; i<100; i++) {
                    y--;
                    kreis.repaint();
                    try {Thread.sleep(50);} catch(Exception ex) {}
                }
            }

            else if(buttonA.getText().equals("Ball")) {
                buttonA.setText("Hüpf!");
            }
        }//actionPerformed zuende
    }//ButtonAlistener zuende
}

Ich möchte also in den for Schleifen das Panel schwarz übermalen, ein Stückchen höher einen neuen Ball zeichnen und dazwischen etwas warten damit es so aussieht als würde der Ball hochspringen. Drücke ich aber auf "Hüpf!" dann wartet das Programm etwa 5 Sekunden (also 100 mal 50ms) und zeichnet den Ball direkt nach ganz oben, es wird also anscheinend nicht mit jeder Iteration in der for Schleife ein neuer Ball gezeichnet sondern erst wenn die Schleife vorbei ist. Warum ist das so? In folgendem sehr ähnlichen Programm funktioniert alles wie gewollt:

Java:
import javax.swing.*;
import java.awt.*;

public class AnimationA {
    int x,y;
    JFrame frame;

    public static void main(String[] args) {
        AnimationA animation = new AnimationA();
        animation.los();
    }

    public void los() {
        x = 10;
        y = 10;

        frame = new JFrame();

        frame.setSize(300,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        MeinZeichenPanel kreis = new MeinZeichenPanel();

        frame.getContentPane().add(kreis);

        frame.setVisible(true);

        for (int i=0; i<200; i++) {
            kreis.repaint();

            x++;
            y++;

            try {
                Thread.sleep(50);
            } catch (Exception ex) {}
        }
        
        for (int i=0; i<200; i++) {
            kreis.repaint();

            x--;
            y--;

            try {
                Thread.sleep(50);
            } catch (Exception ex) {}
        }


    }

    class MeinZeichenPanel extends JPanel{
        @Override
        public void paintComponent (Graphics g) {
            g.setColor(Color.black);
            g.fillRect(0, 0, this.getHeight(), this.getWidth());

            g.setColor(Color.red);
            g.fillOval(x, y, 30, 30);
        }
    }
}

Hier wandert ein Ball von links oben schräg nach rechts unten und wieder zurück.
 

Monaria

Aktives Mitglied
Probier mal statt repaint das hier:
Code:
kreis.paintImmediately(new Rectangle(kreis.getWidth(), kreis.getHeight()));
 

Monaria

Aktives Mitglied
Also wenn ich das richtig verstanden habe, ist der für die Events bezüglich des GUI zuständige Thread, der Event Dispatcher Thread, blockiert und ruft repaint() erst auf, wenn er durch dein Event durch ist.
Im Konstruktor platziert funktioniert das hier auch, hier ist der Thread ja nicht beschäftigt.

Ich hoffe das stimmt so in etwa^^

It's rarely necessary to call this method. In most cases it's more efficient to call repaint, which defers the actual painting and can collapse redundant requests into a single paint call. This method is useful if one needs to update the display while the current event is being dispatched.
 
G

Gast2

Gast
It's rarely necessary to call this method.
Jo, das ist auch wohl so :)

Wenn man das richtig aufzieht reicht nen einfaches repaint();
Du hast deine Schleife in der actionPerformed, also auf dem EDT laufen.
Setz die Schleife in nen eigenen Thread, der ruft dann einfach repaint und dein JPanel auf.
 

jgh

Top Contributor
jepp, bei der Möglichkeit mit [c]kreis.paintImmediately(new Rectangle(kreis.getWidth(), kreis.getHeight())); [/c] erkennst du, dass der JButton während des "Hochspringen" des Balles weiterhin gedrückt ist...also der EDT weiterhin blockiert ist.

Hier mal qnd:
Java:
	class ButtonAListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			cardMitte.show(panelMitte, "Kreis");

			if (buttonA.getText().equals("Hüpf!")) {
				Thread t = new Thread(new Runnable() {

					@Override
					public void run() {
						for (int i = 0; i < 100; i++) {
							y--;
							kreis.repaint();
							try {
								Thread.sleep(50);
							} catch (Exception ex) {
								ex.printStackTrace();
							}
						}
					}
				});
				t.start();
			} else if (buttonA.getText().equals("Ball")) {
				buttonA.setText("Hüpf!");
			}
		}// actionPerformed zuende
	}//ButtonAlistener zuende
 

wkt

Mitglied
Wunderbares Beispiel. Jetzt ist mir die Thread Programmierung wieder ein Stück
klarer geworden. Danke an alle.

Nur : was bedeutet das Chatkürzel "qnd" bitte ? Möchte mein Lexikon gerne erweitern.
 

Neue Themen


Oben