2008-10-31 44 views
14

我們看到JTable選項在我們執行fireTableDataChanged()fireTableRowsUpdated()時從TableModel被清除。跨TableModel保留JTable選擇

這是預期的,還是我們做錯了什麼?我沒有在JTable(或其他相關類別)上看到有關清除/保留模型更新選擇的任何屬性。

如果這是默認行爲,是否有避免這種情況的好方法?也許某種方式可以在更新之前「鎖定」選擇並在之後解鎖?

開發人員一直在嘗試在更新之前保存選擇並重新應用它。這有點慢。

這是Windows XP上的Java 1.4.2,如果有問題的話。我們僅限於基於我們使用的某些供應商代碼的版本。

回答

4

你需要保存的選擇,然後再應用它。

首先,您需要獲取所有選定單元格的列表。

然後,當您用新數據重新載入JTable時,需要以編程方式重新應用這些相同的選擇。

我想說的另一點是,如果表格中的數字或行或列在每個表模型重新加載後增加或減少,請不要打擾保留選擇。

在模型更新之前,用戶可能已經選擇了行2列1,其值爲「Duck」。但是在模型更新之後,現在可以在第4行第1列中出現相同的數據,並且原始單元格第2行第1列可能會有新數據,例如「Pig」。現在,如果您強行將選擇設置爲模型更新之前的選擇,則可能不是用戶想要的。

因此以編程方式選擇單元可能是一把雙刃劍。不要這樣做,如果你不確定。

0

如果我沒有記錯,選擇保存並重新應用它是我們所做的太...

1

這是默認行爲。如果您撥打fireTableDataChanged(),整個表格將在您設置全新模型時從頭開始重建。在這種情況下,選擇自然會丟失。如果您撥打fireTableRowsUpdated(),則在一般情況下也會清除所選內容。唯一的方法是記住選擇,然後設置它。不幸的是,不能保證選擇仍然有效。如果恢復選擇,請小心。

0

我在應用程序中遇到同樣的問題。在我的情況下,表中的模型是對象列表,其中映射到列的對象屬性在哪裏。在這種情況下,當列表被修改時,我檢索了選定的索引並存儲了在更新列表之前選擇的對象。列表被修改後,表格被更新之前,我會計算所選對象的位置。如果它在修改後仍然存在,那麼我會將選擇設置爲新索引。

只是在修改後在表格中設置選定的索引將不起作用,因爲對象可能會改變列表中的位置。

作爲一個方面說明,我發現使用GlazedLists在處理表格時使生活變得更加容易。

4

如果該表的結構沒有改變(即,如果您沒有添加/刪除任何列/行),您可以自動保留表的選擇,如下所示。

如果你寫自己的實現TableModel的,你可以簡單地覆蓋fireTableDataChanged()方法:

 @Override 
     public void fireTableDataChanged() { 
      fireTableChanged(new TableModelEvent(this, //tableModel 
               0, //firstRow 
               getRowCount() - 1, //lastRow 
               TableModelEvent.ALL_COLUMNS, //column 
               TableModelEvent.UPDATE)); //changeType 
     } 

,這應該確保你的選擇是保持規定,只有數據,而不是結構的表已經改變了。這個之間的唯一區別,以及如果這個方法沒有被覆蓋會被調用的是getRowCount() - 1傳遞給lastRow參數而不是Integer.MAX_VALUE,後者作爲一個指示符,不僅包含所有的表格中的數據已更改,但行數也可能已更改。

+0

要注意:這樣做可能會適得其反 - dataChanged可能包含插入/刪除。如果是這樣的話,聽衆可能會被嚴重誤導 – kleopatra 2012-03-20 17:16:11

0

我面臨同樣的問題,當試圖尋找原因我得到了這個問題,但它似乎是Java SDK中的錯誤。 http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786

解決

的臨時解決辦法是可用的。一旦這個錯誤得到解決,它應該被移除,因爲它的適用性尚未針對固定版本進行測試。

使用這個JTable的子類。

注意:這是用於MetalLookAndFeel。如果使用其他外觀和感覺,內部的FixedTableUI子類將不得不擴展TableUI子類以獲得該外觀。

import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 
import javax.swing.table.*; 
import javax.swing.event.*; 
import javax.swing.plaf.basic.*; 

public class FixedTable extends JTable { 

    private boolean isControlDownInDrag; 

    public FixedTable(TableModel model) { 
     super(model); 
     setUI(new FixedTableUI()); 
    } 

    private class FixedTableUI extends BasicTableUI { 
     private MouseInputHandler handler = new MouseInputHandler() { 
      public void mouseDragged(MouseEvent e) { 
       if (e.isControlDown()) { 
        isControlDownInDrag = true; 
       } 
       super.mouseDragged(e); 
      } 

      public void mousePressed(MouseEvent e) { 
       isControlDownInDrag = false; 
       super.mousePressed(e); 
      } 

      public void mouseReleased(MouseEvent e) { 
       isControlDownInDrag = false; 
       super.mouseReleased(e); 
      } 
     }; 

     protected MouseInputListener createMouseInputListener() { 
      return handler; 
     } 
    } 

    public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) { 
     if (isControlDownInDrag) { 
      ListSelectionModel rsm = getSelectionModel(); 
      ListSelectionModel csm = getColumnModel().getSelectionModel(); 

      int anchorRow = rsm.getAnchorSelectionIndex(); 
      int anchorCol = csm.getAnchorSelectionIndex(); 

      boolean anchorSelected = isCellSelected(anchorRow, anchorCol); 

      if (anchorSelected) { 
       rsm.addSelectionInterval(anchorRow, rowIndex); 
       csm.addSelectionInterval(anchorCol, columnIndex); 
      } else { 
       rsm.removeSelectionInterval(anchorRow, rowIndex); 
       csm.removeSelectionInterval(anchorCol, columnIndex); 
      } 

      if (getAutoscrolls()) { 
       Rectangle cellRect = getCellRect(rowIndex, columnIndex, false); 
       if (cellRect != null) { 
        scrollRectToVisible(cellRect); 
       } 
      } 
     } else { 
      super.changeSelection(rowIndex, columnIndex, toggle, extend); 
     } 
    } 
} 

注意屈膝禮來http://bugs.sun.com

1

參考,如@Swapnonil慕克吉說,這並獲得成功與可選行的表:

 // preserve selection calling fireTableDataChanged() 
     final int[] sel = table.getSelectedRows(); 

     fireTableDataChanged(); 

     for (int i=0; i<sel.length; i++) 
      table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);