Swing Componenten übereinander platzieren.

jf

Bekanntes Mitglied
Hallo, gibe es eine einfachere Möglichkeit, einen Schaltfläche rechts in der Tab-Leiste einer JTabbedPane zu platzieren? - Order muss man hierfür doch wieder auf das Overlay-Layout zurückgreifen?
 

jf

Bekanntes Mitglied
Hallo, ich muss das Thema doch noch mal aufmachen. An und für sich funktioniert das mit der JLayeredPane. Jetzt wollte ich mir aber eine kleine Helfer-Klasse bauen, welche mir die Positionierung der Schaltfläche vereinfacht. - Wenn ich es so mache, dann sehe ich leider keine Komponente.

Java:
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JTabbedPane;


@SuppressWarnings("serial")
public class JTabRowButton extends JComponent {

	private JLayeredPane m_layeredPane = new JLayeredPane();

	public JTabRowButton(JTabbedPane tabbedPane, JButton button) {

		tabbedPane.setBounds(0, 0, this.getWidth(), this.getHeight());
		button.setBounds(this.getWidth()-button.getWidth(), 0, button.getWidth(), 19);
		
		m_layeredPane.add(tabbedPane, new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 0));
		m_layeredPane.add(button,     new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 1));
		
		this.add(m_layeredPane);
	}
}

Ich sehe meinen Fehler leider überhaupt nicht... Was mache ich nur falsch? :(
 

Michael...

Top Contributor
[JAVA=14] tabbedPane.setBounds(0, 0, this.getWidth(), this.getHeight());
button.setBounds(this.getWidth()-button.getWidth(), 0, button.getWidth(), 19);[/code]
Lass Dir doch mal die Größe der beiden Komponenten ausgeben. Diese ist vermutlich 0x0.
z.B. liefert
Code:
this.getWidth()
0 solange die Komponente noch nicht angezeigt wird.
 

jf

Bekanntes Mitglied
Lass Dir doch mal die Größe der beiden Komponenten ausgeben. Diese ist vermutlich 0x0.
z.B. liefert
Code:
this.getWidth()
0 solange die Komponente noch nicht angezeigt wird.
Um dieses Problem auszuschließen, habe ich es auch schon mit fixen Werten ausprobiert: auch hier wird nichts angezeigt...
 

Michael...

Top Contributor
Was mir gerade auffällt: Warum erbt Deine Klasse von JComponent und nicht von JPanel?
Bei JComponent ist imho z.B. kein LayoutManager gesetzt.
 

Marco13

Top Contributor
Falls ich das richtig verstanden habe, SOLL ja gerade kein LayoutManager verwendet werden - damit setBounds überhaupt funktioniert. Aber nebenbei: Ich finde, die Art der Verwendung dieser Klasse sieht etwas suspekt aus. Ich würde mal schauen, die der Code von JTabbedPane aussieht, und ob man da nicht "direkter" einen Button einbauen kann...
 

jf

Bekanntes Mitglied
Ich finde, die Art der Verwendung dieser Klasse sieht etwas suspekt aus. Ich würde mal schauen, die der Code von JTabbedPane aussieht, und ob man da nicht "direkter" einen Button einbauen kann...
Ja, ich dachte auch erst daran, JTabbedPane zu erweitern - aber egal, welche Methode man verwendet (add() oder addTab()), es wird immer als neuer Tab hinzugefügt. Daher glaube ich, dass ich nicht umhingekommen wäre, eine neue Klasse zu bauen, welche durch Komposition ein JTabbedPane und einen JButton auf einer JLayeredPane zusammenführt. Um mir die dabei nötige Delegationsarbeit für die Methoden der JTabbedPane und des JButtons zu sparen, habe ich eben nur so eine kleine Klasse gebastelt: eine Art "Jacke", welche nur für die richtige Platzierung sorgt - gearbeitet wird anschließend weiter auf der JTabbedPane und dem JButton.
Für Anregungen, wie man so etwas eleganter lösen kann, bin ich natürlich sehr dankbar. Ich habe diesbezgl. nämlich noch nicht viel gemacht...

Würde der Component ein BorderLayout geben, damit der LayeredPane die gesamte Fläche einnimmt.
Das hat auch nichts gebracht.

Java:
package LayeredPane;


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;


@SuppressWarnings("serial")
public class SimpleLayerTest extends JFrame {

	private static SimpleLayerTest m_instance = null;
	
	private SimpleLayerTest() {
		JLayeredPane layeredPane = new JLayeredPane();
		JTabbedPane tabs = new JTabbedPane();
		JButton but = new JButton("Drück mich!");
		
		tabs.addTab("Tab", new JPanel());
		
		this.setSize(400, 400);
		layeredPane = new JTabRowButton(tabs, but, this.getWidth(), this.getHeight());
		this.add(layeredPane);
	}
	
	public static SimpleLayerTest getInstance() {
		if(m_instance == null) {
			m_instance = new SimpleLayerTest();
		}
		return m_instance;
	}
	
	public static void main(String[] args) {
		SimpleLayerTest win = SimpleLayerTest.getInstance();
		win.setDefaultCloseOperation(EXIT_ON_CLOSE);
		win.setVisible(true);
	}

}

@SuppressWarnings("serial")
class JTabRowButton extends JLayeredPane {

	private JTabbedPane m_tabbedPane = null;
	private JButton m_button         = null;
	
	public JTabRowButton(JTabbedPane tabbedPane, JButton button, int width, int height) {
		m_tabbedPane = tabbedPane;
		m_button     = button;
		
		this.add(tabbedPane, new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 0));
		this.add(button,     new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 1));
		
		this.setSize(width, height);
	}
	
	public void setSize(int width, int height) {
		int tabW = width;
		int tabH = height;
		int butW = m_button.getPreferredSize().width;
		int butH = m_button.getPreferredSize().height;
		
		System.out.println(tabW + "  " + tabH);
		System.out.println(butW + "  " + butH);
		
		m_tabbedPane.setBounds(0, 0, tabW, tabH);
		m_button.setBounds(tabW-butW, 1, butW, 19);
	}
}

