2016-08-19 9 views
1

enter image description here중첩 된 JScrollPanes를 올바르게 작동시키는 방법은 무엇입니까? 이미지에서 볼 수 있듯이

, 커서가 B 위에있을 때 내가, 내가이 달성하고자하는 어떤이 JScrollPane의, A와 B가 있고, 마우스 휠 스크롤 :

1)의 경우를 B 스크롤 가능한 컨텐츠를 가지고, 단지 스크롤 B. B가 이미 끝으로 스크롤, 또는 B가 스크롤 아니라 거의 내용, 스크롤 A.이있는 경우

2

) 이제 어떻게 무엇

마우스 휠 이벤트가 무엇에 상관없이 항상 B에 의해 소비되므로 A는 결코 스크롤 될 수 없습니다. 어떤 충고? 미리 감사드립니다. 여기

+0

이 (가)를 통지하는 B의 기본 수신기를 구현하고; 당신은 우선 순위에 관한 조건을 만들 수 있습니다. (B가 끝나면 ...) – whyn0t

답변

4

JLayer를 사용하여 하나의 가능한 구현이다

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.plaf.LayerUI; 
import javax.swing.table.*; 
import javax.swing.text.*; 

public class WheelOverNestedScrollPaneTest { 
    private static final String TEXT = "aaa\na\na\na\na\naaaa\na\na\na\naaaa\n"; 

    private JComponent makeUI() { 
    JTextArea textArea = new JTextArea(TEXT + TEXT + TEXT); 
    JTable table = new JTable(50, 3); 
    JTree tree = new JTree(); 
    tree.setVisibleRowCount(5); 

    JTextPane textPane = new JTextPane(); 
    textPane.setEditable(false); 
    textPane.setMargin(new Insets(5, 10, 5, 5)); 
    Document doc = textPane.getDocument(); 
    try { 
     doc.insertString(doc.getLength(), TEXT, null); 
     textPane.insertComponent(createChildScrollPane(textArea)); 
     doc.insertString(doc.getLength(), "\n", null); 
     doc.insertString(doc.getLength(), TEXT, null); 
     textPane.insertComponent(createChildScrollPane(table)); 
     doc.insertString(doc.getLength(), "\n", null); 
     doc.insertString(doc.getLength(), TEXT, null); 
     textPane.insertComponent(new JScrollPane(tree)); 
     doc.insertString(doc.getLength(), "\n", null); 
     doc.insertString(doc.getLength(), TEXT, null); 
    } catch (BadLocationException ex) { 
     ex.printStackTrace(); 
    } 
    return new JLayer<JScrollPane>(
     new JScrollPane(textPane), new WheelScrollLayerUI()); 
    } 
    protected static JScrollPane createChildScrollPane(Component view) { 
    return new JScrollPane(view) { 
     @Override public Dimension getPreferredSize() { 
     Dimension d = super.getPreferredSize(); 
     d.height = 120; 
     return d; 
     } 
    }; 
    } 
    public static void main(String... args) { 
    EventQueue.invokeLater(() -> { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new WheelOverNestedScrollPaneTest().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    }); 
    } 
} 

// http://java-swing-tips.blogspot.jp/2014/09/forward-mouse-wheel-scroll-event-in.html 
class WheelScrollLayerUI extends LayerUI<JScrollPane> { 
    @Override public void installUI(JComponent c) { 
    super.installUI(c); 
    if (c instanceof JLayer) { 
     ((JLayer) c).setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK); 
    } 
    } 
    @Override public void uninstallUI(JComponent c) { 
    if (c instanceof JLayer) { 
     ((JLayer) c).setLayerEventMask(0); 
    } 
    super.uninstallUI(c); 
    } 
    @Override protected void processMouseWheelEvent(
     MouseWheelEvent e, JLayer<? extends JScrollPane> l) { 
    Component c = e.getComponent(); 
    int dir = e.getWheelRotation(); 
    JScrollPane main = l.getView(); 
    if (c instanceof JScrollPane && !c.equals(main)) { 
     JScrollPane child = (JScrollPane) c; 
     BoundedRangeModel m = child.getVerticalScrollBar().getModel(); 
     int extent = m.getExtent(); 
     int minimum = m.getMinimum(); 
     int maximum = m.getMaximum(); 
     int value = m.getValue(); 
     if (value + extent >= maximum && dir > 0 || value <= minimum && dir < 0) { 
     main.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, main)); 
     } 
    } 
    } 
} 
+0

당신의 손가락은 어떨까요? 매우 관대합니다. 완전한 존경의 친구 나는 그다지 할 수 있었으면 좋겠다. (시간당 50 줄 이상의 코드를 작성하기에는 너무 게으름)/ – whyn0t

+0

완벽하게 작동한다. 정말 고마워! –

+0

에는 java 8이 필요합니다. / – whyn0t