JFrame bleibt nach Erzeugung blank

Moin.

Ich habe ein Problem mit meinem Java Programm und hoffe, dass ihr mir weiterhelfen könnt.

Folgende Situation:
Ich habe ein Programm, welches die für uns in der Produktion wichtigen Daten zusammen sucht. Leider kommt es, je nach Auslastung des System, zu Ladezeiten von bis zu 15 Skeunden, deshalb wollte ich ein Startfenster programmieren.
Dieses Fenster sollte nichts anderes machen, als einen Text anzuzeigen (“Starte Programm .”) und dann immer wieder einen Punkt hinzufügen, bis zu einem maximum von 5 (“Starte Programm . . . . .”) und dann wieder bei einem Punkt beginnen. Das funktioniert für sich alleine stehend auch wunderbar, aber leider nicht, wenn ich es aus dem Hauptprogramm herraus aufrufen will.

Hier mal kurz ein wenig (gekürzten) Quellcode:

Das “Wartzeit-Frame”

 * Create the frame.
 */
public OpenFrame() {
	setTitle("Starte Programm");
	setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	setBounds(100, 100, 263, 84);
	contentPane = new JPanel();
	contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
	setContentPane(contentPane);
	contentPane.setLayout(null);
	
	JLabel lblStarteProgramm = new JLabel("Starte Programm");
	lblStarteProgramm.setFont(new Font("Tahoma", Font.BOLD, 12));
	lblStarteProgramm.setBounds(10, 11, 115, 24);
	contentPane.add(lblStarteProgramm);
	
	validate();
	setVisible(true);
	new Thread(this).start();
}```

Und das Hauptframe:
```/**
 * Erstellet das Frame
 */