Ich bin jetzt aber schon etwas weiter: wenn meine Klasse direkt von JLayeredPane erbt anstatt von JComponent oder JPanel, dann funktioniert es komischerweise. Hat jemand eine Erklärung dafür?

Um die Sache richtig rund zu machen, wäre es aber gut, wenn ich die Größe des Client-Bereiches des Fensters ermitteln würde (also Fenstergröße - Randbreite). Wie kann ich das bewerkstelligen?
 

Marco13

Top Contributor
Nur überflogen, vorsicht: Du überschreibst anscheinend die setSize-Methode der JLayeredPane, da kann man sich ziemlich viel kaputt machen! Ggf. werde ich es später nochmal genauer ansehen.
 

jf

Bekanntes Mitglied
Du überschreibst anscheinend die setSize-Methode der JLayeredPane
Ja, das war eigentlich auch der Plan: damit man mit der Klasse schneller zurecht kommt.

da kann man sich ziemlich viel kaputt machen!
Hmm. Gut, da habe ich keinerlei Erfahrung... - vlt. könnte man noch ein super.setSize() einbauen?

Ggf. werde ich es später nochmal genauer ansehen.
Au, das wäre nett! :)
 

Marco13

Top Contributor
Hmja, ist ein bißchen frickelig.

Hab' gerade mal geschaut, ob man den Button direkt in die JTabbedPane einbauen könnte, aber das wäre ziemlich fast unmöglich, wenn man auch andere Tab-Anordnungen usw. unterstützen wollte.

Das könnte man auch als Einschränkung bzgl. der aktuellen Lösung ansehen, aber ist vielleicht hier nicht so schlimm.

Das mit dem setSize ist auch so eine Sache: setSize ist nicht die einzige Methode, die die Größe ändert: Es gibt auch noch resize, setBounds, reshape usw... All diese Methoden ändern die Größe. Durch die überschriebene setSize würde jetzt der Effekt erreicht, dass diese Methode "für Swing" keine Auswirkungen mehr hätte. Wenn Swing also irgendwo
Java:
component.setSize(10,10);
if (component.getWidth() != 10) throw SomethingWrongException("Aaaahhh");
machen würde, dann würde dort die Exception geworfen. In der Tat ist es so, dass setSize intern praktisch nie verwendet wird, aber darauf kann man sich nicht verlassen.

Auch ein super.setSize würde nicht helfen:

Umgekehrt wäre es nämlich so, dass die Methoden, DIE von Swing verwendet werden (z.B. setBounds oder reshape) nicht den Effekt hätten, den du durch das Überschreiben von setSize erreichen willst. Das sieht man auch, wenn man die Framegröße ändert: Die TabbedPane/Button bleiben immer so groß, wie am Anfang, weil der LayoutManager zwar die JTabRowButton der Framegröße anpasst, dafür aber nicht setSize sondern reshape verwendet.

Die einzige einigermaßen "saubere" Lösung, die mir einfallen würde, wäre
Java:
@SuppressWarnings("serial")
class JTabRowButton extends JLayeredPane {
 
    private JTabbedPane m_tabbedPane = null;
    private JButton m_button         = null;
    
    public JTabRowButton(JTabbedPane tabbedPane, JButton button) {
        m_tabbedPane = tabbedPane;
        m_button     = button;
        
        this.add(tabbedPane, new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 0));
        this.add(button,     new Integer(JLayeredPane.DEFAULT_LAYER.intValue() + 1));
        this.addComponentListener(new ComponentAdapter() {
			
			@Override
			public void componentResized(ComponentEvent e) {
		        int butW = m_button.getPreferredSize().width;
		        m_tabbedPane.setBounds(0, 0, getWidth(), getHeight());
		        m_button.setBounds(getWidth()-butW, 1, butW, 19);
			}
		});
    }

}

@die üblichen Verdächtigen (Andre & Co) : Hat noch jemand eine "bessere" Idee?
 

jf

Bekanntes Mitglied
Die einzige einigermaßen "saubere" Lösung, die mir einfallen würde, wäre
Ja, an einen ResizeListener hatte ich auch gedacht - nur bin ich davon ausgegangen, dass ich zunächst in Erfahrung bringen müsste, wie man die Client-Breite des Fensters ermittelt.
Wie ich sehe, kann ich in der ListenerRoutine aber mit this.getWidth() arbeiten, was im Konstruktor nicht der Fall war. Damit erübrigt sich das Ermitteln der Größe ja von ganz allein! :)

Dennoch würde mich interessieren, wie man die Client-Breich-Größe ermittelt (sofern dies schnell erklärt ist - bitte nicht für "Offtopic" groß Zeit verschwenden, so wichtig is es nämlich nun auch wieder nicht).

Was mir in diesem Zusammenhang jetzt aber neu ist, ist die Tatsache, dass man im Listener this verwenden kann. Ich nahm bisher stets an, dass mir this nur das Listener-Objekt selber liefert. - Ist das bei einem ComponentListener etwa anders?

@die üblichen Verdächtigen (Andre & Co) : Hat noch jemand eine "bessere" Idee?
Für weitere Anregungen wäre ich natürlich sehr dankbar. Dennoch bin ich mit der von Marco entwickelten Lösung schon sehr zufrieden. Danke! :toll:
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Dennoch würde mich interessieren, wie man die Client-Breich-Größe ermittelt (sofern dies schnell erklärt ist - bitte nicht für "Offtopic" groß Zeit verschwenden, so wichtig is es nämlich nun auch wieder nicht).
Was genau meinst du mit Client-Bereich?

