Swing/TableCellOfIndeterminateProgressBar の変更点
- 追加された行はこの色です。
- 削除された行はこの色です。
- Swing/TableCellOfIndeterminateProgressBar へ行く。
- Swing/TableCellOfIndeterminateProgressBar の差分を削除
--- category: swing folder: TableCellOfIndeterminateProgressBar title: JTableのセルに不確定進捗状態のJProgressBarを表示する tags: [JTable, JProgressBar, TableCellRenderer, SwingWorker, Animation] author: aterai pubdate: 2024-01-08T03:30:00+09:00 description: JTableのセルに一定期間だけ不確定進捗状態のアニメーションを描画するJProgressBarを適用します。 image: https://drive.google.com/uc?id=1j8bfUbhh4at4824_s2NPQ89sjHUw6N49 hreflang: href: https://java-swing-tips.blogspot.com/2024/01/paint-jprogressbar-with-indeterminate.html lang: en --- * 概要 [#summary] `JTable`のセルに一定期間だけ不確定進捗状態のアニメーションを描画する`JProgressBar`を適用します。 #download(https://drive.google.com/uc?id=1j8bfUbhh4at4824_s2NPQ89sjHUw6N49) * サンプルコード [#sourcecode] #code(link){{ private final JTable table = new JTable(model) { @Override public void updateUI() { super.updateUI(); removeColumn(getColumnModel().getColumn(3)); JProgressBar progress = new JProgressBar(); TableCellRenderer renderer = new DefaultTableCellRenderer(); TableColumn tc = getColumnModel().getColumn(2); tc.setCellRenderer((tbl, value, isSelected, hasFocus, row, column) -> { Component c; if (value instanceof JProgressBar) { c = (JProgressBar) value; } else if (value instanceof Integer) { progress.setValue((int) value); c = progress; } else { c = renderer.getTableCellRendererComponent( tbl, Objects.toString(value), isSelected, hasFocus, row, column); } return c; }); } }; class IndeterminateProgressBarUI extends BasicProgressBarUI { @Override public void incrementAnimationIndex() { super.incrementAnimationIndex(); } } class BackgroundTask extends SwingWorker<Integer, Object> { private final Random rnd = new Random(); @Override protected Integer doInBackground() throws InterruptedException { int lengthOfTask = calculateTaskSize(); int current = 0; int total = 0; while (current <= lengthOfTask && !isCancelled()) { publish(100 * current / lengthOfTask); total += doSomething(); current++; } return total; } private int calculateTaskSize() throws InterruptedException { int total = 0; JProgressBar indeterminate = new JProgressBar() { @Override public void updateUI() { super.updateUI(); setUI(new IndeterminateProgressBarUI()); } }; indeterminate.setIndeterminate(true); // Indeterminate loop: for (int i = 0; i < 200; i++) { int iv = rnd.nextInt(50) + 1; Thread.sleep(iv); ProgressBarUI ui = indeterminate.getUI() ((IndeterminateProgressBarUI) ui).incrementAnimationIndex(); publish(indeterminate); total += iv; } return 1 + total / 100; } private int doSomething() throws InterruptedException { int iv = rnd.nextInt(50) + 1; Thread.sleep(iv); return iv; } } }} * 解説 [#explanation] - `SwingWorker`で`JProgressBar#setIndeterminate(true)`を設定して不確定進捗状態にした`JProgressBar`を生成して`TableModel`の対象セルに設定 - `SwingWorker`から進捗状況を`Integer`で受け取る場合はセルレンダラーとして進捗状態を表示する`JProgressBar`を一つだけ使いまわして使用する([[JTableのセルにJProgressBarを表示>Swing/TableCellProgressBar]]参照)が、不確定進捗状態アニメーションを表示する場合は`SwingWorker`からセルごとに異なる`JProgressBar`自体を受け取ってセルレンダラーにする必要がある -- 一つだけの`JProgressBar`を使用すると複数行で不確定進捗状態アニメーションを実行する場合やセルサイズが変更されて再描画する場合にアニメーション速度が速くなるなどの不具合が発生する - 不確定進捗状態アニメーションは`JProgressBar`が親コンテナに配置されて表示可能状態になっていないと開始、描画されないので、このサンプルでは`BasicProgressBarUI#incrementAnimationIndex()`をオーバーライドして`public`にし、`SwingWorder`で一定期間`SwingWorder#publish(...)`と同時にこれを実行してアニメーションのコマを進めている ---- - [[JTableのセルにAnimated GIFを表示する>Swing/AnimatedIconInTableCell]]のような`Animated GIF`で不確定進捗状態を表示する`JLabel`をセルレンダラーとして使用する方法もある #code{{ if (value instanceof JProgressBar) { label.setIcon(makeImageIcon(url, tbl, row, column)); c = label; } else if (...) // ... public static Icon makeImageIcon(URL url, JTable table, int row, int col) { if (Objects.nonNull(url)) { ImageIcon icon = new ImageIcon(url); icon.setImageObserver((img, infoflags, x, y, w, h) -> { if (!table.isShowing()) { return false; } if ((infoflags & (FRAMEBITS | ALLBITS)) != 0) { int vr = table.convertRowIndexToView(row); int vc = table.convertColumnIndexToView(col); table.repaint(table.getCellRect(vr, vc, false)); } return (infoflags & (ALLBITS | ABORT)) == 0; }); return icon; } else { return UIManager.getIcon("html.missingImage"); } } }} * 参考リンク [#reference] - [[JTableのセルにJProgressBarを表示>Swing/TableCellProgressBar]] - [[JTableのセルにAnimated GIFを表示する>Swing/AnimatedIconInTableCell]] * コメント [#comment] #comment #comment