I'm trying to build a simple panel which I will throw some fields onto and capture some user data. I typically use a combination of GridBagLayouts (thanks to trashgod) and BoxLayouts to achieve the layout I want. I normally don't have any issues with using them and they just do what makes intuitive sense 99% of the time, but I can't seem to make this rather simple panel function properly. Can anyone tell me why?
The panel class:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class EmailPanel extends JPanel {
private JButton m_OkButton;
private JPanel m_MainPanel;
private JTextField m_ServerIPTF;
private JTextField m_ServerPortTF;
private JTextField m_DomainNameTF;
private JTextField m_UnitNameTF;
private JTextField m_Recipient1TF;
private JTextField m_Recipient2TF;
private final Dimension LARGE_TEXTFIELD_SIZE = new Dimension(125, 25);
public EmailPanel() {
init();
}
private void init() {
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel tPanel;
JLabel tLabel;
Header: {
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(Box.createHorizontalGlue());
tLabel = new JLabel("Email Settings");
tPanel.add(tLabel);
tPanel.add(Box.createHorizontalGlue());
tPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 3, 0, Color.red));
this.add(tPanel);
}
MainPanel: {
m_MainPanel = new JPanel();
m_MainPanel.setLayout(new BoxLayout(m_MainPanel, BoxLayout.Y_AXIS));
m_MainPanel.add(Box.createVerticalStrut(5));
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(Box.createHorizontalStrut(3));
tLabel = new JLabel("Server IP Address:");
tPanel.add(tLabel);
tPanel.add(Box.createHorizontalStrut(3));
m_ServerIPTF = new JTextField();
m_ServerIPTF.setMinimumSize(LARGE_TEXTFIELD_SIZE);
m_ServerIPTF.setMaximumSize(LARGE_TEXTFIELD_SIZE);
m_ServerIPTF.setPreferredSize(LARGE_TEXTFIELD_SIZE);
tPanel.add(m_ServerIPTF);
tPanel.add(Box.createHorizontalStrut(25));
tLabel = new JLabel("Server Port");
tPanel.add(tLabel);
tPanel.add(Box.createHorizontalStrut(3));
m_ServerPortTF = new JTextField();
m_ServerPortTF.setMinimumSize(LARGE_TEXTFIELD_SIZE);
m_ServerPortTF.setMaximumSize(LARGE_TEXTFIELD_SIZE);
m_ServerPortTF.setPreferredSize(LARGE_TEXTFIELD_SIZE);
tPanel.add(m_ServerPortTF);
tPanel.add(Box.createHorizontalGlue());
m_MainPanel.add(tPanel);
m_MainPanel.add(Box.createVerticalStrut(5));
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(Box.createHorizontalStrut(6));
tLabel = new JLabel("Domain Name:");
tPanel.add(tLabel);
tPanel.add(Box.createHorizontalStrut(3));
m_DomainNameTF = new JTextField();
m_DomainNameTF.setMinimumSize(LARGE_TEXTFIELD_SIZE);
m_DomainNameTF.setMaximumSize(LARGE_TEXTFIELD_SIZE);
m_DomainNameTF.setPreferredSize(LARGE_TEXTFIELD_SIZE);
tPanel.add(m_DomainNameTF);
tPanel.add(Box.createHorizontalGlue());
m_MainPanel.add(tPanel);
this.add(m_MainPanel);
}
OKButton: {
m_OkButton = new JButton("Ok");
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(Box.createHorizontalGlue());
tPanel.add(m_OkButton);
tPanel.add(Box.createHorizontalGlue());
this.add(tPanel);
}
this.add(Box.createVerticalGlue());
}
}
If you add this to / use this as a content pane, you will see that there are large gaps on the Y axis between the various controls. I'm under the impression that the vertical glue that I add at the end of the init method should grow to consume all the space below the OK button, and the controls would be pushed together as a consequence. What I'm seeing is that it seems to be splitting up the space evenly between the various instances of my temporary JPanel object tPanel and the vertical glue at the bottom. How do I make it stop doing that?
Edit: It seems that the behavior is the same both with and without the somewhat superfluous m_MainPanel object.
This is what I see when it renders and the form is made larger than needed for the controls. I would expect the vertical glue to fill the space below the OK button to keep the controls on the top of the form.
I copy-pasted your code and added the main method:
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new EmailPanel());
frame.pack();
frame.setVisible(true);
}
This is the result:
with or without the line this.add(Box.createVerticalGlue());
Is this what you wanted or not?
Edit: Solution
I edited your code to achieve the desired result:
public class EmailPanel extends JPanel {
private JButton okButton;
private JTextField serverIPTF;
private JTextField serverPortTF;
private JTextField domainNameTF;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new EmailPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setMinimumSize(frame.getPreferredSize());
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public EmailPanel() {
init();
}
private void init() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel tPanel;
JLabel tLabel;
// Header
tLabel = new JLabel("Email Settings", JLabel.CENTER);
tLabel.setAlignmentX(CENTER_ALIGNMENT);
tLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, tLabel.getPreferredSize().height));
tLabel.setBorder(BorderFactory.createMatteBorder(0, 0, 3, 0, Color.red));
add(tLabel);
// Fields
JPanel fieldsPanel = new JPanel();
fieldsPanel.setLayout(new BoxLayout(fieldsPanel, BoxLayout.Y_AXIS));
fieldsPanel.setBorder(BorderFactory.createMatteBorder(5, 3, 5, 3, new Color(0, 0, 255, 255)));
// Top fields
serverIPTF = new JTextField(10);
serverIPTF.setMaximumSize(serverIPTF.getPreferredSize());
serverPortTF = new JTextField(10);
serverPortTF.setMaximumSize(serverPortTF.getPreferredSize());
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(new JLabel("Server IP Address:"));
tPanel.add(Box.createRigidArea(new Dimension(3, 0)));
tPanel.add(serverIPTF);
tPanel.add(Box.createRigidArea(new Dimension(25, 0)));
tPanel.add(new JLabel("Server Port"));
tPanel.add(Box.createRigidArea(new Dimension(3, 0)));
tPanel.add(serverPortTF);
tPanel.add(Box.createHorizontalGlue());
fieldsPanel.add(tPanel);
fieldsPanel.add(Box.createRigidArea(new Dimension(0, 5)));
// Lower field
domainNameTF = new JTextField(10);
domainNameTF.setMaximumSize(domainNameTF.getPreferredSize());
tPanel = new JPanel();
tPanel.setLayout(new BoxLayout(tPanel, BoxLayout.X_AXIS));
tPanel.add(new JLabel("Domain Name:"));
tPanel.add(Box.createRigidArea(new Dimension(3, 0)));
tPanel.add(domainNameTF);
tPanel.add(Box.createHorizontalGlue());
fieldsPanel.add(tPanel);
add(fieldsPanel);
// OK Button
okButton = new JButton("OK");
okButton.setAlignmentX(CENTER_ALIGNMENT);
add(okButton);
}
}
Explanation:
BoxLayout says:
When a BoxLayout lays out components from top to bottom, it tries to size each component at the component's preferred height. If the vertical space of the layout does not match the sum of the preferred heights, then BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components. Any extra space appears at the bottom of the container.
(emphasis mine)
Which tells us that if we restrict the components' maximum height to their preferred height, all the extra vertical space will go to the bottom, just as you want. Hence, we added for all the text fields (the labels do not grow vertically) the line:
nameTF.setMaximumSize(nameTF.getPreferredSize());
and we don't need any vertical glue.
Notes:
I created the text fields with 10 columns, you can change this value.
The top label does not need horizontal glue to stretch it, just relax the maximum width constraint and set the alignment (similarly to the bottom button).
Instead of creating a lot of rigid areas (you used struts), I created a border with the appropriate widths. It is blue for visual purposes, but you should set its alpha to 0 to make is transparent.
Use createRigidArea instead of createXXXStrut (see the note in the above link).
I used frame.setMinimumSize(frame.getPreferredSize()) to not let the window resize to a smaller size than its contents. This is optional.
Non-final fields and variables should not use underscore (_) in the name according to Java naming conventions.
You did not specify horizontal stretching behavior, so it does whatever it does.
I still think that box layout is not the best approach here, or at least do not allow resizing of the window at all (so to not deal with extra space).
Related
I am working on an application using the Swing GUI widget in Java and am having issues with stretching panels vertically within a panel. My main panel is using the BorderLayout and the problem is in the Center Region. I am using a Panel with a BoxLayout.X_AXIS and inside of it additional Panels with a BoxLayout.Y_AXIS are inserted. I am unable to stretch it vertically from top to bottom. I also want the contents to start from the top to the bottom. I have tried using the GridLayout and it does exactly what I want, however I am constrained width wise because all of the columns are equivalent size and I want some panels to have a smaller width. I have looked at the API, tutorials, and searched Googled for an answer. Any help would be great!
Attached are the code and the screenshot with the layouts.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.*;
import java.awt.Color;
public class Colors
{
private JFrame frame;
private JPanel contentPane;
public static void main (String[] args){
Colors gui = new Colors();
gui.start();
}
public void start(){
frame = new JFrame("Words");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = (JPanel)frame.getContentPane();
contentPane.setLayout(new BorderLayout(8,8));
center();
east();
frame.pack();
frame.setVisible(true);
}
private void center(){
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel,BoxLayout.X_AXIS));
//centerPanel.setLayout(new GridLayout(1,3));
centerPanel.setPreferredSize(new Dimension(300,0));
centerPanel.setBackground(Color.BLUE);
JLabel oneLabel,twoLabel,threeLabel;
JPanel panelOne = new JPanel();
panelOne.setLayout(new BoxLayout(panelOne,BoxLayout.Y_AXIS));
panelOne.setBackground(Color.CYAN);
oneLabel = new JLabel(" First Label First Column ");
panelOne.add(oneLabel);
twoLabel = new JLabel(" Second Label First Column ");
panelOne.add(twoLabel);
threeLabel = new JLabel(" Third Label First Column ");
panelOne.add(threeLabel);
centerPanel.add(panelOne);
JPanel panelTwo = new JPanel();
panelTwo.setLayout(new BoxLayout(panelTwo,BoxLayout.Y_AXIS));
panelTwo.setBackground(Color.YELLOW);
oneLabel = new JLabel(" 10 ");
panelTwo.add(oneLabel);
twoLabel = new JLabel(" 20 ");
panelTwo.add(twoLabel);
threeLabel = new JLabel(" 30 ");
panelTwo.add(threeLabel);
centerPanel.add(panelTwo);
JPanel panelThree = new JPanel();
panelThree.setLayout(new BoxLayout(panelThree,BoxLayout.Y_AXIS));
panelThree.setBackground(Color.GREEN);
oneLabel = new JLabel(" 10 ");
panelThree.add(oneLabel);
twoLabel = new JLabel(" 20 ");
panelThree.add(twoLabel);
threeLabel = new JLabel(" 30 ");
panelThree.add(threeLabel);
centerPanel.add(panelThree);
contentPane.add(centerPanel, BorderLayout.CENTER);
}
private void east(){
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
panel.setPreferredSize(new Dimension(100,150));
panel.setBackground(Color.RED);
JPanel labelPanel = new JPanel();
labelPanel.setBackground(Color.WHITE);
labelPanel.setMaximumSize(new Dimension(26,24));
panel.add(labelPanel);
labelPanel = new JPanel();
labelPanel.setBackground(Color.GREEN);
labelPanel.setMaximumSize(new Dimension(26,24));
panel.add(labelPanel);
contentPane.add(panel, BorderLayout.EAST);
}
}
I have tried using the GridLayout and it does exactly what I want, however I am constrained width wise because all of the columns are equivalent size and I want some panels to have a smaller width
You can try using the GridBagLayout. Each column will be the width of the largest component in the column.
Read the section from the Swing tutorial on How to Use GridBagLayout for more information and working examples.
Another option might be to use a JTable. A JTable allows you to display data in a row/column format. The above tutorial also has a section on How to Use Tables.
I guess this is a simple question... basically it's about layout considerations. So let consider the code below, I get this:
.
public class TestCode_Web {
public static void main(String[] args) {
JFrame window = new JFrame("Test");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 300);
// Inner panel ---------------------------------------------------------
JPanel innerPanel = new JPanel(new BorderLayout());
innerPanel.setBackground(new Color(250, 250, 200));
window.add(innerPanel);
// Northern panel ------------------------------------------------------
JPanel panelN = new JPanel(new BorderLayout());
JLabel labelN = new JLabel("Label");
panelN.add(labelN, BorderLayout.WEST);
panelN.setBackground(new Color(200, 250, 250));
innerPanel.add(panelN, BorderLayout.NORTH);
// Center panel --------------------------------------------------------
JPanel panelC = new JPanel();
panelC.setBackground(new Color(250, 200, 250));
JPanel panelCheckBoxes = new JPanel(new GridLayout(0, 1));
final JCheckBox c1 = new JCheckBox("C1");
final JCheckBox c2 = new JCheckBox("C2");
final JCheckBox c3 = new JCheckBox("C3");
panelCheckBoxes.add(c1);
panelCheckBoxes.add(c2);
panelCheckBoxes.add(c3);
int width = panelCheckBoxes.getPreferredSize().width;
int height = panelCheckBoxes.getPreferredSize().height;
panelCheckBoxes.setPreferredSize(new Dimension(width, height));
panelC.add(panelCheckBoxes);
innerPanel.add(panelC, BorderLayout.CENTER);
// Southern panel --------------------------------------------------------
JPanel panelS = new JPanel(new BorderLayout());
JLabel labelS = new JLabel(String.valueOf(width) + "/" + String.valueOf(height));
panelS.add(labelS, BorderLayout.WEST);
panelS.setBackground(new Color(250, 250, 200));
innerPanel.add(panelS, BorderLayout.SOUTH);
// ...
window.setVisible(true);
}
}
What I would like is to have this:
How could I achieve that ? I guesss there are several ways, I'm waiting for your diverse proposals...
One way to do this would be to overwrite the getPreferredSize() method of panelCheckBoxes to return panelC's width. This way, panelCheckBoxes' size will automatically adapt to the width of panelC.
final JPanel panelC = new JPanel();
// [...]
JPanel panelCheckBoxes = new JPanel(new GridLayout(0, 1)) {
public Dimension getPreferredSize() {
return new Dimension(panelC.getWidth(),
super.getPreferredSize().height);
}
};
For accessing panelC inside the anonymous inner class, it has to be final (i.e., after initialization, the panelC variable can not be assigned a new value, which is no problem in your case).
Just setting the preferredSize at that point in the constructor will not work, since (1) the size is not known yet, and (2) it might change when the window is resized. You could, however, use setPreferredSize after the call to window.setVisible(true);, when panelC got a size:
// after window.setVisible(true);
panelCheckBoxes.setPreferredSize(new Dimension(panelC.getWidth(),
panelCheckBoxes.getHeight()));
However, note that this way panelCheckBoxes still won't resize when you resize the window.
If you just want the checkboxes to be aligned to the left (but not necessarily stretch over the whole width), a simpler way would be to put panelC into the WEST container of the BorderLayout. Assuming that the colors are only for debugging and in the end everything will be the same color, you won't see a difference.
Finally, for more complex layouts you might want to check out GridBadLayout. It takes some getting used to, but once mastered, it's worth the effort.
In the first tab of the sample program: In the first row the components are r and l justified in their cells. In the second row the cell is spanned and pushed to the right.
All of the excess space in the first row is given to cell 0,0 which contains the component labelled "20".
Tab "Two" improves the situation by using pushx. The widget looked centered but that is not what I want.
But how do I give all the excess space to cell 0, 1 (the cell containing the component labelled "30")? I tried posting an image of what I want to accomplish but the system disallowed that. Hopefully, my verbal explanation is clear enough.
package test1;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class Main extends JTabbedPane {
public Main() {
addTab("One", createPanel1());
addTab("Two", createPanel2());
}
public static void main(String[] args) {
final JFrame frame = new JFrame("Test MigLayout");
Main main = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(main);
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.pack();
frame.setVisible(true);
frame.setBounds(200, 200, 800, 500);
}
});
}
private JPanel createPanel1() {
JPanel panel = new JPanel(new MigLayout("hidemode 3, debug", "[r][l]"));
JTextField textField1 = new JTextField("20", 20);
JTextField textField2 = new JTextField("30", 30);
JButton button = new JButton("Button");
panel.add(textField1);
panel.add(textField2, "wrap");
panel.add(button, "span 2, pushx");
return (panel);
}
private JPanel createPanel2() {
JPanel panel = new JPanel(new MigLayout("hidemode 3, debug", "[r][l]"));
JTextField textField1 = new JTextField("20", 20);
JTextField textField2 = new JTextField("30", 30);
JButton button = new JButton("Button");
panel.add(textField1);
panel.add(textField2, "pushx, wrap");
panel.add(button, "span 2, pushx");
return (panel);
}
}
Was astonished that any cell was growing horizontally, because the default is not to. Until re-reading the doc for push:
Makes the row and/or column that the component is residing in grow
with "weight". This can be used instead of having a "grow" keyword in
the column/row constraints
Using it in the spanning cell of the button effectively applies a grow constraint to the first column of the span. Without knowing your exact goal, it's hard to advise anything except saying: don't :-) One option might be to explicitly grow the second column:
JPanel panel = new JPanel(new MigLayout("hidemode 3, debug, wrap 2", "[r][l, grow]"));
JTextField textField1 = new JTextField("20", 20);
JTextField textField2 = new JTextField("30", 30);
JButton button = new JButton("Button");
panel.add(textField1);
panel.add(textField2);
panel.add(button, "span");
As an aside: I always recommend to define constraints as high up in the hierarchy (layout > row/column > component) as possible - following DRY :-)
I want to create a JInternalFrame with some components in it.
My aim is to design a bash console in Java.
My frame is made of 4 components:
JTextArea included into a JScrollPane
JLabel with the text "Cmd:"
JTextField
JButton with the text "Send"
And I have the following code:
Box box = Box.createHorizontalBox();
box.add(Box.createVerticalStrut(5));
box.add(this.cmd_label);
box.add(Box.createVerticalStrut(5));
box.add(this.cmd_input);
box.add(Box.createVerticalStrut(5));
box.add(this.submit);
box.add(Box.createVerticalStrut(5));
Box mainBox = Box.createVerticalBox();
mainBox.add(Box.createHorizontalStrut(5));
mainBox.add(this.result_scroll);
mainBox.add(Box.createHorizontalStrut(5));
mainBox.add(box);
mainBox.add(Box.createHorizontalStrut(5));
add(mainBox);
So when the frame has not been maximized, I have a correct look:
But when I maximize it, all components are incorrectly located:
So, here is my question: How can I set a weight to the components to fix their location every time, or, how can I fix it?
Thanks.
I think this would be better done with a BorderLayout. In a BorderLayout, the component specified as the center component will expand to fill as much space as possible, and the other components will remain at their preferred sizes.
int hgap = 5;
int vgap = 5;
internalFrame.getContentPane().setLayout(new BorderLayout(hgap, vgap));
internalFrame.getContentPane().add(this.result_scroll, BorderLayout.CENTER);
JPanel bottomPanel = new JPanel();
bottomPanel.add(this.cmd_label);
bottomPanel.add(this.cmd_input);
bottomPanel.add(this.submit);
internalFrame.getContentPane().add(bottomPanel, BorderLayout.SOUTH);
Here try this code, is this behaviour exceptable :
import java.awt.*;
import javax.swing.*;
public class LayoutExample
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("LAYOUT EXAMPLE");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BorderLayout(5, 5));
centerPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
JTextArea tarea = new JTextArea(10, 10);
tarea.setBackground(Color.DARK_GRAY.darker());
tarea.setForeground(Color.WHITE);
tarea.setCaretColor(Color.WHITE);
tarea.setLineWrap(true);
JScrollPane scrollPane = new JScrollPane(tarea);
centerPanel.add(scrollPane, BorderLayout.CENTER);
JPanel footerPanel = new JPanel();
footerPanel.setLayout(new BorderLayout(5, 5));
footerPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
JLabel cmdLabel = new JLabel("Cmd : ");
JTextField tfield = new JTextField(10);
JPanel buttonPanel = new JPanel();
buttonPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
JButton sendButton = new JButton("SEND");
footerPanel.add(cmdLabel, BorderLayout.LINE_START);
footerPanel.add(tfield, BorderLayout.CENTER);
buttonPanel.add(sendButton);
footerPanel.add(buttonPanel, BorderLayout.LINE_END);
frame.getContentPane().add(centerPanel, BorderLayout.CENTER);
frame.getContentPane().add(footerPanel, BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new LayoutExample().createAndDisplayGUI();
}
});
}
}
OUTPUT :
Base problem here is what I consider a bug in JTextField's max layout hint: it's unbounded in both horizontal and vertical dimension. The latter is pure nonsense for a component designed for showing a single line of text. To fix, subclass and let it return its pref for the height, like:
JTextField cmdInput = new JTextField() {
#Override
public Dimension getMaximumSize() {
Dimension max = super.getMaximumSize();
max.height = getPreferredSize().height;
return max;
}
};
As BoxLayout respects maxSize, the excess height now will be given to the top box only.
On the long run, consider switching to a third party manager which allows fine-tuning in a all-in-one-panel approach. Yeah, here comes my current favourite: MigLayout. Compare the following lines to all the nesting and border tricks above and have fun :-)
MigLayout layout = new MigLayout("wrap 3, debug",
"[][grow, fill][]", // 3 columns, middle column filled and allows growing
"[grow, fill][]"); // two rows, first filled and allows growing
JComponent content = new JPanel(layout);
// the scrollPane in the first row spanning all columns
// and growing in both directions
content.add(new JScrollPane(new JTextArea(20, 20)), "span, grow");
// auto-wrapped to first column in second row
content.add(new JLabel("Cmd:"));
content.add(new JTextField());
content.add(new JButton("Submit"));
Here is my problem
How can I get rid of the gap from the inner rectangle box (it is actually the border of the middle JPanel)?
The outter rectangle is a extends JCompoment. Inside it contains three JPanels. Each of them use GridLayout. I even try to setHgap to a negative value in the big rectangle, but it doesn't change anything.
Edit: Sorry the question is not clear. I do want the border, but I don't want the gap between the inner border and outer border. If there is no gap in between, the whole rectangle will represent a class diagram class.
You may mean this way:
import java.awt.*;
import javax.swing.*;
public class GridBadFrame {
private JFrame frame;
private JPanel pnlCenter;
private JPanel pnl1;
private JPanel pnl2;
private JPanel pnl3;
public GridBadFrame() {
pnl1 = new JPanel();
pnl1.setBackground(Color.red);
pnl2 = new JPanel();
pnl2.setBackground(Color.blue);
pnl3 = new JPanel();
pnl3.setBackground(Color.red);
JLabel lblWest = new JLabel();
lblWest.setPreferredSize(new Dimension(50, 150));
JLabel lblEast = new JLabel();
lblEast.setPreferredSize(new Dimension(50, 150));
JLabel lblNorth = new JLabel();
lblNorth.setPreferredSize(new Dimension(600, 50));
JLabel lblSouth = new JLabel();
lblSouth.setPreferredSize(new Dimension(600, 50));
pnlCenter = new JPanel();
pnlCenter.setBackground(Color.black);
pnlCenter.setLayout(new java.awt.GridLayout(3, 0, 10, 10));
pnlCenter.setPreferredSize(new Dimension(600, 400));
pnlCenter.add(pnl1);
pnlCenter.add(pnl2);
pnlCenter.add(pnl3);
frame = new JFrame();
frame.add(pnlCenter, BorderLayout.CENTER);
frame.add(lblNorth, BorderLayout.NORTH);
frame.add(lblSouth, BorderLayout.SOUTH);
frame.add(lblWest, BorderLayout.WEST);
frame.add(lblEast, BorderLayout.EAST);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
GridBadFrame gridBadFrame = new GridBadFrame();
}
});
}
}
it is actually the border of the middle JPanel
If it is the border, remove that (setBorder(null)).
I think if you try setBorderPainted(false) it may get rid of the unwanted border.
The issue is probably to do with the preferred height and width set by the GridLayout on the JPanel.
Excerpt from the documentation:
The preferred width of a grid layout is the largest preferred width of
any of the components in the container times the number of columns,
plus the horizontal padding times the number of columns plus one, plus
the left and right insets of the target container.
The preferred height of a grid layout is the largest preferred height
of any of the components in the container times the number of rows,
plus the vertical padding times the number of rows plus one, plus the
top and bottom insets of the target container.