I have a button panel and I want a space of 25px between the buttons and a right margin of 5px and a left margin of 5px (the button at the right would be at 5 pixels of the window border).
Flow layout set a gap of the same size everywhere. Gridlayout permit to do that, but then all the buttons have the same size and it is no that I want. The only solution I found is to set Flow layout with hgap=0. then I had an emptyMargin and I but a rigid area before each button, but I think this solution is a bad practice.
What is the best solution to do that ?
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FlowLayoutDemo extends JFrame{
FlowLayout experimentLayout = new FlowLayout(FlowLayout.LEFT, 25, 0);
public FlowLayoutDemo(String name) {
super(name);
}
public void addComponentsToPane(final Container pane) {
final JPanel compsToExperiment = new JPanel();
compsToExperiment.setLayout(experimentLayout);
experimentLayout.setAlignment(FlowLayout.TRAILING);
compsToExperiment.add(new JButton("Button 1"));
compsToExperiment.add(new JButton("Button 2"));
compsToExperiment.add(new JButton("Button 3"));
compsToExperiment.add(new JButton("Long-Named Button 4"));
compsToExperiment.add(new JButton("5"));
pane.add(compsToExperiment, BorderLayout.CENTER);
}
private static void createAndShowGUI() {
FlowLayoutDemo frame = new FlowLayoutDemo("FlowLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addComponentsToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Consider using a GridBagLayout instead, it provides a greater amount of control and customisation.
See How to use GridBagLayout for more details.
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
gbc.insets = new Insets(5, 5, 5, 25);
gbc.fill = gbc.HORIZONTAL;
gbc.weightx = 1;
add(new JButton("Button 1"), gbc);
gbc.insets = new Insets(5, 0, 5, 25);
add(new JButton("Button 2"), gbc);
add(new JButton("Button 3"), gbc);
add(new JButton("Long-Named Button 4"), gbc);
gbc.insets = new Insets(5, 0, 5, 5);
add(new JButton("5"), gbc);
}
}
}
Note, the example forces the buttons too occupy ALL of the available space. If this doesn't meet your needs in particular, try playing around with the fill and weightx values
The best way is to use the GridBagLayout as it shown in example of MadProgrammer. But it also possible using FlowLayout. Here is the example:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FlowLayoutDemo extends JFrame {
FlowLayout experimentLayout = new FlowLayout(FlowLayout.LEFT, 5, 0);
public FlowLayoutDemo(String name) {
super(name);
}
public void addComponentsToPane(final Container pane) {
final JPanel compsToExperiment = new JPanel();
compsToExperiment.setLayout(experimentLayout);
experimentLayout.setAlignment(FlowLayout.TRAILING);
compsToExperiment.add(new JButton("Button 1"));
compsToExperiment.add(Box.createHorizontalStrut(20));
compsToExperiment.add(new JButton("Button 2"));
compsToExperiment.add(Box.createHorizontalStrut(20));
compsToExperiment.add(new JButton("Button 3"));
compsToExperiment.add(Box.createHorizontalStrut(20));
compsToExperiment.add(new JButton("Long-Named Button 4"));
compsToExperiment.add(Box.createHorizontalStrut(20));
compsToExperiment.add(new JButton("5"));
pane.add(compsToExperiment, BorderLayout.CENTER);
}
private static void createAndShowGUI() {
FlowLayoutDemo frame = new FlowLayoutDemo("FlowLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addComponentsToPane(frame.getContentPane());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
If you want to get tricky so you don't need to play with all the constraints of GridBagLayout or add filler components you could do:
JPanel compsToExperiment = new JPanel(experimentLayout);
compsToExperiment.setBorder( new EmptyBorder(0, -20, 0, -20) );
This effectively decrease the space by 20 pixels around the left/right edges of the panel.
Also, just wanted to point out that you have:
FlowLayout experimentLayout = new FlowLayout(FlowLayout.LEFT, 25, 0);
...
experimentLayout.setAlignment(FlowLayout.TRAILING);
You set the layout to left aligned and then change it to trailing. This is a little confusing. You can just set it to trailing when you create the layout:
FlowLayout experimentLayout = new FlowLayout(FlowLayout.TRAILING, 25, 0);
Related
I am a student learning java ahead of my comp sci class, and my teacher knows nothing about JFrames or JButtons, so I'm reaching out here. This is my overarching program to learn about JFrames, the first menu it opens up just fine, sometimes it will set the bounds of buttons correctly, but sometimes it ignores it and fills the frame, sometimes one button, sometimes its different buttons, I couldn't find any other threads on here with the same situation, so I figured I would ask.
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.Random;
public class programToEndAllPrograms {
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(400,400);
JLabel title = new JLabel("Choose a Program");
JButton TempConverter = new JButton();
TempConverter.setText("Temperature Converter");
TempConverter.setBounds(50,155,200,50);
TempConverter.setLayout(null);
frame.add(TempConverter);
JButton CurrentTime = new JButton();
CurrentTime.setText("Current Time");
CurrentTime.setBounds(50,105,200,50);
CurrentTime.setLayout(null);
frame.add(CurrentTime);
JButton RussianRoulette = new JButton();
RussianRoulette.setText("Russian Roulette");
RussianRoulette.setBounds(50,55,200,50);
RussianRoulette.setLayout(null);
frame.add(RussianRoulette);
JButton DaysSinceLastTrinket = new JButton();
DaysSinceLastTrinket.setText("Days Since Last Trinket");
DaysSinceLastTrinket.setBounds(50,15,200,50);
DaysSinceLastTrinket.setLayout(null);
frame.add(DaysSinceLastTrinket);
frame.add(title);
JButton SimpleCalculator = new JButton();
SimpleCalculator.setText("Simple Calculator");
SimpleCalculator.setBounds(50,205,200,50);
SimpleCalculator.setLayout(null);
frame.add(SimpleCalculator);
TempConverter.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
tempConverter();
}
});
SimpleCalculator.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
simpleCalculator();
}
});
CurrentTime.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
currentTime();
}
});
RussianRoulette.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
russianRoulette();
}
});
DaysSinceLastTrinket.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
daysSinceLastTrinket();
}
});
JOptionPane.showMessageDialog(frame, "Choose a program from the list:");
frame.setLayout(null);
frame.setVisible(true);
}```
Pixel perfect layouts are an illusion, too many factors go into determining how best a component should be sized and positioned.
Take the time to learn and understand how to make use of the available layout managers - see Laying Out Components Within a Container. Remember, you're not stuck to a single container/layout, you can compound these together to produce very complex UIs
For example, this is what your UI produces (when I fix the core issue)
But if I make use of an appropriate layout managers I can produce...
GridBagLayout
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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() {
setBorder(new EmptyBorder(8, 8, 8, 8));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
gbc.fill = gbc.HORIZONTAL;
gbc.ipadx = 8;
gbc.ipady = 8;
JLabel title = new JLabel("Choose a Program");
title.setHorizontalAlignment(JLabel.CENTER);
add(title, gbc);
JButton TempConverter = new JButton();
TempConverter.setText("Temperature Converter");
add(TempConverter, gbc);
JButton CurrentTime = new JButton();
CurrentTime.setText("Current Time");
add(CurrentTime, gbc);
JButton RussianRoulette = new JButton();
RussianRoulette.setText("Russian Roulette");
add(RussianRoulette, gbc);
JButton DaysSinceLastTrinket = new JButton();
DaysSinceLastTrinket.setText("Days Since Last Trinket");
add(DaysSinceLastTrinket, gbc);
JButton SimpleCalculator = new JButton();
SimpleCalculator.setText("Simple Calculator");
add(SimpleCalculator, gbc);
}
}
}
But, I appreciate that GridBagLayout is one of the most complex (and flexible) layout managers, but, we can try...
"Compound" layout
We can isolate functionality to individual components, which can make use of their own layout managers, allowing us to focus on the individual components needs and then build up much more complex layouts...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
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() {
setBorder(new EmptyBorder(8, 8, 8, 8));
setLayout(new BorderLayout());
JLabel title = new JLabel("Choose a Program");
title.setBorder(new EmptyBorder(8, 8, 8, 8));
title.setHorizontalAlignment(JLabel.CENTER);
add(title, BorderLayout.NORTH);
JPanel optionsPane = new JPanel(new GridLayout(-1, 1));
optionsPane.setBorder(new EmptyBorder(8, 8, 8, 8));
JButton TempConverter = new JButton();
TempConverter.setMargin(new Insets(8, 8, 8, 8));
TempConverter.setText("Temperature Converter");
optionsPane.add(TempConverter);
JButton CurrentTime = new JButton();
CurrentTime.setText("Current Time");
CurrentTime.setMargin(new Insets(8, 8, 8, 8));
optionsPane.add(CurrentTime);
JButton RussianRoulette = new JButton();
RussianRoulette.setText("Russian Roulette");
RussianRoulette.setMargin(new Insets(8, 8, 8, 8));
optionsPane.add(RussianRoulette);
JButton DaysSinceLastTrinket = new JButton();
DaysSinceLastTrinket.setText("Days Since Last Trinket");
DaysSinceLastTrinket.setMargin(new Insets(8, 8, 8, 8));
optionsPane.add(DaysSinceLastTrinket);
JButton SimpleCalculator = new JButton();
SimpleCalculator.setText("Simple Calculator");
SimpleCalculator.setMargin(new Insets(8, 8, 8, 8));
optionsPane.add(SimpleCalculator);
add(optionsPane);
}
}
}
nb: If you want to change the order of the buttons, then change the order in which they are added 😉
I have a problem related to JList. I'm getting the following layout.
JTextField | Button 1 | Button 2
Button 3 | Button 4 | Button 5
This is the layout I'm getting:
JTextField | Button 1 | Button 2
Button 3 | Button 4 | Button 5
As you can see, I do not have JList in between. I did try inserting a list component there but when I did it, the GridLayout would push the list beside button 2. I only want the list to be my itself in between those.
package ManyThings;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
javax.swing.JTextField;
public class test {
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("GridLayout Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(1, 3));
JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(3,1));
JTextField t1;
t1=new JTextField();
p1.add(new JTextField());
p1.add(new JButton("Search"));
p1.add(new JButton("Clear"));
frame.add(p1);
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(1,3));
p2.add(new JButton("Add"));
p2.add(new JButton("Detail"));
p2.add(new JButton("Remove"));
frame.add(p2);
frame.pack();
frame.setVisible(true);
}
}
Expecting the following layout.
JTextField | Button 1 | Button 2
JList
Button 3 | Button 4 | Button 5
Compound layouts
Make use of multiple containers, using different layout managers (as required)
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Test {
public static void main(String args[]) {
new Test();
}
public Test() {
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(3, 1));
JPanel topRow = new JPanel(new GridLayout(1, 3));
topRow.add(new JTextField(10));
topRow.add(new JButton("Search"));
topRow.add(new JButton("Clear"));
add(topRow);
add(new JScrollPane(new JList()));
JPanel bottomRow = new JPanel(new GridLayout(1, 3));
bottomRow.add(new JButton("Add"));
bottomRow.add(new JButton("Detail"));
bottomRow.add(new JButton("Remove"));
add(bottomRow);
}
}
}
Different layout managers
Use different layout managers to better meet the requirements of the individual components
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
public class Test {
public static void main(String args[]) {
new Test();
}
public Test() {
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());
JPanel topRow = new JPanel(new GridLayout(1, 3));
topRow.add(new JTextField(10));
topRow.add(new JButton("Search"));
topRow.add(new JButton("Clear"));
JPanel bottomRow = new JPanel(new GridLayout(1, 3));
bottomRow.add(new JButton("Add"));
bottomRow.add(new JButton("Detail"));
bottomRow.add(new JButton("Remove"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0;
gbc.gridy = 0;
add(topRow, gbc);
gbc.gridy = 2;
add(bottomRow, gbc);
gbc.gridy = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(new JScrollPane(new JList()), gbc);
}
}
}
See Laying Out Components Within a Container for more details
I am trying to design similar to a browsers title bar(top of the browser). Left side has tabs and right side has minimize, resize(minimize/maximize),exit button.
For this I tried like.
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT));
JPanel tabpanel= new JPanel();
tabpanel.setLayout(new FlowLayout(FlowLayout.LEFT));
tabpanel.add(new JButton("Tab 1"));
tabpanel.add(new JButton("Tab 2"));
panel.add(tabpanel);
panel.add(new JButton("Minimize"));
panel.add(new JButton("Resize"));
panel.add(new JButton("Quit"));
Created Quit, Resize, Minimize buttons at the right as my needed but tabs created near Minimize button not LEFT of Frame. I think there should be method or anything to fill it remainng content or should I use another layout? Any help appreciated
I would highly recommend GridBagLayout, it's one of the most flexible and configurable layout managers available, but it does bring with it complexity
public class HeaderPane extends JPanel {
public HeaderPane() {
setLayout(new GridBagLayout());
add(new JButton("Tab 1"));
add(new JButton("Tab 2"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.BASELINE_TRAILING;
add(new JButton("Minimize"), gbc);
add(new JButton("Maximise"));
add(new JButton("Close"));
}
}
Arrgggh, the complexity burns, it burns 😱 sarcasm
So, this solution is a single container, with a single layout manager. I'm not saying a more complex requirement might benefit from a compounding solution (I'd be tempted to put the min/max/close and tab buttons in there own containers), but as a starting point, it's relatively simple.
Runnable example
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new HeaderPane(), BorderLayout.NORTH);
frame.add(new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 200);
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HeaderPane extends JPanel {
public HeaderPane() {
setLayout(new GridBagLayout());
add(new JButton("Tab 1"));
add(new JButton("Tab 2"));
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.BASELINE_TRAILING;
add(new JButton("Minimize"), gbc);
add(new JButton("Maximise"));
add(new JButton("Close"));
}
}
}
I suggest using BoxLayout as the layout manager of panel to organize the left and right part.
Full demo code below:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(()->{
JFrame frame = new JFrame("Solution");
JPanel container = new JPanel();
container.setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
JPanel tabpanel= new JPanel();
tabpanel.setLayout(new FlowLayout(FlowLayout.LEFT));
tabpanel.add(new JButton("Tab 1"));
tabpanel.add(new JButton("Tab 2"));
panel.add(tabpanel);
panel.add(new JButton("Minimize"));
panel.add(new JButton("Resize"));
panel.add(new JButton("Quit"));
container.add(panel, BorderLayout.PAGE_START);
frame.add(container);
frame.pack();
frame.setSize(new Dimension(500,500));
frame.setVisible(true);
});
}
}
What it looks like:
As suggested in the comments: One solution could be to place the "tabs" and "buttons" into separate panels, and add them in the WEST and EAST of the title panel, which has a BorderLayout:
Here is the MCVE:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TitleBarLayout
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui()
{
JFrame f = new JFrame();
JPanel mainPanel = new JPanel(new BorderLayout());
JPanel titleBar = new JPanel(new BorderLayout());
JPanel tabPanel = new JPanel();
tabPanel.setLayout(new FlowLayout());
tabPanel.add(new JButton("Tab 1"));
tabPanel.add(new JButton("Tab 2"));
titleBar.add(tabPanel, BorderLayout.WEST);
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(new JButton("Minimize"));
buttonsPanel.add(new JButton("Resize"));
buttonsPanel.add(new JButton("Quit"));
titleBar.add(buttonsPanel, BorderLayout.EAST);
mainPanel.add(titleBar, BorderLayout.NORTH);
f.getContentPane().add(mainPanel);
f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
I feel as beginner I may have bitten off too much in regards to application building. That said, I am working on developing an application for a friend that will have prompts where each JPanel will provide fields to create an object to be used later. What I would like to have happen is that when the panel loads, it displays one object creation panel and a button to dynamically add a new panel if the user wants to make multiples (the plus button would add the new panel).
I have drawn up something in paint to illustrate this:
By my very limited understanding, I can create a panel to hold these sub-panels, and then add a action listener to the '+' button to create new panels. The only way I could think to implement this is to create a constructor for the panel I want to add. Is this possible? Let me show you what I have:
package com.company;
import java.awt.*;
import javax.swing.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeGui extends JFrame{
protected int panelCount;
//row 1
JPanel row1 = new JPanel();
JLabel splitSnakeLabel = new JLabel("Create a Split Snake", JLabel.CENTER);
//row 2
JPanel row2 = new JPanel();
JButton addButton = new JButton("+");
public MainSnakeGui() {
super("Snake Channels");
setSize(550, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GridLayout layout = new GridLayout(5, 1, 10, 10);
setLayout(layout);
FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
row1.setLayout(layout1);
row1.add(splitSnakeLabel);
add(row1);
GridLayout layout2 = new GridLayout(1, 2, 10, 10);
row2.setLayout(layout2);
row2.add(addButton);
MainSnakeConstructor snakePanel = new MainSnakeConstructor();
row2.add(snakePanel);
add(row2);
setVisible(true);
}
public static void setLookAndFeel () {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
}
}
public static void main(String[] arg) {
MainSnakeGui.setLookAndFeel();
MainSnakeGui frame = new MainSnakeGui();
}
}
Here is the constructor:
package com.company;
import javax.swing.*;
import java.awt.*;
/**
* Created by Travis on 3/1/2015.
*/
public class MainSnakeConstructor extends JFrame {
public MainSnakeConstructor () {
JPanel splitSnakeRow = new JPanel();
JLabel snakeNameLabel = new JLabel("Snake Name");
JLabel channelCountLabel = new JLabel("Channel Count");
JCheckBox artistSuppliedCheckBox = new JCheckBox("Artist Supplied?");
JTextField snakeNameTextField = new JTextField(30);
JTextField channelCountTextField = new JTextField(3);
GridLayout layout = new GridLayout(3,2,10,10);
splitSnakeRow.setLayout(layout);
splitSnakeRow.add(snakeNameLabel);
splitSnakeRow.add(channelCountLabel);
splitSnakeRow.add(artistSuppliedCheckBox);
splitSnakeRow.add(snakeNameTextField);
splitSnakeRow.add(channelCountTextField);
add(splitSnakeRow);
}
}
Think about it differently. You want a button that allows you to add new panels, so you really only need a single button.
From there, you need some kind common panel which provides the functionality you want to the user (the creation panel). Then, when the user clicks the add button, you create a new creation panel and add it to the container been used to display them, for example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
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.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
JButton btnAdd = new JButton("+");
setLayout(new BorderLayout());
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
buttons.add(btnAdd);
add(buttons, BorderLayout.NORTH);
JPanel content = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 1;
content.add(new JPanel(), gbc);
add(new JScrollPane(content));
btnAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CreationPane pane = new CreationPane();
int insertAt = Math.max(0, content.getComponentCount() - 1);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
content.add(pane, gbc, insertAt);
content.revalidate();
content.repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public static class CreationPane extends JPanel {
private static int count;
public CreationPane() {
setLayout(new GridBagLayout());
add(new JLabel("Make it so " + (count++)));
setBorder(new CompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));
}
}
}
Now having done all that, I prefer the VerticalLayout manager from SwingLabs, SwingX library, which basically does the same thing...
Trying to build out a GUI for my game but no matter what layout I work with I can't get the nest of panels to do what I like
My goal is this
http://i182.photobucket.com/albums/x202/NekoLLX/CharGenmockup-1.jpg
http://i182.photobucket.com/albums/x202/NekoLLX/CharGenmockup2.jpg
And Building off the Mad ones excelent revision I've got my left side as i like it but now the right eludes me
The general idea is that clicking on the title bars of the left menu will colapase (set visible to false) the content panes associated with them
//http://docs.oracle.com/javase/7/docs/api/java/awt/Color.html
//http://stackoverflow.com/questions/16430922/working-with-nested-panels
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.*;
public class JaGCharCreation {
//set inital size of window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int initalWidth = (int) screenSize.width - 50;
int initalHeight = (int) screenSize.height - 50;
public static void main(String[] args) {
new JaGCharCreation ();
}
//set up thread safe invoking for GUI
public JaGCharCreation () {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
//frame.setLocationRelativeTo(null);
frame.setVisible(true);
// Give the frame an initial size.
frame.setSize(initalWidth, initalHeight);
}
});
}
//main panel to hold all others
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(0, 2));
add(createLeftPane());
add(createRightPane());
}//end of class for master frame
protected JPanel createLeftPane() {
JLabel CharName = new JLabel("Character Name");
CharName.setFont(new Font("Impact", Font.BOLD, 30));
CharName.setBorder(new EmptyBorder(0, 81,0, 00));
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.setBackground(Color.RED);
JPanel content = new JPanel(new GridBagLayout());
content.setOpaque(false);
JPanel view3D = new JPanel();
view3D.setBackground(Color.DARK_GRAY);
JPanel view2D = new JPanel();
view2D.setBackground(Color.PINK);
JPanel viewIsometric = new JPanel();
viewIsometric.setBackground(Color.YELLOW);
JPanel viewData = new JPanel();
viewData.setBackground(Color.MAGENTA);
JPanel top = new JPanel(new GridLayout(0, 2));
top.setBorder(new EmptyBorder(0, 80,0, 80));
top.setBackground(Color.GREEN);
top.add(view3D);
top.add(view2D);
JPanel bottom = new JPanel(new GridLayout(2, 0));
bottom.setBorder(new EmptyBorder(0, 80,0, 80));
bottom.setBackground(Color.GREEN);
bottom.add(viewIsometric);
bottom.add(new JScrollPane(viewData));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 0.5f;
gbc.weightx = 1f;
gbc.fill = GridBagConstraints.BOTH;
content.add(top, gbc);
content.add(bottom, gbc);
panel.add(content);
panel.add(CharName, BorderLayout.NORTH);
return panel;
}//end left pane
protected JPanel createRightPane() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBackground(Color.BLUE);
//set up our image for the title bars
ImageIcon icon = new ImageIcon("GradientDetail.png");
Image img = icon.getImage();
img = img.getScaledInstance(initalWidth/2, 40, java.awt.Image.SCALE_SMOOTH);
final ImageIcon iconSM = new ImageIcon(img);
JPanel name_panel = new JPanel(new BorderLayout())
{
protected void paintComponent(Graphics g)
{
// Dispaly image at full size
g.drawImage(iconSM.getImage(), 0, 0, null);
super.paintComponent(g);
}
};
name_panel.setOpaque( false );
JLabel label = new JLabel(" Character Name");
label.setFont(new Font("Impact", Font.BOLD, 30));
label.setForeground(Color.white);
label.setOpaque(false);
JPanel name_panel_text = new JPanel(new BorderLayout());
name_panel_text.setBackground(Color.WHITE);
name_panel.add(label, BorderLayout.NORTH);
panel.add(name_panel_text);
panel.add(name_panel);
return panel;
}//end right pane
//bassed from http://stackoverflow.com/questions/7340001/determine-clicked-jpanel-component-in-the-mouselistener-event-handling
public class MouseAdapterMod extends MouseAdapter {
// usually better off with mousePressed rather than clicked
public void mousePressed(MouseEvent e) {
if (e.getSource() == "name_panel"){
}
}
}
}//end master panel set
}//end master class
Something along the lines of ...
To be honest, I tried following your code, but got lost, so I re-wrote it...
Basically, you relying on setSize which is going to be ignored and changed by the layout managers as they see fit.
This example uses GridBagLayout and weighty to adjust the space allocated to the top (2D/3D) views and the bottom views, but you should also take a look at overriding the getPreferredSize of the final components, to provide better hints to the layout managers.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridLayout(0, 2));
add(createLeftPane());
add(createRightPane());
}
protected JPanel createLeftPane() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
panel.setBackground(Color.RED);
JPanel content = new JPanel(new GridBagLayout());
content.setOpaque(false);
JPanel view3D = new JPanel();
view3D.setBackground(Color.DARK_GRAY);
JPanel view2D = new JPanel();
view2D.setBackground(Color.PINK);
JPanel viewIsometric = new JPanel();
viewIsometric.setBackground(Color.YELLOW);
JPanel viewData = new JPanel();
viewData.setBackground(Color.MAGENTA);
JPanel top = new JPanel(new GridLayout(0, 2));
top.setBorder(new LineBorder(Color.GREEN, 2));
top.add(view3D);
top.add(view2D);
JPanel bottom = new JPanel(new GridLayout(2, 0));
bottom.add(viewIsometric);
bottom.add(new JScrollPane(viewData));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weighty = 0.5f;
gbc.weightx = 1f;
gbc.fill = GridBagConstraints.BOTH;
content.add(top, gbc);
content.add(bottom, gbc);
panel.add(content);
panel.add(new JLabel("Character name"), BorderLayout.NORTH);
return panel;
}
protected JPanel createRightPane() {
JPanel panel = new JPanel();
panel.setBackground(Color.BLUE);
return panel;
}
}
}