Thread macht keine Pause

Status
Nicht offen für weitere Antworten.

flashdog

Bekanntes Mitglied
Hallo,
ich habe eine kleine Simulation die mit einem Button gestartet wird und dies funktioniert, aber ich bekomme es einfach nicht hin mit dem gleichen Button die Simulation anzuhalten um sie bei erneunten druecken wieder fortzufuehren.

Code:
import java.awt.*;
import java.awt.Button;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class BallRoom extends JApplet implements ActionListener, Runnable {
	private final int WIDTH = 350;
	private final int HEIGHT = 300;
	private PaintSurface canvas;
	private JButton controlSimulation;
	boolean doSuspend = false;
	Thread th;

	public void init() {      
		this.setSize(WIDTH, HEIGHT);
		canvas = new PaintSurface();
		this.add(canvas, BorderLayout.CENTER);
		controlSimulation = new JButton("Start");
		controlSimulation.addActionListener(this);
		this.add(controlSimulation, BorderLayout.SOUTH);
	}

	public void run() {
		while (true){
			repaint();
			try {
				Thread.sleep(100);
			}
			catch (InterruptedException ex){
				if (doSuspend) {
					doSuspend = false;
					controlSimulation.setText("Start");//setText("Start");
					System.out.println("Displayer suspended");
					th.suspend();
				}
			}
		}
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void actionPerformed(ActionEvent e){
		if (e.getSource() == controlSimulation){
			if (th == null) {
				th = new Thread(this);
				th.start();
				controlSimulation.setText("Stop");
			}
			//else th.resume();
			//controlSimulation.setLabel("Stop");
			else if (th != null) {	
				doSuspend = true;
		}

		}
	}
}
Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;

class PaintSurface extends JComponent {
  int ball1_x_pos = 0; // the starting X position
  int ball1_y_pos = 150; // the starting Y position
  int ball2_x_pos = 60; // the starting X position
  int ball2_y_pos = 150; // the starting Y position
 
  int d = 20; // the diameter of the ball

  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    ball1_x_pos++; // move ball1 right one pixel
    ball2_x_pos--; // move ball1 left one pixel
    Shape ball1 = new Ellipse2D.Float(ball1_x_pos, ball1_y_pos, d, d);
    Shape ball2 = new Ellipse2D.Float(ball2_x_pos, ball2_y_pos, d, d);
    g2.setColor(Color.RED);
    g2.fill(ball1);
    g2.fill(ball2);
  }
}

Was mache ich falch?

Viele Gruesse
 
S

SlaterB

Gast
die Abfrage
> if (doSuspend) {
steht nur im catch-Block,
der aber nie ausgeführt wird, da du den Thread nicht unterbrichst,
verwende evtl. thread.interrupt(), da hast du aber vielleicht Pech, wenn das genau in der Zeit passiert, in der der Thread nicht schläft

viel sauberer und einfacher wäre aber, das if nicht im catch sondern sondern ganz normal am Anfang oder Ende der Schleife zu schreiben
 

flashdog

Bekanntes Mitglied
Habe if aus catch rausgeholt und jetzt klappt die Unterbrechung, aber leider wenn ich erneut den Button klicke statet die Simultion nicht.

Wo koennte noch der Fehler sein?

Code:
	public void run() {
		while (true){
			if (doSuspend) {
				doSuspend = false;
				controlSimulation.setText("Start");//setText("Start");
				System.out.println("Displayer suspended");
				th.suspend();
			}
			repaint();
			try {
				Thread.sleep(100);
			}
			catch (InterruptedException ex){
			}
		}
	}
 

L-ectron-X

Gesperrter Benutzer
suspend() ist deprecated.
Die run()-Methode kann nur einmal gestartet werden. Du brauchst danach ein neues Thread-Objekt.
 
S

SlaterB

Gast
oder den Thread in ein Dauersleep legen und später aufwecken, z.B. mit interrupt(),
schöner gehts wohl mit wait()/ notify(),

einfach mal Lehrbücher lesen.., suspend habe ich da noch nicht gesehen
 

Marco13

Top Contributor
Für start/stop würde man vielleicht einen neuen Thread erstellen. Für pause/continue (was du ja anscheinen willst) würde man das GANZ GROB so machen
Code:
import java.awt.*;
import java.awt.Button;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
import javax.swing.*;

public class BallRoom extends JApplet implements ActionListener, Runnable {
   private final int WIDTH = 350;
   private final int HEIGHT = 300;
   private PaintSurface canvas;
   private JButton controlSimulation;
   boolean paused = false;
   Thread th;

   public void init() {
      this.setSize(WIDTH, HEIGHT);
      canvas = new PaintSurface();
      this.add(canvas, BorderLayout.CENTER);
      controlSimulation = new JButton("Start");
      controlSimulation.addActionListener(this);
      this.add(controlSimulation, BorderLayout.SOUTH);
   }

   public void run() {
      while (true){
         repaint();
         try {
            Thread.sleep(500);
         }
         catch (InterruptedException ex)
         {
         }
         while (paused)
         {
             System.out.println("Displayer paused");
             synchronized (this)
             {
                 try {
                 wait();
                 }
                 catch (InterruptedException ex)
                 {
                 }
             }
         }
         System.out.println("Displayer running");
      }
   }

   public void update(Graphics g) {
      paint(g);
   }

   public void actionPerformed(ActionEvent e){
      if (e.getSource() == controlSimulation)
      {
         if (th == null)
         {
            th = new Thread(this);
            th.start();
            controlSimulation.setText("Pause");
         }
         else // if (th != null)
         {
             synchronized (this)
             {
                 if (paused)
                 {
                     paused = false;
                     controlSimulation.setText("Pause");
                     notify();
                 }
                 else
                 {
                     paused = true;
                     controlSimulation.setText("Continue");
                 }
             }
         }

      }

      }
}

class PaintSurface extends JComponent {
  int ball1_x_pos = 0; // the starting X position
  int ball1_y_pos = 150; // the starting Y position
  int ball2_x_pos = 60; // the starting X position
  int ball2_y_pos = 150; // the starting Y position

  int d = 20; // the diameter of the ball

  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    ball1_x_pos++; // move ball1 right one pixel
    ball2_x_pos--; // move ball1 left one pixel
    Shape ball1 = new Ellipse2D.Float(ball1_x_pos, ball1_y_pos, d, d);
    Shape ball2 = new Ellipse2D.Float(ball2_x_pos, ball2_y_pos, d, d);
    g2.setColor(Color.RED);
    g2.fill(ball1);
    g2.fill(ball2);
  }
}
 

