I'm trying to design a JButton (an "Ok" button) that to look good has to be horizontally centered in the containing JFrame.
I'm using the GUI Builder with the Free Form layout (GroupLayout).
I've taken several GUI builder tutorials (http://netbeans.org/kb/docs/java/quickstart-gui.html) but haven't found this topic. In other gui builders (delphi) this can be done by removing the anchors from both edges.
GroupLayout does support centering of components. It is a very capable
layout manager. I personally put it after the MigLayout manager and before
the FormLayout manager.
In the following three examples, we have a panel and a button. The button
is horizontally centered.
Centering with NetBeans Builder
To center a component using a Netbeans Builder, we need to create
horizontal resizable gaps from both sides of the button.
The green area of the screenshot is a currently selected gaps. The strings
inside the gaps suggest that it is a resizable gap.
The gaps are automatically added when we place components on the form.
To define a gap to be resizable, we right click on the gap and select
the "Edit Layout Space" option. We get the following dialog:
To get a resizable gap, we check the Resizable check box.
Centering manually by using a parallel group
Components can be centered in the parallel group by passing
the GroupLayout.Alignment.CENTER parameter.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GroupLayoutCenter extends JFrame {
public GroupLayoutCenter() {
initUI();
setTitle("Centered button");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateGaps(true);
gl.setAutoCreateContainerGaps(true);
JPanel pnl = new JPanel();
pnl.setBorder(BorderFactory.createEtchedBorder());
JButton btn = new JButton("Button");
gl.setHorizontalGroup(gl.createParallelGroup(CENTER)
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutCenter ex = new GroupLayoutCenter();
ex.setVisible(true);
}
});
}
}
Centering manually by using gaps
This solution is what NetBeans generated code does. We place
two resizable gaps to the left and right sides of the button.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GroupLayoutCenter2 extends JFrame {
public GroupLayoutCenter2() {
initUI();
setTitle("Centered button");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateGaps(true);
gl.setAutoCreateContainerGaps(true);
JPanel pnl = new JPanel();
pnl.setBorder(BorderFactory.createEtchedBorder());
JButton btn = new JButton("Button");
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addGroup(gl.createSequentialGroup()
.addGap(5, 100, Short.MAX_VALUE)
.addComponent(btn)
.addGap(5, 100, Short.MAX_VALUE))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(pnl, DEFAULT_SIZE, 200, DEFAULT_SIZE)
.addComponent(btn)
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutCenter2 ex = new GroupLayoutCenter2();
ex.setVisible(true);
}
});
}
}
If you want your component to remain centered in its container if the container is resized, you have several options available to you, but I don't think that GroupLayout is one of them (please correct me if I'm wrong). One way is to change the container's layout to GridBagLayout, and then simply add the JButton into it without any constraints.
Try GridbagLayout See this
Try another LayoutManager!
GroupLayout is very obscure when just looking at the code generated by NetBeans.
If you used DesignGridLayout then what you need is as simple as:
DesignGridLayout layout = new DesignGridLayout(container);
layout.row().center().add(okButton);
javax.swing.Box.Filler can be used to pad space around a component inside a GroupLayout. In NetBeans Matisse (GUI Builder) they're called 'Horizontal Strut' under the 'Swing Fillers' section of the palette. Just put one on either side of your button, size them to fill all the empty space between the button and the edge of the container, and make sure they're both flagged to Auto Resize Horizontally.
As for using another LayoutManager, I know people don't like GroupLayout because it is not conducive to manual coding. That is by design. As the docs say, GroupLayout is intended to be used by GUI builders. So as long as you're ok with tying yourself to using NetBeans & Matisse for the life of your GUI, GroupLayout is really the best option.
Related
I built a great GUI using the frowned upon null layout (I defined a lot of constants and used a window resize listener to make it easy). Everything worked perfectly until I started using a new computer. Now, the component's are not positioned properly (from the picture you can see that the components are offset down and right). After researching the problem I learned that layout managers make sure that the components are positioned properly throughout different machines. Because of this, I would like to start rebuilding the GUI in an actual layout manager. The problem is that I often feel limited in the way I position components when attempting to use an actual layout manager.
For anyone who is curious, I was originally using a dell inspiron laptop with windows 10, and have moved to an Asus Laptop (I don't know the actual model, but the touch screen can detach from the keyboard), also with windows 10.
My question:
Which layout manager would be the fastest and easiest to build the GUI shown in the picture above (out of the stock Swing Layouts and others). I would like this layout to respect the components' actual sizes for only a few but not all of the components. Using this layout, how would I go about positioning the inventory button (the hammer at the bottom left) so that the bottom left corner of the inventory button is 5 pixels up and right from the bottom left corner of the container, even after resizing the container?
Thanks in advance. All help is appreciated.
EDIT: The "go find a key" and "Attempt to force the door open" options should have their sizes respected.
The simplest solution that comes to my mind is a BorderLayout for the main panel. Add the textarea to NORTH / PAGE_START. Make another BorderLayout containing the inventory button (WEST / LINE_START) and the location label (EAST / LINE_END). Add that to SOUTH / PAGE_END of the main BorderLayout. Then just add a BoxLayout with vertical alignment to the main BorderLayout's CENTER containing the two buttons. Here's a tutorial for the standard layout managers.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class Example {
public Example() {
JTextArea textArea = new JTextArea("There is a locked door");
textArea.setRows(5);
textArea.setBorder(BorderFactory.createLineBorder(Color.GRAY));
textArea.setEditable(false);
WhiteButton button1 = new WhiteButton("Go find a key") {
#Override
public Dimension getMinimumSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(200, 25);
}
};
WhiteButton button2 = new WhiteButton("Attempt to force the door open");
button2.setMargin(new Insets(0, 60, 0, 60));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(button1);
buttonPanel.add(Box.createVerticalStrut(5));
buttonPanel.add(button2);
WhiteButton inventoryButton = new WhiteButton(
new ImageIcon(new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB)));
JLabel locationLabel = new JLabel("Location: 0");
locationLabel.setVerticalAlignment(JLabel.BOTTOM);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(inventoryButton, BorderLayout.WEST);
southPanel.add(locationLabel, BorderLayout.EAST);
JPanel mainPanel = new JPanel(new BorderLayout(0, 5));
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.add(textArea, BorderLayout.NORTH);
mainPanel.add(buttonPanel);
mainPanel.add(southPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
private class WhiteButton extends JButton {
public WhiteButton() {
setBackground(Color.WHITE);
}
public WhiteButton(String text) {
this();
setText(text);
}
public WhiteButton(ImageIcon icon) {
this();
setIcon(icon);
setBorder(BorderFactory.createLineBorder(Color.GRAY));
}
}
}
This has probably been answered here, but my searches drew up a blank, perhaps I am looking for the wrong thing.
How can I stop a JTextArea and a JTextField from stretching? Does swing provide a panel spacer of some sort which I can add that will be stretched before any other elements will?
I have a JPanel which fills a JFrame with a set size. It uses a BoxLayout set to PAGE_AXIS. If I add a JTextArea with size 3,100 it ignores these row/columns sizes and fills all the available space.
Similarly I have a JPanel with a GridLayout. If I add a JTextField, rather than be the size in columns that I specify, it fills the entire space in the grid.
Edit: The drawing below shows what I would like (at the top) and what I get.
Few words directly from documentation on How to Use GridLayout
A GridLayout object places components in a grid of cells. Each component takes all the available space within its cell, and each cell is exactly the same size. If the GridLayoutDemo window is resized, the GridLayout object changes the cell size so that the cells are as large as possible, given the space available to the container.
GridLayout doesn't consider the size of the component. It tries to fit the component in available space in rows and columns.
Try to avoid setting size explicitly. There is a very good post about Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing? that can help you to design it in a better way.
There are lots of layout managers that can fit as per your requirements. Please have a look at How to Use Various Layout Managers
You can use GridBagLayout instead of GridLayout to divide the components in rows and columns just like table layout that gives you more control on grid width, height, margin, padding, column, rows etc.
You cannot do serious layouts withe GridLayout or BoxLayout. Forget
about them.
The first question is: Are you sure you don't want the JTextArea and JTextField to grow? It is a standard in UI that these components are growing and shrinking; the first one in both directions and the second one horizontally.
Anyway, I post solutions for GroupLayout and MigLayout, which are
the managers I highly recommend.
a) Solution with GroupLayout
Each component has three sizes: minimum, preferred, and maximum. These
are set to some sensible defaults for each component. This is why the
JTextField tends to grow horizontally; its maximum value is set to a
very large number.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class GroupLayoutStretchingEx extends JFrame {
public GroupLayoutStretchingEx() {
initUI();
}
private void initUI() {
JTextArea area = new JTextArea(12, 20);
area.setBorder(BorderFactory.createEtchedBorder());
JLabel input = new JLabel("Input");
JTextField textField = new JTextField(15);
createLayout(area, input, textField);
setTitle("Stretching");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup(GroupLayout.Alignment.TRAILING)
.addComponent(arg[0], GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGroup(gl.createSequentialGroup()
.addComponent(arg[1])
.addComponent(arg[2], GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0], GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addGroup(gl.createParallelGroup()
.addComponent(arg[1])
.addComponent(arg[2], GroupLayout.DEFAULT_SIZE,
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
GroupLayoutStretchingEx ex = new GroupLayoutStretchingEx();
ex.setVisible(true);
});
}
}
In GroupLayout, you need to set the correct values for the maximum
component size in the addComponent() method.
JTextArea area = new JTextArea(12, 20);
By setting the number of rows and columns for the JTextArea, we
set a preffered size for this component. This value is later used
by the layout manager in its calculations.
b) Solution with MigLayout
In MigLayout, we control the resizement of the components with various
constraints, such as fill, grow, or push. By not using them, the
components do not grow.
package com.zetcode;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MigLayoutStretchingEx extends JFrame {
public MigLayoutStretchingEx() {
initUI();
}
private void initUI() {
JTextArea area = new JTextArea(12, 20);
area.setBorder(BorderFactory.createEtchedBorder());
JLabel input = new JLabel("Input");
JTextField textField = new JTextField(15);
createLayout(area, input, textField);
setTitle("MigLayout example");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
setLayout(new MigLayout());
add(arg[0], "wrap");
add(arg[1], "split 2");
add(arg[2], "growx");
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MigLayoutStretchingEx ex = new MigLayoutStretchingEx();
ex.setVisible(true);
});
}
}
And here is the screenshot:
In My code I just set the number of columns
JTextField data = new JTextField();
data.setColumns(30);
I building a quite complicated GUI using Swing, and have come across a alignment issue that I need help with. The code below is a simplified version of the situation I have, in order to make the problem clearer.
Basically I'm wondering it there is a possibility to align a JComponent with a JComponent that has a different parent component? I am aware that I could insert invisible Box components in order to solve this, but I don't think this is a good solution for several reasons.
In the code below, I want the Child to be the same size and vertically aligned with the Niece (basically have Child in the same position as Niece, just in a row below it). Underneath Sister should just be empty space.
Is there someway to get the left alignment of Niece relative to the main content pane, and set the left alignment of Child to be the same?
Code:
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import java.awt.Container;
import javax.swing.JComponent;
import javax.swing.GroupLayout;
import javax.swing.JTextField;
import java.awt.Dimension;
public class Test extends JFrame {
public static void main(String args[]) {
new Test();
}
public Test() {
JTabbedPane tabPane = new JTabbedPane();
JTextField edPane1 = new JTextField("Sister");
JTextField edPane2 = new JTextField("Child");
JTextField tabEdPane = new JTextField("Niece");
edPane1.setPreferredSize(new Dimension(300, 100));
edPane2.setPreferredSize(new Dimension(300, 100));
tabEdPane.setPreferredSize(new Dimension(300, 100));
tabPane.addTab("Tab", tabEdPane);
Container contPane = getContentPane();
GroupLayout layout = new GroupLayout(contPane);
setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(
layout.createParallelGroup()
.addGroup(layout.createSequentialGroup()
.addComponent(edPane1)
.addComponent(tabPane))
.addComponent(edPane2)
);
layout.setVerticalGroup(
layout.createSequentialGroup()
.addGroup(layout.createParallelGroup()
.addComponent(edPane1)
.addComponent(tabPane))
.addComponent(edPane2)
);
setTitle("Title");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
Any suggestions of a solution might be helpful!
EDIT: This is what it should look like:
Here I want to add buttons as per 4-3-3 formation in football but i am getting 3-3-3. how can i put 4 buttons in one row??
I have been referral to this site: https://weblogs.java.net/blog/tpavek/archive/2006/02/getting_to_know_2.html
Code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import static javax.swing.GroupLayout.Alignment.*;
class Abc extends JFrame
{
JButton b[];
Abc()
{
b=new JButton[11];
JPanel jp=new JPanel();
for(int i=0;i<b.length;i++)
{
b[i]=new JButton();
}
GroupLayout layout=new GroupLayout(jp);
jp.setLayout(layout);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(LEADING)
.addComponent(b[0])
.addComponent(b[1])
.addGroup(layout.createSequentialGroup())
.addComponent(b[2])
.addComponent(b[3]))
.addGroup(layout.createParallelGroup(LEADING)
.addComponent(b[4])
.addComponent(b[5])
.addGroup(layout.createSequentialGroup())
.addComponent(b[6]))
.addComponent(b[7])
.addGroup(layout.createParallelGroup(LEADING)
.addComponent(b[8])
.addComponent(b[9])
.addGroup(layout.createSequentialGroup())
.addComponent(b[10]))
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(BASELINE)
.addComponent(b[0])
.addComponent(b[4])
.addComponent(b[8]))
.addGroup(layout.createParallelGroup(BASELINE)
.addComponent(b[1])
.addComponent(b[5])
.addComponent(b[9]))
.addGroup(layout.createParallelGroup(BASELINE)
.addComponent(b[2])
.addComponent(b[3])
.addComponent(b[6])
.addComponent(b[10]))
.addComponent(b[7])
);
setTitle("kuvh b");
setSize(1000,1000);
for(int i=0;i<11;i++)
{
add(b[i]);
}
add(jp);
pack();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(
"javax.swing.plaf.metal.MetalLookAndFeel");
// "com.sun.java.swing.plaf.motif.MotifLookAndFeel");
//UIManager.getCrossPlatformLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
new Abc().setVisible(true);
}
});
}
}
I want to make a structure of 4-3-3 formation with this. Please help me
The code is resulting in 3-3-3 formation. there are 3 buttons on third row but i want 4 how can i do this please help
See the output:
[1]:
http://imgur.com/jxADf2t
i hope i will find my solution as far as possible
I've found two ways to do something like you want; centering the buttons turns out to be something that Swing does not make as easy as it might, but then centering components is probably not as common as other alignments.
You can center components in a FlowLayout; the disadvantage in a FlowLayout is that, if the user shrinks the window to the point the components no longer fit, the layout wraps the components. This is very useful for some things, but not for your football players. I've wrapped my example in a scrollpane so this won't happen.
The other way to center components is with GroupLayout, but GroupLayout is not good for the overall layout you are trying to achieve. GroupLayout is intended for use where you have overall rows and columns in which to line things up, and your four lines of football players are not lined up that way vertically, only horizontally. But you can use the centering characteristic of GroupLayout to do the horizontal centering, and make a separate GroupLayout for each line.
My example uses FlowLayout for the first line, and GroupLayout for the second, just to show how it could be done. I did not address the problem of the gap that appears between the players' lines when the window is made large enough. Especially for examples, I do not use the style of tacking method invocations onto other method invocations and constructors; I think the deeply nested parentheses and non-straightforward logic of this style makes it more difficult to figure out (or keep track of) what's going on.
You can use GridBagLayout to center things, also, but I don't use it at all if anything else will do what I need.
I hope this answers your question.
package grouplayout;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Main2 extends JFrame
{
public static void main(String ... arguments)
{
Main2 main2 = new Main2();
main2.createUI();
main2.setVisible(true);
}
public void createUI()
{
JPanel wingPanel = new JPanel();
FlowLayout flowLayout = new FlowLayout();
flowLayout.setHgap(35);
wingPanel.setLayout(flowLayout);
JButton btnone = new JButton("Lwing");
JButton btntwo = new JButton("center");
JButton btnthr = new JButton("Rwing");
wingPanel.add(btnone);
wingPanel.add(btntwo);
wingPanel.add(btnthr);
// -------------------------------------------
JButton mid1 = new JButton("mid1");
JButton mid2 = new JButton("mid2");
JButton mid3 = new JButton("mid3");
JButton mid4 = new JButton("mid4");
JPanel midfieldPanel = new JPanel();
GroupLayout groupLayout = new GroupLayout(midfieldPanel);
GroupLayout.SequentialGroup horizontalGroup = groupLayout.createSequentialGroup();
groupLayout.setHorizontalGroup(horizontalGroup);
horizontalGroup.addComponent(mid1);
horizontalGroup.addComponent(mid2);
horizontalGroup.addComponent(mid3);
horizontalGroup.addComponent(mid4);
GroupLayout.SequentialGroup verticalGroup = groupLayout.createSequentialGroup();
groupLayout.setVerticalGroup(verticalGroup);
GroupLayout.ParallelGroup midButtonGroup = groupLayout.createParallelGroup(GroupLayout.Alignment.CENTER);
midButtonGroup.addComponent(mid1);
midButtonGroup.addComponent(mid2);
midButtonGroup.addComponent(mid3);
midButtonGroup.addComponent(mid4);
verticalGroup.addGroup(midButtonGroup);
JPanel teamPanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(teamPanel, BoxLayout.PAGE_AXIS);
teamPanel.setLayout(boxLayout);
teamPanel.add(wingPanel);
teamPanel.add(midfieldPanel);
JScrollPane scrollPane = new JScrollPane(teamPanel);
getContentPane().add(scrollPane);
pack();
}
}
EDIT: as requested, the below does the same thing with only GroupLayout.
There is no interaction between the two groups, because GroupLayout aligns things in columns, and your players are not in columns.
And yes, I suppose it is difficult -- GroupLayout, as I understand it, was really intended for use by GUI builder tools, not really for building UIs by hand. I personally have a supporter class or two that allows GroupLayout UIs to be built with slightly simpler logic. But in any event, I think you need to understand the building blocks:
GroupLayout allows - and requires - that you place each component in both horizontal and vertical row/column position independently; this is useful since so many UIs require rows and columns of mixed components and variable extra components.
A sequential group of components in dimension X is arranged sequentially in dimension X; a parallel group in dimension X is also arranged sequentially, but perpendicular to dimension X.
The layout maintains preferred sizes of components; row width and column height are set at the maximum preferred size of the constituent components.
The overall GroupLayout object has one vertical and one horizontal grouping; within that, sequential and parallel groups are created to create the overall layout desired.
I know the examples in the tutorial(s) I've read do not create separate variables to hold the internal sequential and parallel groups, preferring to use forms like new X().addComponent().addGroup() etc. But I think that makes it harder to understand what the code is actually doing, not easier; and the nested parentheses become their own maintenance problem. So I think this is a better way to do things, especially for those just getting started with this layout.
package grouplayout;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class Main3 extends JFrame
{
public static void main(String ... arguments)
{
Main3 main2 = new Main3();
main2.createUI();
main2.setVisible(true);
}
public void createUI()
{
JButton btnone = new JButton("Lwing");
JButton btntwo = new JButton("center");
JButton btnthr = new JButton("Rwing");
JPanel wingPanel = new JPanel();
GroupLayout wingGroupLayout = new GroupLayout(wingPanel);
GroupLayout.SequentialGroup wingHorizontalGroup = wingGroupLayout.createSequentialGroup();
wingGroupLayout.setHorizontalGroup(wingHorizontalGroup);
wingHorizontalGroup.addComponent(btnone);
wingHorizontalGroup.addComponent(btntwo);
wingHorizontalGroup.addComponent(btnthr);
GroupLayout.SequentialGroup wingVerticalGroup = wingGroupLayout.createSequentialGroup();
wingGroupLayout.setVerticalGroup(wingVerticalGroup);
GroupLayout.ParallelGroup wingButtonGroup = wingGroupLayout.createParallelGroup();
wingButtonGroup.addComponent(btnone);
wingButtonGroup.addComponent(btntwo);
wingButtonGroup.addComponent(btnthr);
wingVerticalGroup.addGroup(wingButtonGroup);
// -------------------------------------------
JButton mid1 = new JButton("mid1");
JButton mid2 = new JButton("mid2");
JButton mid3 = new JButton("mid3");
JButton mid4 = new JButton("mid4");
JPanel midfieldPanel = new JPanel();
GroupLayout groupLayout = new GroupLayout(midfieldPanel);
GroupLayout.SequentialGroup horizontalGroup = groupLayout.createSequentialGroup();
groupLayout.setHorizontalGroup(horizontalGroup);
horizontalGroup.addComponent(mid1);
horizontalGroup.addComponent(mid2);
horizontalGroup.addComponent(mid3);
horizontalGroup.addComponent(mid4);
GroupLayout.SequentialGroup verticalGroup = groupLayout.createSequentialGroup();
groupLayout.setVerticalGroup(verticalGroup);
GroupLayout.ParallelGroup midButtonGroup = groupLayout.createParallelGroup(GroupLayout.Alignment.CENTER);
midButtonGroup.addComponent(mid1);
midButtonGroup.addComponent(mid2);
midButtonGroup.addComponent(mid3);
midButtonGroup.addComponent(mid4);
verticalGroup.addGroup(midButtonGroup);
JPanel teamPanel = new JPanel();
BoxLayout boxLayout = new BoxLayout(teamPanel, BoxLayout.PAGE_AXIS);
teamPanel.setLayout(boxLayout);
teamPanel.add(wingPanel);
teamPanel.add(midfieldPanel);
JScrollPane scrollPane = new JScrollPane(teamPanel);
getContentPane().add(scrollPane);
pack();
}
}
I am developing a Java Desktop Application. In the GUI, I want that user can add as many toolbars dynamically as he wants. To implement this, the following are the things that I have done already:
Have taken a mainPanel and set its layout as BorderLayout
Then taken a topPanel and added it to the mainPanel's BorderLayout.NORTH
set the topPanel's layout as BoxLayout
Then taken 5 panels named toolbar1Panel, toolbar2Panel, ....
Afterthat, have added one toolbar to each of the toolbarPanel created in the previous steps.
Have added only one toolbarPanel i.e toolbar1Panel on the topPanel
Now there is a button named "Add" on the first toolbar which is added on the "toolbar1Panel" which in turn is added to the topPanel.
Now I have implemented the "actionPerformed()" method of the above "Add" button as follows:
// to add second toolbar Panel to the topPanel dynamically
topPanel.add(toolbar2Panel);
But the problem is that it is not working. Means there is no toolbar added to the topPanel.
Is there anything which I am missing.
The code is Netbeans Generated so I think it would only add mess for others, that's why I haven't pasted any code here.
After adding another toolbar to the BoxLayout, you may need to (re|in)?validate the panel.
I've done this repeatedly but I can't understand the logic behind the 3 or so method calls; so I just try them until I hit on the one that works:
topPanel.validate();
topPanel.invalidate();
topPanel.revalidate();
topPanel.layout();
(at least) one of those should force your GUI to re-calculate its layout, making the north panel larger and thus showing the 2nd (and successive) toolbar(s) you've added.
Without specifying the layout for the top panel, it might be assuming the incorrect one.
Adding two toolbar panels to it might just be replacing the first with the second, or ignoring the second.
Just for testing set the topPanel's layout to FlowLayout and try again.
I think you are trying to do too much before testing. the way I would approach this is to start with something very simple, for example one panel, one static label. When that appears as you expect add a toolbar with a menu item. Does that work. Then incrmentally add the pieces.
Quite likely you'll have problems with a simple case and can then figure it out, or you'll have a simple case to post here.
Alterntively, as starting point pinck some working example from the net. Cut it down and then build up to your case.
Does it help ?
Is it what you want to achieve ?
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
public class AddingToolbars {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
AddingToolbars me = new AddingToolbars();
me.initGui();
}
});
}
private JPanel topPanel;
private JPanel mainPanel;
private JFrame frame;
private void initGui() {
frame = new JFrame();
mainPanel = new JPanel(new BorderLayout());
frame.setContentPane(mainPanel);
topPanel = new JPanel();
BoxLayout bLayout = new BoxLayout(topPanel,BoxLayout.Y_AXIS);
topPanel.setLayout(bLayout);
mainPanel.add(topPanel,BorderLayout.NORTH);
JButton addButton = new JButton("Add toolbar");
mainPanel.add(addButton,BorderLayout.CENTER);
addButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
addNewToolBar();
}
});
frame.setSize(500,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
protected void addNewToolBar() {
JToolBar tb = new JToolBar();
tb.add(new JButton("b1"));
tb.add(new JButton("b2"));
tb.add(new JButton("b3"));
topPanel.add(tb);
mainPanel.validate();
}
}