首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >JavaFX表格视图先按自定义规则排序,然后按列选择排序

JavaFX表格视图先按自定义规则排序,然后按列选择排序
EN

Stack Overflow用户
提问于 2018-05-01 08:08:08
回答 2查看 2.2K关注 0票数 1

我正在尝试对包含3列的JavaFX TableView进行排序,其中一列是日期,一列是名称(字符串),最后一列是标签列(枚举)。我想要做的是,无论表当前在哪一列上排序,行都将首先按标记排序(如果它有某个标记,则排序在没有该标记的行的前面)。

因此,在升序中按名称搜索时,表的顺序如下:

  • 'George‘tag
  • 'ZZ’tag
  • 'Apple‘no-tag
  • 'Hello’no-tag

等。

我已经查看了列比较器,但是我似乎只能指定该列类型,即我希望能够指定要在整个行的类对象中接受的名称-列比较器,以及名称-列数据类型(字符串),这样我就可以访问该类实例中的标记-但是在网上查看后,这似乎是不可能的。

即使选择了tags列来对desc进行排序,是否也可以保留此规则(因此它仍然会首先放置带有标记的行)。如果没有,我可以禁用标记列的排序

提前感谢所有能为我指明正确方向的人

EN

回答 2

Stack Overflow用户

发布于 2018-09-25 05:10:30

正如我在评论中提到的,您不能只创建一个绑定,它包装TableView的比较器并将其提供给SortedList。另外,SortedList是final,所以你不能扩展它。此外,使用自定义TransformationList也不会起作用,因为TableView有一些以if (itemsList instanceof SortedList)开头的硬编码内容。这就是我最终得到的结果(为了清晰起见,我使用了java7格式,而不是labdas ):

代码语言:javascript
运行
复制
    filteredList = new FilteredList<>(yourOriginalList);
    table.sortPolicyProperty().set(new Callback<TableView<YourObject>, Boolean>() {
        @Override
        public Boolean call(TableView<YourObject> param) {
            final Comparator<YourObject> tableComparator = transactionTable.getComparator();
            // if the column is set to unsorted, tableComparator can be null
            Comparator<YourObject> comparator = tableComparator == null ? null : new Comparator<YourObject>() {
                @Override
                public int compare(YourObject o1, YourObject o2) {
                    // first sort by your tag
                    final int tagCompare = o1.getTag().compareTo(o2.getTag());
                    if (tagCompare == 0) {
                        // secondly sort by the comparator that was set for the table
                        return tableComparator.compare(o1, o2);
                    }
                    return tagCompare;
                }
            };
            table.setItems(filteredList.sorted(comparator));
            return true;
        }
    });

    // you may also need to call
    table.setItems(filteredList.sorted(transactionTable.getComparator()));
票数 2
EN

Stack Overflow用户

发布于 2018-09-25 10:14:54

我同意@Miklos的解决方案。下面是您要求(基于@Miklos解决方案)在对所选列进行排序之前先按标记列排序的完整工作示例。这不是一个完整的解决方案,但这应该会为您提供一些开始的方向,并根据您的需要使其完全工作。

代码语言:javascript
运行
复制
import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import static javafx.scene.control.TableColumn.SortType.ASCENDING;

public class CustomComparatorTableColumn extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        ObservableList<Device> devices = FXCollections.observableArrayList();
        devices.add(new Device(1, "Apple", "Zebra", TagType.TAG));
        devices.add(new Device(2, "BlackBerry", "Parrot", TagType.TAG));
        devices.add(new Device(3, "Amazon", "Yak", TagType.NO_TAG));
        devices.add(new Device(4, "Oppo", "Penguin", TagType.NO_TAG));

        TableView<Device> tableView = new TableView<>();
        TableColumn<Device, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(param -> param.getValue().nameProperty());

        TableColumn<Device, String> displayCol = new TableColumn<>("Display");
        displayCol.setCellValueFactory(param -> param.getValue().displayProperty());

        TableColumn<Device, TagType> tagCol = new TableColumn<>("Tag");
        tagCol.setCellValueFactory(param -> param.getValue().tagTypeProperty());

        tableView.getColumns().addAll(nameCol, displayCol, tagCol);
        tableView.setItems(devices);

        tableView.setSortPolicy(tv -> {
            final ObservableList<Device> itemsList = tableView.getItems();
            if (itemsList == null || itemsList.isEmpty()) {
                return true;
            }
            final List<TableColumn<Device, ?>> sortOrder = new ArrayList<>(tableView.getSortOrder());
            if (!sortOrder.isEmpty()) {
                // If there is no Tag column in the sort order, always adding as the first sort to consider.
                if (!sortOrder.stream().anyMatch(tc -> tc.getText().equals("Tag"))) {
                    sortOrder.add(0, tagCol);
                }
                FXCollections.sort(itemsList, new TableColumnComparator<>(sortOrder));
            }
            return true;
        });

        Scene sc = new Scene(tableView);
        primaryStage.setScene(sc);
        primaryStage.show();

    }

    class TableColumnComparator<S> implements Comparator<S> {
        private final List<TableColumn<S, ?>> allColumns;

        public TableColumnComparator(final List<TableColumn<S, ?>> allColumns) {
            this.allColumns = allColumns;
        }

        @Override
        public int compare(final S o1, final S o2) {
            for (final TableColumn<S, ?> tc : allColumns) {
                if (!isSortable(tc)) {
                    continue;
                }
                final Object value1 = tc.getCellData(o1);
                final Object value2 = tc.getCellData(o2);

                @SuppressWarnings("unchecked") final Comparator<Object> c = (Comparator<Object>) tc.getComparator();
                final int result = ASCENDING.equals(tc.getSortType()) ? c.compare(value1, value2)
                        : c.compare(value2, value1);

                if (result != 0) {
                    return result;
                }
            }
            return 0;
        }

        private boolean isSortable(final TableColumn<S, ?> tc) {
            return tc.getSortType() != null && tc.isSortable();
        }
    }

    class Device {
        IntegerProperty id = new SimpleIntegerProperty();
        StringProperty name = new SimpleStringProperty();
        StringProperty display = new SimpleStringProperty();
        ObjectProperty<TagType> tagType = new SimpleObjectProperty<>();

        public Device(int id, String n, String d, TagType tag) {
            this.id.set(id);
            name.set(n);
            tagType.set(tag);
            display.set(d);
        }

        public String getName() {
            return name.get();
        }

        public StringProperty nameProperty() {
            return name;
        }

        public void setName(String name) {
            this.name.set(name);
        }

        public ObjectProperty<TagType> tagTypeProperty() {
            return tagType;
        }

        public StringProperty displayProperty() {
            return display;
        }

    }

    enum TagType {
        TAG, NO_TAG;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50109815

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档