2014-09-28 10 views
8

Ich versuche GridBagLayout zu verwenden, aber ich habe nicht, was ich erwarte, und ich kann nicht den Fehler in diesem Code finden:Java GridBagLayout funktioniert nicht

public class GridBagEx1 extends JPanel { 

    private static final long serialVersionUID = 1L; 

    protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c) { 
     JButton button = new JButton(name); 
     gridbag.setConstraints(button, c); 
     add(button); 
    } 

    public void init() { 
     GridBagLayout gridbag = new GridBagLayout(); 
     GridBagConstraints c = new GridBagConstraints(); 
     setLayout(gridbag); 

     c.fill = BOTH; 

     c.weightx = 1.0; 
     c.weighty = 1.0; 

     c.anchor = CENTER; 

     c.insets.top = 5; 
     c.insets.bottom = 5; 
     c.insets.left = 5; 
     c.insets.right = 5; 

     c.gridx = 0; 
     c.gridy = 0; 
     c.gridheight = 1; 
     c.gridwidth = 2; 
     makebutton("Button1", gridbag, c);  

     c.gridx = 2; 
     c.gridy = 0; 
     c.gridheight = 1; 
     c.gridwidth = 1; 
     makebutton("Button2", gridbag, c); 

     c.gridx = 3; 
     c.gridy = 0; 
     c.gridheight = 2; 
     c.gridwidth = 2; 
     makebutton("Button3", gridbag, c); 

     c.gridx = 0; 
     c.gridy = 1; 
     c.gridheight = 1; 
     c.gridwidth = 1; 
     makebutton("Button4", gridbag, c); 

     c.gridx = 1; 
     c.gridy = 1; 
     c.gridheight = 1; 
     c.gridwidth = 2; 
     makebutton("Button5", gridbag, c); 

     c.gridx = 0; 
     c.gridy = 2; 
     c.gridheight = 1; 
     c.gridwidth = 1; 
     makebutton("Button6", gridbag, c); 

     c.gridx = 1; 
     c.gridy = 2; 
     c.gridheight = 1; 
     c.gridwidth = 2; 
     makebutton("Button7", gridbag, c); 

     c.gridx = 3; 
     c.gridy = 2; 
     c.gridheight = 1; 
     c.gridwidth = 1; 
     makebutton("Button8", gridbag, c); 

     c.gridx = 4; 
     c.gridy = 2; 
     c.gridheight = 1; 
     c.gridwidth = 1; 
     makebutton("Button9", gridbag, c); 
    } 

    public static void main(String args[]) { 
     JFrame frame = new JFrame(); 
     GridBagEx1 ex1 = new GridBagEx1(); 

     ex1.init(); 

     frame.add(ex1); 
     frame.pack(); 
     frame.setVisible(true); 
    } 
} 

Dieses Bild veranschaulicht, was ich brauche:

Programmers love paint

Gelb sind Tastennamen, rot sind Zeilen- und Spalten.

Dies ist, was wirklich passiert: Whats wrong here?

Kann mir jemand erklären, was in meinem Code falsch?

+4

ich das Problem noch nicht erklären kann, aber sagen, dass Ihre Frage sehr gut präsentiert Danke und 1+. –

+0

@HovercraftFullOfEels Danke – Emax

+0

'c.fill = BOTH;' sollte 'c.fill = GridBagConstraints.BOTH;' sein und für 'c.anchor = CENTER;' gleich sein, damit der Code kompiliert werden kann. – user1803551

Antwort

6

Das Problem ist, dass nichts die zweite Rasterspalte (gridx = 1) davon überzeugen kann, eine beliebige Breite zu haben, da es in der zweiten Spalte keine nur -Komponente geben muss. Die zweite Spalte hat also eine Breite von 0, also obwohl Button1 die ersten beiden Spalten überspannt, sieht das nicht so aus, weil die gesamte Breite von der ersten Spalte erfüllt wird; und obwohl Button5 und Button7 die zweite und dritte Spalte überspannen, wird ihre gesamte Breite von der dritten Spalte erfüllt.

Um es zu beheben, müssen Sie die Knöpfe überreden, die breiter sein sollten (1, 5, 7), um mehr Platz zu nehmen. Hier habe ich diesen Buttons Padding hinzugefügt, indem ich c.ipadx = 35; gesetzt habe. (I entfernt auch die weightx = 1.0 Einschränkung aus Gründen ich verstehe nicht ganz, es nicht funktioniert, wenn das war links in..):

screenshot

Quelle:

