Swing:在JTable结构发生变化后,JScrollPane不会刷新

我有一个JTable,与一个DefaultTableModel相关联,在JPanel中有一个SpringLayout,它位于JScrollPane中。

当我使用下面的方法修改DefaultTableModel的结构时,JTable会刷新,但不会刷新JScrollPane。 我必须第二次应用此方法来刷新JScrollPane。

public void updateProjectView() { SwingProjectViewerController spvc = SwingProjectViewerController. getInstance(); this.projectTitle.setText(spvc.getAcronym() + " : " + spvc.getTitle()); Object[][] tableContent = spvc.getCriteria(CriteriaPreselectionController.getInstance(). getCriteriaPreselection()); Object[] columnsName = new Object[]{"Col1", "Col2"}; this.tableModel.setDataVector(tableContent, columnsName); this.tableModel.fireTableStructureChanged(); } 

任何帮助非常感谢!

这是一个测试程序,它显示当JScrollPane持有JTable并且通过setDataVector(...)更改DefaultTableModel的DataVector时,没有必要在模型上调用fireTableDataChanged()以使JTable的数据正确更改并且正确看待。

程序GUI看起来像下面的图像。
在数据更改之前:
在此处输入图像描述

数据更改后:
在此处输入图像描述

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import javax.swing.*; import javax.swing.table.DefaultTableModel; @SuppressWarnings("serial") public class ScrollPaneRefresh extends JPanel { private static final int PREF_W = 600; private static final int PREF_H = 200; private Integer[][] initialData = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}, {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}, {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0} }; private Integer[][] newData = { {1, 2}, {3, 4} }; private String[] columnNames = {"Col1", "Col2"}; private TablePanel gregsPanel = new TablePanel("With fireTableDataChanged", initialData, columnNames); private TablePanel myPanel = new TablePanel("Without fireTableDataChanged", initialData, columnNames); public ScrollPaneRefresh() { gregsPanel.setButtonAction(new AbstractAction("Change Table Data") { private boolean changeToNewData = true; @Override public void actionPerformed(ActionEvent evt) { if (changeToNewData) { gregsPanel.setTableModelDataVector(newData, columnNames); } else { gregsPanel.setTableModelDataVector(initialData, columnNames); } gregsPanel.fireTableDataChanged(); changeToNewData = !changeToNewData; } }); myPanel.setButtonAction(new AbstractAction("Change Table Data") { private boolean changeToNewData = true; @Override public void actionPerformed(ActionEvent evt) { if (changeToNewData) { myPanel.setTableModelDataVector(newData, columnNames); } else { myPanel.setTableModelDataVector(initialData, columnNames); } // myPanel.getScrollPane().getViewport().revalidate(); changeToNewData = !changeToNewData; } }); setLayout(new GridLayout(1, 0)); add(gregsPanel.getMainPanel()); add(myPanel.getMainPanel()); } @Override // so scrollbars will show public Dimension getPreferredSize() { return new Dimension(PREF_W, PREF_H); } private static void createAndShowGui() { ScrollPaneRefresh mainPanel = new ScrollPaneRefresh(); JFrame frame = new JFrame("ScrollPaneRefresh"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(mainPanel); frame.pack(); frame.setLocationByPlatform(true); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGui(); } }); } } class TablePanel { private JPanel mainPanel = new JPanel(); private DefaultTableModel dm; private JTable table = new JTable(); private JButton changeTableBtn = new JButton(); private JScrollPane scrollpane = new JScrollPane(table); public TablePanel(String title, Object[][] data, Object[] columnNames) { dm = new DefaultTableModel(data, columnNames); table.setModel(dm); JPanel btnPanel = new JPanel(); btnPanel.add(changeTableBtn); mainPanel.setBorder(BorderFactory.createTitledBorder(title)); mainPanel.setLayout(new BorderLayout(5, 5)); mainPanel.add(scrollpane, BorderLayout.CENTER); mainPanel.add(btnPanel, BorderLayout.PAGE_END); } public void setButtonAction(Action action) { changeTableBtn.setAction(action); } public void setTableModelDataVector(Object[][] data, Object[] columnNames) { dm.setDataVector(data, columnNames); } public void fireTableDataChanged() { dm.fireTableDataChanged(); } public JScrollPane getScrollPane() { return scrollpane; } public JComponent getMainPanel() { return mainPanel; } } 

上面我的例子的不足之处在于它没有重现原始海报的问题,我认为这是由于我们使用SpringLayout,他没有完全描述或显示代码:

我有一个JTable,与一个DefaultTableModel相关联,在JPanel中有一个SpringLayout,它位于JScrollPane中。

为了获得更多更好的帮助,OP必须创建与我上面发布的类似(或更简单)相似(或更简单)的sscce 。 或者是,或者通过不使用SpringLayout来保存JTable来解决他的问题,而是将其直接添加到JScrollPane的视口视图中,或者使用JPanel将其添加到BorderLayout(注意也添加JTable的头部)并将其添加到JScrollPane的视口视图。

我以前遇到过这个问题。

尝试使JTable无效并重新绘制JScrollPane。

 table.invalidate(); scrollPane.repaint(); 

尝试在表上调用revalidate()方法。 根据JScrollPanel http://docs.oracle.com/javase/tutorial/uiswing/components/scrollpane.html#update – “动态更改客户端大小”的规范,此方法应通知滚动面板。

 table.revalidate();