Java problem mit swing und threads

skratchi.at

Ensign
Registriert
Dez. 2008
Beiträge
205
hi leute

ich hab mir einen kleinen tcp server gecoded der auch schon soweid funktioniert
is ein multithread server...

da ich den server auch gern überwachen und steuern möchte, wollte ich mir ein kleines GUI basteln
hab dieses mal sehr einfach gehalten mit einen JButton zum start und einen zum beenden des ganzen...
jedoch wenn ich den server starte händt das fenster...
ich kenne das eigentliche problem: der thread für das fenster kommt nicht mehr an die reihe, jedoch habe ich keine ahnung mehr wie ich das behebe...
ich hab mir einen swingworker geholt und iwie bekomm ich den aber ned hin...

bitte um hilfe...
wenn nötig kann ich auch den code des fensters posten

lg
 
Was läuft denn in den Threads? Wenns kurze sind könntest du sie ja am ende jedes Prozesses unterbrechen und dann vom hauptfenster wieder reaktivieren.
 
Was genau passiert wenn du den Start Button drückst?

Die GUI muß beim drücken des Start Buttons einen neuen Thread starten, in dem dann die Operationen ausgeführt werden. Ansonsten ist es klar, daß deine GUI hängt.
 
ablauf:
programm start... GUI läuft wie gewohnt...
drücken des buttons... GUI hängt...

ich post mal den CODE des fensters...
Code:
package sunrise;

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

import java.awt.event.*;
import SwingWorker.SwingWorker;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2008</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
public class Frame1
    extends JFrame {
  private JPanel contentPane;
  private BorderLayout borderLayout1 = new BorderLayout();
  
  
  private JButton b_serverStart = new JButton("Server Starten");
  private JButton b_exit = new JButton("Exit");
  private JPanel p_south = new JPanel (new FlowLayout());
  sunrise_server sunny = new sunrise_server();
  
  b_ActionListener myListener = new b_ActionListener(this);
  
  MySwingWorker swingWorker = new MySwingWorker();

  public Frame1() {
    try {
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      jbInit();
    }
    catch (Exception exception) {
      exception.printStackTrace();
    }
    swingWorker.start();
  }

  /**
   * Component initialization.
   *
   * @throws java.lang.Exception
   */
  private void jbInit() throws Exception {
    contentPane = (JPanel) getContentPane();
    contentPane.setLayout(borderLayout1);
    setSize(new Dimension(400, 300));
    setTitle("SunRise Server");
    
    contentPane.add(p_south, BorderLayout.SOUTH);
    p_south.add(b_serverStart);
    p_south.add(b_exit);
    
    
    b_serverStart.addActionListener(myListener);
    b_exit.addActionListener(myListener); 
  }
  
  public void b_ActionHandler (ActionEvent ae) {
	  if (ae.getSource() == b_serverStart) {
		  sunny.SunRise_Server();
	  }
	  else {
		  System.exit(0);
	  }
  }
  
  class MySwingWorker extends SwingWorker {
	  public Object construct() {
		  while (true) {
			  b_serverStart.repaint();
			  b_exit.repaint();
		  }
	  }
}
  
}

class b_ActionListener implements ActionListener {
	Frame1 cb;
	
	public b_ActionListener (Frame1 cb) {
		this.cb = cb;
	}
	
	public void actionPerformed (ActionEvent ae) {
		cb.b_ActionHandler(ae);
	}
}

hier is eig nix gemacht weil ich eben keine ahnung mehr habe wies ging...


@nightmareves:
is ned so leicht möglich di ganzen threads zu beenden...
weil es wird ein mainthread des servers gestartet, der für jeden einzelne clientverbindung einen eigenen thread startet.
 
Du hast ja bestimmt eine main-Methode mit der du das Programm startest oder? Ich würde das dann etwa so machen:

Code:
	public static void main(String[] args) {
		
		Thread guiThread = new Thread(new Runnable() {
			public void run() {
				/*
				 * Hier wird dein Fenster erzeugt, es laeuft dann in diesem
				 * Thread.
				 */
				MyFrame gui = new MyFrame();
			}
		});
		guiThread.start();
	}

Also da wird erstmal nur in einem Thread dein Fenster erzeugt. Wenn noch was passieren soll muss das natürlich getan werden.

Wo auch immer du deinen Button erzeugst, fügst du ihm einen ActionListener hinzu. Dieser ActionListener hat ja eine Methode die aufgerufen wird wenn er gedrückt wird. In dieser Methode startest du dann wieder einen neuen Thread, in dem ausgeführt wird was passieren soll, etwa so:

Code:
	JButton startButton = new JButton("Start");
	startButton.addActionListener(new ActionListener() {
		public void actionPerformed(ActionEvent arg0) {

			Thread actionThread = new Thread(new Runnable() {
				public void run() {
					/*
					 * Der Button wurde gedrueckt, hier kommt der Code hin der
					 * dann in einem eigenen Thread ausgefuehrt werden soll.
					 */
				}
			});
			actionThread.start();
		}
	});

(Achtung blind geschrieben und ungetestet ;) Aber so in etwa sollte es funktionieren)
 