flashdog

Bekanntes Mitglied
@Marco13: Danke, es ist genau das was ich haben wollte, aber ich dachte es waehre auch praktisch die Simulation mit einem zusaetlichen Stop Button zu beenden.

Die Beendigung funktioniert, aber ich kann die Simulation nicht mit dem Start Button wieder von Anfang an starten.

Code:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Graphics;
import javax.swing.*;

public class BallRoom extends JApplet implements ActionListener, Runnable {
	private final int WIDTH = 350;
	private final int HEIGHT = 300;
	private PaintSurface canvas;
	private JButton controlSimulation, stopSimulation;
	private JPanel controlPanel;
	
	boolean paused = false;
	boolean stop = false;
	Thread th;

	public void init() {
		this.setSize(WIDTH, HEIGHT);
		canvas = new PaintSurface();
		this.add(canvas, BorderLayout.CENTER);
		controlSimulation = new JButton("Start");
		stopSimulation = new JButton("Stop");
		controlSimulation.addActionListener(this);
		stopSimulation.addActionListener(this);
		controlPanel = new JPanel();
		this.add(controlPanel, BorderLayout.SOUTH);
		controlPanel.add(controlSimulation);
		controlPanel.add(stopSimulation);
	}

	public void run() {
		while (!stop){
			repaint();
			try {
				Thread.sleep(500);
			}
			catch (InterruptedException ex)
			{
			}
			while (paused)
			{
				System.out.println("Displayer paused");
				synchronized (this)
				{
					try {
						wait();
					}
					catch (InterruptedException ex)
					{
						System.out.print("InterruptedException");
					}
				}
			}
			System.out.println("Displayer running");
		}
	}

	public void update(Graphics g) {
		paint(g);
	}

	public void actionPerformed(ActionEvent e){
		if (e.getSource() == controlSimulation)
		{
			if (th == null)
			{
				stop = false;
				th = new Thread(this);
				th.start();
				controlSimulation.setText("Pause");
			}
			else // if (th != null)
			{
				synchronized (this)
				{
					if (paused)
					{
						paused = false;
						controlSimulation.setText("Pause");
						notify();
					}
					else
					{
						paused = true;
						controlSimulation.setText("Continue");
					}
				}
			}
		}
		if (e.getSource() == stopSimulation){
			if (th != null){
				stop = true;
				controlSimulation.setText("Start");
				System.out.print("Stop");
			}
		}
	}
}

Was mache ich falsch, dass die Simulation nicht von Anfang an startet?
 
S

SlaterB

Gast
so ein großer Kopf über den Hals, da darf man auch mal eigenständig denken,

schaue dir doch genau die Bedingung für das Starten an,
was steht da?:

