GlassPane正确发送鼠标事件

时间:2016-07-20 12:36:28

标签: java swing mouseevent glasspane

我使用GlassPane来移动框架中的元素。当没有拖动元素时,所有鼠标事件都以正常方式调度

public class MainFrame implements MouseListener {
 private JFrame frame;

 public MainFrame()
 {
    frame = new JFrame();

    JPanel testPanel = new JPanel();
    testPanel.addMouseListener(this);

    JLabel testLabel = new JLabel("Test",JLabel.CENTER);
    testPanel.add(testLabel);

    frame.add(testPanel);
    frame.pack();
    frame.setVisible(true);

    GlassPanel glassPanel = new GlassPanel(frame);
    frame.setGlassPane(glassPanel);
    // Without this line the click in the panel is mentioned.
    // otherwise it is ignored.
    frame.getGlassPane().setVisible(true);
 }

 @Override
 public void mouseClicked(MouseEvent e) 
 {
    System.out.print("CLicked");
 }

 @Override
 public void mousePressed(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseReleased(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseEntered(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 @Override
 public void mouseExited(MouseEvent e) {
    // TODO Auto-generated method stub

 }

 public class GlassPanel extends JPanel implements MouseMotionListener, MouseListener
 {
    private JFrame frame;

    public GlassPanel(JFrame mainframe)
    {
        frame = mainframe;

        setLayout(null);
        setOpaque(false);

        addMouseMotionListener(this);
        addMouseListener(this);

    }

    @Override
    public void mouseClicked(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mousePressed(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseReleased(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseEntered(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseExited(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseDragged(MouseEvent e) 
    {
        redispatchMouseEvent(e, true);
    }

    @Override
    public void mouseMoved(MouseEvent e) 
    {
            redispatchMouseEvent(e, true);
    } 

    private void redispatchMouseEvent(MouseEvent e, boolean repaint) 
    {
        System.out.println("Dispatch");
        Point glassPanePoint = e.getPoint();
        Container container = frame.getContentPane();
        Point containerPoint = SwingUtilities.convertPoint(frame.getGlassPane(),
                glassPanePoint, container);

        if (containerPoint.y < 0) { // we're not in the content pane
            // Could have special code to handle mouse events over
            // the menu bar or non-system window decorations, such as
            // the ones provided by the Java look and feel.
        } else {
            // The mouse event is probably over the content pane.
            // Find out exactly which component it's over.
            Component component = SwingUtilities.getDeepestComponentAt(
                    container, containerPoint.x, containerPoint.y);

            if (component != null) {
                // Forward events to component below
                Point componentPoint = SwingUtilities.convertPoint(
                        frame.getGlassPane(), glassPanePoint, component);
                component.dispatchEvent(new MouseEvent(component, e
                        .getID(), e.getWhen(), e.getModifiers(),
                        componentPoint.x, componentPoint.y, e
                                .getClickCount(), e.isPopupTrigger()));
            }
        }
    }
 }
}

但是这会导致鼠标事件处理中出现异常行为。例如:我有一个带鼠标监听器的JPanel。双击此面板可打开另一个框架。在这个小组上有一些标签。当没有Glasspane时,我可以单击此标签,因为标签不会对鼠标事件起作用,所以事件将传递到面板并完成单击操作。当我使用我的调度例程时,我会将鼠标事件直接发送到标签,而这些事件将导致无法执行操作。

那我怎么解决这个问题呢?当然,我可以创建自己的标签类,并引用其面板并再次将鼠标事件发送到面板,但这看起来不像一个漂亮的设计。 第二个是,我可以在Glasspane调度员中确定,如果最深的面板是鼠标事件中的interesstet,如果不是,则升高或类似的东西?

有什么想法吗?

0 个答案:

没有答案