Zuletzt bearbeitet:
hm... ich bekomms so auch ned hin... =(
da kommt gleich mal kein fenster...
 
Ääh.. das könnte ein Fehler bei der Main Methode sein falls du die übernommen hast. Häng mal eine Endlosschleife ans Ende:

Code:
	public static void main(String[] args) {
		
		Thread guiThread = new Thread(new Runnable() {
			public void run() {
				/*
				 * Hier wird dein Fenster erzeugt, es laeuft dann in diesem
				 * Thread.
				 */
				MyFrame gui = new MyFrame();
			}
		});
		guiThread.start();

		[B][COLOR="Red"]while(true);[/COLOR][/B]

	}

Eventuell rennt das Programm sonst direkt durch und schließt alle anderen Threads wieder bevor du großartig was zu Gesicht bekommst. Ich bin mir nicht ganz sicher ob der auf die Terminierung der anderen Threads wartet.
 
ich hab jetzt exakt folgenden code im programm:
Code:
public static void main(String[] args) {
		
		Thread guiThread = new Thread(new Runnable() {
			public void run() {
				try {
	    			         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	    		        }
	    		        catch (Exception exception) {
	    			          exception.printStackTrace();
	    		        }
				new Application1();
			}
		});
		guiThread.start();

		while(true);

	}

das selbe wie ohne thread... es hängt =(
 
Also ich starte die GUI in der main-Methode immer mit
Code:
public static void main(String[] args) {
	try {
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	} catch (Exception e) {
		e.printStackTrace();
	}
	SwingUtilities.invokeLater(new Application1());
}

Die Verzögerung müsste wie Bender86 schon sagte an der actionPerformed liegen und eigtl. war das vollkommen korrekt was er da gepostet hat. Kannst du uns mal ein Archiv mit einer lauffähigen Demo zur Verfügung stellen, die den Fehler demonstriert? Du hast ja offensichtlich noch andere Klassen ("Application1"), die du hier nicht gepostet hast und sonst wird das zu einem Rätselraten.

Abgesehen davon:
Die Sache mit deinem SwingWorker checke ich nicht so ganz. Was willst du damit bewirken? Selbst wenn das funktioniert würde das ja 100% CPU-Auslastung bedeuten. Normal müsste er hier je Schleifendurchlauf immer paar Millisekunden schlafen.
Eigtl. wird die GUI automatisch neu gezeichnet und nur in sehr speziellen Fällen muss man das über repaint manuell machen; z.B. bei eigenen Spielen. Daher halte ich das hier generell für unsinnig.
 
Zuletzt bearbeitet:
ok... lag an meiner dummheit...
hab das mit dem thread für den actionhandler und listener ned ausprobiad... ^^

danke an euch beiden :)

erinnert euch an mich wenn mein messenger weltberümt wird :p

lg
 
Und ich hab grade eben noch was geschrieben... :freak: Ok dann ist ja gut wenns läuft. Falls du doch noch ein Beispiel brauchst poste ich mal den Code. (Dank GUI Builder hats eh nur 5 Minuten gedauert. :p )

Klasse Main:

Code:
public class Main {

	/**
	 * Erzeugt ein neues MyFrame um die GUI fuer das Programm anzuzeigen.
	 */
	public static void main(String[] args) {

		MyFrame inst = new MyFrame();
		inst.setLocationRelativeTo(null);
		inst.setVisible(true);

	}
	
	/**
	 * Dies ist eine ganz Tolle Funktion die das Programm ausfuehren soll wenn
	 * der Start-Button gedrueckt wird. Vielleicht laeuft sie kurz, lange oder
	 * unendlich? Wer weiss...
	 */
	public static void myAppFunction() {
		
		int i = 0;
		
		while(true) {
			System.out.println("Das ist mein " + (i++) + "ter Schleifen-" +
					"durchlauf.");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// Exceptions sollte man natuerlich behandeln, dazu bin ich
				// jetzt aber zu faul.
				e.printStackTrace();
			}
		}
	}

}

Klasse MyFrame:

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

import javax.swing.WindowConstants;

/**
* Das Fenster fuer die GUI..
*/
public class MyFrame extends javax.swing.JFrame {
	
	private JPanel mainPanel;
	private JButton stopButton;
	private JButton startButton;
	
	public MyFrame() {
		super();
		initGUI();
	}
	
	private void initGUI() {
		try {
			setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
			{
				mainPanel = new JPanel();
				getContentPane().add(mainPanel, BorderLayout.CENTER);
				{
					startButton = new JButton();
					mainPanel.add(startButton);
					startButton.setText("Start");
					startButton.addActionListener(new ActionListener() {
						// Hier kommt die Funktion wenn der Start Button
						// gedrueckt wurde!!!
						public void actionPerformed(ActionEvent evt) {
							
							// Die Methode die ausgefuehrt wird kommt in einen
							// seperaten Thread und blockiert somit den
							// Programmablauf NICHT.
							Thread startThread = new Thread(new Runnable() {
								public void run() {
									Main.myAppFunction();
								}
							});
							startThread.start();
						}
					});
				}
				{
					stopButton = new JButton();
					mainPanel.add(stopButton);
					stopButton.setText("Stop");
					stopButton.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent evt) {
							System.out.println("Der STOPP Button wurde " +
									"gedrueckt!");
						}
					});
				}
			}
			pack();
			setSize(400, 300);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Was passiert? Wenn du die main-Methode startest öffnet sich die GUI.. wenn du auf "Start" drückst, wird einmal pro Sekunde was auf der Konsole ausgegeben, die Methode hat eine Endlosschleife. Da sie aber in einem eigenen Thread läuft, blockiert dieser das Programm NICHT und man kann den Stop Button drücken. (Dann wird ebenfalls was auf der Konsole ausgegeben)

mfg Bender
 
Zurück
Oben