I have a JFrame and three JPanels. On the frame I used BorderLayout. At the CENTER of the frame I have put outerPanel. On my outerPanel I have used MigLayout. The two other panels are added on to the outerPanel. These two panels are of equal size and their widths add up to the width of the outerPanel - I wanted the outerPanel to be divided into two halves. Below is the code for this:
public class ControlPanel extends JFrame {
// components
public JPanel outerPanel;
public JPanel innerPanel1;
public JPanel innerPanel2;
public ControlPanel() {
this.createUI();
}
public void createUI() {
// form properties
this.setSize(new java.awt.Dimension(300, 300));
this.setVisible(true);
this.setLayout(new java.awt.BorderLayout());
this.outerPanel = new JPanel();
this.outerPanel.setPreferredSize(new java.awt.Dimension(260, 250));
this.outerPanel.setLayout(new net.miginfocom.swing.MigLayout());
this.outerPanel.setBorder(BorderFactory.createEtchedBorder());
this.add(new javax.swing.JLabel("North"), BorderLayout.NORTH);
this.add(this.outerPanel, BorderLayout.CENTER);
this.innerPanel1 = new JPanel();
this.innerPanel1.setPreferredSize(new java.awt.Dimension(130, 150));
this.innerPanel1.setLayout(new net.miginfocom.swing.MigLayout());
this.innerPanel1.setBorder(BorderFactory.createTitledBorder("Panel1"));
this.innerPanel2 = new JPanel();
this.innerPanel2.setPreferredSize(new java.awt.Dimension(130, 150));
this.innerPanel2.setLayout(new net.miginfocom.swing.MigLayout());
this.innerPanel2.setBorder(BorderFactory.createTitledBorder("Panel2"));
this.outerPanel.add(this.innerPanel1);
this.outerPanel.add(this.innerPanel2);
this.pack();
}
public static void main(String[] args) {
ControlPanel cp = new ControlPanel();
}
}
Problem: When I run my program, the GUI that appears before I resize the window is fine; but when I resize the window -enlarging it, innerPane1 and innerPanel2 remains of the same size without resizing to occupy the space available.
Question: How do we make the two panels , innerPannel1 and innerPanel2, resize at the same time with the window so that they can share equally the available space? Any particular Layout Manager that can be used to divide a panel into two equal halves that can resize at the same time with the window?
Images Showing the output.
Before resizing - the GUI looks well and the panels have correct size.
After resizing -the GUI is distorted and the panels doesn't change size.
I suggest you use new GridLayout(1, 2). This will split the panel in 1 row and 2 (equally sized) columns.
So, simply changing
this.outerPanel = new JPanel();
to
this.outerPanel = new JPanel(new GridLayout(1, 2));
should do.
Related
I have a component I've written that uses BoxLayout to layout some JLabels horizontally, followed by glue (I'd like the JLabels' width to remain fixed). For example:
I need to add two lines of text to each JLabel, so I'm using a bit of HTML. As soon as I added the HTML, the BoxLayout stopped respecting the glue. I get something like:
I can get around this by specifying that the maximum size should be equal to the preferred size (specifying preferred size has no effect). Is this the correct approach? Is there some explanation for why glue seems to be ignored when there's HTML in my JLabels?
The MWE:
import javax.swing.*;
import java.awt.*;
public class LabelBreak extends JFrame {
JPanel panel;
public LabelBreak() {
setTitle("Frame");
panel = new MyPanel();
panel.setPreferredSize(new Dimension(500, 100));
add(panel);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new LabelBreak();
frame.pack();
frame.setVisible(true);
});
}
private static class MyPanel extends JPanel {
private MyPanel() {
super();
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel header = new JPanel();
header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS));
//JLabel label = new JLabel("One");
JLabel label = new JLabel("<html>One<br>is<br>the<br>loneliest<br>number</html>");
label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
header.add(label);
label = new JLabel("Two");
label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
header.add(label);
header.add(Box.createHorizontalGlue());
this.add(header);
}
}
}
Is there some explanation for why glue seems to be ignored when there's HTML in my JLabels?
A BoxLayout will respect the maximum size (and minimum size) for components.
For normal text the maximum size would be the preferred size of the component, so the glue works as expected.
It looks like the calculation for the maximum size is different for HTML vs regular text.
I can get around this by specifying that the maximum size should be equal to the preferred size
Yes, this is a reasonable approach, but I would override the getMaximumSize() method to simply return the getPreferredSize() value.
#Override
public Dimension getMaximumSize()
{
return getPreferredSize();
}
This way if you change the HTML it will still work.
BoxLayout respects maximum size of JLabel so you have to set it.
To control width between two labels you can use Box.createHorizontalStrut(width).
Note that two labels are centered in header. I would use GridLayout to place components in one row with different space between columns.
private MyPanel() {
super();
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
JPanel header = new JPanel();
header.setLayout(new GridLayout(1,4,20,0));
// JLabel label = new JLabel("One");
JLabel label = new JLabel("<html>One<br>is<br>the<br>loneliest<br>number</html>");
label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
label.setMaximumSize(label.getPreferredSize());
header.add(label);
// header.add(Box.createHorizontalStrut(10));
label = new JLabel("Two");
label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
header.add(label);
// header.add(Box.createHorizontalGlue());
this.add(header);
}
I am trying to put a JPanel in the center of a fullscreen JFrame with a defined size, but it's always stretching for the whole screen...
I tried setBounds, setPreferredSize, but they don't work.
This is the code:
public static void showScene(){
//Create the frame to main application.
JFrame frame = new JFrame("Application"); // set the title of the frame
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // set the size, maximum size.
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create the panel to store the main menu.
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(500,200));
panel.setBackground(new java.awt.Color(0,0,255));
frame.add(panel,BorderLayout.CENTER);
}
public static void main (String[] args){
showScene();
}
BorderLayout stretches the contents to fill the parent container.
If you want the child to have smaller size than the parent, use some other LayoutManager (try FlowLayout).
You can change layout using following code.
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 0,90)));
frame.add(panel);
frame.pack();
For further reference, follow visual guide to layout managers.
Good luck.
I am using BorderLayout in my application. I have a main panel to which I add two JPanels at the center. I want one of them to be transparent.
My code is :
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(getGraphPaneScrollPane(), BorderLayout.CENTER);
mainPanel.add(getSituationPanel(), BorderLayout.CENTER);
Code for these two functions is :
public JScrollPane getGraphPaneScrollPane() {
if (graphPaneScrollPane == null) {
graphPaneScrollPane = new JScrollPane();
graphPaneScrollPane.setViewportView(getGraphEditorPane());
}
return graphPaneScrollPane;
}
private JScrollPane getSituationPanel(){
if(situationPanel == null){
logs.debug("Initializing Situation Panel");
situationPanel = new JScrollPane();
situationLabel = new JLabel("");
situationLabel.setVerticalTextPosition(JLabel.BOTTOM);
situationLabel.setHorizontalTextPosition(JLabel.CENTER);
situationLabel.setVerticalAlignment(JLabel.TOP);
situationLabel.setHorizontalAlignment(JLabel.CENTER);
situationLabel.setBorder(BorderFactory.createTitledBorder(""));
situationLabel.setBackground(Color.WHITE);
situationLabel.setOpaque(true);
situationLabel.setVerticalAlignment(SwingConstants.TOP);
situationPanel.setViewportView(situationLabel);
}
return situationPanel;
}
Now I want situationPanel to be transparent and getGraphPaneScrollPane to be above that in the GUI, because getGraphPaneScrollPane is the canvas, which I use to draw nodes.
I want situationPanel to be transparent and getGraphPaneScrollPane to be above that in the GUI,
The panel that is on top is the panel that needs to be transparent. If the panel on top is opaque then you will never see the panel under the top panel.
So making changes to the layout is the last thing I want.
Well that is what you are going to need to do. You can't just add two panels to one panel and expect it to work the way you want it to. Most Swing layout managers are designed to lay out components in two dimensions, not on top of one another.
Your current code is:
mainPanel.setLayout(new BorderLayout());
mainPanel.add(getGraphPaneScrollPane(), BorderLayout.CENTER);
mainPanel.add(getSituationPanel(), BorderLayout.CENTER);
You could try using the OverlayLayout, it is designed to lay out panels on top of on another. The code should be something like:
JPanel overlay = new JPanel();
overlay.setLayout( new OverlayLayout(overlay) );
overlay.add(getSituationPanel(), BorderLayout.CENTER); // add transparent panel first
overlay.add(getGraphPaneScrollPane(), BorderLayout.CENTER);
mainPanel.setLayout(new BorderLayout());
mainPanel.add(overlay);
Is it possible to have some extra space around the edges of a JFrame that uses AbsoluteLayout? When I have a button as the downwardsmost component on the JFrame, it gets positioned right up against the bottom edge of the JFrame window, and it looks bad. I would like to know if there's a way to add a little extra space between components and the edge of the JFrame while using AbsoluteLayout.
Suggestions:
When you add a component to a JFrame, you're actually adding it to the JFrame's contentPane. To give the contentPane a "buffer" border, consider giving it an EmptyBorder(...) with the parameters being int constants for the amount of border desired around the component.
Avoid using "absolute" layouts for anything, and especially for placing components at easy to place locations for the layout managers, such as at the bottom of the GUI.
For example, note in the GUI created in the code below how the center and bottom JPanel's don't go out to the edge of the GUI because of the empty border:
import java.awt.BorderLayout;
import java.awt.Dimension;
import javax.swing.*;
public class ButtonAtBottom {
private static void createAndShowGui() {
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton("Bottom Button"));
bottomPanel.setBorder(BorderFactory.createTitledBorder("Bottom Panel"));
JPanel centerPanel = new JPanel();
centerPanel.setBorder(BorderFactory.createTitledBorder("Center Panel"));
JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(centerPanel, BorderLayout.CENTER);
mainPanel.add(bottomPanel, BorderLayout.PAGE_END);
// **** here I add the border to the mainPanel which I'll
// make into the contentPane
int eb = 25;
mainPanel.setBorder(BorderFactory.createEmptyBorder(eb, eb, eb, eb));
// don't set the preferredSize per Kleopatra, but am doing it
// here simply to make code shorter for this sscce
mainPanel.setPreferredSize(new Dimension(500, 400));
JFrame frame = new JFrame("ButtonAtBottom");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You can use Box.createRigidArea(dimensions) to create an empty space that you can add below the button.
Set an empty border on your content panel where SIZE is the amount of padding you want.
JFrame frame = new JFrame();
JPanel panel = new JPanel(null);
panel.setBorder(BorderFactory.createEmptyBorder(SIZE,SIZE,SIZE,SIZE);
frame.setContentPane(panel);
//The rest
The arguments are for top, left, bottom and right padding so if you want different paddings on each edge, you can set it accordingly.
So I have a slight issue with adding two JPanels to a main main panel. I've put it as a quick example of what I want to do since you don't want to be looking through loads of lines of unnecessary code :). I want panel one to be added first (north) and then panel two (south). I've tried using Border layout and positioning them invoking north and south on BorderLayout when adding the panels but still no luck.
Thanks in advance.
private JPanel one,two;
public Example(){
one = new JPanel();
one.setSize(new Dimension(400,400));
two = new JPanel(new GridLayout(7,8));
two.setSize(new Dimension(400,400));
one.setBackground(Color.BLACK);
two.setBackground(Color.BLUE);
JPanel mainpanel = new JPanel();
mainpanel.setBackground(Color.orange);
mainpanel.add(one);
mainpanel.add(two);
add(mainpanel);
setSize(500,500);
setVisible(true);
}
If you want to use BorderLayout, then BorderLayout.CENTER takes up as much space as it can, and the other directions take only what they need. If you add extra stuff to the JPanels, they will get bigger, based on the needs of the objects they contain.
If you want to just divide the space evenly within the main JPanel, try this:
JPanel mainpanel = new JPanel(new GridLayout(2, 1));
That creates a GridLayout with 2 rows and 1 column...
Try this code. There was issue that apparently if you install grid layout on a panel and you add no components it will not take space.
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame
{
private JPanel one, two;
public Example()
{
one = new JPanel();
two = new JPanel();///new GridLayout(7, 8));
one.setBackground(Color.BLACK);
two.setBackground(Color.BLUE);
JPanel mainpanel = new JPanel(new BorderLayout());
mainpanel.setBackground(Color.orange);
mainpanel.add(one, BorderLayout.NORTH);
mainpanel.add(two, BorderLayout.SOUTH);
setContentPane(mainpanel);
setSize(500, 500);
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
Example f = new Example();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
GridLayout ignores the values set in setSize method of contained components. If you want to control the size of each component, consider using GridBagLayout.