Need a little GridbagLayout guidance. Please see code below. What I want is for button2 to be twice as wide as buttons 1, 3, and 4. However, all four are actually being displayed with the same width. Obviously doing something wrong, but I can’t figure out what.
Thanks.
import java.awt.*;
import javax.swing.*;
public class GridbagLayoutTetst {
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 250);
JPanel panel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
panel.setLayout(gridbag);
JButton button0 = new JButton("Button 0");
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(button0, c);
panel.add(button0);
JButton button1 = new JButton("Button 1");
c.gridwidth = 1;
gridbag.setConstraints(button1, c);
panel.add(button1);
JButton button2 = new JButton("Button 2");
c.gridwidth = 2;
gridbag.setConstraints(button2, c);
panel.add(button2);
JButton button3 = new JButton("Button 3");
c.gridwidth = 1;
gridbag.setConstraints(button3, c);
panel.add(button3);
JButton button4 = new JButton("Button 4");
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(button4, c);
panel.add(button4);
frame.add(panel);
frame.setVisible(true);
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc) {
//
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
OK, by using a combination of fill, setPreferredSize and weightx I achieved the result I wanted. See below. Now button2 is always twice as wide as the other buttons in that row, even when I resize the frame. Just feels like a hack to me. Would appreciate guidance on the "preferred" way of doing this.
import java.awt.*;
import javax.swing.*;
public class GridbagLayoutTetst {
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 250);
JPanel panel = new JPanel();
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
panel.setLayout(gridbag);
JButton button0 = new JButton("Button 0");
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(button0, c);
panel.add(button0);
JButton button1 = new JButton("Button 1");
button1.setPreferredSize(new Dimension (0,28));
c.weightx = 0.2;
c.gridwidth = 1;
gridbag.setConstraints(button1, c);
panel.add(button1);
JButton button2 = new JButton("Button 2");
button2.setPreferredSize(new Dimension (0,28));
c.weightx = 0.4;
gridbag.setConstraints(button2, c);
panel.add(button2);
JButton button3 = new JButton("Button 3");
button3.setPreferredSize(new Dimension (0,28));
c.weightx = 0.2;
gridbag.setConstraints(button3, c);
panel.add(button3);
JButton button4 = new JButton("Button 4");
button4.setPreferredSize(new Dimension (0,28));
c.gridwidth = GridBagConstraints.REMAINDER;
gridbag.setConstraints(button4, c);
panel.add(button4);
frame.add(panel);
frame.setVisible(true);
System.out.println(button1.getPreferredSize());
}
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
);
} catch (Exception exc) {
//
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
Related
when I double click the swing jar,it displays normal .button,textfield and label are displayed as expected.
but after some time,JPanel is automaticly resized to minimum as below shows.
I have already set frame setResizable(false)
anyone can give some ideas?
public TestSwing() {
super(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
log = new JTextArea(18, 45);
log.setMargin(new Insets(5, 5, 5, 5));
log.setEditable(true);
logScrollPane = new JScrollPane(log);
DefaultCaret caret = (DefaultCaret) log.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
btn_source = new JButton("open");
btn_dest = new JButton("open");
lbl_sourceFile = new JLabel("Source Excel File:");
lbl_destFile = new JLabel("Destination XML Folder:");
txt_source = new JTextField(45);
txt_dest = new JTextField(45);
btn_convert = new JButton("Convert");
c.fill = GridBagConstraints.VERTICAL;
c.insets = new Insets(0, 0, 0, 0);
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
add(lbl_sourceFile, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 1;
c.gridy = 0;
c.gridwidth = 1;
add(txt_source, c);
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 2;
c.gridy = 0;
c.insets = new Insets(0, 10, 2, 0);
c.gridwidth = 1;
add(btn_source, c);
}
public void actionPerformed(ActionEvent e) {}
private static void createAndShowGUI() {
JFrame frame = new JFrame("TestLink Converter");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestSwing());
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
frame.add(new TLSwing());
We don't know what "TLSing()" class is, but I would guess it is a panel that uses a GridBagLayout. When there is no enough space to show the component at its preferred size, the component will be displayed at its minimum size so your text components shrink.
I have already set frame setResizable(false)
You should set the resize state BEFORE you pack() the frame.
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
//frame.setResizable(false);
How can I replace a JPanel or JFrame & its contents with another one by a simple button click in the same container ?
here a simple example that you can follow please show code at lest so we can follow your problem this a snap of code from unknowing source (old one)
package layout;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class CardLayoutExample extends JFrame{
JPanel totelPanel,btnPan,showPan;
JButton btn1,btn2;
public static void main(String[] args) {
CardLayoutExample ex = new CardLayoutExample();
ex.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ex.pack();
ex.setLocationRelativeTo(null);
ex.setTitle("BookClube library system");
ex.setVisible(true);
}
public CardLayoutExample(){
btn1 = new JButton("menu button");
btn2 = new JButton("back button");
CardLayout c1 = new CardLayout();
btnPan = new JPanel();
btnPan.add(btn1);
showPan = new JPanel();
showPan.add(btn2);
totelPanel = new JPanel(c1);
totelPanel.add(btn1,"1");
totelPanel.add(btn2,"2");
c1.show(totelPanel,"1");
JPanel fullLayout = new JPanel(new BorderLayout());
fullLayout.add(totelPanel,BorderLayout.NORTH);
add(fullLayout);
btn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
c1.show(totelPanel,"2");
}
});
btn2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
c1.show(totelPanel,"1");
}
});
}
}
The trick would be to use CardLayout or modify panel visibility.
Please look at the following example that modifies panel visibility.
public class PanelExample {
private JPanel _myPanel1,_myPanel2;
public void init() {
JFrame frame = new JFrame("Testing");
JPanel mainPanel = new JPanel(new GridBagLayout());
_myPanel1 = new JPanel();
_myPanel1.add(new JLabel("Panel 1"));
_myPanel1.setVisible(true);
_myPanel2 = new JPanel();
_myPanel2.add(new JLabel("Panel 2"));
_myPanel2.setVisible(false);
JButton button = new JButton("Switch to Panel2");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(_myPanel1.isVisible()) {
_myPanel1.setVisible(false);
_myPanel2.setVisible(true);
button.setText("Switch to Panel1");
} else {
_myPanel1.setVisible(true);
_myPanel2.setVisible(false);
button.setText("Switch to Panel2");
}
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.PAGE_START;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.weighty = 0;
mainPanel.add(button,gbc);
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = 2;
gbc.gridheight = 2;
gbc.weightx = 1;
gbc.weighty = 1;
mainPanel.add(_myPanel1,gbc);
mainPanel.add(_myPanel2,gbc);
frame.add(mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
PanelExample exmp = new PanelExample();
exmp.init();
}
}
I am trying to align a button using the GridBagLayout but it look I just can't achieve that. Also I want to remove the JButton's texture from my custom button, but I can not.. This is what it looks like:
I want the buttons to be at the top( but using GridBagLayout) and also on the left and right margin of the green button there is the remains of the JButton style and I can't remove it completely.
Also, this is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestPanel{
public TestPanel(){
JFrame frame = new JFrame();
frame.add(new Panel1());
frame.setVisible(true);
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new TestPanel();
}
public class Panel1 extends JPanel{
/**
*
*/
private static final long serialVersionUID = 1L;
public Panel1(){
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
ImageIcon im = new ImageIcon("Start.png");
ImageIcon i = new ImageIcon("Start-Pressed.png");
JButton button = new JButton(im);
JButton but = new JButton("BUT");
button.setRolloverEnabled(true);
Insets margin = new Insets(-15,-10,-10,-10);
button.setBorderPainted(false);
button.setMargin(margin);
button.setRolloverIcon(i);
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx=0.5;
c.gridx=0;
c.gridy=0;
add(button, c);
c.gridx=2;
c.gridy=1;
add(but,c);
}
}
}
Edit:
c.gridy++;
c.fill = GridBagConstraints.VERTICAL;
c.weighty = 1;
c.add(new JLabel(" "),c);
c.gridy++;
c.weighty = 1;
c.fill = GridBagConstraints.NONE;
add(eButton, c);
You can achive it with help of dummy JLabel at bottom, like next(add to the end of constructor):
c.gridy++;
c.fill = GridBagConstraints.VERTICAL;
c.weighty = 1;
add(new JLabel(" "), c);
To remove margin you can try setContentAreaFilled() method
Instead of ImageIcon im = new ImageIcon("Start.png"); use ImageIcon im = new ImageIcon(Panel1.class.getResource("Start.png"));
Also see that answer.
I am relatively new to Java Swing and I am having a little trouble understanding how Grid layouts can do certain things and if they can't, then how the gridbag layout, which is supposedly more powerful can do that.
Here is a program i tried with Grid layout
import javax.swing.*;
import java.awt.*;
//import java.awt.event.*;
public class Swing24
{
public static void main(String[] args)
{
JFrame f1= new JFrame("Grid Layout Test");
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setResizable(true);
f1.setLocation(500,200);
f1.setSize(600,600);
JPanel p1 = new JPanel();
p1.setBackground(Color.black);
f1.add(p1);
JButton b1= new JButton("Button 1");
b1.setBackground(Color.white);
JButton b2= new JButton("Button 2");
b2.setBackground(Color.white);
JButton b3= new JButton("Button 3");
b3.setBackground(Color.white);
JLabel lb1=new JLabel(" Label 1");
lb1.setForeground(Color.orange);
//lb1.setOpaque(true);
lb1.setBackground(Color.yellow);
JLabel lb2=new JLabel(" Label 2");
lb2.setBackground(Color.orange);
lb2.setOpaque(true);
GridLayout glm1=new GridLayout(2,3,0,0);
p1.setLayout(glm1);
p1.add(b1);
p1.add(b2);
p1.add(b3);
p1.add(lb1);
p1.add(lb2);
f1.setVisible(true);
}
}
The above program allows me divide the container into 2 rows and 3 columns. Basically I can divide a container into m rows and n columns with a grid layout. But it adds the components(the butons and labels) serially.
Question 1: How can I directly add a button to the cell(4,3) in a grid of size(10,10)?
Question 2: Can a button occupy multiple cells in a grid layout?
If the answer to any of the above is not possible, then how can gridbag layout help solve the problem.
I tried using gridbag layout with a button. But it gets placed in the center! How can I, say, place it to the cell(4,3) in a container which can be divided into size(10,10)<10 rows and 10 columns>
1) You can't add component to specific cell,but inthat question you can find some type of trick for that.
2)Here is another trick with nested lyout inside cells, for merging.
You can do all what you want with help of GridBagLayout. Watch GridBagConstraints it helps you to layout components properly.
See properties of GridBagConstraints:
gridwidth, gridheight, gridx, gridy, anchor.
But you would need some trick with empty spaces around cell(4,3) , if you want to add only one component to your container.
Also read tutorial for GridBagLayout.
EDIT: you can try something like this
public class Form extends JFrame {
public Form() {
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
for(int i =0;i<10;i++){
c.gridx = i;
for(int j =0;j<10;j++){
c.gridy = j;
if(i == 3 && j == 2){
c.fill = GridBagConstraints.NONE;
getContentPane().add(new JButton("btn"),c);
} else {
c.fill = GridBagConstraints.BOTH;
JPanel p = new JPanel();
p.setBorder(BorderFactory.createLineBorder(Color.red));
getContentPane().add(p,c);
}
}
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Form().setVisible(true);
}
});
}
}
EDIT2: It's not realy cell(4,3) but in same proportions
public Form() {
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 0.2;
c.weighty = 0.3;
c.fill = GridBagConstraints.BOTH;
getContentPane().add(new JLabel(" "),c);
c.gridx++;
c.gridy++;
c.fill = GridBagConstraints.NONE;
getContentPane().add(new JButton("btn"),c);
c.weightx = 0.7;
c.weighty = 0.6;
c.gridx++;
c.gridy++;
c.fill = GridBagConstraints.BOTH;
getContentPane().add(new JLabel(" "),c);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
}
or real cell(4,3), but more then 3 components and less then 100:
public Form() {
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
for(int i =0;i<2;i++){
getContentPane().add(new JLabel(" "),c);
c.gridx++;
}
for(int i =0;i<3;i++){
getContentPane().add(new JLabel(" "),c);
c.gridy++;
}
c.gridx = 3;
c.gridy = 4;
getContentPane().add(new JButton("btn"),c);
for(int i =0;i<7;i++){
getContentPane().add(new JLabel(" "),c);
c.gridx++;
}
for(int i =0;i<6;i++){
getContentPane().add(new JLabel(" "),c);
c.gridy++;
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
}
I've attached a screenshot for which the following Border legend applies:
Yellow = JPanel with BorderLayout
Blue = JPanel with GridBagLayout
Fuchsia = JPanel with FlowLayout
There are two panels not blocked out in colors that warrant mentioning:
1) The title panel where the word "Primary" is displayed; this panel is at BorderLayout.NORTH in "Yellow" panel.
2) The image panel where the image of the device is located; this panel is a sibling to "Fuchsia"
"Blue" is at BorderLayout.CENTER in "Yellow" while "Fuchsia" and the image panel are given the following constraints:
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1.0;
c.weighty = 1.0;
c.gridx = 0;
c.gridy = 0;
c.anchor = GridBagConstraints.NORTHWEST;
c.insets = new Insets(0, 10, 0, 0);
c.fill = GridBagConstraints.BOTH;
//"Blue".add(imagePanel, c);
c.weighty = 0.80;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
//"Blue".add("Fuchsia", c);
As you can probably tell from the image, I'm trying to get rid of the "wasted" space in "Blue" right below "Fuchsia". I don't seem to be able to do it with GridBagConstraints, so am I just using the wrong LayoutManager? It looks to me like "Blue", who is at CENTER in the BorderLayout is just giving each child JPanel half of the available space and reserving the remainder space instead of contracting upward. What am I missing here? Is this simply a matter of setting a preferred or maximum size on "Fuchsia"? it doesn't seem like that will get me where I want to be, since the border around "Fuchsia" (which is covered by my color coding) is where I want the end of the component to be.
Have a look at this output, from this code example :
import java.awt.*;
import javax.swing.*;
public class LayoutTest
{
private void displayGUI()
{
JFrame frame = new JFrame("Layout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBackground(Color.YELLOW);
contentPane.setLayout(new BorderLayout(2, 2));
JPanel topPanel = new JPanel();
topPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
JLabel headingLabel = new JLabel("Primary");
topPanel.add(headingLabel);
contentPane.add(topPanel, BorderLayout.PAGE_START);
JPanel centerPanel = new JPanel();
centerPanel.setOpaque(true);
centerPanel.setBackground(Color.BLUE);
centerPanel.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 1.0;
gbc.weighty = 0.2;
gbc.gridx = 0;
gbc.gridy = 0;
JPanel imagePanel = new JPanel();
JLabel imageLabel = null;
try
{
imageLabel = new JLabel(
new ImageIcon(
new java.net.URL(
"http://pscode.org/"
+ "tame/screenshot/"
+ "landscape/slider1.gif")));
}
catch(Exception e)
{
e.printStackTrace();
}
imagePanel.add(imageLabel);
centerPanel.add(imagePanel, gbc);
JPanel detailsPanel = new JPanel();
detailsPanel.setOpaque(true);
detailsPanel.setBackground(Color.WHITE);
detailsPanel.setBorder(
BorderFactory.createEmptyBorder(
5, 5, 5, 5));
detailsPanel.setLayout(new GridLayout(0, 1, 5, 5));
JLabel statusLabel = new JLabel("Chassis Status : ");
JLabel usageLabel = new JLabel("Bandwidth Usage : ");
JLabel fanLabel = new JLabel("Fan Status : ");
detailsPanel.add(statusLabel);
detailsPanel.add(usageLabel);
detailsPanel.add(fanLabel);
gbc.fill = GridBagConstraints.BOTH;
gbc.weighty = 0.8;
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridheight = 3;
centerPanel.add(detailsPanel, gbc);
contentPane.add(centerPanel, BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new LayoutTest().displayGUI();
}
});
}
}
Without using GridBagLayout could be
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
public class NestedLayout {
private JFrame frame = new JFrame();
private JPanel yellowNorthPanel = new JPanel();
private JPanel yellowPanel = new JPanel();
private JPanel bluePanel = new JPanel();
private JPanel fuchsiaTopPanel = new JPanel();
private JPanel fuchsiaBottonPanel = new JPanel();
public NestedLayout() {
yellowNorthPanel.setBorder(new LineBorder(Color.yellow, 5));
yellowPanel.setLayout(new BorderLayout());
yellowPanel.setBorder(new LineBorder(Color.yellow, 5));
bluePanel.setLayout(new BorderLayout(5, 5));
bluePanel.setBorder(new LineBorder(Color.blue, 5));
fuchsiaTopPanel.setBorder(new LineBorder(Color.cyan, 5));
fuchsiaBottonPanel.setBorder(new LineBorder(Color.cyan, 5));
bluePanel.add(fuchsiaTopPanel, BorderLayout.NORTH);
bluePanel.add(fuchsiaBottonPanel);
yellowPanel.add(bluePanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(yellowNorthPanel, BorderLayout.NORTH);
frame.add(yellowPanel);
//frame.pack();
frame.setSize(400, 300);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new NestedLayout();
}
});
}
}