简体   繁体   English

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

[英]JProgressBar setValue is not working, tried with SwingUtilities as well

I have implemented a JProgressBar in a JTable. 我在JTable中实现了一个JProgressBar。 I used renderer for the ProgressBar NOT EDITOR. 我使用渲染器作为ProgressBar NOT EDITOR。

Now I tried to implement a ProgressBar set value but due to EDT its not working so I used SwingUtilties but it did not work as well. 现在我尝试实现一个ProgressBar设置值,但是由于EDT它没有工作,所以我使用了SwingUtilties,但它没有用。

EXPECTED BEHAVIOUR - The JProgressBar must be setting value to 80 , currently it is showing only 0% 预期行为 - 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;
    }

}

Looks like you're trying to use a ProgressBar as a CellRenderer. 看起来您正在尝试将ProgressBar用作CellRenderer。 One thing you should know, is that CellRenders are only called when a cell is being drawn, and setting values at other moments has no effect: this is because Swing uses a flyweight pattern for renderers, and thus reuses the renderer. 您应该知道的一件事是CellRenders 在绘制单元格时调用,而在其他时刻设置值无效:这是因为Swing对渲染器使用了flyweight模式,因此重用了渲染器。

To get the effect you want, you should 为了获得你想要的效果,你应该

  • notify the table that the cell is to be updated, for instance by updating its underlying model (that will fire the necessary events), and 通知表格要更新单元格,例如通过更新其底层模型(将触发必要的事件),以及
  • set all values you need before the getTableCellRendererComponent return, so, remove the invokeLater (the getter is called on the EDT, so you don't need to worry about threading there). getTableCellRendererComponent返回之前设置所需的所有值,因此,删除invokeLater (在EDT上调用getter,因此您不必担心在那里进行线程化)。

1) even is possible, don't create JComponents inside TableCellRenderer , nor re_create Object, Renderer is only for formatting cell contents 1)甚至可以,不要在TableCellRenderer创建JComponents ,也不要在re_create对象中创建,Renderer仅用于格式化单元格内容

2) use SwingWorker for moving with progress in JProgressBar (if you have real important reasons, then use Runnable#Tread ) 2)使用SwingWorkerJProgressBar进行移动(如果你有真正重要的原因,那么使用Runnable#Tread

example about 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();
    }
}

Take a look at the Swing table tutorial: renderers and editors . 看看Swing表教程:渲染器和编辑器 The renderer uses the component to make a sort of 'stamp'. 渲染器使用该组件进行某种“标记”。 Changing the component afterwards has no effect since the component is not actually contained in your UI. 之后更改组件无效,因为组件实际上不包含在UI中。 That is one of the reasons you can return the same component over and over again, which would not be possible if the component was actually contained in the table. 这是您可以一遍又一遍地返回相同组件的原因之一,如果组件实际包含在表中,则无法实现。 This is all explained in the linked tutorial. 这一点都在链接教程中进行了解释。

To solve your problem, just remove the SwingUtilities.invokeLater method call, and return a JProgressBar where the correct progress is set. 要解决您的问题,只需删除SwingUtilities.invokeLater方法调用,并返回一个JProgressBar ,其中设置了正确的进度。

And if I see this correctly, you have a TableModel containing a JProgressBar . 如果我看到这个,你有一个包含JProgressBarTableModel I hope there is a good reason for this, since this is a UI component which should normally not be included on the model side. 我希望有一个很好的理由,因为这是一个UI组件,通常不应该包含在模型方面。 This is based on your 这是基于你的

final JProgressBar bar = (JProgressBar) value;

call in the renderer. 在渲染器中调用。 I would strongly suggest to take a look at your TableModel to see whether this can be avoided 我强烈建议您查看一下您的TableModel ,看看是否可以避免这种情况

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM