【问题标题】:JXTable not refreshed upon button clickJTable 未在按钮单击时刷新
【发布时间】:2014-12-25 02:56:39
【问题描述】:

我有一个JFrame,其中包含一个JXTable(来自SwingX 依赖项)和一个JButton

单击 JButton 后,表格每次都会更新。就我而言,它仅在第一次更新。其他事件也会在按钮单击时触发(每次单击按钮时都会发生)。只有表没有被添加的新行刷新。

我正在使用DeafultTableModel 并尝试(显式触发)所有建议的方法,例如repaintfireTableDataChanged 等。

有人可以帮忙吗?

EDIT-1(添加了代码 sn-p):-

// the actions will take place when VALIDATE button is clicked
validateButton.addActionListener(new ActionListener() {
    public void actionPerformed(final ActionEvent ae) {
        if (evCheckbox1.isSelected() || !list.isSelectionEmpty()) {
            try {
                // store the validation errors for future use
                List<List<String>> validationErrors = validateSheet(Driver.this.fileLocation, list
                    .getSelectedValuesList(), regulatorTypeCB.getSelectedItem().toString(), sheetTypeCB
                    .getSelectedItem().toString());
                // creates the validation error overview to be added to roTable 
                Map<String, Integer> tmpMap = getValidationErrorsOverview(validationErrors);
                System.out.println(tmpMap);
                // create the report overview table
                String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
                DefaultTableModel tmodel = new DefaultTableModel(0, 0);
                tmodel.setColumnIdentifiers(columnNames);
                JXTable roTable = new JXTable();
                table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
                roTable.addHighlighter(HighlighterFactory.createSimpleStriping());                               
                List<String> tlist = new ArrayList<String>();
                JScrollPane scrPane = new JScrollPane(roTable);
                scrPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
                scrPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
                overviewPanel.add(scrPane);

                // create a list from the validation error overview map to insert as a row in table
                for (Map.Entry<String, Integer> entry : tmpMap.entrySet()) {
                    tlist.add(entry.getKey().split(":")[0]);
                    tlist.add(entry.getKey().split(":")[1]);
                    tlist.add(String.valueOf(entry.getValue()));
                }
                // add rows in table
                for (int i = 0; i < tmpMap.size(); i++) {
                    tmodel.addRow(new Object[] {tlist.get((i * 3) + 0), tlist.get((i * 3) + 1),
                        tlist.get((i * 3) + 2)});
                }

                FileUtils.writeStringToFile(logFile, "\n" + new Date().toString() + "\n", true);                                
                roTable.setModel(tmodel);
                roTable.repaint();
                // frame refresh
                Driver.this.frame.revalidate();
                Driver.this.frame.repaint();
                // open the log file in notepad.exe
                ProcessBuilder pb = new ProcessBuilder("Notepad.exe", "verifier.log");
                pb.start();
            } catch (BiffException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } 
    }
});

【问题讨论】:

  • @dic19 在想我应该发布这么糟糕的代码:P

标签: java swing event-handling jtable swingx


【解决方案1】:

以下几行存在一些概念性错误:

String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
DefaultTableModel tmodel = new DefaultTableModel(0, 0);
tmodel.setColumnIdentifiers(columnNames);
JXTable roTable = new JXTable();
...
JScrollPane scrPane = new JScrollPane(roTable);
...
overviewPanel.add(scrPane);

1) 按下按钮时不要创建新的JXTable,而是通过清除当前表模型并向其添加行或直接设置新表模型来使用表模型。例如:

String[] columnNames = {"SHEET_NAME", "VALIDATION_NAME", "#"};
DefaultTableModel tmodel = new DefaultTableModel(0, 0);
tmodel.setColumnIdentifiers(columnNames);
yourTable.setModel(tmodel);

2) 这些行表明 overviewPanel 在您尝试通过单击按钮添加新表时已经显示,因此 invalidating the components hierarchy 并且因此您必须重新验证并重新绘制面板,如下所示:

overviewPanel.add(scrPane);
overviewPanel.revalidate();
overviewPanel.repaint();

然而,虽然我们可以在 Swing 中动态添加组件,但我们通常会在顶层容器(窗口)可见之前放置所有组件。因此,第 1 点中描述的方法比这一点更可取,我添加这一点只是为了完整性。

3) 请注意,数据库调用或 IO 操作等耗时任务可能会阻塞Event Dispatch Thread (EDT),从而导致 GUI 无响应。 EDT 是一个单一且特殊的线程,在其中创建和更新 Swing 组件。为避免阻塞此线程,请考虑使用SwingWorker 在后台线程中执行繁重的任务并更新 EDT 中的 Swing 组件。在Concurrency in Swing 课程中查看更多信息。


更新

请考虑以下说明第 1 点的示例:

  • 表创建并放置一次之前使顶级容器(窗口)可见。
  • 这两个操作都适用于表格模型:其中一个设置新表格模型,另一个清除并重新填充当前表格模型。

这里是代码。希望对您有所帮助!

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import org.jdesktop.swingx.JXTable;

public class Demo {

    private void createAndShowGUI() {

        final JXTable table = new JXTable(5, 6);
        table.setPreferredScrollableViewportSize(new Dimension(500, 200));

        Action resetModelAction = new AbstractAction("Set a new model") {
            @Override
            public void actionPerformed(ActionEvent e) {
                Random random = new Random(System.currentTimeMillis());
                DefaultTableModel model = new DefaultTableModel(0, 6);

                for (int i = 0; i < model.getColumnCount(); i++) {
                    model.addRow(new Object[]{
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt()
                    });
                }

                table.setModel(model);
            }
        };

        Action clearAndFillModelAction = new AbstractAction("Clear and fill model") {
            @Override
            public void actionPerformed(ActionEvent e) {
                Random random = new Random(System.currentTimeMillis());
                DefaultTableModel model = (DefaultTableModel)table.getModel();
                model.setRowCount(0); // clear the model

                for (int i = 0; i < model.getColumnCount(); i++) {
                    model.addRow(new Object[]{
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt(),
                        random.nextInt()
                    });
                }
            }
        };

        JPanel buttonsPanel = new JPanel();
        buttonsPanel.add(new JButton(resetModelAction));
        buttonsPanel.add(new JButton(clearAndFillModelAction));

        JPanel content = new JPanel(new BorderLayout(8,8));
        content.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
        content.add(new JScrollPane(table));
        content.add(buttonsPanel, BorderLayout.PAGE_END);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(content);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new Demo().createAndShowGUI();
            }
        });
    }    
}

【讨论】:

  • 很好的解释@dic19 让我先尝试一下,然后再接受您的回答。还在学习:B
  • 尝试过的方法 1 --> 不走运,尝试过的方法 1+2 --> 不走运(现在第一次点击表格被填充,第二次点击向前表格消失
  • 请看我的更新。我已经包含了一个完整的示例来说明第 1 点。@Saik0
猜你喜欢
  • 1970-01-01
  • 2013-10-10
  • 1970-01-01
  • 2014-04-10
  • 1970-01-01
  • 2012-01-31
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多