【问题标题】:Moving an image using mouse drag events使用鼠标拖动事件移动图像
【发布时间】:2017-11-27 18:06:25
【问题描述】:

我目前正在用 javafx 制作游戏,我需要的是能够在图像向下移动时使用鼠标拖动事件使图像左右移动。我已经想到了后一部分(向下移动部分),并且需要帮助将拖动事件添加到我的图像视图对象,以便将其拖动到右侧是一个事件,将其拖动到左侧是另一个事件。 提前谢谢你。

这是我的 fxml 文件

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane  maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
   <children>
      <ImageView fx:id="player" fitHeight="42.0" fitWidth="98.0" layoutX="47.0" layoutY="27.0" pickOnBounds="true" preserveRatio="true">
         <image>
            <Image url="@freefall.png" />
         </image>
      </ImageView>
      <Button fx:id="button" layoutX="44.0" layoutY="21.0" mnemonicParsing="false" prefHeight="54.0" prefWidth="81.0" style="-fx-background-color: transparent; -fx-text-fill: transparent; -fx-border-fill: transparent;" text="Button" />
   </children>
</AnchorPane>

这是我的控制器类

package application;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.animation.TranslateTransition;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.ImageView;
import javafx.util.Duration;

    public class Controller implements Initializable {
        @FXML
        ImageView player;



        TranslateTransition transition = new TranslateTransition();
        private double startDragX;
        private double startDragY;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {

         player.setOnMousePressed(e -> {
             startDragX = e.getSceneX();
             startDragY = e.getSceneY();
         });

         player.setOnMouseDragged(e -> {
             double X = e.getSceneX();
              if(X - startDragX > 0)
                 player.setTranslateX(5);
             else if (X - startDragX  < 0)
                 player.setTranslateX(-5);
         });

        //This code makes the player move downwards continuously 
        transition.setDuration(Duration.seconds(15));
        transition.setNode(player);
        transition.setToY(800);
        transition.play();


    }


    }

更改代码后我面临的问题是,当您将其向右拖动一次时,玩家会移动。但是当你再次把它拖到右边时,什么也没有发生,我所能做的就是把它拖回原来的位置(把它拖回左边)。

【问题讨论】:

  • 向我们展示您已经实施的内容,以便我们就您可以或应该做什么提供建议。

标签: javafx javafx-8


【解决方案1】:

我认为您已经掌握了示例中的基础知识。

但有一点我不明白:为什么会有过渡?如果您希望ImageView 在您拖动时跟随您的鼠标光标,那么混入过渡效果会很奇怪(即,它对用户来说似乎是一种滞后)。

这是使用拖动事件移动ImageView 的基本方法。

public class Controller implements Initializable {
    @FXML
    ImageView player;

    private double startDragX;
    private double startDragY;

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        button.setMousePressed(e -> {
            startDragX = e.getSceneX();
            startDragY = e.getSceneY();
        });

        button.setMouseDragged(e -> {
            button.setTranslateX(e.getSceneX() - startDragX);
            button.setTranslateY(e.getSceneY() - startDragY);
        });
    }
}

当然,你可以选择在FXML中添加事件,并用@FXML注解注入事件方法。

编辑

在理解了问题之后,我认为这就是您想要的(或至少几乎是)。我假设您想在触控移动设备上实现类似于“轻弹”的效果,只不过这是通过鼠标完成的。

public class Controller implements Initializable {
    @FXML
    ImageView player;

    private static final double MIN_FLICK_PIXELS = 10;
    private static final double FLICK_MOVEMENT = 5;
    private enum Direction {
        LEFT, RIGHT
    }
    private double lastXPosition;
    private Direction lastFlickDirection = null;

    TranslateTransition transition = new TranslateTransition();

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        player.setOnMousePressed(e -> {
            lastXPosition = e.getSceneX();
        });

        player.setOnMouseDragged(e -> {
            double currentX = e.getSceneX();

            // Detect as "right flick" if the previous flick direction is not right, and the dragged pixels is more than 10
            if (lastFlickDirection != Direction.RIGHT && currentX - lastXPosition > MIN_FLICK_PIXELS) {
                direction = Direction.RIGHT;
                player.setTranslateX(player.getTranslateX() + FLICK_MOVEMENT);
                lastXPosition = currentX;
            }

            // Detect as "left flick" if the previous flick direction is not left, and the dragged pixels is more than -10
            else if (lastFlickDirection != Direction.LEFT && currentX - lastXPosition < -MIN_FLICK_PIXELS) {
                direction = Direction.LEFT;
                player.setTranslateX(player.getTranslateX() -FLICK_MOVEMENT);
                lastXPosition = currentX;
            }
        });

        player.setOnMouseReleased(e -> {
            lastFlickDirection = null;
        });

        //This code makes the player move downwards continuously 
        transition.setDuration(Duration.seconds(15));
        transition.setNode(player);
        transition.setToY(800);
        transition.play();
    }
}

这样做会:

  • 当用户向相应方向拖动至少 10 个像素时,将图像向右或向左移动 5 个像素。
  • 如果用户向同一方向连续拖动 20 个像素,它只会移动一次。
  • 如果用户在单个操作中向右拖动 10 个像素,然后向左拖动 10 个像素,则图像将向右移动 5 个像素,然后向左移动 5 个像素(这是原始位置)。

这里一个可能的明显缺陷是事件设置在ImageView上,因此如果光标超出ImageView的范围,事件可能会丢失(它可能不会丢失,我没有测试这)。如果出现问题,请将事件转移到可能的父级。

【讨论】:

  • 我根据编辑更改了我的代码,但正如我提到的,玩家在向右移动 5 个像素后再次向右拖动时不会移动。当我们将它拖到左边时,它所做的只是回到原来的 X 坐标。请解释它为什么这样做。谢谢。
  • @KushagrTyagi 很难想象你需要什么。根据您的编辑,我了解ImageView 将逐渐向下移动(下降效果)。您的拖动事件用于创建“向左下降”或“向右下降”效果?
  • 是的,你是对的,我想要完成的是一个连续向下移动的图像,如果以类似的方式向右和向左拖动,它可以向右移动 5 个像素。但我面临的问题是它只向右移动一次,我认为这是由于语句 setTranslateX(5),所以将它移动到坐标 x = 5 后,它不执行任何操作,因为imageView 已经在 x 坐标 5。所以我想总结一下,我需要的只是一个方法,它告诉我 Imageview 的当前 x 坐标,我将完成它
  • @KushagrTyagi 已更新。
  • 感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 2016-03-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多