Ausführen pausieren

Max K.

Mitglied
Hi,

ich möchte eine Kugel bewegen und das ganze auch pausieen können (das Bewegen klappt schon).
Dafür habe ich einen Thread, in dem mit einer endlosen while-Schleife die Koordinaten der Kugel erhöht werden.
Nun möchte ich aber bei einem Buttonklick pausieren. Den ActionListener habe ich schon, aber wie sage ich dem femden Thread nun, dass er waten soll, bis ich ihn wieder wecke?

Ich probiere nun schon seit Stunden rum und krige nichts mehr hin.

Danke schonmal im Voraus!


Max K.
 
Ganz grob.. mit einem Flag...
Code:
class Animator implements Runnable
{
    private boolean paused = false;

    public synchronized void setPaused(boolean p)
    {
        if (paused != p)  
        {
            paused = p;
            notifyAll();
        }
    }

    public void run()
    {
        while (true)
        {
            while (paused)
            {
                synchronized(this) { wait(); } // try/catch drum...
            }
            bewegen();
        }
    }

}
 
Durch einen ActionListener könntest du ein boolean setzen. Der andere Thread prüft dieses boolean ständig und falls es gesetzt ist, ruft der Thread die pause-Funktion auf. Die Funktion braucht dazu ein beliebiges Objekt aus der Klasse, indem die pause-Funktion liegt. Um den Thread weiter laufen zu lassen, muss ein anderer Thread dann resume aufrufen.
Das könnte etwas so aussehen:
Java:
private Object lock = new Object();

private void pause() {
  synchronized(lock) {
    lock.wait();
  }
}

public void resume() {
  synchronized (lock) {
    lock.notifyAll();
  }
}
 
Erstmal danke!

Ich habe das jetzt gemacht, wie Marco13geschrieben hat. Es funktioniert soweit auch alles, nur beim Wiederstarten kommt er (das habe ich durch Tests mit System.out.print() herausgefunden) nur bis in die void setPaused. Das NotifyAll füht nicht dazu, dass das Bewegen weitergeht.
 
Jetzt ein Beispiel zu posten, wo man sieht, dass es DOCH geht, würde wohl nichts bringen ... oder vielleicht doch? ???:L Aber poste mal deinen aktuellen Stand, am besten als KSKB
 
Java:
    Object o = new Object();

    public synchronized void setPaused(boolean p)
    {
        if (paused != p)  
        {
            paused = p;
            synchronized (o){
                o.notify();            	
            }

        }
    }


