Easy and Quick Layout for Java Swing - java

I really come from Web Development and I rarely do anything with Swing. However, today I am trying to achieve some simple GUI in Swing, but I'm having trouble because I don't have the time (...yeah, maybe it's rather the lack of interest because I don't see the need to learn it) on understanding GridLayout, GridBagLayout and others in deep...
So, I just want something like the following (each X is a component):
X X X X
X
And all be centered, which is already working. What I don't manage to do is to just find a Layout where I can simply arrange X Components in one row, and then only one in the next, no special alignment needs there...
What's the easiest / cleanest way of getting such a layout with Swing?

What about this:
private static JPanel createPanel() {
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
final JPanel firstRowPanel = new JPanel();
firstRowPanel.setLayout(new BoxLayout(firstRowPanel, BoxLayout.X_AXIS));
firstRowPanel.add(new JLabel("X"));
firstRowPanel.add(new JLabel("X"));
firstRowPanel.add(new JLabel("X"));
firstRowPanel.add(new JLabel("X"));
final JPanel secondRowPanel = new JPanel();
secondRowPanel.setLayout(new BoxLayout(secondRowPanel, BoxLayout.X_AXIS));
secondRowPanel.add(Box.createHorizontalGlue());
secondRowPanel.add(new JLabel("X"));
secondRowPanel.add(Box.createHorizontalGlue());
panel.add(firstRowPanel);
panel.add(secondRowPanel);
return panel;
}

Related

How to Keep JCheckBox Horizontally inside JPanel

I have a JPanel. Inside Panel I have kept one JLabel and three JCheckBox.
I want to keep all the checkBox in one line after JLabel. Here is the sample code and some screenshots.
Output 1
Output 2
When i change to X_AXIS it is coming everything in one line and when i switch to Y_AXIS then it is coming new line means vertically.
But my requirement is all the checkbox should come next line means after JLabel.
JLabel should come in line and all the checkBox should come in one line.
public class CheckBoxWithJLabel {
public static void main(String[] args) {
JFrame f= new JFrame("CheckBox Example");
JPanel panel = new JPanel();
panel.setBounds(40,80,600,200);
JCheckBox chk_Embrodary=new JCheckBox("Embrodary");
JCheckBox chk_Cutting=new JCheckBox("Cutting");
JCheckBox cb_Sewing=new JCheckBox("Sewing");
panel.setLayout(new javax.swing.BoxLayout(panel, javax.swing.BoxLayout.X_AXIS));
JLabel lblHeader=new JLabel("Job Work Process Selection");
panel.add(lblHeader);
panel.add(chk_Embrodary);
panel.add(chk_Cutting);
panel.add(cb_Sewing);
f.add(panel);
f.setSize(600,400);
f.setLayout(null);
f.setVisible(true);
}
}
I want this output like
this
How to solve this problem?
I would highly suggest you to have a look through the Java Swing Tutorial, especially the Laying Out Components Within a Container section, since it seems you lack some basic understanding of how Swing and its Layout Managers are supposed to be used.
Regarding your problem:
Currently, you are using a single BoxLayout, which " puts components in a single row or column". You only want that behavior for your JCheckBoxes though, and not for your JLabel. Keeping this in mind, the solution is to split up your components and to not put all of them in a single JPanel. Doing this will grant you more flexibility in how you design your GUI, since you can use multiple layouts in different nested panels.
You could do something like this (explanation in the code comments):
public static void main(String[] args) {
JFrame f = new JFrame("CheckBox Example");
// add a Y_AXIS boxlayout to the JFrames contentpane
f.getContentPane().setLayout(new BoxLayout(f.getContentPane(), BoxLayout.Y_AXIS));
JCheckBox cbEmbrodary = new JCheckBox("Embrodary");
JCheckBox cbCutting = new JCheckBox("Cutting");
JCheckBox cbSewing = new JCheckBox("Sewing");
// no need to set the bounds, since the layoutmanagers will determine the size
JPanel labelPanel = new JPanel(); // default layout for JPanel is the FlowLayout
JLabel lblHeader = new JLabel("Job Work Process Selection");
labelPanel.add(lblHeader); // JPanel for the label done
// JPanel for the comboboxes with BoxLayout
JPanel cbPanel = new JPanel();
cbPanel.setLayout(new BoxLayout(cbPanel, BoxLayout.X_AXIS));
cbPanel.add(cbEmbrodary);
cbPanel.add(cbCutting);
cbPanel.add(cbSewing);
f.add(labelPanel);
f.add(cbPanel);
// No need to set the size of the JFrame, since the layoutmanagers will
// determine the size after pack()
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
Output:
Sidenotes:
Don't set fixed sizes via setSize() or setBounds() to your components. Swing is designed to be used with appropariate LayoutManagers, and if you do that, calling pack() on the JFrame before setting it visible will layout the components and determine their appropriate size. (Also, don't use null-layout for the same reasons)
If you need the JLabel to not be centered but left aligned, like in your screenshot, then use the following:
FlowLayout layout = (FlowLayout) labelPanel.getLayout();
layout.setAlignment(FlowLayout.LEFT);

