Swing Thread+Animation

Button

Mitglied
Hi,
ich habe ein Problem, und zwar:
Der unten stehende Quelltext soll einen Bewegung eines Button von einer bestimmten Position zu einer anderen in einem JPanel bezwecken, das in ein JFrame (ist nicht im QT) eingebunden ist. Dabei soll von einem Auslöserbutton mit ActionListener und durch Aufruf einer AuslöserMethode diese Buttonbewegung hervorgerufen werden.
Da die Animation erst nur bei Aufruf der AuslöserMethode möglich war, und beim Druck des Auslöserbuttons das GUI laggte und der Button nur an der Endposition erschien( keine Animation also), habe ich iwo gelesen, dass sleep() das Gui zum laggen brint. Also dachte ich, versuch ich's mal mit Threads......
Nur hat das bis jetzt nichts geholfen :(

P.S:
Wenn ich thread.run() durch thread.start() ersetze,
bewegen sich bei einem Schleifenaufruf der AuslöserMethode alle zu bewegendes Buttons gleichzeitig (soll nicht so sein), aber wenigstens gibt es eine Animation beim Drücken des Auslöserbuttons :(



Java:
import javax.swing.*;
import java.awt.*;
public class Test extends JPanel
{
    private ButtonThread thread;
    private int i=0;
    private class ButtonThread extends Thread
    {
        private int x;
        private int y;
        private JButton button;

        public ButtonThread(JButton button, int x, int y, String name )
        {
            this.button=button; this.x=x; this.y=y; setName(name);
        }


        public void run()
        { 
            boolean status=false;
            int yjetzt=button.getLocation().y;
            int xjetzt=button.getLocation().x;
            while(!status)
            {
                try
                {   

                    sleep(10);
                    //System.out.println(""+button.getLocation().x+" "+button.getLocation().y);
                    button.setLocation(xjetzt,yjetzt);
                    if(xjetzt<=x){xjetzt+=10;}else{if(yjetzt<=y){yjetzt+=10;}else{status=true;}}

                }
                catch(InterruptedException e){}
            }

        }

    }
    
    public Test()
    {
        setLayout(null);
    }

    public void buttonAnimation(JButton button, int x,int y)
    { 
        thread=new ButtonThread(button,x,y,""+i);
        System.out.println(""+Thread.currentThread());
        thread.run();
      }
    
   

    public void paintComponent(Graphics g)
    {
        g.setColor(Color.white);
        g.fillRect(0,0,this.getWidth(),this.getHeight());
    }

}

Hoffe, irgendjemand kann mir Hilfe leiste :)

Übrigens, mit invokeLater klappt's iwie auch nicht
 
S

SlaterB

Gast
dein Code ist doch unvollständig, enthält kein JFrame zum Testen und vor allem keinen einzigen definierten Button,
von mehreren ganz zu schweigen

hier ein Testprogramm, mühsam selber erstellt (du hast es dir eingespart) mit einem Button,
eine Animation dafür ist definiert, eine Animation erscheint, keine Überraschung..

Java:
public class TestGUI
    extends JFrame
{

    public TestGUI()
    {
        Test2 t = new Test2();
        t.buttonAnimation(new JButton("hallo"), 30, 30);
        add(t);


        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 400);
        setVisible(true);
    }

    public static void main(String[] args)
    {
        new TestGUI();
    }

}


class Test2
    extends JPanel
{
    private ButtonThread thread;
    private int i = 0;

    private class ButtonThread
        extends Thread
    {
        private int x;
        private int y;
        private JButton button;

        public ButtonThread(JButton button, int x, int y, String name)
        {
            this.button = button;
            button.setSize(100, 50);
            add(button);
            this.x = x;
            this.y = y;
            setName(name);
        }

        public void run()
        {
            boolean status = false;
            int yjetzt = button.getLocation().y;
            int xjetzt = button.getLocation().x;
            while (!status)
            {
                try
                {

                    sleep(500);
                    System.out.println("" + button.getLocation().x + " " + button.getLocation().y);
                    button.setLocation(xjetzt, yjetzt);
                    if (xjetzt <= x)
                    {
                        xjetzt += 10;
                    }
                    else
                    {
                        if (yjetzt <= y)
                        {
                            yjetzt += 10;
                        }
                        else
                        {
                            status = true;
                        }
                    }

                }
                catch (InterruptedException e)
                {
                }
            }

        }

    }

    public Test2()
    {
        setLayout(null);
    }

    public void buttonAnimation(JButton button, int x, int y)
    {
        thread = new ButtonThread(button, x, y, "" + i);
        System.out.println("" + Thread.currentThread());
        thread.start();
    }


    public void paintComponent(Graphics g)
    {
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }

}
 

HimBromBeere

Top Contributor
Wenn ich thread.run() durch thread.start() ersetze...
:eek:
Du hast in deinem Code Thread#run() aufgerufen?? Sowas macht man nicht, Thread#start() ist auf jeden Fall schonmal richtig. Rufst du die run-Methode selbst auf, passiert absolut nichts, was man parallel nenne könnte, sondern dann läuft das Programm - wie du es gewohn bist - schön nacheiander ab...
 

Button

Mitglied
dein Code ist doch unvollständig, enthält kein JFrame zum Testen und vor allem keinen einzigen definierten Button,
von mehreren ganz zu schweigen

hier ein Testprogramm, mühsam selber erstellt (du hast es dir eingespart) mit einem Button,
eine Animation dafür ist definiert, eine Animation erscheint, keine Überraschung..

Ich hatte ja erwähnt, dass das JFrame nicht im QT ist. Beim Methodenaufruf funktioniert die Animation ja, aber wenn ich die Methode innerhalb eines ActionListeners bzw. bei Buttondruck aufrufe, entsteht keine Animation. Zugegeben, im Text oben wird das nicht so ganz klar, sry dafür. Trotzdem danke für deine Mühe.

