2 GUI-Fenster. 2.Fenster wird nicht aufgebaut, wenn erstes beschäftigt ist.

  • Themenstarter Themenstarter die3.lustigen.4
  • Beginndatum Beginndatum
D

die3.lustigen.4

Gast
Moin,

Mein Program soll mit einem SAX-Parser eine XML überprüfen.
Mit der Haupt-GUI sollen sämtliche Einstellungen durch den Benutzer gesammelt werden. So soll auch die XML beim einbinden einmal "vorgeparst" und überprüft werden.
Da die XMLs mehrere 100 MB groß werden können, wollte ich ein kleines Info-Fenster aufploppen lassen mit "Please Wait..." und einer indeterminate JProgressBar.
Die Fenster funktionieren einzeln, aber zusammen wird der Inhalt vom Infofenster nicht aufgebaut, wenn das Hauptfenster parst. Ich weis nicht genau ob es nun ein GUI- oder ein Thread-Problem ist.

Verwendet wird Java 6 und Eclipse Gallileo.

3 Ansätze habe ich schon versucht, aber alle brachten das gleiche Ergebnis...


1. Ansatz Hauptfenster baut Infofenster:

Die Haupt-GUI wird mit meiner Main-Funktion (eigene Klasse) so aufgerufen:

[SPOILER="Main-Funktion" ]
Java:
EventQueue.invokeLater(new Runnable() {
	public void run() {
		try {
			FinalGUI frame = new FinalGUI();
			frame.setVisible(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
});
[/SPOILER]
Die XML wird dann über einen ActionListener eingebunden und eine Methode innerhalb der Klasse FinalGUI aufgerufen:

[SPOILER="Methode in Haupt-GUI" ]
Java:
	private Projectinfos projectinfos;
	private AllLanguages allLanguages;
	...


	private boolean langugageParsing(String path, boolean countEntries){
		
	//Infofenster erstellen
		Thread info = new Thread (new InfoWhileParsing(this, "Linguist-XML", path));
		info.start();
      

		
		boolean oldProjectequalsNewProject=false;
		
	//XML Parsen
		LanguageParsing paLa= new LanguageParsing(path, projectinfos, countEntries);

		oldProjectequalsNewProject= paLa.startParsing();
		allLanguages= paLa.getAllLanguages();
	... //auswertung der Sprachen und Projekteigenschaften.

	//Infofenster beenden
		infoThread.interrupt();
}
[/SPOILER]
Die Klasse die das Infofenster erzeugt sieht so aus:

[SPOILER="Infofenster Klasse" ]
Java:
public class InfoWhileParsing extends JFrame implements Runnable {
 
	private JTextPane txtPnLog;
	private JPanel contentPane;
	private JProgressBar progressBar;


    
	public InfoWhileParsing(JFrame owner, String nameOfObjectToPars, String path) {
		
		setResizable(false);
		setTitle("Parsing...");
		Toolkit.getDefaultToolkit().setDynamicLayout(true);


		contentPane = new JPanel();
        String text ="Loading " + nameOfObjectToPars + ":\n " + path + "\n\nPlease wait... ";


		setBounds(100, 100, 309, 190);

		contentPane.setBackground(Color.WHITE);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
	
		txtPnLog = new JTextPane();
		txtPnLog.setText(text);
		contentPane.add(txtPnLog);
		txtPnLog.setBounds(10, 11, 283, 121);
		
		JProgressBar progressBar = new JProgressBar();
		progressBar.setToolTipText("");
		progressBar.setForeground(new Color(51, 204, 0));
		progressBar.setIndeterminate(true);
		progressBar.setBounds(75, 140, 150, 16);
		contentPane.add(progressBar);
		
        setLocationRelativeTo(owner);

    }
 
    @Override
    public void run() {
		
		  while(!Thread.currentThread().isInterrupted()){

			  try {
			  Thread.currentThread().sleep(200);

		  		} catch (InterruptedException e) {
		  			
		  			Thread.currentThread().interrupt();
		  		}
		  
  	
		  Thread.currentThread().interrupted();
		  System.out.println("test");
		  dispose();

    	}
    }
}
[/SPOILER]
Resultat: Vom Infofenster sieht man nur den Rahmen. Inhalt wird nicht aufgebaut.



2. Ansatz: Timer statt sleep.

Brachte keine Änderung.

Nach Gesprächen mit Kommilitonen, kam der nächste Ansatz.


3. Ansatz: Infofenster vor Hauptfenster erzeugen und mit Interrupts und setVisible ein bzw. ausblenden.

Main-Funktion:
[SPOILER="Main-Funktion" ]

Java:
		final Thread infoWindow = new Thread (new InfoWhileParsing());
		infoWindow.start();
		

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					FinalGUI frame = new FinalGUI(infoWindow);
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
[/SPOILER]
Parser-Methode die durch den ActionListener innerhalb der Haupt-GUI aufgerufen wird:
[SPOILER="Methode in Haupt-GUI" ]

Java:
	private boolean langugageParsing(String path, boolean countEntries){
		
	//InfoFenster anzeigen
		infoThread.interrupt();
      

		
		boolean oldProjectequalsNewProject=false;
		
		LinguistLanguageParsing paLa= new LinguistLanguageParsing(path, projectinfos, countEntries);

		oldProjectequalsNewProject= paLa.startParsing();
		allLanguages= paLa.getAllLanguages();

	... //auswertung der Sprachen und Projekteigenschaften.

	//InfoFenster nicht mehr anzeigen

		infoThread.interrupt();
[/SPOILER]
Und die geänderte Infofenster Klasse.
[SPOILER="Infofenster Klasse" ]

Java:
public class InfoWhileParsing extends JFrame implements Runnable {
 
	private JTextPane txtPnLog = new JTextPane();
	private JPanel contentPane;
	private JProgressBar progressBar;

    
	public InfoWhileParsing() {
		
		setResizable(false);
		setTitle("Parsing...");
		Toolkit.getDefaultToolkit().setDynamicLayout(true);


		contentPane = new JPanel();
        String text ="Loading " + "\n\nPlease wait... ";


		setBounds(100, 100, 309, 190);

		contentPane.setBackground(Color.WHITE);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
	
		txtPnLog = new JTextPane();
		txtPnLog.setText(text);
		contentPane.add(txtPnLog);
		txtPnLog.setBounds(10, 11, 283, 121);
		
		JProgressBar progressBar = new JProgressBar();
		progressBar.setToolTipText("");
		progressBar.setForeground(new Color(51, 204, 0));
		progressBar.setIndeterminate(true);
		progressBar.setBounds(75, 140, 150, 16);
		contentPane.add(progressBar);
		


    }
 
    @Override
    public void run() {
    	
    	while(true){	
		
		  while(!Thread.currentThread().isInterrupted()){

			  try {
			  Thread.currentThread().sleep(200);

		  		} catch (InterruptedException e) {
		  			
		  			Thread.currentThread().interrupt();
		  		}
		  		repaint();
		  }
    	
		  Thread.currentThread().interrupted();
		  System.out.println("test");

		  setVisible(!isVisible());		
    	}
    }
}
[/SPOILER]
Resultat: Vom Infofenster sieht man wieder nur den Rahmen. Inhalt wird nicht aufgebaut.



Das Parsen in einen eigenen Thread stecken wollte ich eigentlich nicht, weil dann alle Variablen final werden müssen und die Zugriffe auf die Parser-Klasse schwieriger werden.

Ich habe den ganzen Freitag an diesem Problem gewerkelt und diverse Internetseiten durchsucht und leider kein ähnliches Problem gefunden.
Vielleicht seht ihr ja auf Anhieb, was ich falsch mache bzw. was fehlt.

Aber falls dieses Thema schonmal behandelt wurde, könntet ihr mir dann sagen unter was ich dieses Problem finden kann?


Vielen Dank schonmal.

Rico
 
Okay, danke vanny.

Aber mich verwirrt, dass die Run Methode des Info-Thread parallel zu laufen scheint.
Ich habe jetzt mal die Konsolenausgabe "Test" in die while(!isInterrupted())-Schleife getan. Hier bekomme ich die Konsolenausgabe "Test" kontinuierlich, wenn der Thread läuft, obwohl das Hauptfenster gerade parst.

Beim 3. Ansatz hatte ich schon in der Main Methode beide GUIs in einzelne Threads gesteckt (denke ich zumindest) und mit Interrupts das Infofenster gesteuert. Aber auch hier wird, wenn die Haupt-GUI beschäftigt ist, der Inhalt vom Infofenster nicht angezeigt. Die Run-Methode gibt trotzdem kontinuierlich Konsolenausgabe "Test" aus.

Also habe ich doch meine gewünschte Parallelität? Nur der Inhalt baut sich nicht auf...
Ist es dann immernoch ein Thread-Problem oder doch ein GUI-Problem?
 
Es handelt sich wohl eher um ein Verständnisproblem.
Deine GUI egal ob 1 oder 100 Fenster läuft im EDT und das ist auch gut so.
Deine Parseaktion (nur die) gehört in einen seperaten Thread. wenn dann wieder was an der GUI geändert wird(Progressbar zBsp.) dann übergibste mit invokeLater nur diese Aktion an den EDT weiter.

Das ganze gibts auch in "benutzerfreundlich" (<<Geschmackssache) und nennt sich SwingWorker.

Gruß Vanny
 
Gut sowas habe ich mir fast schon gedacht. Deswegen hatte ich ja auch den 3. Ansatz versucht, aber wenn es nur einen EDT gibt, dann bringt das ja auch nix.

Habe mir mal eben Swingworker angeguckt, ist auf dem ersten Blick nix anderes als Runnable mit ner Rückgabe...
Egal, also werde ich wohl mal einen Thread drumbasteln.

Danke für deine Hilfe.
 

Zurück
Oben