Put 4 JLabel at corners of a JFrame - java

As the title said, I'm trying to put 4 different JLabels at each of the corners of a JFrame. I want them to stay there forever even if I try to resize the JFrame
I've tried using a layout manager but I just can't get it right.
ImageIcon icon;
JLabel labelNW = new JLabel();
JLabel labelNE = new JLabel();
JLabel labelSW = new JLabel();
JLabel labelSE = new JLabel();
URL buttonURL = InputOutputTest.class.getResource("images/square_dot.gif");
if(buttonURL != null){
icon = new ImageIcon(buttonURL);
labelNW.setIcon(icon);
labelNE.setIcon(icon);
labelSW.setIcon(icon);
labelSE.setIcon(icon);
}
window.add(labelNW, BorderLayout.NORTH);
//window.add(labelNE, BorderLayout.EAST);
//window.add(labelSW, BorderLayout.WEST);
window.add(labelSE, BorderLayout.SOUTH);
This code takes care of the north and south of the left side. I'm probably approaching this wrong though.
I also tried GridLayout (2,2) but they weren't at the corners and there's a huge gap on the right side.

You will want to nest JPanels each using its own layout. In fact you could do this by nesting JPanels that all use BorderLayout.
Going to check if GridBagLayout can do it in one shot.... hang on...
Yep GridBagLayout does it too:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class GridBagExample {
public static void main(String[] args) {
JPanel mainPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(
0, 0, 0, 0), 0, 0);
mainPanel.add(new JLabel("Left Upper"), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.NORTHEAST;
mainPanel.add(new JLabel("Right Upper"), gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTHWEST;
mainPanel.add(new JLabel("Left Lower"), gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.SOUTHEAST;
mainPanel.add(new JLabel("Right Lower"), gbc);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
Edit
Now for the BorderLayout example:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.*;
public class BorderLayoutExample {
public static void main(String[] args) {
JPanel northPanel = new JPanel(new BorderLayout());
northPanel.add(new JLabel("North East"), BorderLayout.EAST);
northPanel.add(new JLabel("North West"), BorderLayout.WEST);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(new JLabel("South East"), BorderLayout.EAST);
southPanel.add(new JLabel("South West"), BorderLayout.WEST);
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(northPanel, BorderLayout.NORTH);
mainPanel.add(southPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("BorderLayout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}

I find that only GroupLayout gives me the control I need for precisely laid out components. This should do the trick. You need to make sure the gap in between has a very large Maximum value (i.e. Short.MAX_VALUE), but you can set the minimum and preferred sizes to whatever you want.
public class LabelFrame extends JFrame {
public LabelFrame() {
JPanel contentPane = new JPanel();
JLabel labelNW = new JLabel();
JLabel labelNE = new JLabel();
JLabel labelSW = new JLabel();
JLabel labelSE = new JLabel();
URL buttonURL = InputOutputTest.class.getResource("images/square_dot.gif");
if(buttonURL != null){
icon = new ImageIcon(buttonURL);
labelNW.setIcon(icon);
labelNE.setIcon(icon);
labelSW.setIcon(icon);
labelSE.setIcon(icon);
}
GroupLayout layout = new GroupLayout(contentPane);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addComponent(labelNW)
.addComponent(labelSW))
.addGap(20,50,Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(labelNE)
.addComponent(labelSE))
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.LEADING)
.addComponent(labelNW)
.addComponent(labelNE))
.addGap(20,50,Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(labelSW)
.addComponent(labelSE))
);
contentPane.setLayout(layout);
setContentPane(contentPane);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
LabelFrame frame = new LabelFrame();
frame.setVisible(true);
}
});
}
}

I've tried using a layout manager..
Layout managers are wonderful at what they do, but are perhaps the wrong tool for this job. Consider using a custom border instead. Here is an example.

Related

Vertically center GridBagLayout like BoxLayout

I am trying to center components using a GridBagLayout in the same manner that a Box centers components when you use Box.createVerticalGlue(). I initially did use a vertical Box:
Box box = Box.createVerticalBox();
box.add(Box.createVerticalGlue());
box.add(add);
box.add(remove);
box.add(edit);
box.add(Box.createVerticalGlue());
JPanel internalPanel = new JPanel(new BorderLayout());
internalPanel.add(keywordsScrollPane, BorderLayout.CENTER);
internalPanel.add(box, BorderLayout.EAST);
But as you can see, it looks sloppy because my buttons are different sizes:
I decided to switch to GridBagLayout so I can utilize GridBagConstraints.fill. This approach fixes my button width issue, but I cannot figure out how to vertically center the buttons. I changed the grid size and placed the buttons in the middle three rows, but the buttons were still appearing at the top of the panel. I tried making use of GridBagConstraints.anchor and GridBagConstraints.weighty as well. The latter almost worked, but there are very large margins between the buttons:
I am looking for the buttons to be grouped together as they were in my Box approach. How can I achieve this with a GridBadLayout?
I am using a class I created called ConstraintsBuilder which works exactly as you would expect. It's for creating GridBagContraints with nice one-liners. Here is all the (relevant) code for your viewing pleasure:
public class KeywordsDialog extends JDialog implements ActionListener, ListSelectionListener {
private JList<String> keywords;
private JScrollPane keywordsScrollPane;
private JButton add;
private JButton remove;
private JButton edit;
private Set<String> keywordsList;
public KeywordsDialog(Window parent, Collection<String> keywordsList) {
super(parent);
this.keywordsList = keywordsList == null ? new HashSet<String>() : new HashSet<String>(keywordsList);
if (keywordsList != null && !keywordsList.isEmpty()) {
this.keywords = new JList<String>(toListModel(keywordsList));
} else {
this.keywords = new JList<String>(new DefaultListModel<String>());
}
this.keywordsScrollPane = new JScrollPane(keywords);
this.add = new JButton("Add");
this.remove = new JButton("Remove");
this.edit = new JButton("Edit");
this.edit.setEnabled(false);
this.add.setEnabled(false);
ConstraintsBuilder builder = LayoutUtils.gridBagConstraintsBuilder();
JPanel internalPanel = new JPanel(new GridBagLayout());
internalPanel.add(this.keywordsScrollPane, builder.gridX(0).gridY(0).gridHeight(3).margins(0, 0, 0, 5)
.fill(GridBagConstraints.BOTH).weightX(1D).weightY(1D).build());
internalPanel.add(this.add,
builder.reset().gridX(1).gridY(0).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
internalPanel.add(this.remove,
builder.reset().gridX(1).gridY(1).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
internalPanel.add(this.edit,
builder.reset().gridX(1).gridY(2).fill(GridBagConstraints.HORIZONTAL).weightX(1D).weightY(1D).build());
this.keywords.setBorder(BorderFactory.createTitledBorder("Keywords"));
internalPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
this.setLayout(new BorderLayout());
this.add(internalPanel, BorderLayout.CENTER);
Dimension screen = GuiHelper.getScreenSize(parent);
this.setSize((int) (screen.getWidth() / 4), (int) (screen.getHeight() / 3));
this.setLocationRelativeTo(parent);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
// ...
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the How to Use GridBagLayout section.
The easiest way to create this GUI is to treat the JTextArea separately from the JButton area.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class ExampleGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ExampleGUI());
}
#Override
public void run() {
JFrame frame = new JFrame("Example GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createTextArea(), BorderLayout.CENTER);
frame.add(createButtonPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JScrollPane createTextArea() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JTextArea textArea = new JTextArea(10, 30);
textArea.setText("keyword");
panel.add(textArea, BorderLayout.CENTER);
return new JScrollPane(panel);
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 5, 5, 5);
gbc.gridy = 0;
JButton button = new JButton("Add");
panel.add(button, gbc);
gbc.gridy++;
button = new JButton("Remove");
panel.add(button, gbc);
gbc.gridy++;
button = new JButton("Edit");
panel.add(button, gbc);
return panel;
}
}
I would make the GUI simpler. Put the three buttons into a JPanel that uses a GridLayout, one declared to use 1 column and variable number of rows, one with a desired spacing between buttons, here, 5 pixels: JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 5, 5)); and then put that JPanel into the center of a another JPanel, and GridBagLayout without constraints works well for this:
JPanel sidePanel = new JPanel(new GridBagLayout());
sidePanel.add(buttonPanel);
and put that JPanel into the right side of a border layout using JPanel. For example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooSwing01 extends JPanel {
public FooSwing01() {
JTextArea textArea = new JTextArea(20, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 5, 5));
int maxButtons = 3;
for (int i = 0; i < maxButtons; i++) {
buttonPanel.add(new JButton("Button " + (i + 1)));
}
JPanel sidePanel = new JPanel(new GridBagLayout());
sidePanel.add(buttonPanel);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BorderLayout(5, 5));
add(scrollPane);
add(sidePanel, BorderLayout.LINE_END);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.add(new FooSwing01());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}

