java - JavaFX - Intercept Drag Events from "child" pannable ScrollPane and redirect to "parent" ScrollPane -
i trying accomplish "intercepting" drag events 1 pannable scrollpane (the "child") , re-direct event scrollpane (the "parent").
here attempt @ doing so:
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 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 parentscrollpane's h , v-values childscrollpane.hvalueproperty().bind(parentscrollpane.hvalueproperty()); childscrollpane.vvalueproperty().bind(parentscrollpane.vvalueproperty()); // attempt intercept drag events childscrollpane , re-direct parentscrollpane childscrollpane.addeventfilter(mouseevent.mouse_dragged, event -> { // re-map x,y coords relative position child parent (as different sizes). // in other words, if drag event happened 40% of way "across" (from left) , 60% // "down" (from top) child pane, re-map relative positions absolute // positions in terms of parent pane (40% across , 60% down 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); } }
i have vbox (the root of stage) 2 scrollpanes. both scrollpanes pannable. in case, designate top (and larger) scrollpane parent scrollpane, , bottom (and smaller) scrollpane child scrollpane. bind h , v-values of child scrollpane parent scrollpane, when 1 drags/pans in parent scrollpane, child scrollpane moves. attempt add event filter mouseevent.mouse_dragged
events can "intercept" drag events on parent scrollpane. attempt re-direct event , re-cast in terms of parent scrollpane, , fire new event, , consume old one.
currently, panning parent scrollpane causes child scrollpane move (this good) nothing happens when dragging in child scrollpane (we want both scrollpane's move in case).
one might ask: why don't use bi-directional binding h , v-values 2 scrollpanes? reason want avoid doing breaks parent->child relationship trying maintain. in other words, want panning "come from" , controlled parent scrollpane.
i managed redirect children events parent scrollpane doing :
// 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); }
hope help.
Comments
Post a Comment