GridBagLayout centering components - java

I have been trying for a while to make this work.
I have looked at many tutorials and examples on-line, nothing seems to help.
The combo box and the label are both centered right under each other in the middle of the frame.
I know that there needs to be a GridBagConstraints and you need to set the gbc every time you add a new component.
I am doing that so I am not sure why it's not working.
Also why would it be in the center?
Shouldn't it be in the top left if anything?
public class Application {
ArrayList listOfTickers = new ArrayList();
JFrame frame;
JPanel panel;
JLabel jLabel;
GridBagLayout layout;
GridBagConstraints gbc;
JComboBox comboBox;
Application(ArrayList listOfTickers) throws BadLocationException {
this.listOfTickers = listOfTickers;
setLabels();
setComboBox(listOfTickers);
setFrameAndPanel();
addComponents();
closeFrame();
}
private void addComponents() {
addobjects(jLabel, panel, layout, gbc, 1, 3, 4, 2);
addobjects(comboBox, panel, layout, gbc, 3, 0, 2, 1);
}
private void setLabels() {
jLabel = new JLabel("test");
}
private void closeFrame() {
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private void setComboBox(ArrayList listOfTickers) throws BadLocationException {
comboBox = new JComboBox(listOfTickers.toArray());
comboBox.addActionListener(e -> {
String ticker = comboBox.getSelectedItem().toString();
});
}
private void setFrameAndPanel() {
frame = new JFrame("JFrame Example");
panel = new JPanel();
layout = new GridBagLayout();
panel.setLayout(layout);
frame.getContentPane().setLayout(layout);
gbc = new GridBagConstraints();
frame.add(panel);
frame.setSize(600, 600);
}
public void addobjects(Component component, Container panel, GridBagLayout layout, GridBagConstraints gbc, int gridx, int gridy, int gridwidth, int gridheight) {
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.gridwidth = gridwidth;
gbc.gridheight = gridheight;
layout.setConstraints(component, gbc);
panel.add(component, gbc);
}
}

Also why would it be in the center? Shouldnt it be in the top left if anything?
No, this is how GridBagLayout works, GridBagLayout will layout it's components around the centre of the container. You can play around with the weightx/y properties to change how much of the remaining space is allocated to a given cell.
I would also recommend avoid gridwidth and gridheight until you have a better understanding of what these do, as they are effecting the position of your components
The following will move the components to the top/left point of the container...
private void addComponents() {
gbc.gridx = 1;
gbc.gridy = 3;
gbc.weighty = 1;
gbc.anchor = GridBagConstraints.NORTHWEST;
panel.add(jLabel, gbc);
gbc.gridx = 3;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.weightx = 1;
gbc.weighty = 0;
panel.add(comboBox, gbc);
}
Although, since you're applying a GridBagLayout to the JFrame itself, I'd be tempted to change the weightx/y and anchor properties for the panel itself when you add it to the frame, it will make it much simpler
so if I wanted to let say build a calculator with positioning the buttons in specific areas, essentially transforming the entire panel into one big grid and plotting my containers inside that grid what would be the best layout to use and how would I do that?
That depends ultimately on what you want the UI to look like. If all you want is for all the buttons to evenly occupy the available space, the maybe GridLayout would be a better choice...
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Application {
public static void main(String[] args) {
new Application();
}
public Application() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(4, 3));
String labels[] = new String[] {"7", "8", "9", "4", "5", "6", "1", "2", "3", "", "0", ""};
for (String label : labels) {
if (label.trim().isEmpty()) {
add(new JLabel());
} else {
add(new JButton(label));
}
}
}
}
}
Note, I had to allow for two empty spaces around the 0 button, this is a requirement of GridLayout, as you don't get control over which cells the components actually appear, they are simply laid out in a linear fashion.
However, if you would prefer something that looks more like most calculators, then you'll need GridBagLayout...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Application {
public static void main(String[] args) {
new Application();
}
public Application() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
String labels[][] = new String[][]{{"7", "8", "9"}, {"4", "5", "6"}, {"1", "2", "3"}};
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
for (String[] row : labels) {
gbc.gridx = 0;
for (String col : row) {
add(new JButton(col), gbc);
gbc.gridx++;
}
gbc.gridy++;
}
gbc.gridx = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = 3;
add(new JButton("0"), gbc);
}
}
}
Needs drive musts, you need to decide on the need of flexibility over uniformity (in this case). GridBagLayout is very powerful and flexible, but with it comes complexity.
Note: I could have done the second layout using two panels and two GridLayouts as well - which is an important concept, you're not stuck to a single layout manager, you can use multiple panels, each using different layout managers and "compound" them together to produce a rich interface

