Swing/LineWrapToolTip のバックアップ(No.2)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- Swing/LineWrapToolTip へ行く。
- 1 (2024-12-23 (月) 01:05:36)
- 2 (2024-12-23 (月) 14:24:02)
- 3 (2024-12-23 (月) 17:36:33)
- 4 (2024-12-24 (火) 10:45:04)
- 5 (2024-12-29 (日) 16:58:01)
- 6 (2024-12-31 (火) 17:13:45)
- 7 (2025-01-03 (金) 08:57:02)
- 8 (2025-01-03 (金) 09:01:23)
- 9 (2025-01-03 (金) 09:02:38)
- 10 (2025-01-03 (金) 09:03:21)
- 11 (2025-01-03 (金) 09:04:02)
- category: swing folder: LineWrapToolTip title: JToolTipにJTextAreaを配置して自動的に行折返しする tags: [JToolTip, JTextArea] author: aterai pubdate: 2024-12-23T01:04:04+09:00 description: JToolTipにJTextAreaを配置して割当て幅に収まりきらない長さの行を自動的に折り返します。 image: https://drive.google.com/uc?id=1jP4wQX4NE_Be8XMG1WNw_pMQ2IX_wf8v
概要
JToolTip
にJTextArea
を配置して割当て幅に収まりきらない長さの行を自動的に折り返します。
Screenshot
Advertisement
サンプルコード
class LineWrapToolTip extends JToolTip {
private final JTextArea textArea = new JTextArea(0, 20);
private final JLabel label = new JLabel(" ");
protected LineWrapToolTip() {
super();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
// textArea.setColumns(20);
textArea.setOpaque(true);
LookAndFeel.installColorsAndFont(
textArea, "ToolTip.background", "ToolTip.foreground", "ToolTip.font");
setLayout(new BorderLayout());
add(textArea);
}
@Override public final void setLayout(LayoutManager mgr) {
super.setLayout(mgr);
}
@Override public final Component add(Component comp) {
return super.add(comp);
}
@Override public Dimension getPreferredSize() {
// return getLayout().preferredLayoutSize(this);
Dimension d = getLayout().preferredLayoutSize(this);
label.setText(textArea.getText());
Insets i = getInsets();
Insets ti = textArea.getInsets();
Insets tm = textArea.getMargin();
int pad = i.left + i.right + ti.left + ti.right + tm.left + tm.right;
d.width = Math.min(d.width, label.getPreferredSize().width + pad);
return d;
}
@Override public void setTipText(String tipText) {
String oldValue = textArea.getText();
if (!Objects.equals(oldValue, tipText)) {
textArea.setText(tipText);
firePropertyChange("tiptext", oldValue, tipText);
revalidate();
repaint();
}
}
@Override public String getTipText() {
return Optional.ofNullable(textArea).map(JTextArea::getText).orElse(null);
}
}
View in GitHub: Java, Kotlin解説
JTextArea#setLineWrap(true)
、JTextArea#setWrapStyleWord(true)
で行の折り返しを設定したJTextArea
をJToolTip
に配置JComponent#getToolTipText(...)
をオーバーライドしてJToolTip
が親JFrame
の外に表示されて重量ポップアップウィンドウ(共用)が使用される場合は現在のJToolTip
の推奨サイズに合わせてリサイズされるようWindow#pack()
を実行
JTextField field = new JTextField(20) {
private transient JToolTip tip;
@Override public JToolTip createToolTip() {
if (tip == null) {
tip = new LineWrapToolTip();
tip.setComponent(this);
}
return tip;
}
@Override public String getToolTipText(MouseEvent e) {
String tipText = getText();
EventQueue.invokeLater(() ->
Optional.ofNullable(SwingUtilities.getWindowAncestor(tip))
.filter(w -> w.getType() == Window.Type.POPUP)
.ifPresent(Window::pack));
return tipText;
}
};
- 文字列の長さが割当て幅に収まるかどうかは
JLabel
に文字列を設定してその推奨サイズと比較して判断 - 割当て幅は
JTextArea#setColumns(...)
で設定Windows 10
+Java 1.8.0_432
環境ではJTextArea
に配置する文字列が変更されてもそのJTextArea
の推奨サイズが正しく更新されない?ため割り当て幅は200px
固定で設定- 初回は推奨サイズの高さも正しい値が取得できないため、
LineBreakMeasurer
を使用してJTextArea
とは別に計算して使用 - JLabelの文字列を折り返し
Java 21.0.5
以上では正しい推奨サイズが取得可能なことを確認したが、いつどの修正で正しく動作するようになったかは不明 → 調査中Java 21.0.5
:OK
Java 17.0.13
:NG
Java 11.0.25
:NG
Java 8.0.432
:NG