我正在创建一个游戏,用户需要将ImageView拖到GridPane上,当他们拖动它时,我希望他们能够按一个键来旋转ImageView。我只希望它们能够在拖动时旋转ImageView,因此我在拖动事件开始时设置KeyEvent处理程序,然后将其删除。
以下是设置处理程序的代码:
private void setPlacementHandlers()
{
setOnMouseMoved(event -> trackMouse(event));
setOnDragDetected(event -> pickedUp(event));
setOnDragDone(event -> placed(event));
}
以下是OnDragDetected的代码:
private void pickedUp(MouseEvent event)
{
//Get variables from Ship
ShipPart[] parts = ship.getParts();
int shipSize = ship.getSize();
Dragboard db = this.startDragAndDrop(TransferMode.MOVE);
ship.getBoard().setDraggedPart(this);
ClipboardContent cbContent = new ClipboardContent();
cbContent.putImage(this.getImage());
db.setDragView(shipImage);
db.setDragViewOffsetX((partIndex * 50) + mouseX);
db.setDragViewOffsetY(mouseY);
db.setContent(cbContent);
setFocusTraversable(true);
requestFocus();
setOnKeyPressed(keyEvent -> rotate(keyEvent, db, cbContent));
getScene().onKeyPressedProperty().bind(this.onKeyPressedProperty());
for(int i = 0; i < shipSize; i++)
parts[i].setVisible(false);
event.consume();
}
以下是OnKeyPressed的临时版本,我将其用于测试目的:
private void rotate(KeyEvent keyEvent, Dragboard db, ClipboardContent cbContent)
{
System.out.println("Potato");
}
我试过setFocusTraversable(true);和requestFocus();
出于调试的目的,我删除了在拖动完成后删除KeyEvent处理程序的代码,结果发现KeyEvent在DragEvent之后工作正常,但在此期间没有。
总而言之,问题似乎并不是ImageView没有获得KeyEvent,看起来好像KeyEvent甚至没有因DragEvent而生成。
感谢任何帮助。
更新:我还尝试将KeyEvent处理程序添加到另一个对象,然后将更改应用于我想要更改的对象,但这并不起作用。我还尝试了各种线程和任务组合。
答案 0 :(得分:1)
拖放操作是本机系统操作。它显示的任何图形都是本机对象,而不是Java应用程序的一部分,尽管系统为应用程序提供了有限的配置能力,Java通过Dragboard等类提供访问。
由于拖动的对象不是JavaFX节点,因此无法在其上侦听(大多数)关键事件。实际上,在拖动过程中,程序中没有Node可能没有键盘焦点。
如果拖动源和拖动目标都在同一个场景中,您可以自己模拟拖动,方法是将场景的内容放在StackPane中,然后在同一个StackPane中放置一个“拖动窗格”,这样就可以了内容的顶部,带有一个剪辑,确保它不会阻止内容的键盘或鼠标事件。拖动窗格同时包含可拖动节点的副本(在您的情况下为ImageView),以及用于突出显示当前拖动下的任何节点的形状。
import java.nio.file.Paths;
import java.util.List;
import javafx.application.Application;
import javafx.beans.Observable;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.stage.Stage;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.SplitPane;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
public class ImageDragExample
extends Application {
private static final String DEFAULT_IMAGE =
"http://solarsystem.nasa.gov/images/galleries/618486main_earth_320.jpg";
private GridPane grid;
private ImageView preview;
private ImageView dragImage;
private Pane dragPane;
private Rectangle dragPaneClip;
private Point2D dragStart;
private Node dragTarget;
private Shape dragHighlight;
@Override
public void start(Stage stage) {
grid = new GridPane();
grid.setHgap(24);
grid.setVgap(24);
grid.setPadding(new Insets(12));
int id = 0;
for (int row = 0; row < 3; row++) {
Node p1 = createPlaceholder(String.valueOf(row * 4 + 1));
Node p2 = createPlaceholder(String.valueOf(row * 4 + 2));
Node p3 = createPlaceholder(String.valueOf(row * 4 + 3));
Node p4 = createPlaceholder(String.valueOf(row * 4 + 4));
grid.addRow(row, p1, p2, p3, p4);
}
List<String> args = getParameters().getRaw();
preview = new ImageView(args.isEmpty() ? DEFAULT_IMAGE :
Paths.get(args.get(0)).toUri().toString());
BorderPane imageArea = new BorderPane(preview);
imageArea.setPadding(new Insets(12));
Region contents = new BorderPane(new SplitPane(grid, imageArea));
dragImage = new ImageView();
dragImage.imageProperty().bind(preview.imageProperty());
dragImage.setFocusTraversable(true);
dragImage.setOpacity(0);
dragImage.setOnMousePressed(e -> startDrag(e));
dragImage.setOnMouseDragged(e -> updateDrag(e));
dragImage.setOnMouseReleased(e -> endDrag(e));
dragImage.setOnKeyPressed(e -> rotate(e));
dragPane = new AnchorPane(dragImage);
dragPaneClip = new Rectangle();
dragPane.setClip(dragPaneClip);
StackPane pane = new StackPane(contents, dragPane);
Scene scene = new Scene(pane);
stage.setScene(scene);
preview.boundsInParentProperty().addListener(this::placeDragImage);
imageArea.boundsInParentProperty().addListener(this::placeDragImage);
stage.widthProperty().addListener(this::placeDragImage);
stage.heightProperty().addListener(this::placeDragImage);
placeDragImage(null);
stage.setTitle("Image Drag Example");
stage.show();
}
private void rotate(KeyEvent e){
System.out.println(e.getCode() + " pressed");
}
private void startDrag(MouseEvent event){
dragStart = new Point2D(event.getScreenX(), event.getScreenY());
dragImage.setOpacity(0.5);
dragImage.requestFocus();
dragPane.setClip(null);
}
private void updateDrag(MouseEvent event){
double x = event.getScreenX();
double y = event.getScreenY();
double xDelta = x - dragStart.getX();
double yDelta = y - dragStart.getY();
dragImage.setTranslateX(xDelta);
dragImage.setTranslateY(yDelta);
Node newDragTarget = null;
for (Node node : grid.getChildren()) {
if (node.contains(node.screenToLocal(x, y))) {
newDragTarget = node;
break;
}
}
removeDragHighlight();
dragTarget = newDragTarget;
addDragHighlight(dragTarget);
}
private void endDrag(MouseEvent event){
if (dragTarget != null) {
removeDragHighlight();
System.out.println("Dropped on " + dragTarget.getId());
}
dragImage.setOpacity(0);
dragImage.setTranslateX(0);
dragImage.setTranslateY(0);
dragPane.setClip(dragPaneClip);
dragStart = null;
dragTarget = null;
}
private void placeDragImage(Observable o) {
if (preview.getScene() != null && dragImage.getScene() != null) {
Point2D point = preview.localToScene(0, 0);
if (point != null) {
point = dragImage.getParent().sceneToLocal(point);
AnchorPane.setLeftAnchor(dragImage, point.getX());
AnchorPane.setTopAnchor(dragImage, point.getY());
dragPaneClip.setX(point.getX());
dragPaneClip.setY(point.getY());
dragPaneClip.setWidth(dragImage.getLayoutBounds().getWidth());
dragPaneClip.setHeight(dragImage.getLayoutBounds().getHeight());
}
}
}
private void addDragHighlight(Node node) {
if (node != null) {
Bounds bounds = node.getBoundsInLocal();
dragHighlight = null;
if (node instanceof Region) {
dragHighlight = ((Region) node).getShape();
}
if (dragHighlight == null) {
dragHighlight = new Rectangle(
bounds.getMinX(), bounds.getMinY(),
bounds.getWidth(), bounds.getHeight());
} else {
// Clone the node's shape by subtracting an empty shape from it.
dragHighlight = Shape.subtract(dragHighlight, new Polyline());
}
dragHighlight.setStrokeWidth(2);
dragHighlight.setStroke(Color.RED);
dragHighlight.setFill(null);
bounds = dragHighlight.getBoundsInLocal();
Point2D shapeOrigin =
node.localToScene(bounds.getMinX(), bounds.getMinY());
shapeOrigin = dragPane.sceneToLocal(shapeOrigin);
dragPane.getChildren().add(dragHighlight);
AnchorPane.setLeftAnchor(dragHighlight, shapeOrigin.getX());
AnchorPane.setTopAnchor(dragHighlight, shapeOrigin.getY());
}
}
private void removeDragHighlight() {
if (dragHighlight != null) {
dragPane.getChildren().remove(dragHighlight);
dragHighlight = null;
}
}
private Node createPlaceholder(String id) {
Label label = new Label(id);
label.setId(id);
label.setAlignment(Pos.CENTER);
label.setStyle("-fx-background-color: #c0c0ff;");
label.setPrefSize(200, 200);
return label;
}
}