【问题标题】:JProgressBar setValue is not working, tried with SwingUtilities as wellJProgressBar setValue 不起作用,也尝试使用 SwingUtilities
【发布时间】:2012-03-06 14:48:45
【问题描述】:

我在 JTable 中实现了 JProgressBar。 我使用 renderer 作为 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;
    }

}

【问题讨论】:

标签: java swing concurrency jprogressbar tablecellrenderer


【解决方案1】:

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

要达到你想要的效果,你应该

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

【讨论】:

    【解决方案2】:

    看看Swing table tutorial: renderers and editors。渲染器使用该组件制作一种“印章”。之后更改组件无效,因为该组件实际上并未包含在您的 UI 中。这就是您可以一遍又一遍地返回相同组件的原因之一,如果该组件实际上包含在表中,这是不可能的。这在链接的教程中都有解释。

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

    如果我没看错的话,你有一个 TableModel 包含一个 JProgressBar。我希望这是有充分理由的,因为这是一个 UI 组件,通常不应包含在模型端。这是基于您的

    final JProgressBar bar = (JProgressBar) value;
    

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

    【讨论】:

      【解决方案3】:

      1) 甚至是可以的,不要在TableCellRenderer里面创建JComponents,也不要re_create Object,Renderer只是用来格式化单元格内容

      2) 使用SwingWorker 在JProgressBar 中移动(如果您有真正重要的原因,请使用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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多