Whenever I press "clear" in my Java GUI, it never works, please help me finish this. If i replace "textPanel" with another button, it works, otherwise with "textpanel" it doesn't.
Here is a lightweight version of my code demonstrating the problem:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainFrame extends JFrame {
private TextPanel textPanel;
private FormPanel formpanel;
public MainFrame(){
super("My Frame");
createLayout();
createFrame();
}
public void createFrame(){
setSize(600, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public void createLayout(){
BorderLayout myLayout = new BorderLayout();
setLayout(myLayout);
textPanel = new TextPanel();
formpanel = new FormPanel();
// adding components
add(textPanel, BorderLayout.CENTER);
add(formpanel, BorderLayout.WEST);
}
public static void main(String[] args){
new MainFrame();
}
public static class FormPanel extends JPanel {
private JButton clear;
private TextPanel textPanel;
public FormPanel(){
clear = new JButton("Clear Cart!");
textPanel=new TextPanel();
add(clear);
clear.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent aev){
System.out.println("Test");
textPanel.setText("");
}
});
createGrid();
}
/* this methods simply creates the layout */
void createGrid(){
//creating layout
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
gc.gridy++;
gc.weightx = .1;
gc.weighty = .1;
gc.gridx = 2;
gc.gridy=5;
gc.anchor = GridBagConstraints.LINE_START;
gc.insets = new Insets(0,0,0,0);
add(clear, gc);
}
}
public static class TextPanel extends JPanel {
private JTextArea textArea;
TextPanel (){
textArea = new JTextArea();
setLayout(new BorderLayout());
JScrollPane p = new JScrollPane(textArea);
add(p, BorderLayout.CENTER);
}
public void appendSomeText(String t){
textArea.append(t);
}
public void setText(String s){
textArea.setText(s);
}
}
}
You have two instances of TextPanel, one in MainFrame and the other one in FormPanel. TextPanel that is defined in FormPanel is actually not added to the panel, so textPanel.setText(""); has no effect on it as it is not visible.
When the text appended with Add To Cart! button it actually goes through a method in MainFrame - formEventOccurred() that executes textPanel.appendSomeText(). This is the other instance of TextPanel that is part of MainFrame and that is actually visible.
Looks like you need to move the duplicated logic from the main frame to the panels. Usually you should not extend JFrame as you are not adding any new functionality.
Related
So I want to have a CardLayout class that switches between a menu page and a main app page, but I want to design those two panels in their own classes, then add an ActionListener and a CardLayout in a different class, and have the ActionListener use a button created in one of the panel classes.
Here is a (Not so short) SSCCE that kind of covers what I'm trying to say:
import java.awt.*;
import javax.swing.*;
public class MenuPanel extends Frame{
JPanel menuPanel;
JButton login;
JButton signup;
public MenuPanel(){
menuPanel = new JPanel(new GridBagLayout());
login = new JButton("Login");
signup = new JButton("Signup");
menuPanel.add(login);
menuPanel.add(signup);
}
}
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JFrame{
JPanel menuPanel;
JButton login;
JButton signup;
public MainPanel(){
mainPanel = new JPanel(new GridBagLayout());=
menuPanel.setBackground(Color.grey);
}
}
import java.awt.*;
import javax.swing.*;
public class CardLayout extends Frame implements ActionL {
//Now how do I add the frames from the other classes so that I can add them to my CardLayout?
CardLayout cl = new CardLayout();
JPanel panelCont;
public CardLayout() {
frame.add(panelCont);
panelCont = new JPanel(cl);
//Here is where I'm having trouble
panelCont.add(menuPanel, "1");
panelCont.add(mainPanel, "2");
cl.show(panelCont, "1");
login.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
cl.show(panelCont, "2");
}
});
}
}
public class Main {
public static void main(String[] args) {
new CardLayout();
}
}
You cannot add Frames to another component. Frame is a top level component with a native peer. You should subclass from something else (JPanel?) instead
Also, btw what you are doing is not good design. Generally, in MVC Swing design, all view and control aspects should be in one class. Don't split the view into multiple classes unless each of those classes stands up as its own reusable widget
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Concurrency in Swing and the Laying Out Components Within a Container sections.
In Java Swing, you create one JFrame and as many JPanels as you need to create the GUI.
I created a card JPanel, a menu JPanel, and a login JPanel in three separate classes. The card JPanel class creates the JPanel with the CardLayout. The menu JPanel creates the JPanel that contains the menu JButtons. The login JPanel class creates the JPanel that contains the login Swing components.
Here's the JFrame with the menu JPanel.
Here's the GUI after you left-click on the Login JButton.
Notice how I named the classes. CardPanel, MenuPanel, LoginPanel. By appending Panel to the end of the class name, that tells me they use a JPanel.
When I create a separate ActionListener class, I'd name it ButtonListener or SignupListener.
The only ActionListener I created ties the menu login JButton to displaying the login JPanel. Since it consists of one line, I made it an anonymous class using a lambda expression.
Here's the complete runnable code. I made all the additional classes inner classes so I could post this code as one block. You can and should put these classes in separate files.
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class CardLayoutExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new CardLayoutExample());
}
#Override
public void run() {
JFrame frame = new JFrame("CardLayout Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CardPanel().getPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class CardPanel {
private final CardLayout cardLayout;
private final JPanel panel;
public CardPanel() {
this.cardLayout = new CardLayout();
this.panel = createCardPanel();
}
private JPanel createCardPanel() {
JPanel panel = new JPanel(cardLayout);
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.add(new MenuPanel(this).getPanel(), "menu");
panel.add(new LoginPanel().getPanel(), "login");
return panel;
}
public void showLoginPanel() {
cardLayout.show(panel, "login");
}
public JPanel getPanel() {
return panel;
}
}
public class MenuPanel {
private final CardPanel cardPanel;
private final JPanel panel;
public MenuPanel(CardPanel cardPanel) {
this.cardPanel = cardPanel;
this.panel = createMenuPanel();
}
private JPanel createMenuPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton login = new JButton("Login");
login.addActionListener(event -> cardPanel.showLoginPanel());
panel.add(login);
JButton signup = new JButton("Signup");
panel.add(signup);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
public class LoginPanel {
private final JPanel panel;
private final JPasswordField passwordField;
private final JTextField useridField;
public LoginPanel() {
this.useridField = new JTextField(30);
this.passwordField = new JPasswordField(30);
this.panel = createLoginPanel();
}
private JPanel createLoginPanel() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
JLabel label = new JLabel("Userid:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(useridField, gbc);
gbc.gridx = 0;
gbc.gridy++;
label = new JLabel("Password:");
panel.add(label, gbc);
gbc.gridx++;
panel.add(passwordField, gbc);
gbc.anchor = GridBagConstraints.CENTER;
gbc.gridwidth = 2;
gbc.gridx = 0;
gbc.gridy++;
JButton button = new JButton("Submit");
panel.add(button, gbc);
return panel;
}
public String getUserid() {
return useridField.getText();
}
public char[] getPassword() {
return passwordField.getPassword();
}
public JPanel getPanel() {
return panel;
}
}
}
Please help me to understand how this works. I'm having difficulties to understand how, for example, JButton in one class can alter text in JTextArea that is in another class of a same package. I've made a simple app just to ask a question here, I need this for a bigger school project where I need to implement this to work with multiple classes.
When I put everything in the same class it works but I need it in separate classes.
Here is the simple code.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Button extends JPanel {
private JButton button;
private Panel panel;
public Button() {
button = new JButton("BUTTON");
panel = new Panel();
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
String input = clicked.getText();
panel.setTextArea(input);
//System.out.println(input);
}
});
}
}
class Panel extends JPanel {
private JTextArea textArea;
public Panel() {
setLayout(new BorderLayout());
textArea = new JTextArea();
add(textArea, BorderLayout.CENTER);
}
public JTextArea getTextArea() {
return textArea;
}
void setTextArea(String text) {
this.textArea.setText(text);
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java() {
frame = new JFrame();
dugme = new Button();
panel = new Panel();
//super("test");
frame.setLayout(new BorderLayout());
frame.setTitle("test");
frame.setSize(300, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(dugme, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
Java app = new Java();
}
}
I want action listener to alter the text in the panel, sys-out works so the listener listens the button but I can't make it to alter the text in text area.
As already mentioned by #XtremeBaumer you have two different instances of Panel class. You need to remove the secode one.
public class Button extends JPanel {
private JButton button;
private Panel panel;
public Button(Panel panel) { // we need already created instance of panel here.
this.panel = panel;
button = new JButton("BUTTON");
// panel = new Panel(); <-- this line must be deleted.
// ...
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java(){
frame = new JFrame();
panel = new Panel();
dugme = new Button(panel);
// ...
}
}
Please also replace the line
add(textArea, BorderLayout.CENTER);
by
add(new JScrollPane(textArea), BorderLayout.CENTER);
This allows you to get the scrool bars when text goes larger than the text ara size.
Here is your reworked example
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class Button extends JPanel {
private JButton button;
private Panel panel;
public Button(Panel panel) {
this.panel = panel;
button = new JButton("BUTTON");
add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JButton clicked = (JButton) e.getSource();
String input = clicked.getText();
panel.setTextArea(input);
//System.out.println(input);
}
});
}
}
class Panel extends JPanel {
private JTextArea textArea;
public Panel() {
setLayout(new BorderLayout());
textArea = new JTextArea();
add(new JScrollPane(textArea), BorderLayout.CENTER);
}
public JTextArea getTextArea() {
return textArea;
}
void setTextArea(String text) {
this.textArea.setText(text);
}
}
public class Java extends JFrame {
private Button dugme;
private JFrame frame;
private Panel panel;
public Java() {
frame = new JFrame();
panel = new Panel();
dugme = new Button(panel);
//super("test");
frame.setLayout(new BorderLayout());
frame.setTitle("test");
frame.setSize(300, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(dugme, BorderLayout.NORTH);
frame.add(panel, BorderLayout.CENTER);
}
public static void main(String[] args) {
Java app = new Java();
}
}
Exception in thread "main" java.lang.NullPointerException
at java.awt.Container.addImpl(Unknown Source)
at java.awt.Container.add(Unknown Source)
at Volume.<init>(Volume.java:25)
at VolumeDriver.main(VolumeDriver.java:6)
I get the above errors when trying to run my program. My program is not complete but I just want to check what my window looks like so I can make sure it looks correct.
This is my worker class for right now
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Volume extends JFrame
{
private static final long serialVersionUID = 1L;
private JPanel topPanel;
private JPanel bottomPanel;
private JPanel rightPanel;
private JPanel mainPanel;
private JLabel message;
private final int width = 500;
private final int height = 400;
public Volume()
{
setTitle("Sphere and Box Volumes");
setSize(width,height);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(topPanel, BorderLayout.NORTH);
BuildTopPanel();
getContentPane().add(bottomPanel, BorderLayout.SOUTH);
BuildBotPanel();
getContentPane().add(rightPanel, BorderLayout.EAST);
BuildRightPanel();
getContentPane().add(mainPanel, BorderLayout.WEST);
BuildMainPanel();
setVisible(true);
}
private void BuildTopPanel()
{
topPanel = new JPanel(new FlowLayout());
topPanel.setBackground(Color.WHITE);
JTextField reqVolume = new JTextField(8);
message = new JLabel("Enter the required amount of volume:");
topPanel.add(message);
topPanel.add(reqVolume);
}
private void BuildBotPanel()
{
bottomPanel = new JPanel(new FlowLayout());
bottomPanel.setBackground(Color.WHITE);
JButton intialQuant = new JButton("Set Initial Quantities");
intialQuant.setActionCommand("I");
intialQuant.addActionListener(new ButtonListener());
JButton calcVolume = new JButton("Calculate Volumes");
calcVolume.setActionCommand("V");
calcVolume.addActionListener(new ButtonListener());
JButton close = new JButton("Close");
close.setActionCommand("C");
close.addActionListener(new ButtonListener());
bottomPanel.add(intialQuant);
bottomPanel.add(calcVolume);
bottomPanel.add(close);
}
private void BuildRightPanel()
{
rightPanel = new JPanel(new FlowLayout());
rightPanel.setBackground(Color.WHITE);
}
private void BuildMainPanel()
{
mainPanel = new JPanel(new FlowLayout());
mainPanel.setBackground(Color.WHITE);
}
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
}
}
}
This is my driver class
public class VolumeDriver
{
public static void main(String[] args)
{
Volume frame = new Volume();
frame.setVisible(true);
}
}
Any help would be appreciated.
getContentPane().add(topPanel, BorderLayout.NORTH); // Uh oh! topPanel is not initialized!
BuildTopPanel();
You try to add your topPanel before its initialization in the BuildTopPanel() method, so it will obviously lead to a NPE!
This is also the case for your other build methods. Be sure to actually initialize and build your GUI elements before using them or adding them to your window!
For instance:
// Initialize GUI elements first:
BuildTopPanel();
BuildBotPanel();
BuildRightPanel();
BuildMainPanel();
// Then add the GUI elements to the window:
getContentPane().add(topPanel, BorderLayout.NORTH);
getContentPane().add(bottomPanel, BorderLayout.SOUTH);
getContentPane().add(rightPanel, BorderLayout.EAST);
getContentPane().add(mainPanel, BorderLayout.WEST);
initialize the component before you add it to panel. see the documents as below:
http://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#add%28java.awt.Component%29
That means you need call BuildMainPanel() before getContentPane().add(mainPanel, BorderLayout.WEST);
The same with the other components.
How to set Jbuttons to a specific place when you have a background in JLabel : code below
i can't get the jlabel to stay at the top and the buttons to stay south(bottom) ??
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonsClass extends JFrame
implements ActionListener {
JButton b1 = new JButton("button1");
JButton b2 = new JButton("button2");
JButton b3 = new JButton("button3");
JButton b4 = new JButton("button4");
JLabel label = new JLabel("buttons:");
public static void main(String[] args) {
new ButtonsClass();
}
public Jukebox() {
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("image.png")));
setLayout(new FlowLayout());
setSize(500,150);
setTitle("Backgroundwithbuttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.add(label);
add("North", top);
JPanel bottom = new JPanel();
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add("South", bottom);
setVisible(true);
}
}
" i can't get the jlabel to stay at the top and the buttons to stay south(bottom)"
That's because you set the layout the BorderLayout, then immediately set it to FlowLayout. With FlowLayout, your BorderLayout positioning will do nothing.
setLayout(new BorderLayout());
setContentPane(new JLabel(new ImageIcon("image.png")));
setLayout(new FlowLayout());
Just get rid of the setLayout(new FlowLayout());
Also your constructor is wrong
public Jukebox() {
-Should be-
public ButtonClass() {
Also you need to set the layout of the JLabel that you set as the content pane. Yout constructor should look like this
public ButtonClass() {
JLabel background = new JLabel(new ImageIcon("image.png"));
background.setLayout(new BorderLayout());
setContentPane(background);
setTitle("Background with buttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.add(label);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add(bottom, BorderLayout.SOUTH);
//pack();
setVisible(true);
}
Also, add("North", top); is a deprecated method. Instead use add(top, BorderLayout.NORTH) and same for add(bottom, BorderLayout.SOUTH)
Also, Swing apps should be run on the Event Dispatch Thread. You can do so by wrapping the code in your main with a SwingUtilities.invokeLater...
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonClass();
}
});
}
Also, you should set the panel's opaque property to false, if you want the image to show behind them.
top.setOpaque(false);
bottom.setOpaque(false);
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonClass extends JFrame
implements ActionListener {
JButton b1 = new JButton("button1");
JButton b2 = new JButton("button2");
JButton b3 = new JButton("button3");
JButton b4 = new JButton("button4");
JLabel label = new JLabel("buttons:");
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ButtonClass();
}
});
}
public ButtonClass() {
label.setForeground(Color.WHITE);
JLabel background = new JLabel(new ImageIcon(getClass().getResource("/resources/space.png")));
background.setLayout(new BorderLayout());
setContentPane(background);
setTitle("Background with buttons");
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
JPanel top = new JPanel();
top.setOpaque(false);
top.add(label);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.setOpaque(false);
bottom.add(b1);
bottom.add(b2);
bottom.add(b3);
bottom.add(b4);
add(bottom, BorderLayout.SOUTH);
setSize(400, 300);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {}
}
Try using:
add(bottom, BorderLayout.SOUTH);
instead of:
add("South", bottom);
BorderLayout tutorial
I made a small program with two buttons. I label
the buttons one exiting the program and the second importing files.
I actually let them both to exit the program when ever someone pressed on it
the problem is the buttons taking all the window, why?
I tried GridBagConstraints to resize the buttons some how but no luck anyway here's the full class without imports..
public class Window2 extends JFrame{
private static final long serialVersionUID = 1L;
public Window2(){
super ("ALANAZ imagtor");
setSize(600,400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel pnl1 = new JPanel(new GridLayout());
JPanel pnl2 = new JPanel();
//button
JButton butn1 = new JButton("EXIT");
JButton butn2 =new JButton("IMPORT");
butn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JOptionPane.showMessageDialog(null, "exiting ... bye...");
System.exit(0);
}
});
butn2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
JOptionPane.showMessageDialog(null, "can't import now exiting");
System.exit(0);
}
});
GridBagConstraints gb1 = new GridBagConstraints();
gb1.insets = new Insets(15,15,15,15);
//Jlabel
JLabel lbl1 = new JLabel("exit or import an image");
pnl1.add(butn1);
pnl1.add(butn2);
pnl2.add(lbl1);
add(pnl2, BorderLayout.SOUTH);
add(pnl1, BorderLayout.CENTER);
}}
You are misusing your layout managers. Your pnl1 JPanel uses GridLayout (without any row or column constants?!), and if you only add one component to it, it will take up the entire JPanel. You seem to have GridBagConstraints in your code, but no GridBagLayout, which is confusing to me.
The solution is to read up on and understand how to use layout managers. Please have a look at the tutorial link: Laying Out Components Within a Container.
Key is to keep remembering that you can nest JPanels within JPanels. For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class Window2 extends JFrame {
private static final long serialVersionUID = 1L;
private static final int PREF_W = 600;
private static final int PREF_H = 400;
public Window2() {
super("ALANAZ imagtor");
setDefaultCloseOperation(EXIT_ON_CLOSE);
int gap = 3;
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, gap, 0));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(gap, gap, gap, gap));
JPanel pnl2 = new JPanel();
JButton butn1 = new JButton("EXIT");
JButton butn2 = new JButton("IMPORT");
butn1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, "exiting ... bye...");
System.exit(0);
}
});
butn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JOptionPane.showMessageDialog(null, "can't import now exiting");
System.exit(0);
}
});
JLabel lbl1 = new JLabel("exit or import an image");
buttonPanel.add(butn1);
buttonPanel.add(butn2);
JPanel centerPanel = new JPanel(new BorderLayout());
centerPanel.add(buttonPanel, BorderLayout.SOUTH);
pnl2.add(lbl1);
add(pnl2, BorderLayout.SOUTH);
add(centerPanel, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] args) {
Window2 win2 = new Window2();
win2.pack();
win2.setLocationRelativeTo(null);
win2.setVisible(true);
}
}
If you initialize your panel with a BorderLayout instead, and add your buttons using EAST, NORTH, WEST, SOUTH, you will have a quick fix - however I do also recommend reading up on layout managers
JPanel pnl1 = new JPanel(new BorderLayout());
pnl1.add(new JButton(), BorderLayout.SOUTH);