If you're going to be doing much UI building, it would greatly benefit you to download the Netbeans IDE and learn to use its GUI builder. It's an excellent GUI builder, and the visual feedback you get as you tweak layout parameters is incredibly helpful for getting the hang of UI building, and especially for getting the hang of how the various GridBagLayout parameters work. It's much more efficient for experimentation than a "write-run-tweak-rerun" loop.
Manually writing UI code is my least favorite thing. Don't inflict it on yourself if possible!

Related

Changing the constraints of a component in a GridBagLayout after they've been added to the frame

I've seen two other posts on stackoverflow about this and in both, the solutions use setConstraints(myComponent, anotherConstraint) which doesn't even come up as an available method when I try to use it in java.
want to change an Inset in a gridbag layout dynamically
Change the component weight dynamically in GridBagLayout
How else could I change the weightx of a component after a button press?
The actual problem is that I have two components at the bottom of the screen and I need to set one of the components to be the max width of the screen after a button press.
I couldn't get setConstraints() to work..
Then it seems the code was wrong. From the fact the RHS of the red panel neatly aligns with the LHS of the Articuno label I suspect that the grid bag cell containing the red panel does not span more than one column, and currently entirely fills that column.
There could be other reasons, but short a minimal reproducible example I won't speculate further.
Here is a simplified example showing how to do it. Note that it was necessary to call revalidate() before the changes could be seen.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.image.BufferedImage;
public class FullWidthToggle {
private JComponent ui = null;
FullWidthToggle() {
initUI();
}
public final void initUI() {
if (ui != null) {
return;
}
GridBagConstraints gbc = new GridBagConstraints();
GridBagLayout gbl = new GridBagLayout();
ui = new JPanel(gbl);
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
BufferedImage image = new BufferedImage(
160, 20, BufferedImage.TYPE_INT_RGB);
gbc.insets = new Insets(5, 5, 5, 5);
ui.add(new JLabel(new ImageIcon(image)), gbc);
final JCheckBox checkBox = new JCheckBox("Full Width");
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.LINE_START;
ui.add(checkBox, gbc);
final JLabel label = new JLabel("Am I full width?");
label.setBorder(new LineBorder(Color.RED, 2));
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 2;
ui.add(label, gbc);
ActionListener actionListener = (ActionEvent e) -> {
if (checkBox.isSelected()) {
gbc.fill = GridBagConstraints.HORIZONTAL;
} else {
gbc.fill = GridBagConstraints.NONE;
}
gbl.setConstraints(label, gbc);
ui.revalidate(); // <- important!
};
checkBox.addActionListener(actionListener);
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = () -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
FullWidthToggle o = new FullWidthToggle();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
};
SwingUtilities.invokeLater(r);
}
}

Drawing graphics on a panel

