To keep things short, I know how to switch between different JPanels using CardLayout and only using one JFrame but I want to know how, if it is possible, to have different sized JPanels occupying the JFrame. CardLayout uses the largest of the panels but I was wondering if there was any way to suppress that or override so that I could add different JPanels to a JFrame that were different sizes. Here is my code:
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class View {
//Views
private JFrame frame;
private JPanel container;
private JPanel panel1;
private JPanel panel2;
private CardLayout layout;
private final int WIDTH = 1280;
private final int HEIGHT = 720;
public View(){
init();
frame = new JFrame();
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.add(container);
frame.pack();
frame.setVisible(true);
}
private void init(){
JButton button = new JButton();
layout = new CardLayout();
container = new JPanel(layout);
panel1 = new JPanel();
panel2 = new JPanel();
panel1.setBackground(Color.WHITE);
panel1.setPreferredSize(new Dimension(500, 500));
panel1.add(button);
panel2.setBackground(Color.BLACK);
panel2.setPreferredSize(new Dimension(500, 500));
container.add(panel1, "panel1");
container.add(panel2, "panel2");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
layout.show(container, "panel2");
}
});
}
public static void main(String [] args){
View view = new View();
}
}
I put the JButton in the init method because I need it for future use and wanted to make sure now that it could be done.
For a quick solution try two separate JFrames, or resize the frame to the size of the panel on button press.
The only way it seems to work with the cardLayout is by setting the preferred size of the container panel after the button is clicked.
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
layout.show(container, "panel2");
container.setPreferredSize(new Dimension(100, 100));
frame.pack();
}
});
It's not a very great solution but it's pretty simple.
If a login window is what you need I would definitely recommend using 2 frames, just seems more logical.
You can't use a CardLayout. So you need to manage the visible panel yourself.
The logic would be something like:
JPanel content = (JPanel)frame.getContentPane();
content.removeAll();
content.add( theOtherPanel );
frame.pack();
So the idea is you only have one panel added to the content pane at a time and you need to swap it by doing the remove and add before you pack the frame so the frame is displayed at the size of each panel.
The question is why do you want to do this? Users don't like to see the size of the frame continually changing.
Related
I have a JPanel and JButton on the JFrame.
on runtime add JLabel to JPanel When click JButton.
I use of the following code:
panel.setLayout(null);
jLabel _lbl=new jLabel();
_lbl.setText("Label");
panel.add(_lbl);
panel.validate();
but no display any JLabel in JPanel.
I see you create a JLabel called _lbl:
JLabel _lbl=new JLabel();
but you never add it to your panel. Instead you add a new JLabel with no text to your panel:
panel.add(new JLabel());
This would ofcourse construct an empty label which wont be visible.
Also try calling revalidate() and repaint() on your JPanel instance after adding the JLabel like so:
JLabel _lbl=new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
With this you may also need to call pack() on your frames instance so as to resize the JFrame to fit the new components.
Also please never use a null/Absolute layout this is very bad practice (unless doing animation) and may prove to be problematic and very hard to use.
Rather use a LayoutManager:
A Visual Guide to Layout Managers
or if you only have a single component on the JPanel simply call add(label); as it will stretch to the JPanel size.
UPDATE:
Here is a small sample. Simply adds JLabels to the JPanel each time JButton is pressed:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JavaApplication116 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication116().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(final JFrame frame) {
final JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Add label");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JLabel _lbl = new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
frame.pack();//so our frame resizes to compensate for new components
}
});
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.SOUTH);
}
}
I'm completely new to using the GUI in java, so I'm having a bit of trouble figuring out how to align everything that I need to. I have to panels in my JFrame that I need to align (One to the left, one to the right) and a few buttons in one of the panels that I need to be centered in the panel. Here is my code.
package application;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.nio.*;
import java.util.*;
public class Main extends JPanel
{
public static void main(String[] args)
{
//set the ui to the native OS
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException | InstantiationException | IllegalAccessException
| UnsupportedLookAndFeelException e)
{
}
JFrame frame = new JFrame("Application Name");
Menu menu = new Menu();
JPanel iconPanel = new JPanel();
final JPanel grid = new JPanel(new FlowLayout());
JButton firewallButton = new JButton("Firewall");
JButton networkButton = new JButton("Network");
JButton printerButton = new JButton("Printer");
int iconPanelSizeX;
int iconPanelSizeY;
int gridSizeX;
int gridSizeY;
int gridPosition;
//frame setting
frame.setSize(800, 600);
frame.setMinimumSize(new Dimension(800, 600));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//add grid and iconPanel JPanels to the frame
frame.add(iconPanel);
iconPanel.add(firewallButton);
iconPanel.add(networkButton);
iconPanel.add(printerButton);
frame.add(grid);
//iconPanel settings
iconPanel.setBorder(BorderFactory.createLoweredSoftBevelBorder());
iconPanel.setBackground(Color.gray);
iconPanel.setLayout(new FlowLayout());
iconPanel.setSize(new Dimension(100, 600));
iconPanel.setVisible(true);
//grid setting
grid.setBackground(Color.red);
grid.setSize(new Dimension(700, 600));
grid.setVisible(true);
//this is for resizing components when the user resizes the window
int counter = 0;
while(counter == 0)
{
firewallButton.setSize(new Dimension(iconPanel.getWidth(), 50));
networkButton.setSize(new Dimension(iconPanel.getWidth(), 50));
printerButton.setSize(new Dimension(iconPanel.getWidth(), 50));
iconPanelSizeX = frame.getWidth() / 10;
iconPanelSizeY = frame.getHeight();
gridSizeX = (frame.getWidth() / 10) * 9;
gridSizeY = frame.getHeight();
iconPanel.setSize(new Dimension(iconPanelSizeX, iconPanelSizeY));
grid.setSize(new Dimension(gridSizeX, gridSizeY));
}
}
}
As you can see, the second JPanel (grid) doesn't line up with the right side of the frame, and the buttons inside iconTray don't center either. I realize these are both probably simple layout fixes, but I have no clue where to start.
For simple splitting of JFrame you can use GridLayout with 1 row and 2 colums.
frame.setLayout(new GridLayout(1,2,3,3)); //3,3 are gaps
frame.add(grid);
frame.add(iconPanel);
For centering components in panels you can use FlowLayout which is by default set on JPanels:
Doing it manualy:
grid.setLayout(new FlowLayout()); //Centered components
grid.setLayout(new FlowLayout(FlowLayout.LEFT,3,3)); //Components aligned to left
grid.setLayout(new FlowLayout(FlowLayout.RIGHT,3,3)); //Components aligned to right
This is how it looks:
Also, few observations:
Never call setXXXSize() methods for your components;
Try to avoid calling setSize(); for JFrame, call pack(); instead;
Call setVisible(true); in the end of code;
All your huge code can be "stripped" to this:
import javax.swing.*;
import java.awt.*;
public class Main extends JPanel
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Application Name");
JPanel iconPanel = new JPanel();
JPanel grid = new JPanel(new FlowLayout());
JButton firewallButton = new JButton("Firewall");
JButton networkButton = new JButton("Network");
JButton printerButton = new JButton("Printer");
frame.add(iconPanel);
iconPanel.add(firewallButton);
iconPanel.add(networkButton);
iconPanel.add(printerButton);
grid.setBackground(Color.GREEN);
frame.setLayout(new GridLayout(1,2,3,3));
frame.add(grid);
frame.add(iconPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
how to align buttons vertically?
This example uses a vertical Box in the WEST area of the frame's default BorderLayout:
import java.awt.*;
import javax.swing.*;
/** #see http://stackoverflow.com/a/14927280/230513 */
public class Main {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
display();
}
});
}
private static void display() throws HeadlessException {
JFrame frame = new JFrame("Application Name");
JButton firewallButton = new JButton("Firewall");
JButton networkButton = new JButton("Network");
JButton printerButton = new JButton("Printer");
//iconPanel settings
Box iconPanel = new Box(BoxLayout.Y_AXIS);
iconPanel.add(firewallButton);
iconPanel.add(networkButton);
iconPanel.add(printerButton);
iconPanel.setBackground(Color.gray);
iconPanel.setVisible(true);
frame.add(iconPanel, BorderLayout.WEST);
//grid setting
JPanel grid = new JPanel() {
#Override
// arbitrary placeholder size
public Dimension getPreferredSize() {
return new Dimension(320, 230);
}
};
grid.setBackground(Color.red);
frame.add(grid, BorderLayout.CENTER);
//frame setting
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
I suggest you take some time going through A Visual Guide to Layout Managers. This will help you become familiar with the layout managers which are available with the Standard API. It takes some experience and hard work to figure out which of these is the right tool to get the exact look you want. Once you become comfortable with what is available from the Standard API, you should also look around for third-party Layout Manager APIs which provide other options.
I have to panels in my JFrame that I need to align (One to the left,
one to the right) and a few buttons in one of the panels that I need
to be centered in the panel. Here is my code.
I realize these are both probably simple layout fixes, but I have no
clue where to start.
Use more complex layout than simple FlowLayout which you actually using. I suggest to you use
GridBagLayout
BoxLayout
Check references here
Hi I am trying to create an interface consisting of a JComboBox and a JTextField. I have sorted out the code to add a label to the JComboBox but I am having trouble adding a label to the text field. Any help would be appreciated.
import javax.swing. *;
import java.awt.event. *;
import java.awt.FlowLayout;
import java.lang.Math;
public class AreaFrame3 extends JFrame
{
public static void main(``String[]args)
{
//Create array containing shapes
String[] shapes ={"(no shape selected)","Circle","Equilateral Triangle","Square"};
//Use combobox to create drop down menu
JComboBox comboBox=new JComboBox(shapes);
JPanel panel1 = new JPanel(new FlowLayout()); //set frame layout
JLabel label1 = new JLabel("Select shape:");
panel1.add(label1);
panel1.add(comboBox);
JTextField text = new JTextField(10); //create text field
JFrame frame=new JFrame("Area Calculator Window");//create a JFrame to put combobox
frame.setLayout(new FlowLayout()); //set layout
frame.add(panel1);
frame.add(text);
JButton button = new JButton("GO"); //create GO button
frame.add(button);
//set default close operation for JFrame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//set JFrame ssize
frame.setSize(400,250);
//make JFrame visible. So we can see it
frame.setVisible(true);
}
}
Here is one way to do it. Simply put all the widgets in your panel1 in appropriate order.
In the long run this is probably not very much maintainable and you would want to have a better LayoutManager than FlowLayout, but if you just want to learn Swing, this may be a good start. If you feel that FlowLayout is not good enough, take a look at the LayoutManager tutorial. My personal favourites are: BorderLayout and GridBagLayout. MigLayout may also be a good one, but I have never used it and it is not part of the JVM.
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class AreaFrame3 {
protected void initUI() {
// Create array containing shapes
String[] shapes = { "(no shape selected)", "Circle", "Equilateral Triangle", "Square" };
// Use combobox to create drop down menu
JComboBox comboBox = new JComboBox(shapes);
JLabel label1 = new JLabel("Select shape:");
JPanel panel1 = new JPanel(new FlowLayout()); // set frame layout
JLabel label2 = new JLabel("Text label:");
JTextField text = new JTextField(10); // create text field
panel1.add(label1);
panel1.add(comboBox);
panel1.add(label2);
panel1.add(text);
JFrame frame = new JFrame("Area Calculator Window");// create a JFrame to put combobox
frame.setLayout(new FlowLayout()); // set layout
frame.add(panel1);
JButton button = new JButton("GO"); // create GO button
frame.add(button);
// set default close operation for JFrame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
// make JFrame visible. So we can see it
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new AreaFrame3().initUI();
}
});
}
}
I have a JPanel and JButton on the JFrame.
on runtime add JLabel to JPanel When click JButton.
I use of the following code:
panel.setLayout(null);
jLabel _lbl=new jLabel();
_lbl.setText("Label");
panel.add(_lbl);
panel.validate();
but no display any JLabel in JPanel.
I see you create a JLabel called _lbl:
JLabel _lbl=new JLabel();
but you never add it to your panel. Instead you add a new JLabel with no text to your panel:
panel.add(new JLabel());
This would ofcourse construct an empty label which wont be visible.
Also try calling revalidate() and repaint() on your JPanel instance after adding the JLabel like so:
JLabel _lbl=new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
With this you may also need to call pack() on your frames instance so as to resize the JFrame to fit the new components.
Also please never use a null/Absolute layout this is very bad practice (unless doing animation) and may prove to be problematic and very hard to use.
Rather use a LayoutManager:
A Visual Guide to Layout Managers
or if you only have a single component on the JPanel simply call add(label); as it will stretch to the JPanel size.
UPDATE:
Here is a small sample. Simply adds JLabels to the JPanel each time JButton is pressed:
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class JavaApplication116 {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new JavaApplication116().createAndShowUI();
}
});
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(final JFrame frame) {
final JPanel panel = new JPanel(new FlowLayout());
JButton button = new JButton("Add label");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JLabel _lbl = new JLabel("Label");//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
frame.pack();//so our frame resizes to compensate for new components
}
});
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.getContentPane().add(button, BorderLayout.SOUTH);
}
}
I am new to Java and mostly CardLayout. I want to simply switch "windows" represented by JPanels. I read somewhere that job for CardLayout. But my problem is, when add chatPanel to mainPanel (this is the CardLayout one), it shifts the content of connectPanel several pixels to the top, away from its centered position. Is I skip in my code createChatPanel(), its where it should be.
I have this code:
package App;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import Validators.*;
public class GUI {
private JFrame mainFrame = null;
private JPanel mainPanel = null;
private CardLayout cl = new CardLayout();
public GUI(){
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (UnsupportedLookAndFeelException e) {
}
catch (ClassNotFoundException e) {
}
catch (InstantiationException e) {
}
catch (IllegalAccessException e) {
}
mainFrame = new JFrame("MainChat");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(640,480);
mainFrame.setLocationRelativeTo(null);
mainFrame.setResizable(false);
mainFrame.setLayout(new GridBagLayout());
JMenuBar menuBar = new JMenuBar();
JMenu menuFile = new JMenu("Soubor");
JMenu menuHelp = new JMenu("Nápověda");
menuBar.add(menuFile);
menuBar.add(menuHelp);
menuFile.add(new JMenuItem("Nové Připojení"));
menuFile.add(new JSeparator());
menuFile.add(new JMenuItem("Konec"));
menuHelp.add(new JMenuItem("O programu"));
mainFrame.setJMenuBar(menuBar);
createMainPanel();
createConnectPanel();
createChatPanel();
mainFrame.setVisible(true);
}
public void createMainPanel() {
mainPanel = new JPanel(cl);
mainFrame.add(mainPanel);
}
public void createConnectPanel() {
JPanel connectPanel = new JPanel();
mainPanel.add(connectPanel,"connectPanel");
JTextField ip = new JTextField();
ip.setDocument(new JTextFieldLimit(15));
ip.setColumns(11);
JLabel iplabel = new JLabel("IP:");
connectPanel.add(iplabel);
connectPanel.add(ip);
JButton connect = new JButton("Connect");
connect.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cl.show(mainPanel,"chatPanel");
}
});
connectPanel.add(connect);
}
public void createChatPanel(){
JPanel chatPanel = new JPanel();
mainPanel.add(chatPanel,"chatPanel");
JTextArea chatbox = new JTextArea();
chatbox.setPreferredSize(new Dimension(200,200));
chatPanel.add(chatbox);
}
}
Please, what I messed up? Thanks.
Since you are adding two JPanels to your main JPanel,
these two panels both need to fit within the main panel.
If one of the inner panels is much larger than the other one,
the main panel will adjust to fit the larger one.
E.g. commenting this line:
chatbox.setPreferredSize(new Dimension(200,200));
would cause your text field to stay put. This is because the
chatbox would not cause the container to resize.
Also note that the main panel is not initially the same size as your
main frame, since you have not set the size of the main panel.
If you would set the size of the connectPanel to the same size
as your main frame, the connectPanel would not
be automatically resized when adding the chatPanel (as a
consequence of the mainPanel being resized)
So what you could do is add the middle line in:
JPanel connectPanel = new JPanel();
connectPanel.setSize(640, 480);
mainPanel.add(connectPanel, "connectPanel");
, which probably would solve your problem.
Although this would work, I definitely recommend using
MIG Layout for
all your GUI designing. It will save you plenty of time if
you take an hour to learn it. It will also save you from
having to set sizes manually (and thereby saving you from
having to rewrite half your GUI code with every design change).
If you want a JPanel centered in another, place your connectPanel in another JPanel that acts as a dumb container, and have this container use GridBagLayout. Then if you add the connectPanel to the container without any GridBagConstraints, it will be added to the default position for GridBagLayout which is centered. You can then add this container JPanel to your mainPanel using the same constant that you would have used for your connectPanel.
I would tend to let the layouts determine the size of components and avoid using setSize and even setPreferredSize, and would definitely call pack() on my JFrame prior to setting it visible. You definitely don't want to set the size or preferredSize of your JTextField, but rather set its columns and rows and place it in a JScrollPane, and then add that JScrollPane to the view.
Edit:
Here's an example that shows placement of something like your connect panel at the top, middle and bottom of a small gui. Just press the "Next" button to see what I mean:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class GUI2 extends JPanel {
public static final String CONNECT_NORTH = "connect north";
public static final String CONNECT_CENTER = "connect center";
private static final String CONNECT_SOUTH = "connect south";
private static final String CHAT_PANEL = "chat panel";
private CardLayout cardlayout = new CardLayout();
public GUI2() {
setLayout(cardlayout);
add(createConnectPanel(BorderLayout.NORTH), CONNECT_NORTH);
add(createConnectPanel(BorderLayout.CENTER), CONNECT_CENTER);
add(createConnectPanel(BorderLayout.SOUTH), CONNECT_SOUTH);
add(createChatPanel(), CHAT_PANEL);
}
public void nextPanel() {
cardlayout.next(this);
}
private JPanel createConnectPanel(String borderlayoutLocation) {
JPanel innerPanel = new JPanel();
innerPanel.add(new JLabel("IP:"));
innerPanel.add(Box.createHorizontalStrut(5));
innerPanel.add(new JTextField(11));
innerPanel.add(Box.createHorizontalStrut(5));
innerPanel.add(new JButton(new AbstractAction("Next") {
#Override
public void actionPerformed(ActionEvent arg0) {
GUI2.this.nextPanel();
}
}));
JPanel innerPanel2 = new JPanel(new GridBagLayout());
innerPanel2.add(innerPanel);
JPanel connectPanel = new JPanel(new BorderLayout());
connectPanel.add(innerPanel2, borderlayoutLocation);
return connectPanel;
}
private JPanel createChatPanel() {
JPanel chatPanel = new JPanel(new BorderLayout(5, 5));
chatPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
chatPanel.add(new JScrollPane(new JTextArea(15, 30)), BorderLayout.CENTER);
chatPanel.add(new JTextField(), BorderLayout.SOUTH);
return chatPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
}
});
}
private static void createGui() {
JFrame frame = new JFrame("App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new GUI2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}