JavaFX处理TableView上的事件

时间:2014-09-18 10:21:52

标签: javafx mouseevent tableview

在JaxaFX 8中,我想对TableView的多个列进行排序,这可以通过按住shift键同时按下标题来实现。

但现在它应该在支持触控的设备上运行,我无法按下shift键。我尝试使用addEventHandler(..)捕获TableView上的事件,使用原始事件,按下修改器创建一个新事件并将其传递回Control。

我在扩展TableView的构造函数中的方法

final EventDispatcher orgDispatcher = getEventDispatcher();
    setEventDispatcher((event, tail) -> {
        if (event.getEventType() == MouseEvent.MOUSE_CLICKED) {
            final MouseEvent mouseEvent = (MouseEvent) event;
            final MouseEvent modifierEvent = new MouseEvent(MouseEvent.MOUSE_CLICKED, // type
                    mouseEvent.getX(), mouseEvent.getY(), mouseEvent.getScreenX(), mouseEvent.getScreenY(), // coords
                    MouseButton.SECONDARY, mouseEvent.getClickCount(), // clicks
                    true, true, true, true, // keyboard modifiers - shift-ctrl-alt-meta
                    false, false, false, // mouse modifiers
                    false, false, false, null);
            mouseEvent.consume();
            System.out.println("dispatched modified event" + mouseEvent.getButton() + modifierEvent.getButton());
            return orgDispatcher.dispatchEvent(modifierEvent, tail);
        }
        return orgDispatcher.dispatchEvent(event, tail);
    });

addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
        System.out.println(event.getButton());
    });

看起来这种方法的作用是点击带有主要打印辅助的TableView。但是排序没有按预期执行。似乎ColumnHeader在小部件的某个地方处理事件...

任何人都可以提供帮助 a)在正确的地方修改事件 或者b)为如何对列进行排序以及将这个漂亮的“箭头”图标添加到列中提供替代解决方案

功能显然已经存在我只是不知道如何解雇事件......

2 个答案:

答案 0 :(得分:1)

显然我的问题的解决方案如下。

为了在多个列之后以编程方式设置排序,必须对ObservableList<TableColumn<E,?>> getSortOrder()所持有的TableView进行更改。可以简单地以正确的顺序添加TableColumn

由于通常通过shift-click导致这种情况的事件在JavaFX框架中某处(可能在某些Skin类或什么?)我无法通过EventFilter捕获它。如果我在TableView上应用过滤器已经发生了魔法......

因此,在我的自定义TableView中,我需要保留自己的sortOrder ObservableList并在每个InputEvent之后替换它。我没有在touchenabled设备上测试它,但是没有按Shift键我现在可以在多列之后进行排序。 (如果MouseEvent或TouchEvent没关系 - 关键是我没有键盘来按下修饰键)

addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
        if (event.getTarget() instanceof TableColumnHeader) {
            event.consume();

            // Search for the clicked TableColumn:
            TableColumn<E, ?> column = null;
            final TableColumnHeader columHead = (TableColumnHeader) event.getTarget();
            final String name = columHead.getTableColumn().getText();
            for (final TableColumn<E, ?> col : getColumns()) {
                if (col.getText().equals(name)) {
                    column = col;
                }
            }

            // Now handle the sortOrder:
            if (sortedColumns.containsKey(name)) {
                if (sortedColumns.get(name) == TableColumn.SortType.ASCENDING) {
                    column.setSortType(TableColumn.SortType.DESCENDING);
                    sortedColumns.remove(name);
                    sortedColumns.put(name, TableColumn.SortType.DESCENDING);
                } else {
                    sortedColumns.remove(name);
                    sortOrder.remove(column);
                }
            } else {
                sortedColumns.put(name, TableColumn.SortType.ASCENDING);
                sortOrder.add(column);
            }

            // Override the getSortOrder():
            getSortOrder().clear();
            getSortOrder().addAll(sortOrder);
        }

    });

带字段

private final ObservableMap<String, TableColumn.SortType> sortedColumns = FXCollections.observableHashMap();
private final ObservableList<TableColumn<E, ?>> sortOrder = FXCollections.observableArrayList();

答案 1 :(得分:0)

请注意,使用事件会阻止调用EventHandler上的其他TableView(更不用说在列标题上注册的处理程序了)直接,在TableView的处理程序之前调用它们。它只会阻止调用TableView父项上的事件处理程序。

您可能希望添加一个消耗该事件的事件过滤器(这会阻止调用任何处理程序)并触发已修改的事件。

addEventFilter(MouseEvent.MOUSE_CLICKED, event -> {
    if(event.getButton() == MouseButton.PRIMARY) {
        MouseEvent modifierEvent = new MouseEvent(MouseEvent.MOUSE_CLICKED, // type
                event.getX(), event.getY(), event.getScreenX(), event.getScreenY(), // coords
                MouseButton.SECONDARY, event.getClickCount(), // clicks
                true, true, true, true, // keyboard modifiers - shift-ctrl-alt-meta
                false, false, false, // mouse modifiers
                false, false, false, null);
        event.consume(); // prevents any left-click handlers from being invoked
        Event.fireEvent(event.getTarget(), modifierEvent);
    }
});

请注意,您无需替换事件调度程序来触发事件。有Event.fireEvent()静态方法可以做到这一点。