@HimBromBeere
Der Aufruf von run() war auch nur ein Akt der Verzweiflung, aber irgendwie ist die Animation dann auch beim Buttondruck sichtbar
 
S

SlaterB

Gast
ich werde jetzt kein Beispiel mit ActionListener bauen, ist eh alles von deinen Konzepten abhängig, z.B. wann welche Buttons in die GUI eingefügt werden

grundsätzlich gehts, ohne Code nichts weiter zu sagen, schätze ich
 

Button

Mitglied
Ok, dann poste ich mal mehr :)

Haupt-Klasse:
Java:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Haupt extends JFrame
{
    private int x;
    private int y;
    private Test te;
    
    public Haupt()
    {
           setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1200,500);
        setResizable(false);
        setVisible(true);
        JPanel rahmen=new JPanel(new BorderLayout());
        JButton b=new JButton("Auslöser");
        JPanel panel=new JPanel();
        b.setBounds(0,0,50,50);
        b.addActionListener(new Listens());
        panel.add(b);
        te=new Test();
        te.setPreferredSize(new Dimension(1100,300));
        rahmen.add(te,BorderLayout.NORTH);
        rahmen.add(panel,BorderLayout.SOUTH);
        getContentPane().add(rahmen);
    }
  
    private class Listens implements ActionListener
    {

        public void actionPerformed(ActionEvent e)
        {
            bewegeTest();
           
        }
    }


    public static void test()
    {
        Haupt h=new Haupt();
        for(int i=0;i<10;i++)
        {
            h.bewegeTest();
        }
    }

  
    public void bewegeTest()
    {

        JButton b=new JButton();
        b.setSize(100, 50);
       
        te.add(b);
        te.buttonAnimation(b,x,y);
        x+=100;

    }

}

Beim Aufrufen von Test bzw. allgemein von bewegeTest gibt es eine Animation, allerdings beim Druck auf den Button mit dem Namen "Auslöser" nicht, der Button, der in bewegeTest erzeugt wird, ist nur sichtbar an der Endposition.

Die Klasse Test ist die gleiche wie oben.
 
S

SlaterB

Gast
setVisible(true); sollte der letzte Befehl im Konstruktor sein, sonst ist (bei mir) der Auslösen-Button nicht zu sehen,

du könntest in die run-Methode in die Schleife noch ein repaint(); aufnehmen, das ist wohl angebracht,
bei mir läuft es aber wiederum auf so schon gut, ich kann kein Problem erkennen

mit etwas kleineren Buttons, Farbe, höheren y, Verzögerung in der 10er-Schleife und langsamerer Bewegung kann ich auch mit dem Auslösen-Button paar blaue Buttons unter die normalen der Schleife mischen, das klappt alles super

Java:
public class Test
{
    public static void main(String[] args)
    {
        Haupt.test();
    }

}


class Haupt
    extends JFrame
{
    private int x;
    private int y = 200;
    private Test2 te;

    public Haupt()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1200, 500);
        setResizable(false);

        JPanel rahmen = new JPanel(new BorderLayout());
        JButton b = new JButton("Auslöser");
        JPanel panel = new JPanel();
        b.setBounds(0, 0, 50, 50);
        b.addActionListener(new Listens());
        panel.add(b);
        te = new Test2();
        te.setPreferredSize(new Dimension(1100, 300));
        rahmen.add(te, BorderLayout.NORTH);
        rahmen.add(panel, BorderLayout.SOUTH);
        getContentPane().add(rahmen);

        setVisible(true);
    }

    private class Listens
        implements ActionListener
    {

        public void actionPerformed(ActionEvent e)
        {
            bewegeTest(true);

        }
    }


    public static void test()
    {
        Haupt h = new Haupt();
        for (int i = 0; i < 10; i++)
        {
            h.bewegeTest(false);
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
            }
        }
    }


    public void bewegeTest(boolean blau)
    {

        JButton b = new JButton();
        b.setSize(40, 40);
        if (blau)
        {
            b.setBackground(Color.BLUE);
        }

        te.add(b);
        te.buttonAnimation(b, x, y);
        x += 40;

    }

}


class Test2
    extends JPanel
{
    private ButtonThread thread;
    private int i = 0;

    private class ButtonThread
        extends Thread
    {
        private int x;
        private int y;
        private JButton button;

        public ButtonThread(JButton button, int x, int y, String name)
        {
            this.button = button;
            // button.setSize(100, 50);
            // add(button);
            this.x = x;
            this.y = y;
            setName(name);
        }

        public void run()
        {
            boolean status = false;
            int yjetzt = button.getLocation().y;
            int xjetzt = button.getLocation().x;
            while (!status)
            {
                try
                {

                    sleep(20);
                    System.out.println("" + button.getLocation().x + " " + button.getLocation().y);
                    button.setLocation(xjetzt, yjetzt);
                    repaint();
                    if (xjetzt <= x)
                    {
                        xjetzt += 10;
                    }
                    else
                    {
                        if (yjetzt <= y)
                        {
                            yjetzt += 10;
                        }
                        else
                        {
                            status = true;
                        }
                    }

                }
                catch (InterruptedException e)
                {
                }
            }

        }

    }

    public Test2()
    {
        setLayout(null);
    }

    public void buttonAnimation(JButton button, int x, int y)
    {
        thread = new ButtonThread(button, x, y, "" + i);
        System.out.println("" + Thread.currentThread());
        thread.start();
    }


    public void paintComponent(Graphics g)
    {
        g.setColor(Color.white);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
    }

}
 

Neue Themen


Oben