2012-03-14 95 views
3

我有一個JTable,與一個DefaultTableModel相關聯,JPanel中的SpringLayout位於JScrollPane中。Swing:JTable的結構發生變化後,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(); 
} 

任何幫助非常感謝!

+1

請1)你沒有看到更新成'JScrollPane' ???,2),但你怎麼能確定'JTable的下面是refreshed' – mKorbel 2012-03-14 17:14:18

+0

你有沒有打過電話'重新驗證()'也許'在JScrollPane的視口重繪()'?如果這沒有幫助,請考慮創建併發布[sscce](http://sscce.org)。 – 2012-03-14 21:37:08

+0

1)例如,我的JTable包含一個2 * 15表,表的大小大於容器面板的大小,因此我的JScrollPane上有一個滾動條。在用2 * 3表更新DefaultTableModel後,我看到JTable中的變化現在比容器面板小。所以滾動條應該消失,但它不會。當我再次應用該方法時,它會消失。 – 2012-03-15 10:01:02

回答

8

這裏是一個測試程序,它表明,當一個JTable是一個JScrollPane通過setDataVector(...)舉行,的DefaultTableModel的dataVector中發生變化,也沒有必要呼籲fireTableDataChanged()型號爲JTable中的數據正確地改變和正常顯示內容。

該程序的GUI看起來像下面的圖像。
數據之前更改:
enter image description here

數據更改後:
enter image description here

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中的一個JSprollPane中的SpringLayout。

爲了獲得更多更好的幫助,OP將不得不創建自己的sscce類似於(或者比我上面發佈的更簡單)。要麼是這樣,要麼通過不使用SpringLayout來保存JTable,而是直接將其添加到JScrollPane的視口視圖或使用JPanel將它添加到BorderLayout(同時添加JTable的頭部)並將其添加到JScrollPane的視口視圖。

+0

謝謝,您的解決方案工作。我的問題來自使用SpringLayout並使用BorderLayout解決問題。 – 2012-03-15 16:07:12

+0

@Hovercraft完整的鰻魚我沒有看到這個答案+1 – mKorbel 2012-03-15 21:48:26

+0

@Bastien:很高興它有幫助。每當遇到類似問題時,通常最好儘可能地隔離問題,因爲它簡化了調試過程,如果失敗了,至少會有一個小的可編譯程序在這裏發佈。 – 2012-03-15 23:16:42

6

我以前遇到過這個問題。

嘗試使JTable無效並重新繪製JScrollPane。

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

會使我非常緊張,如果隨機進入/重新/驗證和/或重新打印似乎可以解決問題;-)某處某處出錯... – kleopatra 2012-03-15 14:50:25

+0

@kleopatra:這些調用不是隨機的。他們特定於我認爲OP正在做的事情。通常,重繪您更改的Swing組件。由於JScrollPane是一個容器組件,因此當您更改JTable時,必須重新繪製容器。 – 2012-03-15 14:56:40

+0

_正常情況下,您重新繪製了一個Swing組件,您更改了__,完全沒有。通常,組件根據更改重新進行自我修復/重新驗證。如果這不會自動發生,那麼在客戶端代碼或核心代碼中就會出現問題。無論如何,它需要一個適當的軌道,而不是繪畫;-) – kleopatra 2012-03-15 15:00:39

相關問題