Java swing layout - java

Im having a hard time identifying what layout to be used. help any suggestions.
JPanel mainpanel = new JPanel();
public void addPanel(JPanel panel){
mainpanel.add(panel);
}
addPanel(A);
addPanel(B);
addPanel(C);
addPanel(D);
addPanel(E);
....
Panels A,B,C,D... are not of fixed sized.
How can I make this possible?

Seems like by using GridBagLayout, you can achieve this. Hopefully you can change the JPanel with MAGENTA colour as per your liking :-)
Here is the output :
And here is the code :
import java.awt.*;
import javax.swing.*; //swing package
public class GridBagLayoutTest
{
//defining the constructor
public GridBagLayoutTest()
{
JFrame maFrame = new JFrame("The main screen"); //creating main Jframe
maFrame.setLocationByPlatform(true); //centering frame
JPanel headPanel = new JPanel(); //creating the header panel
Container container = maFrame.getContentPane();
container.setLayout(new GridBagLayout()); //setting layout of main frame
GridBagConstraints cns = new GridBagConstraints(); //creating constraint
cns.gridx = 0;
cns.gridy = 0;
//cns.gridwidth = 3;
//cns.gridheight = 4;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.FIRST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
headPanel.setBackground(Color.BLUE);
container.add(headPanel, cns);
JPanel panel = new JPanel();
panel.setBackground(Color.CYAN);
cns = new GridBagConstraints();
cns.gridx = 1;
cns.gridy = 0;
//cns.gridwidth = 7;
//cns.gridheight = 4;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.FIRST_LINE_END;
cns.fill = GridBagConstraints.BOTH;
container.add(panel, cns);
JPanel panel1 = new JPanel();
panel1.setBackground(Color.RED);
cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 1;
//cns.gridwidth = 2;
cns.gridheight = 2;
cns.weightx = 0.5;
cns.weighty = 0.3;
cns.anchor = GridBagConstraints.LINE_START;
cns.fill = GridBagConstraints.BOTH;
container.add(panel1, cns);
JPanel panel2 = new JPanel();
panel2.setBackground(Color.PINK);
cns = new GridBagConstraints();
cns.gridx = 1;
cns.gridy = 1;
//cns.gridwidth = 2;
//cns.gridheight = 2;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.LINE_END;
cns.fill = GridBagConstraints.BOTH;
container.add(panel2, cns);
JPanel panel4 = new JPanel();
panel4.setBackground(Color.ORANGE);
cns = new GridBagConstraints();
cns.gridx = 1;
cns.gridy = 2;
//cns.gridwidth = 2;
//cns.gridheight = 2;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.LINE_END;
cns.fill = GridBagConstraints.BOTH;
container.add(panel4, cns);
JPanel mainPanel = new JPanel();
mainPanel.setBackground(Color.WHITE);
mainPanel.setLayout(new GridBagLayout());
cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 4;
cns.gridwidth = 2;
cns.gridheight = 2;
cns.weightx = 1.0;
cns.weighty = 0.3;
cns.anchor = GridBagConstraints.LAST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
container.add(mainPanel, cns);
JPanel panel3 = new JPanel();
panel3.setBackground(Color.MAGENTA);
cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 0;
//cns.gridwidth = 2;
//cns.gridheight = 2;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.FIRST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
mainPanel.add(panel3, cns);
JPanel bottomPanel = new JPanel();
bottomPanel.setBackground(Color.WHITE);
cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 1;
//cns.gridwidth = 2;
//cns.gridheight = 2;
cns.weightx = 1.0;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.LAST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
mainPanel.add(bottomPanel, cns);
//JButton button = new JButton("BUTTON");
//headPanel.add(button);
maFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //setting the default close operation of JFrame
maFrame.pack();
maFrame.setVisible(true); //making the frame visible
}
//defining the main method
public static void main(String[] args)
{
Runnable runnable = new Runnable()
{
public void run()
{
new GridBagLayoutTest(); //instantiating the class
}
};
SwingUtilities.invokeLater(runnable);
}
}

