MigLayout Panel inside a MigLayout panel - aligning it to the bottom - java

The panel to the right with all the buttons, I would like to align to the bottom.
JPanel easternDock = new JPanel(new MigLayout("", ""));
easternDock.add(button1, "wrap");
....
this.add(easternDock);
I'm thinking I could add a component above all the buttons and make it grow in the y dimension to fill the screen, but I'm not sure what component I'd use for that and I can't find any components designed to do such a thing.

The way I would do it is to have another panel within the "easternDock" panel which contains all the components and have "easternDock" push this other panel to the bottom using the push Column/Row constraint.
From the MiG Cheat sheet : http://www.miglayout.com/cheatsheet.html
":push" (or "push" if used with the default gap size) can be added to the gap size to make that gap greedy and try to take as much space as possible without making the layout bigger than the container.
Here is an example:
public class AlignToBottom {
public static void main(String[] args) {
JFrame frame = new JFrame();
// Settings for the Frame
frame.setSize(400, 400);
frame.setLayout(new MigLayout(""));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Parent panel which contains the panel to be docked east
JPanel parentPanel = new JPanel(new MigLayout("", "[grow]", "[grow]"));
// This is the panel which is docked east, it contains the panel (bottomPanel) with all the components
// debug outlines the component (blue) , the cell (red) and the components within it (blue)
JPanel easternDock = new JPanel(new MigLayout("debug, insets 0", "", "push[]"));
// Panel that contains all the components
JPanel bottomPanel = new JPanel(new MigLayout());
bottomPanel.add(new JButton("Button 1"), "wrap");
bottomPanel.add(new JButton("Button 2"), "wrap");
bottomPanel.add(new JButton("Button 3"), "wrap");
easternDock.add(bottomPanel, "");
parentPanel.add(easternDock, "east");
frame.add(parentPanel, "push, grow");
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

Related

How to make a JPanel stay on top of another JPanel that has setSized

I've looked at other stackoverflows and many other examples with JLayeredPane but I can't resolve my issue.
Frame class -> Main JPanel class -> 2 JPanel classes
I have Main JPanel set as Border layout and I have 2 JPanels set as North and South in the Main JPanel. The North JPanel has setPreferredSize.
The issue I have is when I reduce the window size, South Panel where I have buttons declared gets hidden. Even if window is reduced, I still want buttons (south panel) to be visible to users.
JPanel mainPanel = new JPanel(new BorderLayout());
//North panel
JPanel northPanel = new JPanel();
northPanel.setLayout(new GridBagLayout());
northPanel.setPreferredSize(new Dimension(600, 350));
northPanel.add(example..)
......
//South panel
JPanel southPanel = new JPanel(new BorderLayout()););
JButton button1 = new JButton();
JButton button2 = new JButton();
southPanel.add(button1, BorderLayout.WEST);
southPanel.add(button2, BorderLayout.EAST);
//Add north and south panels to main panel
this.mainPanel.add(northPanel, BorderLayout.NORTH);
this.mainPanel.add(southPanel, BorderLayout.SOUTH); //want these buttons
//to be visible even when window size is reduced.
//but now the buttons gets hidden behind the north panel.
How can I make sure the South panel is always visible regardless of the window size?
Hope my explanation makes sense and thank you!
The issue I have is when I reduce the window size, South Panel where I have buttons declared gets hidden.
A component on a panel is painted based on its ZOrder. As a component is added to a panel it is given a higher ZOrder. Swing actually paints components with the highest ZOrder first.
So instead of doing:
panel.setLayout( new BorderLayout() );
panel.add( new JButton("NORTH"), BorderLayout.NORTH );
panel.add( new JButton("SOUTH"), BorderLayout.SOUTH );
You can do:
panel.setLayout( new BorderLayout() );
panel.add( new JButton("SOUTH"), BorderLayout.SOUTH );
panel.add( new JButton("NORTH"), BorderLayout.NORTH );
Now the "South" button will be painted over top of the "North" button. Of course this will only work if the south component is opaque.

How to change width size of Jpanels in BorderLayout?

I have main JPanel which is Borderlayout with added 4 JPANELS: NORTH(Green), WEST(Red), CENTER(Gray), SOUTH(Blue). I want to reduce width size of WEST(Red) Jpanel, or increase width size of Center(Grey) Jpanel.
Screenshot:
Here is my code:
frame = new JFrame("FreshPos baza podataka");
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
// Main paneel
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.setBorder( BorderFactory.createEmptyBorder(10,10,10,10) );
frame.getContentPane().add(panel);
//West panel;
JPanel panelWest = new JPanel(new GridLayout(14,0,0,2));
panelWest.setPreferredSize(new Dimension(300, 300));
panelWest.setBorder( BorderFactory.createEmptyBorder(100,0,0,0) );
panel.add(panelWest, BorderLayout.WEST);
panelWest.setBackground(Color.red);
for (int i = 0; i < MAX_TABLES; i++) {
buttonsTables[i] = new JButton(tables[i]);
buttonsTables[i].setMaximumSize(new Dimension(Integer.MAX_VALUE, buttonsTables[i].getMinimumSize().height));
panelWest.add(buttonsTables[i]);
panelWest.add(Box.createVerticalStrut(10));
}
//South panel;
JPanel southPanel = new JPanel(); // Donji layout za dugmice
southPanel.setBorder( BorderFactory.createEmptyBorder(20,0,0,0) );
panel.add(southPanel, BorderLayout.SOUTH);
southPanel.setBackground(Color.BLUE);
JButton buttonDodaj = new JButton("Dodaj");
southPanel.add(buttonDodaj);
JButton buttonIzmeni = new JButton("Izmeni");
southPanel.add(buttonIzmeni);
JButton butonObrisi = new JButton("Obrisi");
southPanel.add(butonObrisi);
//North panel;
JPanel northPanel = new JPanel(); // Donji layout za dugmice
northPanel.setBorder( BorderFactory.createEmptyBorder(0,10,0,0) );
panel.add(northPanel, BorderLayout.NORTH);
northPanel.setBackground(Color.green);
JButton buttonImport = new JButton("Importuj fajl");
buttonImport.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
importActionPerformed(evt);
}
});
northPanel.add(buttonImport, BorderLayout.WEST);
JButton ButtonRecord = new JButton("Snimi fajl");
northPanel.add(ButtonRecord, BorderLayout.WEST);
// Central panel
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.setBackground(Color.GRAY);
panel.add(centerPanel, BorderLayout.CENTER);
I want to reduce width size of WEST(Red) Jpanel
panelWest.setBorder( BorderFactory.createEmptyBorder(100,0,0,0) );
So why is the width of your Border so large?
A Border is for "extra" space around the components.
So the width of your panel is the width of the buttons plus the width of the border.
Edit:
panelWest.setPreferredSize(new Dimension(300, 300));
Don't hardcode a preferred size. The layout manager will calculate the size based on the above logic. Get rid of that statement.
Edit 2:
// buttonsTables[i].setMaximumSize(new Dimension(Integer.MAX_VALUE, buttonsTables[i].getMinimumSize().height));
Get rid of any logic that attempts to control the size of a component. The point of using layout managers is to let the layout manager do the size calcualtions.
So for your buttons panel you need to nest panels to prevent the buttons from taking all the space.
You can do something like:
JPanel wrapper = new JPanel();
wrapper.add(buttonsPanel);
...
//panel.add(panelWest, BorderLayout.WEST);
panel.add(wrapper, BorderLayout.WEST);
By default a JPanel uses a FlowLayout which will respect the preferred size of any component added to it.
Another option is to use a GridBagLayout with the wrapper panel. By default the panel will then be displayed in the "center" of the available space. So it will be vertically centered and you won't need the EmptyBorder.