> if (th == null)
> {

und was ist wohl th nach dem Drücken des Stop-Buttons?
nicht null, denn du setzt die Variable nirgendwo auf null,


sowas kann dir auch das Programm auf denkbar einfachste Weise sagen,
wenn man sich nur ein bisschen bemüht:

Code:
   public void actionPerformed(ActionEvent e){
      System.out.println("bin in ActionPerformed");
      if (e.getSource() == controlSimulation)
      {
         System.out.println("controlSimulation gedrückt");

         if (th == null)
         {
            System.out.println("th ist null, starte neuen Thread");

            stop = false;
            th = new Thread(this);
            th.start();
            controlSimulation.setText("Pause");
         }
         else // if (th != null)
         {
            System.out.println("th ist nicht null, bearbeite aktuellen Thread");
            // usw mit den Ausgaben

            ...
         }
      }
      if (e.getSource() == stopSimulation){

         ...
      }
   }
 

flashdog

Bekanntes Mitglied
verflickst anscheind ist mein Kopf nicht gross genug. Ich habe mich lange Zeit mit dem Problem beschaeftigt und bin einfach nicht auf die Loesung gekommen.

Leider funktioniert der Stop Knopf wie der Pause Knopf. Ich wollte erreichen, dass nachdem der Stop Knopf gedrueckt wurden ist und man anschliessend den Start Knopf drueckt beginnt die Simulation von Anfang an und nicht wo sie aufgehoert hat.

Vielleicht ist es moeglich die Bealle auf die Anfangsposition zu setzen wenn der Stop Knopf gedruck worden ist und dann mit Start beginnt die Simulation von Anfang an.

Wenn ich dich richtig verstanden habe sollte ich nur dies aendern:
Code:
		if (e.getSource() == stopSimulation){
			if (th != null){
				stop = true;
				controlSimulation.setText("Start");
				System.out.print("Stop");
				th = null;
			}
		}


Macro13 hat geschrieben: "Für start/stop würde man vielleicht einen neuen Thread erstellen.", aber passiert dies nicht hiermit:
Code:
			if (th == null)
			{
				stop = false;
				th = new Thread(this);
				th.start();
				controlSimulation.setText("Pause");
			}

Leider weiss ich nich wie die Simulation von Anfang starten kann.
 
S

SlaterB

Gast
der Thread macht ja nicht viel, er ruft nur repaint auf, setzt keine Variablen,
das passiert bei dir anscheinend in repaint und der paint-Methode ist es sicher herzlich egal, wer denn da repaint() aufgerufen hat,

du brauchst gewiss so eine Art reset()-Methode, die irgendwelche Werte auf den Standard zurücksetzt,
die kannst du bei einen der Buttons aufrufen oder auch zu Beginn der run-Methode vor der while-true-Schleife,

dann würde schon einen Unterschied machen ob ein neuer Thread startet oder ein vorhandener fortgesetzt wird,
denn nur ein neuer Thread kommt an den Code in der run-Methode vor der while-true-Schleife ran
 

Marco13

Top Contributor
Du wirst die Bälle schon wieder auf dei Startposition setzen müssen (von Hand).

Eine (auch sauberere, modularere und in vieler Hinsicht ggf. vorteilhafte) Alternative wäre, den Simulationszusatnd in einer eigenen Klasse zu speichern. Dass der Simulationszustand (die Ballpositionen) im Moment in der PaintSurface gespeichert werden, ist schon ziemlicher Murks :autsch: Und die Ballposition bei jedem neuzeichnen zu verändern, ist noch viel murksiger :autsch: :autsch: (Stell mal au Pause, und schieb' mal ein Fenster vor dein Applet, nimm es wieder weg, schiebe es wieder davor, nimm es wieder weg....... und beobachte, wie sich die Bälle bewegen, owohl eigentlich garnicht simuliert wird..... :roll: )

Ein bißchen Pseudocode nach dem Model-View-Controller-Pattern (Websuche!).

Code:
interface SimulationListener
{
    void simulationStepPerformed();
}

SimulationModel
{
    // Array mit allen Ballpositionen
    private Point ballPositions[] = ...

    // Liste der objekte, die bei jedem Simulationsschritt benachrichtigt werden
    private List<SimulationListener> simulationListeners = ...
    // (dazu noch add/remove-Methoden für SimulationListener)
 

    // Liefert eine Ballposition
    public Point getBallPosition(int ballIndex) { ... }

    public int getNumBalls() { ... }

    public void doSimulationStep()
    {
        // bewege bälle....

       // Benachrichtige alle Listener, dass ein Schritt gemacht wurde
       // (ruft die Methode auch in der PaintSurface auf, die daraufhin
       // die Shapes für die Bälle aktualisiert und neu zeichnet)
       for (SimulationListener simulationListener : simulationListeners)
       { 
           simulationListener.simulationStepPerformed();
       }
    }
}

// zeichnet das aktuelle SimulationModel
class PaintSurface extends JComponent implements SimulationListener
{
    private SimulationModel simulationModel;
    private Shape ballShapes[] = .... (Einmal erstellen, nicht bei jedem neuzeichnen!)

    public PaintSurface(SimulationModel simulationModel)
    {
        this.simulationModel = simulationModel;
        // erstelle ballShapes....
    }


    public void paintComponent(Graphics g) // paintComponent überschreiben, NICHT paint!!!
    {
        for (i=0...n)
        {    
            zeichne(ballShape[i]);
        }
    }

    // Wird bei jedem Simulationsschritt aufgerufen
    public void simulationStepPerformed()
    {
        for (i=0...n)
        {    
            setze Position von ballShape[i] auf simulationModel.getBallPosition(i);
        }
        repaint();
    }

}


class Main
{
    private SimulationModel simulationModel;

    void reset()
    {
        simulationModel = new SimulationModel();
        simulationMode.addSimulationListener(paintSurface);
    }
}

Wenn die Simulationsdaten in einer eigenen Klasse liegen, kann diese Klasse eine "Reset"-Methode anbieten, die sie auf den Anfangszustand zurücksetzt. Oder man kann für ein "reset" einfach ein neues SimulationModel erstellen....
 

flashdog

Bekanntes Mitglied
Danke euch beiden fuer die Tipps. Das ursprungliche Beispiel stammt aus "Java All-in-One Desk Reference for Dummies".

Gibt es ein gutes Buch fuer die Design Paterns?
 

flashdog

Bekanntes Mitglied
@Marco13: Leider habe ich dein Pseudocode nicht verstanden und habe es versucht wie folgt modular aufzubauen. Ich habe geschafft das sich ein JDialog Fenster mit Paintsurface (JComponent) und Startbutton oeffnet, aber leider bekomme ich die Simulation bei betteatigen des Strat-Button nicht zum laufen.

Diese ControlVariables Klasse verwende ich um die Variablen als Referenz an JDialog zu uebergeben.
Code:
public class ControlVariables {
  public Thread th;
  public boolean paused = false;
  public boolean stop = false;
  public int speed = 20;
}

Code:
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JOptionPane;

public class Settings extends JApplet implements ActionListener, Runnable{
	private final int WIDTH = 350;
	private final int HEIGHT = 300;
	private Frame rootFrame;
	private JButton InitButton;
	private ControlVariables controlVariables;
	@Override
	public void init() {
		this.setSize(WIDTH, HEIGHT);
		rootFrame = JOptionPane.getFrameForComponent(this); //For JDialog
		controlVariables = new ControlVariables();
		System.out.print(controlVariables.speed);
		InitButton = new JButton("Init");
		InitButton.addActionListener(this);
		this.add(InitButton, BorderLayout.SOUTH);      
	}

	public void run() {
		while (!controlVariables.stop){
			repaint();
			try {
				System.out.println(controlVariables.speed);
				Thread.sleep(controlVariables.speed);
			}
			catch (InterruptedException ex)
			{
			}
			while (controlVariables.paused)
			{
				System.out.println("Displayer paused");
				synchronized (this)
				{
					try {
						wait();
					}
					catch (InterruptedException ex)
					{
						System.out.print("InterruptedException");
					}
				}
			}
			System.out.println("Displayer running");
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == InitButton){
			Simulation dialog = new Simulation(rootFrame, 
					"Simulations Fenster", true, controlVariables);
			dialog.setSize(500, 300);
			//dialog.pack();
			dialog.setResizable(false);
			dialog.setVisible(true);
		}

	}
}

Code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;

public class Simulation extends JDialog implements ActionListener {
	private PaintSurface canvas;
	private JButton controlSimulation;
	private JPanel controlPanel;
	ControlVariables controlVariables;

	public Simulation(java.awt.Frame parent, String title, 
			boolean modal, ControlVariables controlVariables) {
		super(parent, title, modal);
		this.controlVariables = controlVariables;
		System.out.print(controlVariables.speed);
		canvas = new PaintSurface();
		getContentPane().add(canvas, BorderLayout.CENTER);
		controlSimulation = new JButton("Start");
		controlSimulation.addActionListener(this);
		controlPanel = new JPanel();
		controlPanel.add(controlSimulation);
		getContentPane().add(controlPanel, BorderLayout.SOUTH);

	}
	public void actionPerformed(ActionEvent e){
		if (e.getSource() == controlSimulation)
		{
			if (controlVariables.th == null)
			{
				System.out.println(controlVariables.speed);
				controlVariables.stop = false;
				controlVariables.th = new Thread((Runnable) this);
				controlVariables.th.start();
				controlSimulation.setText("Pause");
			}
			else // if (th != null)
			{
				synchronized (this)
				{
					if (controlVariables.paused)
					{
						System.out.println(controlVariables.speed);
						controlVariables.paused = false;
						controlSimulation.setText("Pause");
						notify();
					}
					else
					{
						controlVariables.paused = true;
						controlSimulation.setText("Continue");
					}
				}
			}
		}
	}
}

Wenn ich im JDialog Fenster auf den Strat Button klicke um die Simmulation zu starten bekommen ich diese Fehlermeldung.
Code:
Exception occurred during event dispatching:
java.lang.ClassCastException: Simulation cannot be cast to java.lang.Runnable
	at Simulation.actionPerformed(Simulation.java:35)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.Dialog$1.run(Unknown Source)
	at java.awt.Dialog$3.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.awt.Dialog.show(Unknown Source)
	at java.awt.Component.show(Unknown Source)
	at java.awt.Component.setVisible(Unknown Source)
	at java.awt.Window.setVisible(Unknown Source)
	at java.awt.Dialog.setVisible(Unknown Source)
	at Settings.actionPerformed(Settings.java:62)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Wo liegt mein Fehler?
 

flashdog

Bekanntes Mitglied
Habe den Fehler gefunden, aber leider wenn ich JDialog Fenster schliesse und wieder oeffne und dann auf den Start-Button klicke funktioniert die Simulation wieder nicht.
Code:
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JOptionPane;

public class Settings extends JApplet implements ActionListener {
	private final int WIDTH = 350;
	private final int HEIGHT = 300;
	private Frame rootFrame;
	private JButton InitButton;
	private ControlVariables controlVariables;
	@Override
	public void init() {
		this.setSize(WIDTH, HEIGHT);
		rootFrame = JOptionPane.getFrameForComponent(this); //For JDialog
		controlVariables = new ControlVariables();
		System.out.print(controlVariables.speed);
		InitButton = new JButton("Init");
		InitButton.addActionListener(this);
		this.add(InitButton, BorderLayout.SOUTH);      
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == InitButton){
			Simulation dialog = new Simulation(rootFrame, 
					"Simulations Fenster", true, controlVariables);
			dialog.setSize(500, 300);
			//dialog.pack();
			dialog.setResizable(false);
			dialog.setVisible(true);
		}

	}
}

Code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;

public class Simulation extends JDialog implements ActionListener, Runnable {
	private PaintSurface canvas;
	private JButton controlSimulation;
	private JPanel controlPanel;
	ControlVariables controlVariables;

	public Simulation(java.awt.Frame parent, String title, 
			boolean modal, ControlVariables controlVariables) {
		super(parent, title, modal);
		this.controlVariables = controlVariables;
		System.out.print(controlVariables.speed);
		canvas = new PaintSurface();
		getContentPane().add(canvas, BorderLayout.CENTER);
		controlSimulation = new JButton("Start");
		controlSimulation.addActionListener(this);
		controlPanel = new JPanel();
		controlPanel.add(controlSimulation);
		getContentPane().add(controlPanel, BorderLayout.SOUTH);

	}
	public void actionPerformed(ActionEvent e){
		if (e.getSource() == controlSimulation)
		{
			if (controlVariables.th == null)
			{
				System.out.println(controlVariables.speed);
				controlVariables.stop = false;
				controlVariables.th = new Thread(this);
				controlVariables.th.start();
				controlSimulation.setText("Pause");
			}
			else // if (th != null)
			{
				synchronized (this)
				{
					if (controlVariables.paused)
					{
						System.out.println(controlVariables.speed);
						controlVariables.paused = false;
						controlSimulation.setText("Pause");
						notify();
					}
					else
					{
						controlVariables.paused = true;
						controlSimulation.setText("Continue");
					}
				}
			}
		}
	}
	@Override
	public void run() {
		while (!controlVariables.stop){
			repaint();
			try {
				System.out.println(controlVariables.speed);
				Thread.sleep(controlVariables.speed);
			}
			catch (InterruptedException ex)
			{
			}
			while (controlVariables.paused)
			{
				System.out.println("Displayer paused");
				synchronized (this)
				{
					try {
						wait();
					}
					catch (InterruptedException ex)
					{
						System.out.print("InterruptedException");
					}
				}
			}
			System.out.println("Displayer running");
		}
		
	}
}

Wahrscheinlich liegt es daran dass die run Methode nur einmal gestartet werden darf, kann man dies irgendwie umgehen, so dass ich beliebig oft das JDialog Fenster schliessen kann?
 
S

SlaterB

Gast
ein vollständiger ProgrammCode würde helfen,
ControlVariables, PaintSurface usw sind unbekannte Klassen,

wieso muss es eigentlich immer noch JApplet sein?
ich zumindest habe keine Lust, das jedesmal auf JFrame umzubiegen, damit es normale Menschen auch ausführen können.
falls ich helfen soll, musst du das auch noch machen ;)
 

