如何让子组件只处理它可以处理的事件,而其他事件保持不变?

时间:2014-04-02 13:46:12

标签: java swing events

如果子组件添加了鼠标侦听器,则会在其中处理鼠标事件,并且父组件中的鼠标侦听器不会听到它们。

以下代码中说明了这种情况。

我想用更精细的颗粒分离处理是什么?例如,在一个组件中处理双击,在另一个组件中单击一次。怎么做到这一点?

更新

在下面的示例中,如果复选框为ON,则子(黄色方块)正在处理鼠标事件。在这种情况下,父(灰色)停止处理单击。我希望父母仍然可以在双子进程双击的情况下同时处理单击。

package tests;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Try_ChildEvents {


    public static void main(String[] args) {

        final MouseAdapter mouseAdapter = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 ) {
                    System.out.println("Double clicked inside inner");
                }
            }
        };



        final JPanel inner = new JPanel();
        {
            inner.setBackground(Color.yellow);
        }
        inner.addMouseListener(mouseAdapter);

        JPanel outer = new JPanel();
        {
            outer.setLayout(null);
            outer.add(inner);
            inner.setBounds(50, 50, 100, 100);
        }
        outer.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1 ) {
                    System.out.println("Single clicked in outer");
                }
            }
        });

        JCheckBox check = new JCheckBox("Enable events", true);
        check.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if( e.getStateChange() == ItemEvent.SELECTED ) {
                    inner.addMouseListener(mouseAdapter);
                }
                else {
                    inner.removeMouseListener(mouseAdapter);
                }
            }
        });

        JFrame frame = new JFrame();

        frame.setLayout(new BorderLayout());
        frame.add(check, BorderLayout.NORTH);
        frame.add(outer, BorderLayout.CENTER);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);

        frame.setVisible(true);


    }

}

更新2

我做了@camickr sadi并且它有效,但我不明白,为什么?为什么不派遣事件再次回到孩子身上?

package tests;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Try_ChildEvents {


    public static void main(String[] args) {

        class JPanelWithTurnableListener extends JPanel {

            final MouseAdapter mouseAdapter = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2 ) {
                        System.out.println("Double clicked inside inner");
                    }
                    else {
                        MouseEvent mouseEvent = new MouseEvent(
                                (Component) e.getSource(), 
                                e.getID(), 
                                e.getWhen(), 
                                e.getModifiers(), 
                                e.getX(), 
                                e.getY(), 
                                e.getXOnScreen(), 
                                e.getYOnScreen(), 
                                e.getClickCount(), 
                                e.isPopupTrigger(), 
                                e.getButton()
                                );
                        getParent().dispatchEvent(mouseEvent);
                    }
                }
            };

            boolean on;

            public JPanelWithTurnableListener() {
                setBackground(Color.yellow);
                addMouseListener(mouseAdapter);
            }

            boolean isOn() {
                return on;
            }

            void setOn(boolean newValue) {
                boolean oldValue = this.on;
                if( newValue != oldValue ) {
                    this.on = newValue;
                    if( newValue ) {
                        addMouseListener(mouseAdapter);
                    }
                    else {
                        removeMouseListener(mouseAdapter);
                    }
                }

            }

        }





        final JPanelWithTurnableListener inner = new JPanelWithTurnableListener();

        JPanel outer = new JPanel();
        {
            outer.setLayout(null);
            outer.add(inner);
            inner.setBounds(50, 50, 100, 100);
        }
        outer.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if( e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 1 ) {
                    System.out.println("Single clicked in outer");
                }
            }
        });

        JCheckBox check = new JCheckBox("Enable events", true);
        check.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if( e.getStateChange() == ItemEvent.SELECTED ) {
                    inner.setOn(true);
                }
                else {
                    inner.setOn(false);
                }
            }
        });

        JFrame frame = new JFrame();

        frame.setLayout(new BorderLayout());
        frame.add(check, BorderLayout.NORTH);
        frame.add(outer, BorderLayout.CENTER);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);

        frame.setVisible(true);


    }

}

1 个答案:

答案 0 :(得分:2)

使用Component.dispatchEvent(...)方法将事件重新分发到父组件。您需要创建一个新的MouseEvent。

请参阅How to Use Root Panes中的GlassPane示例。它将事件从玻璃窗格重新分派到玻璃窗格下的组件。