Swing GUI sperren

multiholle

Aktives Mitglied
Ich möchte eine Statusbar anzeigen während eine längere Aufgabe ausgeführt wird. Das funktioniert auch schon einigermaßen, siehe unten.

Java:
vDialog.setVisible(true);
Wenn ich jedoch diese Zeile auskommentiere (ganz unten) funktioniert die Statusbar auf dem Hauptfenster nicht mehr. Das Dialogfenster sperrt das Hauptfenster solange der Thread arbeitet. Ich brauche also eine ähnliche Funktionalität, jedoch ohne Dialogfenster.

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

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

public class DialogTest {

	public static void main(String[] args) {
		final JFrame frame = new JFrame();
		frame.getContentPane().setLayout(new BorderLayout());
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

		final JProgressBar bar = new JProgressBar();
		bar.setIndeterminate(false);
		frame.getContentPane().add(bar, BorderLayout.SOUTH);

		frame.getContentPane().add(new JButton(new AbstractAction("Test") {
			public void actionPerformed(ActionEvent e) {
				System.out.println(new SampleWorker(frame).doconnect(bar));
			}
		}), BorderLayout.NORTH);

		frame.pack();
		frame.setVisible(true);
	}

	private static class SampleWorker {
		JDialog vDialog;
		private boolean result;

		public SampleWorker(JFrame frame) {
			vDialog = new JDialog(frame, "5 Sekunden warten", true);
			JProgressBar bar = new JProgressBar();
			bar.setIndeterminate(true);
			vDialog.getContentPane().add(bar);
			vDialog
					.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
			vDialog.pack();
		}

		private void finish() {
			vDialog.setVisible(false);
		}

		public boolean doconnect(JProgressBar bar) {
			bar.setIndeterminate(true);
			Thread workerThread = new Thread(new Runnable() {
				public void run() {
					// hier die Lange Funktion mit Rückgabewert boolean.
					boolean done = true;
					try {
						Thread.currentThread().sleep(5000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					result = done;
					SwingUtilities.invokeLater(new Runnable() {
						public void run() {
							finish();
						}
					});
				}
			});
			workerThread.start();
			// hier: Dialog aufrufen
			vDialog.setVisible(true);
			bar.setIndeterminate(false);
			return result;
		}
	}
}
 

KrokoDiehl

Top Contributor
Was mir spontan einfällt und ich mal gelesen und daraufhin erfolgreich angewendet habe, ist eine eigene GlassPane.
Du kannst einem JFrame via
Code:
setGlassPane()
eine eigene Komponente geben. Diese GlassPane sitzt quasi über allen anderen Komponenten. Wenn du an an diese GlassPane noch Key- und MouseListener hängst, die alle Ereignisse konsumieren, wird die GUI damit unbenutzbar.
Außerdem war da noch was mit Transparenz ...
Ich habe es hier nicht mehr gefunden, aber ich vermute dass du unter dem Stichwort GlassPane sicher was findest.

Das ist nur eine Option, es gibt sicherlich auch noch andere Methoden ...
 

_Andi91

Bekanntes Mitglied
Ich würde es auch mit einer GlassPane machen.
Dazu eine neue Klasse erstellen, von JPanel ableite, Events abfangen und durchsichtig setzen (setOpaque(false)).
Was ich dir auch noch empfehlen kann für so Sachen die im Hintergrund laufen sollen ist der SwingWorker. Da brauchst du dich zB schon mal nicht mehr um das invokeLater zu kümmern.

EDIT:
Noch was zur GlassPane: Ich mach es immer so, dass ich die setVisible Methode überschreibe und zusätzlich noch die Sanduhr als Cursor anzeige, wenn visible auf true gesetzt wird.
 
Zuletzt bearbeitet:
G

Gast2

Gast
meinst du mich????
Klar sieht gut aus und regelt das alles ziemlich easy und einfach... Außerdem regelt der JXLayer auch den Cursor von selber usw. Kann das Ding nur empfehlen und ist einfach zu bedienen.
 

multiholle

Aktives Mitglied
Danke für die vielen Tipps, aber ich denke eine GlassPane ist nicht ganz das was ich suche. Momentan wird ja ein Modaler Dialog geöffnet und erst geschlossen, wenn der Thread seine Aufgabe erledigt hat, anschließend wird das Ergebnis des Threads zurückgegeben.

Verwende ich eine Glasspane, wird der Thread gestartet, die Glasspane angezeigt und sofort der Rückgabewert geliefert, bevor der Thread fertig ist. Ich brauche etwas, was wie der Dialog den Code blockiert bis der Thread soweit ist und trotzdem der GUI gestattet sich weiter zu zeichnen.
 
G

Gast2

Gast
Ja das eine hat doch mit anderem nichts zu tun... Musst halt den Thread richtig warten lassen!!!
 

nixnick

Mitglied
[JAVA=38] vDialog = new JDialog(frame, "5 Sekunden warten", true);
[/code]
wie wäre es wenn du modal (das letzte) auf false setzt?
laut api sperrt der dialog dann nicht.
 

multiholle

Aktives Mitglied
Ja das eine hat doch mit anderem nichts zu tun... Musst halt den Thread richtig warten lassen!!!
Nur wenn ich den Thread warten darauf warten lasse, dass die Aktion abgeschlossen wird, friert die GUI in der Zeit ein. Desewegen funktioniert das mit der Glasspane nicht :/

Das Programm macht so ja schon was es soll, nur dass ich halt den Dialog nicht anzeigen möchte. Wenn ich jetzt den Dialog einfach nicht einblende läuft das Programm durch und der Rückgabewert der Funktion stimmt nicht.
 
G

Gast2

Gast
Klar klappt dass mit der GlassPane... Du musst deinen Job halt in dem richtigen Thread ablaufen lasse, dann friert die GUI nicht ein... Schau dir mal den SwingWorker an...
 

multiholle

Aktives Mitglied
Funktioniert wunderbar, Danke :) Hier ist der Code, für alle die es interessiert:
Java:
package marcelsTestPackage;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;

public class WorkerTest extends JFrame {
	JButton button = new JButton();
	JProgressBar progressBar = new JProgressBar();
	
