1

I'm working on my first Java UI and I'm using CardLayout to switch between multiple panels.

I have a few buttons, such as the quit button, that stay the same throughout all of the cards. As such I want that button and it's action handler to be copied to each card panel, but I can't figure out how to do that. It just seems to be on the last panel I added it to, which means I have to repeat the code for that one button numerous times, and that feels wrong.

Does anyone know of a way to reuse JPanel or JButton components on multiple panels/cards?

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Billy C
  • 35
  • 6
  • 2
    *" As such I want that button and it's action handler to be copied to each card panel,"* A better strategy would be to move those common components *outside* (above, below, to the left or right of) the `CardLayout`, One way to do that is to put the panel with card layout into the `CENTER` of another panel with `BorderLayout`, then place the common components in a panel and add it to the `PAGE_START` or `PAGE_END` of the border layout. – Andrew Thompson Aug 09 '15 at 14:01
  • 1
    Please do have a look at the last example of trying to [__add ActionListener to JButton__](http://stackoverflow.com/a/25627775/1057230). Here the use of [Action](https://docs.oracle.com/javase/tutorial/uiswing/misc/action.html), instead of `ActionListener`, which basically helps in reusability of the code. – nIcE cOw Aug 09 '15 at 16:01

1 Answers1

2

Here I've written a sample code for your situation. I hope you'll find it useful as a starting point ;) Combobox changes the functionality panels in pnlCard. The bottom most button is common for all functionality panels.

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * Main class for starting the application.
 */
public class MainProgram {
    public static void main(String[] args) {
        new TopFrame();
    }
}

/**
 * The main, top-most frame in demo app including combobox panel, card panel, and a common action button.
 */
class TopFrame extends JFrame implements ItemListener {

    CardPanel pnlCard = new CardPanel();
    JButton btnWithCommonAction = new JButton("Common action");

    public TopFrame() {
        JPanel comboBoxPane = new JPanel();
        String comboBoxItems[] = {"A", "B"};
        JComboBox cb = new JComboBox(comboBoxItems);
        cb.setEditable(false);
        cb.addItemListener(this);
        comboBoxPane.add(cb);
        //
        // !
        getContentPane().add(comboBoxPane, BorderLayout.PAGE_START);
        getContentPane().add(pnlCard, BorderLayout.CENTER);
        getContentPane().add(btnWithCommonAction, BorderLayout.PAGE_END);
        //
        pack();
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public void itemStateChanged(ItemEvent evt) {
        CardLayout cl = (CardLayout) (pnlCard.getLayout());
        cl.show(pnlCard, (String) evt.getItem());
    }
}

class CardPanel extends JPanel {
    JPanel cardA = new PanelWithSomeFunc("Functionality A");
    JPanel cardB = new PanelWithSomeFunc("Functionality B");
    public CardPanel() {
        setLayout(new CardLayout());
        add(cardA, "A");
        add(cardB, "B");
    }
}

/**
 * Simulates a panel with some functionality.
 * For demo purposes it contains a label and a sample button only.
 */
class PanelWithSomeFunc extends JPanel {

    private JLabel lblTitle;
    private JButton btnAction;

    public PanelWithSomeFunc(String functionalityName) {
        lblTitle = new JLabel(functionalityName);
        btnAction = new JButton(functionalityName);
        organizeLayout();
        final String textToDisplay = functionalityName;
        btnAction.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        JOptionPane.showMessageDialog(new JFrame(), textToDisplay);
                    }
                }
        );
    }

    private void organizeLayout() {
        setLayout(new BorderLayout());
        add(lblTitle, BorderLayout.CENTER);
        add(btnAction, BorderLayout.PAGE_END);
    }
}

class CommonAction extends AbstractAction {
    @Override
    public void actionPerformed(ActionEvent e) {
        JOptionPane.showMessageDialog(new JFrame(), "This action is available regardless of which panel is displayed");
    }
}
radekEm
  • 4,617
  • 6
  • 32
  • 45