JavaFX TableView过滤器鼠标右键选择

梅茨

当我在JavaFX TreeTableView上按鼠标右键时,它将选择我单击的节点。我可以理解为什么在大多数情况下都希望这样做,但并非在所有情况下都希望这样做。

我正在开发一个应用程序,其中树表中有多列,其中一列使用画布小部件来定制图形(波形)。由于各种原因(设置标记,缩放等),必须能够使用鼠标与图形列进行交互。因此,我不希望鼠标按钮选择表中的行(或与表交互)。

我可以通过用放一个addEventFilter()MouseEvent.MOUSE_CLICKED第一个鼠标按键过滤掉点击event.consume()然后,我可以按我想要的方式处理鼠标单击。

但是,当我右键单击该单元格时,表中的选择将更改为该行。我试过将事件过滤器放在单元格,表,行,列上,似乎没有任何东西可以过滤右键单击选择更改。请注意,画布小部件设置为鼠标透明。

这是一个使用标准通讯录示例的示例,除了我用画布小部件替换了电子邮件列。

package sample;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;

public class Main extends Application {
    private TableView<Person> table = new TableView<Person>();
    private ContextMenu menu = new ContextMenu();

    private final ObservableList<Person> data =
        FXCollections.observableArrayList(
                new Person("Jacob", "Smith", "[email protected]"),
                new Person("Isabella", "Johnson", "[email protected]"),
                new Person("Ethan", "Williams", "[email protected]"),
                new Person("Emma", "Jones", "[email protected]"),
                new Person("Michael", "Brown", "[email protected]")
        );

    class MyTableCell extends TableCell<Person, String> {
        public MyTableCell(ContextMenu menu) {
            super();
            setContextMenu(menu);
        }

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            setText(item);
            setGraphic(null);
        }
    }

    class MySpecialCell extends MyTableCell {
        Canvas canvas = new Canvas(200.0, 12.0);
        public MySpecialCell() {
            super(null);
            canvas.setMouseTransparent(true);
            addEventFilter(MouseEvent.ANY, e -> e.consume());
        }

        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            setText(null);
            if (! empty) {
                canvas.getGraphicsContext2D().strokeText(item, 5.0, 10.0);
                setGraphic(canvas);
            } else {
                setGraphic(null);
            }
        }
    }

    @Override
    public void start(Stage stage) throws Exception{
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(500);

        final Label label = new Label("Address Book");
        label.setFont(new Font("Arial", 20));

        table.setEditable(true);
        table.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        menu.getItems().add(new MenuItem("Hello World"));
        Callback cellFactory = param -> new MyTableCell(menu);

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));
        firstNameCol.setCellFactory(cellFactory);

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));
        lastNameCol.setCellFactory(cellFactory);

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));
        emailCol.setCellFactory(param -> new MySpecialCell());

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(label, table);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }

    public static class Person {
        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() {
            return firstName.get();
        }
        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }
        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }
        public void setEmail(String fName) {
            email.set(fName);
        }

    }
}

这是使用Java 8u20。在此示例中,MyTableCell该类用于前两列中的单元格。它将上下文菜单添加到这些列。MySpecialCell班是最后一列和它把一个帆布的表与它的电子邮件文本。它还会落水并过滤ANY鼠标事件。

如果运行此命令,则会看到如果在前两列中使用鼠标按钮1,则可以更改表中的选择。第三列中的鼠标按钮1不会更改选择。但是,鼠标按钮2(鼠标右键)确实会更改第三列中的选择。

我希望它不会更改选择。有人可以提示我如何在使用列中的鼠标右键时防止更改选择吗?

注意:我尝试让画布处理鼠标输入(实际上不是使鼠标透明并过滤所有鼠标事件),并且在单击鼠标右键时表格仍会更改选择。由于各种原因(实际数据是画布实际上是一堆画布小部件的事实,难以确定鼠标在表中与哪个节点进行交互等),我想在单元格中处理该单元格鼠标输入。

谢谢!

克娄巴特拉

重复我的评论:我认为行为可能是错误而不是功能-我希望使用任何mouseEvent会阻止右键(辅助)与左键(主要)正常动作相同。

评估为一项功能:缺少的部分是除了mouseEvents之外还使用contextMenuEvents,类似

public MySpecialCell() {
    super(null);
    canvas.setMouseTransparent(true);
    addEventFilter(MouseEvent.ANY, e -> e.consume());
    // move Jonathan's code from table to cell level:
    // need to consume contextMenuEvents as well
    addEventFilter(ContextMenuEvent.ANY, e -> e.consume());
}

