I need to sort the column with "File creation date", but if the column "File type" == FyleType.DIRECTORY this row should be at the top. That is, first sorting should be by type, and then by date.
My JTable:
Type | Filename | Date |
---|---|---|
DIRECTORY | filename1 | 2025.04.03 |
DIRECTORY | filename2 | 2025.02.01 |
FILE | filename3.txt | 2025.01.01 |
FILE | filename4.txt | 2025.02.03 |
I need to sort the column with "File creation date", but if the column "File type" == FyleType.DIRECTORY this row should be at the top. That is, first sorting should be by type, and then by date.
My JTable:
Type | Filename | Date |
---|---|---|
DIRECTORY | filename1 | 2025.04.03 |
DIRECTORY | filename2 | 2025.02.01 |
FILE | filename3.txt | 2025.01.01 |
FILE | filename4.txt | 2025.02.03 |
I tried using
TableRowSorter<FileTableModel> tableRowSorter = new TableRowSorter<>(tableModel);
tableRowSorter.setComparator(2, ((o1, o2) -> {}
Comparator but it only gets the value of the current cell and I can't get the file type because the date is not unique
Share Improve this question asked 17 hours ago StarkvellStarkvell 212 bronze badges 2 |2 Answers
Reset to default 0You need to create a comparator (should be a non-static class in or with access to your table model) to set on your RowSorter, like
class MyComparator implements Comparator<date> {
if (row1.column1 = "DIRECTORY" && row2.column1 != "DIRECTORY) {
return -1;
}
else if (row2.column1 == "DIRECTORY") {
return 1;
} else {
return MyDateComparatorpareTo (row1.column4, row2.column4);
}
}
Another option is to create a JTable
that contains a File
copy of every data column.
This way, you would need to change the TableCellRenderer
to display the file type, file name, or file creation date from the File
depending on the column,
but the comparators for each column would be able to get the file type and file creation date from the File
at the same time.
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
public class GroupDirectoriesFirstComparatorTest {
private Component makeUI() {
String[] columnNames = {"Type", "Filename", "Date"};
DefaultTableModel model = new DefaultTableModel(columnNames, 0) {
@Override
public Class<?> getColumnClass(int column) {
return File.class;
}
};
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);
table.setDefaultRenderer(File.class, new FileCellRenderer());
RowSorter<? extends TableModel> sorter = table.getRowSorter();
if (sorter instanceof TableRowSorter) {
TableRowSorter<? extends TableModel> rs =
(TableRowSorter<? extends TableModel>) sorter;
for (int i = 0; i < model.getColumnCount(); i++) {
rs.setComparator(i, new GroupDirectoriesFirstComparator(table, i));
}
}
JButton button = new JButton("Choose directory");
button.addActionListener(e -> {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int ret = chooser.showOpenDialog(button.getRootPane());
if (ret == JFileChooser.APPROVE_OPTION) {
model.setRowCount(0);
File[] files = chooser.getSelectedFile().listFiles();
if (files != null) {
Arrays.stream(files)
.map(f -> Collections.nCopies(3, f).toArray())
.forEach(model::addRow);
}
}
});
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
p.add(button, BorderLayout.SOUTH);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(
new GroupDirectoriesFirstComparatorTest().makeUI());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
class FileCellRenderer extends DefaultTableCellRenderer {
private final DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd");
@Override
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
Component c = super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
if (c instanceof JLabel && value instanceof File) {
JLabel l = (JLabel) c;
l.setHorizontalAlignment(LEFT);
File file = (File) value;
switch (table.convertColumnIndexToModel(column)) {
case 0:
l.setText(file.isDirectory() ? "DIRECTORY" : "FILE");
break;
case 1:
l.setText(file.getName());
break;
case 2:
l.setHorizontalAlignment(RIGHT);
try {
BasicFileAttributes attr =
Files.readAttributes(file.toPath(), BasicFileAttributes.class);
l.setText(dateFormat.format(attr.creationTime().toMillis()));
} catch (IOException e) {
throw new RuntimeException(e);
}
break;
default:
break;
}
}
return c;
}
}
class FileComparator implements Comparator<File> {
private final int column;
public FileComparator(int column) {
this.column = column;
}
@Override
public int compare(File a, File b) {
switch (column) {
case 0: return getWeight(a) - getWeight(b);
case 2: return Longpare(getCreationTime(a), getCreationTime(b));
default: return a.getName()pareToIgnoreCase(b.getName());
}
}
public int getColumn() {
return column;
}
public static int getWeight(File file) {
return file.isDirectory() ? 1 : 2;
}
public static Long getCreationTime(File file) {
BasicFileAttributes attr;
try {
attr = Files.readAttributes(file.toPath(), BasicFileAttributes.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
return Optional.ofNullable(attr)
.map(BasicFileAttributes::creationTime)
.map(FileTime::toMillis)
.orElse(0L);
}
}
// https://java-swing-tips.blogspot/2011/11/jtable-group-directories-first-sorting.html
class GroupDirectoriesFirstComparator extends FileComparator {
private final JTable table;
public GroupDirectoriesFirstComparator(JTable table, int column) {
super(column);
this.table = table;
}
@Override
public int compare(File a, File b) {
int v = getWeight(a) - getWeight(b);
return v == 0 ? superpare(a, b) : v * getSortOrderDirection();
}
private int getSortOrderDirection() {
int dir = 1;
List<? extends RowSorter.SortKey> keys = table.getRowSorter().getSortKeys();
if (!keys.isEmpty()) {
RowSorter.SortKey sortKey = keys.get(0);
if (sortKey.getColumn() == getColumn() &&
sortKey.getSortOrder() == SortOrder.DESCENDING) {
dir = -1;
}
}
return dir;
}
}
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()); table.setRowSorter(sorter);sorter.setSortKeys(List.of(new RowSorter.SortKey(0, SortOrder.ASCENDING), new RowSorter.SortKey(2, SortOrder.ASCENDING)));
– g00se Commented 11 hours ago