JScrollPane 内に JTextArea コンポーネントがありますが、テキスト領域は編集できません。上下の矢印キーを使用してテキスト領域をスクロールできるようにしたいと考えています (つまり、矢印キーを押すと、テキスト領域が 1 行スクロールされます)。これを達成する方法はありますか?
5 に答える
はい、キー バインディングが最適ですが、常に独自のアクションを作成する必要はありません。Swing コンポーネントには、頻繁に再利用できるデフォルトのアクションが付属しています。
これらのアクションの完全なリストについては、キー バインドを参照してください。
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");
JTextArea が編集不可かつフォーカス不可の場合、矢印キーに反応しません。これを回避する標準的な方法があるかどうかはわかりませんが、応答させる 1 つの方法は、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();
}
});
}
}
この問題に遭遇したばかりで、答えは私を正しい方向に導くのに役立ちましたが、それ以来、解決策の一部が変更されている可能性があります。次の変更でうまくいきました:-変更する必要があったのはJScrollPaneインスタンスのInputMapでした-actionMapKeysは「unitScrollX」および/または「scrollX」(X = Down、Up、Left、Right)である必要がありました。それらは BasicScrollPaneUI にあります。
JScrollPane に KeyListener を追加する必要があります。