我正在使用javafx构建一个GUI应用程序,当用户从任何地方拖动内容时,需要ScrollPane中的PannableProperty工作。
在oracle docs中,他们谈到" pannableProperty":
指定用户是否应该能够使用平移视口 老鼠。如果鼠标事件到达ScrollPane(即,如果鼠标 包含的节点或其子节点之一不阻止事件) 然后咨询pannable以确定是否应该使用事件 淘选。
所以我的问题是鼠标事件无法到达ScrollPane ..
任何人都知道如何使它成为可能?
这是一个测试它的简单代码:
ScrollPane root = new ScrollPane();
root.setHbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setVbarPolicy(ScrollPane.ScrollBarPolicy.ALWAYS);
root.setPannable(true);
VBox v = new VBox(10);
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
HBox c2 = new HBox(new Label("we are just in HBox "), new TextField());
Label c3 = new Label("I'm just a label and pannableProperty works here");
TitledPane c4 = new TitledPane("test4", new HBox(new Label("test: "), new TextField()));
AnchorPane c5 = new AnchorPane();
c5.setPrefSize(100, 100);
v.getChildren().addAll(c1, c2, c3, c4, c5);
root.setContent(v);
Scene scene = new Scene(root, 300, 300);
primaryStage.setScene(scene);
primaryStage.show();
答案 0 :(得分:1)
另一个棘手的问题: - )
TitledPane
的默认外观实现是SkinBase
的子类,默认构造函数(由TitledPaneSkin
调用)执行此操作(缩短版本):
protected SkinBase(final C control) {
// Default behavior for controls is to consume all mouse events
consumeMouseEvents(true);
}
所以我们需要扭转这种局面,遗憾的是你必须对此进行反思:
TitledPane c1 = new TitledPane("test: ", new HBox(new Label("test: "), new TextField()));
c1.skinProperty().addListener((w,o,n)-> {
if(n instanceof SkinBase) {
SkinBase<?> skinbase = (SkinBase<?>) n;
try {
Method m = SkinBase.class.getDeclaredMethod("consumeMouseEvents", Boolean.TYPE);
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
boolean wasAccessible = m.isAccessible();
try {
m.setAccessible(true);
m.invoke(skinbase, false);
return null;
}
catch(ReflectiveOperationException e) { throw new IllegalStateException(e); }
finally {
m.setAccessible(wasAccessible);
}
});
} catch (ReflectiveOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
现在它应该可以工作,至少在我的测试应用程序中是这样。
编辑#1:
执行此操作会在鼠标操作期间重置焦点,这会使TitledPane无法使用。所以我们现在正在搞乱焦点系统:
ScrollPane root = new ScrollPane();
root.setFocusTraversable(false);
Scene scene = new Scene(root, 300, 300);
scene.focusOwnerProperty().addListener((w,o,n)->
if(n == root && o != null) {
o.requestFocus();
}
});
基本上我们在这里做的是,如果新聚焦的元素是ScrollPane,我们会重新聚焦以前聚焦的组件。