Align to the limit Components in a JPanel Swing

I need to totally align components to the JTextArea components, I am currently using a BoxLayout and I already used the setAlignmentX and setHorizontalAlignment to LEFT but it's not working. Here I upload an image to make clearer what I mean. For example look at "+ Pla PLAMARC" it's clearly not aligned with the text area component.
By the moment this is the code:
//Declarations
private JLabel nomPla;
private JTextArea infoPla;
private JScrollPane textAreaScroll;
//Inside the constructor
nomPla = new JLabel();
infoPla = new JTextArea(2, 50);
textAreaScroll = new JScrollPane(infoPla);
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
nomPla.setAlignmentX(Component.LEFT_ALIGNMENT);
nomPla.setHorizontalAlignment(nomPla.LEFT);
textAreaScroll.setAlignmentX(Component.CENTER_ALIGNMENT);
this.setBorder(new EmptyBorder(new Insets(25, 25, 25, 25)));
this.add(nomPla, BorderLayout.NORTH);
this.add(textAreaScroll, BorderLayout.NORTH); //Orientacions
I am clearly telling nomPla to be on the leftside, but this is not the same as the JTextArea.
How is this done then?
I already used the setAlignmentX and
The setAlignmentX(...) needs to be applied to all the components you add to the BoxLayout if you want all to be left aligned with respect to the BoxLayout.
Edit:
I just want the labels to be on the left side, not the JTextArea components..
Then you need to use a wrapper panel for the BoxLayout Panel.
For example:
JPanel wrapper = new JPanel( new FlowLayout(FlowLayout.CENTER) );
wrapper.add(yourBoxLayoutPanel);
frame.add(wrapper);
Now all the components in the BoxLayout will be left aligned and the BoxLayout panel will be center aligned in the wrapper panel.
Layout management is about nesting panels with different layout manager to achieve you desired effect.

How to control the size of the panels

