Adding multiple jpanels to container, adding space/border between? - java

I am creating a program which has three jpanels: one container, and inside the container is two jpanels, one that is going to hold buttons and one which will hold the content. Ive got them both showing so far and its looking good, the only problem i I was hoping to add some space or a border between or the two (or around the button menu if possible) however since both internal panels are set to null layouts and the external layout is set to a border layout I cannot seem to add a border between the two internal ones. Here is my code so far:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class internal_test extends JFrame {
int height = 480;
int width = 640;
public internal_test() {
initUI();
}
private void initUI() {
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
container.setBackground(Color.black);
JPanel buttonMenu = new JPanel();
buttonMenu.setLayout(null);
buttonMenu.setBackground(Color.DARK_GRAY);
buttonMenu.setPreferredSize(new Dimension(150, height));
JPanel dragFrame = new JPanel();
dragFrame.setLayout(null);
dragFrame.setPreferredSize(new Dimension(200, 100));
dragFrame.setSize(new Dimension(490, height));
dragFrame.setBackground(Color.gray);
container.add(buttonMenu, BorderLayout.WEST);
container.add(dragFrame, BorderLayout.CENTER);
// container.setBorder(new EmptyBorder(new Insets(10, 10, 10, 10)));
add(container);
pack();
setTitle("internal_test V0.1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(width, height);
setLocationRelativeTo(null);
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
internal_test c = new internal_test();
c.setVisible(true);
}
});
}
}
The dragFrame is going to be a DragLayout since that layout does what I need it to, but the button menu could technically be any layout, as long as it would allow me to place buttons/other items in a list with a label next to each.
Any help is greatly appreciated.

I would use the BoxLayout and for the spacing use
panel.add(Box.createRigidArea(new Dimension(x, y)));
Here are some decent examples.

I Suggest GridBagLayout
beacause it is more easy to intent spaces between the components

This should help you add the type of border you want:
http://docs.oracle.com/javase/tutorial/uiswing/components/border.html
You can start with a red line border like this:
buttonMenu.setBorder(BorderFactory.createLineBorder(Color.red));

Related

Java Swing Moving Away From Null Layout

I built a great GUI using the frowned upon null layout (I defined a lot of constants and used a window resize listener to make it easy). Everything worked perfectly until I started using a new computer. Now, the component's are not positioned properly (from the picture you can see that the components are offset down and right). After researching the problem I learned that layout managers make sure that the components are positioned properly throughout different machines. Because of this, I would like to start rebuilding the GUI in an actual layout manager. The problem is that I often feel limited in the way I position components when attempting to use an actual layout manager.
For anyone who is curious, I was originally using a dell inspiron laptop with windows 10, and have moved to an Asus Laptop (I don't know the actual model, but the touch screen can detach from the keyboard), also with windows 10.
My question:
Which layout manager would be the fastest and easiest to build the GUI shown in the picture above (out of the stock Swing Layouts and others). I would like this layout to respect the components' actual sizes for only a few but not all of the components. Using this layout, how would I go about positioning the inventory button (the hammer at the bottom left) so that the bottom left corner of the inventory button is 5 pixels up and right from the bottom left corner of the container, even after resizing the container?
Thanks in advance. All help is appreciated.
EDIT: The "go find a key" and "Attempt to force the door open" options should have their sizes respected.
The simplest solution that comes to my mind is a BorderLayout for the main panel. Add the textarea to NORTH / PAGE_START. Make another BorderLayout containing the inventory button (WEST / LINE_START) and the location label (EAST / LINE_END). Add that to SOUTH / PAGE_END of the main BorderLayout. Then just add a BoxLayout with vertical alignment to the main BorderLayout's CENTER containing the two buttons. Here's a tutorial for the standard layout managers.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class Example {
public Example() {
JTextArea textArea = new JTextArea("There is a locked door");
textArea.setRows(5);
textArea.setBorder(BorderFactory.createLineBorder(Color.GRAY));
textArea.setEditable(false);
WhiteButton button1 = new WhiteButton("Go find a key") {
#Override
public Dimension getMinimumSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 25);
}
#Override
public Dimension getMaximumSize() {
return new Dimension(200, 25);
}
};
WhiteButton button2 = new WhiteButton("Attempt to force the door open");
button2.setMargin(new Insets(0, 60, 0, 60));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(button1);
buttonPanel.add(Box.createVerticalStrut(5));
buttonPanel.add(button2);
WhiteButton inventoryButton = new WhiteButton(
new ImageIcon(new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB)));
JLabel locationLabel = new JLabel("Location: 0");
locationLabel.setVerticalAlignment(JLabel.BOTTOM);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.add(inventoryButton, BorderLayout.WEST);
southPanel.add(locationLabel, BorderLayout.EAST);
JPanel mainPanel = new JPanel(new BorderLayout(0, 5));
mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
mainPanel.add(textArea, BorderLayout.NORTH);
mainPanel.add(buttonPanel);
mainPanel.add(southPanel, BorderLayout.SOUTH);
JFrame frame = new JFrame("Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
private class WhiteButton extends JButton {
public WhiteButton() {
setBackground(Color.WHITE);
}
public WhiteButton(String text) {
this();
setText(text);
}
public WhiteButton(ImageIcon icon) {
this();
setIcon(icon);
setBorder(BorderFactory.createLineBorder(Color.GRAY));
}
}
}