Consider using JGoodies Forms layout. it is highly flexible and easy to use. Any sort of layouting of widgets are possible, vertical stacking , horizontal stacking etc.
http://www.jgoodies.com/freeware/forms/index.html
/* B1 Space B2 Space B3 Space B4 */
String col1 = "10dlu, 3dlu, 10dlu, 3dlu 10dlu, 3dlu, 10ldu";
/*Width of button */
String row1 = "5dlu";
FormLayout layout = new FormLayout( col1, row1);
JPanel panel = new JPanel(layout);
panel.setBorder(Borders.DIALOG_BORDER);
CellConstraints cc = new CellConstraints();
/* X - stands for column position :: Y - stand for row */
panel.add(new JButton("B1"), cc.xy(1, 1));
panel.add(new JButton("B2"), cc.xy(2, 1));
.
.
.
there is one more cc.xyh(1,1,2) where 'h' stands for vertical span or width.
Yes, you read more about JGoodies forms layout, 'DLU' means dialog units, rather than me explaining all these, kindly visit JGoodies site, download the library and documentation. Trust be, this layout manager is much better, in terms of usability , maintainability and readability.

I would say, create a temporary panel for ACF, then BDE, then create one to combine ACF and BDE, then add the last temp panel and your main panel onto the frame with BorderLayout NORTH and SOUTH

Grid layout might be fit into this shape. Just look to the java swing documentation.

Depends on what the behaviour should be when the window is resized. But you won't avoid building a tree structure with JPanels.
The top component can have BorderLayout, with one panel in the North and main panel in Center.
The North panel will have X-axis BoxLayout and contain two panels.
Both these panels should have Y-axis BoxLayout and the first one will contain A, C, F and the second one B, D, E.
You should also set preferred sizes for A B C D E and F so that they render with appropriate size.
EDIT:
Here, I created an example:
public class GladysPanel extends JPanel
{
public GladysPanel(JComponent A, JComponent B, JComponent C, JComponent D, JComponent E, JComponent F, JComponent main){
super(new BorderLayout());
JPanel abcdef = new JPanel(new BorderLayout());
Box ab = new Box(BoxLayout.X_AXIS);
ab.add(A);
ab.add(B);
abcdef.add(ab, BorderLayout.NORTH);
Box cdef = new Box(BoxLayout.X_AXIS);
Box cf = new Box(BoxLayout.Y_AXIS);
cf.add(C);
cf.add(F);
cf.add(Box.createVerticalGlue());
Box de = new Box(BoxLayout.Y_AXIS);
de.add(D);
de.add(E);
de.add(Box.createVerticalGlue());
cdef.add(cf, BorderLayout.WEST);
cdef.add(de, BorderLayout.EAST);
abcdef.add(cdef);
add(abcdef, BorderLayout.NORTH);
add(main);
}
public static void main(String[] args){
JPanel A = new JPanel();
A.setOpaque(true);
A.setBackground(Color.BLUE);
A.add(new JLabel("A"));
JPanel B = new JPanel();
B.setOpaque(true);
B.setBackground(Color.LIGHT_GRAY);
B.add(new JLabel("B"));
JPanel C = new JPanel();
C.setPreferredSize(new Dimension(0, 100));
C.setOpaque(true);
C.setBackground(Color.RED);
C.add(new JLabel("C"));
JPanel D = new JPanel();
D.setOpaque(true);
D.setBackground(Color.PINK);
D.add(new JLabel("D"));
JPanel E = new JPanel();
E.setOpaque(true);
E.setBackground(Color.YELLOW);
E.add(new JLabel("E"));
E.setPreferredSize(new Dimension(0, 60));
JPanel F = new JPanel();
F.setOpaque(true);
F.setBackground(Color.MAGENTA);
F.add(new JLabel("F"));
JPanel main = new JPanel();
main.setOpaque(true);
main.setBackground(Color.WHITE);
main.add(new JLabel("main"));
GladysPanel panel = new GladysPanel(A, B, C, D, E, F, main);
JFrame example = new JFrame("Gladys example");
example.setContentPane(panel);
example.setSize(300, 300);
example.setVisible(true);
}
}
you can omit the setPreferredSize(), I added it only to demonstate behaviour. You can also try to resize the window. The code is much much shorter that when using GridBagLayout.

Related

How many vertical field details can I have in a Java swing application?

