TITLE:JTextPaneを一行に制限してスタイル可能なJTextFieldとして使用する
#navi(../)
#tags(JTextPane, StyledDocument, JScrollPane, JTextField, KeyboardFocusManager, Focus, InputMap)
RIGHT:Posted by &author(aterai); at 2013-05-06
*JTextPaneを一行に制限してスタイル可能なJTextFieldとして使用する [#i94a5c71]
``JTextPane``の行数を一行のみに制限して、文字色などのスタイル付けが可能な``JTextField``として使用します。

-&jnlp;
-&jar;
-&zip;

//#screenshot
#ref(https://lh4.googleusercontent.com/-jckifA3Ym6c/UYZlsvWPTqI/AAAAAAAABrY/ERGHE6rtaPo/s800/OneLineTextPane.png)

**サンプルコード [#la6c46b8]
#code(link){{
JTextPane textPane = new JTextPane() {
  @Override public void scrollRectToVisible(Rectangle rect) {
    int r = getBorder().getBorderInsets(this).right;
    rect.grow(r, 0);
    super.scrollRectToVisible(rect);
  }
};
textPane.setEditorKit(new NoWrapEditorKit());
AbstractDocument doc = new SimpleSyntaxDocument();
textPane.setDocument(doc);
try {
  doc.insertString(0, text, null);
} catch(Exception ex) {
  ex.printStackTrace();
}
InputMap im = textPane.getInputMap(JComponent.WHEN_FOCUSED);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), new AbstractAction() {
  @Override public void actionPerformed(ActionEvent e) {
    // Do nothing
  }
});
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), new AbstractAction() {
  @Override public void actionPerformed(ActionEvent e) {
    // Do nothing
  }
});

// @see http://terai.xrea.jp/Swing/FocusTraversalKeys.html
Set<AWTKeyStroke> forwardKeys = new HashSet<AWTKeyStroke>(
    textPane.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
forwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
forwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_MASK));
textPane.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, forwardKeys);

JScrollPane scrollPane = new JScrollPane(
  textPane, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) {
  @Override public Dimension getMinimumSize() {
    return super.getPreferredSize();
  }
};
}}

**解説 [#fffdaf9e]
- ``JScrollPane``に追加
-- ``JScrollBar``を常に非表示にした、``JScrollPane``に``JTextPane``を追加
- JTextPaneの折り返しを無効化
-- %% [http://www.java2s.com/Code/Java/Swing-JFC/NonWrappingWrapTextPane.htm Non Wrapping(Wrap) TextPane : TextField « Swing JFC « Java]を参考に、``JTextPane#getScrollableTracksViewportWidth()``をオーバーライドして、折り返しを無効化%%
-- [[JEditorPaneで長い行を折り返さない>Swing/NoWrapTextPane]]の``ParagraphView``を使用して、折り返しを無効化
- 文字列の最後にある``Caret``が表示されないのを修正
-- ``JTextPane#scrollRectToVisible(Rectangle)``をオーバーライドして、余白までスクロールするように設定
-- メモ: [http://tips4java.wordpress.com/2009/01/25/no-wrap-text-pane/ No Wrap Text Pane ≪ Java Tips Weblog]のように、``CaretListener``を使用する方法もある
- 改行キーの無効化
-- ``JTextPane``から``InputMap``を取得して、``KeyEvent.VK_ENTER``をなにもしない``Action``で置き換える
-- ``Document#insertString(...)``をオーバーライドして、コピー・ペーストなどで張り込まれた文字列から、改行を空白に置換
- タブキーでフォーカス移動
-- [[FocusTraversalKeysに矢印キーを追加してフォーカス移動>Swing/FocusTraversalKeys]]
-- ``JTextPane``から``InputMap``を取得して、``KeyEvent.VK_TAB``をなにもしない``Action``で置き換え、``JTextPane#setFocusTraversalKeys(...)``で、タブキーでフォーカス移動するように設定
- 文字スタイルの変更
-- [http://www.discoverteenergy.com/files/SyntaxDocument.java SyntaxDocument.java]を使って、入力された``red``, ``green``, ``blue``の文字色を変更

**参考リンク [#ab80be9a]
- [[JEditorPaneで長い行を折り返さない>Swing/NoWrapTextPane]]
//- [http://www.java2s.com/Code/Java/Swing-JFC/NonWrappingWrapTextPane.htm Non Wrapping(Wrap) TextPane : TextField « Swing JFC « Java]
- [[FocusTraversalKeysに矢印キーを追加してフォーカス移動>Swing/FocusTraversalKeys]]

**コメント [#y0a07202]
- ``JTextField``では、"aaaaa|bbbbb"でカーソル``|``の位置に文字を追加していくと領域外にカーソルが移動した時点で``bbbbb``が表示されるようにスクロールするが、ここの``OneLineTextPane``では未対応。 -- [[aterai]] &new{2013-05-06 (月) 15:35:00};

#comment