Layout to stretch component width but let height be decided by what it holds

I can't seem to find the correct layoutmanager, perhaps it doesn't exist, so I wanted to do it in miglayout, yet I can't seem to find my way to do this there either.
Most documentation, tutorials and examples I found don't adress the JPanel having contents at all 0.o
The problem I'm having is, I've got two JPanels(C 1&2) inside a JPanel(B) which in turn is inside a bigger resizeable JPanel(A).
Now both lowest level "C" JPanels contain 5 buttons, when the highest level "A" resizes and gets less width the buttons go from this:
to this:
As you can see the FlowLayout I'm using on the lowest level "C" JPanels is doing it's job!
c.setLayout(new FlowLayout(FlowLayout.LEFT,0,0))
But while the "B" JPanel that holds the C's does exactly what I want for the horizontal part
b.setLayout(new BoxLayout(b, BoxLayout.Y_AXIS));
I don't want it doing that on the height though!
So could anyone point me in the right direction like a tutorial or docs that cover such stuff? For miglayout or swing layout managers?
I have created a solution with a MigLayout manager. The panels keep their
height nicely when the window is resized and never shrink below the size
necessary to hold all the buttons.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutSolution extends JFrame {
public MigLayoutSolution() {
initUI();
}
private void initUI() {
JPanel pnl = new JPanel(new MigLayout());
pnl.add(createPanel1("First"), "push, grow, wrap");
pnl.add(createPanel2("Second"), "push, grow");
add(pnl);
pack();
setTitle("MigLayout solution");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private JPanel createPanel1(String text) {
JPanel pnl = new JPanel(new MigLayout());
pnl.add(new JButton("A"));
pnl.add(new JButton("B"));
pnl.add(new JButton("C"));
pnl.add(new JButton("D"));
pnl.setBorder(BorderFactory.createTitledBorder(text));
return pnl;
}
private JPanel createPanel2(String text) {
JPanel pnl = new JPanel(new MigLayout());
pnl.add(new JButton("E"));
pnl.add(new JButton("F"));
pnl.add(new JButton("G"));
pnl.add(new JButton("H"));
pnl.setBorder(BorderFactory.createTitledBorder(text));
return pnl;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutSolution ex = new MigLayoutSolution();
ex.setVisible(true);
}
});
}
}
The first picture shows two panels with plenty of empty space.
The second picture shows the panels in their minimal size.

