如何将 mouseListener 添加到 jscrollbar?

Posted

技术标签:

【中文标题】如何将 mouseListener 添加到 jscrollbar?【英文标题】:How do you add a mouseListener to a jscrollbar? 【发布时间】:2015-09-04 19:09:51 【问题描述】:

我有 mouseEntered 和 mouseExited 事件导致 jPanel 内容发生改变,从而改变了 jPanel 的大小。在 mouseEntered 后,内容会增长并且可以滚动。 mouseExited 后,内容会缩小且不可滚动。

问题是鼠标悬停在滚动条上会触发jPanel的mouseExited事件,所以当用户想要拖动滚动条的旋钮时,点击它时它会消失。

如果我可以将 mouseListener 添加到滚动条本身,我想我可以防止内容缩小。但我从来没有在滚动条上添加过 mouseListener。如何通过滚动条触发 mouseEntered/Exited 事件?

【问题讨论】:

您是否尝试将侦听器添加到 JScrollBar?当你这样做时会发生什么? 【参考方案1】:

是的,您可以将 mouseListener 附加到滚动条。当您的内容在 mouseEntered/mouseExited 上更改时,这是必要的 WRT 一个 jPanel,因为悬停在 jPanel 的滚动条上会触发 mouseExited。您必须实现 2 个方面以保持内容就像您将鼠标悬停在 jPanel 上一样:mouseEntered/mouseExited 和 mouseClicked/mouseReleased。这样做的原因是因为当滚动条的旋钮被拖动时,鼠标可以悬停在滚动条上,并且您不希望内容在滚动中更改。

您需要做的就是,直接将监听器添加到滚动条:

myscrollbar.addMouseListener(new MouseAdapter() 

        @Override
        public void mouseEntered(MouseEvent e) 
            if(overScrollOffTimer != null) 
                overScrollOffTimer.stop();
                overScrollOffTimer = null;
            
            mymodel.setOverScrollbar(true);
        

        @Override
        public void mouseExited(MouseEvent e) 
            if(overScrollOffTimer == null) 
                overScrollOffTimer = new Timer(250,
                        overScrollOffListener);
                overScrollOffTimer.start();
            
        

        @Override
        public void mousePressed(MouseEvent e) 
            if(activeScrollOffTimer != null) 
                activeScrollOffTimer.stop();
                activeScrollOffTimer = null;
            
            mymodel.setBeingScrolled(true);
        

        @Override
        public void mouseReleased(MouseEvent e) 
            if(activeScrollOffTimer == null) 
                activeScrollOffTimer =
                    new Timer(250,
                              activeScrollOffListener);
                activeScrollOffTimer.start();
            
        
    );

在我的 mouseListener 中,我添加了 2 个计时器来启动 jPanel 内容的更改(250 毫秒后)(加上第三个计时器用于 jPanel 悬停)。如果没有计时器,当您从面板悬停到滚动条或返回时,内容可能会在视觉上打嗝。一个计时器从滚动条的 mouseExited 开始。另一个在鼠标释放滚动条旋钮时启动。我跟踪鼠标是否在滚动条上、移动滚动条以及鼠标是否在 jPanel 上。如果这些事情中的任何一个是真的,我就会展示我的大量内容。否则,如果他们都是假的,我会画我的小内容。

这是一个计时器的例子:

private javax.swing.Timer overScrollOffTimer;
ActionListener overScrollOffListener = new ActionListener() 
    @Override
    public void actionPerformed(ActionEvent evt) 
        if(evt.getSource() == overScrollOffTimer) 
            /* Stop timer */
            overScrollOffTimer.stop();
            overScrollOffTimer = null;

            mymodel.setOverScrollbar(false);
            mymodel.notifyObservers();
            revalidate();
            repaint();
        
    
;

private javax.swing.Timer activeScrollOffTimer;
ActionListener activeScrollOffListener = new ActionListener() 
    @Override
    public void actionPerformed(ActionEvent evt) 
        if (evt.getSource() == activeScrollOffTimer) 
            /* Stop timer */
            activeScrollOffTimer.stop();
            activeScrollOffTimer = null;

            mymodel.setBeingScrolled(false);
            mymodel.notifyObservers();
            revalidate();
            repaint();
        
    
;

我没有为 jPanel 包含计时器或鼠标侦听器,但在没有单击/释放方法的情况下,这是一个类似的尝试。

注意,我在模型中跟踪了悬停和滚动的状态,因为其他 jPanel 也会基于此悬停交互显示不同的内容,并且它们都可以访问模型。

顺便说一句,我使用了“OffTimer”、“OffListener”等术语,因为我基本上只在将鼠标悬停在一组面板上时显示真实内容。将鼠标悬停在这些面板中的任何一个基本上都会导致内容消失。我希望内容消失的原因是因为当您将鼠标悬停在内容上时内容会发生变化,并且我不希望用户被静止不动的内容所迷惑并导致他们做出不正确的视觉结论(例如,在 2 个面板中关联视觉对齐的数据其对齐方式会根据悬停位置而变化)。

【讨论】:

【参考方案2】:

为什么不将滚动窗格放在另一个 JPanel 中,并在该外部窗格上添加侦听器。那么移动到滚动条不会触发mouseExited事件;仅当您越过滚动条(退出外部面板)或在滚动面板之外以另一个方向移动时才会触发它。

【讨论】:

糟糕——我认为这行不通。我曾经使用 Motif 做过类似的事情,但那里的事件略有不同。

以上是关于如何将 mouseListener 添加到 jscrollbar?的主要内容,如果未能解决你的问题,请参考以下文章

除非与mouselistener一起使用,否则JLabel不会显示

repaint 导致 mouseListener 注册没有发生的点击

当在子组件中添加其他 MouseListener 时,父组件的 MouseListener 在子组件中不起作用

如何将 MouseListener 留在 ChildComponent 上但正确跟踪鼠标在父级上的进入和退出?

如何使用 mouselistener 访问一个组件而不是另一个组件

如何通过 WKWebVIew 或 JSC 在 iOS 应用程序中加载 WebAssembly