Question

I've 2 panels. One where the user inserts the data and the other with a JTable where the results will be shown.

My problem is when the user press's the ok (in my case apply) JButton the data is computed but is not shown on the JTable, nothing changes in the JTable.

For my JTable I'm using the Bean Table Model from tips4Java (http://tips4java.wordpress.com/2008/11/27/bean-table-model/).

One weird thing is if I send data (lets call this data 'A') to the table when the program starts it is shown on the table and if later on I try to update the table, the table does not update. But when I don't send data to the table at start up but try to update/send the table with data 'A' it does not update.

So my question is, why is not the JTable showing whatever data I send to?

Here's my code:

JButton listenere that starts the processing and sends the data to the table:

crashForm.setFormListener(new FormListener() {
    @Override
    public void formEvent(OptionsFormEvent oe) {
        String readTable = oe.getReadFromTable();
        int access = oe.getAccess();
        int transition = oe.getTransition();
        boolean smooth = oe.isTrainCrash();
        ArrayList<String> allTrains = new ArrayList<>();
        List crashedTrainList = new ArrayList<>();

        try {
            allTrains = controller.getUniqueTrains(controller.connectServer(), readTable, "trainid");
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "An error occured while getting trains data\n"
                    + "Error description: " + ex.getMessage(), "Error",
                    JOptionPane.ERROR_MESSAGE);
        }

        try {
            for (int i = 0; i < allTrains.size(); i++) 
            {
                ArrayList<Train> trainDataList = new ArrayList<>();
                ArrayList<Train> crashedProccessedData = new ArrayList<>();

                String query = "the sql query...";

                trainDataList = controller.getTrainData(controller.connectServer(), readTable, query);

                crashedProccessedData = controller.detectCrash(access, transition, trainDataList);
                crashedTrainList.addAll(crashedProccessedData);

            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "An error occured while detecting a crash.\n"
                    + "Error description: " + ex.getMessage(), "Error",
                    JOptionPane.ERROR_MESSAGE);
        }

        System.out.println("Total crashes detected:" + crashedTrainList.size());
        tablePanel.createTable(Train.class, crashedTrainList, true, false, tableLabels);
        tablePanel.fireTableDataChanged();
    }
});
}

And here's my tablePanel class:

    public TablePanel() {
    }
    public void createTable(Class c, List data, boolean toolBarUp, 
            boolean toolBarBottom, ArrayList<String> labelsCheckBox) {

        beanTableModel = new BeanTableModel(c, data);
        columnModel = new XTableColumnModel();
        table = new JTable(beanTableModel);
        table.setColumnModel(columnModel);
        table.createDefaultColumnsFromModel();

        if(toolBarUp == true)
        {
            final JToolBar toolBarTop = new JToolBar();

            // Create the Show ALL
            JButton reset = new JButton("Reset");

            reset.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                for(Component c : toolBarTop.getComponents()){
                    if(c instanceof JCheckBox){
                        JCheckBox checkBox = (JCheckBox) c;
                        checkBox.setSelected(false);
                        columnModel.setAllColumnsVisible();
                    }
                }
                int numberOfColumn = columnModel.getColumnCount();

                for(int aux = 0; aux < numberOfColumn; aux++)
                {
                    int num = columnModel.getColumnCount();
                    TableColumn column = columnModel.getColumnByModelIndex(aux);
                    columnModel.setColumnVisible(column, true);
                }
            }
            });

            toolBarTop.add(reset);

            // Create a JCheckBox for each column
            for(int i = 0; i < labelsCheckBox.size(); i++)
            {
                final int index = i;
                toolBarTop.add(new JCheckBox(new AbstractAction(labelsCheckBox.get(i)) {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        TableColumn column = columnModel.getColumnByModelIndex(index);
                        boolean visible = columnModel.isColumnVisible(column);
                        columnModel.setColumnVisible(column, !visible);
                    }
                }));
            }



            setLayout(new BorderLayout());
            add(toolBarTop, BorderLayout.NORTH);
            add(new JScrollPane(table), BorderLayout.CENTER);
//            add(toolBarDown, BorderLayout.SOUTH);
        }


        final JToolBar toolBarDown = new JToolBar();

        toolBarDown.add(new JButton(new AbstractAction("Save Table") {
            @Override
            public void actionPerformed(ActionEvent e) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        }));


    }

    public void createTable(Class c, Class cAncestor) {
        beanTableModel = new BeanTableModel(c, cAncestor);
        table = new JTable(beanTableModel);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
    }

    public void createTable(Class c, Class cAncestor, List data) {
        beanTableModel = new BeanTableModel(c, cAncestor, data);
        table = new JTable(beanTableModel);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
        beanTableModel.fireTableDataChanged();
    }

    public void createTable(Class c) {
        beanTableModel = new BeanTableModel(c);
        table = new JTable(beanTableModel);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
    }

    public void createTable(Class c, List data)
    {
        beanTableModel = new BeanTableModel(c, data);
        table = new JTable(beanTableModel);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
    }

    //to refresh the table everytime there is an update
    public void fireTableDataChanged()
    {
        beanTableModel.fireTableDataChanged();
    }

So again, my question is: Isn't my JTable not updated with the new results every time I send new data to it?

Was it helpful?

Solution

You should never invoke fireTableDataChanged manually. Only the TableModel is responsible for invoking this event.

From your code it looks like you are creating a new TableModel, JTable and JScrollPane every time you make a change. Any time you add a component to a visible GUI the basic code should be:

panel.add(....);
panel.revalidate();
panel.repaint();

By default all components have a size of zero so since you don't invoke revalidate() then never get a proper size and there is nothing to paint. Also, it is never a good idea to simply keep adding components to the CENTER of your panel since the old component are still part of the container.

However, there is a better solution. There is no need to keep creating new components. All you need to do is create an new TableModel and then use:

table.setModel( newlyCreatedModel );

and the model will be added to the table and the table will repaint itself automatically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top