与鼠标事件分开触摸

时间:2014-04-23 08:48:22

标签: java events javafx touch mouse

我使用触摸显示器来控制应用程序上的节点。但是,如果应用程序没有使用触摸监视器运行,我还想用鼠标事件控制节点,以便可以处理这两个事件。我尝试了以下方式:

private void initDraggable() {
    touchFilter = new EventHandler<TouchEvent>() {
        @Override public void handle(TouchEvent event) {
            System.out.println("Touch dragged");    

            touchTaskViewModel.actualClickPointProperty().set(new ClickPoint(event.getTouchPoint().getX(), event.getTouchPoint().getY()));
            touchTaskViewModel.sceneXProperty().set(event.getTouchPoint().getSceneX());

            touchTaskViewModel.handleTaskMoved();

            event.consume();
        }
    };

    addEventFilter(TouchEvent.TOUCH_MOVED, touchFilter);

    setOnTouchPressed(new EventHandler<TouchEvent>() {
        @Override
        public void handle(TouchEvent event) {
            touchTaskViewModel.entryClickPointProperty().set(new ClickPoint(event.getTouchPoint().getX(), event.getTouchPoint().getY()));

            touchTaskViewModel.taskSelectedProperty().set(true);

            event.consume();
        }
    });

    setOnTouchReleased(new EventHandler<TouchEvent>() {
        @Override
        public void handle(TouchEvent event) {
            touchTaskViewModel.taskSelectedProperty().set(false);

            event.consume();
        }
    });

    clickFilter = new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent event) {
          if(!event.isSynthesized()){
            System.out.println("Mouse dragged!");   

            touchTaskViewModel.actualClickPointProperty().set(new ClickPoint(event.getX(), event.getY()));
            touchTaskViewModel.sceneXProperty().set(event.getSceneX());

            touchTaskViewModel.handleTaskMoved();
            event.consume();
          }
      }
    };

    addEventFilter(MouseEvent.MOUSE_DRAGGED, clickFilter);

    setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            if(!event.isSynthesized()){

                touchTaskViewModel.entryClickPointProperty().set(new ClickPoint(event.getX(), event.getY()));

                touchTaskViewModel.taskSelectedProperty().set(true);

                event.consume();
            }
        }
    });

    setOnMouseReleased(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent event) {
            if(!event.isSynthesized()){ 
                touchTaskViewModel.taskSelectedProperty().set(false);

                event.consume();
            }
        }
    });
}

因此,如果事件已由触摸事件处理,则函数isSynthesized()应返回true。但无论我使用触摸显示器还是鼠标拖动节点,它都会返回false。

触摸事件处理正确,我看到它会同时打印“触摸拖动”和“鼠标拖动”。

1 个答案:

答案 0 :(得分:1)

混合触摸和鼠标事件很难。即使isSynthesized可靠(似乎总是对我来说),它也不能解决所有可能出现的问题。例如,如果你有一个Button,并且你希望能够通过鼠标或触摸屏触发它的动作,你可以让触摸屏模拟鼠标,这样就可以在没有任何额外代码的情况下工作超出鼠标界面所需的范围。但是,当您使用鼠标单击时,Button会获得焦点,并且在您按住鼠标左键时会明显布防。但是,在释放鼠标左键之前,Button的操作不会触发。

对于触控界面,鼠标仿真并不是很好。当您用手指按下Button时,它不会聚焦,也不会设防。当您将手指从屏幕上移开时释放Button,然后您获得鼠标按下事件,然后操作触发,然后(有点莫名其妙)您释放鼠标并使用鼠标点击活动。因此,当您依赖触摸屏的鼠标仿真时,视觉反馈并不是很好。此外,根据您的喜好,通过屏幕按下按钮并不能完成真正的机电按钮所做的事情,这会导致他们的行动发生火灾。 。。

现在,假设您希望鼠标界面继续按照它的方式工作(在鼠标释放事件时发生操作),您可以添加自己的&#34;跳过&#34;标记触摸事件处理,并让操作处理程序查询该标记。诀窍是知道何时设置该标志,何时不设置。人们希望在处理触摸按下事件时始终设置该标志,因为那将是焦点的事件,设置Button并触发操作,所以你不要&# 39;不希望鼠标事件导致第二次射击。

但是...

如果在将手指从屏幕上抬起之前将手指从Button上移开, 这是因为模拟的鼠标释放事件不会在Button内,并且不会用真正的鼠标触发动作,因此仿真不会触发它或者(尽管在调用动作处理程序之后鼠标释放和鼠标单击事件都被发送到您的代码)。

因此,为避免在未发生第二次触发时设置跳过标志,您不能在触摸按下处理程序中设置它。当Button包含的屏幕点发生释放时,您必须在触摸释放处理程序中有条件地设置它

下面的代码显示了它的工作原理。 (你知道有关拖动的问题,而不是Button s。但是你在两年多的时间内没有得到任何答案,而且我正在思考制作触摸界面和鼠标界面所涉及的问题很好地在一起,特别是那些要求触摸事件导致动作的双重触发的那些,通常可以通过我在这里使用的技术来处理。希望它有所帮助。)

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ShowNanoTime extends Application
{
    Label msg = new Label();

    public static void main(String... args)
    {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception
    {
        Button btnShowTime = new Button("Show Time");
        VBox root = new VBox();

        Handler handler = new Handler();

        btnShowTime.setOnTouchPressed(handler.new TouchPressed());
        btnShowTime.setOnTouchReleased(handler.new TouchReleased());

        btnShowTime.setOnAction(handler.new Action(this));

        root.getChildren().addAll(msg, btnShowTime);

        Scene scene = new Scene(root, 640, 360);
        stage.setScene(scene);

        stage.show();
    }

    void showTime()
    {
        msg.setText(String.format("%d", System.nanoTime()));
    }
}

class Handler
{
    boolean skip = false;

    class TouchPressed implements EventHandler<TouchEvent>
    {
        @Override
        public void handle(TouchEvent event)
        {
            System.out.println("Touch pressed.");
            ((Button) event.getSource()).requestFocus();
            ((Button) event.getSource()).arm();
            ((Button) event.getSource()).fire();
        }
    }

    class TouchReleased implements EventHandler<TouchEvent>
    {
        @Override
        public void handle(TouchEvent event)
        {
            System.out.println("Touch released");

            Button button = (Button) event.getSource();

            double x = event.getTouchPoint().getX();
            double y = event.getTouchPoint().getY();

            if (button.contains(x, y))
            {
                System.out.println("Setting skip.");
                skip = true;
            }
        }
    }

    class Action implements EventHandler<ActionEvent>
    {
        ShowNanoTime app;

        Action(ShowNanoTime app)
        {
            this.app = app;
        }

        @Override
        public void handle(ActionEvent event)
        {
            if (skip)
            {
                skip = false;
                System.out.println("Action skipped.");
                return;
            }

            System.out.println("Action happens!");

            app.showTime();
        }
    }
}

注意:我的代码中没有特定于平台的内容,但我只在Windows 10计算机上运行上述内容。