Need the following UI in Swing

I need the following UI on JFrame. Two Jlabel Vertically Left aligned. Two button horizontally below the Jlabel. I tried below code but it is coming in one row.
Label should be left and vertically aligned.
Button should cover all the width of Jframe.
import javax.swing.*;
import java.awt.*;
public class CustomPanel {
private JFrame frame = new JFrame();
private JPanel basePanel= new JPanel();
public static void main(String []args){
CustomPanel cp= new CustomPanel();
cp.showUI();
}
private void addui(){
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new GridBagLayout());
JLabel label11 = new JLabel("I am here to test");
JLabel label12 = new JLabel("I am here to test row");
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.BOTH;
labelPanel.add(label11, gbc);
gbc.gridy++;
gbc.gridwidth = 2;
labelPanel.add(label12, gbc);
basePanel.add(labelPanel);
/////////////// button panel//////////
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 2, 5, 5));
panel.add(new JButton("Click me"));
panel.add(new JButton("Click me22"));
basePanel.add(panel);
}
private void showUI(){
JFrame.setDefaultLookAndFeelDecorated(true);
addui();
frame.setAlwaysOnTop(true);
frame.setType(Window.Type.UTILITY);
frame.setResizable(true);
frame.getContentPane().setLayout(new BorderLayout());
JScrollPane scrollPane = new JScrollPane(basePanel);
scrollPane.setPreferredSize(new Dimension(400, 250));
frame.getContentPane().add(scrollPane);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.setSize(500, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
When creating a Swing GUI, you can break up a complex JPanel layout into more than one simpler JPanels. I created three JPanels for this GUI; the main JPanel, the label JPanel, and the button JPanel.
A Swing application must start with a call to the SwingUtilities invokeLater method. This method ensures that the Swing components are created and executed on the Event Dispatch Thread.
I created the JFrame and the three JPanels in separate methods. This allows me to focus on one part of the GUI at a time and makes the code much easier to read and follow. This also allows me to experiment with different Swing layout managers to see which one is appropriate for the GUI.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class CustomPanel implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CustomPanel());
}
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
panel.add(createLabelPanel(), BorderLayout.NORTH);
panel.add(createButtonPanel(), BorderLayout.SOUTH);
return panel;
}
private JPanel createLabelPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JLabel label11 = new JLabel("I am here to test");
panel.add(label11, BorderLayout.NORTH);
JLabel label12 = new JLabel("I am here to test row");
panel.add(label12, BorderLayout.SOUTH);
return panel;
}
private JPanel createButtonPanel() {
JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JButton button = new JButton("Click me");
panel.add(button);
button = new JButton("Click me22");
panel.add(button);
return panel;
}
}