flashdog

Bekanntes Mitglied
Sorry für die fehlende Programm Teile. Ich würde es dir gerne JFrame umschreiben nur unter JFrame gibt es eine keine run Methode und ich weiss nicht wie man es ohne macht. Wahrschein ist es besser ohne die run Methode, da diese nur einmal gestartet werden kann. Könntest du mir trotzdem bitte Helfen?

Code:
public class ControlVariables {
  public int speed = 20;
  public Thread th;
  public boolean paused = false;
public boolean stop = false;
  public String teststring = null;
}

Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;

class PaintSurface extends JComponent {
  int ball1_x_pos = 0; // the starting X position
  int ball1_y_pos = 150; // the starting Y position
  int ball2_x_pos = 60; // the starting X position
  int ball2_y_pos = 150; // the starting Y position
 
  int d = 20; // the diameter of the ball

  @Override
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    ball1_x_pos++; // move ball1 right one pixel
    ball2_x_pos--; // move ball1 left one pixel
    Shape ball1 = new Ellipse2D.Float(ball1_x_pos, ball1_y_pos, d, d);
    Shape ball2 = new Ellipse2D.Float(ball2_x_pos, ball2_y_pos, d, d);
    g2.setColor(Color.RED);
    g2.fill(ball1);
    g2.fill(ball2);
  }
}
 
