I have a TableCellEditor
like that:
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.*;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Calendar;
import java.util.Date;
import java.util.EventObject;
public class JTimePeriodSelectorTableCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = -3458207749295701928L;
private JXDatePicker datePicker;
private static final int prefWidthPicker = 150;
private static final int prefHeightPicker = 22;
public JTimePeriodSelectorTableCellEditor() {
this("dd.MM.yyyy HH:mm:ss");
}
public JTimePeriodSelectorTableCellEditor(final String dateFormat) {
super();
initUI(dateFormat);
}
public void setKeyListener(KeyListener keyListener) {
datePicker.getDateField().addKeyListener(keyListener);
}
private JXDatePicker createDateComponent(final String dateFormat, final Date date) {
JXDatePicker datePicker = new JXDatePicker(date.getTime());
datePicker.setFormats(dateFormat);
datePicker.setMaximumSize(new Dimension(prefWidthPicker, prefHeightPicker));
datePicker.setPreferredSize(new Dimension(prefWidthPicker, prefHeightPicker));
datePicker.addActionListener(e -> {
try {
datePicker.commitEdit();
} catch (ParseException ex) {};
stopCellEditing();
});
return datePicker;
}
private JLabel createLabel(final String text) {
return new JEditLabel(text);
}
private void initUI(final String dateFormat) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
datePicker = createDateComponent(dateFormat, calendar.getTime());
Dimension separatorDim = new Dimension(3, 1);
}
public Date getDate() {
return datePicker.getDate();
}
public void setDate(final Date date) {
datePicker.setDate(date);
}
public void setEnabled(final boolean enabled) {
datePicker.setEnabled(enabled);
}
/**
* @param args
*/
public static void main(final String[] args) throws InterruptedException, InvocationTargetException {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
JFrame mainFrame = new JFrame("BasicApp");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTimePeriodSelectorTableCellEditor jCalendar = new JTimePeriodSelectorTableCellEditor();
//mainFrame.add(jCalendar, BorderLayout.CENTER);
mainFrame.pack();
mainFrame.setVisible(true);
mainFrame.setLocationRelativeTo(null);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return datePicker;
}
@Override
public Object getCellEditorValue() {
return new Date(datePicker.getDate().getTime());
}
@Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
@Override
public void cancelCellEditing() {
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
MouseEvent e = (MouseEvent)anEvent;
return e.getID() != MouseEvent.MOUSE_DRAGGED;
}
return true;
}
@Override
public boolean stopCellEditing() {
return super.stopCellEditing();
}
@Override
public void addCellEditorListener(CellEditorListener l) {
}
@Override
public void removeCellEditorListener(CellEditorListener l) {
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = new JLabel();
if (value instanceof Date) {
label.setText(value.toString()+" edit stopped");
}
return label;
}
}
and a TableCellRenderer
like that:
import javax.swing.table.DefaultTableCellRenderer;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateRenderer extends DefaultTableCellRenderer {
private SimpleDateFormat dateFormat;
public DateRenderer(String format) {
super();
dateFormat = new SimpleDateFormat(format);
}
@Override
public void setValue(Object value) {
if (value instanceof Date) {
super.setText(dateFormat.format((Date) value));
} else {
super.setValue(value);
}
}
}
JEditLabel
used in the first class is:
import javax.swing.*;
public class JEditLabel extends JLabel {
private static final long serialVersionUID = -4872698588890575636L;
public static class JEditLabelBuilder {
private String text;
private Icon icon;
private int horizontalAlignment;
public JEditLabelBuilder() {
setText("");
setHorizontalAlignment(SwingConstants.LEADING);
}
public JEditLabelBuilder setText(final String text) {
this.text = text;
return this;
}
public JEditLabelBuilder setIcon(final Icon icon) {
this.icon = icon;
return this;
}
public JEditLabelBuilder setHorizontalAlignment(final int horizontalAlignment) {
this.horizontalAlignment = horizontalAlignment;
return this;
}
public JEditLabel build() {
return new JEditLabel(this);
}
}
public JEditLabel(final String text) {
this((new JEditLabelBuilder()).setText(text));
}
protected JEditLabel(final JEditLabelBuilder builder) {
super();
setText(builder.text);
setIcon(builder.icon);
setHorizontalAlignment(builder.horizontalAlignment);
}
}
so then I upply them both the column of the JTable:
TableColumn timeColumn = changeTrafficProviderPaymentsTable.getColumnModel().getColumn(1);
JTimePeriodSelectorTableCellEditor timeColumnEditor = new JTimePeriodSelectorTableCellEditor();
timeColumn.setCellEditor(timeColumnEditor);
timeColumn.setCellRenderer(new DateRenderer("yyyy-MM-dd HH:mm:ss"));
I expect, that after date selection, the Editor will complete its work and will be switched to the Renderer. This doesn't happens on date selection in JXDatePicker. How can I trigger this change from Editor in the cell to Renderer in the cell and picj up the inserted datePicker
's data into the JTable.getModel()
?
The problem is here:
@Override
public void cancelCellEditing() {
}
And here:
@Override
public boolean stopCellEditing() {
return super.stopCellEditing();
}
@Override
public void addCellEditorListener(CellEditorListener l) {
}
@Override
public void removeCellEditorListener(CellEditorListener l) {
}
Those methods have a purpose. CellEditorListeners are how JTables (and other components that use cell editors) know when editing is started and stopped.
You have removed that important functionality entirely, so a JTable has no idea what your cell editor is doing.
Remove all of the above code. Let AbstractCellEditor do its job and properly handle listeners. Your class’s job is to notify those listeners by calling fireEditingStopped and fireEditingCanceled at the appropriate times.