Swing/HorizontalVisibility の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/HorizontalVisibility へ行く。
- Swing/HorizontalVisibility の差分を削除
--- category: swing folder: HorizontalVisibility title: JTextFieldの表示領域をJScrollBarでスクロールする tags: [JTextField, JScrollBar, BoundedRangeModel] author: aterai pubdate: 2014-05-12T00:05:11+09:00 description: JTextFieldの表示領域をJScrollBarでスクロール可能にします。 image: https://lh3.googleusercontent.com/-e-5Z2Ze6fmU/U4Q5K7nrzqI/AAAAAAAACGQ/9vdUHpxI2VA/s800/HorizontalVisibility.png hreflang: href: https://java-swing-tips.blogspot.com/2015/04/scrollbar-for-jtextfield.html lang: en --- * 概要 [#summary] `JTextField`の表示領域を`JScrollBar`でスクロール可能にします。 #download(https://lh3.googleusercontent.com/-e-5Z2Ze6fmU/U4Q5K7nrzqI/AAAAAAAACGQ/9vdUHpxI2VA/s800/HorizontalVisibility.png) * サンプルコード [#sourcecode] #code(link){{ scroller.setModel(textField.getHorizontalVisibility()); }} * 解説 [#explanation] 上記のサンプルでは、`JTextField#getHorizontalVisibility()`で取得した`BoundedRangeModel`(可視領域のモデル)を`JScrollBar`に設定することで、これを使用したスクロールや現在の可視領域の位置、幅の表示などが可能になっています。 - `JScrollPane + VERTICAL_SCROLLBAR_NEVER` -- `JTextField`をスクロールバーを常に非表示に設定した`JScrollPane`に追加 - `BoundedRangeModel: textField.getHorizontalVisibility()` -- `JTextField`と水平スクロールバー`JScrollBar(Adjustable.HORIZONTAL)`を別々に配置 -- `JTextField#getHorizontalVisibility()`で`BoundedRangeModel`を取得し、これを`JScrollBar#setModel(...)`で設定して二つを同期する - `BoundedRangeModel+textField.ArrowButtonlessScrollBarUI` -- 上の`JScrollBar`に矢印ボタンなどを非表示化、ノブの半透明化などを行う`ScrollBarUI`を設定 -- 上の`JScrollBar`に矢印ボタンなどを非表示化とノブの半透明化などを行う`ScrollBarUI`を設定 ---- - `setCaretPosition: 0`: `JTextField#setCaretPosition(0);`は`JTextField`にフォーカスが無い場合無効? -- `JScrollBar`が同期しない場合がある - `setScrollOffset: 0`: `JScrollBar`のノブがマウスドラッグに反応しなくなる場合がある? - ノブの表示: 文字列をすべて削除するなどしても、ノブが非表示にならない -- `1px`の余白?、以下のようなリスナーで回避するテストを追加 #code{{ class EmptyThumbHandler extends ComponentAdapter implements DocumentListener { private final BoundedRangeModel emptyThumbModel = new DefaultBoundedRangeModel(0, 1, 0, 1); private final JTextField textField; private final JScrollBar scroller; public EmptyThumbHandler(JTextField textField, JScrollBar scroller) { super(); this.textField = textField; this.scroller = scroller; } private void changeThumbModel() { EventQueue.invokeLater(new Runnable() { @Override public void run() { BoundedRangeModel m = textField.getHorizontalVisibility(); int iv = m.getMaximum() - m.getMinimum() - m.getExtent() - 1; //-1:bug? if (iv <= 0) { scroller.setModel(emptyThumbModel); } else { scroller.setModel(textField.getHorizontalVisibility()); } } }); } @Override public void componentResized(ComponentEvent e) { changeThumbModel(); } @Override public void insertUpdate(DocumentEvent e) { changeThumbModel(); } @Override public void removeUpdate(DocumentEvent e) { changeThumbModel(); } @Override public void changedUpdate(DocumentEvent e) { changeThumbModel(); } } }} ---- - 以下は、サイズ`0`の`ArrowButton`を使用する`ScrollBarUI`を設定する方法 #code{{ class ArrowButtonlessScrollBarUI extends BasicScrollBarUI { private static final Color DEFAULT_COLOR = new Color(220, 100, 100, 100); private static final Color DRAGGING_COLOR = new Color(200, 100, 100, 100); private static final Color ROLLOVER_COLOR = new Color(255, 120, 100, 100); @Override protected JButton createDecreaseButton(int orientation) { return new ZeroSizeButton(); } @Override protected JButton createIncreaseButton(int orientation) { return new ZeroSizeButton(); } @Override protected void paintTrack(Graphics g, JComponent c, Rectangle r) { // Graphics2D g2 = (Graphics2D) g.create(); // g2.setPaint(new Color(100, 100, 100, 100)); // g2.fillRect(r.x, r.y, r.width - 1, r.height - 1); // g2.dispose(); } @Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) { JScrollBar sb = (JScrollBar) c; if (!sb.isEnabled()) { return; } BoundedRangeModel m = sb.getModel(); int iv = m.getMaximum() - m.getMinimum() - m.getExtent() - 1; //-1:bug? if (iv > 0) { Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Color color; if (isDragging) { color = DRAGGING_COLOR; } else if (isThumbRollover()) { color = ROLLOVER_COLOR; } else { color = DEFAULT_COLOR; } g2.setPaint(color); g2.fillRect(r.x, r.y, r.width - 1, r.height - 1); g2.dispose(); } } } }} ---- - `JScrollPane scroll = new JScrollPane(new JTextField(TEXT), ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);` -- 縦スクロールバーを非表示にした`JScrollPane`を使用する場合、`JTextField`内の文字列選択でスクロールしない -- 文字列を適当な長さまで削除するとノブが非表示になる * 参考リンク [#reference] - [https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JTextField.html#getHorizontalVisibility-- JTextField#getHorizontalVisibility() (Java Platform SE 8)] * コメント [#comment] #comment - 可視領域の幅の表示を考えると`ArrowButton`は不要なので、[[JScrollBarを半透明にする>Swing/TranslucentScrollBar]]のような外見の`JScrollBar`を使用した方が良いかもしれない。 -- &user(aterai); &new{2014-05-14 (水) 16:05:32}; - サンプルの追加と、スクリーンショットの更新。 -- &user(aterai); &new{2014-05-27 (火) 16:12:38}; #comment