RedRoses
RedRoses

Reputation: 337

Mouse events from JTextField do not get propagated

I am trying to listen to mouse events coming from both a JLabel and a JTextField. However, I am only able to listen to mouse events from JLabel, but not JTextField.

Consider this code:

class FieldPanel extends JPanel{
  JLabel label;
  JTextField text;

  public FieldPanel(){
    label = new JLabel("This is a test label");
    text = new JTextField("This is a test field");
    add(label);
    add(text);
  } 
}

class OuterPanel extends JPanel{
  FieldPanel fieldPanel;

  public OuterPanel(){
    fieldPanel = new FieldPanel();
    fieldPanel.addMouseListener(new MouseAdapter(){
        @Override
        public void mousePressed(MouseEvent event) {
            System.out.println("Mouse pressed !!");
        }
    });
    add(fieldPanel);
  }
}

public class UITest{
    public static void main (String args[]){
        JFrame frame = new JFrame();
        OuterPanel outerPanel = new OuterPanel();
        frame.getContentPane().add(outerPanel);
        frame.pack();
        frame.setVisible(true);
    }
}

The 'Mouse Pressed !!' message is displayed when I click on the JLabel. However, it does not get displayed when I click on the JTextField. Why is this the case?

Thanks!

Upvotes: 1

Views: 2248

Answers (2)

RedRoses
RedRoses

Reputation: 337

Thanks for all the answers.

I found some sort of workaround. I am changing my code so that I listen directly to the JTextField component, as opposed to listening to the panel.

Upvotes: 1

Jasonw
Jasonw

Reputation: 5064

I think this is an interesting question which kinda stomp on the finding accidentally. I will explain using the snippet code below.

class FieldPanel extends JPanel
{
    //JLabel label;
    JTextField text;

    public FieldPanel()
    {
        //label = new JLabel("This is a test label");
        text = new JTextField("This is a test field");
        //add(label);
        add(text);          
    }
}

when you run the code with the changes above, what we expect the output only the text field right? Then if you click on the area near to the textfield outside region, check in your console output, it actually print out Mouse pressed !!

So I went a little deeper to study into JTextField, it actually consist of the JTextField and JTextComponent. When you called the constructor new JTextField("This is a test field");, the text is actually set into the JTextComponent and not JTextField and I guess that is why when you click the text, it does not trigger the mousePressed event but it trigger only the JTextField only.

Below is my full code. If you want the text field to aware of the mouse pressed, consider implements MouseAdapter() in your FieldPanel class and add addMouseListener(this) for text and label.

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;


public class MyMouseEvent extends JPanel
{

    public MyMouseEvent()
    {
        FieldPanel fieldPanel;
        fieldPanel = new FieldPanel();
        fieldPanel.addMouseListener(new MouseAdapter() {
               @Override
                public void mousePressed(MouseEvent event)
               {
                    System.out.println("Mouse pressed !!");
                }
        });
        add(fieldPanel);

    }

    class FieldPanel extends JPanel
    {
        //JLabel label;
        JTextField text;

        public FieldPanel()
        {
            //label = new JLabel("This is a test label");
            text = new JTextField("This is a test field");
            //add(label);
            add(text);          
        }
    }

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

        MyMouseEvent evt = new MyMouseEvent();
        evt.setOpaque(true);
        frame.setContentPane(evt);

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

    public static void main (String args[])
    {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() 
            {
                createAndShowGUI();             
            }
        });

    }


}

Upvotes: 1

Related Questions