JScrollPane scrolling with arrow keys

时间秒杀一切 提交于 2019-12-18 11:32:01

问题


I've a JTextArea component inside JScrollPane and the text area is not editable. I would like to enable scrolling of the text area with up and down arrow keys (i.e. pressing the arrow keys will scroll the text area by one line). Any ideas how to achieve this?


回答1:


Yes Key Bindings is the way to go, but you don't always need to create your own actions. Swing components come with default Actions that you can often reuse.

See Key Bindings for a complete list of these Actions.

Now that you know the Action name you can just bind it to a 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:


If the JTextArea is non-editable and non-focuseable, it will not respond to the arrow keys. I'm not sure if there is a canonical way to get around this, but one way to make it respond is to set its key binding to respond to the up and down keys when the JTextArea is in the focusable window. An example of this is as follows:

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();
            }
        });
    }
}



回答3:


You should add KeyListener to your JScrollPane.




回答4:


Just came across this problem and while the answers was useful in driving me to the right direction some bits of the solution may have changed since then. It worked for me with he following changes: - it was the InputMap of JScrollPane instance that had to be changed - actionMapKeys had to be: "unitScrollX" and/or "scrollX" (X= Down, Up, Left, Right). They reside in BasicScrollPaneUI.



来源:https://stackoverflow.com/questions/4298582/jscrollpane-scrolling-with-arrow-keys

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!