如何在不破坏默认实现的情况下为JPanel实现MouseWheelListener?

Sal*_*eek 5 java swing jpanel mousewheel jscrollpane

只是; 我有一个JPanel里面的JScrollPane;

正如所料; JScrollPane默认情况下会监听,MouseWheelEvent以便在滚轮旋转时以及光标悬停在滚轮上时滚动效果很好JPanel.

在那之后; 我刚刚更新,JPanel以便它实现MouseWheelListener,我为JPanel自己添加了这个鼠标滚轮监听器.

@Override
public void mouseWheelMoved(MouseWheelEvent e) {
    if (e.isControlDown()) {
        if (e.getWheelRotation() < 0) {
            System.out.println("mouse wheel Up");
        } else {
            System.out.println("mouse wheel Down");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

JPanel响应这个实施时都; 在Ctrl被按下和车轮旋转且当光标悬停在JPanel.但是默认行为JScrollPane却意外丢失了!

当我在光标悬停在JPanel滚动时旋转滚轮JScrollPane没有响应!

看起来; 这个实现MouseWheelListener打破了默认的a JPanel.

所以; 如何实现MouseWheelListenerJPanel不破坏它的默认实现?

Mar*_*o13 8

MouseWheelEvents 滚动行为有一些微妙的警告.

例如,当您打开此页面(我的意思是您正在阅读的那个页面)时,将鼠标放在中间,然后开始用滚轮向下滚动,您将滚动代码片段.需要注意的是,虽然该代码片段包含在代码块有一个滚动条,不断滚动鼠标滚轮将不会触发滚动的代码块,但只有在整个页面.但是当你代码块移动鼠标时,然后滚动鼠标滚轮,那么你只会在代码块中滚动 - 而不是整个页面.

类似地,旋转鼠标滚轮可能不会影响悬停的可滚动.我认为这取决于窗口管理器和外观,但在某些情况下,您将滚动包含焦点组件的滚动窗格 - 即使鼠标光标位于此组件之外,即使它位于可分辨的上方组件(例如,您也可以在Windows资源管理器中观察它)!


但是,其中一些机制和细微之处也可以在Swing组件中找到.例如,如果组件本身未处理它们,则会传递给祖先的重新分配机制MouseWheelEvents.

遵循这种模式,一个解决方案(在概念上类似于LuxxMiner提出的解决方案,但可能有点更通用)可能只是简单地重新分配MouseWheelEvent给父组件:

package stackoverflow;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class MouseWheelListenerForPanelInScrollpane
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().setLayout(new GridLayout(1,2));

        MouseWheelListenerPanel m = new MouseWheelListenerPanel();
        m.setPreferredSize(new Dimension(100,4000));
        JScrollPane scrollPane = new JScrollPane(m);
        f.getContentPane().add(scrollPane);

        f.setSize(500,500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class MouseWheelListenerPanel extends JPanel implements MouseWheelListener
{
    MouseWheelListenerPanel()
    {
        addMouseWheelListener(this);
    }

    @Override
    public void mouseWheelMoved(MouseWheelEvent e)
    {
        if (e.isControlDown())
        {
            if (e.getWheelRotation() < 0)
            {
                System.out.println("mouse wheel Up");
            }
            else
            {
                System.out.println("mouse wheel Down");
            }
        }
        else
        {
            getParent().dispatchEvent(e);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)


Ian*_*rts 6

else如果ctrl 关闭,则添加一个以直接将事件重新分派到滚动窗格:

@Override
public void mouseWheelMoved(MouseWheelEvent e) {
    if (e.isControlDown()) {
        if (e.getWheelRotation() < 0) {
            System.out.println("mouse wheel Up");
        } else {
            System.out.println("mouse wheel Down");
        }
    } else {
        // pass the event on to the scroll pane
        getParent().dispatchEvent(e);
    }
}
Run Code Online (Sandbox Code Playgroud)