Align 2 sets/items on either side of center

I'm trying to figure out the best way to align 2 sets of items in the center of a panel in a Java Swing application. The panel is in the North position of a BorderLayout whose width is determined by the JTextField in the Center position of the layout. The problem I'm having is, I have a set of labels and smaller text fields that I want to center so that the end of the label and the start of the first text field meet at the center of the panel.
I've tried GroupLayout, but ended up with the following result:
Note: The 2 text fields separated by a + are in a sub-panel.
What I'm trying to achieve is the following:
Apparently I'm either missing something, or this is far more complicated than necessary to do. I actually run into this issue a LOT! I'm surprised there isn't a special grid layout specifically for this.
Trying to do this with a GridLayout resulted in this:
So... what IS the easiest way to get the layout I'm looking for (second image)?
GroupLayout example code below:
JFrame frame = new JFrame();
JPanel panel = new JPanel(new BorderLayout());
frame.setContentPane(panel);
JPanel longText = new JPanel();
JPanel shortText = new JPanel();
JPanel mediumText = new JPanel();
longText.add(new TextField(5));
longText.add(new JLabel("+"));
longText.add(new TextField(5));
shortText.add(new TextField(5));
shortText.add(new JLabel("+"));
shortText.add(new TextField(5));
mediumText.add(new TextField(5));
mediumText.add(new JLabel("+"));
mediumText.add(new TextField(5));
JLabel lExample = new JLabel("Long text example:");
JLabel sExample = new JLabel("Short:");
JLabel mExample = new JLabel("Medium Example:");
JPanel subPanel = new JPanel();
GroupLayout layout = new GroupLayout(subPanel);
subPanel.setLayout(layout);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.CENTER)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(lExample)
.addComponent(sExample)
.addComponent(mExample))
.addGroup(layout.createParallelGroup(Alignment.TRAILING)
.addComponent(longText)
.addComponent(shortText)
.addComponent(mediumText))))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER))
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(lExample)
.addComponent(longText))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(sExample)
.addComponent(shortText))
.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
.addComponent(mExample).addComponent(mediumText))
);
JTextArea textArea = new JTextArea() {
#Override
public Dimension getPreferredSize() {
return new Dimension(600,300);
}
};
textArea.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setAutoscrolls(true);
panel.add(subPanel,BorderLayout.NORTH);
panel.add(textArea,BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
Consider using a GridBagLayout, as it gives you a lot more control over the placement of individual components and respects the preferred size of the components where it can (unless you override them through the use of the GridBagConstraints)
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class LayoutExample {
public static void main(String[] args) {
new LayoutExample();
}
public LayoutExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JLabel longText = new JLabel("Long Text Example");
JLabel shortText = new JLabel("Short Example");
JLabel medText = new JLabel("Medium Example");
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
add(longText, gbc);
addFields(gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
add(shortText, gbc);
addFields(gbc);
gbc.gridx = 0;
gbc.gridy++;
gbc.anchor = GridBagConstraints.EAST;
add(medText, gbc);
addFields(gbc);
}
protected void addFields(GridBagConstraints gbc) {
JTextField field1 = new JTextField("0", 5);
field1.setEnabled(false);
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridx++;
add(field1, gbc);
gbc.gridx++;
gbc.insets = new Insets(0, 4, 0, 4);
add(new JLabel("+"), gbc);
JTextField field2 = new JTextField(5);
gbc.gridx++;
add(field2, gbc);
}
}
}

