JTable不想显示内容

时间:2016-02-14 17:53:22

标签: java swing jtable

我试图从JSONArray中显示表格。但结果永远不会出现。通过调用此initTable()方法,该表已显示正确的列名。 initTable()如下:

private void initTable() {
    contentPane.removeAll();

    PrintTableModel tblModel = new PrintTableModel();

    DefaultTableColumnModel columns = new DefaultTableColumnModel();
    TableColumn c;

    c = new TableColumn();
    c.setHeaderValue(columnNames[0]);
    columns.addColumn(c);

    c = new TableColumn();
    c.setHeaderValue(columnNames[1]);
    columns.addColumn(c);

    c = new TableColumn();
    c.setHeaderValue(columnNames[2]);
    columns.addColumn(c);

    c = new TableColumn();
    c.setHeaderValue(columnNames[3]);
    columns.addColumn(c);

    listTable = new JTable(tblModel, columns);
    listTable.getTableHeader().setReorderingAllowed(false);

    JScrollPane scrollPane = new JScrollPane();
    scrollPane.add(listTable);
    scrollPane.setViewportView(listTable);
    contentPane.add(scrollPane, BorderLayout.CENTER);       
}

我从这样的线程调用刷新表:

public class RetrievePrintRequest extends Thread {
    private boolean speedUp = false;

