0

I've got a Frame (named here "MainApplication"), which mainly has a JPanel to show informations, depending on the context.

On startup, the MainApplication has an empty JPanel.

It then creates a "LoginRequest" class, which creates a simple login/password form, and send it back to the MainApplication, which displays it in its JPanel.

The "LoginRequest" class implements ActionListener, so when the user clicks on the "Login" button, it checks wheter or not the login/password is correct, and, if the user is granted, I want to unload that form, and display the main screen on the MainApplication Frame.

So, to do it, I came up with this :

public class LoginRequest implements ActionListener {

    protected MainApplication owner_m = null;

    public LoginRequest(MainApplication owner_p) {
            owner_m = owner_p;
    }

    @Override
    public void actionPerformed(ActionEvent event_p) {

        // the user just clicked the "Login" button
        if (event_p.getActionCommand().equals("RequestLogin")) {

            // check if login/password are correct
            if (getParameters().isUserGranted(login_l, password_l)) {

                // send an ActionEvent to the "MainApplication", so as it will
                // be notified to display the next screen
                this.owner_m.actionPerformed(
                    new java.awt.event.ActionEvent(this, 0, "ShowSummary")
                );
            } else {
                messageLabel_m.setForeground(Color.RED);
                messageLabel_m.setText("Incorrect user or password");
            }
        }
    }
}

Then, the "MainApplication" class (which extends JFrame) :

public class MainApplication extends JFrame implements ActionListener {

    protected void load() {
            // create the panel to display information
            mainPanel_m = new JPanel();
            // on startup, populate the panel with a login/password form
            mainPanel_m.add(new LoginRequest(this).getLoginForm());

            this.add(mainPanel_m);
    }

    @Override
    public void actionPerformed(ActionEvent event_p) {
        // show summary on request
        if (event_p.getActionCommand().equals("ShowSummary")) {

            // remove the previous information on the panel
            // (which displayed the login form on this example)
            mainPanel_m.removeAll();

            // and populate the panel with other informations, from another class
            mainPanel_m.add(...);
            ...
            ...
        }

        // and then refresh GUI
        this.validate();
        this.repaint();
        this.pack();
    }
}

When the ActionEvent is sent from the "LoginRequest" class to the "MainApplication" class, it executes the code, but at the end, nothing happens, as if the JFrame wasn't repainted.

Any ideas ?

Thanks,

adrien.pain
  • 443
  • 2
  • 11
  • 18

1 Answers1

1

The best way would be to use JDialog (main frame JFrame would be a parent component) for login form and CardLayout to switch between panels (so there is no need for removing, repainting and revalidating):

Your main form should look something like this:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MainFrame{
    JFrame frame = new JFrame("Main frame");

    JPanel welcomePanel = new JPanel();
    JPanel workspacePanel = new JPanel();
    JPanel cardPanel = new JPanel();

    JButton btnLogin = new JButton("Login");
    JLabel lblWelcome = new JLabel("Welcome to workspace");

    CardLayout cl = new CardLayout();

    LoginRequest lr = new LoginRequest(this);

    public MainFrame() {
        welcomePanel.add(btnLogin);
        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                lr.setVisible(true);
            }
        });

        workspacePanel.add(lblWelcome);

        cardPanel.setLayout(cl);
        cardPanel.add(welcomePanel, "1");
        cardPanel.add(workspacePanel, "2");
        cl.show(cardPanel,"1");

        frame.getContentPane().add(cardPanel);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setPreferredSize(new Dimension(320,240));
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

Your login form should look something like this:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginRequest extends JDialog{
    /**You can add, JTextFields, JLabel, JPasswordField..**/
    JPanel panel = new JPanel();
    JButton btnLogin = new JButton("Login");

    public LoginRequest(final MainFrame mf) {
        setTitle("Login");
        panel.add(btnLogin);
        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //Put some login logic here
                mf.cl.show(mf.cardPanel,"2");
                dispose();
            }
        });
        add(panel, BorderLayout.CENTER);
        setModalityType(ModalityType.APPLICATION_MODAL);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        pack();
        setLocationByPlatform(true);
    }
}

EDIT:

Your way:

MainFrame class:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MainFrame{
    JFrame frame = new JFrame("Main frame");

    JPanel welcomePanel = new JPanel();
    JPanel workspacePanel = new JPanel();
    JPanel cardPanel = new JPanel();

    JButton btnLogin = new JButton("Login");
    JLabel lblWelcome = new JLabel("Welcome");

    LoginRequest lr = new LoginRequest(this);

    public MainFrame() {
        welcomePanel.add(btnLogin);
        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                lr.setVisible(true);
            }
        });

        workspacePanel.add(lblWelcome);

        frame.getContentPane().add(welcomePanel);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setPreferredSize(new Dimension(320,240));
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

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

LoginRequest class:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class LoginRequest extends JDialog{
    /**You can add, JTextFields, JLabel, JPasswordField..**/
    JPanel panel = new JPanel();
    JButton btnLogin = new JButton("Login");

    public LoginRequest(final MainFrame mf) {
        setTitle("Login");
        panel.add(btnLogin);
        btnLogin.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //Put some login logic here
                mf.frame.getContentPane().removeAll();
                mf.frame.add(mf.workspacePanel);
                mf.frame.repaint();
                mf.frame.revalidate();
                dispose();
            }
        });
        add(panel, BorderLayout.CENTER);
        setModalityType(ModalityType.APPLICATION_MODAL);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        pack();
        setLocationByPlatform(true);
    }
}
Branislav Lazic
  • 14,388
  • 8
  • 60
  • 85
  • thank you for your complete answer. I'll go with the CardLayout, altough it's a bit of modifications, because my Panels were "lazy" (they didn't construct themselves before requested by the "MainApplication"). – adrien.pain Feb 17 '13 at 14:49
  • by the way, I still don't understand why my first code didn't work... removing/repainting/revalidating panels is maybe not the best way to do it, but it should work... :/ – adrien.pain Feb 17 '13 at 14:50
  • You are trying to trigger an event in MainApplication class and yet, you are passing `this` in your `actionPerformed` method which is in `LoginRequest` class. Try to pass `owner_m`. – Branislav Lazic Feb 17 '13 at 15:06
  • @adrien.pain: For reference, here's a working [example](http://stackoverflow.com/a/14894894/230513) using `validate()`, but `CardLayout` (+1) is better. – trashgod Feb 17 '13 at 15:07
  • @trashgod : yep, I refactored the code and change it a little bit, and yet it's working fine ! But i'll go with the CardLayout, for the elegant solution ;) Thanks again ! – adrien.pain Feb 17 '13 at 15:19
  • 1
    @brano88 : thanks for the advice, but I can pass a "LoginRequest" object to the "MainApplication", even in the actionPerformed. (i use it to know what was the caller of the action). And it's working now – adrien.pain Feb 17 '13 at 15:20