JTextPane prevents scrolling in the parent JScrollPane

前端 未结 4 490
温柔的废话
温柔的废话 2021-01-06 00:49

I have the following \"tree\" of objects:

JPanel
    JScrollPane
        JPanel
            JPanel
                JScrollPane
                    JTextPane
         


        
4条回答
  •  南笙
    南笙 (楼主)
    2021-01-06 01:13

    Inspired by the existing answers, I

    • took the code from Nemi's answer
    • combined it with kleopatra's answer to a similar question to avoid constructing the MouseWheelEvent verbosely
    • extracted the listener into its own top-level class so that it can be used in contexts where the JScrollPane class cannot be extended
    • inlined the code as far as possible.

    The result is this piece of code:

    import java.awt.Component;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseWheelEvent;
    import java.awt.event.MouseWheelListener;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    
    /**
     * Passes mouse wheel events to the parent component if this component
     * cannot scroll further in the given direction.
     * 

    * This behavior is a little better than Swing's default behavior but * still worse than the behavior of Google Chrome, which remembers the * currently scrolling component and sticks to it until a timeout happens. * * @see Stack Overflow */ public final class MouseWheelScrollListener implements MouseWheelListener { private final JScrollPane pane; private int previousValue; public MouseWheelScrollListener(JScrollPane pane) { this.pane = pane; previousValue = pane.getVerticalScrollBar().getValue(); } public void mouseWheelMoved(MouseWheelEvent e) { Component parent = pane.getParent(); while (!(parent instanceof JScrollPane)) { if (parent == null) { return; } parent = parent.getParent(); } JScrollBar bar = pane.getVerticalScrollBar(); int limit = e.getWheelRotation() < 0 ? 0 : bar.getMaximum() - bar.getVisibleAmount(); if (previousValue == limit && bar.getValue() == limit) { parent.dispatchEvent(SwingUtilities.convertMouseEvent(pane, e, parent)); } previousValue = bar.getValue(); } }

    It is used like this:

    JScrollPane pane = new JScrollPane();
    pane.addMouseWheelListener(new MouseWheelScrollListener(pane));
    

    Once an instance of this class is created and bound to a scroll pane, it cannot be reused for another component since it remembers the previous position of the vertical scroll bar.

提交回复
热议问题