JLayerdPane richtig anwenden


#1

Hallo an alle,

ich versuche gerade auf ein JFrame ein Bild (im Hintergrund) zu platzieren auf dem sich aber bereits mehrere JPanels mit Buttons befinden. Auf das JFrame habe ich das GridLayout angewendet.

Das heißt ich kann nicht einfach ein JLabel verwenden das Bild dort einfügen und es auf das JFrame setzen damit es im Hintergrund angezeigt wird.

Das muss ich dann wohl mit dem JLayerdPane machen.

Daher dachte ich mir, ich erstelle eine Ebene in JLayerdPane und füge dort das JLabel hinzu.

Nur stellt sich mir die Frage wie ich dem Programm sage, das er das JLayerdPane hinter das JFrame setzen soll?

Zuerst habe ich einmal ein LayerdPane erstellt:

JLayerdPane layerdpane = new JLayerPane();

Dann das label hinzugefügt:

layeredPane.add( label, new Integer(...) );

Jetzt müsste ich den richtigen Integerwert vom JFrame herausfinden und dann einen geringeren für mein JLayerdPane setzen?

Bitte sagt mir Bescheid, wenn das nicht stimmt.

Danach müsste es doch funktionieren?

frame.add(layerdpane); darf ich doch nicht machen, da ich es doch nicht dem JFrame hinzufügen möchte.

Bitte euch um Hilfe, da ich das ganze nicht so wirklich durchblicke.

SG


#2

Falls ich das richtig verstanden habe, brauchst du dafür nicht unbedingt ein layered pane. Du könntest auch als content pane des JFrames ein JPanel setzen, in dem du die paintComponent-Methode passend überschreiben.

Aber ggf. ist eine layered pane flexibler.

Unabhängig davon: Der Integer, der da übergeben wird, bezieht sich nur auf die Elemente innerhalb der layered pane. Schnell hingeschriebener Pseudocode:

JComponent imageComponent = createImageComponent();
JComponent otherComponent = createComponentWithButtonsAndWhatnot();

JLayeredPane layeredPane = new JLayeredPane();
layeredPane.add(imageComponent, Integer.valueOf(0));
layeredPane.add(otherComponent , Integer.valueOf(1));

frame.getContentPane().add(layeredPane);

(Nie new Integer(...) verwenden, immer Integer.valueOf(...))


#3

Hallo,

danke für deinen Code, doch leider wird immer nur das JLabel mit dem Bild dargestellt:

JLayeredPane layerpane = new JLayeredPane();
layerpane.add(label, Integer.valueOf(1));
layerpane.add(panel, Integer.valueOf(0));

	window.getContentPane().add(layerpane);
	
	window.setVisible(true);

am JPanel befinden sich zwei JCheckBoxen.

Warum werden die Checkboxen nicht angezeigt?

MfG


#4

sind solche Grundlagen von Foren/ Diskussionen/ Interaktion allgemein nicht inzwischen klar?
zu JLayeredPane als ein weiteres Grundlagenthema ist das Internet mal wieder von Beispielen zugepflastert, natürlich wieder alle bestens funktionierend,
z.B. https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html

dein Code bzw. Nicht-Code bietet genug Zweifel, so dass in der Tat glaubwürdig, dass bei dir auch dies nun, wie anscheinend so ziemlich alles, nicht funktioniert :wink:
von allgemein einfach jeden theoretisch möglichen Fehler zu vermuten (JCheckboxen unsichtbar konfiguriert, Monitor an entsprechender Stelle kaputt?..) bis zu halbwegs naheliegenden Fragen wie “was ist aktuell ‘window’, zumal im ersten Post noch von ‘frame’ die Rede?..”,

aber unterm Strich bleibt allein ein Punkt zu sagen, der immer und überall gilt, ohne dass ihn eigentlich noch jemand sagen müsste (jedenfalls nicht mehr nach anscheinend bereits 20 Themen allein hier im Forum) :
poste ein vollständiges kurzes Testprogramm!, dann kann fast jeder in Minuten sagen was los ist,

ansonsten gibt es nur dämliche Postings wie dieses hier :wink:


#5