S

SlaterB

Gast
sorry musst du nicht sagen, ich schreibe nur wie es ist, korrigieren und gut ;)

--------

also dann merke dir mal genau wie das mit dem JFrame hier aussieht, sind nur minimale Änderungen,
mit run-Methoden hat das nix zu tun:
Code:
public class Settings
    extends JFrame
    implements ActionListener
{
    private final int WIDTH = 350;
    private final int HEIGHT = 300;
    private JButton InitButton;
    private ControlVariables controlVariables;

    public Settings()
    {


        this.setSize(WIDTH, HEIGHT);
        controlVariables = new ControlVariables();
        System.out.print(controlVariables.speed);
        InitButton = new JButton("Init");
        InitButton.addActionListener(this);
        this.add(InitButton, BorderLayout.SOUTH);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public void actionPerformed(ActionEvent e)
    {
        if (e.getSource() == InitButton)
        {
            Simulation dialog = new Simulation(this, "Simulations Fenster", true, controlVariables);
            dialog.setSize(500, 300);
            // dialog.pack();
            dialog.setResizable(false);
            dialog.setVisible(true);
        }

    }

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

-------

das Problem ist, dass
controlVariables.th nur im ersten JDialog gesetzt wird,
danach wirds nie auf null gesetzt, der zweie JDialog macht nix,
außer
a) auf sich selber dann notify aufzurufen, worauf der andere immer noch laufende Thread nicht reagiert, der wait()ed ja auf das erste Dialog-Objekt
b) pause = true/false wird gesetzt, darauf würde der erste Thread auch reagieren wenn er nicht per wait() ewig warten muss,


