So I'm trying to get the button on the bottom right and the text field taking up the bottom left but it keeps switching around for some reason. I think its borderLayout being stupid. I'm a noob at Java btw. Here's my code:
package textchat;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class window extends JFrame{
public static void main(String[] args)
{
new window();
}
public window()
{
//Window Config
//JFrame frame = new JFrame();
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension dm = tk.getScreenSize();
this.setSize(400,400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("CALI V1");
this.setExtendedState(this.getExtendedState() | JFrame.MAXIMIZED_BOTH);
//this.setLayout(null);
int Width = this.getWidth();
//Panel(s)
JPanel Panel = new JPanel();
Panel.setLayout(new BorderLayout());
JPanel PanelSouth = new JPanel();
JPanel PanelEast = new JPanel();
JPanel PanelWest = new JPanel();
//button
JButton btn = new JButton("SEND");
//Text Area
JTextArea txt = new JTextArea(100 , 100);
txt.setText("TEXT IS HERE");
//Text Field
JTextField fld = new JTextField("Type Here",15);
//Adding to the panel
Panel.add(txt);
PanelSouth.add(PanelEast, BorderLayout.EAST);
PanelSouth.add(PanelWest, BorderLayout.WEST);
PanelEast.add(btn);
PanelWest.add(fld);
//adding to frame
this.add(Panel);
this.add(PanelSouth , BorderLayout.SOUTH);
this.setVisible(true);
}
}
While using BorderLayout in such a way kind of works, you should
not use it in such a way. Besides, your example has several issues.
For instance, you did not start the application on the EDT (Event Dispatch Tread).
Here is a working example that creates your inteded layout. It uses the powerful GroupLayout manager.
package com.zetcode;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class TextChatEx extends JFrame {
public TextChatEx() {
initUI();
}
private void initUI() {
JTextArea area = new JTextArea(15, 15);
JTextField field = new JTextField(15);
JButton sendButton = new JButton("Send");
createLayout(area, field, sendButton);
setTitle("Text chat");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
gl.setAutoCreateContainerGaps(true);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createParallelGroup()
.addComponent(arg[0])
.addGroup(gl.createSequentialGroup()
.addComponent(arg[1])
.addComponent(arg[2]))
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addComponent(arg[0])
.addGroup(gl.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(arg[1])
.addComponent(arg[2]))
);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
TextChatEx ex = new TextChatEx();
ex.setVisible(true);
});
}
}
GroupLayout is a powerful layout manager; with this manager, you don't have to create a bunch of panels to create some basic layout.
public TextChatEx() {
initUI();
}
The GUI creation is delegated to the initUI() method. Rather than placing all the code into the constructor, we use a specialized method.
EventQueue.invokeLater(() -> {
TextChatEx ex = new TextChatEx();
ex.setVisible(true);
});
Each Swing application should be placed on the EDT. Failing to do this can lead to hard to find bugs in the future.
Related
I am just Starting out with JAVA.
I have say a JPanel x, a JPanel y and a BorderLayout JPanel z.
When I try to change the contents of the center of z from default x t y, it works but it doesn't go back to x. I AM calling revalidate() after each. Help please.
The class below is where the problem is.
Main Class Below
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.LayoutManager;
import javax.swing.BorderFactory;
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.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
#SuppressWarnings({ "serial", "unused" })
public class Manager extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Manager frame = new Manager();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Manager() {
setTitle("Popper");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
double width = screenSize.getWidth();
double height = screenSize.getHeight();
height = height/5.1;
setSize((int)width, (int)height);
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(0,0,0,0));
setContentPane(contentPane);
contentPane.setBackground(new Color(14,99,165));
contentPane.setLayout(new BorderLayout(0, 0));
ImageIcon image = new ImageIcon("D:/popper26.png");
setIconImage(image.getImage());
JPanel pane = new JPanel();
calcu cal = new calcu();
curr nup = new curr();
stopc newst = new stopc();
pane.setLayout(new FlowLayout(FlowLayout.CENTER));
JPanel mainpanel = new JPanel();
BorderLayout x =new BorderLayout(0,0);
mainpanel.setLayout(x);
mainpanel.setBackground(Color.WHITE);
JLabel madeby = new JLabel("Project By Anant Bhasin");
madeby.setHorizontalAlignment(SwingConstants.RIGHT);
mainpanel.add(madeby, BorderLayout.SOUTH);
JPanel logo = new JPanel();
logo.setLayout(new FlowLayout(FlowLayout.CENTER));
JLabel jk = new JLabel(new ImageIcon("D:/popper2.png"));
logo.add(jk, BorderLayout.NORTH);
logo.setBackground(Color.decode("#1abc9c"));
mainpanel.add(logo, BorderLayout.NORTH);
mainpanel.add(cal, BorderLayout.CENTER);
contentPane.add(mainpanel, BorderLayout.CENTER);
JPanel newj = new JPanel();
BoxLayout bxl = new BoxLayout(newj, BoxLayout.PAGE_AXIS);
newj.setLayout(bxl);
newj.setBackground(new Color(58,115,144));
contentPane.add(newj, BorderLayout.WEST);
Border emptyBorder = BorderFactory.createEmptyBorder();
JButton calc = new JButton(new ImageIcon("D:/calc.png"));
newj.add(calc);
calc.setBorder(emptyBorder);
calc.setFocusPainted(false);
calc.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
mainpanel.add(BorderLayout.CENTER, cal);
mainpanel.revalidate();
}
});
JButton currb = new JButton(new ImageIcon("D:/curr.png"));
currb.setBorder(emptyBorder);
newj.add(currb);
currb.setFocusPainted(false);
currb.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
mainpanel.add(BorderLayout.CENTER, nup);
mainpanel.revalidate();
}
});
JButton stop = new JButton(new ImageIcon("D:/stop.png"));
stop.setBorder(emptyBorder);
newj.add(stop);
stop.setFocusPainted(false);
stop.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
mainpanel.add(BorderLayout.CENTER, newst);
mainpanel.revalidate();
}
});
JButton timer = new JButton(new ImageIcon("D:/timer.png"));
timer.setBorder(emptyBorder);
newj.add(timer);
timer.setFocusPainted(false);
JButton memo = new JButton(new ImageIcon("D:/memo.png"));
memo.setBorder(emptyBorder);
newj.add(memo);
memo.setFocusPainted(false);
}
}
A BorderLayout is not designed to display multiple components with the same constraint because of the way ZOrder painting works in Swing.
If you need the ability to swap panels, then you should be using a CardLayout.
A CardLayout lets you specify the name of the panel that you want to display. Read the section from the Swing tutorial on How to Use CardLayout for more information and working examples.
You set up the layout with code like:
JPanel main = new JPanel( new CardLayout() );
main.add(panelx, "X");
main.add(panely, "Y");
Then to swap a panel you use code like:
CardLayout cl = (CardLayout)(main.getLayout());
cl.show(main, "X");
I have a JFrame with a JButton , this button open a new JFrame where there should be a text box ( JTextField ) that I will use for a search , the problem is that I don't know how to insert it . I came up with this :
N.B I'm a beginner, sorry in advance for the easy question :)
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.JTextField;
public class MainWindow {
// Seconda Finestra
public static void NuovaFinestra (JPanel panel) {
panel.setLayout(null);
JButton Ricerca = new JButton("Ricerca");
Ricerca.setBounds(100, 100, 200, 50);
panel.add(Ricerca);
Ricerca.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
JFrame FinestradiRicerca = new JFrame("Finestra di Ricerca");
FinestradiRicerca.setBounds(300, 300, 500, 500);
FinestradiRicerca.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel riquadroRicerca = new JPanel();
FinestradiRicerca.add(riquadroRicerca);
FinestradiRicerca.setVisible(true);
JTextField ciao;
ciao = new JTextField ();
}
});
}
//Main
public static void main(String[] args) {
//Finestra Principale
JFrame finestra = new JFrame("Finestra principale");
finestra.setSize(500, 500);
finestra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel della finestra principale
JPanel riquadro = new JPanel();
finestra.add(riquadro);
finestra.setVisible(true);
NuovaFinestra(riquadro);
}
}
You needed to add your new elements to riquadroRicerca BEFORE adding the Panel to FinestradiRicerca, I recommend you NOT to use null layout but a Layout Manager or combinations of them. If you insist on keeping null layout then see below example. But for this kind of app I'd suggest a CardLayout.
I also suggest not using multiple JFrames since they will open multiple windows on task bar which is user unfriendly. See: Use of multiple JFrames, Good / Bad Practice
As an aside note, follow Java naming conventions. For example you called a JFrame as FinestradiRicerca instead rename it to: finestradiRicerca (1st letter of a variable in lowercase).
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.JTextField;
public class MainWindow {
// Seconda Finestra
public static void NuovaFinestra (JPanel panel) {
panel.setLayout(null);
JButton Ricerca = new JButton("Ricerca");
Ricerca.setBounds(100, 100, 200, 50);
panel.add(Ricerca);
Ricerca.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
JFrame FinestradiRicerca = new JFrame("Finestra di Ricerca");
FinestradiRicerca.setBounds(300, 300, 500, 500);
//If you don't want to close whole app when closing this windo change it to: JFrame.DISPOSE_ON_CLOSE
FinestradiRicerca.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel riquadroRicerca = new JPanel();
JTextField ciao;
JLabel myLabel = new JLabel("Here goes your label text");
ciao = new JTextField ();
ciao.setColumns(20);
riquadroRicerca.add(myLabel);
riquadroRicerca.add(ciao);
FinestradiRicerca.add(riquadroRicerca);
FinestradiRicerca.setVisible(true);
}
});
}
//Main
public static void main(String[] args) {
//Finestra Principale
JFrame finestra = new JFrame("Finestra principale");
finestra.setSize(500, 500);
finestra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel della finestra principale
JPanel riquadro = new JPanel();
finestra.add(riquadro);
finestra.setVisible(true);
NuovaFinestra(riquadro);
}
}
So, your code after a few modifications, to make JLabel and JTextField visible gives the following output:
However, please follow my above recomendations.
Add the JTextField to your new JFrame like this. You also have to initialize your textfield. It is basically the same as you have done with the initial JFrame.
JTextField ciao = new JTextField();
FinestradiRicerca.add(ciao);
I am relatively new to programming, so I am sorry if this question is stupid. I am creating a Java program that involves one JButton inside a JPanel, and the JPanel is in a JFrame. Another button is outside the JPanel but still in the JFrame. I set the layout to a BoxLayout. My problem is that the the panel, which I made black, is taking up the whole JFrame except for where the second button is. How do I make the JPanel so it is only taking up the area right around the first button?
public class alt {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
public alt(){
frame.setVisible(true);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
panel.setBackground(Color.black);
frame.setTitle("test");
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
panel.add(button1);
frame.add(panel);
frame.add(button2);
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
}
}
You could make use of a different layout manager, one which gives you more control over deciding how space is allocated and filling is handled, for example, GridBagLayout...
import java.awt.Color;
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 SampleLayout {
public static void main(String[] args) {
new SampleLayout();
}
public SampleLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JPanel panel = new JPanel();
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
panel.setBackground(Color.black);
panel.add(button1);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(panel, gbc);
frame.add(button2, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Take a look at Laying Out Components Within a Container for more details
The reason why your panel takes up the bulk of the frame's content pane lies
in the way the BoxLayout manager works with the minimum, preferred,
and maximum values of components. It takes the maximum value of a component
into account. And since the maximum value of a JPanel is huge, it takes
all the space available. The solution is to change the maximum value
of a panel. However, this is bad practice. I do not recommend to use
the BoxLayout manager -- it is very weak and leads to poor code.
I recommend to use either the MigLayout manager or the GroupLayout manager.
I provide three solutions: a corrected BoxLayout solution, a MigLayout solution,
and a GroupLayout solution.
BoxLayout solution
We determine the maximum size of the button and change the panel's size
to be a bit larger than the button's.
package com.zetcode;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BoxLayoutPanel extends JFrame {
public BoxLayoutPanel() {
initUI();
}
private void initUI() {
JPanel cpane = (JPanel) getContentPane();
cpane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
cpane.setLayout(new BoxLayout(cpane,
BoxLayout.Y_AXIS));
JPanel pnl = new JPanel();
JButton btn1 = new JButton("Button 1");
JButton btn2 = new JButton("Button 2");
Dimension dm = btn1.getMaximumSize();
dm.height += 15;
dm.width += 15;
pnl.setMaximumSize(dm);
pnl.setBackground(Color.black);
add(pnl);
add(Box.createVerticalStrut(10));
pnl.add(btn1);
btn2.setAlignmentX(Component.CENTER_ALIGNMENT);
add(btn2);
setTitle("BoxLayout solution");
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
BoxLayoutPanel ex = new BoxLayoutPanel();
ex.setVisible(true);
}
});
}
}
This is not a clean solution. Generally, we should avoid calling the getMaximumSize() and
the setMaximumSize() in the application code -- this is the layout manager's job. Also in three occasions, we use fixed pixel widths: when we define an empty border, a vertical strut, and a maximum panel's size. This code is however not portable.
Pixel widths change when the resolution of the screen changes. This is a
shortcoming of the BoxLayout manager.
MigLayout solution
This solution is much cleaner and more portable. MigLayout is a third-party
manager, so we need to download additional libraries.
package com.zetcode;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutPanel extends JFrame {
public MigLayoutPanel(){
initUI();
setTitle("MigLayout solution");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void initUI() {
JPanel main = new JPanel(new MigLayout("center"));
JPanel pnl2 = new JPanel();
JButton btn1 = new JButton("Button 1");
JButton btn2 = new JButton("Button 2");
pnl2.setBackground(Color.black);
pnl2.add(btn1);
main.add(pnl2, "wrap");
main.add(btn2, "alignx center");
add(main);
pack();
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutPanel ex = new MigLayoutPanel();
ex.setVisible(true);
}
});
}
}
GroupLayout solution
GroupLayout is a built-in layout manager. With MigLayout, they are the most
portable and flexible layout managers.
package com.zetcode;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import static javax.swing.GroupLayout.PREFERRED_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
public class GroupLayoutPanel extends JFrame {
public GroupLayoutPanel(){
initUI();
setTitle("GroupLayout solution");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JPanel pnl = new JPanel();
JButton btn1 = new JButton("Button 1");
pnl.add(btn1);
JButton btn2 = new JButton("Button 2");
pnl.setBackground(Color.black);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addContainerGap(DEFAULT_SIZE, Integer.MAX_VALUE)
.addGroup(gl.createParallelGroup(CENTER)
.addComponent(pnl, DEFAULT_SIZE, DEFAULT_SIZE,
PREFERRED_SIZE)
.addComponent(btn2))
.addContainerGap(DEFAULT_SIZE, Integer.MAX_VALUE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addContainerGap()
.addComponent(pnl, DEFAULT_SIZE, DEFAULT_SIZE,
PREFERRED_SIZE)
.addPreferredGap(RELATED)
.addComponent(btn2)
.addContainerGap()
);
pack();
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutPanel ex = new GroupLayoutPanel();
ex.setVisible(true);
}
});
}
}
I have JPanel with a border, the problem is that when I add the panel on the JFrame it takes the panel size although I set the preferred size for the panel using setPreferredSize. The layout of the frame is 'BoxLayout' and here's the code:
public class ActionForm extends JFrame {
JPanel namePanel;
JPanel descPanel;
JLabel actionName;
JLabel nameLabel;
JTextField nameTextField, descTextField;
FlowLayout toolBarLayout = new FlowLayout();
public ActionForm() {
this.setLayout(new BoxLayout(this.getContentPane(), BoxLayout.Y_AXIS));
TitledBorder nameBorder= BorderFactory.createTitledBorder(
"Change Description");
nameBorder.setTitleJustification(TitledBorder.LEFT);
namePanel = new JPanel(toolBarLayout);
namePanel.setPreferredSize(new Dimension(150, 150));
nameLabel = new JLabel("ButtonName");
nameTextField = new JTextField("Action's Name", 50);
namePanel.add(nameLabel);
namePanel.add(nameTextField);
namePanel.setBorder(nameBorder);
namePanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
this.add(namePanel);
}
public static void main(String[] args) {
ActionForm form = new ActionForm();
form.setVisible(true);
form.setSize(970, 500);
form.setResizable(false);
}
}
Why the size of the panel doesn't change?
BoxLayout accepting Min/Max/preferredSize that came from JComponents layed by this LayoutManager
(I'm don't want to comment something, because my answer will be so long) please to compare your code with this code example, there are implemented all good (required and important) Swing rulles
for example
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;
public class ActionForm {
private static final long serialVersionUID = 1L;
private JFrame frame;
private JPanel namePanel;
private JLabel nameLabel;
private JTextField nameTextField;
private FlowLayout toolBarLayout = new FlowLayout();
public ActionForm() {
TitledBorder nameBorder = BorderFactory.createTitledBorder(
"Change Description");
nameBorder.setTitleJustification(TitledBorder.LEFT);
namePanel = new JPanel(toolBarLayout);
namePanel.setPreferredSize(new Dimension(150, 150));// hardCoded sizing
namePanel.setMaximumSize(new Dimension(250, 150)); // hardCoded sizing
namePanel.setMinimumSize(new Dimension(150, 150)); // hardCoded sizing
nameLabel = new JLabel("ButtonName");
nameTextField = new JTextField("Action's Name", 10);
namePanel.add(nameLabel);
namePanel.add(nameTextField);
namePanel.setBorder(nameBorder);
namePanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
frame = new JFrame("Mix / Max / PreferredSize for BoxLayout");
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),
BoxLayout.Y_AXIS)); // otherwise nice exceptions java.awt.AWTError:
// BoxLayout can't be shared
frame.add(namePanel);
frame.setPreferredSize(new Dimension(970, 500));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ActionForm form = new ActionForm();
}
});
}
}
> I have a jframe defined in a package 'abc'. this jframe acts as a main class too.
> the same package 'abc' also contain 4 jpanels(panel1,panel2,panel3,panel4) defined in different java classes.
how one should call/show these different jpanels from main jframe class at user clicks on different buttons ?
what if I've got 40-50 such jpanels.what would be the most efficient way to toggle these panels from the main class ?
This is a very simple example that uses next() and one button to change panels.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.border.Border;
public class TestCards extends JFrame {
private final CardLayout cl = new CardLayout();
private final JPanel cards = new JPanel(cl);
private final Border border = BorderFactory.createEmptyBorder(60, 60, 60, 60);
public TestCards() {
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
JPanel panel1 = new JPanel(new GridBagLayout());
panel1.setBorder(border);
panel1.setBackground(Color.RED);
panel1.add(new JLabel("Card 1"));
cards.add(panel1, "First Panel");
JPanel panel2 = new JPanel(new GridBagLayout());
panel2.setBorder(border);
panel2.setBackground(Color.GREEN);
panel2.add(new JLabel("Card 2"));
cards.add(panel2, "Second Panel");
JPanel panel3 = new JPanel(new GridBagLayout());
panel3.setBorder(border);
panel3.setBackground(Color.BLUE);
panel3.add(new JLabel("Card 3"));
cards.add(panel3, "Third Panel");
JButton controlButton = new JButton("Switch");
controlButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cl.next(cards);
}
});
JPanel controlPanel = new JPanel();
controlPanel.setBackground(Color.LIGHT_GRAY);
controlPanel.add(controlButton);
contentPane.add(cards);
contentPane.add(controlPanel);
cl.show(cards, "First Panel");
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
TestCards frame = new TestCards();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
An alternative (among many) would be to use 3 buttons where each one shows a specific panel (by using show instead of next).
See this for more info.
CardLayout's previous and next methods can be used to navigate forward & back respectively through the card components. To make it easier to navigate the components non-consecutively, you could place the card names in a String array:
private static final String[] CARD_NAMES = { "name_2996062106101", ... };
Then, to display a specific cardIndex, you could simply use:
CardLayout layout = (CardLayout) contentPane.getLayout();
layout.show(contentPane, CARD_NAMES[cardIndex]);
For more see How to Use CardLayout.