Beim ersten Überfliegen sieht es aus, als wäre das Label in Layer 1, und damit über dem Panel, das in Layer 0 liegt. Ansonsten hat SlaterB Recht. Swing ist besser dokumentiert als so ziemlich jede andere Lib, die ich kenne (was nicht heißt, dass es nicht seine dunklen Ecken hat, und man manche Sachen “einfach wissen” sollte), aber … ein Beispiel von

https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html

kopieren, einfach mal starten… das funktioniert ja alles recht leicht, meistens standalone, keine makefiles nötig :wink:


#6

Hallo Marco13,

nun funktioniert es.

Ich habe “setBounds” anstatt den Layoutmanager verwendet.

Nur mit einem Layout-Manager gibt es Probleme.
Sobald ein Layout auf das JLayerdPane angewendet wird, wird das JLabel was sich von der Ebene her hinter den JPanels befindet scheinbar auf die selbe ebene angehoben.
Das JLabel wird wie die JPanels in einem kleinen Bereich des Fenster angezeigt und das Bild nur zum Teil dargestellt.

Muss nochmal googeln, warum es mit dem Layout Manager nicht mehr funktioniert.

MfG


#7

IIRC setzt man bei einer LayeredPane das Layout nicht für die Layered Pane selbst. Die LayeredPane hat schon ein Layout, nämlich das, wo sie alle components übereinander anordnet.

Also kurz:

layeredPane.add(panelA, Integer.valueOf(0));
layeredPane.add(panelB, Integer.valueOf(1))

//layeredPane.setLayout(new BorderLayout()); // FALSHC!

// Richtig
panelA.setLayout(new BorderLayout());
panelB.setLayout(new GridLayoutOderWelchesAuchImmerEsMüssenJaAuchNichtAlleDasGleicheLayoutHaben());

#8

Das habe ich mir schon gedacht, meine JPanels haben ja jeweils ein Layout für die Buttons und checkboxen die sich darauf befinden.
Nur möchte ich die vier JPanels auf das LayerdPane setzen mit einem GridLayout.
Die JPanels sollen am JLayerdPane mit einem GridLayout angeordnet werden.

Das wollte ich machen.

Da das LayerdPane wie du sagtest bereits das spezielle Layout hat um Komponenten übereinander anordnen zu können, geht das ja gar nicht anders.

Eigentlich könnte ich ja ein JScrollPane auf das JLayerdPane setzen, dann die einzelnen JPanels auf das JScrollPane.
Anschließend den JScrollPane ein Layout geben und es Transparent machen.

Das wäre auch eine möglichkeit.

SG


#9

Layout in JLayeredPane geht wohl durchaus,

und
https://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
hat auch genau ein Beispiel mit GridLayout…

wenn es bei dir nicht geht helfen keine ‘och menno, woran kann es nur liegen?’-blahblah-Postings,
sondern du solltest wissen, was stattdessen die simple Variante ist, die jedem anderen die Lösung in potentiell wenigen Minuten statt vielen Tagen ermöglich


welchen Zweck hat dann noch das JLayerdPane?
würde das JScrollPane ganz normal in die GUI eingefügt nicht dasselbe bewirken?

nicht dass ich mich groß auskennen würde, praktisch nie selbst JLayerdPane verwendet


#10

Ich habe doch schon erklärt was mein Problem ist.

Das Beispiel ist mir durchaus bekannt und funktioniert auch in meinem Programm.
Nur das ist nicht das was ich möchte.

Ohne Layout Manager und mit setBounds(); funktioniert mein Programm einwandfrei.
Wende ich aber den Layout-Manager an, dann wir das Bild von der hinteren Ebene nach vorne gerückt und zusammen auf einer Ebene mit den JPanels dargestellt.
Das Bild soll aber den Hintergrund des Programmes schmücken.
Deshalb befindet sich das JLabel mit dem Bild eine Ebene tiefer am JLayerPane als die JPanels.

Ohne Layout-Manager funktioniert es einwandfrei und mit nicht mehr.

Deshalb meine Idee mit dem JScrollPane.

Werde dies heute mal versuchen.

SG


#11

Layouts direkt in die LayeredPane ist ein bißchen heikel, weil die Layout-Constraints dann ggf. als “layer” interpretiert werden. Ich finde es sauberer, das LayeredPane so zu lassen, wie es ist, und nur die Components darin mit einem LayoutManager zu versehen.

