JScrollPane 用箭头键滚动

Posted

技术标签:

【中文标题】JScrollPane 用箭头键滚动【英文标题】:JScrollPane scrolling with arrow keys 【发布时间】:2011-05-16 23:06:16 【问题描述】:

我在 JScrollPane 中有一个 JTextArea 组件,并且文本区域不可编辑。我想使用向上和向下箭头键启用文本区域的滚动(即按箭头键将文本区域滚动一行)。任何想法如何实现这一目标?

【问题讨论】:

我知道您已经接受了答案,但您并不总是需要编写自定义代码。查看我新添加的建议。 是的,通过结合两个答案的知识,可以很好地解决这类问题。不幸的是,不可能接受多个答案;( 【参考方案1】:

是的,键绑定是要走的路,但您并不总是需要创建自己的操作。 Swing 组件带有默认的操作,您可以经常重复使用。

有关这些操作的完整列表,请参阅 Key Bindings。

现在您知道了 Action 名称,您可以将其绑定到 keyStroke:

JScrollBar vertical = scrollPane.getVerticalScrollBar();
InputMap im = vertical.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke("DOWN"), "positiveUnitIncrement");
im.put(KeyStroke.getKeyStroke("UP"), "negativeUnitIncrement");

【讨论】:

谢谢,这个键绑定链接非常有用!预先存在的操作的重用使代码更易于维护。【参考方案2】:

如果 JTextArea 是不可编辑和不可聚焦的,它不会响应箭头键。我不确定是否有解决此问题的规范方法,但使其响应的一种方法是设置其键绑定以在 JTextArea 位于可聚焦窗口中时响应向上和向下键。一个例子如下:

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;
import javax.swing.text.JTextComponent;

@SuppressWarnings("serial")
public class TestScrollingArea extends JPanel 
    private static final String UP = "Up";
    private static final String DOWN = "Down";
    private JTextArea area = new JTextArea(20, 40);
    private JScrollPane scrollPane = new JScrollPane(area);

    public TestScrollingArea() 
        // make textarea non-editable and non-focusable
        area.setEditable(false);
        area.setFocusable(false);
        area.setWrapStyleWord(true);
        area.setLineWrap(true);
        add(scrollPane);

        // fill area with letters
        for (int i = 0; i < 10; i++) 
            for (int j = 0; j < 100; j++) 
                area.append("abcdefg ");
            
        

        // have JTextArea tell us how tall a line of text is.
        int scrollableIncrement = area.getScrollableUnitIncrement(scrollPane.getVisibleRect(), 
                    SwingConstants.VERTICAL, 1);

        // add key bindings to the JTextArea 
        int condition = JTextComponent.WHEN_IN_FOCUSED_WINDOW;
        InputMap inMap = area.getInputMap(condition);
        ActionMap actMap = area.getActionMap();

        inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), UP);
        inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), DOWN);
        actMap.put(UP, new UpDownAction(UP, scrollPane.getVerticalScrollBar().getModel(), 
                    scrollableIncrement));
        actMap.put(DOWN, new UpDownAction(DOWN, scrollPane.getVerticalScrollBar().getModel(), 
                    scrollableIncrement));

    

    // Action for our key binding to perform when bound event occurs
    private class UpDownAction extends AbstractAction 
        private BoundedRangeModel vScrollBarModel;
        private int scrollableIncrement;
        public UpDownAction(String name, BoundedRangeModel model, int scrollableIncrement) 
            super(name);
            this.vScrollBarModel = model;
            this.scrollableIncrement = scrollableIncrement;
        

        @Override
        public void actionPerformed(ActionEvent ae) 
            String name = getValue(AbstractAction.NAME).toString();
            int value = vScrollBarModel.getValue();
            if (name.equals(UP)) 
                value -= scrollableIncrement;
                vScrollBarModel.setValue(value);
             else if (name.equals(DOWN)) 
                value += scrollableIncrement;
                vScrollBarModel.setValue(value);
            
        
    

    private static void createAndShowUI() 
        JFrame frame = new JFrame("TestScrollingArea");
        frame.getContentPane().add(new TestScrollingArea());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    

    public static void main(String[] args) 
        java.awt.EventQueue.invokeLater(new Runnable() 
            public void run() 
                createAndShowUI();
            
        );
    

【讨论】:

太棒了!一个小问题是 pageup/pagedown 键不起作用。我通过将文本区域设置为可聚焦并使用 WHEN_FOCUSED 而不是 WHEN_IN_FOCUSED_WINDOW 的输入映射来使其工作。非常感谢! 或者向上翻页和向下翻页可以添加为与上面相同的键绑定,除了增加/减少量将是视口高度。 您并不总是需要创建自定义操作。请参阅我的建议。【参考方案3】:

您应该将 KeyListener 添加到您的 JScrollPane。

【讨论】:

在这种情况下,使用键绑定几乎总是比使用键监听器更好。【参考方案4】:

刚遇到这个问题,虽然答案有助于我朝着正确的方向前进,但从那时起,解决方案的某些部分可能已经发生了变化。它对我有用,他进行了以下更改: - 必须更改 JScrollPane 实例的 InputMap - actionMapKeys 必须是:“unitScrollX”和/或“scrollX”(X= 下、上、左、右)。它们驻留在 BasicScrollPaneUI 中。

【讨论】:

以上是关于JScrollPane 用箭头键滚动的主要内容,如果未能解决你的问题,请参考以下文章

使用箭头键滚动的 Tkinter 列表框

到达最后一张幻灯片时,使用键盘左箭头键不应向左滚动

如何在 Kirigami ScrollablePage 中使用箭头键滚动?

检测 JavaScript 中的箭头键按下

SwiftUI macOS 在 TextField 处于活动状态时使用箭头键滚动列表

DIV滚动条啥设置滑块的大小及滑道的宽度?