可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a little issue with the GridBag Layout Manager. I am trying to display 9 panels like this:
To do so, I separated the Grid like this:
For the panels 1 to 7 there is no problem, they show up just as I want. But the issue starts with the panels S8
and S9
. As you can see, the S8
and S9
takes up half the frame, but I can't make it display like this. The S8
ends at the start of S4
, and the S9
begins at the end of S4
, I cannot handle the half space.
Only way I figured out is to put the S8
and S9
panel in another panel which takes all the frame width - but surely there must be a proper way to display these two panels without putting them in another panel!
Here is the code:
workzone.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.weightx = 0.5;
c.weighty = 0.5;
c.insets = new Insets(0,0,0,0);
//S1
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 2;
c.gridheight = 2;
workzone.add(S1, c);
//S2
c.gridx = 2;
c.gridy = 0;
c.gridwidth = 2;
c.gridheight = 1;
workzone.add(S2, c);
//S3
c.gridx = 2;
c.gridy = 1;
c.gridwidth = 2;
c.gridheight = 1;
workzone.add(S3, c);
//S4
c.gridx = 4;
c.gridy = 0;
c.gridwidth = 2;
c.gridheight = 2;
workzone.add(S4, c);
//S5
c.gridx = 7;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
workzone.add(S5, c);
//S6
c.gridx = 7;
c.gridy = 1;
c.gridwidth = 2;
c.gridheight = 1;
workzone.add(S6, c);
//S7
c.gridx = 8;
c.gridy = 0;
c.gridwidth = 2;
c.gridheight = 2;
workzone.add(S7, c);
//S8
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 5;
c.gridheigth = 1;
workzone.add(S8, c);
//S9
c.gridx = 6;
c.gridy = 2;
c.gridwidth = 5;
c.gridheight = 1;
workzone.add(S9, c);
Any ideas and propositions are welcome !
回答1:
Good question. It took me little to crack it, but I got it. Normally, I would have put setions 1-7 in a top panel, and sections 8-9 in a bottom panel, but I liked the challange of 1 panel with GBL. [bored]
The problem is that section 4 (column indexes 4 and 5) is not well-defined for GBL, so section 8 doesn't know how far out to go to cover it's fifth column (index 4) so it then just stops after column index 3.
So, I added 2 zero-height spacers in the columns that make up section 4 and it worked. Comment out the 2 lines marked SPACERS to see what I mean:
EDIT: added fix suggested by @SheridanVespo
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridBagDemo2 implements Runnable
{
private Color[] colors = {Color.BLACK, Color.BLUE, Color.CYAN, Color.GRAY,
Color.GREEN, Color.MAGENTA, Color.ORANGE,
Color.PINK, Color.RED, Color.YELLOW};
private JPanel panel;
private GridBagConstraints gbc;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new GridBagDemo2());
}
public void run()
{
panel = new JPanel(new GridBagLayout());
gbc = new GridBagConstraints();
add(0,0, 2,2, "1");
add(2,0, 2,1, "2");
add(2,1, 2,1, "3");
add(4,0, 2,2, "4");
add(6,0, 2,1, "5");
add(6,1, 2,1, "6");
add(8,0, 2,2, "7");
add(0,2, 5,1, "8");
add(5,2, 5,1, "9");
// SPACERS: define the 2 columns that is section "4"
add(4,3, 1,1, "");
add(5,3, 1,1, "");
JFrame frame = new JFrame("Grig Bag");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
private void add(int x, int y, int colspan, int rowspan, String name)
{
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = colspan;
gbc.gridheight = rowspan;
gbc.weightx = .1;
gbc.weighty = .1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.BOTH;
// using another panel for illustrative purposes only
JPanel p = new JPanel();
if (!name.equals(""))
{
gbc.weightx = 1; // @SheridanVespo fix
int index = Integer.parseInt(name);
JLabel label = new JLabel("Panel " + name);
p.add(label);
p.setBackground(colors[index]);
panel.add(p, gbc);
}
else
{
gbc.weightx = 0.5; // @SheridanVespo fix
gbc.weighty = 0; // don't allow the spacer to grow
gbc.fill = GridBagConstraints.NONE;
panel.add(Box.createHorizontalGlue(), gbc);
}
}
}
回答2:
The accepted answer is appealing, but it causes section 4 to widen faster than the flanking panels as the frame is resized. This variation places panels 8 & 9 in a separate sub-panel of a BoxLayout
.
import java.awt.*;
import javax.swing.*;
/** @see https://stackoverflow.com/q/14755487/261156 */
public class GridBagDemo implements Runnable {
private JPanel panel;
public static void main(String[] args) {
SwingUtilities.invokeLater(new GridBagDemo());
}
@Override
public void run() {
JFrame frame = new JFrame("GridBag");
frame.setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
panel = new JPanel(new GridBagLayout());
add(1, 0, 0, 1, 2);
add(2, 1, 0, 1, 1);
add(3, 1, 1, 1, 1);
add(4, 2, 0, 1, 2);
add(5, 3, 0, 1, 1);
add(6, 3, 1, 1, 1);
add(7, 4, 0, 1, 2);
frame.add(panel);
panel = new JPanel(new GridBagLayout());
add(8, 0, 0, 1, 1);
add(9, 1, 0, 1, 1);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void add(int i, int x, int y, int w, int h) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;
gbc.weightx = .1;
gbc.weighty = .1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.BOTH;
JPanel p = new JPanel();
p.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
p.add(new JLabel("Panel " + i));
p.setBackground(Color.getHSBColor((i - 1) / 9f, 0.75f, 0.95f));
panel.add(p, gbc);
}
}
回答3:
I never been a big fan of GridBagLayout. So for me I would break your GUI down into multiple panels and would probably use multiple GridLayout to achieve what you want. Something like:
JPanel top = new JPanel( new GridLayout(0, 5) );
top.add(s1);
JPanel s23 = new JPanel( new GridLayout(2, 0) );
s23.add(s2);
s23.add(s3);
top.add(s23);
...
JPanel bottom = new JPanel( new GridLayout(0, 2) );
bottom.add(s8);
bottom.add(s9);
JPanel main = new JPanel( appropriate layout manager );
main.add(top);
main.add(bottom);
回答4:
For the last two JPanel
, I would suggest you to simply add them to a new JPanel
with GridLayout
and set this JPanel
with the GridLayout
on to the JPanel
having the GridBagLayout
. Please have a look at the code example, that resulted in actually the same output, as you were expecting :
import javax.swing.*;
import java.awt.*;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 2/7/13
* Time: 10:34 PM
* To change this template use File | Settings | File Templates.
*/
public class GridBagExample
{
private JPanel contentPane, footerPanel;
private JPanel s1, s2, s3, s4, s5, s6, s7, s8, s9;
private void displayGUI()
{
JFrame frame = new JFrame("GridBagLayout Example");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
contentPane = new JPanel();
contentPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
/*
* Constraints for S1 JPanel.
*/
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 1;
gbc.gridheight = 2;
gbc.weightx = 0.2;
gbc.weighty = 0.8;
s1 = new JPanel(new GridBagLayout());
s1.setOpaque(true);
s1.setBackground(Color.BLUE);
s1.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s1Label = new JLabel("S1", JLabel.CENTER);
s1.add(s1Label);
contentPane.add(s1, gbc);
/*
* Constraints for S2 JPanel.
*/
gbc.weighty = 0.4;
gbc.gridx = 1;
gbc.gridheight = 1;
s2 = new JPanel(new GridBagLayout());
s2.setOpaque(true);
s2.setBackground(Color.GREEN);
s2.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s2Label = new JLabel("S2", JLabel.CENTER);
s2.add(s2Label);
contentPane.add(s2, gbc);
/*
* Constraints for S3 JPanel.
*/
gbc.gridy = 1;
s3 = new JPanel(new GridBagLayout());
s3.setOpaque(true);
s3.setBackground(Color.CYAN);
s3.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s3Label = new JLabel("S3", JLabel.CENTER);
s3.add(s3Label);
contentPane.add(s3, gbc);
/*
* Constraints for S4 JPanel.
*/
gbc.weighty = 0.8;
gbc.gridx = 2;
gbc.gridy = 0;
gbc.gridheight = 2;
s4 = new JPanel(new GridBagLayout());
s4.setOpaque(true);
s4.setBackground(Color.WHITE);
s4.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s4Label = new JLabel("S4", JLabel.CENTER);
s4.add(s4Label);
contentPane.add(s4, gbc);
/*
* Constraints for S5 JPanel.
*/
gbc.weighty = 0.4;
gbc.gridx = 3;
gbc.gridheight = 1;
s5 = new JPanel(new GridBagLayout());
s5.setOpaque(true);
s5.setBackground(Color.RED);
s5.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s5Label = new JLabel("S5", JLabel.CENTER);
s5.add(s5Label);
contentPane.add(s5, gbc);
/*
* Constraints for S6 JPanel.
*/
gbc.gridy = 1;
s6 = new JPanel(new GridBagLayout());
s6.setOpaque(true);
s6.setBackground(Color.MAGENTA);
s6.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s6Label = new JLabel("S6", JLabel.CENTER);
s6.add(s6Label);
contentPane.add(s6, gbc);
/*
* Constraints for S7 JPanel.
*/
gbc.gridheight = 2;
gbc.weighty = 0.8;
gbc.gridx = 4;
gbc.gridy = 0;
s7 = new JPanel(new GridBagLayout());
s7.setOpaque(true);
s7.setBackground(Color.ORANGE);
s7.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s7Label = new JLabel("S7", JLabel.CENTER);
s7.add(s7Label);
contentPane.add(s7, gbc);
footerPanel = new JPanel();
footerPanel.setLayout(new GridLayout(1, 2, 5, 5));
s8 = new JPanel(new GridBagLayout());
s8.setOpaque(true);
s8.setBackground(Color.PINK);
s8.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s8Label = new JLabel("S8", JLabel.CENTER);
s8.add(s8Label);
footerPanel.add(s8);
s9 = new JPanel(new GridBagLayout());
s9.setOpaque(true);
s9.setBackground(Color.YELLOW);
s9.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 5));
JLabel s9Label = new JLabel("S9", JLabel.CENTER);
s9.add(s9Label);
footerPanel.add(s9, gbc);
/*
* Constraints for Footer JPanel.
*/
gbc.gridheight = 1;
gbc.gridwidth = 5;
gbc.weightx = 1.0;
gbc.weighty = 0.2;
gbc.gridx = 0;
gbc.gridy = 2;
contentPane.add(footerPanel, gbc);
frame.setContentPane(contentPane);
frame.pack();
//frame.setSize(500, 500);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
new GridBagExample().displayGUI();
}
});
}
}
Here is the Output of the above code :
回答5:
Generally, I create and add the components of a GridBagLayout in Y, X position order. I don't know if this is required, but it makes it easier for me to diagnose problems.
Here's what I came up with for your grid.
Component xPosition yPosition xWidth yHeight
--------- --------- --------- ------ -------
S1 0 0 2 2
S2 2 0 2 1
S4 4 0 2 2
S5 6 0 2 1
S7 8 0 2 2
S8 0 2 5 1
S3 2 2 2 1
S9 5 2 5 1
S6 6 2 2 1
回答6:
For the S9 component, your code is
//S9
c.gridx = 6;
c.gridy = 2;
c.gridwidth = 5;
c.gridheight = 1;
workzone.add(S9, c);
Since the coordinate system begins at 0 rather than 1, I propose the code be
//S9
c.gridx = 5; // I changed this
c.gridy = 2;
c.gridwidth = 5;
c.gridheight = 1;
workzone.add(S9, c);
回答7:
I have tried using BorderLayout
to check how it works. But just posting here .. :) This process uses multiple panels inside each other. You can try this approach if this example is comfortable.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class BorderAndGridBag {
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
new GridWithBorder().createUI();
}
};
EventQueue.invokeLater(r);
}
}
class GridWithBorder {
public void createUI() {
JFrame frame = new JFrame();
JPanel motherPanel = new JPanel(new BorderLayout());
JPanel topPanel = new JPanel();
topPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel bottomPanel = new JPanel(new BorderLayout());
bottomPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel topLeftPanel = new JPanel();
topLeftPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel topRightPanel = new JPanel();
topRightPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel topMiddlePanel = new JPanel();
topMiddlePanel.add(new JLabel("Top Middle"));
topMiddlePanel.setBorder(LineBorder.createBlackLineBorder());
JPanel bottomLeftPanel = new JPanel();
bottomLeftPanel.add(new JLabel("Bottom Left"));
bottomLeftPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel bottomRightPanel = new JPanel();
bottomRightPanel.add(new JLabel("Bottom Right"));
bottomRightPanel.setBorder(LineBorder.createBlackLineBorder());
JPanel topLeftLeft = new JPanel();
topLeftLeft.add(new JLabel("Top Left"));
topLeftLeft.setBorder(LineBorder.createBlackLineBorder());
JPanel topLeftRight = new JPanel(new BorderLayout());
JPanel topLeftRightTop = new JPanel();
topLeftRightTop.add(new JLabel("Top Left's Right Top"));
topLeftRight.setBorder(LineBorder.createBlackLineBorder());
JPanel topLeftRightBottom = new JPanel();
topLeftRightBottom.add(new JLabel("Top Left's Right Bottom"));
JPanel topRightLeft = new JPanel(new BorderLayout());
topRightLeft.setBorder(LineBorder.createBlackLineBorder());
JPanel topRightRight = new JPanel();
topRightRight.add(new JLabel("Top Right Right"));
topRightRight.setBorder(LineBorder.createBlackLineBorder());
JPanel topRightLeftTop = new JPanel();
topRightLeftTop.add(new JLabel("Top Right Left Top"));
JPanel topRightLeftBottom = new JPanel();
topRightLeftBottom.add(new JLabel("Top Right Left Bottom"));
topLeftPanel.add(topLeftLeft, BorderLayout.WEST);
// Top panel sub alignment.
topLeftPanel.add(topLeftRight, BorderLayout.EAST);
topLeftRight.add(topLeftRightTop, BorderLayout.NORTH);
topLeftRight.add(topLeftRightBottom, BorderLayout.CENTER);
topRightLeft.add(topRightLeftTop, BorderLayout.NORTH);
topRightLeft.add(topRightLeftBottom, BorderLayout.SOUTH);
topRightPanel.add(topRightLeft, BorderLayout.WEST);
topRightPanel.add(topRightRight, BorderLayout.EAST);
// Top Panel main alignment.
topPanel.add(topLeftPanel, BorderLayout.WEST);
topPanel.add(topMiddlePanel, BorderLayout.CENTER);
topPanel.add(topRightPanel, BorderLayout.EAST);
// Bottom Panel main alignment.
bottomPanel.add(bottomLeftPanel, BorderLayout.WEST);
bottomPanel.add(bottomRightPanel, BorderLayout.EAST);
motherPanel.add(topPanel, BorderLayout.NORTH);
motherPanel.add(bottomPanel, BorderLayout.CENTER);
frame.add(motherPanel);
frame.pack();
frame.setTitle("Layout Manager");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}