我目前正在基于JavaFX的GUI程序进行视频编辑。在这里,我遇到了ScrollPanes的问题。我不知道如何使ScrollPane(真正)在边界上拾取。这意味着我实际上可以在ScrollPane上单击以下节点。这可能是ScrollPane的视口存在的问题。我试图在下面给出程序的简化版本:Styles.css:
.scroll-pane > .viewport {
-fx-background-color: transparent;
-fx-background-radius: 4;
}
FXML:
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.ScrollPane?>
<StackPane
xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="sample.Controller" fx:id="myStackPane">
<Pane onMousePressed="#onMouseInteraction" style="-fx-background-color: red"/>
<AnchorPane fx:id="markerIconPane" pickOnBounds="false">
<ScrollPane style="-fx-background-color: transparent" pickOnBounds="false" vbarPolicy="ALWAYS" hbarPolicy="ALWAYS"/>
</AnchorPane>
</StackPane>
sample.Controller.java:
package sample;
import javafx.scene.input.MouseEvent;
import javafx.fxml.FXML;
public class Controller implements Initializable {
//...
public onMouseInteraction(MouseEvent mouseEvent) {
System.out.println(mouseEvent.getX());
}
}
sample.Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
root.getStylesheets().add("./Styles.css");
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
现在您可以清楚地看到左上方的滚动条。当您按下滚动条外部的红色时,会调用onMouseInteraction()
,但是当您按下滚动条内部时,什么也不会发生。
谢谢菲利普
假设Pane
要素是您提到的视口;您可以将onMouseInteraction
处理程序作为EventFilter添加到堆栈窗格中,以便它位于正确的事件链中。例如:
myStackPane.addEventFilter(Controller::onMouseInteraction) ;
那样,Pane
不需要作为额外的事件层,尽管缺点是您无法仅从fxml文件添加EventFilter。但是,您也可以在控制器的init方法中添加该语句。
如果要在Pane
中进行视觉叠加,可以将其mouseTransparent
属性设置为true。这样,它就不会干扰事件(就像它不在那儿一样)
如果无法将EventFilter放入事件链中,那么实际上不是一个好的解决方案。在javafx8中,我通过使用修改后的PickResult
传播事件来“入侵”系统。但是在以后的版本中,已使用(已描述)的方法已设为私有(即,没有大量反射就无法使用)。