I'm learning swing gui and I get this result when I use the following code:-
The code I use :-
private void initUI() {
JTextArea visualize=new JTextArea();
visualize.setEditable(false);
//DEFINE BUTTONS....
JButton[] buttons1={addition,subtraction,division,multiplication};
JButton [] buttons2={expr,date,conversion};
JPanel numerical=new JPanel(new FlowLayout());
numerical.setPreferredSize(new Dimension(350, 50));
for(int i=0;i<buttons1.length;i++){
numerical.add(buttons1[i]);
}
numerical.setBorder(new TitledBorder("Numerical Operations"));
JPanel nonnum=new JPanel(new FlowLayout());
nonnum.setPreferredSize(new Dimension(500, 50));
for(int i=0;i<buttons2.length;i++){
nonnum.add(buttons2[i]);
}
nonnum.setBorder(new TitledBorder("Non-numerical Operations"));
JPanel operations = new JPanel(new BorderLayout(2,2));
operations.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
operations.setSize(800, 100);
operations.add(numerical,BorderLayout.WEST);
operations.add(nonnum,BorderLayout.EAST);
JTable sheet = new JTable(10,5);
add(visualize, BorderLayout.NORTH);
add(sheet,BorderLayout.SOUTH);
add(operations,BorderLayout.CENTER);
pack();
setSize(1000, 700);
setTitle("Spreadsheet Application");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
But what I really want is this:-
My questions :-
Why is the operations panel too long?
How can I change it's height?
Doesn't "operations.setSize(..)" work?
Try using GroupLayout.
I'm also new to swing gui and had similar problems - GroupLayout saved the day
JPanel complete=new JPanel();
GroupLayout gl=new GroupLayout(complete);
complete.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup() //this is parallel bcz you need components vertically
.addComponent(visualize) //you MUST add components to both horizontal and vertical groups
.addComponent(operations)
.addComponent(sheet)
);
gl.setVerticalGroup(gl.createSequentialGroup() //NOTE that this is sequential
.addComponent(visualize)
.addComponent(operations)
.addGap(50) //you can add gaps if you want
.addComponent(sheet)
);
add(complete);
Because that's how BorderLayout works, take a closer look at How to Use BorderLayout. The CENTRE position will occupy all the remaining space of the frame, where as the NORTH and SOUTH positions will try and honour the preferred sizes of the components.
You could use a GridBagLayout, which will allow you more control over the layout or use a series of compound layouts.
Something like...
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.BOTH;
add(visualize, gbc);
add(operations, gbc);
gbc.gridy = 1;
add(sheet, gbc);
It is generally discouraged to extend from a top level container like JFrame, instead you should use something like JPanel to define your UIs and then add them to the containers you want. This increases there re-usability and makes it easier to use on different containers
You may also like to take a look at How to Use Scroll Panes
SOME of us find GridBagLayout to be a royal pain, and you may not have to use it to do what you want to do.
The idea behind a layout manager is to let the layout manager control the size and position of its components so that you don't have to futz with them. MP is right, GridBag allows you a lot of control, but that also means you have to get a lot of things right to have it do what you want it to do.
So, an alternative: Make a JPanel to hold the visualize and operations panels; give this new panel a BoxLayout with a Y_AXIS orientation, then add them in the order you want them to appear, top-to-bottom.
Then put sheet in the BorderLayout.CENTER of the JFrame. In fact, I think you'll want to take MP's advice and go through a tutorial on JScrollPane; as best I remember, you create the panel, then create the JScrollPane instance with the panel as a construction parameter, then add the scrollpane instance to the JFrame (in the CENTER, in your case).
Being in the center, it will then expand and contract as the user changes window size.
Good luck. Swing takes some getting used to.

createVerticalGlue() in BoxLayout not functioning