How can I place buttons in the center of the frame in a vertical line?

I will place these buttons in the center of the frame and above each other, like this.
BUTTON
BUTTON
BUTTON
I've searched multiple topics on this forum but everything I tried didn't work for so far. I hope that somebody has the solution.
This is my code for so far:
package ípsen1;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Paneel extends JPanel implements ActionListener {
Image achtergrond;
private JButton spelHervatten;
private JButton spelOpslaan;
private JButton spelAfsluiten;
public Paneel(){
//buttons
spelHervatten = new JButton("Spel hervatten");
spelHervatten.setPreferredSize(new Dimension(380, 65));
spelOpslaan = new JButton("Spel opslaan");
spelOpslaan.setPreferredSize(new Dimension(380, 65));
spelAfsluiten = new JButton("Spel afsluiten");
spelAfsluiten.setPreferredSize(new Dimension(380, 65));
//object Paneel luistert naar button events
spelAfsluiten.addActionListener(this);
add (spelHervatten);
add (spelOpslaan);
add (spelAfsluiten);
}
public void paintComponent(Graphics g) {
//achtergrond afbeelding zetten
achtergrond = Toolkit.getDefaultToolkit().getImage("hout.jpg");
//screensize
g.drawImage(achtergrond, 0,0, 1024,768,this);
}
//actie na klik op button
public void actionPerformed(ActionEvent e) {
if(e.getSource() == spelAfsluiten){
System.out.println("Spel afsluiten");
System.exit(0);
}
}
}
You could use a GridBagLayout
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JButton("Button"), gbc);
add(new JButton("Button"), gbc);
add(new JButton("Button"), gbc);
add(new JButton("Button"), gbc);
See How to Use GridBagLayout for more details
A BoxLayout might be what you're after. You can specify that you want to add components along the y-axis in the constructor for that particular layout manager.
You could add this line to the constructor of your Paneel class.
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
As for center-aligning everything, I don't know if it's good practice but you can set the horizontal alignment for each of your buttons individually. Example:
spelHervatten.setAlignmentX(CENTER_ALIGNMENT);
Uses a GridLayout for a single column of buttons of equal width.
The buttons stretch as the window's size increases. To maintain the button size, put the GridLayout as a single component into a GridBagLayout with no constraint. It will be centered.
The size of the buttons is increased by setting a margin.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
/*
* Uses a GridLayout for a single column of buttons of equal width.
* The buttons stretch as the window's size increases. To maintain
* the button size, put the GridLayout as a single component into a
* GridBagLayout with no constraint. It will be centered.
*/
public class CenteredSingleColumnOfButtons {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
// the GUI as seen by the user (without frame)
JPanel gui = new JPanel(new GridLayout(0,1,10,10));
gui.setBorder(new EmptyBorder(20,30,20,30));
String[] buttonLabels = {
"Spel hervatten",
"Spel opslaan",
"Spel afsluiten"
};
Insets margin = new Insets(20,150,20,150);
JButton b = null;
for (String s : buttonLabels) {
b = new JButton(s);
b.setMargin(margin);
gui.add(b);
}
JFrame f = new JFrame("Centered Single Column of Buttons");
f.add(gui);
// Ensures JVM closes after frame(s) closed and
// all non-daemon threads are finished
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// See http://stackoverflow.com/a/7143398/418556 for demo.
f.setLocationByPlatform(true);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
f.setMinimumSize(f.getSize());
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
System.out.println(b.getSize());
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency
SwingUtilities.invokeLater(r);
}
}
I thought there is no way to do that.
You should get size of Panel/Frame then calculate manually to find to center position for your button.
Rephrased some parts:
You might want to try to put the buttons in JFrame's "wind direction"-style BorderLayout:
http://www.leepoint.net/notes-java/GUI/layouts/20borderlayout.html
Just create a block in the CENTER with one EAST and WEST block with a certain size around it. Then insert the buttons inside of the center block. If you don't want them to be the full size, just add another EAST and WEST.

