Swing/ColumnSpanningCellRenderer のバックアップの現在との差分(No.9)
- バックアップ一覧
- 差分 を表示
- 現在との差分 - Visual を表示
- ソース を表示
- バックアップ を表示
- Swing/ColumnSpanningCellRenderer へ行く。
- 1 (2013-05-13 (月) 16:59:22)
- 2 (2013-06-04 (火) 13:37:19)
- 3 (2013-06-04 (火) 15:08:18)
- 4 (2013-06-04 (火) 18:25:04)
- 5 (2013-06-05 (水) 10:00:24)
- 6 (2013-08-17 (土) 01:31:41)
- 7 (2014-05-13 (火) 14:47:03)
- 8 (2014-10-26 (日) 04:03:20)
- 9 (2014-11-22 (土) 04:02:40)
- 10 (2015-03-01 (日) 16:07:55)
- 11 (2015-06-26 (金) 17:47:41)
- 12 (2016-01-13 (水) 13:38:38)
- 13 (2017-03-31 (金) 16:12:29)
- 14 (2017-04-07 (金) 13:51:51)
- 15 (2017-09-19 (火) 06:12:05)
- 16 (2018-02-24 (土) 19:45:40)
- 17 (2020-03-06 (金) 16:27:01)
- 18 (2021-08-19 (木) 00:54:24)
- 19 (2024-02-03 (土) 14:09:44)
- 追加された行はこの色です。
- 削除された行はこの色です。
--- category: swing folder: ColumnSpanningCellRenderer title: JTableのセルを横方向に連結する tags: [JTable, TableCellRenderer, JTextArea, JScrollPane] author: aterai pubdate: 2013-05-13T16:59:22+09:00 description: JTableのセルを横方向に連結するセルレンダラーを作成します。 image: https://lh5.googleusercontent.com/-wcXag_bBidU/UY-uA3riCRI/AAAAAAAABrs/Q_V-fdNVRu8/s800/ColumnSpanningCellRenderer.png hreflang: href: https://java-swing-tips.blogspot.com/2013/05/column-spanning-tablecellrenderer.html lang: en --- * 概要 [#y3d3b7a0] * 概要 [#summary] `JTable`のセルを横方向に連結するセルレンダラーを作成します。 #download(https://lh5.googleusercontent.com/-wcXag_bBidU/UY-uA3riCRI/AAAAAAAABrs/Q_V-fdNVRu8/s800/ColumnSpanningCellRenderer.png) * サンプルコード [#j27fd87a] * サンプルコード [#sourcecode] #code(link){{ class ColumnSpanningCellRenderer extends JPanel implements TableCellRenderer { private static final int TARGET_COLIDX = 0; private final JTextArea textArea = new JTextArea(2, 999999); private final JLabel label = new JLabel(); private final JLabel iconLabel = new JLabel(); private final JScrollPane scroll = new JScrollPane(); private final JScrollPane scroll = new JScrollPane(textArea); public ColumnSpanningCellRenderer() { super(new BorderLayout(0, 0)); protected ColumnSpanningCellRenderer() { super(new BorderLayout()); scroll.setViewportView(textArea); scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scroll.setBorder(BorderFactory.createEmptyBorder()); scroll.setViewportBorder(BorderFactory.createEmptyBorder()); scroll.setOpaque(false); scroll.getViewport().setOpaque(false); textArea.setBorder(BorderFactory.createEmptyBorder()); textArea.setMargin(new Insets(0, 0, 0, 0)); textArea.setForeground(Color.RED); textArea.setEditable(false); textArea.setFocusable(false); textArea.setOpaque(false); iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4)); iconLabel.setOpaque(false); Border b1 = BorderFactory.createEmptyBorder(2, 2, 2, 2); Border b2 = BorderFactory.createMatteBorder(0, 0, 1, 1, Color.GRAY); label.setBorder(BorderFactory.createCompoundBorder(b2, b1)); setBackground(textArea.getBackground()); setOpaque(true); add(label, BorderLayout.NORTH); add(scroll); } @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Test test; if (value instanceof Test) { test = (Test)value; OptionPaneDescription d; if (value instanceof OptionPaneDescription) { d = (OptionPaneDescription) value; add(iconLabel, BorderLayout.WEST); } else { String title = Objects.toString(value, ""); int mrow = table.convertRowIndexToModel(row); String title = value != null ? value.toString() : ""; Test t = (Test)table.getModel().getValueAt(mrow, 0); String text = t != null ? t.text : ""; Icon icon = t != null ? t.icon : null; test = new Test(title, icon, text); Object o = table.getModel().getValueAt(mrow, 0); if (o instanceof OptionPaneDescription) { OptionPaneDescription t = (OptionPaneDescription) o; d = new OptionPaneDescription(title, t.icon, t.text); } else { d = new OptionPaneDescription(title, null, ""); } remove(iconLabel); } label.setText(test.title); textArea.setText(test.text); iconLabel.setIcon(test.icon); label.setText(d.title); textArea.setText(d.text); iconLabel.setIcon(d.icon); Rectangle cr = table.getCellRect(row, column, false); if (column != 0) { if (column != TARGET_COLIDX) { cr.x -= iconLabel.getPreferredSize().width; } scroll.getViewport().setViewPosition(cr.getLocation()); if (isSelected) { setBackground(Color.ORANGE); } else { setBackground(Color.WHITE); } return this; } } class OptionPaneDescription { public final String title; public final Icon icon; public final String text; protected OptionPaneDescription(String title, Icon icon, String text) { this.title = title; this.icon = icon; this.text = text; } } }} * 解説 [#m5397014] 文字列を配置した`JTextArea`を各カラムごとに`JViewport`で表示する領域を切り取ってセルに貼り付けています。さらに、`JTable`のセルの縦罫線自体は、`table.setShowVerticalLines(false);`などで非表示にすることでレンダラー内の`JTextArea`は、連続しているように見せかけ、上部の`JLabel`は`Border`を設定することで区切りを表示しています。 * 解説 [#explanation] 文字列を配置した`JTextArea`を各カラムごとに`JViewport`で表示する領域を切り取ってセルに貼り付けています。さらに`JTable`のセルの縦罫線自体を`table.setShowVerticalLines(false)`などで非表示にしてレンダラー内の`JTextArea`は連続しているように見せかけ、代わりに上部の`JLabel`は`Border`を設定することで区切りを表示しています。 - メモ -- 列の入れ替えには対応していない -- `0`行目だけカラムヘッダのサイズを変更すると、描画がおかしくなる? --- `0`行目ではなく、一番上に表示されている行の表示が乱れている --- `JTextArea#scrollRectToVisible(...)`ではなく、`JViewport#setViewPosition(Point)`を使用すると正常にリサイズできる --- %%`0`行目だけ高さ`1`のダミー行を追加して回避(ソートなどで問題が残る)%% -- %%`JTable`のクリック(セル選択?)などで表示が乱れる場合がある%% --- %%`JTable#repaint(Rectangle)`をオーバーライドして常に全体を描画することで回避%% - 列の入れ替えには対応していない - `0`行目だけカラムヘッダのサイズを変更すると描画がおかしくなる? -- `0`行目ではなく一番上に表示されている行の表示が乱れている -- `JTextArea#scrollRectToVisible(...)`ではなく`JViewport#setViewPosition(Point)`を使用すると正常にリサイズ可能 -- %%`0`行目だけ高さ`1`の仮行を追加して回避(ソートなどで問題が残る)%% - %%`JTable`のクリック(セル選択?)などで表示が乱れる場合がある%% -- %%`JTable#repaint(Rectangle)`をオーバーライドして常に全体を描画することで回避%% - `JScrollPane`内に`JTextArea`を配置せずに直接`JTextArea`から表示領域を切り取っても良さそう? * 参考リンク [#k0cadf9c] * 参考リンク [#reference] - [http://docs.huihoo.com/javaone/2007/desktop/TS-3548.pdf PDF: Extreme GUI Makeover 2007] -- via: [http://stackoverflow.com/questions/16305023/jtable-complex-cell-renderer java - JTable : Complex Cell Renderer - Stack Overflow] -- via: [https://stackoverflow.com/questions/16305023/jtable-complex-cell-renderer java - JTable : Complex Cell Renderer - Stack Overflow] - [[JTableの罫線の有無とセルの内余白を変更>Swing/IntercellSpacing]] * コメント [#dcdb5bd1] * コメント [#comment] #comment - `JTable`をスクロールするとおかしくなる? -- &user(aterai); &new{2013-06-04 (火) 13:37:19}; -- `0`行目ではなく、一番上に表示されている行の表示が原因かもしれない。 -- &user(aterai); &new{2013-06-04 (火) 13:44:14}; -- 移動の幅からみて、`TableCellRenderer`の`Border`が関連しているような気がするけど、よく分からない。 -- &user(aterai); &new{2013-06-04 (火) 15:08:18}; -- 一番上の行のみの症状なので、ヘッダレンダラーとか関係してるのかと調べてたけど、`JViewport#setViewPosition(Point)`を使って直接ジャンプ?すれは、正常にヘッダサイズを変更できるようだ。もしかしたら[http://docs.oracle.com/javase/jp/6/api/javax/swing/JViewport.html 次にビューポートにペイントが呼び出されたときに、クリッピング領域がビューポートサイズより小さい場合には、タイマーが開始され全体をペイントし直す]せいだった? -- &user(aterai); &new{2013-06-04 (火) 18:29:12}; -- 一番上の行のみの症状なので、ヘッダセルレンダラーとか関係してるのかと調べてたけど、`JViewport#setViewPosition(Point)`を使って直接ジャンプ?すれは、正常にヘッダサイズを変更できるようだ。もしかしたら[https://docs.oracle.com/javase/jp/8/docs/api/javax/swing/JViewport.html 次にビューポートにペイントが呼び出されたときに、クリッピング領域がビューポートサイズより小さい場合には、タイマーが開始され全体をペイントし直す]せい? -- &user(aterai); &new{2013-06-04 (火) 18:29:12}; #comment