我的标题措辞严厉,因为我的问题很难描述,所以我为它绘制了一个图像:
我有一个ImageView对象,代表一堆牌(不是扑克牌,但只是用它们作为例子)。单击此图像视图时,我需要一个弹出窗口,其中包含ScrollPane并向其显示链接列表中的所有卡对象。当用户单击窗口外的任何位置(稍后点击鼠标右键)时,需要关闭滚动窗格窗口。
我已经尝试过的方法:
使用APPLICATION_MODAL的场景。然后做了Scene.showAndWait()。我不喜欢这种方法,因为它在用户的任务栏上创建了另一个应用程序。它也感觉笨重而且很糟糕。
将我的根窗格更改为StackPane,然后在用户点击套牌时将此Scrollpane添加到堆栈窗格。这出于某种原因非常缓慢,看起来非常突兀。这也很烦人,因为我的备用类需要访问根窗格(因为当它关闭时,它需要转到根StackPane并自己调用.remove())。
还有其他更好的方法来实现这一目标吗?我的应用程序将拥有许多这样的堆,所以这个框架需要很好地工作。
答案 0 :(得分:2)
我仍然建议开设一个新的Stage
,但有一些限制可以通过这种方法解决您的问题。
您可以使用Stage
的{{3}}属性将另一个Stage
作为所有者,因此任务栏上不会显示其他图标。
您可以将initOwner属性与initStyle或TRANSPARENT StageStlye
一起使用,这样可确保只显示内容。
最后,您可以使用UNDECORATED检查Stage
是否失去了关闭它的重点。
示例强>
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
BorderPane root = new BorderPane();
Scene scene = new Scene(root,400,400);
Button b = new Button("Open deck");
b.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Stage popupStage = new Stage();
popupStage.initOwner(primaryStage);
popupStage.initStyle(StageStyle.UNDECORATED);
Scene sc = new Scene(new ScrollPane(), 300, 300);
popupStage.setScene(sc);
popupStage.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue,
Boolean newValue) {
if(!newValue)
popupStage.close();
}
});
popupStage.show();
}
});
root.setCenter(b);
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
当然也可以不在新的Stage
中打开它,而是在当前ScrollPane
内绘制Stage
重叠的内容Stage
使用例如focusedProperty或AnchorPane作为root,但第一个解决方案的优势在于您没有绑定主Stage
的维度(弹出窗口可以有你想要的任何尺寸。)
答案 1 :(得分:0)
您可以使用捕获鼠标事件的低级系统挂钩来实现此目的。
http://kra.lc/blog/2016/02/java-global-system-hook/或https://github.com/kwhat/jnativehook/releases
我希望这就是你所需要的,否则我的问题就会出错。