【问题标题】:JTable populated but not shown. Using DefaultTableModelJTable 已填充但未显示。使用 DefaultTableModel
【发布时间】:2019-06-23 04:59:10
【问题描述】:

我不明白为什么我的JTable 没有更新。

下面是我的代码:

package it.franpic.chat.client.prestazioni.view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;

import it.franpic.chat.client.prestazioni.model.RecordBean;

public class FinestraPrincipale {

    private JFrame frame;
    private JTable tabellaDati;
    private JScrollPane scrollPaneTabella;
    private JSplitPane splitPaneContenuti;

    /**
     * Launch the application.
     */
    public void avvia() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    FinestraPrincipale window = new FinestraPrincipale();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the application.
     */
    public FinestraPrincipale() {
        initialize();
    }

    /**
     * Initialize the contents of the frame.
     */
    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel pnlOpzioni = new JPanel();
        frame.getContentPane().add(pnlOpzioni, BorderLayout.NORTH);
        pnlOpzioni.setBorder(new TitledBorder(new LineBorder(new Color(0, 0, 0)), "Opzioni", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
        pnlOpzioni.setLayout(new BorderLayout(0, 0));

        JCheckBox chckbxAggiornaAutomaticamente = new JCheckBox("Aggiorna Automaticamente");
        chckbxAggiornaAutomaticamente.setEnabled(false);
        pnlOpzioni.add(chckbxAggiornaAutomaticamente);
        chckbxAggiornaAutomaticamente.setVerticalAlignment(SwingConstants.TOP);

        splitPaneContenuti = new JSplitPane();
        splitPaneContenuti.setOneTouchExpandable(true);
        splitPaneContenuti.setOrientation(JSplitPane.VERTICAL_SPLIT);
        frame.getContentPane().add(splitPaneContenuti, BorderLayout.CENTER);

        JScrollPane scrollPaneGrafico = new JScrollPane();
        splitPaneContenuti.setLeftComponent(scrollPaneGrafico);

        scrollPaneTabella = new JScrollPane();
        splitPaneContenuti.setRightComponent(scrollPaneTabella);

        tabellaDati = new JTable();
        tabellaDati.setModel(new DefaultTableModel(
            new Object[][] {
            },
            new String[] {
                "ISTANTE", "GESTITE", "DISTRIBUITE", "PIANIFICATO", "SOSTENIBILE", "LOGGATI", "LOGGATI_PIANIFICATO"
            }
        ) {
            Class[] columnTypes = new Class[] {
                String.class, Integer.class, Integer.class, Integer.class, Integer.class, Integer.class, Integer.class
            };
            public Class getColumnClass(int columnIndex) {
                return columnTypes[columnIndex];
            }
        });
        tabellaDati.getColumnModel().getColumn(3).setPreferredWidth(76);
        tabellaDati.getColumnModel().getColumn(6).setPreferredWidth(127);
        tabellaDati.setColumnSelectionAllowed(true);
        tabellaDati.setCellSelectionEnabled(true);
        scrollPaneTabella.setViewportView(tabellaDati);
    }

    public void aggiornaTabella(List<RecordBean> lista) {
        DefaultTableModel model = (DefaultTableModel) tabellaDati.getModel();
        model.setRowCount(0);
        System.out.println("tabellaDati.getRowCount() = " + tabellaDati.getRowCount());

        for (RecordBean record : lista) {
            model.addRow(new Object[]{record.getMomento(), record.getGestite(), record.getDistribuite(), record.getSostenibile(), record.getPianificato(), record.getLoggati(), record.getLoggatiPianificato()});
        }

        System.out.println("tabellaDati.getRowCount() = " + tabellaDati.getRowCount());
    }   

}

这是调用这些方法的主类的代码:

package it.franpic.chat.client.prestazioni.control;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import it.franpic.chat.client.prestazioni.model.RecordBean;
import it.franpic.chat.client.prestazioni.view.FinestraPrincipale;

public class Client {
    public static void main(String[] args) {
        FinestraPrincipale finestraPrincipale = new FinestraPrincipale();
        GestoreDb gestoreDb = new GestoreDb();


        String adessoFormatoMySql = LocalDateTime.now().format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss"));

        List<RecordBean> lista = gestoreDb.getRecordsDaDate("2019-01-26 18:00:00", adessoFormatoMySql);

        finestraPrincipale.avvia();
        finestraPrincipale.aggiornaTabella(lista);
    }
}

从其他讨论和文档中,我认为我的代码很好,但显然不是。

表格在构造时正确显示,但未通过aggiornaTabella(List&lt;RecordBean&gt; lista) 方法更新。我不知道为什么。

我在aggiornaTabella(List&lt;RecordBean&gt; lista) 中尝试过,在addRow 循环之后:

  • tabellaDati.setModel(model);
  • .invalidate() 方法在 GUI 的每个组件上(即使不推荐)
  • GUI 的每个组件上的.repaint() 方法
  • model.fire....() 方法(即使不推荐)

从 aggiornaTabella(List&lt;RecordBean&gt; lista) 方法中的 2 println 我可以看到 JTable 的行已填充但未显示。

【问题讨论】:

  • 您的代码示例中没有任何地方调用aggiornaTabella
  • 所以,我玩过你的代码,如果我打电话给aggiornaTabella,它工作得很好,问题出在你没有向我们展示的其他地方
  • 与上述相同的 cmets。也许调用该方法的代码在 EDT 上被阻塞,因此表本身永远无法 repaint()。也许您创建了类的第二个实例,而该类永远不会可见,因此您看不到第二帧。
  • 对不起,我已经添加了调用方法的类。我认为问题不在于它。非常感谢您的回复
  • 我已经提出了问题所在,您发布的代码证实了我的建议..

标签: java swing jtable defaulttablemodel


【解决方案1】:

这...

public class Client {
    public static void main(String[] args) {
        FinestraPrincipale finestraPrincipale = new FinestraPrincipale();
        GestoreDb gestoreDb = new GestoreDb();


        String adessoFormatoMySql = LocalDateTime.now().format(DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss"));

        List<RecordBean> lista = gestoreDb.getRecordsDaDate("2019-01-26 18:00:00", adessoFormatoMySql);

        finestraPrincipale.avvia();
        finestraPrincipale.aggiornaTabella(lista);
    }
}

解释很多。

首先,您创建FinestraPrincipale 的实例,加载一些数据并调用finestraPrincipale.avvia,但avvia 正在创建FinestraPrincipale 的新实例

public void avvia() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                // Hello new instance...
                FinestraPrincipale window = new FinestraPrincipale();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

显示在屏幕上,与你最初创建的实例无关(并且正在更新)

avvia 不应该创建一个新实例,它应该只是使用它自己和之前在构造它时初始化的状态......

public void avvia() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

仅此一项就可以解决您的问题

【讨论】:

  • 成功了!非常感谢!这件事刚刚从我身边逃脱了
猜你喜欢
  • 2012-05-04
  • 2020-02-21
  • 2013-01-19
  • 2021-08-21
  • 2022-01-03
  • 1970-01-01
  • 2019-07-31
  • 2020-07-23
  • 1970-01-01
相关资源
最近更新 更多