2012-01-06 18 views
9

Sütun yeniden boyutlandırıldığını algılamak için bir TableColumnModelListener() kullanan bir JTable'ım var ve columnMarginChanged() yönteminde yürütmek istediğim bir kod var. Sütun kullanıcı tarafından veya başka kodun bir sonucu olarak yeniden boy edilipJava JTable algılaması Sütun kullanıcı tarafından yeniden boyutlandırıldı

nasıl belirliyorsunuz?

ben ChangeEvent.getSource() ile başlamak zorunda ama nereye oradan gitmek bilmiyorum düşünüyorum.

Teşekkür ederiz.

+0

Bunu değiştirmediğiniz sürece, kaynak her zaman tablonun 'DefaultChieldColumnModel'idir, 'fireColumnMarginChanged()'. Ne problemi çözmeye çalışıyorsun? – trashgod

+0

yol yok. @ Trashgod'un sorusu tekrarlanıyor: neden? – kleopatra

+0

Sütun boyutunu değiştiren kodunuz varsa, değişiklikten önce dinleyiciyi her zaman devre dışı bırakabilir ya da kaldırabilir, değişikliği yapabilir ve daha sonra tepkisel hale getirebilir ya da dinleyiciyi tekrar ekleyebilirsiniz. – Robin

cevap

7

Sana olası bir yaklaşım verebilir. Ben masa başvurumu açtı sonraki sefer, uygun sütun genişliklerini yeniden böylece, diske sütun genişlikleri ile ilgili bilgileri seri hale getirmek istedim çünkü aynı sorunu çözmeye çalışıyordum. Buraya:

Adım 1 - JTable geçersiz kıl ve

class MyTable extends JTable { 

    private boolean isColumnWidthChanged; 
    public boolean getColumnWidthChanged() { 
     return isColumnWidthChanged; 
    } 

    public void setColumnWidthChanged(boolean widthChanged) { 
     isColumnWidthChanged = widthChanged; 
    } 

} 

Adım 2 buna bir boole özelliği eklemek - (a TableColumnModelListener ekle) masanın

private class TableColumnWidthListener implements TableColumnModelListener 
{ 
    @Override 
    public void columnMarginChanged(ChangeEvent e) 
    { 
     /* columnMarginChanged is called continuously as the column width is changed 
      by dragging. Therefore, execute code below ONLY if we are not already 
      aware of the column width having changed */ 
     if(!tableObj.hasColumnWidthChanged()) 
     { 
      /* the condition below will NOT be true if 
       the column width is being changed by code. */ 
      if(tableObj.getTableHeader.getResizingColumn() != null) 
      { 
       // User must have dragged column and changed width 
       tableObj.setColumnWidthChanged(true); 
      } 
     } 
    } 

    @Override 
    public void columnMoved(TableColumnModelEvent e) { } 

    @Override 
    public void columnAdded(TableColumnModelEvent e) { } 

    @Override 
    public void columnRemoved(TableColumnModelEvent e) { } 

    @Override 
    public void columnSelectionChanged(ListSelectionEvent e) { } 
} 

için Adım 3 - tablo başlığındaki

bir fare dinleyicisi ekleyin
private class TableHeaderMouseListener extends MouseAdapter 
{ 
    @Override 
    public void mouseReleased(MouseEvent e) 
    { 
     /* On mouse release, check if column width has changed */ 
     if(tableObj.getColumnWidthChanged()) 
     { 
      // Do whatever you need to do here 

      // Reset the flag on the table. 
      tableObj.setColumnWidthChanged(false); 
     } 
    } 
} 

NOT: Uygulamamda, TableHeaderMouseListener ve TableColumnWidthListener sınıfları, ana uygulama sınıfımın özel iç sınıflarıydı. Ana uygulama sınıfım, gözlemlenen tablonun bir referansına tutuldu. Bu nedenle, bu iç sınıflar tablo örneğine erişime sahipti. Açıkçası, kurulumunuza bağlı olarak, tablo örneğini bu diğer sınıflara sunmak için uygun olan şeyi yapmanız gerekir. Bu yardımcı olur umarım!

+0

(gereksiniminizi tam olarak almayın - neden genişlikleri her zaman kaydetmiyorsunuz?) - ama işaretleyiciye gelince: imleci kullanmak yerine, zaten belirttiğiniz gibi, son derece kırılgan olan :-) başlığın resizingColumn: bu!= Sadece kullanıcı tarafından bir yeniden boyutlandırma devam ederken null. Bu şekilde JXTableHeader, yeniden boyutlandırırken bile bir tür tetiklemeye neden olan can sıkıcı çekirdek hatasını paketlemeyi ve düzeltmeyi destekler ... – kleopatra

+1