    public void run() {
        if (loginId == 0)
            return;

        try {
            String token = generateLink("prc_admin_id=" + loginId);
            do {
                JSONArray jsonresult = readJsonFromUrl(BASE_URL + "ajax/get_latest_print?code=" + token);

                // looping through All elements
                // list holding row data
                List<PrintModel> printList = new ArrayList<PrintModel>();
                for (int i = 0; i < jsonresult.length(); i++) {
                    JSONObject c = jsonresult.getJSONObject(i);

                    // Storing each json item in variable
                    int printId = c.getInt("print_id");
                    String bookingCode = c.getString("booking_code");
                    long startDate = c.getLong("start_date");
                    String patientName = c.getString("patient_name");
                    String doctorName = c.getString("doc_name");

                    PrintModel printModel = new PrintModel(
                            printId, bookingCode, patientName, doctorName, new Date(startDate));
                    // add rest of the json data to NodePOJO class

                    System.out.println(printId + ";" + bookingCode + ";" + startDate + ";" + patientName + ";" + doctorName);
                    // the object to list
                    printList.add(printModel);
                }
                PrintTableModel printModel = (PrintTableModel) listTable.getModel();
                printModel.refresh(printList); //<--- I expect this to refresh the table content
                Thread.sleep(!speedUp ? 10000 : 60000);
            } while(true);
        } catch (JSONException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

这是TableModel中的刷新方法(添加整个PrintTableModel类)

protected class PrintTableModel extends DefaultTableModel {
        private List<PrintModel> listData;

        public void refresh(List<PrintModel> data) {
            listData = data; // <== refresh with new List and call fireTableDataChanged
            fireTableDataChanged();
        }

        public Object getValueAt(int row, int column) {
            Object result = null;

            PrintModel model = (PrintModel)listData.get(row);
            switch (column)
            {
                case 0:
                    result = model.getBookingCode();
                    break;
                case 1:
                    result = SDF.format(model.getAppointmentDate());
                    break;
                case 2:
                    result = model.getPatientName();
                    break;
                case 3:
                    result = model.getDoctorName();
                    break;      
            }
            return result;
        }

        public Class getColumnClass(int column) {
            switch (column)
            {
                case 0:
                    return String.class;
                case 1:
                    return String.class;
                case 2:
                    return String.class;            
                case 3:
                    return String.class;
            }
            return null;
        }

任何人都可以发现我的错误?非常感谢。

3 个答案:

答案 0 :(得分:3)

您正在从未与Event Dispatch Thread(EDT)同步的主题更新UI:

  

Swing事件处理代码在称为事件派发线程的特殊线程上运行。大多数调用Swing方法的代码也在这个线程上运行。 这是必要的,因为大多数Swing对象方法不是&#34;线程安全&#34;:从多个线程调用它们可能会导致线程干扰或内存一致性错误

Swing 线程安全,因此您需要使用SwingUtilities.invokeLater更新用户界面。

来自SwingUtilities.invokeLater的文档:

  

导致doRun.run()在AWT事件派发线程上异步执行。这将在处理完所有挂起的AWT事件后发生。 当应用程序线程需要更新GUI时,应使用此方法。

PS:使用这种方法将表格添加到内容窗格中:

contentPane.add(new JScrollPane(listTable), BorderLayout.CENTER);

答案 1 :(得分:3)

添加到什么TT。已经说过......

对于for-loop的迭代,你可以这样做......

    PrintModel printModel = new PrintModel(printId, bookingCode, patientName, doctorName, new Date(startDate));
    // add rest of the json data to NodePOJO class

    System.out.println(printId + ";" + bookingCode + ";" + startDate + ";" + patientName + ";" + doctorName);
    // the object to list
    printList.add(printModel);
}

处理完每个&#34;行&#34;后,你就这样做了......

PrintTableModel printModel = (PrintTableModel) listTable.getModel();
printModel.refresh(printList); //<--- I expect this to refresh the table content

这里的问题是,您在PrintModelfor-loop与您尝试刷新的关系有什么关系?

相反,您应该在PrintTableModel开始之前创建for-loop的新实例,将每行数据添加到此PrintTableModel实例,然后(在同步之后)致电EDT)将此PrintTableModel实例应用于JTable

OR

使用SwingWorkerpublish每行数据,并在PrintTableModel时添加JTable的当前实例(来自process)。

有关详细信息,请参阅Concurrency in JavaWorker Threads and SwingWorker

答案 2 :(得分:1)

答案: 它没有用,因为DefaultTableModel拥有它自己的Vector数据,并且在调用fireTableDataChanged()时创建新的没有受到影响。所以,我猜DefaultTableModel没有设计要扩展,而是用作标准的TableModel。 Java为扩展目的提供了AbstractTableModel。

所以,这是从AbstractTableModel扩展的新代码:

protected class PrintTableModel extends AbstractTableModel {
    private List<PrintModel> listData = new ArrayList<PrintModel>();
    protected String[] columnNames;

    public int getRowCount() {
        return listData.size();
    }

    public void setColumnNames(String[] columnNames) {
        this.columnNames = columnNames;
    }

    public String getColumnName(int column) {
        return columnNames[column];
    }

    public int getColumnCount() {
        return columnNames.length;
    }

    public void add(Object obj) {
        listData.add(0, (PrintModel)obj);
        fireTableRowsInserted(listData.size() - 1, listData.size() - 1);
    }

    public void update(Object obj, int row) {
        listData.set(row, (PrintModel)obj);
        fireTableRowsUpdated(row, row);
    }

    public void remove(int row) {
        listData.remove(row);
        fireTableRowsDeleted(row, row);
    }

    public Object getObjectAt(int row) {
        return listData.get(row);
    }

    public void refresh(List<PrintModel> data) {
        listData = data;
        fireTableDataChanged();
    }

    public Object getValueAt(int row, int column) {
        Object result = null;

        PrintModel model = (PrintModel)listData.get(row);
        switch (column)
        {
            case 0:
                result = model.getBookingCode();
                break;
            case 1:
                result = SDF.format(model.getAppointmentDate());
                break;
            case 2:
                result = model.getPatientName();
                break;
            case 3:
                result = model.getDoctorName();
                break;  
            case 4:
                result = "Print";
                break;                  
        }
        return result;
    }

    public Class getColumnClass(int column) {
        switch (column)
        {
            case 0:
                return String.class;
            case 1:
                return String.class;
            case 2:
                return String.class;            
            case 3:
                return String.class;
            case 4:
                return String.class;                    
        }
        return null;
    }       
}