Placing a JLabel at a specific x,y coordinate on a JPanel

I'm trying to place a series of JLabels at specific X and Y coordinates on a JPanel (and set its height and width, too). No matter what I do, each label winds up immediately to the right of the previous label and has the exact same size as all of the others.
Right now, my Jpanel is in a Grid Layout. I've tried Absolute Layout (illegal argument exception results), Free Design (no labels appear), Flow Layout (everything just gets squeezed to the center), and a few others.
Not sure what I need to do to make this work. Can anyone help? Thanks!
JLabel lbl1 = new JLabel("label 1");
JLabel lbl2 = new JLabel("label 2");
JLabel lbl3 = new JLabel("label 3");
JLabel lbl4 = new JLabel("label 4");
JLabel lbl5 = new JLabel("label 5");
myPanel.add(lbl1);
myPanel.add(lbl2);
myPanel.add(lbl3);
myPanel.add(lbl4);
myPanel.add(lbl5);
lbl1.setLocation(27, 20);
lbl2.setLocation(123, 20);
lbl3.setLocation(273, 20);
lbl4.setLocation(363, 20);
lbl5.setLocation(453, 20);
lbl1.setSize(86, 14);
lbl2.setSize(140, 14);
lbl3.setSize(80, 14);
lbl4.setSize(80, 14);
lbl5.setSize(130, 14);
You have to set your container's Layout to null:
myPanel.setLayout(null);
However is a good advise also to take a look at the Matisse Layout Manager, I guess it is called GroupLayout now. The main problem with absolute positioning is what happens when the window changes its size.
Set the container's layout manager to null by calling setLayout(null).
Call the Component class's setbounds method for each of the container's children.
Call the Component class's repaint method.
Note:
Creating containers with absolutely positioned containers can cause problems if the window containing the container is resized.
Refer this link:
http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
Layout managers are used to automatically determine the layout of components in a container. If you want to put components at specific coordinate locations, then you should not use a layout manager at all.
myPanel = new JPanel(null);
or
myPanel.setLayout(null);
My advise is to use an IDE like NetBeans with its GUI editor. To inspect the code and because there are many ways:
Setting the layout manager, or for absolute positioning doing a myPanel.setLayout(null), has several influences.
In general, assuming you do your calls in the constructor of a JFrame, you can call pack() to start the layouting.
Then, every layout manager uses its own implementation of add(Component) or add(Component, Constraint). BorderLayout's usage is with add(label, BorderLayout.CENTER) and so on.
// Best solution!!
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Main {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = (JPanel) frame.getContentPane();
panel.setLayout(null);
JLabel label = new JLabel("aaa");
panel.add(label);
Dimension size = label.getPreferredSize();
label.setBounds(100, 100, size.width, size.height);
frame.setSize(300, 200);
frame.setVisible(true);
}
}
You can use your own method that calling by setSize, setLocation values for directly....! `
As well i show you how to use JProgress Bar
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class installComp{
void install(Component comp, int w, int h, int x, int y){
comp.setSize(w,h);
comp.setLocation(x,y);
}
}
class MyFrame extends JFrame{
int cur_val = 0;
JButton btn = new JButton("Mouse Over");
JProgressBar progress = new JProgressBar(0,100);
MyFrame (){
installComp comp=new installComp();
comp.install(btn,150,30,175,20);
comp.install(progress,400,20,50,70);
btn.addMouseListener(new MouseAdapter(){
public void mouseEntered(MouseEvent evt){
cur_val+=2;
progress.setValue(cur_val);
progress.setStringPainted(true);
progress.setString(null);
}
});
add(btn);
add(progress);
setLayout(null);
setSize(500,150);
setResizable(false);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
}
}
class Demo{
public static void main(String args[]){
MyFrame f1=new MyFrame();
}
}

JPanel layout Issue

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.

Categories

Resources