2009-06-18 16 views
3

Das Layout der Komponenten in dem Projekt, an dem ich arbeite, sah nicht korrekt aus, ich vermute, dass es einen Bug in Swing gibt. Grundsätzlich scheint es so zu sein, dass die Proportionen weightx und weighty nicht eingehalten werden, wenn die auszulegenden Zellen unterschiedliche Mindestgrößen und/oder bevorzugte Größen aufweisen. Ich ein Beispielprogramm erstellt, dies zu zeigen, ist hier die Quelle:GridBagLayout Gewicht Bug?

package com.ensoftcorp.product.simmerge.gui.swing.dialogs; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 

import javax.swing.BorderFactory; 
import javax.swing.Box; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class TestClass { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     try { 
      //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
      new TestClass(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    static final GridBagConstraints GBC_CELL = new GridBagConstraints(); 
    static final GridBagConstraints GBC_ROWEND = new GridBagConstraints(); 
    static final GridBagConstraints GBC_FILLROW = new GridBagConstraints(); 
    static { 
     GBC_CELL.anchor = GridBagConstraints.NORTHWEST; 
     GBC_CELL.weightx = 0.5; 
     GBC_CELL.fill = GridBagConstraints.BOTH; 

     GBC_ROWEND.gridwidth = GridBagConstraints.REMAINDER; 

     GBC_FILLROW.gridwidth = GridBagConstraints.REMAINDER; 
     GBC_FILLROW.weightx = 1.0; 
     GBC_FILLROW.fill = GridBagConstraints.BOTH; 
    } 

    public TestClass() { 
     JFrame frame = new JFrame(); 

     JPanel pnlContent = new JPanel(new GridBagLayout()); 
     pnlContent.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

     /* 
     * Layout "ruler" panel 
     */ 
     JPanel pnlRuler = new JPanel(new GridBagLayout()); 

     pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL); 
     pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL); 

     pnlRuler.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Layout "correct" panel 
     */ 
     JPanel pnlGoodLayout = new JPanel(new GridBagLayout()); 

     pnlGoodLayout.add(new JButton("JButton1"),GBC_CELL); 
     pnlGoodLayout.add(new JButton("JButton2"),GBC_CELL); 

     pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     pnlGoodLayout.add(new JButton("JButton3"),GBC_CELL); 
     pnlGoodLayout.add(new JButton("JButton4"),GBC_CELL); 

     pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Layout "incorrect" panel 
     */ 
     JPanel pnlBadLayout = new JPanel(new GridBagLayout()); 

     pnlBadLayout.add(new JButton("JButton1"),GBC_CELL); 
     pnlBadLayout.add(new JButton("JButton2"),GBC_CELL); 

     pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     pnlBadLayout.add(new JButton("JButton number 3 is wide"),GBC_CELL); 
     pnlBadLayout.add(new JButton("JButton4"),GBC_CELL); 

     pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Add panels to main panel 
     */ 
     pnlContent.add(pnlRuler,GBC_FILLROW); 
     pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW); 
     pnlContent.add(pnlGoodLayout,GBC_FILLROW); 
     pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW); 
     pnlContent.add(pnlBadLayout,GBC_FILLROW); 

     /* 
     * Configure frame 
     */ 
     frame.getContentPane().add(pnlContent); 
     frame.setTitle("GridBagLayout Weight Bug?"); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400,200); 
     frame.setVisible(true); 
} 

    JComponent createRulerCell(Color border, Color background) { 
     JPanel glue = new JPanel(); 
     glue.setBorder(BorderFactory.createLineBorder(border)); 
     glue.setBackground(background); 

     return glue; 
    } 

} 

Das Beispielprogramm besteht aus drei Gruppen ... die erste ein „Herrscher“ von Sorten ist die 50% -Marke zu zeigen. Die zweite und dritte Gruppe sind Panels, die ein GridBagLayout verwenden, wobei jede Zelle eine weightx von 0,5 hat. Der einzige Unterschied zwischen den Gruppen besteht in der Länge des Schaltflächen-Texts. Die zweite Gruppe verteilt die Spalten jedoch nicht gleichmäßig, obwohl sie genügend Platz dafür bietet.

Meine Frage ist dann diese: hat jemand dieses Problem vor, und haben eine Workaround, die sie empfehlen würden?

P.S. - Ich benutze jdk1.6.0_11, wenn das einen Unterschied macht.

Antwort

4

vom GridBagConstraints.weightx JavaDoc:

Gibt an, wie zusätzlichen horizontalen Raum zu verteilen.

Der Grid-Bag-Layout-Manager berechnet das Gewicht einer Spalte als maximale Gewichtung x aller Komponenten in einer Spalte. Wenn das resultierende Layout horizontal kleiner ist als der zu füllende Bereich, wird der zusätzliche Platz proportional zum Gewicht auf jede Spalte verteilt.

in diesem Sinne, ich glaube nicht, dass dies ein Fehler ist, weil die Spalte mit der breiten Taste berechnet wird, um mehr Platz zu benötigen. Sobald diese und die normalen Schaltflächenspaltengrößen berechnet sind, wird der verbleibende Platz verteilt.

Umgehung:

, dies umgehen, können Sie GBC_CELL.gridx und GBC_CELL.gridy vor dem Hinzufügen jeder der Tasten, und bevor die Schaltfläche festlegen, die die Zeile mit dem großen Knopf teilt, könnten Sie setzen

