【问题标题】:JavaFX: Right click on TableColumn disables resizingJavaFX:右键单击 TableColumn 禁用调整大小
【发布时间】:2021-11-16 15:55:39
【问题描述】:

在 OpenJFX 11.0.2 和 12.0.1 SDK(Windows 10、x64)中重现,在 JavaFX 8 中不可重现

右键单击表格列,然后尝试调整列的大小。在您再次手动单击列之前,不会显示调整大小的光标并且无法调整列的大小。

任何解决方法的想法?我需要为 TableColumns 使用contextMenu,因此无法使用使标题忽略鼠标右键单击的潜在解决方法。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;

public class Foo extends Application {


    @Override
    public void start(Stage stage) throws Exception {
        TableView<Object> testView = new TableView<>();
        testView.getColumns().addAll(new TableColumn<Object, Object>("C1"), new TableColumn<Object, Object>("C2"), new TableColumn<Object, Object>("C3"));

        stage.setScene(new Scene(testView));
        stage.show();
    }

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

【问题讨论】:

  • 我无法在 Ubuntu 18.04 上使用 JavaFX 11.0.2 重现此问题
  • 我很惊讶程序在 Java 12 中运行,因为 JavaFX 不再是 Java SE 的一部分。 javafx.application.Application 的子类不能再是 Java 主类,因为 JavaFX 所需的本机库在 JVM 启动主类时不可用。
  • @VGR 只要 JavaFX 模块在模块路径上,这就是不对的——至少,我从来没有遇到过问题(即使省略了main(String[]) 方法)。
  • 可以在 Windows 10 上使用 JavaFX 12.0.1 重现该问题。
  • @Slaw 你是对的。我应该澄清一下,我的陈述仅在使用类路径而不是模块路径时才成立。

标签: java javafx tableview openjfx


【解决方案1】:

好的,我找到了以下(非常非常肮脏)的解决方法。我以前从未尝试过,因为我认为它会阻止上下文菜单显示(正如我在原始问题中指出的那样),但显然只是简单地消耗每个 TableColumnHeader 作品的鼠标事件并且上下文菜单仍然正确显示(也有效TableColumns 没有上下文菜单)。

不确定内部是否会出现问题,但由于默认情况下右键单击似乎没有做任何有用的事情,我希望不会。

当然lookupAll 需要在渲染后调用。

注意 1:如果您将 TableMenuButtonVisible 设置为 true,则每次将列设置为可见时都需要执行此操作。

注2:越来越脏。在将列设置为可见后再次调用它(见注 1)并总是就足够了(Platform.runLater 调用也不行)。我认为那是因为此时尚未呈现列标题。你要么

  • 需要等到Set&lt;Node&gt;被填满,即大小 它必须是amountOfVisibleColumns + 1。如果它等于金额 可见列,它不适用于新显示的列。
  • 或在lookupAll之前在TableView上调用layout()
  • 或者如果您有一个扩展 TableView 的类,则覆盖 layoutChildren 并在可见列的数量发生变化时执行查找

注意3:你需要跟踪旧的onMousePressed,如果按钮不是SECONDARY,则执行它,否则列的重新排序将不起作用。

如果您能想到任何更清洁的方法,请告诉我。

import java.util.Set;

import javafx.application.Application;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.skin.TableColumnHeader;
import javafx.scene.input.MouseButton;
import javafx.stage.Stage;

public class Foo extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        TableView<Object> testView = new TableView<>();
        testView.getColumns().addAll(createColumn("C1"), createColumn("C2"), createColumn("C3"));

        stage.setOnShown(ev -> {
            Set<Node> headers = testView.lookupAll("TableColumnHeader");
            for (Node header : headers) {
                if (header != null) {
                    ((TableColumnHeader) header).setOnMousePressed(e -> {
                        if (e.getButton() == MouseButton.SECONDARY) {
                            e.consume();
                        }
                    });
                }
            }
        });

        stage.setScene(new Scene(testView));
        stage.show();
    }

    private TableColumn<Object, Object> createColumn(String text) {
        MenuItem item = new MenuItem("Context");
        item.setOnAction(e -> {
            System.out.println("Action");
        });

        ContextMenu contextMenu = new ContextMenu();
        contextMenu.getItems().add(item);

        TableColumn<Object, Object> column = new TableColumn<>(text);
        column.setContextMenu(contextMenu);

        return column;
    }

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

【讨论】:

  • 如果不存在,您应该提交一份错误报告。
  • 在下面查看我的答案:-)
【解决方案2】:

编辑:在 Java 错误跟踪器中找到了描述的错误,并提交了带有修复程序的 PR:
https://github.com/openjdk/jfx/pull/483
编辑 2:我的 PR 被接受并合并回来。该错误现已修复,您可以使用 17-ea+11 进行测试。 :-)

我也有同样的问题。此错误是由TableColumnHeader 中添加的mousePressedHandler 引起的。这个类有更多的问题,例如如果我通过单击列关闭PopupControlsetConsumeAutoHidingEvents(true),将触发排序。这些方法需要更改,也许应该使用addEventHandler 方法而不是方便的setOn... 方法。

当我要显示我的 PopupControl 时,我通过使用该事件来修复它:

public class MyTableColumnHeader extends TableColumnHeader {

    public MyTableColumnHeader(TableColumnBase tc) {
        super(tc);
        addEventHandler(MouseEvent.MOUSE_PRESSED, this::onMousePressed);
    }

    private void onMousePressed(MouseEvent mouseEvent) {
        if (mouseEvent.getButton() == MouseButton.SECONDARY) {
            showPopup();
            // Consume here, so the column won't get 'stuck'.
            mouseEvent.consume();
        }
    }

    private void showPopup() {
        ...
    }
}

最终,至少应该有人打开一个错误。不远的将来我可能也会去看看。

【讨论】:

    猜你喜欢
    • 2020-05-07
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 2020-10-11
    相关资源
    最近更新 更多