Basically the problem here is as follow, I have this TableCellRenderer:
public class CellRenderer_LocalDate extends DefaultTableCellRenderer implements TableCellRenderer {
private static final long serialVersionUID = -9184414041940041458L;
String displayFormat;
public CellRenderer_LocalDate(String dateFormat) {
this.displayFormat = dateFormat;
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
if (value instanceof LocalDate) {
LocalDate date = (LocalDate) value;
value = date.format(DateTimeFormatter.ofPattern(displayFormat));
}
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
And this function to search a JTable:
/**
* Filters the table to show a specific text
*/
public void searchTable(JTextField searchTextField) {
// Get model & instantiate table sorter
DefaultTableModel tableToFilter = (DefaultTableModel) this.getModel();
TableRowSorter<DefaultTableModel> trSorter = new TableRowSorter<DefaultTableModel>(tableToFilter);
// Get text to search & Set row filter for this table
String search = searchTextField.getText();
// Filter table in correct format
trSorter.setRowFilter(RowFilter.regexFilter("(?i)" + search)); // Insensitive to upper case or lower case
this.setRowSorter(trSorter);
}
I have a column in the JTable that holds LocalDate in it. I made TableCellRenderer to display LocalDate column as dd.mm.yyyy. It works the way it should.
The problem is that when I use search function in format dd.mm.yyyy it does not show me any rows that match the way LocalDate is displayed in JTable.
An example: I have a column that holds LocalDate 2022-05-10. Due to the TableCellRenderer it is shown as 10.05.2022. Now if I use search and look for 10.05.2022 nothing will be shown as if nothing matches. But if I write in search field 2022-05-10 it will immediately show me the correct result. Please, what should I change in my functions to fix this bug?
So, based on this example, I dove into the Java source code and extracted the
RowFilter.dateFilter
and modified it to supportLocalDate
directly. This means, you get all the features and functionality ofRowFilter.dateFilter
, but withLocalDate
instead ofDate
.Caveat
If I was providing a searchable solution for a mixed series of values, I would design a dedicated "filter component" which provided the mechanisms for allowing a user to configure the filter them selves. In this case, that would mean allowing the user to, independently, configure filter parameters for the date values (ie, included/exclude a given range, filter by month or year or straight up, only this day)
This would then build the
RowSorter
accordingly, based on the user preferencesRunnable example
The following example is overly simplistic and is intended only as a demonstration of how you could customise a
RowSorter
to work with different data types.To search by a date value, you must supply a valid date in the format of
dd/MM/yyyy
.The example is making use of
RowFilter.orFilter
, so it will either match theLocalDateFilter
OR theRowFilter.regexFilter
Again, this is intended as a demonstration only.
You "could" modify the
LocalDateFilter
to convert the date values toString
via a suppliedDateTimeFormatter
, but I'd be concerned that you're mixing presentation and data concepts inappropriately, as they should be agnostic to each other - but that's me.There's a little bit of discussion over if a renderer should be used to "change the text" of data item or not. Honestly, I don't think it's black and white. There are times when you, hostly, don't want that kind of feature, but for me, a view is a "visual representation of data", you shouldn't "need" to massage the data for it to be presented via the view, that's not the job of the model, that's the job of the view.
For example, I could have the same data represented in a
JList
, with a short or long date format, based on the needs of the application and what the app is trying to present to the user - even more, it could be a user supplied configuration which needs to be applied - these are domains of the renderers/views, the data should need to be changed (IMHO).So, copy'n'paste. When I copied a row (Command+C) it copied
A 1 2000-05-12
, so, nothing to be done here. If you need to change "how" it's copied (ie, you'd like to present it asddd MMM yyyy
instead, you could do something like this for example - the important thing here is, you've got control)As for accessibility, if you have a read through How to Support Assistive Technologies you will note that accessibility is provided via such functionality as
toolTipText
andJComponent#getAccessibleContext
, which are methods of the cell render, so, again, it's not an issue that would drive me to "massage" my data.Again, context is king. There may be times when a wrapper/proxy object is worth the effort, but I'd always be asking myself, "what am I losing?" and "what am I gaining?" by doing it and how many of these do I need to create so I present the same data in a
JTable
orJComboBox
orJList
or some other component - but, that's me.