• category: swing folder: InsertTabIntoTextField title: JTextFieldにタブ文字を挿入する tags: [JTextField, PlainDocument] author: aterai pubdate: 2023-04-10T00:02:08+09:00 description: JTextFieldにキー入力でタブ文字を挿入したり、タブサイズを変更します。 image: https://drive.google.com/uc?id=1ov_4TMnJZUMXHOo_GqC9TRDNHhCTOMNf

概要

JTextFieldにキー入力でタブ文字を挿入したり、タブサイズを変更します。

サンプルコード

String txt2 = "aaa\tbbb\tccc";
JTextField field1 = new JTextField(txt2, 20);
initActionInputMap(field1);

int tabSize = 4;
Document doc = new PlainDocument();
doc.putProperty(PlainDocument.tabSizeAttribute, tabSize);
JTextField field2 = new JTextField(doc, txt2, 20);
initActionInputMap(field2);

SpinnerNumberModel model = new SpinnerNumberModel(tabSize, -2, 12, 1);
model.addChangeListener(e -> setTabSize(field2, model.getNumber().intValue()));
JSpinner spinner = new JSpinner(model);

// ...
private static void initActionInputMap(JTextComponent editor) {
  String mapKey = "insert-horizontal-tab";
  editor.getActionMap().put(mapKey, new AbstractAction() {
    @Override public void actionPerformed(ActionEvent e) {
      try {
        editor.getDocument().insertString(
            editor.getCaretPosition(), "\t", null);
      } catch (BadLocationException ex) {
        UIManager.getLookAndFeel().provideErrorFeedback(editor);
      }
    }
  });
  KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_DOWN_MASK);
  editor.getInputMap(WHEN_FOCUSED).put(keyStroke, mapKey);
}
View in GitHub: Java, Kotlin

解説

  • JTextField: 上
    • キャレット位置にタブ文字0x09を挿入するActionJTextFieldActionMapに追加
    • JTextFieldTabキーにはフォーカス移動が設定されているので、Ctrl+Iキーで上記のタブ文字挿入アクションを実行するようInputMapを設定
    • JTextFieldなどに使用されるPlainDocumentのデフォルトタブサイズは8
  • JTextField: 下
    • Document#putProperty(PlainDocument.tabSizeAttribute, 4)でタブサイズを4に変更し、これを初期モデルとしてJTextField(Document, String, int)JTextFieldを生成
    • JSpinnerでタブサイズを変更可能に設定
      • タブサイズに負の値を設定してもエラーなどは発生しないが描画はおかしくなる
      • コンストラクタでタブサイズを変更したドキュメントを指定するのではなく、JTextField#getDocument()でドキュメントを取得してタブサイズを変更する場合はJTextArea#setTabSize(...)メソッドのようにBasicTextUI#modelChanged()を実行してタブサイズのキャッシュを更新する必要がある
      • JTextFieldにはsetTabSize(...)メソッドは存在しないので、このサンプルでは代わりにJTextField#setEditable(false);JTextField#setEditable(true);、またはJTextField#firePropertyChange("font", 0, 1);でフォント属性のダミー更新などを実行してBasicTextUI#modelChanged()を呼び出している
Document doc = editor.getDocument();
if (doc != null) {
  doc.putProperty(PlainDocument.tabSizeAttribute, size);
  // int old = getTabSize(doc);
  // firePropertyChange("tabSize", old, size);
  //     BasicTextUI#modelChanged();
  editor.setEditable(false);
  editor.setEditable(true);
  // or: editor.firePropertyChange("font", 0, 1);
}

参考リンク

コメント