Calling swing JPanels from actionlistener

2019-06-13 00:21发布

问题:

im coding a project using various classes, but i got stuck when i press a button which call my main menu, here's my resumed code:

My main class:

public static void main(String[] args) {

    SwingUtilities.invokeLater(new Runnable() {
        Dimension res = Toolkit.getDefaultToolkit().getScreenSize();

public void run(){

    Principal frame = new Principal("Program");

    frame.setSize(res.width,res.height);

    frame.setResizable(false);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.setUndecorated(true);

    frame.setVisible(true); 
    }
});`

Now, my principal:

 public class Principal extends JFrame implements ActionListener {


     private DetallesPrincipal DetallesPrincipal;

     private ClientesNuevo ClientesNuevo;

     private ClientesModificar ClientesModificar;

     Container p;

     private static final long serialVersionUID = 1L;

     final JMenuItem Clientes1,Clientes2,Clientes3;

     final JMenuBar MenuBarMain = new JMenuBar();

 public Principal (String titulo){

      super(titulo); 

          setLayout(new BorderLayout());

      final JMenuBar MenuBarMain = new JMenuBar();

        MenuBarMain.setBackground(new Color(177,178,182));

      final JMenu MenuMainClientes;

        MenuMainClientes = new JMenu("Clientes");



            DetallesPrincipal = new DetallesPrincipal();
            ClientesNuevo = new ClientesNuevo();

                   p = getContentPane();

                MenuBarMain.add(MenuMainClientes);

                Clientes1 = new JMenuItem("Nueva ficha");

                    MenuMainClientes.add(Clientes1);

                            Clientes1.addActionListener(this);

                p.add(MenuBarMain, BorderLayout.PAGE_START);

                p.add(DetallesPrincipal, BorderLayout.CENTER);

    }


     @Override
     public void actionPerformed(ActionEvent e) {

        if (e.getSource()==Clientes1){

            p.removeAll();

            p.repaint();

            p.add(ClientesNuevo, BorderLayout.CENTER);

            p.revalidate();

            p.repaint();
        }

My ClientesNuevo:

public class ClientesNuevo extends JPanel implements ActionListener {

    private static final long serialVersionUID = 1L;

    DetallesPrincipal m;

    GridBagConstraints gc = new GridBagConstraints();

public ClientesNuevo() {


    Dimension size = getPreferredSize();
        size.width = 250;

        setPreferredSize(size);

        setBackground(new Color(111,114,123));

        TitledBorder Principal2 = BorderFactory.createTitledBorder("Te encuentras en clientes");

        Principal2.setTitleColor(new Color(100,100,100));

        Principal2.setTitleFont(new Font("Arial",0,24));

        Principal2.setTitlePosition(TitledBorder.BOTTOM);

        Principal2.setTitleJustification(TitledBorder.LEFT);

        setBorder(Principal2);


    JLabel Titulo1 = new JLabel("Nueva ficha cliente");

        Titulo1.setFont(new Font("Tahoma",0,36));

    JLabel Nombre = new JLabel("Nombre/Razón social ");

    JLabel Apellidos = new JLabel("Apellidos ");

    JLabel Cif = new JLabel("CIF/DNI ");

    JLabel Poblacion = new JLabel("Población ");

    JLabel Provincia = new JLabel("Provincia");

    JLabel Cpostal = new JLabel("Código postal");

    JLabel Telefono = new JLabel("Teléfono");

    JLabel Movil = new JLabel("Móvil");

    JLabel Notas = new JLabel("Notas");


    JTextField NombreText = new JTextField(25);

    JTextField ApellidosText = new JTextField(25);

    JTextField CifText = new JTextField(15);

    JTextField PoblacionText = new JTextField(15);

    JTextField ProvinciaText = new JTextField(20);

    JTextField CpostalText = new JTextField(15);

    JTextField TelefonoText = new JTextField(20);

    JTextField MovilText = new JTextField(20);

    JTextField NotasText = new JTextField(30);


    JButton Aceptar = new JButton("Aceptar");

    JButton Cancelar = new JButton("Cancelar");

        Aceptar.addActionListener(this);


    setLayout(new GridBagLayout());

        GridBagConstraints gc = new GridBagConstraints();


            gc.gridx = 0;

            gc.gridy = 0;

            gc.weighty = 1;

            add(Titulo1, gc);


            gc.anchor = GridBagConstraints.LINE_START;

            gc.gridx = 0;

            gc.gridy = 1;

            add(Nombre, gc);


            gc.gridx = 1;

            gc.gridy = 1;

            add(NombreText, gc);


            gc.gridx = 0;

            gc.gridy = 2;

            add(Apellidos, gc);

            gc.anchor = GridBagConstraints.LINE_START;

            gc.gridx = 1;

            gc.gridy = 2;

            add(ApellidosText, gc);


            gc.anchor = GridBagConstraints.LINE_START;

            gc.weightx = 1;

            gc.weighty = 1;

            gc.gridx = 0;

            gc.gridy = 3;

            add(Cif, gc);


            gc.anchor = GridBagConstraints.LINE_START;

            gc.gridx = 1;

            gc.gridy = 3;

            add(CifText, gc);

            gc.gridx = 0;

            gc.gridy = 4;

            add(Poblacion, gc);


            gc.gridx = 1;

            gc.gridy = 4;

            add(PoblacionText, gc);

            gc.gridx = 2;

            gc.gridy = 4;

            add(Provincia, gc);


           gc.gridx = 2;

           gc.gridy = 7;

            add(Aceptar, gc);


           gc.gridx = 3;

           gc.gridy = 7;

            add(Cancelar, gc);
}



 public void actionPerformed(ActionEvent e) {

               removeAll();

               repaint();

                m = new DetallesPrincipal();

            add(m,gc);

            revalidate();

            repaint();

    }


    }

Well, sorry for that walltext, but i am pretty lost, i just want call to my components of my DetallesPrincipal class, what's the better option to manage a program like this?

回答1:

Well besides the fact that you dont post your full source or an SSCCE I cannot fully test.

Looking at your code you are using the removeAll() method to switch between multiple JPanels on a single JFrame/container.

The mistake I see you are making though is in the logic, as you attempt to switch between JPanels within another JPanel rather than within your actual JFrame.

See this small example I created (allows a user to alternate between 2 JPanels on a single JFrame/container which implements a Singleton design pattern, can easily be changed for passing instance of MainGUI class to each JPanel the MainGUI spawns so that the JPanels will have access to the single MainGUIs swapPanel(JPanel p) method):

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class Test {

    public static void main(String[] args) {
        MainGUI mainGUI = MainGUI.getInstance();
    }
}
class MainGUI {

    private JFrame frame;

    private static class SingletonHolder {

        public static final MainGUI INSTANCE = new MainGUI();
    }

    public static MainGUI getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private MainGUI() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                frame = createJFrame();
                frame.setVisible(true);
            }
        });
    }

    private JFrame createJFrame() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Test");

        frame.add(new Panel1());//initial Jpanel to display

        frame.pack();
        return frame;
    }

    public void swapPanel(JPanel p) {
        frame.getContentPane().removeAll();
        frame.add(p);
        frame.pack();
        frame.revalidate();
        frame.repaint();
    }
}

class Panel1 extends JPanel {

    public Panel1() {
        JLabel labelPanel1 = new JLabel("Panel 1");
        JButton switchPanelButton = new JButton("Goto Panel 2");
        switchPanelButton.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MainGUI.getInstance().swapPanel(new Panel2());
            }
        });
        add(labelPanel1);
        add(switchPanelButton);
    }
}

class Panel2 extends JPanel {

    public Panel2() {
        JLabel labelPanel1 = new JLabel("Panel 2");
        JButton switchPanelButton = new JButton("Goto Panel 1");
        switchPanelButton.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MainGUI.getInstance().swapPanel(new Panel1());
            }
        });
        add(labelPanel1);
        add(switchPanelButton);
    }
}

An higher-level alternative to the above is a CardLayout The CardLayout class manages two or more components (usually JPanel instances) that share the same display space.:

import java.awt.BorderLayout;
import java.awt.CardLayout;
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.SwingUtilities;

public class Test {

    private final static String PANEL1 = "panel 1";
    private final static String PANEL2 = "panel 2";

    public Test() {
        initComponents();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Test();
            }
        });
    }

    private void initComponents() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel1 = new JPanel();
        panel1.add(new JLabel("Panel 1"));

        JPanel panel2 = new JPanel();
        panel2.add(new JLabel("Panel 2"));

        //Create the panel that contains the "cards".
        final JPanel cards = new JPanel(new CardLayout());
        cards.add(panel1, PANEL1);
        cards.add(panel2, PANEL2);

        //create button to allow chnage to next card
        JButton buttonNext = new JButton(">");
        buttonNext.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                cl.next(cards);
            }
        });

        //create button to allow chnage to previous card
        JButton buttonPrev = new JButton("<");
        buttonPrev.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                CardLayout cl = (CardLayout) (cards.getLayout());//get cards
                cl.previous(cards);
            }
        });

        //create panel to hold buttons which will allow switching between cards
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(buttonPrev);
        buttonPanel.add(buttonNext);


        frame.add(cards);
        frame.add(buttonPanel, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
    }
}