I am trying to draw graphics on panels, but I am not sure how I would go about doing that.
I have tried creating a class that extends the JPanel and overrided paintComponent, and some other methods, but nothing gets rendered at all.
Here is my code:
edit:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Lesson1 extends JFrame {
private static final long serialVersionUID = -198253288329146091L;
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Lesson1 frame = new Lesson1();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Lesson1() {
contentPane = new JPanel();
setContentPane(contentPane);
JPanel panel = new JPanel() {
private static final long serialVersionUID = -5974584127539186578L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 500, 500);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
};
contentPane.add(panel);
JPanel panel_1 = new JPanel() {
private static final long serialVersionUID = 123456789L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.PINK);
g.fillRect(0, 0, 200, 200);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
panel.setLayout(new BorderLayout());
panel_1.setLayout(new BorderLayout());
panel.add(panel_1);
}
}
I am not sure what I am doing wrong here, but I have tried everything I could. Thanks!
Mistake #1
contentPane.setLayout(null);
and
panel.setLayout(null);
Before you do anything else, you need to learn and understand what the layout managers actually do and why null layouts are naive and not recommended (especially when you're just learning).
Start by taking the time to go through Laying Out Components Within a Container
Remove contentPane.setLayout(null); and change panel.setLayout(null); to panel.setLayout(new BorderLayout()); and you will see an immediate change.
In fact, you really don't need panel, as the default contentPane of a JFrame is already setup to use BorderLayout.
This means you can get rid of panel.setBounds(73, 52, 231, 143);
Mistake #2
Okay, this is more of an oversight, but, when you start customising components, you need to provide sizing hints, which allows the layout managers to make decisions about how best to layout your component in relationship to other components and based on it's own internal rules.
To this end, you should, at the very least, override the getPreferredSize method (avoid the setXxxSize methods as these can lead to unexpected results if used incorrectly)
Add...
#Override
public Dimension getPreferredSize() {
return new Dimension(1001, 1001);
}
to panel_1
This now means you can do something more like...
Lesson1 frame = new Lesson1();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
and the window will pack it self around the component (and be centred on the screen) and you can get rid of setBounds(100, 100, 450, 300);
Alright, anyways I tried but have no luck making it so I can set panels in a specific position :/
Layout management in a GUI environment is part science, part voodoo, part black magic
Pixel perfect positioning is an illusion in modern UI development. There are so many factors which go into determining "how" a component should be positioned on a single platform, let along across multiple platforms, you'd spend the rest of your live constantly adding "hacks" to account for the infinite number of possible edge case.
This is why any decent UI framework abstracts the concept, Swing uses the layout manager API for this purpose, iOS (and MacOS) use Auto layout, etc...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Lesson1 {
/**
* Launch the application.
*/
public static void main(String[] args) {
new Lesson1();
}
public Lesson1() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.NORTHWEST;
add(new RectPane(), gbc);
gbc.gridx = 2;
gbc.anchor = GridBagConstraints.NORTHEAST;
add(new RectPane(), gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.weightx = 1;
gbc.weighty = 1;
add(new RectPane(), gbc);
gbc.weightx = 0;
gbc.weighty = 0;
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.SOUTHWEST;
add(new RectPane(), gbc);
gbc.gridx = 2;
gbc.anchor = GridBagConstraints.SOUTHEAST;
add(new RectPane(), gbc);
}
// This is just to demonstrate how the layout works when the avaliable
// space is larger then the desired space, you don't need this
// and should get rid of it and just let the layout manager calculate
// it's desired size based on it's content
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
}
public class RectPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 100, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
}
}
Understand, GridBagLayout IS the most complex layout manager in the standard API, but it is the most flexible. You're also not confined to a single layout manager, you can use compound layouts to create very advanced interfaces

How to make jLabels stay attached to the corners of a window form, despite resizing the form in java?

