Swing/TextFieldCaretScrollSapn の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/TextFieldCaretScrollSapn へ行く。
- Swing/TextFieldCaretScrollSapn の差分を削除
--- category: swing folder: TextFieldCaretScrollSapn title: JTextFieldでキー入力による水平スクロールのスパンを変更する title: JTextFieldでカーソルキーによる水平スクロールのスパンを変更する tags: [JTextField, Caret, LookAndFeel] author: aterai pubdate: 2025-01-06T01:05:24+09:00 description: JTextFieldへのカーソルキー入力で水平スクロールが発生する場合のスクロールスパンを変更します。 image: https://drive.google.com/uc?id=1tdPGBll2KYlWEut4sUdnNRs43VwGgBU5 --- * Summary [#summary] `JTextField`へのカーソルキー入力で水平スクロールが発生する場合のスクロールスパンを変更します。 #download(https://drive.google.com/uc?id=1tdPGBll2KYlWEut4sUdnNRs43VwGgBU5) * Source Code Examples [#sourcecode] #code(link){{ // @see WindowsTextFieldUI.WindowsFieldCaret class HorizontalScrollCaret extends DefaultCaret { @Override protected void adjustVisibility(Rectangle r) { EventQueue.invokeLater(() -> { JTextComponent c = getComponent(); if (c instanceof JTextField) { horizontalScroll((JTextField) c, r); } }); } private void horizontalScroll(JTextField field, Rectangle r) { TextUI ui = field.getUI(); int dot = getDot(); Position.Bias bias = Position.Bias.Forward; Rectangle startRect = null; try { startRect = ui.modelToView(field, dot, bias); } catch (BadLocationException ble) { UIManager.getLookAndFeel().provideErrorFeedback(field); } Insets i = field.getInsets(); BoundedRangeModel vis = field.getHorizontalVisibility(); int x = r.x + vis.getValue() - i.left; int n = 8; int span = vis.getExtent() / n; if (r.x < i.left) { vis.setValue(x - span); } else if (r.x + r.width > i.left + vis.getExtent()) { vis.setValue(x - (n - 1) * span); } if (startRect != null) { try { Rectangle endRect = ui.modelToView(field, dot, bias); if (endRect != null && !endRect.equals(startRect)) { damage(endRect); } } catch (BadLocationException ble) { UIManager.getLookAndFeel().provideErrorFeedback(field); } } } } }} * Explanation [#explanation] - `LookAndFeel Default` -- デフォルトの`JTextField`では現在の`LookAndFeel`が使用する`Caret`に依存してカーソルキー入力による水平スクロールスパン(移動量)が決まる -- `MetalLookAndFeel`や`NimbusLookAndFeel`の場合、`DefaultCaret`が`JTextComponent#scrollRectToVisible(...)`を使用して`1`文字分ずつ滑らかにスクロールする -- `WindowsTextFieldUI`の場合、`WindowsTextFieldUI.WindowsFieldCaret`が同様に`JTextComponent#scrollRectToVisible(...)`を使用してスクロールするが、その移動量は`JTextField`に設定された`BoundedRangeModel`のエクステント(`JTextField`の表示可能なサイズ)の`1/4`(`int quarterSpan = vis.getExtent() / 4;`)ずつのスパンでジャンプ・スクロールになる - `DefaultCaret` -- `WindowsLookAndFeel`でも`1`文字分ずつスクロールするよう`JTextField`に`DefaultCaret`を設定 - `override DefaultCaret#adjustVisibility(...)` -- [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/text/DefaultCaret.html#adjustVisibility-java.awt.Rectangle- DefaultCaret#adjustVisibility(Rectangle)]をオーバーライドしてエクステントの`1/8`ずつのスパンでジャンプ・スクロールする`Caret`を作成し、`JTextField`に設定 * Reference [#reference] - [[JTextFieldの表示領域をJScrollBarでスクロールする>Swing/HorizontalVisibility]] - [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/text/DefaultCaret.html#adjustVisibility-java.awt.Rectangle- DefaultCaret#adjustVisibility(Rectangle) (Java Platform SE 8 )] * Comment [#comment] #comment #comment