public void init() { 
    GridBagLayout gridbag = new GridBagLayout(); 
    GridBagConstraints c = new GridBagConstraints(); 
    setLayout(gridbag); 

    c.fill = c.BOTH; 

    //c.weightx = 1.0; 
    //c.weighty = 1.0; 

    c.anchor = c.CENTER; 

    c.insets.top = 5; 
    c.insets.bottom = 5; 
    c.insets.left = 5; 
    c.insets.right = 5; 

    c.gridx = 0; 
    c.gridy = 0; 
    c.gridheight = 1; 
    c.gridwidth = 2; 
    c.ipadx = 35; 
    makebutton("Button1", gridbag, c); 

    c.gridx = 2; 
    c.gridy = 0; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.ipadx = 0; 
    makebutton("Button2", gridbag, c); 

    c.gridx = 3; 
    c.gridy = 0; 
    c.gridheight = 2; 
    c.gridwidth = 2; 
    c.ipadx = 0; 
    makebutton("Button3", gridbag, c); 

    c.gridx = 0; 
    c.gridy = 1; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.ipadx = 0; 
    makebutton("Button4", gridbag, c); 

    c.gridx = 1; 
    c.gridy = 1; 
    c.gridheight = 1; 
    c.gridwidth = 2; 
    c.ipadx = 35; 
    makebutton("Button5", gridbag, c); 

    c.gridx = 0; 
    c.gridy = 2; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.ipadx = 0; 
    makebutton("Button6", gridbag, c); 

    c.gridx = 1; 
    c.gridy = 2; 
    c.gridheight = 1; 
    c.gridwidth = 2; 
    c.ipadx = 35; 
    makebutton("Button7", gridbag, c); 

    c.gridx = 3; 
    c.gridy = 2; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.ipadx = 0; 
    makebutton("Button8", gridbag, c); 

    c.gridx = 4; 
    c.gridy = 2; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.ipadx = 0; 
    makebutton("Button9", gridbag, c); 
} 

Bearbeiten: Wie in den Kommentaren erwähnt, ist der obige Ansatz nicht geeignet, da es verhindert, dass das Layout dynamisch in der Größe geändert wird. Um das Layout zu erweitern, um die Größe seines Containers zu füllen, werden die weightx und weighty Einschränkungen benötigt, aber dann erhält die zweite Spalte keine Breite.

Hier ist ein Versuch, eine Alternative Lösung. Es ist ein schmutziger Hack, der eine unsichtbare Komponente am unteren Rande der zweiten Spalte fügt die Spalte zu zwingen Breite zu haben:

c.gridx = 1; 
    c.gridy = 3; 
    c.gridheight = 1; 
    c.gridwidth = 1; 
    c.insets.set(0, 0, 0, 0); 
    c.weighty = 0; 
    add(Box.createRigidArea(new Dimension(50, 0)), c); 

Dieser meistert ziemlich gut, wenn das Fenster wegen der Größe verändert wird, obwohl die Komponente eine feste Anfangsgröße gegeben ist GridBagLayout skaliert es proportional zu den anderen Komponenten. Es ist jedoch immer noch nicht perfekt. Vielleicht gibt es eine bessere Lösung, aber ich kann es nicht finden.

+0

Kann ich den Quellcode sehen? – Emax

+0

@ FilipB.Vondrášek Ich denke nicht, dass _dies_ ein besonderer Fall mit einem bestimmten (ziemlich komplexen) Layout-Manager _sums up_ und rechtfertigt, dass Swing ein Greuel ist. Sure Swing hat seine Vor- und Nachteile, aber es ist nicht so, als wäre es ein Geheimnis, das weiß jeder. – icza

+0

@Emax hinzugefügt – Boann

2

ich es geschafft, die benötigt Layout ohne Hack und unterstützt dynamische Größenanpassung von JGoodies FormLayout mit gestalten:

import java.awt.Component; 

import javax.swing.JButton; 
import javax.swing.JPanel; 

import com.jgoodies.forms.factories.FormFactory; 
import com.jgoodies.forms.layout.ColumnSpec; 
import com.jgoodies.forms.layout.FormLayout; 
import com.jgoodies.forms.layout.RowSpec; 

public class FormLayoutPanel extends JPanel 
    { 
    public FormLayoutPanel() 
     { 
     setAlignmentY(Component.BOTTOM_ALIGNMENT); 
     setAlignmentX(Component.RIGHT_ALIGNMENT); 
     setLayout(new FormLayout(new ColumnSpec[] { 
      ColumnSpec.decode("41px:grow"), 
      FormFactory.LABEL_COMPONENT_GAP_COLSPEC, 
      ColumnSpec.decode("25px:grow"), 
      FormFactory.LABEL_COMPONENT_GAP_COLSPEC, 
      ColumnSpec.decode("41px:grow"), 
      FormFactory.LABEL_COMPONENT_GAP_COLSPEC, 
      ColumnSpec.decode("41px:grow"), 
      FormFactory.LABEL_COMPONENT_GAP_COLSPEC, 
      ColumnSpec.decode("41px:grow"), }, 
      new RowSpec[] { 
       RowSpec.decode("25px:grow"), 
       FormFactory.LINE_GAP_ROWSPEC, 
       RowSpec.decode("25px:grow"), 
       FormFactory.LINE_GAP_ROWSPEC, 
       RowSpec.decode("25px:grow"), })); 

     JButton button1 = new JButton("1"); 
     add(button1, "1, 1, 3, 1, fill, fill"); 
     JButton button2 = new JButton("2"); 
     add(button2, "5, 1, fill, fill"); 
     JButton button3 = new JButton("3"); 
     add(button3, "7, 1, 3, 3, fill, fill"); 
     JButton button4 = new JButton("4"); 
     add(button4, "1, 3, fill, fill"); 
     JButton button5 = new JButton("5"); 
     add(button5, "3, 3, 3, 1, fill, fill"); 
     JButton button6 = new JButton("6"); 
     add(button6, "1, 5, fill, fill"); 
     JButton button7 = new JButton("7"); 
     add(button7, "3, 5, 3, 1, fill, fill"); 
     JButton button8 = new JButton("8"); 
     add(button8, "7, 5, fill, fill"); 
     JButton button9 = new JButton("9"); 
     add(button9, "9, 5, fill, fill"); 
     } 
    } 
+0

Ich werde diese Lösung versuchen, danke für Ihre Hilfe! – Emax