为什么 JXTable 丢失输入而 JTable 没有?
Why is JXTable losing input where JTable is not?
当我使用 JXTable 来呈现和编辑我的数据时,CellEditors 中的某些输入会丢失。
如果我单击 JXTable-ColumnHeader 的 Resizing-Divider 或更改 JFrame 的宽度,CellEditor 将在不提交值的情况下终止。如果我使用 JTable,这些值将被保存。
我想使用 JXTable 因为它的其他功能,那么有没有办法修复 JXTable?
示例:
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();
}
} );
}
}
当您查看 JTable 的 frameInit() 方法时,您会发现它绑定到所有 AWTEvent.WINDOW* 事件。在 JXTable 中,initActionsAndBindings() 方法绑定到特定的操作(例如更改值),并且仅针对 table。
您需要添加自己的侦听器
jXTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnMarginChanged(ChangeEvent e) {
}
});
然后必须公开 table 的某些功能以允许事件触发更新 table。或者您可以从那里触发 TableModelEvent。
在调试 JXTable
和 JTable
时,我找到了 CellEdits 丢失的原因。
区别在于方法columnMarginChanged()
:
JXTable:
if (isEditing()) {
removeEditor();
}
JTable:
if (isEditing() && !getCellEditor().stopCellEditing()) {
getCellEditor().cancelCellEditing();
}
起初我认为 removeEditor()
方法是 JTable
的增强...但后来我发现这个 OpenJDK changeset from September 2010 修复了错误 "4330950 : 调整列宽大小时丢失单元格中新输入的数据。 JDK 中的更改似乎并未应用于 SwingX 源代码。
我会接受我自己的回答,因为不同行为的原因现在很清楚了。
为了为我和其他 SwingX 用户解决这个问题,我将前往 SwingX 邮件列表和错误跟踪器。
当我使用 JXTable 来呈现和编辑我的数据时,CellEditors 中的某些输入会丢失。 如果我单击 JXTable-ColumnHeader 的 Resizing-Divider 或更改 JFrame 的宽度,CellEditor 将在不提交值的情况下终止。如果我使用 JTable,这些值将被保存。
我想使用 JXTable 因为它的其他功能,那么有没有办法修复 JXTable?
示例:
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();
}
} );
}
}
当您查看 JTable 的 frameInit() 方法时,您会发现它绑定到所有 AWTEvent.WINDOW* 事件。在 JXTable 中,initActionsAndBindings() 方法绑定到特定的操作(例如更改值),并且仅针对 table。
您需要添加自己的侦听器
jXTable.getColumnModel().addColumnModelListener(new TableColumnModelListener() {
@Override
public void columnMarginChanged(ChangeEvent e) {
}
});
然后必须公开 table 的某些功能以允许事件触发更新 table。或者您可以从那里触发 TableModelEvent。
在调试 JXTable
和 JTable
时,我找到了 CellEdits 丢失的原因。
区别在于方法columnMarginChanged()
:
JXTable:
if (isEditing()) {
removeEditor();
}
JTable:
if (isEditing() && !getCellEditor().stopCellEditing()) {
getCellEditor().cancelCellEditing();
}
起初我认为 removeEditor()
方法是 JTable
的增强...但后来我发现这个 OpenJDK changeset from September 2010 修复了错误 "4330950 : 调整列宽大小时丢失单元格中新输入的数据。 JDK 中的更改似乎并未应用于 SwingX 源代码。
我会接受我自己的回答,因为不同行为的原因现在很清楚了。 为了为我和其他 SwingX 用户解决这个问题,我将前往 SwingX 邮件列表和错误跟踪器。