Belirtildiği gibi, bir yaklaşım, uygulama kapatıldığında tüm sütun genişliklerini serileştirmektir (belki windowClosing yöntemiyle). bir WindowListener). Bu soruyu gönderen kişi için doğru yaklaşım olabilir. Sütun genişliklerini kademeli olarak serilatmamın nedeni, JTable'ımın her satır/sütun oluşturulduğunda/imha edildiğinde imha edilmesi ve sıfırdan yeniden oluşturulmasıdır. (Bu tuhaf görünebilir, ancak bunun bir kamu forumunda açıklayamamam için bir nedeni var.) Bu yüzden orijinal genişlikleri geri almanın tek yolu, onları aşamalı olarak serileştirmektir. – eternaln00b

+0

Belki biraz daha detay verebilirim. :) Görüyorsunuz, JTable'm daha sofistike bir arka plan için bir giriş formu. Kullanıcı, uygulamamdaki JTable'da değişiklik yaptığında, arka planda kullanıcı için bazı şeyler otomatik olarak oluşturulur. Yani JTable'ım esasen bir sihirbaz. Tablonun arka planda otomatik olarak oluşturulmuş olanı tam olarak yansıttığından emin olmak için, otomatik olarak oluşturulmuş nesneleri ayrıştırmalı ve tabloyu yeniden oluşturmalıyım. Bunu yapmazsam, tablonun ve otomatik oluşturulmuş nesnelerin birbirinden ayrılmaya başladığı ve artık tek bir hakikatin olmadığı (programlama hatası nedeniyle) bir tehlike vardır. – eternaln00b

4

Tipik bir tamamlanmış sütun sürükleme veya tamamlanmış sütun boyutlandırmak bildirilmesini istiyoruz. Örneğin.

interface SGridModel { 
    public void columnMoved(int oldLocation, int newLocation); 
    public void columnResized(int column, int newWidth); 
}   

Bu hoş değil ama ne istediğinizi yapacağız şu şekildedir:

class SColumnListener extends MouseAdapter implements TableColumnModelListener { 

    private final Logger log = Logger.getLogger(getClass()); 
    private final SGridModel model; 

    private int oldIndex = -1; 
    private int newIndex = -1; 
    private boolean dragging = false; 

    private boolean resizing = false; 
    private int resizingColumn = -1; 
    private int oldWidth = -1; 

    SColumnListener(SGridModel model){ 
     this.model = model; 
    } 

    @Override 
    public void mousePressed(MouseEvent e) { 
     // capture start of resize 
     if(e.getSource() instanceof JTableHeader) { 
      TableColumn tc = ((JTableHeader)e.getSource()).getResizingColumn(); 
      if(tc != null) { 
       resizing = true; 
       resizingColumn = tc.getModelIndex(); 
       oldWidth = tc.getPreferredWidth(); 
      } else { 
       resizingColumn = -1; 
       oldWidth = -1; 
      } 
     } 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) { 
     // column moved 
     if(dragging && oldIndex != newIndex) { 
      model.columnMoved(oldIndex, newIndex); 
      log.info("column moved: " +oldIndex+" -> "+newIndex); 
     } 
     dragging = false; 
     oldIndex = -1; 
     newIndex = -1; 


     // column resized 
     if(resizing) { 
      if(e.getSource() instanceof JTableHeader) { 
       TableColumn tc = ((JTableHeader)e.getSource()).getColumnModel().getColumn(resizingColumn); 
       if(tc != null) { 
        int newWidth = tc.getPreferredWidth(); 
        if(newWidth != oldWidth) { 
         model.columnResized(resizingColumn, newWidth); 
         log.info("column resized: " +resizingColumn+" -> "+newWidth); 
        } 
       } 
      } 
     } 
     resizing = false; 
     resizingColumn = -1; 
     oldWidth = -1; 
    } 

    @Override 
    public void columnAdded(TableColumnModelEvent e) {  
    } 

    @Override 
    public void columnRemoved(TableColumnModelEvent e) {   
    } 

    @Override 
    public void columnMoved(TableColumnModelEvent e) { 
     // capture dragging 
     dragging = true; 
     if(oldIndex == -1){ 
      oldIndex = e.getFromIndex(); 
     } 

     newIndex = e.getToIndex(); 
    } 

    @Override 
    public void columnMarginChanged(ChangeEvent e) { 
    } 

    @Override 
    public void columnSelectionChanged(ListSelectionEvent e) { 
    } 
} 

tabloya ekleyin:

table.getColumnModel().addColumnModelListener(cl); 
table.getTableHeader().addMouseListener(cl); 
0

Daha basit bir çözüm sadece dinlemek olabilir fare serbest bırakma olayında (bu kullanıcı etkileşiminde yalnızca bir kez gerçekleşir) ve bu sırada sütun boyutlarının değişip değişmediğini kontrol edin. Sütun yeniden sıralama ve boyut değişikliklerini dinlemek için aşağıdaki kodu kullanıyorum.