Reputation: 927
This question is a follow up of this one due to issues that arose: Remove cell editor border in JTable (Windows LaF)
I am experiencing unexpected behaviour from the JTextArea
taken from DefaultCellEditor#getComponent()
when modifying its borders once it's already on the table. The borders simply don't visually change.
Even after calling:
textField.setBorder(BorderFactory.createCompoundBorder(null, BorderFactory.createEmptyBorder(1, 1, 1, 1)));
and right after that doing:
System.out.println(textField.getBorder());
the console shows javax.swing.border.CompoundBorder@6aff616
which means the border has changed internally. However, this isn't reflected visually and I'm very confused.
My test class:
public class TableStackOverflow extends javax.swing.JFrame {
public TableStackOverflow() {
initComponents();
prepareTable();
}
public void prepareTable() {
for (int i = 0; i < table.getColumnCount(); i++) {
Class columnClass = table.getColumnClass(i);
DefaultCellEditor defaultEditor = (DefaultCellEditor) table.getDefaultEditor(columnClass);
if (defaultEditor.getComponent() instanceof JTextField) {
JTextField textField = (JTextField) defaultEditor.getComponent();
textField.setFont(new Font("Segoe UI", Font.PLAIN, 12));
textField.setBorder(BorderFactory.createCompoundBorder(null, BorderFactory.createEmptyBorder(1, 1, 1, 1)));
System.out.println(textField.getBorder());
}
defaultEditor.setClickCountToStart(1);
}
}
private void initComponents() {
scrPane = new javax.swing.JScrollPane();
table = new org.jdesktop.swingx.JXTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
table.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null},
{null, null}
},
new String [] {
"First", "Second"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
});
table.setSelectionBackground(new java.awt.Color(223, 238, 249));
table.setSelectionForeground(new java.awt.Color(0, 0, 0));
scrPane.setViewportView(table);
getContentPane().add(scrPane, java.awt.BorderLayout.CENTER);
pack();
}
public static void main(String args[]) {
try {
javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
}
java.awt.EventQueue.invokeLater(() -> {
new TableStackOverflow().setVisible(true);
});
}
private javax.swing.JScrollPane scrPane;
private org.jdesktop.swingx.JXTable table;
And finally here is a nasty workaround that makes it work but isn't viable:
public void prepareTable() {
for (int i = 0; i < table.getColumnCount(); i++) {
DefaultCellEditor defaultEditor = (DefaultCellEditor) table.getDefaultEditor(table.getColumnClass(i));
if (defaultEditor.getComponent() instanceof JTextField) {
JTextField textField = new JTextField();
textField.setFont(new Font("Segoe UI", Font.PLAIN, 12));
textField.setBorder(BorderFactory.createCompoundBorder(null, BorderFactory.createEmptyBorder(1, 1, 1, 1)));
defaultEditor = new DefaultCellEditor(textField);
table.setDefaultEditor(table.getColumnClass(i), defaultEditor);
}
defaultEditor.setClickCountToStart(1);
}
}
Finally, something much nicer that works (Thanks Camickr!)
table.addPropertyChangeListener((evt) -> {
if ("tableCellEditor".equals(evt.getPropertyName())) {
if (table.isEditing()) {
JTextField jtextField = (JTextField) ((DefaultCellEditor) table.getCellEditor()).getComponent();
jtextField.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
}
}
});
Upvotes: 1
Views: 387
Reputation: 324207
DefaultCellEditor defaultEditor = (DefaultCellEditor) table.getDefaultEditor(columnClass);
System.out.println(defaultEditor.getClass());
Add the above statement to your code and you will see that the default editor is the GenericEditor
which is an inner class of the JTable.
This editor adds extra functionality for usage in a JTable.
One of the things it does is manage the Border. If an error is found a "red border" is displayed in the editor. Otherwise the border is set the the default "black border".
And finally here is a nasty workaround that makes it work but isn't viable:
You either need to use the DefaultCellEditor or create a custom editor.
You might be able to extend the JTable.GenericEditor class and override the getTableCellEditor(...)
method. This is the method that resets the Border to the default black border.
Or maybe you can override the getCellEditor(...)
method to the table to get the editor and then remove the border.
Another approach would be to add a PropertyChangeListener
to the table. Then whenever a cell is edited you will get an event so you can get the active editor and remove its border:
@Override
public void propertyChange(PropertyChangeEvent e)
{
// A cell has started/stopped editing
if ("tableCellEditor".equals(e.getPropertyName()))
{
if (table.isEditing())
// add your code here
}
}
Also, why would you use a CompoundBorder to create an EmptyBorder?
Upvotes: 2