JProgressBar setValue不起作用,也尝试使用SwingUtilities

我在JTable中实现了一个JProgressBar。 我使用渲染器作为ProgressBar NOT EDITOR。

现在我尝试实现一个ProgressBar设置值,但由于EDT它没有工作,所以我使用了SwingUtilties,但它没有用。

预期行为 – JProgressBar必须将值设置为80,目前它只显示0%

public class SkillSetTableProgressBarRenderer extends JProgressBar implements TableCellRenderer { public SkillSetTableProgressBarRenderer() { super(0, 100); super.setPreferredSize(new Dimension(100, 80)); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final JProgressBar bar = (JProgressBar) value; if (bar.getString().equals("JAVA") || bar.getString().equals("SWING")) super.setString("Mellow"); else super.setString("GOOD"); setOpaque(true); table.setOpaque(true); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { System.err.println("MAIN ANDER"); setValue(80); bar.setValue(80); } }); super.setStringPainted(true); super.setIndeterminate(true); super.setPreferredSize(new Dimension(140, 16)); if (isSelected) { super.setBackground(table.getSelectionBackground()); super.setForeground(table.getSelectionForeground()); // this.setBackground(table.getSelectionBackground()); } else { super.setForeground(table.getForeground()); super.setBackground(Color.WHITE); } return this; } } 

1)甚至可以,不要在TableCellRenderer创建JComponents ,也不要在re_create对象中创建,Renderer仅用于格式化单元格内容

2)使用SwingWorkerJProgressBar进行移动(如果你有真正重要的原因,那么使用Runnable#Tread

关于Runnable#Tread例子

在此处输入图像描述

 import java.awt.Component; import java.util.Random; import javax.swing.JFrame; import javax.swing.JProgressBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableCellRenderer; public class TableWithProgressBars { public static class ProgressRenderer extends JProgressBar implements TableCellRenderer { private static final long serialVersionUID = 1L; public ProgressRenderer(int min, int max) { super(min, max); this.setStringPainted(true); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { this.setValue((Integer) value); return this; } } private static final int maximum = 100; public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TableWithProgressBars().createGUI(); } }); } public void createGUI() { final JFrame frame = new JFrame("Progressing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Integer[] oneRow = {0, 0, 0, 0}; String[] headers = {"One", "Two", "Three", "Four"}; Integer[][] data = {oneRow, oneRow, oneRow, oneRow, oneRow,}; final DefaultTableModel model = new DefaultTableModel(data, headers); final JTable table = new JTable(model); table.setDefaultRenderer(Object.class, new ProgressRenderer(0, maximum)); table.setPreferredScrollableViewportSize(table.getPreferredSize()); frame.add(new JScrollPane(table)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); new Thread(new Runnable() { @Override public void run() { Object waiter = new Object(); synchronized (waiter) { int rows = model.getRowCount(); int columns = model.getColumnCount(); Random random = new Random(System.currentTimeMillis()); boolean done = false; while (!done) { int row = random.nextInt(rows); int column = random.nextInt(columns); Integer value = (Integer) model.getValueAt(row, column); value++; if (value <= maximum) { model.setValueAt(value, row, column); try { waiter.wait(15); } catch (InterruptedException e) { e.printStackTrace(); } } done = true; for (row = 0; row < rows; row++) { for (column = 0; column < columns; column++) { if (!model.getValueAt(row, column).equals(maximum)) { done = false; break; } } if (!done) { break; } } } frame.setTitle("All work done"); } } }).start(); } } 

看起来您正在尝试将ProgressBar用作CellRenderer。 您应该知道的一件事是,CellRenders 在绘制单元格时调用,而在其他时刻设置值无效:这是因为Swing对渲染器使用了flyweight模式,因此重用了渲染器。

为了获得你想要的效果,你应该

  • 通知表格要更新单元格,例如通过更新其底层模型(将触发必要的事件),以及
  • getTableCellRendererComponent返回之前设置所需的所有值,因此,删除invokeLater (在EDT上调用getter,因此您不必担心在那里进行线程化)。

看一下Swing表教程:渲染器和编辑器 。 渲染器使用该组件进行某种“标记”。 之后更改组件无效,因为组件实际上并未包含在UI中。 这是您可以反复返回相同组件的原因之一,如果组件实际包含在表中,则无法实现。 这已在链接教程中解释。

要解决您的问题,只需删除SwingUtilities.invokeLater方法调用,并返回一个JProgressBar ,其中设置了正确的进度。

如果我看到这个,你有一个包含JProgressBarTableModel 。 我希望有一个很好的理由,因为这是一个UI组件,通常不应该包含在模型方面。 这是基于你的

 final JProgressBar bar = (JProgressBar) value; 

在渲染器中调用。 我强烈建议您查看一下您的TableModel ,看看是否可以避免这种情况