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);
}
}
Lass Dir doch mal die Größe der beiden Komponenten ausgeben. Diese ist vermutlich 0x0.[JAVA=14] tabbedPane.setBounds(0, 0, this.getWidth(), this.getHeight());
button.setBounds(this.getWidth()-button.getWidth(), 0, button.getWidth(), 19);[/code]
this.getWidth()
Um dieses Problem auszuschließen, habe ich es auch schon mit fixen Werten ausprobiert: auch hier wird nichts angezeigt...Lass Dir doch mal die Größe der beiden Komponenten ausgeben. Diese ist vermutlich 0x0.
z.B. liefert0 solange die Komponente noch nicht angezeigt wird.Code:this.getWidth()
Aber genau das fehlt dem LayeredPane. Etwas ohne Position und Ausmaß sieht man auf einem Null Layout eben nicht.damit setBounds überhaupt funktioniert.
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.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...
Das hat auch nichts gebracht.Würde der Component ein BorderLayout geben, damit der LayeredPane die gesamte Fläche einnimmt.
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);
}
}
Ja, das war eigentlich auch der Plan: damit man mit der Klasse schneller zurecht kommt.Du überschreibst anscheinend die setSize-Methode der JLayeredPane
Hmm. Gut, da habe ich keinerlei Erfahrung... - vlt. könnte man noch ein super.setSize() einbauen?da kann man sich ziemlich viel kaputt machen!
Au, das wäre nett!Ggf. werde ich es später nochmal genauer ansehen.
component.setSize(10,10);
if (component.getWidth() != 10) throw SomethingWrongException("Aaaahhh");
@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);
}
});
}
}
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.Die einzige einigermaßen "saubere" Lösung, die mir einfallen würde, wäre
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:@die üblichen Verdächtigen (Andre & Co) : Hat noch jemand eine "bessere" Idee?
Was genau meinst du mit Client-Bereich?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?
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
}
});
}
Der Client-Bereich eines Fenster ist der Bereich des Fensters ohne Titelleiste und Rahmen.Was genau meinst du mit Client-Bereich?
Ah, ok. Sehr interessant. Dank für die Info.Da steht ja kein 'this' 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.
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.Aber allgemein: Um in so einem Fall auf die Äußere Klasse (bzw. Instanz) zu verweisen, muss manverwenden.Code:JTabRowButton.this.getWidth()
Stichwort ContentPane, die wurde mit Java 1.5 leider ein bisschen "versteckt"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.
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());