0

I have a JXTable with two columns that hold string values and one column that holds a date time value that follows this format: yyyy-MM-dd HH:mm:ss.

Since I only care about the users changing the date, I thought I'd make use of DatePickerCellEditor from the Swingx package with a custom SimpleDateFormat("yyyy-MM-dd HH:mm:ss").

So far so good, except the problems start to occur when editing starts. The date part of the datetime is maintained, however, the time portion of it gets reset to "00:00:00" and to make matters worse, when I move to edit another cell, the value that remains in the cell that was being edited is the proper date, but the time at 00:00:00.

In other words, this Before edit becomes this enter image description here

I have tried many things to fix this, including overriding the getTableCellEditorComponent from DatePickerCellEditor and printing the date directly from the JXDatePicker. I found out that somewhere along the way, the time part of the day was being reset to "00:00:00". I couldn't find out where. I then tried, within the getTableCellEditorComponent, manually setting the date by using JXDatePicker#setDate and that also didn't work.

One workaround I found was, inside getTableCellEditorComponent, calling JXDatePicker#getEditor and manually setting the date there, however, the time part of the cell value still gets reset when editing stops.

public class SQLDatePickerCellEditor extends DatePickerCellEditor {

    public SQLDatePickerCellEditor(DateFormat dateFormat) {
        super(dateFormat);
    }

    @Override
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        JXDatePicker picker = (JXDatePicker) super.getTableCellEditorComponent(table, value, isSelected, row, column);
        picker.getEditor().setText(value.toString());
        System.out.println(picker.getDate()); //this prints the correct date but for some reason at 00:00:00
        return picker;
    }

}

Here's the sample code to work with:

public class DateForm extends javax.swing.JFrame {

    public DateForm() {
        initComponents();
        pack();
        setLocationRelativeTo(null);
        initModel();
    }

    public void initModel() {
        Class<?>[] types = new Class<?>[]{String.class, String.class, Date.class};
        Object[][] data = new Object[][]{
            {"John", "Smith", new Date(System.currentTimeMillis())}
        };
        DefaultTableModel model = new DefaultTableModel(data, new String[]{"Name", "Surname", "Date"}) {
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                return types[columnIndex];
            }
        };

        table.setModel(model);
        table.getColumn(2).setCellEditor(new DatePickerCellEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));
        StringValue sv = new FormatStringValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        TableCellRenderer r = new DefaultTableRenderer(sv);
        table.getColumn(2).setCellRenderer(r);
    }

    @SuppressWarnings("unchecked")                      
    private void initComponents() {

        scrPane = new javax.swing.JScrollPane();
        table = new org.jdesktop.swingx.JXTable();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setPreferredSize(new java.awt.Dimension(500, 500));
        scrPane.setViewportView(table);

        getContentPane().add(scrPane, java.awt.BorderLayout.CENTER);
    }                     

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                DateForm df = new DateForm();
                df.setVisible(true);
            }
        });
    }

    private javax.swing.JScrollPane scrPane;
    private org.jdesktop.swingx.JXTable table;               

}

Is this behaviour intended? I am aware that JXDatePicker is for dates only, but I naturally assumed that it would preserve the time as long as the user didn't change the date.

4

1 回答 1

0

天哪,我想我做到了。经过大量挖掘,问题出JXMonthViewJXDatePicker. 简而言之,它使用了错误的选择模型。为了让它正常工作,我们需要实例化一个 newSingleDaySelectionModel并将其传递给JXMonthView.

JXDatePicker#setDate为我提供了问题答案的方法的文档:

设置日期属性。

如果 ui 否决新日期,则不执行任何操作 - 如果代码尝试设置在 monthView 的上下文中不可选择的日期,则可能会发生这种情况。新日期的实际值由 JXMonthView 的 DateSelectionModel 控制。默认实现将日期标准化为模型日历坐标中一天的开始,即所有时间字段都归零。要保留时间字段,请使用 SingleDaySelectionModel 配置 monthView

默认初始化JXDatePicker.java- 如您所见,我们需要的行已被注释:

private void initMonthView() {
    _monthView = new JXMonthView();
    //        _monthView.setSelectionModel(new SingleDaySelectionModel());
    _monthView.setTraversable(true);
    _monthView.addPropertyChangeListener(getMonthViewListener());
}

由于继承自JXDatePicker不是一个选项,我所做的是创建一个自定义 CellEditor,如下所示:

public class SQLDatePickerCellEditor extends DatePickerCellEditor {

    public SQLDatePickerCellEditor() {
        super(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        datePicker.getMonthView().setSelectionModel(new SingleDaySelectionModel());
    }

}

这可以根据需要保留时间。

注意:我使用的是已编译的 .jar,因此无法编辑源文件。如果使用可编辑的源文件,自然最好的解决方案是简单地取消注释该行。

于 2018-01-11T04:15:43.330 回答