java 滚动到焦点文本字段

ao218c7q  于 2022-12-17  发布在  Java
关注(0)|答案(4)|浏览(162)

所以,我在滚动窗格中有一堆文本域。当用户聚焦从底部开始的最后一个时,会添加更多的文本域。我的问题是,我如何让滚动窗格滚动到聚焦的文本域?我的意思是,用户将按TAB或ENTER键跳转到下一个文本域,但如果不滚动,他将无法看到它。我可以模拟在最后一个文本字段有焦点时按下下下箭头或PageDown,但那会很难看,即使它会做我需要做的事情。
我试过这样的东西,从我发现通过搜索,但我不能使它工作。

public void focusGained(FocusEvent e) {
            currentview = t1;
            int cons = i - 1;
             Rectangle r = new Rectangle(t1.getX(), t1.getY(), 1, 1);
            jScrollPane1.scrollRectToVisible(r);
            if (t1.getName().equals("prod" + cons)) {

                newproduct();
            };

        }

字符串

ttygqcqt

ttygqcqt1#

请看FormScroller。它是一个简单的类,可以用来确保在使用Tab键切换到组件时组件是可见的。FormScroller可以与任何滚动窗格一起使用,并且不需要向表单上的每个组件添加FocusListener。
它提供了几个选项,允许您确实控制滚动的工作方式。

mzmfm0qo

mzmfm0qo2#

有两件事。
首先,JTextField#scrollRectToVisible被覆盖了,做了一些与其他组件略有不同的事情......很烦人......
其次,您需要转换字段相对于其父级的位置,然后使用父级的scrollRectToVisible方法,例如...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ScrollFocusedField {

    public static void main(String[] args) {
        new ScrollFocusedField();
    }

    public ScrollFocusedField() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                FocusAdapter fh = new FocusAdapter() {

                    @Override
                    public void focusGained(FocusEvent e) {
                        JComponent comp = (JComponent) e.getComponent();
                        System.out.println("FocusGained");
                        Rectangle bounds = comp.getBounds();
                        bounds.setLocation(SwingUtilities.convertPoint(comp, bounds.getLocation(), comp.getParent()));

                        JComponent parent = (JComponent) comp.getParent();
                        parent.scrollRectToVisible(comp.getBounds());
                    }

                };

                JPanel panel = new JPanel(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                for (int index = 0; index < 100; index++) {
                    gbc.fill = GridBagConstraints.NONE;
                    gbc.weightx = 0;
                    gbc.gridx = 0;
                    gbc.gridy = index;
                    panel.add(new JLabel(Integer.toString(index)), gbc);

                    JTextField field = new JTextField();
                    field.addFocusListener(fh);
                    gbc.fill = GridBagConstraints.HORIZONTAL;
                    gbc.weightx = 1;
                    gbc.gridx = 1;
                    panel.add(field, gbc);
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(panel));
                frame.setSize(200, 400);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}
30byixjq

30byixjq3#

我用一个自定义的焦点遍历策略解决了这个问题,它 Package 了容器的原始遍历策略,并在请求下一个或上一个组件时对滚动请求进行排队:

private static class FocusTraversalPolicyAdapter extends FocusTraversalPolicy {
    FocusTraversalPolicy focusTraversalPolicy;

    FocusTraversalPolicyAdapter(FocusTraversalPolicy focusTraversalPolicy) {
        this.focusTraversalPolicy = focusTraversalPolicy;
    }

    @Override
    public Component getComponentAfter(Container container, Component component) {
        var nextComponent = focusTraversalPolicy.getComponentAfter(container, component);

        scrollToVisible(nextComponent);

        return nextComponent;
    }

    @Override
    public Component getComponentBefore(Container container, Component component) {
        var previousComponent = focusTraversalPolicy.getComponentBefore(container, component);

        scrollToVisible(previousComponent);

        return previousComponent;
    }

    @Override
    public Component getFirstComponent(Container container) {
        return focusTraversalPolicy.getFirstComponent(container);
    }

    @Override
    public Component getLastComponent(Container container) {
        return focusTraversalPolicy.getLastComponent(container);
    }

    @Override
    public Component getDefaultComponent(Container container) {
        return focusTraversalPolicy.getDefaultComponent(container);
    }

    void scrollToVisible(Component component) {
        var parent = component.getParent();

        if (parent instanceof JComponent) {
            SwingUtilities.invokeLater(() -> {
                ((JComponent)parent).scrollRectToVisible(SwingUtilities.convertRectangle(parent, component.getBounds(), parent));
            });
        }
    }
}

请注意,这依赖于现有行为,理论上将来可能会中断。

2vuwiymt

2vuwiymt4#

根据我之前的回答,一个更简单也可能更可靠的方法是定义一个自定义键盘焦点处理程序,每当组件接收到输入焦点时,管理器就会调度事件并将组件滚动到视图中:

public class ScrollingKeyboardFocusManager extends DefaultKeyboardFocusManager {
    @Override
    public boolean dispatchEvent(AWTEvent event) {
        var dispatched = super.dispatchEvent(event);

        if (dispatched && event.getID() == FocusEvent.FOCUS_GAINED) {
            var component = (Component)event.getSource();
            var parent = component.getParent();

            if (parent instanceof JComponent) {
                ((JComponent)parent).scrollRectToVisible(SwingUtilities.convertRectangle(parent, component.getBounds(), parent));
            }
        }

        return dispatched;
    }
}

焦点管理器可按如下方式安装:

KeyboardFocusManager.setCurrentKeyboardFocusManager(new ScrollingKeyboardFocusManager());

相关问题