private void createFrame() {
	
	[...]
	//Erzeugung des Grundgerüstes (Tab Pane und Menüleiste)
	[...]

	//Abfrage von Benutzer und Passwort, der Dialog ist Modal, blockiert also die weitere Ausführung
	PasswortDialog pd = new PasswortDialog();
	pd.setVisible(true);
	benutzer = pd.getUser();
	passwort = pd.getPassword();
	
	//Nach der Eingabe von Benutzername und Passwort soll das JFrame geöffnet werden
	if(of == null) {
		of = new OpenFrame();
	}
	of.start();
		
	[...]
	//Erzeugung der restlichen Panels
	[...]
		
	//Nach diesem Muster werden nun mehrere Threads angelegt, die die Daten zusammensuchen, die bereits
	//beim Starten des Programms benötigt werden
	Thread initMas = new Thread() {
		@Override
		public void run() {
			masPanel = new SortPanel(true, benutzer, passwort);
			masPanel.setBounds(10, 11, 1306, 910);
			panel_1.add(masPanel);
		}
	};
		
	[...]
		
	//Hier werden alle Threads gestartet
	initMas.start();

	//Und anschließend wird gewartet, dass alle fertig sind
	while(initMas.isAlive()) {
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	//Um dann das oben geöffnete Fenster zu schließen und dieses Frame anzuzeigen
	of.setVisible(false);
	setVisible(true);
}```

Starte ich das Programm jetzt, sieht mein JFrame leider so aus:

Es wird also scheinbar blockiert, mein Versuch mit dem EventQueue.invokeLater() brachte auch keinen wirklichen Erfolg, da er das Fenster erst anzeigen würde, nachdem bereits das setVisibile(false) ausgeführt wurde.

Mit freundlichen Grüße
Gossi

Moin,

ich verstehe nicht so ganz, was Du da versuchst …
Was soll das “new Thread(this).start();” am Ende von “OpenFrame” machen ??

Erzeuge doch einfach das Fenster und setzte es im Hauptprogramm solange es angezeigt werden soll mit “setVisible(true)” auf **sichtbar ** und anschließend auf **unsichtbar ** mit “setVisible(false)” (oder besser gleich “dispose”) !

Gruß Klaus

[QUOTE=vfl_freak;126934]Moin,

ich verstehe nicht so ganz, was Du da versuchst …
Was soll das “new Thread(this).start();” am Ende von “OpenFrame” machen ??

Erzeuge doch einfach das Fenster und setzte es im Hauptprogramm solange es angezeigt werden soll mit “setVisible(true)” auf **sichtbar ** und anschließend auf **unsichtbar ** mit “setVisible(false)” (oder besser gleich “dispose”) !

Gruß Klaus[/QUOTE]

Zu Punkt 1 (new Thread(this).start(); )
Das Ruft die Run Methode auf, damit sich der Text ändert:
Starte Programm .
Starte Programm . .
[…]
Starte Programm . . . . .
Starte Programm .
usw.

Zu Punkt 2:
Genau das Versuche ich ja, aber dabei bekomme ich das leere Fenster, welches ich oben mit angehängt habe als Grafik.

Hallo,

hier mal ein Beispiel mit einer Progressbar.

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class ProgressView extends JFrame implements PropertyChangeListener {

	private static final long serialVersionUID = 7969171884314179196L;

	private JPanel container = new JPanel();
	private JProgressBar progressBar;

	private Task task;
	private int begin = 0;
	private int end = 10;
	private int currentPos = 0;

	class Task extends SwingWorker<Void, Void> {
		@Override
		public Void doInBackground() {
			while (currentPos < end) {
				try {
					Thread.sleep(1000);
					currentPos++;
				} catch (InterruptedException ignore) {
				}
				setProgress(currentPos);
			}
			return null;
		}

		@Override
		public void done() {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					setVisible(false); // Schliesst dieses Fenster
					
					
					AbsoluteExample ex = new AbsoluteExample();
					ex.setVisible(true); //Öffnet die eigentliche View. 
				}
			});
		}
	}

	public ProgressView() {

		initUI();

		task = new Task();
		task.addPropertyChangeListener(this);
		task.execute();
	}

	public final void initUI() {
		container.setLayout(new BoxLayout(container, BoxLayout.PAGE_AXIS));
		progressBar = new JProgressBar(begin, end);
		progressBar.setValue(currentPos);
		progressBar.setStringPainted(true);
		container.add(progressBar);

		add(container);
		setTitle("Beispiel");
		setSize(250, 100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {

				ProgressView ex = new ProgressView();
				ex.setVisible(true);
			}
		});

	}

	public void propertyChange(PropertyChangeEvent evt) {
		if ("progress" == evt.getPropertyName()) {
			int progress = (Integer) evt.getNewValue();
			progressBar.setValue(progress);
			progressBar.setString(String.valueOf(progress));
		}
	}

}

Zudem würde ich dir noch empfehlen dich ein wenig damit zu beschäftigen:

Java Thread Pool Example using Executors and ThreadPoolExecutor

Grüße

Hallo hier mal ein kleines Beispiel mit eine Progressbar:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class ProgressView extends JFrame implements PropertyChangeListener {

	private static final long serialVersionUID = 7969171884314179196L;

	private JPanel container = new JPanel();
	private JProgressBar progressBar;

	private Task task;
	private int begin = 0;
	private int end = 10;
	private int currentPos = 0;

	class Task extends SwingWorker<Void, Void> {
		@Override
		public Void doInBackground() {
			while (currentPos < end) {
				try {
					Thread.sleep(1000);
					currentPos++;
				} catch (InterruptedException ignore) {
				}
				setProgress(currentPos);
			}
			return null;
		}

		@Override
		public void done() {
			SwingUtilities.invokeLater(new Runnable() {

				public void run() {
					setVisible(false); // Schliesst dieses Fenster

					AbsoluteExample ex = new AbsoluteExample();
					ex.setVisible(true); // Öffnet die eigentliche View.
				}
			});
		}
	}

	public ProgressView() {

		initUI();

		task = new Task();
		task.addPropertyChangeListener(this);
		task.execute();
	}

	public final void initUI() {
		container.setLayout(null);
		progressBar = new JProgressBar(begin, end);
		progressBar.setValue(currentPos);
		progressBar.setStringPainted(true);
		container.add(progressBar);

		add(container);
		setTitle("ProgressView");
		setSize(250, 100);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {

			public void run() {

				ProgressView ex = new ProgressView();
				ex.setVisible(true);
			}
		});

	}

	public void propertyChange(PropertyChangeEvent evt) {
		if ("progress" == evt.getPropertyName()) {
			int progress = (Integer) evt.getNewValue();
			progressBar.setValue(progress);
			progressBar.setString(String.valueOf(progress));
		}
	}

}

Zudem solltest du dir mal das hier anschauen:

Java Thread Pool Example using Executors and ThreadPoolExecutor

Grüße

Moin,

Aha … das war aus Deinem Code nun wirklich erkennbar :frowning:

Dann solltest Du zumindest vorher aus den Thread stoppen!

Aber das Ganze ist IMHO eh’ ziemlich unglücklich!
Warum benutzt Du keine ProgessBar, die ist doch sowas in der Art ideal?
JProgressBar

Gruß Klaus

Da dieses Fenster eigentlich angezeigt werden soll, bevor das Hauptfenster zu sehen ist, ist eine ProgressBar schlecht einzubinden :smiley:
Aber ich bin grad dabei das etwas anders zu schreiben um diese Problematik zu umgehen.

Du suchst wohl eigentlich das hier: https://docs.oracle.com/javase/tutorial/uiswing/misc/splashscreen.html

Um ein Frame zu schließen sollte man lieber dispose() statt setVisible(false) nutzen. Auch lässt der Code auf extends JFrame/JDialog schließen > ganz böses Design. Dann denke ich so an den Klassiker: ernst anzeigen und dann zusammenbauen. Dann noch NullLayout …

Kurz und knapp: die paar Fetzen reichen schon um sagen zu können: dein GUI-Code scheint ziemlicher Mist zu sein und bedarf erstmal einem sauberen re-write. Dadurch dürfte sich dann das Problem sicher von selbst lösen.
Ansonsten: Spaghetti-code ahoi - du kannst es zwar sicher fixen, aber der Code der dann dabei raus kommt dürfte die absolute Katastrophe werden.

In wie weit ist ein extends JFrame ganz böses Design? Bzw. was wäre dort die schönere Variante?

Und auf .dispose() habe ich schon umgestellt.

Alternative ist ein JFrame-Objekt zu erstellen und darauf aufzurufen,

je nach Strenge kann man diese Vererbung für unnötig halten,
du würdest ja sicher auch nicht von einer ArrayList erben nur weil du danach 20x add() und get() aufrufen musst,

aber Swing-Komponenten sind dafür irgendwie anfällig, mache ich auch häufig,
liegt auch etwas näher, jedes JFrame oder besonderes Unter-JPanel ist stark individualisiert, konfiguriert, ein Einzelstück

eine eigene Klasse muss oft so oder so her, zur Verwaltung aller enthaltenen Komponenten,
wenn nicht geerbt dann normalerweise keine Oberklasse und nur 1:1 Attribut mit komplizierteren Aufrufen…

aber gilt wiederum für ArrayList teils genauso, Objektivität spricht gegen Vererbung

Alles klar, danke dafür :slight_smile:

Schau mal in unser Wiki: Warum man nicht von JFrame/JDialog erben sollte – Byte-Welt Wiki

@TO
Da das Thema als “solved” makiert wurde wäre es allen sehr hilfreich wenn du die “Lösung” dann auch bitte posten würdest.

oft genug setzten Moderatoren wie ich auf ‘Erledigt’,

und was immer hier das genaue Problem war außer der JFrame-Vererbungsfrage habe ich bis heute nicht genau verfolgt, aber entweder Standardproblem oder sonstiger individueller Fehler in simpler JFrame-Zusammensetzung,

das hilft so gut wie keinem, hier groß nachzuverfolgen, wo der Fehler lag,
keine eindeutige Fehlermeldung/ Suchbegriff der je wieder hierherführen wird

-> Moral von der Geschichte: ‘bitte an Lösung denken’-Postings sind für sich schon fragwürdig User belastend, hier vom Thema her unnötig und halbe Woche später unnötig Thread wiederbelebend,

bitte auf sowas eher verzichten, vorsichtig und defensiv einsetzen, keine Gieskanne,
zum Glück ja auch recht selten zu lesen, umso ungewöhnlicher warum in diesem Thema

Kurz zu meiner Verteidigung, ich hab das Thema nicht auf Erledigt gesetzt, da ich bis heute morgen das Problem noch nicht komplett gelöst hatte.

Die Lösung war in meinem Fall, dass ich die Oberfläche von Grund auf neu aufgesetzt habe.

Aber für alle die für sowas (wie ich in diesem Falle) den Eclipse WindowBuilder benutzen:

Der baut in der main-Methode ein Konstrukt was ungefähr so aussieht:

    @Override
    public void run() {
        try{
            ScanViewGui frame = new ScanViewGui();
            frame.setVisible(true);
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
});```
Nachdem ich das umgeändert hatte in:
```ScanViewGui frame = new ScanViewGui();
frame.setVisible(true);```
Funktioniert die Geschichte mit dem Frame wunderbar. Naja, jetzt hab ich wenigstens ne sauber aufgesetzte GUI ohne extends JFrame :D

Mit einem anderen L&F (oder, THEORETISCH* auch schon mit der nächsten Java-Version) könnte das aber nicht mehr funktionieren. Das GUI muss normalerweise so (d.h. auf dem Event Dispatch Thread) aufgebaut werden.


  • THEORETISCH, weil es SO viele Snippets und Beispiele gibt (selbst von Sun/Oracle), wo das NICHT gemacht wird, dass klar ist, dass es “praktisch immer” auch anders funktionieren wird. Aber ich habe schon L&Fs gesehen, wo sowas schlicht abgekachelt ist.