Java: определить компонентный блок для событий мыши - PullRequest
3 голосов
/ 15 августа 2011

Я хочу иметь JPanel с именем mainPanel и добавить несколько компонентов; Также я определил mouseAdapter и добавил к своему mainPanel, который переопределяет mouseEntered и mouseExited, чтобы, например, изменить цвет фона mainPanel при вводе мышью. Но когда мышь вошла в mainPanel и вошла в компоненты, которые я добавил (например, метки), вызывается событие mouseExited; Но я не хочу этого, поскольку мышь находится в области mainPanel; Я хочу, чтобы он вызывался, когда мышь выходила из области mainPanel; и также хочу это для mouseEntered. Ранее я добавил mouseListeners к компонентам на mainPanel, но это неочевидное решение. Может кто-нибудь сказать мне ясный путь для моей цели?

спасибо вашему вниманию; Хороший замок

Ответы [ 2 ]

3 голосов
/ 15 августа 2011

Вы хотите, чтобы mouseEntered и mouseExited вызывались на полных границах. Как вы заметили, это невозможно напрямую с «нормальным» MouseListener.

Самый простой способ - добавить слушателя ко всем дочерним компонентам панели:

private static void addListenerToAllComponents(JComponent c, MouseListener l) {

    c.addMouseListener(l);

    for (Component cc : c.getComponents())
        if (cc instanceof JComponent)
            addListenerToAllComponents((JComponent) cc, l);
}

Полный пример:

public static void main(String[] args) {

    final JFrame frame = new JFrame("Test");

    frame.add(new JLabel("Testing"), BorderLayout.NORTH);

    final JPanel panel = new JPanel(new GridLayout(2, 1));
    panel.setBackground(Color.RED);

    MouseListener l = new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
            panel.setBackground(Color.BLUE);
        }
        @Override
        public void mouseExited(MouseEvent e) {
            panel.setBackground(Color.RED);
        }
    };

    panel.add(new JLabel("Hello"));
    panel.add(new JTextField("World!"));

    addListenerToAllComponents(panel, l);

    frame.add(panel, BorderLayout.CENTER);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
}

Другой обходной путь (предыдущий ответ) ...

... это установить GlassPane и проверить границы самостоятельно:

public static void main(String[] args) {

    JFrame frame = new JFrame("Test");

    frame.add(new JLabel("Testing"), BorderLayout.NORTH);

    final JPanel panel = new JPanel(new GridLayout(2, 1));
    frame.add(panel, BorderLayout.CENTER);

    panel.add(new JLabel("Hello"));
    panel.add(new JTextField("World!"));

    class GlassPane extends JComponent {
        GlassPane(final JComponent c) {
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {

                    Point p = SwingUtilities.convertPoint(e.getComponent(), 
                                                          e.getPoint(), 
                                                          c);

                    if (c.contains(p))
                        c.setBackground(Color.BLUE);
                    else
                        c.setBackground(Color.RED);
                }
            });

            addMouseListener(new MouseAdapter() {
                public void mouseExited(MouseEvent e) {
                    c.setBackground(Color.MAGENTA);
                }
            });
        }
    }        

    GlassPane glass = new GlassPane(panel);
    frame.setGlassPane(glass);
    glass.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
}

Есть некоторые вещи, на которые вам нужно обратить внимание ... Перераспределение событий - это одно и может быть проблемой в вашем случае. Следуйте этому примеру и внедрите прослушиватель распространения событий на стеклянную панель:

MouseInputListener i = new MouseInputListener() {

    private void redispatchMouseEvent(MouseEvent e) {

        Point glassPanePoint = e.getPoint();
        Container container = frame.getContentPane();

        Point containerPoint = SwingUtilities.convertPoint(
                GlassPane.this,
                glassPanePoint,
                container);

        Component component = 
            SwingUtilities.getDeepestComponentAt(
                    container,
                    containerPoint.x,
                    containerPoint.y);

        if (component != null) {

            Point componentPoint = SwingUtilities.convertPoint(
                    GlassPane.this,
                    glassPanePoint,
                    component);

            component.dispatchEvent(new MouseEvent(component,
                    e.getID(),
                    e.getWhen(),
                    e.getModifiers(),
                    componentPoint.x,
                    componentPoint.y,
                    e.getClickCount(),
                    e.isPopupTrigger()));
        }
    }

    public void mouseMoved(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseDragged(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseClicked(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseEntered(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseExited(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mousePressed(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseReleased(MouseEvent e) {
        redispatchMouseEvent(e);
    }
};

addMouseListener(i);
addMouseMotionListener(i);
2 голосов
/ 15 августа 2011

Получение mouseEvents для компонента и всех его потомков ... сложно понять правильно. Вы можете полагаться на стабильный (и тщательно протестированный код :-). Способ jdk7 сделать это - использовать JLayer (который внутренне регистрирует AWTEventListener, поскольку у него есть все привилегии). Для более ранних версий вы можете использовать его предшественник JXLayer

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...