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:
Related
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.
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(..);
I am using GridBagLayout to align components. Actually, i have two buttons which i want to align like this:
Desired layout:
But the following code results in the following layout:
Resulted layout:
My code:
iconAdd = new ImageIcon(getClass().getResource("../images/add.png"));
add = new JButton(iconAdd);
add.setPreferredSize(new Dimension(130, 100));
add.setBorder(new LineBorder(Color.decode("#9b9999"), 1, true));
add.setCursor(Cursor.getPredefinedCursor(12));
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
pane.add(add, gbc);
iconSearch = new
ImageIcon(getClass().getResource("../images/search.png"));
search = new JButton(iconSearch);
search.setCursor(Cursor.getPredefinedCursor(12));
search.setPreferredSize(new Dimension(130, 100));
search.setBorder(new LineBorder(Color.decode("#9b9999"), 1, true));
gbc.gridx++;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
pane.add(search, gbc);
Any help would be highly appreciated.
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
public class GridBagLayoutDemo extends JFrame{
GridBagLayoutDemo(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWeights = new double[]{1.0, 1.0, 1.0};
gridBagLayout.columnWidths = new int[]{0,0,300};
getContentPane().setLayout(gridBagLayout);
JButton button1 = new JButton("Long Button");
GridBagConstraints c1 = new GridBagConstraints();
c1.fill = GridBagConstraints.HORIZONTAL;
c1.weightx = 0.0;
c1.gridwidth = 3;
c1.gridx = 0;
c1.gridy = 0;
getContentPane().add(button1, c1);
JButton button2 = new JButton("Button 2");
GridBagConstraints c2 = new GridBagConstraints();
c2.weightx = 0.5;
c2.gridx = 0;
c2.gridy = 1;
getContentPane().add(button2, c2);
JButton button3 = new JButton("Button 3");
GridBagConstraints c3 = new GridBagConstraints();
c3.weightx = 0.5;
c3.gridx = 1;
c3.gridy = 1;
getContentPane().add(button3, c3);
pack();
setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GridBagLayoutDemo();
}
});
}
}
gbc.weightx = 1;
You are telling the layout to give extra space to each component. So essentially each component becomes half the size of the frame.
You really only want that constraint set for the second button, so it takes up all the remaining space.
Read the section from the Swing tutorial on How to Use GridBagLayout which explains how the weightx/y constraints should be used.
Also, an easier solution would be do just use a FlowLayout. Create a panel with a FlowLayout. Add the buttons to the panel. Then add the panel to the BorderLayout.PAGE_START of the frame.
I've already search, read and watch many tutorials about GridBagLayouts but I always having an error while I'm dealing with my buttons. How can I get rid of the wide spacing between button 1 and 2?
JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
//pane.setLayout(new GridBagLayout());
Dimension d = new Dimension(300,0);
pane.setBackground(Color.red);
pane.setPreferredSize(d);
JButton b1 = new JButton("1");
c.gridy=0;
c.weighty = 1;
c.weightx =1;
c.insets = new Insets(10,10,10,10);
c.anchor = GridBagConstraints.NORTHWEST;
pane.add(b1, c);
JButton b2 = new JButton ("2");
c.gridy=1;
c.weighty = 2;
c.anchor = GridBagConstraints.NORTHWEST;
pane.add(b2, c);
getContentPane().add(pane, BorderLayout.WEST);
setTitle("test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(900,500);
setVisible(true);
enter image description here
sorry I'm a beginner with gui. Thanks in advance!
I don't know exactly what you wanted to have as a result. But I have this as result:
The biggest problem in the code, you should have to define an instance of GridbagConstraints for each Button. After that you can set the alignments. And here is how I did it:
JPanel pane = new JPanel(new GridBagLayout());
pane.setLayout(new GridBagLayout());
Dimension d = new Dimension(300,0);
pane.setBackground(Color.red);
pane.setPreferredSize(d);
GridBagConstraints c1 = new GridBagConstraints();
JButton b1 = new JButton("1");
c1.gridx = 0;
c1.gridy = 0;
c1.weightx = 1.0;
c1.anchor = GridBagConstraints.NORTHWEST;
pane.add(b1, c1);
GridBagConstraints c2 = new GridBagConstraints();
JButton b2 = new JButton ("2");
c2.gridx = 0;
c2.gridy = 1;
c2.weighty = 1.0;
c2.anchor = GridBagConstraints.NORTHWEST;
pane.add(b2, c2);
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 :