How to make jLabels stay attached to the corners of a window form, despite resizing the form in java?

I have 4 jLabels in my java program, which i placed in 4 corners I want them to stay there despite user resizing the window. I have written the code for the labels, but cannot seem to figure out how to keep them glued to each corner.
here is my code for the jLabels
JLabel label_1 = new JLabel("");
label_1.setEnabled(false);
label_1.setBounds(0, 0, 19, 19);
contentPane.add(label_1);
JLabel label_2 = new JLabel("");
label_2.setEnabled(false);
label_2.setBounds(0, 242, 19, 19);
contentPane.add(label_2);
JLabel label_3 = new JLabel("");
label_3.setEnabled(false);
label_3.setBounds(549, 242, 19, 19);
contentPane.add(label_3);
JLabel label_4 = new JLabel("");
label_4.setEnabled(false);
label_4.setBounds(549, 0, 19, 19);
contentPane.add(label_4);
Thanks
Don't use null layouts
Don't use setBounds(...)
Do use proper layout managers. Read the Layout Manager Tutorials for all the gory details.
Note that by using a null layout and setBounds, you ham-string your application's layout to being very rigid, very difficult to debug, enhance, and modify, and you also create a GUI that might look good on your box, but likely will not look good on another box using a different OS, or even the same OS with a slightly different screen resolution.
For example, using a GridBagLayout:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout extends JPanel {
private static final int[] ANCHORS = {NORTHWEST, SOUTHWEST, NORTHEAST, SOUTHEAST};
public LabelLayout() {
setLayout(new GridBagLayout());
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i / 2;
gbc.gridy = i % 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
add(new JLabel("Label " + (i + 1)), gbc);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Labels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LabelLayout());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
A couple other notes:
I try to avoid using GridBagLayouts since they are one of the more complex layouts, but for your problem, they work nicely and simply.
Your problem can also be solved by using nested JPanels each using a simpler layout such as a BorderLayout.
Demo program, iteration number 2 that shows two GUI's, one using GridBagLayout and the other using nested JPanels, each using BorderLayout:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout {
private static final int[] ANCHORS = { NORTHWEST, NORTHEAST, SOUTHWEST,
SOUTHEAST };
private JPanel gridBagPanel = new JPanel(new GridBagLayout());
private JPanel borderPanel = new JPanel(new BorderLayout());
public LabelLayout() {
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i % 2;
gbc.gridy = i / 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
gridBagPanel.add(new JLabel("Label " + (i + 1)), gbc);
}
JPanel northPanel = new JPanel(new BorderLayout());
JPanel southPanel = new JPanel(new BorderLayout());
northPanel.add(new JLabel("Label 1"), BorderLayout.WEST);
northPanel.add(new JLabel("Label 2"), BorderLayout.EAST);
southPanel.add(new JLabel("Label 3"), BorderLayout.WEST);
southPanel.add(new JLabel("Label 4"), BorderLayout.EAST);
borderPanel.add(northPanel, BorderLayout.NORTH);
borderPanel.add(southPanel, BorderLayout.SOUTH);
}
public JPanel getGridBagPanel() {
return gridBagPanel;
}
public JPanel getBorderPanel() {
return borderPanel;
}
private static void createAndShowGui() {
LabelLayout labelLayout = new LabelLayout();
JFrame frame = new JFrame("Label GridBagLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getGridBagPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame = new JFrame("Label BorderLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getBorderPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Resizable Swing layout with buttons arranged according to variable dimensions

I would like to make a layout using Java Swing which looks like the following drawing.
(source: braun-abstatt.de)
On the left is a JPanel which is drawn through paintComponent() in a way that the graphics automatically scale when the window is resized. (The question isn't about that panel. That one's already done.)
Now I need some buttons (the black boxes, added in Photoshop for the drawing) to the right of the JPanel mentioned before. The height of the reddish areas at the top and bottom, next to which there should be just empty space, is calculated along the lines of CONSTANT_FACTOR * getHeight(). Next to each compartment on the left, there should be a group of buttons, lined up to the center of the respective compartment (see the blue lines).
The JPanel containing the buttons knows about the CONSTANT_FACTOR and the number of compartments, so it should be possible to feed this information into a layout manager.
Which layout manager would I best use to achieve this layout? I've read about all the different layout managers, but I can't quite figure out which one or which combination of them best fits in this case.
For example, by use of a different LayoutManager, a very easy and simple container, takes no more than 15-20 minutes:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ThinLineFrame {
private JFrame frame = new JFrame();
private JScrollPane scrollPane;
private JPanel panel = new JPanel();
private JPanel panelNorth = new JPanel();
private JPanel panelCenter = new JPanel();
private JPanel panelCenterCh1 = new JPanel();
private JPanel panelCenterCh2 = new JPanel();
private JPanel panelCenterCh3 = new JPanel();
private JPanel panelCenterCh4 = new JPanel();
private JPanel panelCenterCh5 = new JPanel();
private JPanel panelSouth = new JPanel();
public ThinLineFrame() {
panelNorth.setBackground(Color.red.darker());
panelNorth.setPreferredSize(new Dimension(80, 30));
//
panelCenter.setBackground(Color.darkGray);
panelCenter.setLayout(new GridLayout(5, 1, 2, 2));
//
panelCenterCh1.setLayout(new BorderLayout());
JButton panelCenterCh1Button = new JButton();
panelCenterCh1.add(panelCenterCh1Button, BorderLayout.CENTER);
//
JButton panelCenterCh2Button1 = new JButton();
JButton panelCenterCh2Button2 = new JButton();
panelCenterCh2.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh2.add(panelCenterCh2Button1);
panelCenterCh2.add(panelCenterCh2Button2);
//
JButton panelCenterCh3Button1 = new JButton();
JButton panelCenterCh3Button2 = new JButton();
panelCenterCh3.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh3.add(panelCenterCh3Button1);
panelCenterCh3.add(panelCenterCh3Button2);
//
JButton panelCenterCh4Button1 = new JButton();
JButton panelCenterCh4Button2 = new JButton();
panelCenterCh4.setLayout(new GridLayout(2, 1, 2, 2));
panelCenterCh4.add(panelCenterCh4Button1);
panelCenterCh4.add(panelCenterCh4Button2);
//
panelCenterCh5.setLayout(new BorderLayout());
JButton panelCenterCh5Button = new JButton();
panelCenterCh5.add(panelCenterCh5Button, BorderLayout.CENTER);
//
panelCenter.add(panelCenterCh1);
panelCenter.add(panelCenterCh2);
panelCenter.add(panelCenterCh3);
panelCenter.add(panelCenterCh4);
panelCenter.add(panelCenterCh5);
//
panelSouth.setBackground(Color.red.darker());
panelSouth.setPreferredSize(new Dimension(80, 30));
//
panel.setLayout(new BorderLayout(2, 2));
panel.add(panelNorth, BorderLayout.NORTH);
panel.add(panelCenter, BorderLayout.CENTER);
panel.add(panelSouth, BorderLayout.SOUTH);
//
scrollPane = new JScrollPane(panel);
frame.add(scrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(80, 600));
frame.setLocation(100, 150);
frame.pack();
frame.setVisible(true);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ThinLineFrame dlg = new ThinLineFrame();
}
});
}
}
You should try looking at MigLayout. It's a super flexible LayoutManager that is also very simple.
The code would look something like:
MigLayout layout = new MigLayout("flowy");
panel.setLayoutManager(layout);
panel.add(button1);
panel.adD(button2);
etc..
Try adding debug, flowy to the constructor to get a visual idea of what is going on.
GBC without an anchor, just with plain vanilla GridBagConstraints and preferred size.
Centered JButton with fixed size:
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MainWithFixSize {
public static void main(String[] argv) throws Exception {
JFrame frame = new JFrame();
Container container = frame.getContentPane();
GridBagLayout gbl = new GridBagLayout();
container.setLayout(gbl);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 1;
JButton component = new JButton();
component.setPreferredSize(new Dimension(25, 25));
gbl.setConstraints(component, gbc);
container.add(component);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(40, 90));
frame.pack();
frame.setVisible(true);
}
private MainWithFixSize() {
}
}

Categories

Resources