JavaFX:右击TableColumn禁用调整大小

2022-08-03 00:00:00 java javafx tableview openjfx

在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);
    }
}

解决方案

好了,我发现了以下(非常非常脏)的解决方法。我以前从未尝试过这样做,因为我假设它会阻止显示上下文菜单(正如我在最初的问题中所指出的),但显然只需使用每个TableColumnHeader作品的鼠标事件,上下文菜单仍然可以正确显示(也适用于没有上下文菜单的TableColumns)。

不确定内部是否会出现任何问题,但由于默认情况下右击似乎不起任何作用,我希望不会。

当然,lookupAll需要在呈现之后调用。

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

注2:越来越脏。简单地在将列设置为可见之后再次调用它(请参见注释1)并不总是足够(也不是通过Platform.runLater调用)。我认为这是因为列标题在那时还没有被呈现。您要么

  • 需要等待Set<Node>填满,即 必须是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);
    }
}

相关文章