Прокрутка JPanel при наведении курсора мыши на JTable

У меня JTable внутри JPanel. Я могу прокручивать JPanel вверх и вниз с помощью колеса прокрутки мыши, но когда моя мышь зависает над JTable, мне приходится переместить ее из таблицы, чтобы прокрутить вверх JPanel с помощью колеса прокрутки. Есть ли способ прокрутки JPanel вверх и вниз с помощью колеса прокрутки, если мышь находится над JTable?


person BJ Dela Cruz    schedule 07.06.2012    source источник
comment
Я только что реализовал описанный вами случай, но я могу прокрутить событие JPanel, если указатель мыши находится на JTable. Вы можете опубликовать SSCCE?   -  person Xeon    schedule 07.06.2012
comment
Но в основном вы можете пересылать событие прокрутки колеса (MouseWheelListener) на свой JPanel JScrollPane   -  person Xeon    schedule 07.06.2012
comment
или (может быть масштабируемым), чтобы потреблять события, исходящие от :-), для лучшей помощи скорее публикуйте SSCCE   -  person mKorbel    schedule 07.06.2012
comment
Лучше объясните здесь (если корневая проблема не в вызвано JTable, но ошибкой Swing). Может дубликат.   -  person Juan Calero    schedule 17.10.2013


Ответы (2)


Я воспользовался советом Xeon в комментарии выше и реализовал слушатель колеса мыши, который перенаправляет события колеса мыши родительскому компоненту. См. Код ниже.

public class CustomMouseWheelListener implements MouseWheelListener {

  private JScrollBar bar;
  private int previousValue = 0;
  private JScrollPane parentScrollPane;
  private JScrollPane customScrollPane;

  /** @return The parent scroll pane, or null if there is no parent. */
  private JScrollPane getParentScrollPane() {
    if (this.parentScrollPane == null) {
      Component parent = this.customScrollPane.getParent();
      while (!(parent instanceof JScrollPane) && parent != null) {
        parent = parent.getParent();
      }
      this.parentScrollPane = (JScrollPane) parent;
    }
    return this.parentScrollPane;
  }

  /**
   * Creates a new CustomMouseWheelListener.
   * @param customScrollPane The scroll pane to which this listener belongs.
   */
  public CustomMouseWheelListener(JScrollPane customScrollPane) {
    ValidationUtils.checkNull(customScrollPane);
    this.customScrollPane = customScrollPane;
    this.bar = this.customScrollPane.getVerticalScrollBar();
  }

  /** {@inheritDoc} */
  @Override
  public void mouseWheelMoved(MouseWheelEvent event) {
    JScrollPane parent = getParentScrollPane();
    if (parent != null) {
      if (event.getWheelRotation() < 0) {
        if (this.bar.getValue() == 0 && this.previousValue == 0) {
          parent.dispatchEvent(cloneEvent(event));
        }
      }
      else {
        if (this.bar.getValue() == getMax() && this.previousValue == getMax()) {
          parent.dispatchEvent(cloneEvent(event));
        }
      }
      this.previousValue = this.bar.getValue();
    }
    else {
      this.customScrollPane.removeMouseWheelListener(this);
    }
  }

  /** @return The maximum value of the scrollbar. */
  private int getMax() {
    return this.bar.getMaximum() - this.bar.getVisibleAmount();
  }

  /**
   * Copies the given MouseWheelEvent.
   * 
   * @param event The MouseWheelEvent to copy.
   * @return A copy of the mouse wheel event.
   */
  private MouseWheelEvent cloneEvent(MouseWheelEvent event) {
    return new MouseWheelEvent(getParentScrollPane(), event.getID(), event.getWhen(),
        event.getModifiers(), 1, 1, event.getClickCount(), false, event.getScrollType(),
        event.getScrollAmount(), event.getWheelRotation());
  }

}
person BJ Dela Cruz    schedule 09.07.2012

Спасибо denshaotoko за то, что поделились своим кодом. Я реализовал решение в том же духе (пересылка событий), но поместил его непосредственно в панель прокрутки. Думал, что это может быть полезно другим.

/**
 * Scroll pane that only scrolls when it owns focus. When not owning focus (i.e. mouse
 * hover), propagates mouse wheel events to its container.
 * <p>
 * This is a solution for <i>"I have a JTable inside a JPanel. When my mouse is hovering
 * over the JTable, I have to move it out of the table to scroll the JPanel."</i>
 */
public class ScrollWhenFocusedPane extends JScrollPane {
    // Note: don't leave users with "scroll on focus" behaviour
    // on widgets that they cannot focus. These will be okay.
    public ScrollWhenFocusedPane (JTree view) {super (view);}
    public ScrollWhenFocusedPane (JList view) {super (view);}
    public ScrollWhenFocusedPane (JTable view) {super (view);}
    public ScrollWhenFocusedPane (JTextArea view) {super (view);}

    @Override
    protected void processMouseWheelEvent (MouseWheelEvent evt) {
        Component outerWidget = SwingUtilities.getAncestorOfClass (Component.class, this);

        // Case 1: we don't have focus, so we don't scroll
        Component innerWidget = getViewport().getView();
        if (!innerWidget.hasFocus())
            outerWidget.dispatchEvent(evt);

        // Case 2: we have focus
        else {
            JScrollBar innerBar = getVerticalScrollBar();
            if (!innerBar.isShowing()) // Deal with horizontally scrolling widgets
                innerBar = getHorizontalScrollBar();

            boolean wheelUp = evt.getWheelRotation() < 0;
            boolean atTop = (innerBar.getValue() == 0);
            boolean atBottom = (innerBar.getValue() == (innerBar.getMaximum() - innerBar.getVisibleAmount()));

            // Case 2.1: we've already scrolled as much as we could
            if ((wheelUp & atTop) || (!wheelUp & atBottom))
                outerWidget.dispatchEvent(evt);

            // Case 2.2: we'll scroll
            else
                super.processMouseWheelEvent (evt);
        }
    }
}
person space programmer    schedule 19.10.2012