最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - How to sort a column by data from another column in JTable - Stack Overflow

programmeradmin1浏览0评论

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
  • first sorting should be by type, and then by date. - you can set the "sort keys" that you want the data sorted by. This allows you to specify multiple columns. See: stackoverflow/a/65093631/131872 for a simple example to get you started. You would set the SortKeys when you load data into the table, not in an ActionListener. – camickr Commented 14 hours ago
  • You need something like 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
Add a comment  | 

2 Answers 2

Reset to default 0

You 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;
  }
}
发布评论

评论列表(0)

  1. 暂无评论