1

My FatherPanel changes colors through mouse entered (RED)/exited (ORANGE) mouse events. It works good, but when I enter the button "Testbutton" (which is a child component of my father panel) the mouse exited event appears. But I am still inside my father panel.

Can somebody explain me why and how to solve such an issue?

I want the father panel to be orange as long as my mouse is inside that panel (no matter if the mouse is on a child-object or not).

public class MainFrame extends JFrame {

    public MainFrame() {

        FatherPanel fatherPanel = new FatherPanel();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(800, 700);
        setLayout(null);

        add(fatherPanel);
        fatherPanel.setBounds(150, 20, 300, 300);
    }


    public class FatherPanel extends JPanel{

        JButton btn1 = new JButton("Testbutton");

        public FatherPanel() {
            setSize(300, 300);
            setLayout(null);
            setBackground(Color.RED);

            add(btn1);
            btn1.setBounds(150, 150, 100, 100);

            addMouseListener(new MouseListener() {

                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseExited(MouseEvent e) {
                    setBackground(Color.RED);
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                    setBackground(Color.ORANGE);
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                }
            });
        }
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Serek
  • 35
  • 4
  • 1
    you could also add a mouselistener to the button which edits the color of the father panel – XtremeBaumer Mar 03 '17 at 12:58
  • Java GUIs have to work on different OS', screen size, screen resolution etc. using different PLAFs in different locales. As such, they are not conducive to pixel perfect layout. Instead use layout managers, or [combinations of them](http://stackoverflow.com/a/5630271/418556) along with layout padding and borders for [white space](http://stackoverflow.com/a/17874718/418556). – Andrew Thompson Mar 03 '17 at 13:02
  • @XtremeBaumer: I thought about that, but than I have to do this to every child component. There must be an easier way... – Serek Mar 03 '17 at 13:47
  • Andrew Thompson: Are you sure that the LayoutManager could solve this issue? I tried the FlowManager for the father-panel, but the behaviour is the same: `public FatherPanel() { setSize(300, 300); setLayout(new FlowLayout()); setBackground(Color.RED); ` – Serek Mar 03 '17 at 13:50
  • layoutmanager wont fix that. he just told you that, because you used absolute layout. imagine you work on a screen with 1920x1080 and make the application full size for you. then you execute the application on a pc with a screen which is for example 800x800. this would result in some really messed up gui and layoutmanager help you to prevent this – XtremeBaumer Mar 03 '17 at 14:22

1 Answers1

2

In the mouseExited event you can check the mouse point to see if it is still in the bounds of the parent component.

Something like:

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)
            setBackground( Color.RED );
    }

    @Override
    public void mouseEntered(MouseEvent e)
    {
        setBackground( Color.ORANGE );
    }
});

Note: extending MouseAdapter is easier since you only need to implement the methods you want to handle.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thx for your solution. However, I ask myself if there is a way to make the child-component (in my case the button) pass the mouse-entered-event to the father-panel. But I dont know under which topic to search for. I thought it would be something like "action-passing" or "event-passing". Can you help me where to look at? – Serek Mar 04 '17 at 11:55
  • @Serek, Components only listen for events if you add a listener to the component. So you would add a listener to the button, then you can use the Component.dispatchEvent(...). But you would need to convert the event to change the source of the event to be the panel, not the button adding extra work. You already stated you don't want to add a listener to all the components, so I gave you a simple solution. – camickr Mar 04 '17 at 15:52
  • Don't forget to "accept" the answer by clicking on the checkmark, so people know the problem has been solved. – camickr Mar 04 '17 at 15:53
  • Thanks for the solution. I will take a look at the dispatchEvent() method. Checkmark has been checked :-) – Serek Mar 04 '17 at 17:17
  • How do I use the mouseAdapter, if I already extended my View from JFrame? I cant extend from a second class. – Serek Mar 08 '17 at 12:55