如何使JScrollPane滚动以跟随输入焦点? [英] How do I make JScrollPane scroll to follow input focus?

查看:118
本文介绍了如何使JScrollPane滚动以跟随输入焦点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有大面板的Swing应用程序,它包含在 JScrollPane 中。用户通常通过Tab键在面板的子组件之间移动,因此当他们选择查看某些内容时,我希望滚动窗格自动滚动,以便具有输入焦点的组件始终可见。

I have a Swing app with a large panel which is wrapped in a JScrollPane. Users normally move between the panel's subcomponents by tabbing, so when they tab to something out view, I want the scroll pane to autoscroll so the component with input focus is always visible.

我尝试过使用 KeyboardFocusManager 侦听输入焦点更改,然后调用 scrollRectToVisible

I've tried using KeyboardFocusManager to listen for input focus changes, and then calling scrollRectToVisible.

这是一个显示我当前策略的 SSCCE (只需复制/粘贴并运行!):

Here's an SSCCE displaying my current strategy (just copy/paste and run!):

import java.awt.KeyboardFocusManager;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;

public class FollowFocus {

  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

      public void run() {
        final int ROWS = 100;
        final JPanel content = new JPanel();
        content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
        content.add(new JLabel(
          "Thanks for helping out. Use tab to move around."));
        for (int i = 0; i < ROWS; i++) {
          JTextField field = new JTextField("" + i);
          field.setName("field#" + i);
          content.add(field);
        }

        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                            .addPropertyChangeListener("focusOwner", 
                     new PropertyChangeListener() {

          @Override
          public void propertyChange(PropertyChangeEvent evt) {
            if (!(evt.getNewValue() instanceof JComponent)) {
              return;
            }
            JComponent focused = (JComponent) evt.getNewValue();
            if (content.isAncestorOf(focused)) {
              System.out.println("Scrolling to " + focused.getName());
              focused.scrollRectToVisible(focused.getBounds());
            }
          }
        });

        JFrame window = new JFrame("Follow focus");
        window.setContentPane(new JScrollPane(content));
        window.setSize(200, 200);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setVisible(true);
      }
    });
  }
}

如果你运行这个例子,你会注意到它效果不好。它确实获得焦点更改通知,但对 scrollRectToVisible 的调用似乎没有任何效果。在我的应用程序中(这里显示起来太复杂了), scrollRectToVisible 大约有一半的时间我选中了视口之外的东西。

If you run this example, you'll notice it doesn't work very well. It does get the focus change notifications, but the call to scrollRectToVisible doesn't appear to have any effect. In my app (which is too complex to show here), scrollRectToVisible works about half the time when I tab into something outside of the viewport.

有没有一种既定方法可以解决这个问题?如果它有所不同,Swing应用程序是基于Netbeans RCP(我们的大多数客户运行Windows)。

Is there an established way to solve this problem? If it makes any difference, the Swing app is built on Netbeans RCP (and most of our customers run Windows).

推荐答案

我的评论另一个答案:


组件本身的scrollRectToVisible是
方法的全部点;-)它已经过去了找到
滚动的父级之前的层次结构

scrollRectToVisible on the component itself is the whole point of that method ;-) It's passed up the hierarchy until a parent doing the scroll is found

...除非组件本身处理它 - 作为JTextField确实:它实现了水平滚动以使插入符号可见。解决方法是在该字段的父级上调用该方法。

... except when the component itself handles it - as JTextField does: it's implemented to scroll horizontally to make the caret visible. The way out is to call the method on the field's parent.

编辑

为了清楚起见,替换的行是

just for clarity, the replaced line is

    content.scrollRectToVisible(focused.getBounds());

这篇关于如何使JScrollPane滚动以跟随输入焦点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