Subframes als JFrame oder JDialog

mueslirocker

Mitglied
Hallo,

ich stehe vor einem Problem, das schon 1000 mal da war, aber ich finde für meinen Fall keine passende Antwort. Vermutlich bin ich zu blind, aber ich komm um einen Thread wohl nicht drum herum. Es geht um die Entscheidung, was man für Sub-GUIs benutzen sollte.

Ich habe einige Fenster (JFrames), die im Prinzip alle eigene Applikationen darstellen. Man kann sie einzeln starten. Nun sollen einige dieser GUIs aber andere aufrufen können. Das soll modal geschehen. Dafür benutzt man ja aber eigentlich den JDialog. Alle GUIs als JFrame (für den alleinigen Aufruf) und JDialog (für die Sub-Aufrufe) zu implementieren, ist kein Problem, da der eigentliche Inhalt in einem JPanel-Objekt steht, von denen ich beiden eine Instanz zuweisen kann.

Mein Problem sind die Eigenschaften des Sub-Frames:
Ein JDialog ist als etwas Vorübergehendes gedacht, das kurz mit dem User spricht, damit das eigentliche Programm dann gleich weiter machen kann. Entspreched ist das Verhalten des Programms bei offenem Dialog. Der Programmfluss ist "unterbrochen". Man kann das Programm z.B. nicht mehr minimieren. Ich möchte auch, dass das Super-Fenster deaktiviert ist (sonst könnte ich es ja nicht-modal machen), aber ich möchte, dass die Steuerung des gesamten Programms von dem Sub-Fenster übernommen wird. Wenn man dieses minimiert, soll es sich mit allen Super-Fenstern minimieren. Also so, als ob man es nicht-modal macht und dann im Super-Fenster minimiert... nur eben vom Sub-Fenster aus. Es ist klar, dass das mit dem JDialog nicht (ohne erheblichen Aufwand) geht, denn so ist die Nutzung gar nicht gedacht. Mein Sub-Fenster ist kein Dialog, kein kurzes Gespräch mit dem User. Dieser könnte 90% der Zeit auf Sub-Fenstern arbeiten und am Ende nur kurz das oberste Fenster nutzen/beenden. Und während dieser 90% möchte er mit einem JFrame und nicht mit einem JDialog arbeiten... und das Programm z.B. minimieren können.

Als nächstes habe ich überlegt, nur JFrames zu benutzen und mittels setEnabled(...) das Super-Fenster zu deaktivieren. Aber auch das ist nicht das Verhalten, das ich suche. Es erscheinen zwei Taskbar-Einträge, es sind zwei eigenständige Applikationen. Ich kann zwar das Super-Fenster nicht mehr minimieren und könnte wohl einrichten, dass beim Minimieren des Sub-Fensters das Super-Fenster mit minimiert wird und ebenso das Wiederherstellen irgendwie führen... aber das Taskbar-Problem (damit hängt ja noch mehr zusammen) bleibt bestehen und zeigt eigentlich, dass es so auch nicht gedacht ist.

JInternalFrames sind - wenn ich das richtig verstanden habe - auch keine Lösung, da sie als Teil des Super-Fensters agieren. Ich möchte sie aber wie einen JDialog quer über den Bildschirm schieben können.

Ich kann mir nicht vorstellen, dass dieses Verhalten so selten erwünscht ist, dass es da keinen Standardfall für gibt und man ein Workaround basteln muss. Das Sub-Fenster soll ein vollwertiges Hauptfenster sein, das die Steuerung aller Super-Fenster (also der gesamten Applikation) in der Oberfläche des Betriebsystems übernimmt.

Hat jemand eine Idee, wie ich da vorgehen kann?
 
Uffz, viel Text ;)
Aber dadurch ist immerhin klar verständlich was du willst!

Also IMHO kommst du um ein Workaround nicht drumrum... Normalerweise würde ich für mehrere Fenster einer Applikation beispielsweise eine JDesktopPane (Hauptfenster) mit JInternalFrames (Unterfenster) verwenden. JDialogs sind ja beispielsweise nicht minimierbar (soweit ich weiß), was eine Steuerung der restlichen Applikation damit hinfällig macht. Daher tippe ich auf ein Workaround mit Sub-JFrames.

