JScrollPane прокрутка с помощью клавиш со стрелками - PullRequest
11 голосов
/ 28 ноября 2010

Внутри JScrollPane есть компонент JTextArea, и текстовая область не редактируется.Я хотел бы включить прокрутку текстовой области с помощью клавиш со стрелками вверх и вниз (т.е. нажатие клавиш со стрелками приведет к прокрутке текстовой области на одну строку).Есть идеи как этого добиться?

Ответы [ 4 ]

13 голосов
/ 29 ноября 2010

Да, связывание ключей - это путь, но вам не всегда нужно создавать свои собственные действия. Компоненты Swing поставляются с Действиями по умолчанию, которые вы часто можете использовать повторно.

См. Привязки клавиш для получения полного списка этих действий.

Теперь, когда вы знаете имя действия, вы можете просто привязать его к нажатию клавиши:

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");
6 голосов
/ 28 ноября 2010

Если 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();
            }
        });
    }
}
0 голосов
/ 06 января 2017

Только что натолкнулся на эту проблему, и хотя ответы были полезны для того, чтобы направить меня в правильном направлении, некоторые части решения, возможно, изменились с тех пор.Он работал для меня со следующими изменениями: - это должен был быть изменен InputMap экземпляра JScrollPane - actionMapKeys должен был быть: «unitScrollX» и / или «scrollX» (X = Down, Up, Left, Right).Они находятся в BasicScrollPaneUI.

0 голосов
/ 28 ноября 2010

Вы должны добавить KeyListener в JScrollPane.

...