I am aware of the NORTH, CENTER and SOUTH field details for setting a component (e.g. BorderLayout) to either the top, middle or bottom respectively, however, I was wondering if it's possible to have more than three components and if so, how would I go about doing this with additional field details.
Currently, I have the following.
North - BorderLayout
Center - GridLayout
South - GridBagLayout
I am wanting to add an additional GridBagLayout to the bottom of the program (either below or above existing GridBagLayout). How would I go about adding an additional layout so that it does not interfere with and merge with the current SOUTH area?
Code:
public class boggleView extends JFrame {
public boggleView(){
super("Boggle");
setResizable(false);
setLocationRelativeTo(null);
setMinimumSize(new Dimension(400, 400));
JPanel northPanel = new JPanel();
JPanel middlePanel = new JPanel();
JPanel southPanel = new JPanel();
JPanel southPanelBottom = new JPanel();
// North Panel
getContentPane().add(northPanel, BorderLayout.NORTH);
northPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
JLabel gameBoardTitle = new JLabel("<html><font size = 5>Game Board</font></html>");
northPanel.add(gameBoardTitle);
// Middle Panel
getContentPane().add(middlePanel, BorderLayout.CENTER);
middlePanel.setLayout(new GridLayout(4,4));
for(int button=0 ; button<16 ; button++){
JButton diceButton = new JButton(String.valueOf("<html><font size = 10>E</font></html>"));
diceButton.setBackground(Color.WHITE);
diceButton.setBorder(new LineBorder(Color.BLACK));
diceButton.setPreferredSize(new Dimension(100, 100));
middlePanel.add(diceButton);
}
// South Panel
southPanel.setLayout (new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.insets = new Insets(10,10,0,10);
c.fill = GridBagConstraints.HORIZONTAL;
Border wordBorder = BorderFactory.createLineBorder(Color.BLACK, 1);
Border textFieldBorder = BorderFactory.createLineBorder(Color.BLACK, 2);
JButton button;
JLabel textField = new JLabel("");
textField.setBorder(textFieldBorder);
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 8;
textField.setPreferredSize(new Dimension(0,35));
southPanel.add(textField, c);
button = new JButton("Submit");
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 1;
button.setBackground(Color.GREEN);
button.setPreferredSize(new Dimension(80, 35));
southPanel.add(button, c);
button = new JButton("Cancel");
c.gridx = 2;
c.gridy = 1;
c.gridwidth = 1;
button.setBackground(Color.RED);
button.setPreferredSize(new Dimension(80, 35));
southPanel.add(button, c);
button = new JButton("Restart");
c.gridx = 4;
c.gridy = 1;
c.gridwidth = 1;
button.setBackground(Color.CYAN);
button.setPreferredSize(new Dimension(80, 35));
southPanel.add(button, c);
button = new JButton("Info");
c.gridx = 6;
c.gridy = 1;
c.gridwidth = 1;
button.setBackground(Color.CYAN);
button.setPreferredSize(new Dimension(80, 35));
southPanel.add(button, c);
JLabel wordListTitle = new JLabel("<html><font size = 5>Recent Words</font></html>");
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 3;
c.insets = new Insets(0,5,0,0);
southPanel.add(wordListTitle, c);
// Bottom South Panel
southPanelBottom.setLayout (new GridBagLayout());
GridBagConstraints d = new GridBagConstraints();
d.fill = GridBagConstraints.HORIZONTAL;
d.insets = new Insets(0,0,0,0);
JLabel word = new JLabel("<html><font size = 5>HAT</font></html>");
word.setBorder(wordBorder);
d.gridx = 0;
d.gridy = 3;
d.gridwidth = 2;
southPanelBottom.add(word, d);
JLabel word2 = new JLabel("<html><font size = 5>1</font></html>");
word2.setBorder(wordBorder);
d.gridx = 2;
d.gridy = 3;
d.gridwidth = 1;
southPanelBottom.add(word2, d);
getContentPane().add(southPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
}
use a new helper Panel with layout Borderlayout.
put your new GridBagLayout panel to this new helper Panel's South and put the existing GridBagLayout panel (currently at SOUTH) this panel's North.
then put this new helper Panel to SOUTH replacing old GridBagLayout panel.
JPanel southHelperPanel = new JPanel(new BorderLayout());
southHelperPanel.add(southPanel, BorderLayout.NORTH);
southHelperPanel.add(southPanelBottom, BorderLayout.SOUTH);
getContentPane().add(southHelperPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
You can just combine layouts as you need them. Please have a look at the below example.. In this example, the main panel has a BorderLayout. In the different directions of this panel I'm adding new panels with other layouts.
public class Test extends JFrame {
public static void main(String[] args) {
Test test = new Test();
test.setVisible(true);
}
public Test() {
JPanel main = new JPanel(new BorderLayout());
JPanel top = new JPanel(new FlowLayout());
JPanel center = new JPanel(new GridBagLayout());
JPanel bottom = new JPanel(new BorderLayout());
main.add(top, BorderLayout.PAGE_START);
main.add(center, BorderLayout.CENTER);
main.add(bottom, BorderLayout.PAGE_END);
this.getContentPane().add(main);
this.setSize(800, 500);
}
}
You could also give your main panel a different layout (like GridBagLayout) if you need more "directions" in the beginning.
BorderLayout cannot itself do this; it can only lay out 3 things vertically. Switch the container (window.getContentPane(), presumably) to a different layout.
Something similar-ish to BorderLayout is to use BoxLayout; I'd need to know a little more about exactly what's in those subcomponents to be sure if it's the right replacement here.

GridBagLayout Resizing Panel

I have read several articles regarding this topic as well the documentation, yet I still can't seem to solve my problem.
I have created a GUI that needs to be resizeable; however, I would like to maintain that there are 3 JTextFields for each row.
I have tried adjusting the weightx, yet no success.
Here is a snippet of my code:
JPanel panelMain = new JPanel();
getContentPane().add(panelMain);
JPanel panelForm = new JPanel(new GridBagLayout());
panelMain.add(panelForm);
//JScrollPane scrollpane = new JScrollPane(panelForm);
//panelMain.add(scrollpane);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
// Row 1
buttonAddCourses = new JButton("Add Credit Hours");
buttonAddCourses.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
c.gridx = 0;
c.weightx = 0.2;
for(int i = 0; i < 15; i++) {
JTextField newTextField = new JTextField(20);
listTextFields.add(newTextField);
panelMain.add(newTextField,c);
c.gridy++;
}
panelMain.validate();
panelMain.repaint();
}
});
panelForm.add(buttonAddCourses, c);
c.gridx++;
Before Resize : !https://imgur.com/a/XCUtJ
After Resize :
!https://imgur.com/a/a4Qo4
JPanel panelMain = new JPanel(); // <- gets a FlowLayout by default
// ..
JPanel panelForm = new JPanel(new GridBagLayout()); // panel with GBL
// ...
panelMain.add(newTextField,c); // No, this should be panelForm.add(..);

How to make GUI using Java Swing

So I recently started learning object-oriented programming, did most basic stuff in Java and now I want to change from console writing to actual GUI.
But I have problem understanding how it works, I read everything in oracle documentation but their examples are not so clear and easy to understand, also googled it but couldn't manage to find any good explanation. This is my last resort.
Here is my idea of how my program GUI should look:
![like this][1]
I couldn't draw very nice but all check boxes should be aligned.
If someone can provide me explanation with code that would be great, if not just some good explanation would help me a lot, my problem is that when I align 1 thing other gets messed up.
My current code:
public class Zadatak2 extends JFrame{
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
new Zadatak2();
}
public Zadatak2(){
JPanel panel1 = new JPanel();
setSize(500, 250);
setLocationRelativeTo(null);
add(panel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
BorderLayout border1 = new BorderLayout();
panel1.setLayout(border1);
JPanel panel2 = new JPanel();
GridLayout grid1 = new GridLayout(3,2);
panel2.setLayout(grid1);
panel2.add(new JCheckBox("Bold"));
panel2.add(new JCheckBox("Italic"));
panel2.add(new JCheckBox("Underline"));
panel1.add(panel2,BorderLayout.WEST);
JPanel panel3 = new JPanel();
GridLayout grid2 = new GridLayout(4,1);
panel3.setLayout(grid2);
panel3.add(new JCheckBox("Strikerthrough"));
panel3.add(new JCheckBox("Teletype"));
panel3.add(new JCheckBox("Emphasis"));
panel3.add(new JCheckBox("Strong"));
panel1.add(panel3,BorderLayout.CENTER);
JPanel panel4 = new JPanel();
BorderLayout border2 = new BorderLayout();
panel4.setLayout(border2);
panel4.add(new JButton("Apply"), BorderLayout.EAST);
panel4.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 70));
panel1.add(panel4,BorderLayout.SOUTH);
JPanel panel5 = new JPanel();
GridLayout grid3 = new GridLayout(2,1);
panel5.setLayout(grid3);
panel5.add(new JLabel("Sample text"));
JTextArea ta = new JTextArea("Sample text");
panel5.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 30));
ta.setSize(200, 200);
panel5.add(ta);
panel1.add(panel5,BorderLayout.EAST);
setVisible(true);
}
}
Thanks for help from everyone, finally made the gui right, now I understand thins much better.
To position the check boxes in the GridLayout, you should not define a panel for each column. Just define and place them like this:
JPanel panel2 = new JPanel();
GridLayout grid1 = new GridLayout(4, 2);
panel2.setLayout(grid1);
panel2.add(new JCheckBox("Bold"));
panel2.add(new JCheckBox("Strikerthrough"));
panel2.add(new JCheckBox("Italic"));
panel2.add(new JCheckBox("Teletype"));
panel2.add(new JCheckBox("Underline"));
panel2.add(new JCheckBox("Emphasis"));
panel2.add(new JLabel("")); // fill the empty cell with an empty label
panel2.add(new JCheckBox("Strong"));
However, since you have a TextArea that should be aligned with the check boxes and span several rows, I would recomment using a GridBagLayout instead. It's more code to write, but much more flexible than the GridLayout.
An example:
public Zadatak2() {
JPanel panel1 = new JPanel();
setSize(500, 250);
setLocationRelativeTo(null);
add(panel1);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
BorderLayout border1 = new BorderLayout();
panel1.setLayout(border1);
JPanel panel2 = new JPanel();
GridBagLayout grid1 = new GridBagLayout();
panel2.setLayout(grid1);
panel2.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
Insets insets = new Insets(2, 2, 2, 2);
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Bold"), c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Strikerthrough"), c);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 1;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Italic"), c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Teletype"), c);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 2;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Underline"), c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 2;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Emphasis"), c);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 3;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JCheckBox("Strong"), c);
insets = new Insets(2, 40, 2, 2);
c = new GridBagConstraints();
c.gridx = 2;
c.gridy = 0;
c.insets = insets;
c.anchor = GridBagConstraints.WEST;
panel2.add(new JLabel("Sample text"), c);
c = new GridBagConstraints();
c.gridx = 2;
c.gridy = 1;
c.insets = insets;
c.weightx = .5;
c.fill = GridBagConstraints.BOTH;
c.gridheight = 3;
JTextArea ta = new JTextArea("Sample text", 4, 4);
JScrollPane sp = new JScrollPane(ta);
panel2.add(sp, c);
c = new GridBagConstraints();
c.gridx = 2;
c.gridy = 5;
c.insets = new Insets(40, 40, 2,2);
c.anchor = GridBagConstraints.WEST;
panel2.add(new JButton("Apply"), c);
panel1.add(panel2, BorderLayout.CENTER);
pack();
setVisible(true);
}
The result:
Please see the GridBagLayout Tutorial and the JavaDoc to learn about all the options of this layout.
Remember to nest JPanels each using its own layout. For instance your imaged GUI could be made one of many ways. The overall JPanel could use BoxLayout oriented to the line, and on the left have a GridLayout using JPanel on the right a BorderLayout using JPanel. For example:
Other issues:
The JTextArea should be placed into a JScrollPane, and the scrollpane then added to the GUI.
NEVER set the sizes or preferred sizes of text components, especially JTextAreas as that will prevent them from working correctly, especially if within a scrollpane.
Instead set the JTextArea's column and row properties.
Avoid setting sizes in general. Let the GUI components and layouts set their own sizes by calling pack() on the JFrame after adding everything and before setting it visible.
For example, with slight modification:
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class SimpleGui extends JPanel {
private static final String[] CHK_BOX_TEXTS = {"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday"};
private String title = "My Title";
private JTextArea textArea = new JTextArea(10, 30);
private JButton applyButton = new JButton("Apply");
public SimpleGui() {
// gridlayout with 2 columns, variable rows
JPanel checkBoxPanel = new JPanel(new GridLayout(0, 2, 4, 4));
for (String chkBoxText : CHK_BOX_TEXTS) {
checkBoxPanel.add(new JCheckBox(chkBoxText));
}
JPanel leftPanel = new JPanel();
leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
leftPanel.add(Box.createVerticalStrut(20));
leftPanel.add(checkBoxPanel);
leftPanel.add(Box.createGlue());
JLabel titleLabel = new JLabel(title, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 20));
JScrollPane scrollPane = new JScrollPane(textArea);
JPanel btnPanel = new JPanel();
btnPanel.add(applyButton);
JPanel rightPanel = new JPanel(new BorderLayout(5, 5));
rightPanel.add(titleLabel, BorderLayout.PAGE_START);
rightPanel.add(scrollPane, BorderLayout.CENTER);
rightPanel.add(btnPanel, BorderLayout.PAGE_END);
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
add(leftPanel);
add(rightPanel);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("SimpleGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimpleGui());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Which displays as:

How can we have a contained GridBagLayout, with preferredSize, with vertical scroll only?

Does anyone know how to add a ScrollBar to a JPanel with a Gridbaglayout, allowing the Gridbaglayout to still reposition components on the horizontal axis. I've tried adding the scroll bar - but when I do the Gridbaglayout repositioning of components on the horizontal stops working and the components go off the side of the screen when I reduce the window width. How can we include vertical scroll, while allowing the Gridbaglayout to still reposition components on the horizontal axis. And help would be appreciated.
The GridBagLayout should still move the components.
The code:
import java.awt.*;
import javax.swing.*;
public class SwingTest {
public static void main(String[] args) {
final JScrollPane scrollPane = new JScrollPane(addCustomer());
JFrame frame = new JFrame("Swing Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(640, 480);
frame.setMinimumSize(new Dimension(300, 480));
frame.setLocation(200, 200);
frame.getContentPane().add(scrollPane);
frame.setVisible(true);
}
public static Component addCustomer(){
JTextField textField1;
/***********************Initialize Fields******************************/
JLabel labels[] = new JLabel[2];
labels[0] = new JLabel("Left side - more components to add here");
labels[1] = new JLabel("Right side - more components to add here");
textField1 = new JTextField(10);
JComboBox<String> materialTitlesCombo = new JComboBox<String>();
materialTitlesCombo.addItem("-");
materialTitlesCombo.addItem("test");
materialTitlesCombo.setPreferredSize(new Dimension(250, 500));
materialTitlesCombo.setMinimumSize(materialTitlesCombo.getPreferredSize());
/****************************Create the canvas**************************/
GridBagConstraints constraints;
constraints = new GridBagConstraints();
final JPanel panel = new JPanel(new GridBagLayout());
constraints.gridx = 0;
constraints.gridy = 3;
constraints.gridheight = 1;
constraints.gridwidth = 1;
constraints.weightx = 0.5;
constraints.weighty = 1;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(-20,20,0,0);
panel.add(labels[0], constraints); //Left side
constraints.gridx = 1;
constraints.gridy = 3;
constraints.gridheight = 1;
constraints.gridwidth = 1;
constraints.weightx = 0.5;
constraints.weighty = 1;
constraints.anchor = GridBagConstraints.CENTER;
constraints.insets = new Insets(-10,-9,0,9);
panel.add(textField1, constraints); // TextField 1
constraints.gridx = 8;
constraints.gridy = 3;
constraints.gridheight = 1;
constraints.gridwidth = 1;
constraints.weightx = 0.5;
constraints.weighty = 1;
constraints.anchor = GridBagConstraints.WEST;
constraints.insets = new Insets(-15,15,0,0);
panel.add(labels[1], constraints);//Right side
return panel;
}
}
To add a scrollable JPanel as a tab, you can do the following:
JScrollPane scrollPane = new JScrollPane(addCustomer());
pane.addTab("...", scrollPane);
I noticed that you never add the JTabbedPane component to the CustomerPane, which means the tabbed pane will never be rendered in the UI. You can try the following:
private void initializeUI() {
...
add(pane);
}
Just add setMaximumSize, and setPreferredSize with a minimumSizeValue to the parent panel, containing a nested panel that uses gridbaglayout housing your components.
panel.setMaximumSize(getYourMinimumSize);
panel.setPreferredSize(getYourMinimumSize);
Works with nested tabPanes and nested Panels.

GridBagLayout - Height of one row causes the width of next row to change

The UI I am working on displays a panel which lets a user select a movie and play. There are controls to play, pause, etc.
The layout seems to look the way I want. The panel uses a GridBagLayout. Row 2 displays a text area for status messages and row 3 displays a panel with buttons and a progress bar.
The problem I am running into is that when I have too many lines of text in the text area, the buttons in row 3 wrap around. This is irrespective of the height of the outer frame.
The height in row 2 is affecting the width in row 3. I don't understand this behavior. I am wondering if someone can tell me what is it that I am doing wrong and how I can fix it? I have attached the code.
On a slightly different topic, if you are looking at the code, can you also suggest a way to leave a margin between the bottom-most component and the outermost panel?
Thank you in advance for your help.
Regards,
Peter
private static JButton CreateImageButton(String fileName) {
JButton retVal = new JButton("xxx");
return retVal;
}
public MoviePanel() {
this.setLayout(new GridBagLayout());
this.setBackground(Color.WHITE);
JButton btnRefresh = CreateImageButton("refresh.png");
GridBagConstraints c = new GridBagConstraints();
c.gridx=0;
c.gridy=0;
c.fill = GridBagConstraints.NORTH;
c.insets.left = 10; c.insets.right = 10; c.insets.top = 10;
this.add(btnRefresh, c);
JComboBox cbMovieList = new JComboBox();
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets.right = 10; c.insets.top = 10;
c.weightx = 1.0;
this.add(cbMovieList, c);
JButton btnAuthorize = new JButton("Get Info");
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.anchor = GridBagConstraints.WEST;
c.insets.top = 10;
this.add(btnAuthorize, c);
JTextArea txtInfo = new JTextArea();
txtInfo.setFont( new Font("SansSerif", Font.BOLD, 12));
txtInfo.setBackground(Color.cyan);
// txtInfo.setText("abc\ndef");
txtInfo.setText("abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyz");
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 2;
c.anchor = GridBagConstraints.NORTHWEST;
c.weighty = 1.0;
c.insets.top = 10;
this.add(txtInfo, c);
JPanel controllerOuter = new JPanel();
controllerOuter.setLayout(new BoxLayout(controllerOuter, BoxLayout.Y_AXIS));
controllerOuter.setBorder(BorderFactory.createRaisedBevelBorder());
FlowLayout controllerLayout = new FlowLayout(FlowLayout.CENTER);
controllerLayout.setHgap(0);
JPanel controller = new JPanel(controllerLayout);
controller.setBorder(new EmptyBorder(10, 10, 10, 10));
Dimension dim = new Dimension(60, 40);
JButton btnPlay = CreateImageButton("play.png");
btnPlay.setPreferredSize(dim);
controller.add(btnPlay);
JButton btnPause = CreateImageButton("pause.png");
btnPause.setPreferredSize(dim);
controller.add(btnPause);
JButton btnStop = CreateImageButton("stop.png");
btnStop.setPreferredSize(dim);
controller.add(btnStop);
JButton btnForward = CreateImageButton("forward.png");
btnForward.setPreferredSize(dim);
controller.add(btnForward);
JComboBox cbAspectRatio = new JComboBox();
cbAspectRatio.setPreferredSize(new Dimension(100, 40));
cbAspectRatio.setBorder(new EmptyBorder(0, 10, 0, 0));
controller.add(cbAspectRatio);
controllerOuter.add(controller);
JProgressBar pbProgress = new JProgressBar(0, 100);
pbProgress.setPreferredSize(new Dimension(350, 40));
pbProgress.setBorder(new EmptyBorder(0, 10, 10, 10));
pbProgress.setValue(50);
pbProgress.setString("50/100");
pbProgress.setStringPainted(true);
pbProgress.setForeground(Color.BLUE);
pbProgress.setBorderPainted(true);
controllerOuter.add(pbProgress);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 3;
c.gridwidth = 2;
c.weightx = 1.0;
this.add(controllerOuter, c);
}
I see several things in your code:
You force the preferredSize of the JButton's. If possible, I would remove that because this will often get you more problems than solutions. If you want to force the preferredSize, you should also pay attention to set the minimum and maximum sizes as well, otherwise you get weird behaviour like the one you are observing
You use a BoxLayout to display the controls. While this is perfectly acceptable, BoxLayout also relies on min/max size to perform the layout, which you did not set.
You use imbricated layouts. This is fine too, but why not use only the GridBagLayout of your MoviePanel?
Usually TextAreas are wrapped in JScrollPane, in case the text is too big. You can also setLineWrap(true) on the TextArea, so that it does not go too far on the right. By setting rows/columns on the TextArea, you will define its preferreSize (to prevent it from depending of the text it contains).
On your GridBagConstraints, the fill property can only be: NONE, VERTICAL, HORIZONTAL or BOTH (You used VERTICAL for one of them). Also, it is not needed to recreate a new instance, you can reuse the same GridBagConstraint over and over, it is automatically cloned by the LayoutManager when you set the constraint for the component.
Now for the solutions, I found several:
When you add the contollerOuter, also specify c.fill = GridBagConstraints.HORIZONTAL; (This is the easiest way to solve your issues)
When you set the preferredSize of the JButtons, also force their minimumSize to the same value.
Use only the GridBagLayout to layout all components. (This would be my favorite)
Replace the FlowLayout by a BoxLayout with a X_AXIS.
Rember that GridBagConstraints properties :
gridx, gridy: specifies the location
gridwidth, gridheight: specifies the colspan/rowspan
weightx, weighty: specifies who gets the extra horizontal/vertical space and in what proportion
anchor: specifies the alignement of the component withing its "cell", if the "cell" is bigger than the component
fill: specifies if the component should stretch to the cell width/height
Just adding one JPanel each for Center and Bottom will do the trick for you, so till your JTextArea your GridBagLayout will server the purpose and after that the BorderLayout of the MAIN JPanel will do. Moreover, adding JScrollPane also to the whole thing reduces the effort needed at other areas. Have a look at the code and output :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class JTextPaneExample extends JPanel
{
private Icon info = UIManager.getIcon("OptionPane.informationIcon");
private Icon error = UIManager.getIcon("OptionPane.errorIcon");
private static JButton CreateImageButton(String fileName) {
JButton retVal = new JButton("xxx");
return retVal;
}
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("JTextPane Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.setBackground(Color.WHITE);
JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
centerPanel.setLayout(new GridBagLayout());
centerPanel.setBackground(Color.WHITE);
JButton btnRefresh = CreateImageButton("refresh.png");
GridBagConstraints c = new GridBagConstraints();
c.gridx=0;
c.gridy=0;
c.fill = GridBagConstraints.NORTH;
c.insets.left = 10; c.insets.right = 10; c.insets.top = 10;
centerPanel.add(btnRefresh, c);
JComboBox cbMovieList = new JComboBox();
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 0;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets.right = 10; c.insets.top = 10;
c.weightx = 1.0;
centerPanel.add(cbMovieList, c);
JButton btnAuthorize = new JButton("Get Info");
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.anchor = GridBagConstraints.WEST;
c.insets.top = 10;
centerPanel.add(btnAuthorize, c);
JTextArea txtInfo = new JTextArea();
txtInfo.setFont( new Font("SansSerif", Font.BOLD, 12));
txtInfo.setBackground(Color.cyan);
// txtInfo.setText("abc\ndef");
txtInfo.setText("abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyz");
JScrollPane scroller = new JScrollPane();
scroller.setViewportView(txtInfo);
c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 2;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.HORIZONTAL;
c.weighty = 1.0;
c.insets.top = 10;
centerPanel.add(scroller, c);
JPanel controllerOuter = new JPanel();
controllerOuter.setLayout(new BoxLayout(controllerOuter, BoxLayout.Y_AXIS));
controllerOuter.setBorder(BorderFactory.createRaisedBevelBorder());
FlowLayout controllerLayout = new FlowLayout(FlowLayout.CENTER);
controllerLayout.setHgap(0);
JPanel controller = new JPanel(controllerLayout);
controller.setBorder(new EmptyBorder(10, 10, 10, 10));
Dimension dim = new Dimension(60, 40);
JButton btnPlay = CreateImageButton("play.png");
btnPlay.setPreferredSize(dim);
controller.add(btnPlay);
JButton btnPause = CreateImageButton("pause.png");
btnPause.setPreferredSize(dim);
controller.add(btnPause);
JButton btnStop = CreateImageButton("stop.png");
btnStop.setPreferredSize(dim);
controller.add(btnStop);
JButton btnForward = CreateImageButton("forward.png");
btnForward.setPreferredSize(dim);
controller.add(btnForward);
JComboBox cbAspectRatio = new JComboBox();
cbAspectRatio.setPreferredSize(new Dimension(100, 40));
cbAspectRatio.setBorder(new EmptyBorder(0, 10, 0, 0));
controller.add(cbAspectRatio);
controllerOuter.add(controller);
JProgressBar pbProgress = new JProgressBar(0, 100);
pbProgress.setPreferredSize(new Dimension(350, 40));
pbProgress.setBorder(new EmptyBorder(0, 10, 10, 10));
pbProgress.setValue(50);
pbProgress.setString("50/100");
pbProgress.setStringPainted(true);
pbProgress.setForeground(Color.BLUE);
pbProgress.setBorderPainted(true);
controllerOuter.add(pbProgress);
add(centerPanel, BorderLayout.CENTER);
add(controllerOuter, BorderLayout.PAGE_END);
frame.getContentPane().add(this);
frame.pack();
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new JTextPaneExample().createAndDisplayGUI();
}
});
}
}
Here is the output as you add more lines :

Categories