返回不同意评估:

  • 所有鼠标按钮的行为应与消耗所有mouseEvent的行为保持一致
  • contextMenuEvent基本上与选择无关,因此使用它应该对选择没有影响(无论哪种方式)

如果需要由特殊列上的键盘触发的contextMenu进行触发,则可能仍然需要以下技巧,但是请不要进一步研究。

无论如何,一种快速的解决方法是用自定义实现方式替换默认行为。合作者

  • 覆盖doSelect的自定义TableCellBehaviour,在接收到辅助按钮事件时不执行任何操作
  • 一个自定义的TableCellSkin:仅需要插入自定义行为-需要扩展TableCellSkinBase(并从TableCellSkin中c&p实现其抽象方法的实现),因为只有那时我们才有一个构造函数采用我们的自定义行为
  • 让自定义TableCell创建自定义外观,而不是默认外观

像这样的东西(注意:在工作时,它没有经过适当的测试):

class MySpecialCellBehavior extends TableCellBehavior {

    public MySpecialCellBehavior(TableCell control) {
        super(control);
    }

    @Override
    protected void doSelect(double x, double y, MouseButton button,
            int clickCount, boolean shiftDown, boolean shortcutDown) {
        // do nothing on secondary button
        if (button == MouseButton.SECONDARY) return;
        super.doSelect(x, y, button, clickCount, shiftDown, shortcutDown);
    }

}

class MySpecialCellSkin extends TableCellSkinBase {
    private final TableColumn tableColumn;

    public MySpecialCellSkin(TableCell tableCell) {
        super(tableCell, new MySpecialCellBehavior(tableCell));
        // doesn't make a difference
        //consumeMouseEvents(true);
        this.tableColumn = tableCell.getTableColumn();
        super.init(tableCell);
    }

    @Override protected BooleanProperty columnVisibleProperty() {
        return tableColumn.visibleProperty();
    }

    @Override protected ReadOnlyDoubleProperty columnWidthProperty() {
        return tableColumn.widthProperty();
    }

}

class MySpecialCell extends MyTableCell {
    Canvas canvas = new Canvas(200.0, 12.0);
    public MySpecialCell() {
        super(null);
        canvas.setMouseTransparent(true);
        addEventFilter(MouseEvent.ANY, e -> e.consume());
    }

    @Override
    protected void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        setText(null);
        if (! empty) {
            canvas.getGraphicsContext2D().strokeText(item, 5.0, 10.0);
            setGraphic(canvas);
        } else {
            setGraphic(null);
        }
    }
    // create and return the custom skin
    @Override
    protected Skin<?> createDefaultSkin() {
        return new MySpecialCellSkin(this);
    }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在 VBox JavaFX-8 中使用过滤器参数过滤 TableView

来自分类Dev

JavaFX Webview不支持过滤器?

来自分类Dev

JavaFX中的TextField的TAB事件过滤器

来自分类Dev

右键单击JavaFX for Minesweeper

来自分类Dev

将文件过滤器添加到Jython中的JavaFx Filechooser并将其参数化

来自分类Dev

javafx Minesweeper:如何区分鼠标左右键输入

来自分类Dev

javafx-无法通过鼠标选择ListView

来自分类Dev

JavaFX TableView右键单击自定义项

来自分类Dev

JavaFX如何定位鼠标

来自分类Dev

鼠标进行JavaFX转换

来自分类Dev

JavaFX鼠标坐标

来自分类Dev

JAVAFX:TableView获取多个选择数据

来自分类Dev

如何检测JavaFX TableView中选择的列?

来自分类Dev

JavaFX更改TableView选择行栏的蓝色

来自分类Dev

JavaFX TableView:选择整个TableColumn并获取索引

来自分类Dev

JavaFX通过使用ComboBox选择填充TableView

来自分类Dev

JavaFX tableview 启用和禁用行选择

来自分类Dev

Javafx TableView编辑验证

来自分类Dev

TableView中的JavaFX属性

来自分类Dev

JavaFX Derby TableView

来自分类Dev

JavaFX TableView排序策略

来自分类Dev

JavaFX TableView删除问题

来自分类Dev

JavaFX TableView频繁更新

来自分类Dev

JavaFX的从TableView中删除

来自分类Dev

使javafx TableView像JTable

来自分类Dev

在JavaFX中编辑TableView

来自分类Dev

JavaFX TableView与SceneBuilder

来自分类Dev

JavaFX从ObservableList填充TableView

来自分类Dev

在JavaFX tableView中导航