JavaFX - 截取来自" child"的拖动事件pannable ScrollPane并重定向到" parent"滚动窗格

时间:2015-04-25 23:25:20

标签: java javafx mouseevent javafx-8

我正在努力完成"拦截"从一个pannable ScrollPane(" child")拖动事件,并将该事件重定向到另一个ScrollPane(" parent")。

这是我尝试这样做的:

--assuming your string looks something like this..
declare @s varchar(max) = 'asdaf=xxx|PersonIQ=100|xxx=yyy'

select convert(xml, '<x ' + replace(replace(@s, '=', '='''), '|', ''' ') + '''/>').value('(/x/@PersonIQ)[1]','int')

我有一个带有两个ScrollPanes的VBox(舞台的根)。两个ScrollPanes都是可以使用的。在这种情况下,我将顶部(和更大的)ScrollPane指定为父ScrollPane,将底部(和较小的)Scrollpane指定为子ScrollPane。我将子ScrollPane的h和v值绑定到父ScrollPane,这样当在父ScrollPane中拖动/平移时,子ScrollPane也会移动。然后我尝试为import javafx.application.Application; import javafx.geometry.Point2D; import javafx.scene.Cursor; import javafx.scene.Scene; import javafx.scene.control.ScrollPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.input.MouseEvent; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class Main extends Application { private final Image PARENT_IMAGE = new Image("http://www.tolkien.co.uk/file/IfbTdA8/5d04a105-e66b-4d9b-b218-928c691eb83d.jpg"); private final Image CHILD_IMAGE = new Image("http://knightly-slumber.com/worldofwarcraft/files/ScreenShot00019.jpg"); @Override public void start(Stage stage) throws Exception { stage.setTitle("ScrollPane Sync"); // Set up the scene (two ScrollPanes, both pannable) final ScrollPane parentScrollPane = new ScrollPane(); final ScrollPane childScrollPane = new ScrollPane(); parentScrollPane.setPrefSize(600, 400); childScrollPane.setPrefSize(200, 200); parentScrollPane.setContent(new ImageView(PARENT_IMAGE)); childScrollPane.setContent(new ImageView(CHILD_IMAGE)); parentScrollPane.setPannable(true); childScrollPane.setPannable(true); parentScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); parentScrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); childScrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); childScrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); parentScrollPane.setCursor(Cursor.MOVE); childScrollPane.setCursor(Cursor.MOVE); VBox root = new VBox(parentScrollPane, childScrollPane); root.setPrefSize(800, 600); // Make childScrollPane sync with parentScrollPane's h and v-values childScrollPane.hvalueProperty().bind(parentScrollPane.hvalueProperty()); childScrollPane.vvalueProperty().bind(parentScrollPane.vvalueProperty()); // Attempt to intercept drag events from childScrollPane and re-direct to parentScrollPane childScrollPane.addEventFilter(MouseEvent.MOUSE_DRAGGED, event -> { // re-map x,y coords relative position from child to parent (as they are different sizes). // In other words, if the drag event happened 40% of the way "across" (from the left) and 60% // "down" (from the top) the child pane, then re-map those relative positions to absolute // positions in terms of the parent pane (40% across and 60% down the parent pane). double xRelative = event.getX() / childScrollPane.getViewportBounds().getWidth(); double xInParent = xRelative * parentScrollPane.getViewportBounds().getWidth(); double yRelative = event.getY() / childScrollPane.getViewportBounds().getHeight(); double yInParent = yRelative * parentScrollPane.getViewportBounds().getHeight(); Point2D screenCoords = parentScrollPane.localToScreen(xInParent, yInParent); MouseEvent redirectedEvent = new MouseEvent( parentScrollPane, root, MouseEvent.MOUSE_DRAGGED, xInParent, yInParent, screenCoords.getX(), screenCoords.getY(), event.getButton(), event.getClickCount(), event.isShiftDown(), event.isControlDown(), event.isAltDown(), event.isMetaDown(), event.isPrimaryButtonDown(), event.isMiddleButtonDown(), event.isSecondaryButtonDown(), event.isSynthesized(), event.isPopupTrigger(), event.isStillSincePress(), event.getPickResult() ); MouseEvent.fireEvent(parentScrollPane, redirectedEvent); event.consume(); }); Scene scene = new Scene(root); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } } 个事件添加一个事件过滤器,以便我们可以拦截&#34;拖动父ScrollPane上的事件。然后我尝试重新指导该事件,并根据父ScrollPane重新投射它,然后触发这个新事件,并使用旧事件。

目前,平移父ScrollPane会导致子ScrollPane也移动(这很好)但是在子ScrollPane中拖动时没有任何反应(我们希望ScrollPane在这种情况下都移动)。

有人可能会问:为什么不对两个ScrollPanes的h和v值使用双向绑定?我想避免这样做的原因是它打破了我试图维护的parent-gt;子关系。换句话说,我希望所有人都能来自&#34;来自&#34;并由父ScrollPane控制。

1 个答案:

答案 0 :(得分:0)

我设法通过这样做将子事件重定向到父滚动窗格:

// Catch events on scrollPane's children
@FXML
public void press(MouseEvent event) {
    ScrollPane sp = (ScrollPane) ((Node) event.getSource()).getParent().getParent().getParent().getParent();

    PickResult pr = new PickResult(sp.getContent(), event.getSceneX(), event.getSceneY());
    MouseEvent event2 = new MouseEvent(sp, sp.getContent(), event.getEventType(), event.getX(), event.getY(), event.getScreenX(), event.getScreenY(), event.getButton(), event.getClickCount(), event.isShiftDown(), event.isControlDown(), event.isAltDown(), event.isMetaDown(), event.isPrimaryButtonDown(), event.isMiddleButtonDown(), event.isSecondaryButtonDown(), event.isSynthesized(), event.isPopupTrigger(), event.isStillSincePress(), pr);
    sp.getContent().fireEvent(event2);
}

@FXML
public void drag(MouseEvent event) {
    ScrollPane sp = (ScrollPane) ((Node) event.getSource()).getParent().getParent().getParent().getParent();

    PickResult pr = new PickResult(sp.getContent(), event.getSceneX(), event.getSceneY());
    MouseEvent event2 = new MouseEvent(sp, sp.getContent(), event.getEventType(), event.getX(), event.getY(), event.getScreenX(), event.getScreenY(), event.getButton(), event.getClickCount(), event.isShiftDown(), event.isControlDown(), event.isAltDown(), event.isMetaDown(), event.isPrimaryButtonDown(), event.isMiddleButtonDown(), event.isSecondaryButtonDown(), event.isSynthesized(), event.isPopupTrigger(), event.isStillSincePress(), pr);
    sp.getContent().fireEvent(event2);
}

// drag detected => cursor changes
@FXML
public void dragDetected(MouseEvent event) {
    ScrollPane sp = (ScrollPane) ((Node) event.getSource()).getParent().getParent().getParent().getParent();

    PickResult pr = new PickResult(sp.getContent(), event.getSceneX(), event.getSceneY());
    MouseEvent event2 = new MouseEvent(sp, sp.getContent(), event.getEventType(), event.getX(), event.getY(), event.getScreenX(), event.getScreenY(), event.getButton(), event.getClickCount(), event.isShiftDown(), event.isControlDown(), event.isAltDown(), event.isMetaDown(), event.isPrimaryButtonDown(), event.isMiddleButtonDown(), event.isSecondaryButtonDown(), event.isSynthesized(), event.isPopupTrigger(), event.isStillSincePress(), pr);
    sp.getContent().fireEvent(event2);
}

希望它会有所帮助。