我有一个带有大型面板的Swing应用程序,该应用程序包装在JScrollPane。用户通常通过按Tab键在面板的子组件之间移动,因此当他们按Tab键切换到某个视图时,我希望滚动窗格自动滚动,以便具有输入焦点的组件始终可见。
JScrollPane
我尝试使用KeyboardFocusManager侦听输入焦点更改,然后调用scrollRectToVisible。
KeyboardFocusManager
scrollRectToVisible
这是一个显示我当前策略的SSCCE(只需复制/粘贴并运行!):
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当我进入视口之外的内容时,其工作时间大约只有一半。
是否有解决此问题的既定方法?如果有任何不同,Swing应用程序将基于Netbeans RCP构建(我们的大多数客户都运行Windows)。
我对其他答案的评论:
该方法的重点在于组件本身上的scrollRectToVisible ;-)它沿层次结构向上传递,直到找到进行滚动的父级为止
…除非组件本身对其进行处理-就像JTextField一样:实现了水平滚动以使插入符号可见。出路是在字段的父级上调用方法。
编辑
为了清楚起见,替换的行是
content.scrollRectToVisible(focused.getBounds());