Was mir in diesem Zusammenhang jetzt aber neu ist, ist die Tatsache, dass man im Listener this verwenden kann. Ich nahm bisher stets an, dass mir this nur das Listener-Objekt selber liefert. - Ist das bei einem ComponentListener etwa anders?

Da steht ja kein 'this' :D Wenn man einfach nur 'getWidth()' aufruft, dann schaut er zuerst nach, ob es das in der anonymen Klasse gibt - wenn nicht, nimmt er das von der einschließenden Klasse. Mit 'this.getWidth()' würde es nicht direkt funktionieren, weil man damit explizit auf die innere Klasse verweisen würde, die ja kein getWidth hat.

Aber allgemein: Um in so einem Fall auf die Äußere Klasse (bzw. Instanz) zu verweisen, muss man
Java:
class JTabRowButton extends JLayeredPane {
... 
    public JTabRowButton(JTabbedPane tabbedPane, JButton button) {
...
        this.addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                int widthOfJTabRowButton = JTabRowButton.this.getWidth(); // <----- DAS HIER
            }
        });
    }
verwenden.
 
Zuletzt bearbeitet:

jf

Bekanntes Mitglied
Was genau meinst du mit Client-Bereich?
Der Client-Bereich eines Fenster ist der Bereich des Fensters ohne Titelleiste und Rahmen.
Hierfür gibt es die Windows-API GetClientRect. Aber wenn du an dieser Stelle nachfragen musst, dann wird man das bei Java nur äußerst selten benötigen, was evtl. auch der Verwendung der LayoutManager geschuldet ist.


Da steht ja kein 'this' :D Wenn man einfach nur 'getWidth()' aufruft, dann schaut er zuerst nach, ob es das in der anonymen Klasse gibt - wenn nicht, nimmt er das von der einschließenden Klasse.
Mit 'this.getWidth()' würde es nicht direkt funktionieren, weil man damit explizit auf die innere Klasse verweisen würde, die ja kein getWidth hat.
Ah, ok. Sehr interessant. Dank für die Info.

Aber allgemein: Um in so einem Fall auf die Äußere Klasse (bzw. Instanz) zu verweisen, muss man
Code:
JTabRowButton.this.getWidth()
verwenden.
Auch das ist mir neu. - Ich habe bisher immer eine Member-Variable hierfür verwendet, welche ich im Konstruktor gesetzt habe. Bloß gut, dass ich nochmal nachgefragt habe. :D
 

Michael...

Top Contributor
Der Client-Bereich eines Fenster ist der Bereich des Fensters ohne Titelleiste und Rahmen.
Hierfür gibt es die Windows-API GetClientRect. Aber wenn du an dieser Stelle nachfragen musst, dann wird man das bei Java nur äußerst selten benötigen, was evtl. auch der Verwendung der LayoutManager geschuldet ist.
Stichwort ContentPane, die wurde mit Java 1.5 leider ein bisschen "versteckt"
Java:
	JFrame frame = new JFrame();
	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	frame.setBounds(0, 0, 300, 300);
	frame.setVisible(true);
	System.out.println(frame.getBounds());
	System.out.println(frame.getContentPane().getBounds());
 

Marco13

