JXTable not refreshed upon button click

五迷三道 提交于 2020-01-22 02:49:08

问题


I have a JFrame which holds a JXTable (from SwingX dependency) and a JButton.

Once I click the JButton the table should get updated each time. In my case it gets updated only at the first time. Other events also get triggered on the button click (which happens each time I click the button). Only the table is not refreshed with the new rows added.

I am using DeafultTableModel and have tried (explicit trigger) all suggested methods like repaint, fireTableDataChanged etc.

Can someone please help?

EDIT-1 (code snippet added): -

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

回答1:


There are some conceptual mistakes in the lines below:

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) Don't create a new JXTable when you press the button but work with the table model instead either by clearing the current table model and adding rows to it or directly by setting a new one. For example:

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

2) These lines suggests that overviewPanel has already been displayed by the time you are trying to add the new table by clicking the button, thus invalidating the components hierarchy and in consequence you have to revalidate and repaint the panel like this:

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

However while we can add components dynamically in Swing we tipically place all our components before the top-level container (window) is made visible. Thus the approach described in point 1 is highly preferable over this one and I'm adding this point just for completeness.

3) Be aware that time consuming tasks such as database calls or IO operations may block the Event Dispatch Thread (EDT) causing the GUI become unresponsive. The EDT is a single and special thread where Swing components creation and update take place. To avoid block this thread consider use a SwingWorker to perform heavy tasks in a background thread and update Swing components in the EDT. See more in Concurrency in Swing lesson.


Update

Please consider the following example illustrating point 1:

  • The table is created and placed once before making the top-level container (window) visible.
  • Both actions work with the table model: one of them sets a new table model and the other one clear and re-fill the current table model.

Here is the code. Hope it helps!

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


来源:https://stackoverflow.com/questions/26629763/jxtable-not-refreshed-upon-button-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!