Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to avoid mouseExited to fire while on any nested component

In my code i have:

an abstract class extending JComponent which contains some JTextFields. JTextFields aren't editable. JComponent class implement MouseListener: - when mouseEntered event fires a border is added to it. - when mouseExited event fires border is removed. - when mouseClicked event fires all fields of that component are set as editable.

This should work in this way:

  • User want to edit a field.
  • He mouseHover any point of the the jComponent
  • border is draw on the jComponent to highlight it
  • User click and the mouseClicked method fires which does its stuffs.

The problem is: mouseExited fires when the mouse goes over on any JTextField. How would you solve the problem?

What follows is a simple class which will show you a window with a jTextField contained into a panel which implement MouseListener in a way pretty similar to the one described above. Do not take into consideration how it's written, it s just for purpose!

public static void main(String[] args)  {       
        SwingUtilities.invokeLater(new Runnable() {
            public void run(){   
                int i=0;
                //mainWindow
                    JFrame mainWindow = new JFrame("MyFrame");
                    mainWindow.setLayout(new BorderLayout());
                    mainWindow.setMinimumSize(new Dimension(200,200));

                    JPanel viewPort = new JPanel();

                    final JTextField text = new JTextField("SOME_RANDOM_TEXT");
                    text.setEditable(false);

                    final JPanel panel = new JPanel();
                    panel.add(text);
                    panel.setBackground(Color.green);
                    panel.addMouseListener(new MouseListener() {
                        @Override
                        public void mouseReleased(MouseEvent e) {
                            //NOTHING
                        }
                        @Override
                        public void mousePressed(MouseEvent e) {
                            //NOTHING
                        }

                        @Override
                        public void mouseExited(MouseEvent e) {
                            panel.setBorder(BorderFactory.createEmptyBorder());
                        }

                        @Override
                        public void mouseEntered(MouseEvent e) {
                            panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
                        }

                        @Override
                        public void mouseClicked(MouseEvent e) {
                            ((JTextField)panel.getComponent(0)).setEditable(true);
                            panel.getComponent(0).requestFocus();
                        }
                    });
                    viewPort.add(panel);
                    mainWindow.add(viewPort,BorderLayout.CENTER);
                    mainWindow.setVisible(true);
            }
        });
    }
like image 932
Koop4 Avatar asked Oct 20 '25 08:10

Koop4


2 Answers

You can check the mouse point of the event to determine if the point is still in the bounds of the panel or not:

panel.addMouseListener(new MouseAdapter()
{
    @Override
    public void mouseExited(MouseEvent e)
    {
        Rectangle r = e.getComponent().getBounds();
        Point p = e.getPoint();

        if (p.x < 0 || p.x >= r.width
        ||  p.y < 0 || p.y >= r.height)
            panel.setBorder( null );
    }

    @Override
    public void mouseEntered(MouseEvent e)
    {
        panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
    }
});

It is easier to extend MouseAdapter, then you only need to override the methods you want to customize.

like image 127
camickr Avatar answered Oct 22 '25 05:10

camickr


Problem is you set the MouseListener to the JPanel, which does not make much sense (for the desired described behaviour).

Just change the MouseListener to JTextField:

text.addMouseListener(new MouseListener() {

It's working nice for me.


UPDATE:

You missed something mate :) Thx for the fast answer, but, my JPanel can contains more then a single textField, it could contains for example, 10 of them!

The example is ok as example, but in real life you won't create an inner listener, you will create a class.

class MyMouseListener implements MouseListener {
    // define methods and behaviour
}

and then you will add it to your selectable areas like:

MyMouseListener listener = new MyMouseListener()
panel1.addMouseListener(listener);
panel2.addMouseListener(listener);
panel3.addMouseListener(listener);

TIP: remember MouseEvent extends from ComponentEvent that has a great method getComponent()

Returns the originator of the event.

like image 26
Jordi Castilla Avatar answered Oct 22 '25 05:10

Jordi Castilla