Top Contributor
Hmja, aber die Größe braucht man eigentlich nicht... Üblicherweise liegt in der ContentPane irgendwas (ggf. auch mehrere Components, gelayoutet), und jede Component sollte bestenfalls IHRE eigene Größe wissen müssen...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
E Swing Componenten werden nach Änderung des display modes verzerrt dargestellt AWT, Swing, JavaFX & SWT 8
kaoZ Frage zum einfügen von Componenten AWT, Swing, JavaFX & SWT 14
L Componenten im JFrame an genaue stelle verschieben. AWT, Swing, JavaFX & SWT 2
V Swing Componenten Array AWT, Swing, JavaFX & SWT 3
B Swing JMenu zwischen anderen Componenten AWT, Swing, JavaFX & SWT 4
M SWT SWT Componenten auf GLCanvas zeichnen AWT, Swing, JavaFX & SWT 3
earlgrey_tea GridBagLayout Componenten proportional vergößern AWT, Swing, JavaFX & SWT 12
L LayoutManager Componenten über verfügbaren Platz strecken AWT, Swing, JavaFX & SWT 7
L Swing Serverbrowser, aber welche componenten? AWT, Swing, JavaFX & SWT 2
H Mit for-schleife die Componenten eines Frames verändern AWT, Swing, JavaFX & SWT 5
H SWT Breite von componenten zu bestimmen AWT, Swing, JavaFX & SWT 2
T JFrame Componenten Problem AWT, Swing, JavaFX & SWT 17
T Swing JSplitPane Componenten ausrichten AWT, Swing, JavaFX & SWT 4
lumo Swing Componenten ersetzen AWT, Swing, JavaFX & SWT 2
L Swing Kommunikation zwischen JMenuBar und anderen Componenten AWT, Swing, JavaFX & SWT 2
E Im Frame alle Componenten abrufen AWT, Swing, JavaFX & SWT 2
R Wie kann ich programmatisch Clicks auf Componenten ausfuehren? AWT, Swing, JavaFX & SWT 26
S Standpunkt von Componenten frei bestimmen AWT, Swing, JavaFX & SWT 10
R Thumbpanel bzw. Layout das Componenten in einem Grid anordnet ..? AWT, Swing, JavaFX & SWT 13
D verschieden große Componenten in einem JPanel? AWT, Swing, JavaFX & SWT 2
A Swing: Componenten in einem deaktivierten JPanel AWT, Swing, JavaFX & SWT 2
R HTML Hintergrund für Swing - Componenten AWT, Swing, JavaFX & SWT 2
G Suche 2 Componenten: Splitpane ausblenden / Stecknadel AWT, Swing, JavaFX & SWT 2
G SystemTray BubbleInfo an anderen Componenten anzeigen AWT, Swing, JavaFX & SWT 6
J durchsichtige componenten AWT, Swing, JavaFX & SWT 3
S Componenten werden nicht angezeigt AWT, Swing, JavaFX & SWT 3
R Componenten eines JFrames updaten AWT, Swing, JavaFX & SWT 11
thE_29 TableRenderer und JPanel => Abfrage auf Componenten Posit AWT, Swing, JavaFX & SWT 2
S Mehere Componenten setEnabled(false) in JToolBar AWT, Swing, JavaFX & SWT 4
M componenten im jframe erst nach fensterveränderung sichtbar AWT, Swing, JavaFX & SWT 2
S verhindern von drag-n-drop von swing componenten AWT, Swing, JavaFX & SWT 2
T Objektorientierung bei Componenten häh? AWT, Swing, JavaFX & SWT 5
D Componenten Problem - aktualisieren nach hinzufügen AWT, Swing, JavaFX & SWT 2
V JTable mit mehreren Componenten in einer Spalte ? AWT, Swing, JavaFX & SWT 6
CptK JPanels übereinander legen AWT, Swing, JavaFX & SWT 6
M Zwei JPanel übereinander nur vorderes "repainten" AWT, Swing, JavaFX & SWT 3
M Java FX Layouts übereinander statt nebeneinander AWT, Swing, JavaFX & SWT 4
S Swing Mehrere Modal-Dialoge übereinander AWT, Swing, JavaFX & SWT 5
C LayoutManager Bei verkleinern des Fensters, verschieben sich JPanels übereinander. AWT, Swing, JavaFX & SWT 7
F Swing JPanels übereinander ohne Mananger AWT, Swing, JavaFX & SWT 1
M Komponenten übereinander AWT, Swing, JavaFX & SWT 7
N Komponenten übereinander AWT, Swing, JavaFX & SWT 3
T Prüfen ob 2 JLabel übereinander liegen. Performance Problem. AWT, Swing, JavaFX & SWT 5
S 2 Canvas übereinander AWT, Swing, JavaFX & SWT 2
M 2D-Grafik Mehrere Linien (nacheinander) übereinander Zeichnen AWT, Swing, JavaFX & SWT 6
M Swing JPanel lagern übereinander AWT, Swing, JavaFX & SWT 14
C Swing JPanel übereinander legen AWT, Swing, JavaFX & SWT 4
C Zwei Bilder übereinander legen AWT, Swing, JavaFX & SWT 1
S Graphics2D: Transparent übereinander zeichnen AWT, Swing, JavaFX & SWT 7
M Komponenten übereinander prüfen AWT, Swing, JavaFX & SWT 3
J LayoutManager Panels übereinander AWT, Swing, JavaFX & SWT 3
D Texte zeichenweise übereinander darstellen, gemeinsam umbrechen AWT, Swing, JavaFX & SWT 5
I 2 Panels übereinander, 1 transparent AWT, Swing, JavaFX & SWT 2
S mehere panels übereinander AWT, Swing, JavaFX & SWT 2
M JProgressBar übereinander legen? AWT, Swing, JavaFX & SWT 3
Y Mehrere Komponenten übereinander ohne Swing AWT, Swing, JavaFX & SWT 2
B Komponenten übereinander platzieren AWT, Swing, JavaFX & SWT 2
S Labels und Button übereinander --> Reihenfolge? AWT, Swing, JavaFX & SWT 4
F JPanel übereinander zeichnen AWT, Swing, JavaFX & SWT 4
W Bilder übereinander legen AWT, Swing, JavaFX & SWT 1
N Mehrere JComponents übereinander AWT, Swing, JavaFX & SWT 3
H Komponenten übereinander anordnen, I/O-Konsole AWT, Swing, JavaFX & SWT 3
E Panels übereinander darstellen AWT, Swing, JavaFX & SWT 2
D 2 Komponenten übereinander AWT, Swing, JavaFX & SWT 2
S Komponenten übereinander anordnen? AWT, Swing, JavaFX & SWT 5
P JLabels übereinander legen AWT, Swing, JavaFX & SWT 8
M JTabbedPane zeigt alle Panels übereinander an :( AWT, Swing, JavaFX & SWT 8
B 2D-Grafik String drehen/platzieren/formatieren in bestimmten Bereich AWT, Swing, JavaFX & SWT 1
B GUI: SWING-Steuerelemente freihand platzieren AWT, Swing, JavaFX & SWT 2
G Swing Buttons in Layouts frei platzieren AWT, Swing, JavaFX & SWT 7
J LayoutManager BorderLayout - 2 Buttons in SOUTH nebeneinander platzieren? AWT, Swing, JavaFX & SWT 3
D LayoutManager JPanels ohne LayoutManager platzieren AWT, Swing, JavaFX & SWT 6
O Swing JFrame auf Monitor platzieren AWT, Swing, JavaFX & SWT 3
M Elemente in JTabbedPane platzieren AWT, Swing, JavaFX & SWT 7
G Fenster auf zweitem Monitor platzieren AWT, Swing, JavaFX & SWT 5
R Kleine Panels auf einem großen Panel frei platzieren AWT, Swing, JavaFX & SWT 11
T Markierten Mausbereich erfassen, Text beim Cursor platzieren AWT, Swing, JavaFX & SWT 6
C JLabel in JMenuBar frei platzieren AWT, Swing, JavaFX & SWT 2
O JList platzieren AWT, Swing, JavaFX & SWT 4
S Bild auf JWindow platzieren AWT, Swing, JavaFX & SWT 4
M JFrame in der Mitte platzieren. AWT, Swing, JavaFX & SWT 6
B Zwei "gleiche" Objekte auf einem Frame platzieren AWT, Swing, JavaFX & SWT 2

Ähnliche Java Themen


Oben