I have 4 jLabels in my java program, which i placed in 4 corners I want them to stay there despite user resizing the window. I have written the code for the labels, but cannot seem to figure out how to keep them glued to each corner.
here is my code for the jLabels
JLabel label_1 = new JLabel("");
label_1.setEnabled(false);
label_1.setBounds(0, 0, 19, 19);
contentPane.add(label_1);
JLabel label_2 = new JLabel("");
label_2.setEnabled(false);
label_2.setBounds(0, 242, 19, 19);
contentPane.add(label_2);
JLabel label_3 = new JLabel("");
label_3.setEnabled(false);
label_3.setBounds(549, 242, 19, 19);
contentPane.add(label_3);
JLabel label_4 = new JLabel("");
label_4.setEnabled(false);
label_4.setBounds(549, 0, 19, 19);
contentPane.add(label_4);
Thanks
Don't use null layouts
Don't use setBounds(...)
Do use proper layout managers. Read the Layout Manager Tutorials for all the gory details.
Note that by using a null layout and setBounds, you ham-string your application's layout to being very rigid, very difficult to debug, enhance, and modify, and you also create a GUI that might look good on your box, but likely will not look good on another box using a different OS, or even the same OS with a slightly different screen resolution.
For example, using a GridBagLayout:
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout extends JPanel {
private static final int[] ANCHORS = {NORTHWEST, SOUTHWEST, NORTHEAST, SOUTHEAST};
public LabelLayout() {
setLayout(new GridBagLayout());
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i / 2;
gbc.gridy = i % 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
add(new JLabel("Label " + (i + 1)), gbc);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Labels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new LabelLayout());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
A couple other notes:
I try to avoid using GridBagLayouts since they are one of the more complex layouts, but for your problem, they work nicely and simply.
Your problem can also be solved by using nested JPanels each using a simpler layout such as a BorderLayout.
Demo program, iteration number 2 that shows two GUI's, one using GridBagLayout and the other using nested JPanels, each using BorderLayout:
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
import static java.awt.GridBagConstraints.*;
public class LabelLayout {
private static final int[] ANCHORS = { NORTHWEST, NORTHEAST, SOUTHWEST,
SOUTHEAST };
private JPanel gridBagPanel = new JPanel(new GridBagLayout());
private JPanel borderPanel = new JPanel(new BorderLayout());
public LabelLayout() {
for (int i = 0; i < ANCHORS.length; i++) {
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = i % 2;
gbc.gridy = i / 2;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.anchor = ANCHORS[i];
gridBagPanel.add(new JLabel("Label " + (i + 1)), gbc);
}
JPanel northPanel = new JPanel(new BorderLayout());
JPanel southPanel = new JPanel(new BorderLayout());
northPanel.add(new JLabel("Label 1"), BorderLayout.WEST);
northPanel.add(new JLabel("Label 2"), BorderLayout.EAST);
southPanel.add(new JLabel("Label 3"), BorderLayout.WEST);
southPanel.add(new JLabel("Label 4"), BorderLayout.EAST);
borderPanel.add(northPanel, BorderLayout.NORTH);
borderPanel.add(southPanel, BorderLayout.SOUTH);
}
public JPanel getGridBagPanel() {
return gridBagPanel;
}
public JPanel getBorderPanel() {
return borderPanel;
}
private static void createAndShowGui() {
LabelLayout labelLayout = new LabelLayout();
JFrame frame = new JFrame("Label GridBagLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getGridBagPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame = new JFrame("Label BorderLayout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(labelLayout.getBorderPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Floating JPanel above a JPanel with BorderLayout

I have a JPanel called pnlMain with a layout set to BorderLayout. Inside the panel are three JPanel added to PAGE_START, CENTER, and PAGE_END. Now, my requirement is if the Settings button is clicked, it will display a transparent JPanel above pnlMain. This transparent panel will then contain an opaque, smaller, centered panel, that will contain the settings stuff.
I know I can do this using JLayeredPane, but looking at the tutorial it says that you can only put components of different depth using absolute positioning which I'm aware is highly discouraged.
Is there some other way to do this without using absolute positioning?
You can use the glass pane of the parent frame, which will allow you to add components to it that will appear to overlaid over the main content.
Basically, I would, create a JPanel and set it to be transparent (setOpaque(false)). I would set it's layout manager to something like GridBagLayout (as it will use the preferred size of the child component and center it automatically within it's parent container).
Onto this panel I would then add the Settings panel.
Finally, I would set the parent frame's glass pane to the first (backing) pane and make it visible.
frame.getRootPane().setGlassPane(backingPane); // Or similar
Take a look at How to use Root Panes
Updated
If you can't use the glass pane of the top level frame yourself, then you need to fake it.
This example basically uses a JLayeredPane backed by a GridBagLayout
If you add a MouseListener and KeyListener to the background pane you can consume events going to the child components.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
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.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class FloatingPane {
public static void main(String[] args) {
new FloatingPane();
}
public FloatingPane() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final WorkPane workPane = new WorkPane();
JButton settings = new JButton("Settings");
settings.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
workPane.toggleSettings();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(workPane);
frame.add(settings, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class WorkPane extends JLayeredPane {
private final BackingPane backingPane;
public WorkPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(createLabel("Center", Color.BLUE), gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.VERTICAL;
add(createLabel("Left", Color.RED), gbc);
gbc.gridx = 2;
add(createLabel("Right", Color.GREEN), gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
backingPane = new BackingPane();
backingPane.add(new SettingsPane());
backingPane.setVisible(false);
add(backingPane, gbc);
setLayer(backingPane, DEFAULT_LAYER + 1);
}
public void toggleSettings() {
backingPane.setVisible(!backingPane.isVisible());
}
protected JLabel createLabel(String text, Color bg) {
JLabel label = new JLabel(text);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBackground(bg);
return label;
}
}
public class BackingPane extends JPanel {
public BackingPane() {
setLayout(new GridBagLayout());
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(128, 128, 128, 192));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public class SettingsPane extends JPanel {
public SettingsPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new JLabel("Settings"));
}
}
}
Another solution might be to fake the entire glass pane by taking a snap shot of the current panel and using a CardLayout, flip to the settings pane, using the snap shot as the backgound image for the settings pane (which can could then apply effects to like gray scaling and bluring)

Two JPanels in JFrame , One under other

I've got two panels in my frame, and I would like to set them one under other, and this first should have size like 9/10*screen frame, and this second 1/10.
I've tried with GridLayout (2 rows and one column) but I can't set them specific size.
How should I do that?
ok maybe I will write some my code:
I am writing game - pacman, and in the first panel there is a whole game, and in this second I would like to display player info(like score, name etc.) This first I would like to set on 80% screen, and second on 20%.
What is more my frame should be resizeable and all in it, sa I have to change size of Panels(keeping this 80% to 20%) when size of frame is changing. SO that I wrote this InitComponents().
package pacman;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Toolkit;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import java.awt.Image;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
public class Pacman extends JFrame implements items
{
Image image;
public Pacman()
{
initComponents();
try {
image = ImageIO.read( Pac.class.getResourceAsStream("/img/Pac02.gif"));
} catch (Exception e) {
System.out.println("Blad prz otwieraniu " + e);
System.exit(0);
}
int screen_width = Toolkit.getDefaultToolkit().getScreenSize().width;
int screen_height = Toolkit.getDefaultToolkit().getScreenSize().height;
this.setLocation(screen_width/3, screen_height/3);
this.setLayout(new BorderLayout());
this.getContentPane().add(panel, BorderLayout.CENTER);
this.getContentPane().add(panel2, BorderLayout.PAGE_END);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setIconImage(image);
setTitle("..::Pacman::..");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(416,438));
this.pack();
setLocationRelativeTo(null);
setVisible(true);
}
private void initComponents() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int width = e.getComponent().getSize().width;
int height = e.getComponent().getSize().height;
panel.setSize(width, height*8/10) ;
panel2.setSize(width, height*2/10);
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Pacman();
}
});
}
}
GridLayout is the wrong layout if you want different sized components. As the javadoc states:
The container is divided into equal-sized rectangles, and one
component is placed in each rectangle.
If you've only got JPanels, you might want to consider a JSplitPane - see javadoc or tutorial.
EDIT: Based on your edit/code, a JSplitPane really looks like the solution to your problem. You can then set the divider location after creation using setDividerLocation(double) - see the javadoc - e.g.
JSplitPane split = new JSplitPane(JSplitPane.VERTICAL);
split.setTopComponent(topPanel);
split.setBottomComponent(bottomPanel);
split.setDividerLocation(0.8);
Alternatively, since it's quite hard to suggest a layout without knowing your intentions for the GUI, you should consider taking a look at the Visual Guide to layouts.
Have a look at this output :
And here is the code for that, you are not suppose to use GridLayout when you need to adjust sizes for columns/rows, under such situations comes GridBagLayout to the rescue.
import java.awt.*;
import javax.swing.*;
// http://stackoverflow.com/questions/10968853/two-jpanels-in-jframe-one-under-other
public class GridBagLayoutExample
{
private void displayGUI()
{
JFrame frame = new JFrame("GridBagLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridBagLayout());
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.9;
JPanel topPanel = new JPanel();
topPanel.setOpaque(true);
topPanel.setBackground(Color.WHITE);
contentPane.add(topPanel, gbc);
gbc.weighty = 0.1;
gbc.gridy = 1;
JPanel bottomPanel = new JPanel();
bottomPanel.setOpaque(true);
bottomPanel.setBackground(Color.BLUE);
contentPane.add(bottomPanel, gbc);
frame.setContentPane(contentPane);
frame.setSize(200, 300);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new GridBagLayoutExample().displayGUI();
}
});
}
}
Check out,
Assuming that by under you mean one Jpanel is overlapping another!
http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
cheers!
You can use border layout
http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html
Set the bigger panel to be CENTER, and the smaller to be PAGE_END. Set the size of the bigger panel, and the smaller panel will use what space is left.

Categories

Resources