Could anyone point out where I am going wrong with this java swing gui code. I am trying to add two buttons to a JPanel and then add it into a frame after setting the size but it seems to not be responding to the setSize values passed to it
public Test() {
GridLayout layout = new GridLayout(1, 2);
//this.setLayout(layout);
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setSize(new Dimension(30, 100));
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
this.add(buttonPanel);
this.add(new PaintSurface());
this.setVisible(true);
}
This may not answer your immediate question...but...
GridLayout layout = new GridLayout(1, 2);
this.setLayout(layout);
// You're original code...
// Why are you using `BorderLayout.CENTER` on a `GridLayout`
this.add(new PaintSurface(), BorderLayout.CENTER);
You set the layout as a GridLayout, but you are using BorderLayout constraints to apply one of the components??
Also, make sure that there are not calls to Test#pack else where in your code, as this will override the values of setSize
UPDATED (from changes to question)
Remember, the default layout manager for JFrame is BorderLayout, so even though you're calling buttonPanel.setSize, it's likely that it's begin overridden by the layout manager anyway.
I would take a read through A Visual Guide to Layout Managers and Using Layout Managers to find a layout manager that best meets your requirements.
If you can't find a single one, consider using compound components with different layout managers to bring the layout closer to what you want to achieve.
Ok, I'll just give you a solution:
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Cobie extends JFrame{
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
JPanel buttonPanel = new JPanel();
JPanel paintSurface = new JPanel();
public Cobie(){
setLayout(new GridLayout(2,1));
buttonPanel.setBackground(Color.RED);
paintSurface.setBackground(Color.BLUE);
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
add(buttonPanel);
add(paintSurface);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run(){
Cobie c = new Cobie();
c.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
c.setSize(600,400); //Avoid using this method
c.setVisible(true);
}
});
}
}
According to your updated answer, you are not setting your layout on anything.
Anyway, if you use LayoutManager's (which you should), it is pointless to call setSize()/setBounds()/setLocation() since it will be overriden by the LayoutManager (that is actually its job).
And guessing that your Test class extends JFrame, by calling this.add(buttonPanel); this.add(new PaintSurface()); you are adding two components with the same constraint (BorderLayout.CENTER, since BorderLayout is the default LayoutManager of the content pane of the JFrame) to the content pane.
Consider reading the LayoutManager tutorial.
Just for information, although far from perfect, this shows something "working":
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test extends JFrame {
private JPanel buttonPanel;
public class PaintSurface extends JButton {
public PaintSurface() {
super("Paint surface dummy");
}
}
public Test() {
GridLayout layout = new GridLayout(1, 2);
this.setLayout(layout);
this.setSize(700, 700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonPanel = new JPanel();
buttonPanel.setSize(new Dimension(30, 100));
JButton rectButton = new JButton("Rectangle");
JButton ovalButton = new JButton("Oval");
buttonPanel.add(rectButton);
buttonPanel.add(ovalButton);
this.add(buttonPanel);
this.add(new PaintSurface());
this.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
Related
There's a simple application that uses JScrollPane for 2 lists and have 1 button to switch them. I want to add many more Swing elements, but I cannot move them with object.setBounds. Whatever I will write in this method element doesn't change its place and size.
package paka;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;;
public class Question extends JFrame {
private JList leftlist,rightlist;
private JButton movebutton;
private JLabel pointlessLabel;
private static String[] foods={"bacon","wings","ham","beef","more bacon"};
public Question(){
super("title");
setLayout(new FlowLayout());
leftlist=new JList(foods);
leftlist.setVisibleRowCount(3);
leftlist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
add(new JScrollPane(leftlist));
movebutton = new JButton("Move");
movebutton.addActionListener(
new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
rightlist.setListData(leftlist.getSelectedValues());
}
}
);
add(movebutton);
rightlist = new JList();
rightlist.setVisibleRowCount(3);
rightlist.setFixedCellWidth(100);rightlist.setFixedCellHeight(15);
rightlist.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
add(new JScrollPane(rightlist));
//Okay, deleting everything below we have only two list with button that moves elements from 1st list to 2nd
movebutton = new JButton("Click me!");
movebutton.setBounds(700, 100, 80, 20);
add(movebutton);
pointlessLabel = new JLabel("I'm unbreakable");
pointlessLabel.setBounds(500,200,100,50);
add(pointlessLabel);
}
public static void main(String args[]){
Question go = new Question();
go.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
go.setSize(300,200);
go.setVisible(true);
}
}
You need to use combinations of Layout Managers (as stated by #AndrewThompson on his comment above) to achieve the same output that you have with a null layout.
Avoid the use of null layout, see: Null layout is evil and Why is it frowned upon to use a null layout in Swing?
With the code below you can have the same output you had with setBounds() method. I didn't added an ActionListener to this code, since I'm just demonstrating how to stop using null layout and have the same output. Yes! The second one seems shorter, that's because of pack() but you can still setSize() if you want / need an specific window size.
To add more elements below just add more JPanels and add them to pane, I hope this helps to solve your issue, and if not, please post a Minimal Complete and Verifiable Example that we can copy-paste, make it short, but still shows your issue and follows above recommendations
Important Note:
I'll bring a quote from This answer's comment of #MadProgrammer, because I used prototypeCellValue to make the rightList's width shorter:
I'd also be careful with prototypeCellValue, unless the value matches the expected length of your data, it could truncate your data when it's displayed, just need to be careful
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class QuestionTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
String[] foods = { "bacon", "wings", "ham", "beef", "more bacon" };
JFrame frame;
JPanel topPane, bottomPane, pane;
JList leftList, rightList;
JButton moveButton, clicMeButton;
JScrollPane scroll;
JLabel label;
frame = new JFrame("title");
topPane = new JPanel();
bottomPane = new JPanel();
pane = new JPanel();
leftList = new JList(foods);
rightList = new JList();
moveButton = new JButton("Move");
clicMeButton = new JButton("Click me!");
label = new JLabel("I'm unbreakable");
leftList.setVisibleRowCount(3);
rightList.setVisibleRowCount(3);
leftList.setPrototypeCellValue(String.format("%30s", ""));
rightList.setPrototypeCellValue(String.format("%30s", ""));
pane.setLayout(new BoxLayout(pane, BoxLayout.PAGE_AXIS));
topPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
scroll = new JScrollPane(leftList);
topPane.add(scroll);
topPane.add(moveButton);
scroll = new JScrollPane(rightList);
topPane.add(scroll);
bottomPane.setLayout(new FlowLayout());
bottomPane.add(clicMeButton);
bottomPane.add(label);
pane.add(topPane);
pane.add(bottomPane);
frame.add(pane);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
I have a problem using BorderLayout, but first of all, here is my GUI setup:
As you can see, I have 3 different components inside my JFrame. Adding the JMenu and JList works fine. But my JPanel should have a fixed size so I want to prevent my BorderLayout from stretching the panel. I tried everything, setPreferredSize() setMinimumSize() setMaximumSize() setSize() but again the layout stretches my panel to fit to the frame. (The panel is added to the frame using BorderLayout.CENTER).
Is there any way to prevent this or do you have other suggestions to manage the problem?
I'm pretty sure you mean BorderLayout, not BoxLayout, because there is no BoxLayout.CENTER and it looks like you use a BorderLayout to place the components.
I think the problem here is that you only set the preferred size of the panel that you add to BorderLayout.CENTER. This doesn't have any effect. Instead you need nested layouts.
In this example I added the JPanel called centerPanel, which is using a standard GridBagLayout (to center the added component), to BorderLayout.CENTER. Then I added the additional JPanel called panel, which has a custom preferrdSize, to centerPanel. This way panel won't get stretched.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Example {
public Example() {
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));
DefaultListModel<String> listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
list.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Uncomment the following lines if you also want to prevent the
// 'wrapping' of the panel.
/*
* #Override public Dimension getMinimumSize() { return new
* Dimension(400, 400); }
*/
};
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (int i = 1; i <= 5; i++) {
menuBar.add(new JMenu("Menu " + i));
listModel.addElement("Element " + i);
panel.add(new JLabel("Label " + i));
}
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(panel);
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(menuBar, BorderLayout.NORTH);
contentPanel.add(list, BorderLayout.WEST);
contentPanel.add(centerPanel);
JFrame frame = new JFrame();
frame.setContentPane(contentPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
Add your existing JPanel to a JPanel having Flowlayout, the default, or having GridBagLayout with default constraints. Add this panel to the frame's center, BorderLayout.CENTER by default.
Panel centerPane = new Panel(new GridBagLayout())`;
centerPane.add(yourJPanel);
frame.add(centerPane, BorderLayout.CENTER);
Also consider using Box, rather than a JPanel having BoxLayout.
Also consider using the frame's setJMenuBar(), rather than add(BorderLayout.PAGE_START).
Attached is my window code:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import java.awt.BorderLayout;
import javax.swing.JTextPane;
public class Window extends JFrame{
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init(){
panel = new JPanel();
getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(null);
textPane = new JTextPane();
textPane.setBounds(6, 48, 788, 185);
panel.add(textPane);
textPane.setFocusable(true);
textPane_1 = new JTextPane();
textPane_1.setBounds(6, 346, 788, 185);
panel.add(textPane_1);
JScrollPane scroll1 = new JScrollPane(textPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
JScrollPane scroll2 = new JScrollPane(textPane_1, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
}
}
My objective is for both JTextPanes to have their own scroll bars. All that appears on the screen though is a single JTextPane (not sure which one), and it has only a vertical scroll bar (I think this is because JTextPanes have word wrap). The second JTextPane isn't showing up. Can anyone help me?
Thanks in advance to all who reply.
You can use GridLayout in this case. See Swing Tutorial on How to Use GridLayout
Here is the code with GridLayout along with inline comments.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class MyWindow extends JFrame {
private JPanel panel;
private JTextPane textPane;
private JTextPane textPane_1;
public MyWindow() {
super("Window");
this.init();
}
void init() {
// panel with GridLayout having 2 rows and 1 column
panel = new JPanel(new GridLayout(2,1));
textPane = new JTextPane();
// enclose the text pane inside the scroll pane
// scroll pane shows scrollbars when needed
JScrollPane scroll1 = new JScrollPane(textPane);
// add scroll pane at first column of the first row
// never add text pane again in the panel because
// it's already added in scroll pane
panel.add(scroll1);
textPane_1 = new JTextPane();
JScrollPane scroll2 = new JScrollPane(textPane_1);
// add scroll pane at first column of the second row
panel.add(scroll2);
// finally add the panel in the JFrame's content pane in the center
getContentPane().add(panel, BorderLayout.CENTER);
}
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
MyWindow window=new MyWindow();
window.setVisible(true);
}
});
}
}
snapshot:
Please have a look at Swing Tutorial on How to Use Various Layout Managers
Two points to start with, first, JFrame uses a BorderLayout by default, a BorderLayout only allows a single component to occupy any one of its five available positions. Second a component can only belong to a single parent
Taking a look at your code...
scroll1.setViewportView(textPane);
panel.add(scroll1);
this.add(scroll1);
//...
scroll2.setViewportView(textPane);
panel.add(scroll2);
this.add(scroll2);
this.add(panel);
You set textPane as the viewport view for scroll1
You add scroll1 to panel
You add scroll to this, effectively removing it from panel...
You set textPane as the viewport view of scroll2, removing it from the viewport for scroll1
You add scroll2 to the panel
You add scroll2 to this, effectively removing it from panel...
You add panel to this, overriding everything that was added to the frame previously...
This effectively means that panel is the only visible component the BorderLayout will try to layout on the frame, but it contains nothing
Instead, you could specify a position for each scroll pane when adding it to the frame, for example..
scroll1.setViewportView(textPane);
this.add(scroll1, BorderLayout.NORTH);
//...
scroll2.setViewportView(textPane_1);
this.add(scroll2, BorderLayout.SOUTH);
Updated with working example
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Window extends JFrame {
private JTextPane textPane;
private JTextPane textPane_1;
public Window() {
super("Window");
this.init();
this.setSize(800, 600);
this.setVisible(true);
}
void init() {
textPane = new JTextPane();
textPane_1 = new JTextPane();
JScrollPane scroll1 = new JScrollPane(textPane);
scroll1.setViewportView(textPane);
JScrollPane scroll2 = new JScrollPane(textPane_1);
add(scroll1, BorderLayout.NORTH);
add(scroll2, BorderLayout.SOUTH);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Window frame = new Window();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
This is the default behaviour for a JTextPane, it's overall size is determine by the size of it's content...
Now, you can make suggestions to the scrollpane about how much space your component would like to use by using the Scrollable interface and specifying the "initial", PreferredScrollableViewportSize...
Lucky for you, JTextPane already implements this interface, so you only need to override the getPreferredScrollableViewportSize method, for example...
textPane = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
textPane_1 = new JTextPane() {
#Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
};
Take a look at Laying Out Components Within a Container for more details
Avoid using null layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
I'm making a GUI for a a custom source server browser with improved filtering.
This is what I have so far.
However, when I resize...
When I resize the window I want the L4D2 'filter panel' to resize to the current maximum width of the container. I also want to be able to add more of these panels in a column (such as box layout provides).
Boxlayout get's the panels to appear in a column, but it doesn't do anything for their widths.
I'm thinking I may need to override the filter panels preferred size methods so that they can retrieve the size of the parent container, but I'm not sure how to do this.
How should I approach this problem?
EDIT: Here's an example program depicting the problem.
import javax.swing.*;
import java.awt.*;
public class guiExampleProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final MyWindows wnd = new MyWindows("guiExampleProblem");
wnd.setVisible(true);
}
});
}
}
class MyWindows extends JFrame {
public MyWindows(String text) {
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
JPanel containerPanel1 = new JPanel();
JPanel containerPanel2 = new JPanel();
JPanel containerPanel3 = new JPanel();
containerPanel1.setBackground(Color.BLACK);
containerPanel2.setBackground(Color.RED);
containerPanel3.setBackground(Color.GREEN);
mainPanel.add(containerPanel1);
mainPanel.add(containerPanel2);
mainPanel.add(containerPanel3);
this.add(mainPanel);
pack();
}
}
When the window is resized, I want the panels to expand only along the x-axis, and remain at a constant height on the y-axis, however in the example the panels expand on both the x y axis.
I managed to get the desired functionality by overriding the 'filter panels' getPrefferedSize methods so that they retrieve the parent containers width and use that. Here is the code in the form of an example:
import javax.swing.*;
import java.awt.*;
public class guiExampleProblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final MyWindows wnd = new MyWindows("guiExampleProblem");
wnd.setVisible(true);
}
});
}
}
class MyWindows extends JFrame {
public MyWindows(String text) {
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new FlowLayout());
JPanel containerPanel1 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
JPanel containerPanel2 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
JPanel containerPanel3 = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(this.getParent().getWidth(),60);
}
};
containerPanel1.setBackground(Color.BLACK);
containerPanel2.setBackground(Color.RED);
containerPanel3.setBackground(Color.GREEN);
mainPanel.add(containerPanel1);
mainPanel.add(containerPanel2);
mainPanel.add(containerPanel3);
this.add(mainPanel);
pack();
}
}
Put the panel (with BoxLayout) that is to stretch in the CENTER of a BorderLayout -- put the panel to the right in the EAST of that BorderLayout. You have given no detail of what else you want this to do, nor any code, but this might be what you want.
--
After your solution: it seems to me that using FlowLayout here is confusing -- it lays out its components one after the other horizontally, and your trick of getting preferred size from the width of the container makes it behave differently. I also avoid getting into layout logic in my application when I can, so I looked for another way to do this and came up with:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class guiExampleProblem2
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
final MyWindows2 wnd = new MyWindows2("guiExampleProblem2");
wnd.setVisible(true);
}
});
}
}
class MyWindows2 extends JFrame
{
public MyWindows2(String text)
{
super(text);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
JPanel containerPanel1 = addContainedPanel(Color.BLACK, 60, 60, mainPanel);
JPanel containerPanel2 = addContainedPanel(Color.RED, 60, 60, mainPanel);
JPanel containerPanel3 = addContainedPanel(Color.GREEN, 60, 60, mainPanel);
this.add(mainPanel, BorderLayout.NORTH);
pack();
}
JPanel addContainedPanel(Color color, int width, int height, JPanel container)
{
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(width, height));
panel.setBackground(color);
container.add(panel);
return panel;
}
}
This uses the NORTH portion of a BorderLayout (which is the default layout for a JFrame, by the way) to do the main thing you wanted -- stretch things horizontally. The BoxLayout with a page axis is intended to lay things out top-to-bottom, so I think that's less confusing for the reader. Anyway, it's another way to do it that I think uses the components - including the layout managers - more like they were intended and documented.
I designed an interface for the welcome screen with one JFrame included two JPanels (JPanel1 on right and JPanel2 on left). The buttons on the left is to switch the Panels in JPanel1. I want to press on a button to replace JPanel1 content with another JPanel but I don`t know how. Please help.
Here is a very simple example of something that should approximate your description. On the left, we have a hug button to toggle the content of the right panel. On the right, you have a panel with a given border and a label. When you press the button, the content on the right is swapped with the other panel.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestCardLayout2 {
protected void initUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel leftPanel = new JPanel(new BorderLayout());
JLabel label = new JLabel("Left panel");
leftPanel.add(label, BorderLayout.NORTH);
JButton button = new JButton("Toggle right panel");
leftPanel.add(button);
frame.add(leftPanel, BorderLayout.WEST);
final CardLayout cardLayout = new CardLayout();
final JPanel rightPanel = new JPanel(cardLayout);
rightPanel.setPreferredSize(new Dimension(200, 500));
JPanel rightPanel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
rightPanel1.setBorder(BorderFactory.createLineBorder(Color.RED));
JPanel rightPanel2 = new JPanel(new FlowLayout(FlowLayout.RIGHT));
rightPanel2.setBorder(BorderFactory.createLineBorder(Color.BLUE));
JLabel label1 = new JLabel("Right panel 1 with a red border");
JLabel label2 = new JLabel("Right panel 2 with a blue borer");
rightPanel1.add(label1);
rightPanel2.add(label2);
rightPanel.add(rightPanel1, "panel1");
rightPanel.add(rightPanel2, "panel2");
frame.add(rightPanel, BorderLayout.EAST);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(rightPanel);
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestCardLayout2().initUI();
}
});
}
}
An alternative to CardLayout would be JRootPane and its JRootPane.setContentPane() method. Here's an example:
final JPanel panel1 = ...;
final JPanel panel2 = ...;
boolean showingPanel1 = true;
final JRootPane rootPane = new JRootPane();
rootPane.setContentPane(panel1);
JButton switchButton = new JButton("Switch");
switchButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (showingPanel1) {
rootPane.setContentPane(panel2);
} else {
rootPane.setContentPane(panel1);
}
showingPanel = !showingPanel;
}
});
Add the rootPane and switchButton components to your window, and then clicking switchButton will switch out the panels.
Here's a tutorial. You should mostly be concerned with JRootPane.setContentPane, the other stuff in the tutorial isn't relevant.
The best answer I found is that I will create one JFrame only and gonna make one big JPanel include two JPanels (JPanelLeft include the buttons and JPanelRight include what the button do) then I will copy the main JPanel for each JButton.
When I press on any button I will do (JFrame.getContentPane.removeAll) to remove the old JPanel then (JFrame.getContentPane.Add(NewJPanel).
This works for me and keep my design as I Want. Thanks for every body.