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.
Related
I'm trying to put a JPanel inside OR on a JPanel, whichever may be the case, ultimately I just want this to work like this
As you can see on the picture, the red line is a JFrame and it has 2 JPanels inside it, on the green JPanel there are some different JPanels.
I need help with the green JPanel and the little JPanels inside it. Is there any way to make it work like this?
Any help would be greatly appreciated!
==============EDIT 1==============
So here is some code, to show you what I've done so far with the help of #hfontanez.
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
public class Main
{
public static void main(String[] args)
{
//JFrame
JFrame jframe = new JFrame();
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setSize(1920, 1080);
jframe.setResizable(false);
jframe.setLocationRelativeTo(null);
jframe.setVisible(true);
//parentJpanel - This is the main panel
JPanel parentJpanel = new JPanel();
parentJpanel.setBackground(Color.YELLOW);
parentJpanel.setSize(1920, 1080);
parentJpanel.setLayout(new BorderLayout());
//smallPanel - This is the little panel on the bottom
JPanel smallPanel = new JPanel();
smallPanel.setBackground(Color.GREEN);
smallPanel.setSize(1920, 300);
smallPanel.setLocation(0, 780);
smallPanel.setLayout(new BoxLayout(smallPanel, BoxLayout.PAGE_AXIS));
parentJpanel.add(smallPanel);
jframe.add(parentJpanel);
}
}
I expected the top part to be yellow, and the small part on the bottom to be green, yet the whoel thing turned green. What did I do wrong?
The pictured GUI is created using three panels.
The YELLOW panel is the game play area. It has no layout, no components (which define their own preferred sizes) and is custom painted, so it defines a sensible preferred size to report to the layout manager.
The GREEN panel contains controls. It uses a FlowLayout.
The RED panel uses a BorderLayout, and puts the YELLOW panel in the CENTER and the GREEN panel in the PAGE_END.
Code
This is the code that made the screenshot seen above.
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
public class GameLayout {
GameLayout() {
// The main GUI. Everything else is added to this panel
JPanel gui = new JPanel(new BorderLayout(5, 5));
gui.setBorder(new EmptyBorder(4, 4, 4, 4));
gui.setBackground(Color.RED);
// The custom painted area - it is a panel that defines its preferred size.
gui.add(new GamePanel());
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEADING));
buttonPanel.setBackground(Color.GREEN);
for (int ii = 1; ii<5; ii++) {
buttonPanel.add(new JButton("B " + ii));
}
gui.add(buttonPanel,BorderLayout.PAGE_END);
JFrame f = new JFrame("Game Layout");
f.setContentPane(gui);
f.setLocationByPlatform(true);
f.pack();
f.setVisible(true);
}
public static void main(String[] args) {
Runnable r = () -> new GameLayout();
SwingUtilities.invokeLater(r);
}
}
class GamePanel extends JPanel {
GamePanel() {
setBackground(Color.YELLOW);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 100);
}
}
You need to use a LayoutManager so when you put the JPanel inside the other JPanel it will have the correct look. If you simply put panels inside the others, the parent JPanel will use its default layout manager, which is FlowLayout.
For the look of it, it seems you need to use Border Layout for the parent (yellow) panel. For the green, you have options, but I think your best bet is to use Box Layout with a PAGE_AXIS Component Orientation.
In general, you need to be familiarized with two things: 1) Layout Managers and how they behave, and 2) the default layout behavior of JComponents.
I want to create a two dimensional JSplitpane like design in Java swing.
Such that the JFrame will be split into 4 parts, and upper and lower parts are separated by another split, and left and right part are separated by yet another split line. Also if I click and drag any part of vertical split line, the complete line should move in dragged direction.
I am trying to achieve this, by using split pane within split pane. But then on dragging vertical split line, it only drags either components below horizontal line or above horizontal split line.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Demo extends JFrame {
int screenwidth=760,screenheigth=550;
JSplitPane top_sp,bottom_sp,main_sp;
JButton b1,b2,b3,b4,b5,b6;
JButton b7,b8,b9,b10;
MailClient(){
setSize(screenwidth,screenheigth);
setLayout(new BorderLayout());
setTitle("Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
b1=new JButton("B1");
b2=new JButton("B2");
b3=new JButton("B3");
b4=new JButton("B4");
b5=new JButton("B5");
b6=new JButton("B6");
b7=new JButton("B7");
b8=new JButton("B8");
b9=new JButton("B9");
b10=new JButton("B10");
JPanel topleft=new JPanel(new FlowLayout());
topleft.add(b1);
topleft.add(b2);
JPanel topright=new JPanel(new FlowLayout(FlowLayout.CENTER));
topright.add(b3);
topright.add(b4);
topright.add(b5);
topright.add(b6);
JPanel bottomleft=new JPanel(new FlowLayout(FlowLayout.CENTER));
bottomleft.add(b7);
bottomleft.add(b8);
bottomleft.add(b9);
bottomleft.add(b10);
JPanel bottomright=new JPanel(new FlowLayout(FlowLayout.CENTER));
bottomright.add(new JLabel("TABLE"));
top_sp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,topleft,topright);
bottom_sp=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,true,bottomleft,bottomright);
main_sp=new JSplitPane(JSplitPane.VERTICAL_SPLIT,true,top_sp,bottom_sp);
add(main_sp,"Center");
setVisible(true);
}
public static void main(String args[]){
Demo demo=new Demo();
}
}
You can use a property change listener to detect when the split pane divider has been moved, and then set the location of the other split pane:
import javax.swing.*;
import java.awt.*;
public class Example extends JFrame {
public Example() {
JPanel topLeftPanel = new JPanel();
JPanel topRightPanel = new JPanel();
JPanel bottomLeftPanel = new JPanel();
JPanel bottomRightPanel = new JPanel();
JSplitPane topPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, topLeftPanel, topRightPanel);
JSplitPane bottomPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, bottomLeftPanel, bottomRightPanel);
topPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, pce -> {
bottomPane.setDividerLocation((int) pce.getNewValue());
});
bottomPane.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, pce -> {
topPane.setDividerLocation((int) pce.getNewValue());
});
JSplitPane mainPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topPane, bottomPane);
setContentPane(mainPane);
setLocationRelativeTo(null);
setMinimumSize(new Dimension(400, 400));
setVisible(true);
}
public static void main(String[] args) {
new Example();
}
}
you have to listen to the split-change:
split.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY,
new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pce) {}
});
(see Detecting JSplitPane Divider Movement for further information)
whenever you change the size of one JSplitPane, you have to change the other as well.
split.setDividerLocation(proportionalLocation);
You can also check out the Split Pane Synchronizer.
This is a reusable class that allows you to synchronize 2 (or more) split panes. The classes uses a single PropertyChangeListener to manage the change in divider location so your application code doesn't need to keep track of each split pane separately.
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.
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.
In java, I have been trying to create a panel that can accept other panels with a scroll bar.
I tried using gridlayout, and this works fine, except for the fact that if I only add a few panels, it grows those panels to fit the size of the parent panel.
I tried using flowlayout, but this makes the panels flow horizontally as there is a scroll bar.
How do I make it so I can add panels to the parent panel starting at the top and make them always the same size(or their preferred size).
Also, when I add panels to the parent panel after an event, they do not appear until after I move or resize the form. How do I make it repaint? calling repaint() on it did not work.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
/** This lays out components in a column that is constrained to the
top of an area, like the entries in a list or table. It uses a GridLayout
for the main components, thus ensuring they are each of the same size.
For variable height components, a BoxLayout would be better. */
class ConstrainedGrid {
ConstrainedGrid() {
final JPanel gui = new JPanel(new BorderLayout(5,5));
gui.setBorder(new EmptyBorder(3,3,3,3));
gui.setBackground(Color.red);
JPanel scrollPanel = new JPanel(new BorderLayout(2,2));
scrollPanel.setBackground(Color.green);
scrollPanel.add(new JLabel("Center"), BorderLayout.CENTER);
gui.add(new JScrollPane(scrollPanel), BorderLayout.CENTER);
final JPanel componentPanel = new JPanel(new GridLayout(0,1,3,3));
componentPanel.setBackground(Color.orange);
scrollPanel.add(componentPanel, BorderLayout.NORTH);
JButton add = new JButton("Add");
gui.add(add, BorderLayout.NORTH);
add.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
componentPanel.add(new JTextField());
gui.validate();
}
});
Dimension d = gui.getPreferredSize();
d = new Dimension(d.width, d.height+100);
gui.setPreferredSize(d);
JOptionPane.showMessageDialog(null, gui);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ConstrainedGrid cg = new ConstrainedGrid();
}
});
}
}
Assuming JScrollPane, see Sizing a Scroll Pane. For convenience, Scrollable clients such as JTable offer setPreferredScrollableViewportSize(), but you can always set the viewport's size explicitly.