I created simple app with Border Layout and added into it two buttons and JTable. I use JSplitPane between button2 and JTable. I would like redefine default size of block where is situated button1. How can I to solve this task?
Here is my code:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
public class Sample {
public Sample() {
JFrame app = new JFrame("Sample");
app.setSize(new Dimension(800,600));
JPanel panel = new JPanel();
app.add(panel);
BorderLayout borderlayout = new BorderLayout();
panel.setLayout(borderlayout);
JButton but1 = new JButton("1");
JButton but2 = new JButton("2");
but2.setMinimumSize(new Dimension(250,0));
String[] colNames = {"Name","Number","Scores"};
Object[][] data = {
{ "Mark",11,12},
{"Tommy",23,34},
{"John",34,45}
};
JTable table = new JTable(data, colNames);
JScrollPane scrollpane = new JScrollPane(table);
JSplitPane jsplitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,but2,scrollpane);
panel.add(but1,BorderLayout.NORTH);
panel.add(jsplitpane,BorderLayout.CENTER);
app.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Sample();
}
});
}
}
Components in the BorderLayout.PAGE_START location have the height of their preferred sizes respected. Therefore, you can override the preferred size of JButton but1
JButton but1 = new JButton("1") {
public Dimension getPreferredSize() {
return new Dimension(100, 80);
};
};
If you are willing to use GridBagLayout for the said purpose, then I guess this Layout and do this job for you, as stated in the below pasted code example :-)
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
public class Sample {
public Sample() {
JFrame app = new JFrame("Sample");
app.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
app.setSize(new Dimension(800,600));
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.setLayout(new BorderLayout(5, 5));
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new GridBagLayout());
JButton but1 = new JButton("1");
JButton but2 = new JButton("2");
but2.setMinimumSize(new Dimension(250,0));
String[] colNames = {"Name","Number","Scores"};
Object[][] data = {
{ "Mark",11,12},
{"Tommy",23,34},
{"John",34,45}
};
JTable table = new JTable(data, colNames);
JScrollPane scrollpane = new JScrollPane(table);
JSplitPane jsplitpane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,but2,scrollpane);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.weighty = 0.3;
centerPanel.add(but1, gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridy = 1;
gbc.weighty = 0.7;
centerPanel.add(jsplitpane, gbc);
panel.add(centerPanel, BorderLayout.CENTER);
app.add(panel);
app.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Sample();
}
});
}
}
Here is the output of the same :
Related
I would like to create a panel, to which I can dynamically add sub-panels with fixed height. I tried using a glue component, but it does not work. I would like to achieve that the sub-panels are visible at the top of the gridbaglayout. Side problem is that when I keep adding sub-panels, they start to overlap because the JScrollPane isn't adjusting. However, when I resize the frame, both problems are solved.
At this moment I don't see where I went wrong. Why does the glue component not take up the vertical space to push the side panels to the top?
This is my SSCCE code:
import javax.swing.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import jrdb.data.ProcessingCommand;
public class ProcessingPipelineBuilderSSCCE extends JFrame {
/**
*
*/
private static final long serialVersionUID = 2413084448601918744L;
private JPanel interiorPanel = null;
private GridBagConstraints gbc = null;
private Component glue = null;
public ProcessingPipelineBuilderSSCCE() {
super("SSCCE");
this.getContentPane().setLayout(new BorderLayout());
gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 0, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = GridBagConstraints.PAGE_START;
JPanel pipelineBuilder = new JPanel();
pipelineBuilder.setLayout(new GridLayout(0, 1, 0, 0));
interiorPanel = new JPanel(new GridBagLayout());
interiorPanel.setBorder(BorderFactory.createLineBorder(Color.red));
JScrollPane scrollPane = new JScrollPane(interiorPanel);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(500,300));
pipelineBuilder.add(scrollPane);
JButton btnNew = new JButton("Add new panel");
btnNew.setPreferredSize(new Dimension(500, 30));
btnNew.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (glue!=null) {
interiorPanel.remove(glue);
} else {
glue = Box.createGlue();
}
gbc.gridy = gbc.gridy + 1;
interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
interiorPanel.add(glue,gbc);
interiorPanel.validate();
interiorPanel.repaint();
}
});
this.getContentPane().add(btnNew, BorderLayout.PAGE_START);
this.getContentPane().add(pipelineBuilder,BorderLayout.CENTER);
}
public class PipelineStep extends JPanel {
int number;
public PipelineStep (int n) {
super();
JOptionPane.showMessageDialog(interiorPanel, "adding new panel");
this.number = n;
this.setLayout(new FlowLayout());
JLabel lbl = new JLabel(new Integer(this.number).toString());
lbl.setPreferredSize(new Dimension(45,45));
lbl.setFont(lbl.getFont().deriveFont(26));
this.add(lbl);
this.setPreferredSize(new Dimension(450, 50));
this.setBorder(BorderFactory.createLineBorder(Color.green));
}
}
public static void main (String args[]) {
ProcessingPipelineBuilderSSCCE frame = new ProcessingPipelineBuilderSSCCE();
frame.pack();
frame.setVisible(true);
}
}
Why does the glue component not take up the vertical space to push the side panels to the top?
The "glue" component only has meaning when used with the BoxLayout. It has no effect with the GridBagLayout.
So my suggestion is to forget about the GridBagLayout and use the BoxLayout.
The easiest way to do this is to convert "interiorPanel" to use a vertical Box and just add your PipelineStep instances to this panel.
Try this. However, you will notice that the panels will still increase in size until the scroll pane is full, at which time you will see scrollbars appear. This is because the BoxLayout will resize components up to the maximum size of the component. So to prevent this resizing you could override the getMaximumSize() method of your PipelineStep class:
#Override
public Dimension getMaximumSize()
{
return getPreferredSize();
}
Or, another option is to use a "wrapper" panel for your "interiorPanel". Something like:
JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(interiorPanel, BorderLayout.PAGE_START);
//JScrollPane scrollPane = new JScrollPane(interiorPanel);
JScrollPane scrollPane = new JScrollPane(wrapper);
BorderLayout.PAGE_START respects the preferred height of the component added to it so the "interiorPanel" will always be displayed at it preferred height and scrollbars will appear when the viewport of the scroll pane is full.
I modified you code using the "wrapper" approach.
import javax.swing.*;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.awt.GridLayout;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
//import jrdb.data.ProcessingCommand;
public class SSCCE1 extends JFrame {
/**
*
*/
private static final long serialVersionUID = 2413084448601918744L;
// private JPanel interiorPanel = null;
private Box interiorPanel = null;
private GridBagConstraints gbc = null;
private Component glue = null;
public SSCCE1() {
super("SSCCE");
this.getContentPane().setLayout(new BorderLayout());
gbc = new GridBagConstraints();
//gbc.insets = new Insets(5, 5, 0, 5);
//gbc.fill = GridBagConstraints.HORIZONTAL;
//gbc.gridx = 0;
//gbc.gridy = 0;
//gbc.weightx = 1.0;
//gbc.weighty = 1.0;
//gbc.anchor = GridBagConstraints.PAGE_START;
JPanel pipelineBuilder = new JPanel();
pipelineBuilder.setLayout(new GridLayout(0, 1, 0, 0));
// interiorPanel = new JPanel(new GridBagLayout());
interiorPanel = Box.createVerticalBox();
interiorPanel.setBorder(BorderFactory.createLineBorder(Color.red));
JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(interiorPanel, BorderLayout.PAGE_START);
// JScrollPane scrollPane = new JScrollPane(interiorPanel);
JScrollPane scrollPane = new JScrollPane(wrapper);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollPane.setPreferredSize(new Dimension(500,300));
pipelineBuilder.add(scrollPane);
JButton btnNew = new JButton("Add new panel");
btnNew.setPreferredSize(new Dimension(500, 30));
btnNew.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// if (glue!=null) {
// interiorPanel.remove(glue);
// } else {
// glue = Box.createGlue();
// }
gbc.gridy = gbc.gridy + 1;
// interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
interiorPanel.add(new PipelineStep(gbc.gridy),gbc);
// interiorPanel.add(glue,gbc);
// interiorPanel.validate();
interiorPanel.revalidate();
interiorPanel.repaint();
}
});
this.getContentPane().add(btnNew, BorderLayout.PAGE_START);
this.getContentPane().add(pipelineBuilder,BorderLayout.CENTER);
}
public class PipelineStep extends JPanel {
int number;
public PipelineStep (int n) {
super();
JOptionPane.showMessageDialog(interiorPanel, "adding new panel");
this.number = n;
this.setLayout(new FlowLayout());
JLabel lbl = new JLabel(new Integer(this.number).toString());
lbl.setPreferredSize(new Dimension(45,45));
lbl.setFont(lbl.getFont().deriveFont(26));
this.add(lbl);
this.setPreferredSize(new Dimension(450, 50));
this.setBorder(BorderFactory.createLineBorder(Color.green));
}
}
public static void main (String args[]) {
SSCCE1 frame = new SSCCE1();
frame.pack();
frame.setVisible(true);
}
}
I've been trying to learn by Youtube videos, but there must be something I missing about GridBagLayout.
Basically what I expect is 4 buttons, one below another, with an height of 2 grids, but it seems that no matter what value I set gridheight, the buttons stay the same size
Compilable code :
package test;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class Test{
public static void main(String []args){
System.out.println("Hello World");
JFrame jay = new JFrame("test");
JPanel jp = new JPanel(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
JButton j1 = new JButton("Button 1");
JButton j2 = new JButton("Button 22222222222222");
JButton j3 = new JButton("Button 333333");
JButton j4 = new JButton("4");
gc.gridx = 0; gc.gridy = 0;
gc.insets = new Insets(5,10,5,10);
gc.gridheight = 2; //This is where the problem is;
gc.fill = GridBagConstraints.BOTH;
jp.add(j1,gc);
gc.gridx = 0; gc.gridy = 2;
jp.add(j2,gc);
gc.gridx = 0; gc.gridy = 4;
jp.add(j3,gc);
gc.gridx = 0; gc.gridy = 6;
jp.add(j4,gc);
jay.add(jp);
jay.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jay.setSize(300,350);
jay.setVisible(true);
}
}
Also if someone explain me what determines the size of the grids? is it just the component size?
gridheight specifies the number of rows that a component will expand, assuming that there are components in those rows (any empty row will automatically be sized to 0)
how would I go about achieving taller buttons then? adding blank components?
One possible solution is to use ipady which is added to the component's preferredSize property (you can also use ipadx for width)
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
JButton j1 = new JButton("Button 1");
JButton j2 = new JButton("Button 22222222222222");
JButton j3 = new JButton("Button 333333");
JButton j4 = new JButton("4");
gc.insets = new Insets(5, 10, 5, 10);
gc.ipady = 50;
gc.gridwidth = GridBagConstraints.REMAINDER;
gc.fill = GridBagConstraints.BOTH;
add(j1, gc);
add(j2, gc);
add(j3, gc);
add(j4, gc);
}
}
}
Have a look at How to Use GridBagLayout for more details
I feel as beginner I may have bitten off too much in regards to application building. That said, I am working on developing an application for a friend that will have prompts where each JPanel will provide fields to create an object to be used later. What I would like to have happen is that when the panel loads, it displays one object creation panel and a button to dynamically add a new panel if the user wants to make multiples (the plus button would add the new panel).
I have drawn up something in paint to illustrate this:
By my very limited understanding, I can create a panel to hold these sub-panels, and then add a action listener to the '+' button to create new panels. The only way I could think to implement this is to create a constructor for the panel I want to add. Is this possible? Let me show you what I have:
package com.company;
import java.awt.*;
import javax.swing.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeGui extends JFrame{
protected int panelCount;
//row 1
JPanel row1 = new JPanel();
JLabel splitSnakeLabel = new JLabel("Create a Split Snake", JLabel.CENTER);
//row 2
JPanel row2 = new JPanel();
JButton addButton = new JButton("+");
public MainSnakeGui() {
super("Snake Channels");
setSize(550, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout layout = new GridLayout(5, 1, 10, 10);
setLayout(layout);
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row1.setLayout(layout1);
row1.add(splitSnakeLabel);
add(row1);
GridLayout layout2 = new GridLayout(1, 2, 10, 10);
row2.setLayout(layout2);
row2.add(addButton);
MainSnakeConstructor snakePanel = new MainSnakeConstructor();
row2.add(snakePanel);
add(row2);
setVisible(true);
}
public static void setLookAndFeel () {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
}
public static void main(String[] arg) {
MainSnakeGui.setLookAndFeel();
MainSnakeGui frame = new MainSnakeGui();
}
}
Here is the constructor:
package com.company;
import javax.swing.*;
import java.awt.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeConstructor extends JFrame {
public MainSnakeConstructor () {
JPanel splitSnakeRow = new JPanel();
JLabel snakeNameLabel = new JLabel("Snake Name");
JLabel channelCountLabel = new JLabel("Channel Count");
JCheckBox artistSuppliedCheckBox = new JCheckBox("Artist Supplied?");
JTextField snakeNameTextField = new JTextField(30);
JTextField channelCountTextField = new JTextField(3);
GridLayout layout = new GridLayout(3,2,10,10);
splitSnakeRow.setLayout(layout);
splitSnakeRow.add(snakeNameLabel);
splitSnakeRow.add(channelCountLabel);
splitSnakeRow.add(artistSuppliedCheckBox);
splitSnakeRow.add(snakeNameTextField);
splitSnakeRow.add(channelCountTextField);
add(splitSnakeRow);
}
}
Think about it differently. You want a button that allows you to add new panels, so you really only need a single button.
From there, you need some kind common panel which provides the functionality you want to the user (the creation panel). Then, when the user clicks the add button, you create a new creation panel and add it to the container been used to display them, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btnAdd = new JButton("+");
setLayout(new BorderLayout());
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttons.add(btnAdd);
add(buttons, BorderLayout.NORTH);
JPanel content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
content.add(new JPanel(), gbc);
add(new JScrollPane(content));
btnAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CreationPane pane = new CreationPane();
int insertAt = Math.max(0, content.getComponentCount() - 1);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
content.add(pane, gbc, insertAt);
content.revalidate();
content.repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class CreationPane extends JPanel {
private static int count;
public CreationPane() {
setLayout(new GridBagLayout());
add(new JLabel("Make it so " + (count++)));
setBorder(new CompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
}
}
}
Now having done all that, I prefer the VerticalLayout manager from SwingLabs, SwingX library, which basically does the same thing...
I have problems with GridBagLayout. I have to replace a component but after inserting the new one the positions change. See the following code as example.
At the start it is CYAN and YELLOW (from left to the right). After replacing it is YELLOW and RED. My desired result is RED and YELLOW. How can I fix this (with GridBagLayout)?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GBLTest extends JFrame
{
public static void main(String [] args)
{
new GBLTest();
}
JPanel panelA;
JPanel panelB;
JPanel panelAReplacement;
GBLTest()
{
this.setLayout(new GridBagLayout());
GridBagConstraints cons = new GridBagConstraints();
cons.weightx = 1.0;
cons.weighty = 1.0;
cons.fill = GridBagConstraints.BOTH;
panelA = new JPanel();
panelA.setBackground(Color.CYAN);
panelB = new JPanel();
panelB.setBackground(Color.YELLOW);
panelAReplacement = new JPanel();
panelAReplacement.setBackground(Color.RED);
cons.anchor = GridBagConstraints.EAST;
this.add(panelA, cons);
cons.anchor = GridBagConstraints.WEST;
this.add(panelB, cons);
GridBagConstraints oldCons = ((GridBagLayout) this.getContentPane().getLayout()).getConstraints(panelA);
this.remove(panelA);
this.add(panelAReplacement, oldCons);
this.setSize(new Dimension(200, 200));
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
}
I think you are not using the correct Layout for this pourpose.
You should use BorderLayout instead GridBagLayout. Or use the gridx and gridy properties to set the cell where each panel should be allocated.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GBLTest extends JFrame
{
public static void main(String [] args)
{
new GBLTest();
}
JPanel panelA;
JPanel panelB;
JPanel panelAReplacement;
GBLTest()
{
this.setLayout(new GridBagLayout());
GridBagConstraints consA = new GridBagConstraints();
consA.weightx = 1.0;
consA.weighty = 1.0;
consA.fill = GridBagConstraints.BOTH;
consA.gridx = 0;
consA.gridy = 0;
GridBagConstraints consB = new GridBagConstraints();
consB.weightx = 1.0;
consB.weighty = 1.0;
consB.fill = GridBagConstraints.BOTH;
consB.gridx = 1;
consB.gridy = 0;
panelA = new JPanel();
panelA.setBackground(Color.CYAN);
panelB = new JPanel();
panelB.setBackground(Color.YELLOW);
panelAReplacement = new JPanel();
panelAReplacement.setBackground(Color.RED);
consA.anchor = GridBagConstraints.EAST;
this.add(panelA, consA);
consA.anchor = GridBagConstraints.WEST;
this.add(panelB, consB);
GridBagConstraints oldCons = ((GridBagLayout) this.getContentPane().getLayout()).getConstraints(panelA);
this.remove(panelA);
this.add(panelAReplacement, oldCons);
this.setSize(new Dimension(200, 200));
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
}
}
I am making an application for which I am using a BoxLayout. As you can see in the following picture, when the title string is short, it's perfect. But as the string gets longer, the JLabel gets more and more misaligned.
Here's some code that is related to the problem:
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.PAGE_AXIS));
frame.add(centerPanel, BorderLayout.CENTER);
//...
JLabel l = new JLabel(/*...*/);
l.setHorizontalAlignment(SwingConstants.CENTER); //I tried removing and adding
//this but nothing changed
centerPanel.add(l);
Is there something obvious I am missing? Google isn't being helpful with this problem.
In case it's important, the country-label-progress-bar things are just JPanels with FlowLayouts.
SSCCE:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SSCCE {
public static void main(String[] args) {
final JFrame f = new JFrame("SSCCE");
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
final JLabel[] titles = new JLabel[5];
JPanel[] smallPanels = new JPanel[titles.length];
for (int i = 0; i < smallPanels.length; i ++) {
titles[i] = new JLabel(Math.random() < 0.5 ? "foo" : "bar");
p.add(titles[i]);
smallPanels[i] = new JPanel();
smallPanels[i].add(new JLabel("foobar"));
smallPanels[i].add(new JProgressBar());
p.add(smallPanels[i]);
}
f.add(p, BorderLayout.CENTER);
final JTextField tf = new JTextField("foobar");
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
titles[2].setText(tf.getText());
f.repaint();
}
});
f.add(tf, BorderLayout.NORTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 600);
f.setVisible(true);
}
}
To operate the SSCCE, type something in the text field and press enter.
Here is an updated version of your SSCCE with a GridBagLayout. Not sure of how you want components to resize when labels or frame size changes but it should not be too hard to manage this.
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
public class SSCCE {
public static void main(String[] args) {
final JFrame f = new JFrame("SSCCE");
JPanel p = new JPanel();
p.setLayout(new GridBagLayout());
Insets insets = new Insets(3, 3, 3, 3);
GridBagConstraints gbc1 = new GridBagConstraints();
gbc1.gridwidth = GridBagConstraints.REMAINDER;
gbc1.anchor = GridBagConstraints.CENTER;
gbc1.insets = insets;
GridBagConstraints gbc2 = new GridBagConstraints();
gbc2.anchor = GridBagConstraints.EAST;
gbc2.insets = insets;
GridBagConstraints gbc3 = new GridBagConstraints();
gbc3.weightx = 1.0;
gbc3.fill = GridBagConstraints.HORIZONTAL;
gbc3.gridwidth = GridBagConstraints.REMAINDER;
gbc3.insets = insets;
final JLabel[] titles = new JLabel[5];
Random random = new Random();
for (int i = 0; i < titles.length; i++) {
titles[i] = new JLabel(Math.random() < 0.5 ? "foo" : "bar");
p.add(titles[i], gbc1);
p.add(new JLabel("foobar"), gbc2);
JProgressBar progress = new JProgressBar();
progress.setStringPainted(true);
progress.setString(String.valueOf(random.nextInt(100)));
p.add(progress, gbc3);
}
f.add(p, BorderLayout.CENTER);
final JTextField tf = new JTextField("foobar");
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
titles[2].setText(tf.getText());
f.repaint();
}
});
f.add(tf, BorderLayout.NORTH);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
BoxLayout accepting Min, Max and PreferredSize, childs could be resizable from Min to MaxSize
FlowLayout accepting only PreferredSize, rest (Min, MaxSize) is ignored by this LayoutManager, childs aren't resizable
these XxxSize are calculated from PreferredSize came from childs placed into container (JPanel in this case)
(your question) for better help sooner post an SSCCE, short, runnable, compilable, just about your issue