下面列出了javafx.scene.Node#contains ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public void handle(MouseEvent event) {
//use this so that when the mouse moves over the canvas and something in canvas controls has focus, the key presses
//and mouse events are sent to the canvas rather than the focuses control
canvasView.focusToCanvas(event.getTarget() == canvasView.uiCanvasEditor.getCanvas());
double sceneX = event.getSceneX();
double sceneY = event.getSceneY();
for (Node node : canvasView.notificationPane.getContentPane().getChildren()) {
Point2D point2D = node.sceneToLocal(sceneX, sceneY);
if (node.contains(point2D)) {
canvasView.notificationPane.getContentPane().setMouseTransparent(false);
return;
}
}
canvasView.notificationPane.getContentPane().setMouseTransparent(true);
}
public Set<Node> pickNodes(double sceneX, double sceneY, Node root) {
Set<Node> picked = new HashSet<>();
// start with given root node
Queue<Node> nodes = new LinkedList<>();
nodes.add(root);
while (!nodes.isEmpty()) {
Node current = nodes.remove();
if (current.contains(current.sceneToLocal(sceneX, sceneY))) {
picked.add(current);
// test all children, too
if (current instanceof Parent) {
nodes.addAll(((Parent) current).getChildrenUnmodifiable());
}
}
}
return picked;
}
/**
* Determines the closest node that resides in the x,y scene position, if any.
* <br>
* Obtained from: http://fxexperience.com/2016/01/node-picking-in-javafx/
*
* @param node parent node
* @param sceneX x-coordinate of picking point
* @param sceneY y-coordinate of picking point
*
* @return topmost node containing (sceneX, sceneY) point
*/
public static Node pick(Node node, double sceneX, double sceneY) {
Point2D p = node.sceneToLocal(sceneX, sceneY, true /* rootScene */);
// check if the given node has the point inside it, or else we drop out
if (!node.contains(p)) {
return null;
}
// at this point we know that _at least_ the given node is a valid
// answer to the given point, so we will return that if we don't find
// a better child option
if (node instanceof Parent) {
// we iterate through all children in reverse order, and stop when we find a match.
// We do this as we know the elements at the end of the list have a higher
// z-order, and are therefore the better match, compared to children that
// might also intersect (but that would be underneath the element).
Node bestMatchingChild = null;
List<Node> children = ((Parent) node).getChildrenUnmodifiable();
for (int i = children.size() - 1; i >= 0; i--) {
Node child = children.get(i);
p = child.sceneToLocal(sceneX, sceneY, true /* rootScene */);
if (child.isVisible() && !child.isMouseTransparent() && child.contains(p)) {
bestMatchingChild = child;
break;
}
}
if (bestMatchingChild != null) {
return pick(bestMatchingChild, sceneX, sceneY);
}
}
return node;
}
/**
* Performs picking on the scene graph beginning at the specified root node
* and processing its transitive children.
*
* @param sceneX
* The x-coordinate of the position to pick nodes at, interpreted
* in scene coordinate space.
* @param sceneY
* The y-coordinate of the position to pick nodes at, interpreted
* in scene coordinate space.
* @param root
* The root node at which to start with picking
* @return A list of {@link Node}s which contain the the given coordinate.
*/
public static List<Node> getNodesAt(Node root, double sceneX,
double sceneY) {
List<Node> picked = new ArrayList<>();
// start with given root node
List<Node> nodes = new ArrayList<>();
nodes.add(root);
while (!nodes.isEmpty()) {
Node current = nodes.remove(0);
// transform to local coordinates
Point2D pLocal = current.sceneToLocal(sceneX, sceneY);
// check if bounds contains (necessary to find children in mouse
// transparent regions)
if (!current.isMouseTransparent()
&& current.getBoundsInLocal().contains(pLocal)) {
// check precisely
if (current.contains(pLocal)) {
picked.add(0, current);
}
// test all children, too
if (current instanceof Parent) {
nodes.addAll(0,
((Parent) current).getChildrenUnmodifiable());
}
}
}
return picked;
}
public static boolean contains(Node n, double screenx, double screeny)
{
if(n != null)
{
Point2D p = n.screenToLocal(screenx, screeny);
if(p != null)
{
return n.contains(p);
}
}
return false;
}
/** returns true if (x,y) point in eventSource coordinates is contained by eventTarget node */
public static boolean contains(Node eventSource, Node eventTarget, double x, double y)
{
Point2D p = eventSource.localToScreen(x, y);
if(p != null)
{
p = eventTarget.screenToLocal(p);
if(p != null)
{
return eventTarget.contains(p);
}
}
return false;
}
/**
* Traverse the scene graph for all open stages and pick an event target for a dock event based on
* the location. Once the event target is chosen run the event task with the target and the
* previous target of the last dock event if one is cached. If an event target is not found fire
* the explicit dock event on the stage root if one is provided.
*
* @param location The location of the dock event in screen coordinates.
* @param eventTask The event task to be run when the event target is found.
* @param explicit The explicit event to be fired on the stage root when no event target is found.
*/
private void pickEventTarget(Point2D location, EventTask eventTask, Event explicit) {
// RFE for public scene graph traversal API filed but closed:
// https://bugs.openjdk.java.net/browse/JDK-8133331
List<DockPane> dockPanes = DockPane.dockPanes;
// fire the dock over event for the active stages
for (DockPane dockPane : dockPanes) {
Window window = dockPane.getScene().getWindow();
if (!(window instanceof Stage)) continue;
Stage targetStage = (Stage) window;
// obviously this title bar does not need to receive its own events
// though users of this library may want to know when their
// dock node is being dragged by subclassing it or attaching
// an event listener in which case a new event can be defined or
// this continue behavior can be removed
if (targetStage == this.dockNode.getStage())
continue;
eventTask.reset();
Node dragNode = dragNodes.get(targetStage);
Parent root = targetStage.getScene().getRoot();
Stack<Parent> stack = new Stack<Parent>();
if (root.contains(root.screenToLocal(location.getX(), location.getY()))
&& !root.isMouseTransparent()) {
stack.push(root);
}
// depth first traversal to find the deepest node or parent with no children
// that intersects the point of interest
while (!stack.isEmpty()) {
Parent parent = stack.pop();
// if this parent contains the mouse click in screen coordinates in its local bounds
// then traverse its children
boolean notFired = true;
for (Node node : parent.getChildrenUnmodifiable()) {
if (node.contains(node.screenToLocal(location.getX(), location.getY()))
&& !node.isMouseTransparent()) {
if (node instanceof Parent) {
stack.push((Parent) node);
} else {
eventTask.run(node, dragNode);
}
notFired = false;
break;
}
}
// if none of the children fired the event or there were no children
// fire it with the parent as the target to receive the event
if (notFired) {
eventTask.run(parent, dragNode);
}
}
if (explicit != null && dragNode != null && eventTask.getExecutions() < 1) {
Event.fireEvent(dragNode, explicit.copyFor(this, dragNode));
dragNodes.put(targetStage, null);
}
}
}
@Override
public Optional<Hit> isHit(double x, double y) {
if (targetGroup.getBoundsInParent().contains(x, y)) {
// Target was hit, see if a specific region was hit
for (int i = targetGroup.getChildren().size() - 1; i >= 0; i--) {
final Node node = targetGroup.getChildren().get(i);
if (!(node instanceof TargetRegion)) continue;
final Bounds nodeBounds = targetGroup.getLocalToParentTransform().transform(node.getBoundsInParent());
final int adjustedX = (int) (x - nodeBounds.getMinX());
final int adjustedY = (int) (y - nodeBounds.getMinY());
if (nodeBounds.contains(x, y)) {
// If we hit an image region on a transparent pixel,
// ignore it
final TargetRegion region = (TargetRegion) node;
// Ignore regions where ignoreHit tag is true
if (region.tagExists(TargetView.TAG_IGNORE_HIT)
&& Boolean.parseBoolean(region.getTag(TargetView.TAG_IGNORE_HIT)))
continue;
if (region.getType() == RegionType.IMAGE) {
// The image you get from the image view is its
// original size. We need to resize it if it has
// changed size to accurately determine if a pixel
// is transparent
final Image currentImage = ((ImageRegion) region).getImage();
if (adjustedX < 0 || adjustedY < 0) {
logger.debug(
"An adjusted pixel is negative: Adjusted ({}, {}), Original ({}, {}), "
+ " nodeBounds.getMin ({}, {})",
adjustedX, adjustedY, x, y, nodeBounds.getMaxX(),
nodeBounds.getMinY());
return Optional.empty();
}
if (Math.abs(currentImage.getWidth() - nodeBounds.getWidth()) > .0000001
|| Math.abs(currentImage.getHeight() - nodeBounds.getHeight()) > .0000001) {
final BufferedImage bufferedOriginal = SwingFXUtils.fromFXImage(currentImage, null);
final java.awt.Image tmp = bufferedOriginal.getScaledInstance((int) nodeBounds.getWidth(),
(int) nodeBounds.getHeight(), java.awt.Image.SCALE_SMOOTH);
final BufferedImage bufferedResized = new BufferedImage((int) nodeBounds.getWidth(),
(int) nodeBounds.getHeight(), BufferedImage.TYPE_INT_ARGB);
final Graphics2D g2d = bufferedResized.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
try {
if (adjustedX >= bufferedResized.getWidth() || adjustedY >= bufferedResized.getHeight()
|| bufferedResized.getRGB(adjustedX, adjustedY) >> 24 == 0) {
continue;
}
} catch (final ArrayIndexOutOfBoundsException e) {
final String message = String.format(
"Index out of bounds while trying to find adjusted coordinate (%d, %d) "
+ "from original (%.2f, %.2f) in adjusted BufferedImage for target %s "
+ "with width = %d, height = %d",
adjustedX, adjustedY, x, y, getTargetFile().getPath(),
bufferedResized.getWidth(), bufferedResized.getHeight());
logger.error(message, e);
return Optional.empty();
}
} else {
if (adjustedX >= currentImage.getWidth() || adjustedY >= currentImage.getHeight()
|| currentImage.getPixelReader().getArgb(adjustedX, adjustedY) >> 24 == 0) {
continue;
}
}
} else {
// The shot is in the bounding box but make sure it
// is in the shape's
// fill otherwise we can get a shot detected where
// there isn't actually
// a region showing
final Point2D localCoords = targetGroup.parentToLocal(x, y);
if (!node.contains(localCoords)) continue;
}
return Optional.of(new Hit(this, (TargetRegion) node, adjustedX, adjustedY));
}
}
}
return Optional.empty();
}