Java: Showing a BoxLayout panel in the middle of the frame

I recently started working with Java and I am not too sure how to put my BoxedLayout Panel in the middle of my `JFrame. At the moment, I have the following:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
JLabel quizLabel = new JLabel("Java Quiz",SwingConstants.CENTER);
quizLabel.setForeground(Color.BLUE);
quizLabel.setFont(new Font("Arial", Font.BOLD, 20));
quizLabel.setOpaque(true);
panel.add(quizLabel);
JLabel newLineLabel = new JLabel(" ",SwingConstants.CENTER);
newLineLabel.setOpaque(true);
panel.add(newLineLabel);
JLabel createdByLabel = new JLabel("Created By",SwingConstants.CENTER);
createdByLabel.setOpaque(true);
panel.add(createdByLabel);
JLabel nameLabel = new JLabel("XXX",SwingConstants.CENTER);
nameLabel.setOpaque(true);
panel.add(nameLabel);
contentPane.add(panel, BorderLayout.CENTER);
contentPane is taken from my frame. This gives me the following output:
I want the three labels inside the panel to appear in the middle of the Frame.
Because it is the only panel on the screen, the BoxLayout will fill the entire frame and thus depending on how your JComponents are created in the panel, it will show it like that on the frame too.
What I would do if I were you, is created a BorderLayout as a container for your BoxLayout.
This way, you can set your BoxLayout as the center of the Borderlayout.
See if this code works:
//This will fill your frame
JPanel containerPanel = new JPanel(new BorderLayout());
contentPane.add(containerPanel);
//this is the BoxPanel you wnat your components to be organized in
JPanel boxPanel = new JPanel(new BoxLayout());
//Add all your components to the boxPanel
//add your panel with all the components to the container panel
containerPanel.add(boxPanel, BorderLayout.CENTER);
The easiest way is to use a GridBagLayout. Using the default constraints a single component will be centered in the panel:
//contentPane.add(panel, BorderLayout.CENTER);
contentPane.setLayout( new GridBagLayout() );
contentPane.add(panel, new GridBagConstraints());

Boxlayouts with JPanels incorrectly expanding with resize

I've searched a fair amount and I cannot locate a good, simple answer to this problem.
I want a box layout (superPanel), which contains an upper and lower JPanel (mainPanel and footerPanel). The upper will contain further JPanels (leftPanel and rightPanel).
Consider the code below, I find that when I resize the window, the mainPanel gets larger, and so does the footer. The footer should always stay the same size, below the mainPanel, at the bottom of the frame.
frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
JPanel superPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel= new JPanel();
JPanel footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
mainPanel.setBackground(Color.RED);
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
mainPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
leftPanel.add(new JButton("left"));
rightPanel.add(new JButton("right"));
footerPanel.add(new JButton("footer"));
container.add(mainPanel);
container.add(footerPanel);
frame.add(container);
frame.pack();
frame.setVisible(true);
Anybody know why this is occurring? If you run this you'll see that red and green both grow in size as the window is resized. What I want to see is the red getting larger, while the green remains the same size.
Glue doesn't work, and I don't want to have to use GridBagLayout unless I have to (please explain why I should if need be)
Thanks
When you want a "main" section and side sections which don't change size, you usually want a BorderLayout:
container.setLayout(new BorderLayout());
container.add(mainPanel, BorderLayout.CENTER);
container.add(footerPanel, BorderLayout.PAGE_END);
Try to use GridBagLayout with fill.BOTH, weightx = 1 and weighty = 1 for the main panel and fill.NONE, weightx = 0 and weighty = 0 for the footer panel or use Miglayout which is really easy and with it you can do all what you want.
BorderLayout is what you want on your container, adding the mainPanel to the center and footerPanel to the south. Try the following changes on your code:
frame = new JFrame("Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel container = new JPanel();
container.setLayout(new BorderLayout()); // Use BorderLayout instead of BoxLayout
JPanel superPanel = new JPanel();
JPanel mainPanel = new JPanel();
JPanel leftPanel = new JPanel();
JPanel rightPanel = new JPanel();
JPanel footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
mainPanel.setBackground(Color.RED);
mainPanel.add(leftPanel);
mainPanel.add(rightPanel);
mainPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
leftPanel.add(new JButton("left"));
rightPanel.add(new JButton("right"));
footerPanel.add(new JButton("footer"));
container.add(mainPanel, BorderLayout.CENTER); // Add mainPanel to the central area
container.add(footerPanel, BorderLayout.SOUTH); // Add footePanel to the bottom
frame.add(container);
frame.pack();
frame.setVisible(true);
The BorderLayout determines that a component added to the CENTER area will expand both horizontally and vertically to follow the container. The SOUTH area can only expand horizontally while EAST and WEST can only expand vertically. Keep in mind that every layout manager class has its own rules on how to divide the container space among components and how they are resized.

How to center a component on a row containing multiple components with MiGLayout

I started using MiGLayout about a month and half ago and everything is simple and works great. There's only one issue I still have that I haven't been able to fix.
Let's say I want to have a row that has two buttons on the right-most side and a centered title, the title doesn't actually get centered when I do it this way:
("this" is a JPanel)
this.add(labelTitle, "split, span, center");
this.add(closeButton, "east");
this.add(mainMenuButton, "east");
What happens is that "labelTitle" is centered in the remaining space available after the buttons are placed, but I actually want it to be centered relative to the whole JPanel, not just the remaining space.
What parameters could I use to get the desired effect? I know I could use absolute positioning, but I don't want to do that because it defeats the purpose of using MiGLayout in the first place in my case.
Can it be something like this you are looking for?
Cheers!
public static void main(String[] args)
{
JFrame frame = new JFrame();
JPanel panel = new JPanel(new MigLayout("debug"));
panel.add(new JLabel("Label Title"), "x2 min(b1.x - unrel, (container.w+pref)/2)");
panel.add(new JButton("Close Button"), "id b1, pushx, alignx right");
panel.add(new JButton("Main Menu Button"), "alignx right");
frame.add(panel);
frame.setSize(800, 200);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
You can use the JXLayer and put the buttons in the glasspane.
JButton closeButton = new JButton("Close");
JButton mainMenuButton = new JButton("Menu");
JLabel labelTitle = new JLabel("Application");
JPanel panel = new JPanel();
panel.setLayout(new MigLayout(new LC().fillX()));
panel.add(labelTitle, new CC().alignX("center").spanX());
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new MigLayout(new LC().fillX()));
buttonPanel.add(closeButton, new CC().alignX("right").split());
buttonPanel.add(mainMenuButton, new CC().alignX("right"));
buttonPanel.setOpaque(false);
JXLayer<JPanel> mainPanel = new JXLayer<JPanel>();
mainPanel.setView(panel);
mainPanel.setGlassPane(buttonPanel);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.setSize(400, 600);
frame.setVisible(true);
When creating your JPanel, use the following MigLayout initializer:
new MigLayout("","[]push[center]push[]","")
If you don't know about constraints, check here: MigLayout Whitepaper
This is assuming you don't have anything else in this JPanel...

Categories