GBC_CELL.ipadx=100;

und dann auf 0 setzen, bevor der breite Knopf (# 3) hinzugefügt wird. Dies sollte Ihre Schaltflächen mehr in einem Raster ausrichten.

4

GridBagLayout ist alt und ausführlich.

In Erwägung ziehen, zu FormLayout oder zu einer kleineren Alternative zu wechseln - TableLayout.

Wenn Sie jemals HTML-Tabellen geschrieben haben, werden Sie schnell die Idee hinter diesen 2 Jungs bekommen.

2

Verwenden Sie das integrierte GroupLayout. Sie haben mehr Kontrolle als das GridBagLayout.

1

Dies könnte (source) helfen:

Wenn mehr als eine Säule mit einem Nicht-Null-Gewicht hat, wird der überschüssige Raum unter den Nicht-Null Gewicht Spalten unter Verwendung der Gewichtswerte verteilt ist. Insbesondere, wenn der Überschussraum P Pixel ist, und die Spaltengewichte für die Spalte^i ist Gewicht^i, dann erhält die Spalte^i genau (Gewicht^i * P)/ (Summe aller Spalten- Gewichte). Wenn Spalte 1 beispielsweise das Gewicht 1 hat und Spalte 2 das Gewicht 2 hat und der überschüssige Speicherplatz 90 Pixel beträgt, erhält Spalte 1 30 zusätzliche Pixel und Spalte 2 60 zusätzliche Pixel. Zeilen mit einem Nicht-Null-Gewicht verhalten sich in ähnlicher Weise.

0

Ich fand eine einfache Problemumgehung. Explizit gesetzt preferredSize.width Attribut von jedem JButton zu preferredSize.width=0.

Dies ist der Weg, es zu tun:

private JButton createButton(String text) { 
    JButton button = new JButton(text); 
    button.setPreferredSize(new Dimension(0, button.getPreferredSize().height)); 
    return button; 
} 

Hier ist Ihr modifiziertes Beispiel (ich die Änderungen mit // <============== Kommentar markiert):

public class TestClass { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     try { 
      //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
      new TestClass(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    static final GridBagConstraints GBC_CELL = new GridBagConstraints(); 
    static final GridBagConstraints GBC_ROWEND = new GridBagConstraints(); 
    static final GridBagConstraints GBC_FILLROW = new GridBagConstraints(); 
    static { 
     GBC_CELL.anchor = GridBagConstraints.NORTHWEST; 
     GBC_CELL.weightx = 0.5; 
     GBC_CELL.fill = GridBagConstraints.BOTH; 

     GBC_ROWEND.gridwidth = GridBagConstraints.REMAINDER; 

     GBC_FILLROW.gridwidth = GridBagConstraints.REMAINDER; 
     GBC_FILLROW.weightx = 1.0; 
     GBC_FILLROW.fill = GridBagConstraints.BOTH; 
    } 

    public TestClass() { 
     JFrame frame = new JFrame(); 

     JPanel pnlContent = new JPanel(new GridBagLayout()); 
     pnlContent.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 

     /* 
     * Layout "ruler" panel 
     */ 
     JPanel pnlRuler = new JPanel(new GridBagLayout()); 

     pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL); 
     pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL); 

     pnlRuler.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Layout "correct" panel 
     */ 
     JPanel pnlGoodLayout = new JPanel(new GridBagLayout()); 

     pnlGoodLayout.add(createButton("JButton1"),GBC_CELL); // <============== 
     pnlGoodLayout.add(createButton("JButton2"),GBC_CELL); // <============== 

     pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     pnlGoodLayout.add(createButton("JButton3"),GBC_CELL); // <============== 
     pnlGoodLayout.add(createButton("JButton4"),GBC_CELL); // <============== 

     pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Layout "incorrect" panel 
     */ 
     JPanel pnlBadLayout = new JPanel(new GridBagLayout()); 

     pnlBadLayout.add(createButton("JButton1"),GBC_CELL); // <============== 
     pnlBadLayout.add(createButton("JButton2"),GBC_CELL); // <============== 

     pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     pnlBadLayout.add(createButton("JButton number 3 is wide"),GBC_CELL); // <============== 
     pnlBadLayout.add(createButton("JButton4"),GBC_CELL); // <============== 

     pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND); 

     /* 
     * Add panels to main panel 
     */ 
     pnlContent.add(pnlRuler,GBC_FILLROW); 
     pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW); 
     pnlContent.add(pnlGoodLayout,GBC_FILLROW); 
     pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW); 
     pnlContent.add(pnlBadLayout,GBC_FILLROW); 

     /* 
     * Configure frame 
     */ 
     frame.getContentPane().add(pnlContent); 
     frame.setTitle("GridBagLayout Weight Bug?"); 

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setSize(400,200); 
     frame.setVisible(true); 
    } 

    JComponent createRulerCell(Color border, Color background) { 
     JPanel glue = new JPanel(); 
     glue.setBorder(BorderFactory.createLineBorder(border)); 
     glue.setBackground(background); 

     return glue; 
    } 

    private JButton createButton(String text) { 
     JButton button = new JButton(text); 
     button.setPreferredSize(new Dimension(0, button.getPreferredSize().height)); 
     return button; 
    } 

} 

Und das ist, wie das Ergebnis aussieht. Sehen? Jetzt ist der Raum gleichmäßig verteilt:

enter image description here

enter image description here