Java:
		while (wei){
			synchronized (o){
				while (paused){
					try {
						o.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
bewegen();
 
Ok, wenn du den Code willst:

Erste Class:
Java:
public class ablauf {
static Thread bew;
static drawShape kugel;
static move mo;
	/**
	 * @param args
	 */
	public static JFrame openFrame (){
		JFrame f = new JFrame();		
		f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		f.setSize( 700, 500 );
		f.setResizable(false);
		f.setVisible( true );
		return f;	
	}
	public void end (){
		System.exit(0);
	}
	public static JPanel drawit () {
		drawShape kugel = new drawShape();
		return kugel;
	}
	public static void main(String[] args) {
		ActionListener stopper = new ActionListener(){
			public void actionPerformed(ActionEvent e) {

				mo = new move(kugel);
				mo.setPaused(true);

			}


		};
		ActionListener weitermachen = new ActionListener(){
			public void actionPerformed(ActionEvent e){
					mo = new move(kugel);
					mo.setPaused(false);
			}
		};
		// TODO Auto-generated method stub
		JFrame f = openFrame();
		JPanel kugel = drawit();
		f.setLayout(null);
		kugel.setBounds(0, 0, 50, 50);
		f.add(kugel);
		JButton stop = new JButton("Anhalten");
		JButton weiter = new JButton("Weiter");
		weiter.setBounds(200, 100, 100, 50);
		stop.setBounds(100,100,100,50);
		f.add(stop);
		f.add(weiter);
		weiter.addActionListener(weitermachen);
		stop.addActionListener(stopper);
		bew = new Thread(new move(kugel));
		bew.run();
	}

}

Zweite Class:
Java:
public class move implements Runnable{
	JPanel kugel;
	int x = 0;
	int y = 0;
	int vx = 1;
	int vy = 1;
	int mx = 700-60;
	int my = 500-60;
	int frequenz = 10;
	boolean enlx = true;
	boolean enly = true;
	static boolean wei = true;
    private static boolean paused = false;

    Object o = new Object();

    public synchronized void setPaused(boolean p)
    {
        if (paused != p)  
        {
            paused = p;
            synchronized (o){
                o.notify();
            }
        }
    }

	
	
	public move(JPanel kugel2) {
		// TODO Auto-generated constructor stub
		kugel = kugel2;
	}
	public synchronized void run (){
		while (wei){
			synchronized (o){
				while (paused){
					try {
						o.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
		if (enlx & x<=mx){
			x = x+vx;
		}
		if (enlx & x>mx){
			x = x-vx;
			enlx = false;
		}
		if (!enlx & x>0){
			x = x-vx;
		}
		if (!enlx & x<=0){
			x = x+vx;
			enlx = true;
		}
		
		
		if (enly & y<=my){
			y = y+vy;
		}
		if (enly & y>my){
			y = y-vy;
			enly = false;
		}
		if (!enly & y>0){
			y = y-vy;
		}
		if (!enly & y<=0){
			y = y+vy;
			enly = true;
		}
		
		kugel.setBounds(x, y, 50, 50);
		try {
			Thread.sleep(frequenz);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}}
	}
	public static void start(){
	}
	public static void stop(){


	}


}

Dritte Class:
Java:
public class drawShape extends JPanel{
	@Override
	protected void paintComponent ( Graphics g ) {
		g.drawOval(0, 0, 50, 50);
	}

}

Bitte nicht über unschönes Coding beschweren, ich bin Anfänger!;(
 
Es ist NICHT dasselbe "o" - es ist ja nichtmal dasselbe "mo" (die Variablennamen solltest du vielleicht nochmal überdenken 😉 ). In der actionPerformed erstellst du ja ein neues Objekt:
mo = new move(kugel);

Schreib diese Zeile EINmal im Konstruktor, und lass sie an den anderen Stellen weg. Wenn's dann noch nicht geht, compilier' ich's mal 😀
 
Ich hab dir das mal notdürftig gefixt so dass es läuft.

Java:
import javax.swing.JPanel;

public class move implements Runnable{
    JPanel kugel;
    int x = 0;
    int y = 0;
    int vx = 1;
    int vy = 1;
    int mx = 700-60;
    int my = 500-60;
    int frequenz = 10;
    boolean enlx = true;
    boolean enly = true;
    private volatile boolean paused = false;
 
    Object o = new Object();
 
    public void setPaused(boolean p)
    {
        if (paused != p)  
        {
            paused = p;
            synchronized (o){
                o.notify();
            }
        }
    }
 
    
    
    public move(JPanel kugel2) {
        // TODO Auto-generated constructor stub
        kugel = kugel2;
    }
    public void run (){
        while (true){
            
        	synchronized (o){
                while (paused){
                    try {
                        o.wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
        if (enlx & x<=mx){
            x = x+vx;
        }
        if (enlx & x>mx){
            x = x-vx;
            enlx = false;
        }
        if (!enlx & x>0){
            x = x-vx;
        }
        if (!enlx & x<=0){
            x = x+vx;
            enlx = true;
        }
        
        
        if (enly & y<=my){
            y = y+vy;
        }
        if (enly & y>my){
            y = y-vy;
            enly = false;
        }
        if (!enly & y>0){
            y = y-vy;
        }
        if (!enly & y<=0){
            y = y+vy;
            enly = true;
        }
        
        kugel.setBounds(x, y, 50, 50);
        
        try {
            Thread.sleep(frequenz);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }}
    }
  }

Java:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ablauf {
static Thread bew;
static drawShape kugel;
static move mo = null;
    /**
     * @param args
     */
    public static JFrame openFrame (){
        JFrame f = new JFrame();        
        f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        f.setSize( 700, 500 );
        f.setResizable(false);
        f.setVisible( true );
        return f;   
    }
    public void end (){
        System.exit(0);
    }
    public static JPanel drawit () {
        drawShape kugel = new drawShape();
        return kugel;
    }
    public static void main(String[] args) {
        ActionListener stopper = new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                mo.setPaused(true);
            }
       };
        ActionListener weitermachen = new ActionListener(){
            public void actionPerformed(ActionEvent e){
                    mo.setPaused(false);
            }
        };
        // TODO Auto-generated method stub
        JFrame f = openFrame();
        JPanel kugel = drawit();
        f.setLayout(null);
        kugel.setBounds(0, 0, 50, 50);
        f.add(kugel);
        JButton stop = new JButton("Anhalten");
        JButton weiter = new JButton("Weiter");
        weiter.setBounds(200, 100, 100, 50);
        stop.setBounds(100,100,100,50);
        f.add(stop);
        f.add(weiter);
        weiter.addActionListener(weitermachen);
        stop.addActionListener(stopper);
        mo = new move(kugel);
        bew = new Thread(mo);
        bew.start();
    }
 
}
 
Halt, da unten steht ja nochmal
bew = new Thread(new move(kugel));
... wart mal, ich räum mal auf...


EDIT: Ah, da war ThreadPool schneller. Nomen es omen 😀
 
Danke, danke, danke! Das ist echt voll nett von euch. Jetzt geht es.

Aber auch ich habe nicht geschlafen und mittlerweile eine Lösung ohne wait und notify ausgegraben. Ist aber nicht so schön!

Jetzt habe ich allerdings gleich das nächste Problem. Das bewegte Teil ruckelt ziehmlich. Bei Delphi gibt's dagegen ja irgendeine Methode (doppelt buffern). Gibt es soetwas bei Java auch und wie benutzt man das?
 
Bei Swing ist DoubleBuffering eigentlich schon eingebaut, da braucht man nichts mehr per Hand zu machen. (Bei mir flackert's auch nicht, ganz nebenbei). Kannst mal schauen, ob es was hilft, die vx/vy auf z.B. 3 zu setzen, und dafür 'frequenz=30'... ist aber nur geraten...
 

Zurück
Oben