代码之家  ›  专栏  ›  技术社区  ›  user3045798

即使触发了正确的事件,GUI也没有更新当前信息

  •  0
  • user3045798  · 技术社区  · 10 年前

    我的GUI有点问题 ProgressCellRenderer 直到我单击它或高亮显示它,甚至调整窗口大小,才更新。我已经精简了代码,只使用通用数据,并使用睡眠来模拟长时间运行的任务。

    我错过了什么,导致它在更新gui本身之前无法更新?

    这是将运行的最低工作代码。

     public class Test
        {
    
            public static void main(String[] args)
            {
                new Test();
            }
    
            public Test()
            {
                EventQueue.invokeLater(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        try
                        {
                            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                        }
                        catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)
                        {
                        }
    
                        UpdatableTableModel model = new UpdatableTableModel();
    
                        JTable table = new JTable();
                        table.setModel(model);
    
                        table.getColumn("Status").setCellRenderer(new ProgressCellRender());
    
                        JFrame frame = new JFrame();
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        frame.setLayout(new BorderLayout());
                        frame.add(new JScrollPane(table));
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
    
                        StringFinderWorker worker = new StringFinderWorker(model);
                        worker.execute();
    
                    }
                });
            }
    
            public class ProgressCellRender extends JProgressBar implements TableCellRenderer
            {
                private static final long serialVersionUID = 1L;
    
                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
                {
                    int progress = 0;
                    if (value instanceof Float)
                    {
                        progress = Math.round(((Float) value) * 100f);
                    }
                    else if (value instanceof Integer)
                    {
                        progress = (int) value;
                    }
                    setValue(progress);
                    return this;
                }
            }
    
            public class RowData
            {
                private String string;
                private float status;
    
                public RowData(String string)
                {
                    this.string = string;
                    this.status = 0f;
                }
    
                public String getString()
                {
                    return string;
                }
    
                public float getStatus()
                {
                    return status;
                }
    
                public void setStatus(float status)
                {
                    this.status = status;
                }
            }
    
            public class UpdatableTableModel extends AbstractTableModel
            {
                private static final long serialVersionUID = 1L;
    
                private List<RowData> rows;
                private Map<String, RowData> mapLookup;
    
                public UpdatableTableModel()
                {
                    rows = new ArrayList<>(25);
                    mapLookup = new HashMap<>(25);
                }
    
                @Override
                public int getRowCount()
                {
                    return rows.size();
                }
    
                @Override
                public int getColumnCount()
                {
                    return 2;
                }
    
                @Override
                public String getColumnName(int column)
                {
                    String name = "??";
                    switch (column)
                    {
                        case 0:
                            name = "The String";
                            break;
                        case 1:
                            name = "Status";
                            break;
                    }
                    return name;
                }
    
                @Override
                public Object getValueAt(int rowIndex, int columnIndex)
                {
                    RowData rowData = rows.get(rowIndex);
                    Object value = null;
                    switch (columnIndex)
                    {
                        case 0:
                            value = rowData.getString();
                            break;
                        case 1:
                            value = rowData.getStatus();
                            break;
                    }
                    return value;
                }
    
                @Override
                public void setValueAt(Object aValue, int rowIndex, int columnIndex)
                {
                    RowData rowData = rows.get(rowIndex);
                    switch (columnIndex)
                    {
                        case 3:
                            if (aValue instanceof Float)
                            {
                                rowData.setStatus((float) aValue);
                            }
                            break;
                    }
                }
    
                public void addString(String string)
                {
                    RowData rowData = new RowData(string);
                    mapLookup.put(string, rowData);
                    rows.add(rowData);
                    fireTableRowsInserted(rows.size() - 1, rows.size() - 1);
                }
    
                protected void updateStatus(String string, int progress)
                {
                    RowData rowData = mapLookup.get(string);
                    if (rowData != null)
                    {
                        int row = rows.indexOf(rowData);
                        float p = (float) progress / 100f;
                        setValueAt(p, row, 3);
                        fireTableCellUpdated(row, 3);
                    }
                }
            }
    
            public class StringFinderWorker extends SwingWorker<List<String>, String>
            {
    
                private UpdatableTableModel model;
    
                public StringFinderWorker(UpdatableTableModel model)
                {
                    this.model = model;
                }
    
                @Override
                protected void process(List<String> chunks)
                {
                    for (String string : chunks)
                    {
                        model.addString(string);
                    }
                }
    
                protected ArrayList<String> getStrings()
                {
                    ArrayList<String> strings = new ArrayList<String>();
                    for (int i = 0; i < 24; i++)
                    {
                        strings.add("test: " + i);
                    }
                    return strings;
                }
    
                @Override
                protected List<String> doInBackground() throws Exception
                {
                    List<String> strings = getStrings();
    
                    for (int i = 0; i < strings.size(); i++)
                    {
                        publish(strings.get(i));
                    }
                    return strings;
                }
    
                @Override
                protected void done()
                {
                    try
                    {
                        List<String> strings = get();
                        for (String string : strings)
                        {
                            new StringDownloaderWorker(model, string).execute();
                        }
                    }
                    catch (Exception exp)
                    {
                        exp.printStackTrace();
                    }
                }
            }
    
            public class StringDownloaderWorker extends SwingWorker<String, String>
            {
    
                private String currentString;
                private UpdatableTableModel model;
    
                public StringDownloaderWorker(UpdatableTableModel model, String string)
                {
                    this.currentString = string;
                    this.model = model;
    
                    addPropertyChangeListener(new PropertyChangeListener()
                    {
                        @Override
                        public void propertyChange(PropertyChangeEvent evt)
                        {
                            if (evt.getPropertyName().equals("progress"))
                            {
                                StringDownloaderWorker.this.model.updateStatus(currentString, (int) evt.getNewValue());
                            }
                        }
                    });
    
                }
    
                @Override
                protected String doInBackground() throws Exception
                {
                    for (int i = 0; i <= 100; i++)
                    {
                        setProgress(i);
                        try
                        {
                            Thread.sleep(1000);
                        }
                        catch (InterruptedException ie)
                        {
                            //
                        }
                    }
    
                    return currentString;
                }
            }
        }
    
    2 回复  |  直到 10 年前
        1
  •  1
  •   MadProgrammer    10 年前

    当你看到这个时,你会踢自己。。。

    用于注册单元格已更改这一事实的列索引是错误的。。。

    您正在使用 setValueAt(p, row, 3); ,当进度列实际为 1 ,所以您实际上应该使用 setValueAt(p, row, 1);

    这也意味着 switch 在您的 setValueAt 方法需要改变。

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        RowData rowData = rows.get(rowIndex);
        switch (columnIndex) {
            case 1:
                if (aValue instanceof Float) {
                    rowData.setStatus((float) aValue);
                    fireTableCellUpdated(rowIndex, columnIndex);
                }
                break;
        }
    }
    

    您还将注意到,我移动了 fireTableCellUpdated 调用此方法,因为您永远不知道何时调用 setValueAt(设置值) 可以调用。

        2
  •  0
  •   abdessamed    10 年前

    每次发生更改时都必须更新表

    我的意思是,当您的表发生一些更改时,您必须调用Update函数来更新该表

    要做到这一点,您可以使用监听器来检测一些变化;如果一个或多个单元格中有更改,则必须调用该函数来更新表

    通常,为了实现这样的更新,您必须使用模型输入,因为每当您的表在一个或多个单元格中发生某些更改时==>那意味着你桌子的型号在改变

    更新模型,然后调用主函数更新当前窗口的容器 例如,有三个函数用于更新接口SWING:更新函数或重新绘制函数或setContentPane(表的Jpanel或Container)