JTable中的JProgressBar没有更新

为什么以下代码中的进度条没有更新,如何将它们更新?

import java.awt.event.{ActionListener, ActionEvent} import javax.swing.table.{TableCellRenderer, AbstractTableModel} import javax.swing.{Timer, JTable, JProgressBar, JFrame} object TestProgressBar { val frame = new JFrame() val model = new TestModel() val table = new JTable(model) class TestModel extends AbstractTableModel { def getColumnCount = 4 def getRowCount = 4 def getValueAt(y: Int, x: Int) = "%d,%d".format(x, y) override def setValueAt(value: Any, row: Int, col: Int) { if (col == 0) { model.fireTableCellUpdated(row, col); } } } class TestCellRenderer extends TableCellRenderer with ActionListener { val progressBar = new JProgressBar() val timer = new Timer(100, this) progressBar.setIndeterminate(true) timer.start() override def getTableCellRendererComponent(tbl: JTable, value: AnyRef, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int) = { progressBar } override def actionPerformed(e: ActionEvent) { val model = table.getModel for (row <- 0 to model.getRowCount) { model.setValueAt(0, row, 0) } } } def main(args: Array[String]) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) table.getColumnModel.getColumn(0).setCellRenderer(new TestCellRenderer()) frame.add(table) frame.pack() frame.setVisible(true) } } 

正如@Robin指出的那样,渲染器仅在更新模型时引发。 您需要定期更改所需行中的值。 此示例使用javax.swing.Timer

 private class TestCellRenderer implements TableCellRenderer, ActionListener { JProgressBar bar = new JProgressBar(); Timer timer = new Timer(100, this); public TestCellRenderer() { bar.setIndeterminate(true); timer.start(); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { return bar; } @Override public void actionPerformed(ActionEvent e) { TableModel model = table.getModel(); for (int row = 0; row < model.getRowCount(); row++) { table.getModel().setValueAt(0, row, 0); } } } 

您可能还想实现setValueAt() ,因为AbstractTableModel实现为空:

 @Override public void setValueAt(Object aValue, int row, int col) { if (col == 1) { // update your internal model and notify listeners this.fireTableCellUpdated(row, col); } } 

附录:作为参考,这里有一个相应的Java实现来补充Scala。

在此处输入图像描述

码:

 import java.awt.Component; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.Timer; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableModel; /** * @see http://stackoverflow.com/a/10491290/230513 */ public class TestProgressBar extends JPanel { private JTable table = new JTable(new TestModel()); public TestProgressBar() { table.getColumnModel().getColumn(0).setCellRenderer(new TestCellRenderer()); table.setPreferredScrollableViewportSize(new Dimension(320, 120)); this.add(new JScrollPane(table)); } private class TestModel extends AbstractTableModel { @Override public int getRowCount() { return 4; } @Override public int getColumnCount() { return 4; } @Override public Object getValueAt(int row, int col) { return String.valueOf(row) + ", " + String.valueOf(col); } @Override public void setValueAt(Object aValue, int row, int col) { // update internal model and notify listeners fireTableCellUpdated(row, col); } } private class TestCellRenderer implements TableCellRenderer, ActionListener { JProgressBar bar = new JProgressBar(); Timer timer = new Timer(100, this); public TestCellRenderer() { bar.setIndeterminate(true); timer.start(); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { return bar; } @Override public void actionPerformed(ActionEvent e) { TableModel model = table.getModel(); for (int row = 0; row < model.getRowCount(); row++) { table.getModel().setValueAt(0, row, 0); } } } private void display() { JFrame f = new JFrame("TestProgressBar"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(this); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { new TestProgressBar().display(); } }); } } 

不确定Scala,但在Swing中, TableRenderer返回的组件仅用于创建“标记”。 因此实际组件不包含在JTable ,只是它的标记。 这意味着如果之后更新组件,这不会反映在`JTable中。

主要好处是您可以在渲染器中重用您的组件。 例如,为了渲染String ,您只需要一个JLabel实例来更新文本并让渲染器返回它。

Swing表教程中的渲染器部分更详细地解释了这一点

我似乎通过覆盖JPDressressBar的isDisplayable和重绘方法解决了这个问题。

 import javax.swing.table.{TableCellRenderer, AbstractTableModel} import javax.swing.{JTable, JProgressBar, JFrame} object TestProgressBar { val frame = new JFrame() val model = new TestModel() val table = new JTable(model) class TestModel extends AbstractTableModel { def getColumnCount = 4 def getRowCount = 4 def getValueAt(y: Int, x: Int) = "%d,%d".format(x, y) } class TestCellRenderer extends TableCellRenderer { val progressBar = new JProgressBar() { override def isDisplayable = true override def repaint() { table.repaint() } } progressBar.setIndeterminate(true) override def getTableCellRendererComponent(tbl: JTable, value: AnyRef, isSelected: Boolean, hasFocus: Boolean, row: Int, column: Int) = { progressBar } } def main(args: Array[String]) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) table.getColumnModel.getColumn(0).setCellRenderer(new TestCellRenderer()) frame.add(table) frame.pack() frame.setVisible(true) } }