TravisinSeattle
TravisinSeattle

Reputation: 23

Use a JButton to add new panels at runtime

I feel as beginner I may have bitten off too much in regards to application building. That said, I am working on developing an application for a friend that will have prompts where each JPanel will provide fields to create an object to be used later. What I would like to have happen is that when the panel loads, it displays one object creation panel and a button to dynamically add a new panel if the user wants to make multiples (the plus button would add the new panel).

I have drawn up something in paint to illustrate this:

By my very limited understanding, I can create a panel to hold these sub-panels, and then add a action listener to the '+' button to create new panels. The only way I could think to implement this is to create a constructor for the panel I want to add. Is this possible? Let me show you what I have:

package com.company;

import java.awt.*;
import javax.swing.*;

/**
 * Created by Travis on 3/1/2015.
 */
public class MainSnakeGui extends JFrame{

    protected int panelCount;


    //row 1
    JPanel row1 = new JPanel();
    JLabel splitSnakeLabel = new JLabel("Create a Split Snake", JLabel.CENTER);

    //row 2
    JPanel row2 = new JPanel();
    JButton addButton = new JButton("+");



    public MainSnakeGui() {
        super("Snake Channels");

        setSize(550, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridLayout layout = new GridLayout(5, 1, 10, 10);
        setLayout(layout);

        FlowLayout layout1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
        row1.setLayout(layout1);
        row1.add(splitSnakeLabel);
        add(row1);

        GridLayout layout2 = new GridLayout(1, 2, 10, 10);
        row2.setLayout(layout2);
        row2.add(addButton);
        MainSnakeConstructor snakePanel = new MainSnakeConstructor();
        row2.add(snakePanel);
        add(row2);

        setVisible(true);
    }

    public static void setLookAndFeel () {
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
        }
    }

    public static void main(String[] arg) {
        MainSnakeGui.setLookAndFeel();
        MainSnakeGui frame = new MainSnakeGui();
    }
}

Here is the constructor:

package com.company;

import javax.swing.*;
import java.awt.*;

/**
 * Created by Travis on 3/1/2015.
 */
public class MainSnakeConstructor extends JFrame {

    public  MainSnakeConstructor () {
        JPanel splitSnakeRow = new JPanel();
        JLabel snakeNameLabel = new JLabel("Snake Name");
        JLabel channelCountLabel = new JLabel("Channel Count");
        JCheckBox artistSuppliedCheckBox = new JCheckBox("Artist Supplied?");
        JTextField snakeNameTextField = new JTextField(30);
        JTextField channelCountTextField =  new JTextField(3);

        GridLayout layout = new GridLayout(3,2,10,10);
        splitSnakeRow.setLayout(layout);
        splitSnakeRow.add(snakeNameLabel);
        splitSnakeRow.add(channelCountLabel);
        splitSnakeRow.add(artistSuppliedCheckBox);
        splitSnakeRow.add(snakeNameTextField);
        splitSnakeRow.add(channelCountTextField);
        add(splitSnakeRow);
    }
}

Upvotes: 0

Views: 1087

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347314

Think about it differently. You want a button that allows you to add new panels, so you really only need a single button.

From there, you need some kind common panel which provides the functionality you want to the user (the creation panel). Then, when the user clicks the add button, you create a new creation panel and add it to the container been used to display them, for example...

MakeItSo

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton btnAdd = new JButton("+");
            setLayout(new BorderLayout());
            JPanel buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
            buttons.add(btnAdd);
            add(buttons, BorderLayout.NORTH);

            JPanel content = new JPanel(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weighty = 1;
            content.add(new JPanel(), gbc);

            add(new JScrollPane(content));

            btnAdd.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    CreationPane pane = new CreationPane();
                    int insertAt = Math.max(0, content.getComponentCount() - 1);
                    GridBagConstraints gbc = new GridBagConstraints();
                    gbc.gridwidth = GridBagConstraints.REMAINDER;
                    gbc.fill = GridBagConstraints.HORIZONTAL;
                    gbc.weightx = 1;
                    content.add(pane, gbc, insertAt);
                    content.revalidate();
                    content.repaint();
                }
            });

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

    public static class CreationPane extends JPanel {

        private static int count;

        public CreationPane() {

            setLayout(new GridBagLayout());
            add(new JLabel("Make it so " + (count++)));
            setBorder(new CompoundBorder(new LineBorder(Color.BLACK), new EmptyBorder(10, 10, 10, 10)));

        }

    }

}

Now having done all that, I prefer the VerticalLayout manager from SwingLabs, SwingX library, which basically does the same thing...

Upvotes: 2

Related Questions