	public WorkerTest() {
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		getContentPane().setLayout(new BorderLayout());
		
		button.setAction(new AbstractAction("work!") {
			@Override
			public void actionPerformed(ActionEvent e) {
				new Worker().execute();
			}
		});
		getContentPane().add(button, BorderLayout.CENTER);

		getContentPane().add(progressBar, BorderLayout.SOUTH);
		
		pack();
		setVisible(true);
	}
	
	private class Worker extends SwingWorker<Boolean, Object> {
		@Override
		protected Boolean doInBackground() throws Exception {
			progressBar.setIndeterminate(true);
			setGlassPane(new Glass());
			getGlassPane().setVisible(true);
			
			try {
				Thread.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return true;
		}
		
		@Override
		protected void done() {
			progressBar.setIndeterminate(false);
			getGlassPane().setVisible(false);
			try {
				System.out.println(get());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private class Glass extends JPanel {
		public Glass() {
			setOpaque(false);
			addMouseListener(new MouseListener() {
				@Override
				public void mouseReleased(MouseEvent e) {
				}
				@Override
				public void mousePressed(MouseEvent e) {
				}
				@Override
				public void mouseExited(MouseEvent e) {
				}
				@Override
				public void mouseEntered(MouseEvent e) {
				}
				@Override
				public void mouseClicked(MouseEvent e) {
				}
			});
			addKeyListener(new KeyListener() {
				@Override
				public void keyTyped(KeyEvent e) {
				}
				@Override
				public void keyReleased(KeyEvent e) {
				}
				@Override
				public void keyPressed(KeyEvent e) {
				}
			});
		}
		
		@Override
		public void setVisible(boolean visible) {
			super.setVisible(visible);
			setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		}
	}
	
	
    public static void main(String[] args) {
    	new WorkerTest();
    }
}
 
G

Gast2

Gast
Den Code
Java:
			progressBar.setIndeterminate(true);
			setGlassPane(new Glass());
			getGlassPane().setVisible(true);

solltest du nicht im Hintergrund ausführen!!! Außer er ist thredsafe steht in der api... Ansonsten musst du ihn zum EDT synchronisieren...
 

Ähnliche Java Themen

Neue Themen


Oben