Ansonsten… wenn ich das richtig verstanden habe, willst du eine ganz normale Component, nur soll im Hintergrund ein Bild sein. Wie groß das Bild sein soll, ob es ggf. mitgescrollt werden soll, … alles relevante Fragen, aber … das wird sich sicher noch festrütteln.


#12

das sind so Dinge die in Worten alles und nichts bedeuten können, mit Code evtl. deutlicher wären,
wobei idealerweise ohne Bilder, nur Standardkomponenten zum Test

GridLayout klingt freilich nicht so ganz nach ‘übereinander’, eher streng ‘nebeneinander’,
aber das Beispiel im Tutorial mit dem beweglichen Duke bzw. noch besser dem schwarzen Rechteck (auch wieder Problem mit Bild-Datei, die man nicht so schnell da hat), bewegt per Maus + setLocation(), in alle Ebenen verschiebbar, über/ drunter allem anderen, scheint wiederum genau für deine Ideen relevant


#13

Ich möchte es folgendermaßen machen:

Ein JLayerdPane hat auf einer Ebene ein Hintergrundbild.
Eine Ebene darüber befinden sich drei JPanels die jeweils Buttons enthalten.

JPanel 1 ganz oben, JPanel 2 in der Mitte und JPanel 3 ganz unten.
Mit einem GridLayout alles kein Problem, doch auf das JLayerdPane lässt sich kein GridLayout anwenden.
Das JLayerdPane besitzt ja schon ein spezielles Layout um Elemente in unterschiedlichen Ebenen darstellen zu können.

Warum verwende ich eigentlich drei JPanel für die Bedienelemente wie Buttons JCheckBoxen usw.

Ganz einfach, da ich die einzelnen Buttons unterschiedlich angeordnet haben möchte.
Daher verwende ich drei Jpanels mit unterschiedlichen Layouts. Funktioniert alles wunderbar.
Das Hintergrundbild sieht man auch hinter den Buttons.
Ich habe das Problem mit setBounds gelöst. Bei mir funktioniert das so auch problemlos, da das Fenster immer gleich groß ist und nicht verändert werden kann.

Nur mit einem Layoutmanager könnte ich die Größe des Fensters auch verändern und dann würde die Anordnung immer noch passen. Deshalb wollte ich wissen, wie ich das mit dem Layoutmanager bei JLayerdPane machen kann.

JScrollPane kann ich auch nicht verwenden.

MfG


#14

du kannst es gerne für dich glauben und im weiteren ohne Kommentar von mir behaupten,
aber einmal mehr stelle ich noch fest, dass das schlicht nicht stimmt,

man kann den JLayeredPane ein beliebiges Layout zur Anordnung der Komponenten geben,
das ist unabhängig vom Layer-Verhalten und ja auch leicht einzusehen:
die 2D-Anordnung der Komponenten spielt keine Rolle für die quasi dritte Dimension der Layer


dein Beispiel mit Hintergrundbild + drei Panel darüber dürfte auch ohne Layer in einem normalen JPanel schwierig werden, wenn GridLayout eben alles nebeneinander anordnet, kein Übereinander vorgesehen,
mit JLayeredPane wie früher gesagt gleiches Problem in dieser Hinsicht

willst du überhaupt Layer, die Button-Panel übereinander verschieben?
ein Hintergrundbild, englisch background image, und darauf normale Komponenten ohne Layer,
das ist für sich ein häufig angefragtes Konzept mit manchen Lösungen, ohne Bezug auf JLayeredPane

was standardmäßig zu finden ist hat aber wohl eher Hack-Charakter
etwa
http://www.java2s.com/Tutorial/Java/0240__Swing/CreatingFrameswithabackgroundimage.htm
http://www.java2s.com/Code/Java/Swing-JFC/Panelwithbackgroundimage.htm
mit Panel mit paintComponent

oder
https://java-demos.blogspot.de/2012/09/setting-background-image-in-jframe.html
mit Nutzung eines JLabels welches intern weitere Komponenten aufnehmen kann

‘java background image example’ findet diverse andere


#15

Vielen Dank SalterB!

Das Beispiel ist echt gut.

Wie gesagt, in meinem aktuellen Fall funktioniert es auch mit setBounds.
Jetzt weiß ich wie es sonst noch geht.

Nochmals Danke!

SG