also:
unbedingt den ersten Thread beenden, sonst läuft der ewig nebenher weiter,
+ th auf null setzen,

du müsstest dafür auf das Schließen des JDialogs reagieren,
WindowListener hilft vielleicht
 

flashdog

Bekanntes Mitglied
Der WindowListener hielft, aber nur wenn ich zuerst auf den Pause Button klicke und dann auf schliesse. Wenn ich aber sofort auf schließe klicke läuft der Thread weiter.
Code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import sun.awt.WindowClosingListener;

public class SimulationWindowNew extends JDialog implements ActionListener, ChangeListener, Runnable, WindowListener {
	private PaintSurface canvas;
	private JButton controlSimulation, stopSimulation;
	private JPanel controlPanel;
	private JLabel speedControlLabel;
	private JSlider speedControl;
        private ControlVariables controlVariables;

  public SimulationWindowNew(java.awt.Frame parent, String title, 
          boolean modal) {
    super(parent, title, modal);
    controlVariables = new ControlVariables();
    this.addWindowListener(this);
		canvas = new PaintSurface();
		getContentPane().add(canvas, BorderLayout.CENTER);
                controlSimulation = new JButton("Start");
		stopSimulation = new JButton("Stop");
		controlSimulation.addActionListener(this);
		stopSimulation.addActionListener(this);
		
		speedControlLabel = new JLabel("Speed:");
		
		speedControl = new JSlider(1,20,20);
		speedControl.addChangeListener(this);
		speedControl.setInverted(true); 
		controlPanel = new JPanel();
		controlPanel.add(controlSimulation);
		controlPanel.add(stopSimulation);
		controlPanel.add(speedControlLabel);
		controlPanel.add(speedControl);
              getContentPane().add(controlPanel, BorderLayout.SOUTH);
    
    }
  public void actionPerformed(ActionEvent e){
		if (e.getSource() == controlSimulation)
		{
			if (controlVariables.th == null)
			{
        System.out.println(controlVariables.teststring);
				controlVariables.stop = false;
				controlVariables.th = new Thread(this);
				controlVariables.th.start();
				controlSimulation.setText("Pause");
			}
			else // if (th != null)
			{
				synchronized (this)
				{
					if (controlVariables.paused)
					{
						controlVariables.paused = false;
						controlSimulation.setText("Pause");
						notify();
					}
					else
					{
						controlVariables.paused = true;
						controlSimulation.setText("Continue");
					}
				}
			}
		}
		if (e.getSource() == stopSimulation){
			if (controlVariables.th != null){
				controlVariables.stop = true;
				controlSimulation.setText("Start");
				System.out.print("Stop");
				controlVariables.th = null;
			}
		}
	}
  	@Override
	public void run() {
		while (!controlVariables.stop){
			repaint();
			try {
				System.out.println(controlVariables.speed);
				Thread.sleep(controlVariables.speed);
			}
			catch (InterruptedException ex)
			{
			}
			while (controlVariables.paused)
			{
				System.out.println("Displayer paused");
				synchronized (this)
				{
					try {
						wait();
					}
					catch (InterruptedException ex)
					{
						System.out.print("InterruptedException");
					}
				}
			}
			System.out.println("Displayer running");
		}
}
		@Override
		public void windowClosed(WindowEvent arg0) {
			// TODO Auto-generated method stub
		}
		@Override
		public void windowActivated(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void windowClosing(WindowEvent e) {
			System.out.print("windowClosing");
			controlVariables.th = null;
			
		}
		@Override
		public void windowDeactivated(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void windowDeiconified(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void windowIconified(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void windowOpened(WindowEvent e) {
			// TODO Auto-generated method stub
			
		}
}

Woran kann dies liegen?
 
S

SlaterB

Gast
> Woran kann dies liegen?

du setzt eine Variable auf null, na und?
warum in alles in der Welt soll der Thread anhalten, nur weil du irgendwo irgendeine Variable setzt?

das interessiert den Thread nicht die Bohne,
selbst wenn der Pausen-Button geklickt ist würde der Thread so nicht beendet werden, sondern wartet bis in alle Ewigkeit

ein Thread ist beendet, wenn seine run-Methode ausgelaufen ist, schon mal davon gehört?
du hast sogar eine stop-Variable und eine gute Schleife
> while (!controlVariables.stop){
in dem Thread, willst du diese nicht nutzen?

hier noch eine Hilfe

Code:
public void run() { 
      while (!controlVariables.stop){ 
         .....
      } 
       System.out.println("Displayer macht Feierabend"); 
}
solange diese Meldung nicht kommt, bist du mit dieser Aufgabe noch nicht fertig

----

> ich habe nur vergessen "controlVariables.paused = true;" zu setzen.

der Thread schläft dann, ist aber weiter vorhanden,
naja, damit kann man in einem einfachen Programm wohl auch leben
 

flashdog

Bekanntes Mitglied
Ich haette noch eine Frage, warum musst 6 weiter Methoden überschreiben. Gibt es noch eine andere Möglichkeit?
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
P thread nimmt veränderte boolean nicht AWT, Swing, JavaFX & SWT 7
N JFrame loescht alles, sobald der Thread zuende ist AWT, Swing, JavaFX & SWT 22
M Server/Client thread von GUI Trennen AWT, Swing, JavaFX & SWT 2
K JavaFx, Sound Aufnahme und Thread AWT, Swing, JavaFX & SWT 0
T Exception in thread "main" java.lang.NoClassDefFoundError AWT, Swing, JavaFX & SWT 4
G Exception javafx Thread -> caused by removing children while in EventHandler AWT, Swing, JavaFX & SWT 28
H Event Handling Thread - Abruf der get-Methode AWT, Swing, JavaFX & SWT 5
J "Exception in thread "AWT-EventQueue-0"" Fehler AWT, Swing, JavaFX & SWT 3
G Thread starten Swing AWT, Swing, JavaFX & SWT 5
C Thread verwalten AWT, Swing, JavaFX & SWT 2
A Swing Exception in thread "AWT-EventQueue-0" AWT, Swing, JavaFX & SWT 1
S JavaFX Exception in thread "JavaFX Application Thread" AWT, Swing, JavaFX & SWT 3
L Label im JavaFX Thread Updaten AWT, Swing, JavaFX & SWT 3
ralfb1105 JavaFX Alert Confirmation Dialog aus einem Service Thread AWT, Swing, JavaFX & SWT 8
ralfb1105 JavaFX MVC: Thread in Model Class mit Ausgabe in TextArea AWT, Swing, JavaFX & SWT 10
D Swing SwingUtils / Thread Problem AWT, Swing, JavaFX & SWT 3
J Thread per Button starten AWT, Swing, JavaFX & SWT 10
J Thread kennt JButton nicht. AWT, Swing, JavaFX & SWT 11
T JavaFX Task / Thread / FXThread Komplikationen AWT, Swing, JavaFX & SWT 5
O Swing Event Dispatch Thread AWT, Swing, JavaFX & SWT 1
L JavaFX UI Thread block AWT, Swing, JavaFX & SWT 13
X Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1 AWT, Swing, JavaFX & SWT 6
sandaime Swing Thread für CMD auslesen AWT, Swing, JavaFX & SWT 16
E JavaFX JavaFX Application in Thread ausführen AWT, Swing, JavaFX & SWT 1
D JavaFX UI-Thread und DB-Thread trennen um z.B. Ladebalken anzuzeigen AWT, Swing, JavaFX & SWT 15
T JavaFX Controller im extra Thread AWT, Swing, JavaFX & SWT 0
T Swing 2 Thread.sleep parallel laufen lassen AWT, Swing, JavaFX & SWT 4
L Zweites Fenster mit Thread AWT, Swing, JavaFX & SWT 0
E JavaFX Stage.show() in ursprünglichem Thread starten AWT, Swing, JavaFX & SWT 7
L Swing Frame in Thread wird nicht gezeichnet AWT, Swing, JavaFX & SWT 2
N Programm mit Swing und Thread, Figur bewegen sich nicht AWT, Swing, JavaFX & SWT 6
C Im ActionListener Buttons disablen, einen Thread starten, dann Buttons enablen AWT, Swing, JavaFX & SWT 2
C Thread-/ Simulations- Problem AWT, Swing, JavaFX & SWT 18
T Swing Button bleibt grau [=> UI hat sich aufgehängt, Aufgabe in Thread auslagern] AWT, Swing, JavaFX & SWT 3
M Thread-Frage in SWT AWT, Swing, JavaFX & SWT 1
Q GUI außerhalb GUI-Thread updaten - GUI friert ein AWT, Swing, JavaFX & SWT 18
C Thread in Klassen starten AWT, Swing, JavaFX & SWT 4
L exception in thread awt-eventqueue-0 java.lang.nullpointerexception AWT, Swing, JavaFX & SWT 2
S Swing Exception in thread "AWT-EventQueue-0" bei Jlabel AWT, Swing, JavaFX & SWT 4
D SWT SWT Elemente aus anderen Klassen aufrufen - Invalid thread access AWT, Swing, JavaFX & SWT 6
K JavaFX Tableview mit fxml ohne Aktualiserung trotz Thread AWT, Swing, JavaFX & SWT 13
K Event Handling 2 Buttons und Thread stop AWT, Swing, JavaFX & SWT 3
C Swing Update von swing-TableModels per Thread. Eins geht, das andere nicht, warum? AWT, Swing, JavaFX & SWT 12
V JLabel bzw. GUI aus externen Thread ansteuern AWT, Swing, JavaFX & SWT 3
J Applet Paralleles Thread Handling AWT, Swing, JavaFX & SWT 3
H Swing JfreeChart aktualisieren - mit daten aus thread AWT, Swing, JavaFX & SWT 3
T Java Swing Main GUI Thread AWT, Swing, JavaFX & SWT 3
C Event Handling Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException AWT, Swing, JavaFX & SWT 43
T Table-Zeilen mit Thread einfärben AWT, Swing, JavaFX & SWT 15
F Swing GUI-Thread für automatisches Update nutzen AWT, Swing, JavaFX & SWT 10
Y KeyListener, GUI Thread, repaint AWT, Swing, JavaFX & SWT 7
V Nullpointerexception (etwas mit thread und jframe) AWT, Swing, JavaFX & SWT 3
P Problem Thread.sleep() und JProgressBar AWT, Swing, JavaFX & SWT 7
S SWT GUI-Thread AWT, Swing, JavaFX & SWT 11
A Thread und sleep(1000); AWT, Swing, JavaFX & SWT 7
B Swing Thread+Animation AWT, Swing, JavaFX & SWT 7
S Timer oder Thread.sleep AWT, Swing, JavaFX & SWT 3
M Exception in thread "Thread-3" java.lang.NullPointerException AWT, Swing, JavaFX & SWT 18
B Über SWT Button Thread beenden AWT, Swing, JavaFX & SWT 2
C SWT Gui Thread hängt sich auf AWT, Swing, JavaFX & SWT 3
lumo SWT Exception in thread "main" org.eclipse.swt.SWTError: No more handles AWT, Swing, JavaFX & SWT 3
Luk10 Swing Problem mit Zeichen-Thread AWT, Swing, JavaFX & SWT 8
G 2D-Grafik Von Thread aus Zeichnen AWT, Swing, JavaFX & SWT 5
U Swing JLabel bewegen mittels Thread AWT, Swing, JavaFX & SWT 3
M JProgressBar für einen Thread AWT, Swing, JavaFX & SWT 14
R JTable und Thread AWT, Swing, JavaFX & SWT 4
K Thread.sleep in GUI AWT, Swing, JavaFX & SWT 4
J Thread funktioniert nicht AWT, Swing, JavaFX & SWT 10
D JPanel mit Thread in JPanel AWT, Swing, JavaFX & SWT 4
F Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: null AWT, Swing, JavaFX & SWT 5
P Teil einer Swing GUI in eigenem Thread AWT, Swing, JavaFX & SWT 4
S Thread.sleep() in einer methode fürs zeichen AWT, Swing, JavaFX & SWT 3
O JTree/TreeModel/DefaultMutableTreeNodes thread safe machen AWT, Swing, JavaFX & SWT 3
P repaint während Thread läuft AWT, Swing, JavaFX & SWT 9
F SWT table refresh per Thread AWT, Swing, JavaFX & SWT 2
V Swing remove(Component) blockiert Thread sehr lange. AWT, Swing, JavaFX & SWT 6
J AWT Artefakte bei AWT-Rendering durch parallelen Thread AWT, Swing, JavaFX & SWT 4
H Thread-Problem mit der Darstellung beim Sperren des Fensters AWT, Swing, JavaFX & SWT 2
T Event Dispatch Thread und noch ein Thread AWT, Swing, JavaFX & SWT 7
Burny91 Swing Thread mit wait() und notify() steuern AWT, Swing, JavaFX & SWT 22
N SWT - über Thread Composite erstellen und Anhängen AWT, Swing, JavaFX & SWT 6
K Vom Gui aus auf einen Thread warten AWT, Swing, JavaFX & SWT 4
X Problem bei JTextArea und Thread.sleep() AWT, Swing, JavaFX & SWT 8
F Merkwürdiges Verhalten zeichnen sperater Thread AWT, Swing, JavaFX & SWT 13
B Swing Swing und Thread.sleep() AWT, Swing, JavaFX & SWT 6
N Exception Behandlung mit setDefaultUncaughtExceptionHandler, insbesondere im EventDispatcher Thread AWT, Swing, JavaFX & SWT 4
Q Neuer Thread zum Öffnen AWT, Swing, JavaFX & SWT 2
P Swing GUI im Thread? AWT, Swing, JavaFX & SWT 5
T GUI JFrame - neuer Thread AWT, Swing, JavaFX & SWT 2
data89 Was mache ich mit "Dispatched Event Thread"/Substance falsch? AWT, Swing, JavaFX & SWT 4
0x7F800000 Allg. Frage zum ev. dispatch thread, wie korrekt auf reaktion der Listener warten? AWT, Swing, JavaFX & SWT 4
S Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException AWT, Swing, JavaFX & SWT 7
T thread.sleep Sprung Problem AWT, Swing, JavaFX & SWT 24
N Server mit Thread und Statusbox AWT, Swing, JavaFX & SWT 3
S Objektverhalten in einen Thread legen AWT, Swing, JavaFX & SWT 4
G JProgressBar actionPerformedMethode und SwingUI thread AWT, Swing, JavaFX & SWT 36
E Komponenten in Event Dispatch Thread erzeugen? AWT, Swing, JavaFX & SWT 4
J Thread in GUI einbauen AWT, Swing, JavaFX & SWT 2
Lony AbstractTableModel Exception in thread "AWT-EventQueue- AWT, Swing, JavaFX & SWT 3
A Ticker als Thread AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen

Neue Themen


Oben