2015-01-30 10 views
8

Verilerimi oluşturmak ve düzenlemek için bir JXTable kullandığımda, CellEditor'lara bazı girişler kaybolur. JXTable-ColumnHeader'ın Yeniden Boyutlandırır-Bölücüsünü tıklatırsam veya JFrame'in genişliğini değiştirirsem, CellEditor değeri taahhüt etmeden sonlandırılır. JTable'ı kullanırsam değerler kaydedilir.JTTable neden JTTable'ı kaybetmiyor?

Diğer özellikleri nedeniyle JXTable'ı kullanmak istiyorum, bu yüzden JXTable'ı düzeltmenin bir yolu var mı?

Screenrecording

Örnek:

package table.columnresize; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.table.DefaultTableModel; 

import org.jdesktop.swingx.JXTable; 

/** 
* Demo of differing behaviour of JXTable and JTable. JXTable loses input in a TableCell where JTable persists 
* it. 
* <p> 
* <table border=1> 
* <tr> 
* <th></th> 
* <th>JXTable</th> 
* <th>JTable</th> 
* </tr> 
* <tr> 
* <td>Click on TableColumnHeader</td> 
* <td>saved</td> 
* <td>saved</td> 
* </tr> 
* <tr> 
* <td>Resizing with Divider of TableColumnHeader</td> 
* <td>lost</td> 
* <td>saved</td> 
* </tr> 
* <tr> 
* <td>Changing the width of JFrame</td> 
* <td>lost</td> 
* <td>saved</td> 
* </tr> 
* 
* </table> 
* </p> 
* 
* @author bobndrew 2015-01-29 
*/ 
public class JXTableAndJTableEditLossDemo 
{ 
    private static class DataModel extends DefaultTableModel 
    { 
    public DataModel(Object[][] data, Object[] columnNames) 
    { 
     super(data, columnNames); 
    } 
    } 

    private static void createAndShowUI() 
    { 
    Object[][] DATA = { { "One", 1 }, { "Two", 2 }, { "Three", 3 }, { "Four", 4 }, { "Five", 5 } }; 
    String[] COLUMNS = { "A", "B" }; 
    DataModel dataModel = new DataModel(DATA, COLUMNS); 

    JFrame frame1 = new JFrame("JXTable"); 
    JXTable jXTable = new JXTable(dataModel); 
    //does not change anything: jXTable.setTerminateEditOnFocusLost(true); 
    System.out.println(jXTable.isTerminateEditOnFocusLost()); 
    frame1.add(new JScrollPane(jXTable)); 
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame1.pack(); 
    frame1.setVisible(true); 

    JFrame frame2 = new JFrame("JTable"); 
    JTable jTable = new JTable(dataModel); 
    //does not change anything: jTable.putClientProperty("terminateEditOnFocusLost", Boolean.FALSE); 
    System.out.println(jTable.getClientProperty("terminateEditOnFocusLost")); 
    frame2.add(new JScrollPane(jTable)); 
    frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame2.pack(); 
    frame2.setLocation((int) frame1.getLocation().getX() + frame1.getWidth() + 100, (int) frame1 
     .getLocation().getY()); 
    frame2.setVisible(true); 
    } 

    public static void main(String[] args) 
    { 
    java.awt.EventQueue.invokeLater(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
     createAndShowUI(); 
     } 
    }); 
    } 

} 
+0

JXTable'a özel bir odak dinleyicisi eklemeye çalıştınız mı? Bu yayının 2. ve 3. yanıtlarına bakın. http://stackoverflow.com/questions/1652942/can-a-jtable-save-data-whenever-a-cell-loses-focus –

+0

İyi bir fikir, ancak bir FocusListener farklı OperatingSystems altında çok güvenilmez. – bobndrew

cevap

3

JXTable ve JTable hatalarını ayıklarken, CellEdits kaybının nedenini buldum.

JXTable:

if (isEditing()) { 
    removeEditor(); 
} 

JTable: fark yönteminde columnMarginChanged() olduğunu ben removeEditor() yöntem JTable bir büyümesidir düşünce İlk başta

if (isEditing() && !getCellEditor().stopCellEditing()) { 
    getCellEditor().cancelCellEditing(); 
} 

... Ama sonra numaralı hatayı düzelten bu OpenJDK changeset from September 2010'u buldu. "4330950: Sütun genişliğini yeniden boyutlandırırken yeni girilen veriyi sil". JDK'daki değişikliklerin SwingX kaynak koduna uygulanmadığı görülüyor.

Kendi yanıtımı kabul edeceğim çünkü farklı davranışların nedeni açık. Bu ve diğer SwingX kullanıcıları için bunu düzeltmek için SwingX posta listesine ve hata izleyicisine gideceğim.

1

Eğer JTable frameInit() yöntemine bakmak, bunun tüm AWTEvent.WINDOW * olaylara bağlandığını görebilirsiniz. JXTable'da initActionsAndBindings() yöntemi, belirli eylemlere (örneğin değer değişti) ve yalnızca tabloya bağlanır. Bundan sonra kendi dinleyici

jXTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() { 
     @Override 
     public void columnMarginChanged(ChangeEvent e) { 

     } 
    }); 

ekleyip gerekecektir

olay tablosunu güncellemek tetiklemek için izin tablonun bazı işlevlerinin açığa gerekir. Ya da belki de bir TableModelEvent'i buradan tetikleyebilirsiniz.

+0

'frameInit()', JFrame.java'daki bir yöntemdir ve 'JTable.java' değil. Ama 'TableColumnModelListener' ve 'columnMarginChanged()' ile olan fikriniz bulgularıma benzer; cevabımı gör. – bobndrew