Home > front end >  The JFrame or the JPanel don't listen to the clicking event
The JFrame or the JPanel don't listen to the clicking event

Time:03-31

I have this JFrame(BorderLayout), that has 3 Jpanel in it(north, center, south). The center panel, has a login button. For testing purposes, what I want is to print "hello", when pressed.

This is how the frame currently looks: enter image description here

I have tried 2 ways:

  1. "implements ActionListener", on the center panel, but nothing happens, not even an error.

  2. "implements ActionListener", on the frame itself, however, I am having issues (more like, I don't know how to) "importing"/having access to the button, so the JFrame can listen to the cliking event

Hope you can help me.

This is the code:

Main program:

package com.system.reservation.airline;

public class Main {
    public static void main(String[] args) {
        LoginPage loginPage = new LoginPage(); 
    }
}

LoginPage:

import com.system.reservation.airline.panels.BodyPanel;
import com.system.reservation.airline.panels.FooterPanel;
import com.system.reservation.airline.panels.HeaderPanel;

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

public class LoginPage extends JFrame{ 
    HeaderPanel headerPanel = new HeaderPanel();
    BodyPanel bodyPanel = new BodyPanel();
    FooterPanel footerPanel = new FooterPanel();

    public LoginPage(){ // Constructor
        this.setTitle("Login");
        this.setSize(400, 600);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
        this.getContentPane().setBackground(new Color(240,248,255));
        this.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();

        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.BOTH;

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridheight = 1;
        this.add(headerPanel, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridheight = 1;
        this.add(bodyPanel, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridheight = 3;
        this.add(footerPanel, gbc);

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

BodyPanel:

package com.system.reservation.airline.panels;

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

public class BodyPanel extends JPanel implements ActionListener{
    JLabel login_label;
    JButton login_button = new JButton("Login");
    Color transparent = new Color(1f,0f,0f,0f);

    public BodyPanel(){
        this.setBackground(transparent);
        this.setLayout(new BorderLayout());
        this.setBorder(BorderFactory.createLineBorder(Color.green, 3));
        //------------ Login Panel ------------------------
        JPanel login_panel = new JPanel(new BorderLayout());
        login_panel.setBackground(transparent);
        login_panel.setPreferredSize(new Dimension(400, 100));
        //login_panel.setBorder(BorderFactory.createLineBorder(Color.YELLOW, 5));

        login_label = new JLabel();
        login_label.setText("Login");
        login_label.setHorizontalAlignment(JLabel.CENTER);
        login_label.setFont(new Font("Arial", Font.PLAIN, 20));

        login_panel.add(login_label, BorderLayout.NORTH);
        //------------ Login Panel ------------------------

        //------------ Input Panel ------------------------
        JPanel input_fields_panel = new JPanel(new GridBagLayout());
        input_fields_panel.setBackground(transparent);
        input_fields_panel.setPreferredSize(new Dimension(400, 150));
        //input_fields_panel.setBorder(BorderFactory.createLineBorder(Color.black, 5));

        GridBagConstraints gbc = new GridBagConstraints();

        gbc.weightx = 1;
        gbc.weighty = 1;
        gbc.fill = GridBagConstraints.BOTH;

        //-------------
        JLabel userName_label = new JLabel("Username: ");
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        gbc.insets = new Insets(0,10,0,0);
        input_fields_panel.add(userName_label, gbc);

        JTextField userName_txb = new JTextField();
        userName_txb.setPreferredSize(new Dimension(250,30));
        gbc.gridx = 3;
        gbc.insets = new Insets(0,0,5,20);
        input_fields_panel.add(userName_txb, gbc);
        //-------------

        //-------------
        JLabel password_label = new JLabel("Password: ");
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        gbc.insets = new Insets(0,10,0,0);
        input_fields_panel.add(password_label, gbc);

        JTextField password_txb = new JTextField();
        password_txb.setPreferredSize(new Dimension(250,30));
        gbc.gridx = 1;
        gbc.gridy = 1;
        gbc.gridwidth = 3;
        gbc.gridheight = 1;
        gbc.insets = new Insets(5,0,5,20);
        input_fields_panel.add(password_txb, gbc);
        //-------------

        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.gridwidth = 4;
        gbc.gridheight = 1;
        gbc.insets = new Insets(5,150,5,150);
        input_fields_panel.add(login_button, gbc);

        JLabel tokenResponse = new JLabel("Username or password, are incorrect!");
        tokenResponse.setHorizontalAlignment(JLabel.CENTER);
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.gridwidth = 4;
        gbc.gridheight = 1;
        gbc.insets = new Insets(0,0,0,0);
        input_fields_panel.add(tokenResponse, gbc);
        //------------ Input Panel ------------------------

        //-------------------------------------
        this.add(login_panel, BorderLayout.NORTH);
        this.add(input_fields_panel, BorderLayout.CENTER);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == login_button) {
            System.out.println("Hello");
        }
    }
}

The center panel is the BodyPanel, hence I did not include the code for the HeaderPanel, or the FooterPanel.

So to recap, I want to either the LoginPage to have access or to listen to the clicking event of the login_button, or the exact same for the BodyPanel.

CodePudding user response:

I think you forgot to add an implementation of the ActionListener interface to your button.

In your constructor there should be something like this at some point:

public BodyPanel(){
   //...
   login_button.addActionListener(this);
   //...
}

CodePudding user response:

The "obvious" problem is the fact that you've not registered an ActionListener to the login_button. The less "obvious" problem is, what do you do with it when the actionPerformed method is called.

This is where an observer pattern becomes important (you've already used one, ActionListener is a type of an observer pattern).

You need someway to know when the BodyPanel has authenticated the user. To this end, I would add some kind of "login observer" to the BodyPanel, to which the LoginPage would register to, for example.

public interface LoginObserver {
    public void didAuthenticate(BodyPanel source, User user);
}

I might also consider using Dependency Injection to define some kind of "authentication" workflow, which would be passed through LoginPage to BodyPanel to decouple the workflow, but that's probably getting beyond scope.

Runnable example

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

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

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new LoginPage();
            }
        });
    }

    public interface User {
        public String getName();
    }

    public class DefaultUser implements User {
        private String name;

        public DefaultUser(String name) {
            this.name = name;
        }

        @Override
        public String getName() {
            return name;
        }
    }

    public class LoginPage extends JFrame {
//        HeaderPanel headerPanel = new HeaderPanel();
        BodyPanel bodyPanel = new BodyPanel(new BodyPanel.LoginObserver() {
            @Override
            public void didAuthenticate(BodyPanel source, User user) {
                JOptionPane.showMessageDialog(getContentPane(), "Welcome "   user.getName(), "Welcome", JOptionPane.PLAIN_MESSAGE);
            }
        });
//        FooterPanel footerPanel = new FooterPanel();

        public LoginPage() { // Constructor
            this.setTitle("Login");
            this.setSize(400, 600);
            this.setLocationRelativeTo(null);
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.getContentPane().setBackground(new Color(240, 248, 255));
            this.setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();

            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridheight = 1;
//            this.add(headerPanel, gbc);

            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridheight = 1;
            this.add(bodyPanel, gbc);

            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.gridheight = 3;
//            this.add(footerPanel, gbc);

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

    public class BodyPanel extends JPanel implements ActionListener {
        private interface LoginObserver {
            public void didAuthenticate(BodyPanel source, User user);
        }

        JLabel login_label;
        JButton login_button = new JButton("Login");
        // This is VERY bad idea
        //Color transparent = new Color(1f, 0f, 0f, 0f);

        private JTextField userName_txb;
        private JPasswordField password_txb;
        private JLabel tokenResponse;

        private LoginObserver loginObserver;

        public BodyPanel(LoginObserver loginObserver) {
            this.loginObserver = loginObserver;
            //this.setBackground(transparent);
            setOpaque(false);
            this.setLayout(new BorderLayout());
            this.setBorder(BorderFactory.createLineBorder(Color.green, 3));
            //------------ Login Panel ------------------------
            JPanel login_panel = new JPanel(new BorderLayout());
//            login_panel.setBackground(transparent);
            login_panel.setOpaque(false);
            // This is another BAD idea
//            login_panel.setPreferredSize(new Dimension(400, 100));
            //login_panel.setBorder(BorderFactory.createLineBorder(Color.YELLOW, 5));

            login_label = new JLabel();
            login_label.setText("Login");
            login_label.setHorizontalAlignment(JLabel.CENTER);
            login_label.setFont(new Font("Arial", Font.PLAIN, 20));

            login_panel.add(login_label, BorderLayout.NORTH);
            //------------ Login Panel ------------------------

            //------------ Input Panel ------------------------
            JPanel input_fields_panel = new JPanel(new GridBagLayout());
//            input_fields_panel.setBackground(transparent);
            input_fields_panel.setOpaque(false);
            // This is another BAD idea
//            input_fields_panel.setPreferredSize(new Dimension(400, 150));
            //input_fields_panel.setBorder(BorderFactory.createLineBorder(Color.black, 5));

            GridBagConstraints gbc = new GridBagConstraints();

            gbc.weightx = 1;
            gbc.weighty = 1;
            gbc.fill = GridBagConstraints.BOTH;

            //-------------
            JLabel userName_label = new JLabel("Username: ");
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(0, 10, 0, 0);
            input_fields_panel.add(userName_label, gbc);

            userName_txb = new JTextField(10);
            //userName_txb.setPreferredSize(new Dimension(250, 30));
            gbc.gridx = 3;
            gbc.insets = new Insets(0, 0, 5, 20);
            input_fields_panel.add(userName_txb, gbc);
            //-------------

            //-------------
            JLabel password_label = new JLabel("Password: ");
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            gbc.insets = new Insets(0, 10, 0, 0);
            input_fields_panel.add(password_label, gbc);

            password_txb = new JPasswordField(10);
//            password_txb.setPreferredSize(new Dimension(250, 30));
            gbc.gridx = 1;
            gbc.gridy = 1;
            gbc.gridwidth = 3;
            gbc.gridheight = 1;
            gbc.insets = new Insets(5, 0, 5, 20);
            input_fields_panel.add(password_txb, gbc);
            //-------------

            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.gridwidth = 4;
            gbc.gridheight = 1;
            gbc.insets = new Insets(5, 150, 5, 150);
            input_fields_panel.add(login_button, gbc);

            login_button.addActionListener(this);

            tokenResponse = new JLabel("Username or password, are incorrect!");
            tokenResponse.setHorizontalAlignment(JLabel.CENTER);
            gbc.gridx = 0;
            gbc.gridy = 3;
            gbc.gridwidth = 4;
            gbc.gridheight = 1;
            gbc.insets = new Insets(0, 0, 0, 0);
            input_fields_panel.add(tokenResponse, gbc);
            //------------ Input Panel ------------------------

            //-------------------------------------
            this.add(login_panel, BorderLayout.NORTH);
            this.add(input_fields_panel, BorderLayout.CENTER);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource() == login_button) {
                // Perform authentication via a seperate service
                loginObserver.didAuthenticate(this, new DefaultUser(userName_txb.getText()));
            }
        }
    }
}

Notes

Using transparent color (Color transparent = new Color(1f, 0f, 0f, 0f);) on Swing components is going to cause no end of issues. Swing components are either fully opaque or fully transparent and this is controlled via the opaque property.

I would avoid using setPreferredSize, again, this is just going to cause you no end of issues. Make use of the layout (GridBagLayoutConstraints provide a number of properties which can help adjust the spacing and size of the components), EmptyBorders and, for text components, sizing hints via the columns property

  • Related