Als Tipp für die Sup-JFrames:
Es gibt ein Projekt namens >>JNative<<, wo du über einen Wrapper eine native Funktion zum Verbannen eines JFrames aus der Taskleiste aufrufen kannst. Der Code muss wohl so oder ähnlich aussehen (in einem anderen Forum grad gefunden):
Java:
HWND hWnd = User32.FindWindow(null, deinFrame.getTitle());
if(hWnd.getValue() != 0)
{
    User32.ShowWindow(hWnd, WindowsConstants.SW_HIDE);
}
JNative stellt auch eine TrayIcon-Klasse bereit, falls du ohnehin eins verwenden wolltest. Der Vorteil gegenüber der TrayIcon-Klasse von Java 1.6 ist wohl der, dass über diese ein JFrame aus Taskleiste verschwinden lassen kannst.

Prinzipiell würde ich mir eine Managment-Klasse erzeugen, die eine Art Stack bereitstellt. Diesem Stack würde ich die nacheinander aufgerufenen Fenster hinzufügen und beim jeweiligen Schließen wieder vom Stack entfernen. Immer das oberste Fenster hat die Kontrolle (und ist modal), die anderen sind deaktiviert.

Na dann mal viel Erfolg!

Gruß
miffi
 
Danke für die Antwort! :)

Also gibt es wirklich kein Standardvorgehen dafür.. hm... dann sollte ich mir überlegen, ob ich mein Konzept nicht überdenken sollte. Warum muss ich unbedingt von dem 1-Hauptfenster-Standard abweichen? Mir war nicht klar, dass das so unnatürlich ist. Dachte, das gibt es öfters.

Dennoch denke ich mal aus Interesse hier weiter und gehe auf deine Antwort ein. Vielleicht finde ich so etwas, das eher einer Standardbenutzung gleicht.

Ein JDesktopPane kommt für mich leider nicht in Frage, da es wirklich eigenständige Fenster sein sollen. Ich möchte sie über beliebige Monitore verschieben und von einander trennen können. Allein da stellt sich mir jetzt schon die Frage, warum das so ist. Die Super-Fenster sind eh deaktivert und können nicht verschoben werden.

JDialogs sind aus dem Rennen, da sind wir uns wohl einig.

Das Workaround zum Löschen des Taskbar-Eintrags ist cool, danke. Aber das funktioniert logischerweise nur unter Windows, richtig? Eigentlich wollte ich das Ganze plattformübergreifend machen.

Den Stack hatte ich auch schon so implementiert. :D Schön, dass die Idee hier auch aufkam, so hab ich das Gefühl, auf dem richtigen Weg zu sein. (Hab vom Stack<JFrame> abgeleitet und push und pop überschrieben.)

Im Moment überlege ich, ob ich nicht eher den Content des Fensters komplett austausche und den Titel neu setze. Wäre ja nur ein Panel, das ich austauschen müsste, in dem alles drin ist. Würde das den User verwirren, wenn sich auf einmal die komplette GUI ändert damit sie dann nach dem Sub-Prozess wieder die alte wird? In dem Titel könnte ich irgendwie den Stack-Inhalt widergeben...

Hat jemand eine Idee, wie und mit welchen GUI-Mitteln ich sowas sonst umsetzen könnte?

/edit
Das mit dem Austausch des Contents ist irgendwie Blödsinn, oder? Dann kann ich auch doch nen JDesktopPane benutzen und das oberste JInternalFrame immer maximieren. Klingt beides nicht wirklich natürlich.
 
Zuletzt bearbeitet:
Nur weil ich kein Standardvorgehen dafür kenne, heißt nicht, dass es keins gibt ;)
Vielleicht kennt ja einer der lokalen Java-Gurus eine Möglichkeit, mal abwarten, was hier noch so gepostet wird. Hab zwar inzwischen schon einige Erfahrung mit Swing, aber mit einigen Postern hier kann ich noch nicht mithalten.

Und ich denke, so unnatürlich ist die Vorgehensweise mit mehreren Fenstern nicht - allerdings, dass alle nicht-aktiven Fenster deaktiviert sein sollen, ist IMHO in diesem Zusammenhang eher selten. Und die TaskBar-Geschichten über JNative gelten in diesem Beispiel natürlich nur für Windows. Zugriffe auf native Bibliotheken trotzdem einigermaßen plattformunabhängig zu halten artet in viel Arbeit aus, das ist wahr... Wäre halt eine Option gewesen, wenn du nur für Windows entwickelt hättest.