I have used the createVerticalGlue() successfully on a number of times. However in the following screen building code it is not working. I am still wondering why.
The situation is that I have two JPanels (leftPanel, rightPanel) within another Panel (centralPanel). Each of these two panels will host two JComponents using a BoxLayout Y-Axis. I want to distribute the remaining free space before, between and after the two JComponents.
I know that I can use empty borders and rigid areas to solve the problem but it happens that I am a bit hard headed!
My appologies for the long question.
public class MemberGUI extends JFrame {
JPanel contPane = (JPanel) this.getContentPane();
JPanel centralPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JPanel lowerPanel = new JPanel();
JLabel title = new JLabel("Add/Delete Member");
JLabel nameLbl = new JLabel("Member's name");
JLabel idLbl = new JLabel ("Member ID");
JTextField nameFld = new JTextField(10);
JTextField idFld = new JTextField(10);
public void buildMe(){
//LayoutManagers
contPane.add(title,BorderLayout.PAGE_START);
contPane.add(centralPanel,BorderLayout.CENTER);
contPane.add(lowerPanel,BorderLayout.PAGE_END);
centralPanel.add(leftPanel);
centralPanel.add(rightPanel);
leftPanel.setLayout(new BoxLayout(leftPanel,BoxLayout.Y_AXIS));
rightPanel.setLayout(new BoxLayout(rightPanel,BoxLayout.Y_AXIS));
//leftPanel.add(Box.createRigidArea(new Dimension(0,50)));
leftPanel.add(Box.createVerticalGlue());
leftPanel.add(idLbl);
leftPanel.add(Box.createVerticalGlue());
leftPanel.add(nameLbl);
leftPanel.add(Box.createVerticalGlue());
//rightPanel.add(Box.createRigidArea(new Dimension(0,50)));
rightPanel.add(Box.createVerticalGlue());
rightPanel.add(idFld);
rightPanel.add(Box.createVerticalGlue());
rightPanel.add(nameFld);
rightPanel.add(Box.createVerticalGlue());
// JFrame Settings
this.setSize(500,400);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
}
afaics, centralPanel has default layoutManager, which is FlowLayout. This always sizes its children to their prefSize, so the glue never comes into play.
Nesting containers comes at a price (which nesting wizards like #Andrew happily pay :-) Also, it's not entirely trivial to get right (f.i. replace the upper textField with a comboBox to see the mis-alignment). In the longer run, there's hardly a route around learning to master a more powerful manager, like f.i. MigLayout (my current personal favorite)

Java Positioning a list on a GUI

I'm trying to add a JList to a GUI, but am wondering how to position it? I want it to appear on the right hand side of the TextArea for data that will be sent to the GUI for selection.
Can anyone suggest how to do this? Here is the code (note: very new to Java and GUI's)
protected static void createAndShowGUI() {
GUI predict = new GUI();
JFrame frame = new JFrame("Phone V1.0");
frame.setContentPane(predict.createContentPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setMinimumSize(new Dimension(300, 400));
frame.setVisible(true); // Otherwise invisible window
}
private JPanel createContentPane() {
JPanel pane = new JPanel();
TextArea = new JTextArea(5, 10);
TextArea.setEditable(false);
TextArea.setLineWrap(true);
TextArea.setWrapStyleWord(true);
TextArea.setWrapStyleWord(true);
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
//Adds the buttons from Top to Bottom
String[] items = {"dsfsdfd"};
list = new JList(items);
JScrollPane scrollingList = new JScrollPane(list);
int orient = list.getLayoutOrientation();
JPanel window = new JPanel();
pane.add(window);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(5, 3));
JButton[] buttons = new JButton[] {
new JButton("Yes"),
new JButton(""),
new JButton("Clr"),
new JButton("1"),
new JButton("2abc"),
new JButton("3def"),
new JButton("4ghi"),
new JButton("5jkl"),
new JButton("6mno"),
new JButton("7pqrs"),
new JButton("8tuv"),
new JButton("9wxyz"),
new JButton("*+"),
new JButton("0_"),
new JButton("^#")
}; // Array Initialiser
for (int i = 0; i < buttons.length; i++) {
buttonPanel.add(buttons[i]);
buttons[i].addActionListener(this);
}
pane.add(TextArea);
pane.add(list);
pane.add(buttonPanel);
return pane;
}
Read the section from the Swing tutorial on Using Layout Mananger. There is no need to only use a single layout manager. You can nest layout managers to get the desired effect.
Wrap your TextArea and list in a new panel with a BorderLayout manager. Basically the BorderLayout manager lets you arrange components using north, south, east, west and center coordinates. The components at the center takes all available space as the parent container has more space available to it.
private JPanel createContentPane() {
JPanel pane = new JPanel(); //this is your main panel
JPanel textAreaPanel = new JPanel(new BorderLayout()); //the wrapper
//Some more code...
//Then at the end
//Make your TextArea take the center
textAreaPanel.add(TextArea, BorderLayout.CENTER);
//And the list to the east
textAreaPanel.add(list, BorderLayout.EAST);
pane.add(textAreaPanel);
pane.add(buttonPanel);
return pane;
}
The cool thing is that you can nest panels inside other panels, adding them different layout managers to get your desired layout.
On an unrelated note, try to follow Java naming conventions. Instead of JTextArea TextArea use JTextArea textArea. It makes it easier for you and people reading your code to understand it.
You could use a layout manager like Mig Layout for that kind of positionning.
(source: miglayout.com)
I could recommend you FormLayout. Before I found this layout I had a real pain with GridBagLayout. FormLayout is more powerful and much more convenient to learn and use and it is free. Give it a chance.
As others suggested, familiarize yourself with the concept of layout managers. There are several that come with the standard Swing API and several good 3rd party ones out there.
In addition, you will want to add the JList to a scroll pane (JScrollPane). You may want to consider adding it to a split pane (JSplitPane). And by consider I don't mean "do it because some guy on the net said so" I mean "do it if it makes sense for your end users".

Categories

Resources