JavaFX:右键单击 TableColumn 禁用调整大小
JavaFX: Right click on TableColumn disables resizing
在 OpenJFX 11.0.2 和 12.0.1 SDK 中重现(Windows 10,x64),在 JavaFX 8 中无法重现
Right-click 在 table-column 上,然后尝试调整列的大小。在您再次手动单击该列之前,不会显示调整大小光标并且无法调整该列的大小。
有什么解决方法吗?我需要对 TableColumns 使用 contextMenu
,因此无法使用 header 忽略鼠标右键单击的潜在解决方法。
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)并不 always 就足够了(也不适用于 Platform.runLater
调用)。我认为那是因为 header 列在那个时候还没有呈现。你要么
- 需要等到
Set<Node>
填满,即
它必须是 amountOfVisibleColumns + 1
。如果它等于数量
可见列,它不适用于新显示的列。
- 或在
lookupAll
之前在 TableView 上调用 layout()
- 或者如果您有一个扩展
TableView
的 class,覆盖 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);
}
}
编辑:在 Java bug tracker 中找到了描述的 bug 并提交了一个带有修复的 PR:
https://github.com/openjdk/jfx/pull/483
编辑 2:我的 PR 被接受并合并回来。目前bug已经修复,可以使用17-ea+11进行测试。 :-)
我也遇到了同样的问题。此错误是由 TableColumnHeader
中添加的 mousePressedHandler
引起的。这个 class 有更多问题,例如,如果我通过单击列关闭 PopupControl
和 setConsumeAutoHidingEvents(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() {
...
}
}
最终,至少应该有人打开一个错误。说不定不久的将来我也会去看看
在 OpenJFX 11.0.2 和 12.0.1 SDK 中重现(Windows 10,x64),在 JavaFX 8 中无法重现
Right-click 在 table-column 上,然后尝试调整列的大小。在您再次手动单击该列之前,不会显示调整大小光标并且无法调整该列的大小。
有什么解决方法吗?我需要对 TableColumns 使用 contextMenu
,因此无法使用 header 忽略鼠标右键单击的潜在解决方法。
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)并不 always 就足够了(也不适用于 Platform.runLater
调用)。我认为那是因为 header 列在那个时候还没有呈现。你要么
- 需要等到
Set<Node>
填满,即 它必须是amountOfVisibleColumns + 1
。如果它等于数量 可见列,它不适用于新显示的列。 - 或在
lookupAll
之前在 TableView 上调用 - 或者如果您有一个扩展
TableView
的 class,覆盖layoutChildren
并在可见列的数量发生变化时执行查找
layout()
注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);
}
}
编辑:在 Java bug tracker 中找到了描述的 bug 并提交了一个带有修复的 PR:
https://github.com/openjdk/jfx/pull/483
编辑 2:我的 PR 被接受并合并回来。目前bug已经修复,可以使用17-ea+11进行测试。 :-)
我也遇到了同样的问题。此错误是由 TableColumnHeader
中添加的 mousePressedHandler
引起的。这个 class 有更多问题,例如,如果我通过单击列关闭 PopupControl
和 setConsumeAutoHidingEvents(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() {
...
}
}
最终,至少应该有人打开一个错误。说不定不久的将来我也会去看看