Wenn ich an deiner Stelle wäre, würde ich eine von zwei Möglichkeiten versuchen:
  1. Wie du selbst gesagt hast, ein einziges Frame, dessen Inhalt sich ändert. So verwirrend finde ich das nicht, solange du nicht bei jedem zweiten Klick die ganze GUI änderst. In Installations-Wizards beispielsweise ist es ja auch so, dass die GUI sich je nach Schritt ändert, und damit kommen User auch klar. Allerdings würde ich mir bei diesem Ansatz Überlegungen zu einem Navigations-Panel machen, das es dem User auch ermöglicht, zwischen den Frames hin und her zu wechseln. Außerdem könnte hier auch eine Übersicht vorhanden sein, welche Konfiguration du gerade vom Stack her aktiv hast.
  2. Schon mal daran gedacht, Tabs (JTabbedPane) einzusetzen? Mache ich immer öfter, um mehrere getrennte Module in einem JFrame darzustellen. Hier weiß ich allerdings nicht, ob und wie Tabs de/aktivierbar sind, aber da es sich um JComponents handelt, wirds wohl schon möglich sein.

Gruß,
miffi
 
Hehe, okay, ja, da hab ich ein bisschen gevorurteilt und deine Antwort verallgemeinert. Wäre natürlich cool, wenn sich doch noch was elegantes dafür finden würde.

Punkt 1 gefällt mir immer besser. Es ist zwar nicht wirklich mit einem Wizard zu vergleichen, denn der spielt eher eine Sequenz von GUIs ab, bei denen man vor und zurück gehen kann, während ich eher eine GUI unterbrechen und später zu ihr zurück finden möchte (ein Stack eben)... wenn man auf einer Super-GUI ist, kann man dann auch eine andere Sub-GUI als zuvor aufrufen - es läuft also vielleicht eher auf einen Baum hinaus als auf eine Sequenz... aber ja, eigentlich ist es trotzdem nicht soo verwirrend. Man kann sich die Sub-GUIs bei mir als Ausschnitte denken. GUI 1 hält mehrere Objekte und man wählt eines aus und dazu öffnet sich eine neue GUI, die dieses Objekt im Detail betrachtet. Das wiederum kann andere Objekte beinhalten, die man wieder "groß machen" können soll.

Das Navigieren zwischen den Frames wollte ich eigentlich auf die Eigenschaften eines Stacks beschränken. Man soll das Super-Fenster wirklich erst wieder benutzen können, wenn man mit dem Sub-Fenster fertig ist. Daher finde ich Tabs auch nicht so gelungen, da man zwischen denen ja beliebig wechseln können soll. Auch wenn man sie deaktivieren kann, entsteht da ein falscher Eindruck, denke ich.
Aber grundsätzlich eine Navigations-Hilfe zu bauen, ist eine gute Idee. Das meinte ich auch, als ich davon sprach, in den Titel des Frames den Stack-Inhalt zu schreiben. Aber eine richtige Anzeige in der GUI ist natürlich besser.
 
Der Wizard war auch nur ein Beispiel für ein sich änderndes GUI, mir ist grad nichts besseres eingefallen :D

Also mir gefällt dieser Ansatz auch am besten bisher, muss ich sagen. So kannst du dir erstmal Code sparen, da du keine De/Aktivierungs-Methodik benötigst. Außerdem ist auf diese Weise wesentlich leichter sicherzustellen, dass der Benutzer die Sub-Funktionen (falls nötig) auf jeden Fall zu Ende durchspielt, da er sonst nicht wieder zur Haupt-GUI zurückkommt. Das TaskBar-Problem fällt dadurch natürlich auch weg.
Und es sieht einfach besser aus ;)

Na dann wünsch ich mal viel Erfolg. Was auch immer du da gerade bastelst...

Gruß
miffi
 
Warum sag ich eigentlich dauernd "die GUI" statt "das GUI"? Vielleicht hab ich ein Frauenproblem... -.-

Ich hab mir jetzt ein Konzept mit dem Panel-Stack zurechtgelegt. Das scheint doch am besten zu passen. Vielen Dank, miffi, für die vielen Denkanstöße und Informationen.

Über neue Möglichkeiten, das Problem ohne Workaround anzugehen, freu ich mich weiterhin, aber bis dahin betrachte ich das Thema als erledigt.

Ist übrigens nicht aufregendes. ;) Nur ein Tool zur leichten Suche in einer Datenbank mit der Möglichkeit, Objekte herauszufischen und verändert wieder abzuspeichern.
 

Neue Beiträge

Zurück