当前位置: 首页 > 知识库问答 >
问题:

JavaFX:如何对形状进行分组以便拖动?

萧远
2023-03-14

如何在JavaFX中组合形状(例如圆形)以拖动它们?示例代码基于 Oracle 教程。每个圆圈都可以移动。我想在拖动蓝色圆圈时单独移动它。我想在单击并拖动绿色圆圈时移动绿色和蓝色圆圈,并在单击并拖动红色圆圈时移动所有三个圆圈。有什么想法吗?

public class DragGroupSample extends Application {

    public static void main( String[] args ) {
        launch();
    }

    private void makeDraggable( Circle circle ) {
        DragContext dragContext = new DragContext();

        // --- remember initial coordinates of mouse cursor and node
        circle.addEventFilter( MouseEvent.MOUSE_PRESSED, (
                final MouseEvent mouseEvent ) -> {
            dragContext.dx = mouseEvent.getX() - circle.getCenterX();
            dragContext.dy = mouseEvent.getY() - circle.getCenterY();
        } );

        // --- Shift node calculated from mouse cursor movement
        circle.addEventFilter( MouseEvent.MOUSE_DRAGGED, (
                final MouseEvent mouseEvent ) -> {
            circle.setCenterX( mouseEvent.getX() + dragContext.dx );
            circle.setCenterY( mouseEvent.getY() + dragContext.dy );
        } );

        // --- Drop card onto allowed target field
        circle.addEventFilter( MouseEvent.MOUSE_RELEASED, (
                final MouseEvent mouseEvent ) -> {
            circle.setCenterX( mouseEvent.getX() + dragContext.dx );
            circle.setCenterY( mouseEvent.getY() + dragContext.dy );
        } );
    }

    @Override
    public void start( Stage primaryStage ) throws Exception {
        Circle[] circles = new Circle[3];
        circles[0] = new Circle( 30.0, 30.0, 30.0, Color.RED );
        circles[1] = new Circle( 45.0, 45.0, 30.0, Color.GREEN );
        circles[2] = new Circle( 60.0, 60.0, 30.0, Color.BLUE );
        for ( Circle circle : circles ) {
            makeDraggable( circle );
        }

        Group root = new Group();
        root.getChildren().addAll( circles[0], circles[1], circles[2] );
        primaryStage.setResizable( false );
        primaryStage.setScene( new Scene( root, 400, 350 ) );
        primaryStage.setTitle( DragGroupSample.class.getSimpleName() );
        primaryStage.show();
    }

    private static final class DragContext {
        public double dx, dy;
    }
}

共有1个答案

敖毅
2023-03-14

只要移动所有你想移动的圆圈。相对于某个固定的东西(比如场景)来存储最后的鼠标位置可能更容易,而不是相对于圆来工作。

这里有一种方法,还有很多:

import java.util.ArrayList;
import java.util.List;

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class DragGroupSample extends Application {

    public static void main( String[] args ) {
        launch();
    }

    // list of nodes that are dragged. Can be modified at any time (on the FX Application Thread):
    private final List<Circle> nodesToDrag = new ArrayList<>();

    private final Circle[] circles = new Circle[3] ;

    private void makeDraggable( Circle circle ) {
        MouseLocation lastMouseLocation = new MouseLocation();

        // --- remember initial coordinates of mouse cursor and node
        circle.addEventFilter( MouseEvent.MOUSE_PRESSED, (
                final MouseEvent mouseEvent ) -> {
            lastMouseLocation.x = mouseEvent.getSceneX() ;
            lastMouseLocation.y = mouseEvent.getSceneY() ;

            // just some example logic to modify the list of dragged nodes:
            boolean found = false ;
            for (Circle c : circles) {
                if (c == circle) found = true ;
                if (found) nodesToDrag.add(c);
            }
        } );

        // --- Shift node calculated from mouse cursor movement
        circle.addEventFilter( MouseEvent.MOUSE_DRAGGED, (
                final MouseEvent mouseEvent ) -> {
                    double deltaX = mouseEvent.getSceneX() - lastMouseLocation.x ;
                    double deltaY = mouseEvent.getSceneY() - lastMouseLocation.y ;
                    for (Circle c : nodesToDrag) {
                        c.setCenterX( c.getCenterX() + deltaX  );
                        c.setCenterY( c.getCenterY() + deltaY );
                    }
                    lastMouseLocation.x = mouseEvent.getSceneX();
                    lastMouseLocation.y = mouseEvent.getSceneY();
        } );

        circle.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> nodesToDrag.clear());

    }

    @Override
    public void start( Stage primaryStage ) throws Exception {

        circles[0] = new Circle( 30.0, 30.0, 30.0, Color.RED );
        circles[1] = new Circle( 45.0, 45.0, 30.0, Color.GREEN );
        circles[2] = new Circle( 60.0, 60.0, 30.0, Color.BLUE );

        for ( Circle circle : circles ) {
            makeDraggable( circle );
        }

        Group root = new Group();
        root.getChildren().addAll( circles[0], circles[1], circles[2] );
        primaryStage.setResizable( false );
        primaryStage.setScene( new Scene( root, 400, 350 ) );
        primaryStage.setTitle( DragGroupSample.class.getSimpleName() );
        primaryStage.show();
    }

    private static final class MouseLocation {
        public double x, y;
    }
}
 类似资料:
  • 我是否正确地认为无法在网格窗格中拖动形状?下面是一些代码的链接,这些代码允许用户在屏幕上拖动形状:拖放形状 我希望我的形状具有与上述相同的行为,但我希望它们在GridPane中(最终我希望它们的移动被锁定到X或Y轴以移动到相邻的形状)。 我将以下代码添加到“start”方法中。它使用与示例代码相同的方法创建圆,而是将它们添加到网格中。令人惊讶的是,这消除了他们被拖来拖去的能力。 如果您想测试这一点

  • 我有app,我有很多不同风格的按钮组件(我特意把它分开,以提高可读性),例如:普通、概述、文本、链接和其他。我想创建一个特殊的组件,在其中我将传递prop,component将返回我需要的按钮组件。现在我制作了这个组件,但我必须传递我可能不需要的道具。我如何解决这个问题,或者你知道分组的不同实现方式? 分组组件:

  • 我有一个网格窗格的圆圈,我希望能够将一个圆圈拖到另一个圆圈之上,并将第一个圆圈的颜色应用于第二个圆圈。 我遇到的问题是,我无法让目标圆检测到dragEntered或dragOver。我已经能够使用标签成功地实现这一点,但由于某些原因,圆圈不会产生相同的效果。 我见过一些准解决方案,涉及设置circle.setMouseTransparent(true),以便被拖动节点下的节点可以看到拖动,但这里也

  • 有人知道一种方法(如果可能的话也可以使用lodash)通过对象键对对象数组进行分组,然后根据分组创建新的对象数组吗?例如,我有一个汽车对象数组: 我想制作一个由分组的新汽车对象数组:

  • 问题内容: 所以,我有一张表,上面有这样的行: 每次扫描警报时(即每次触发或清除警报时)都会添加“已扫描的警报”行。任何警报都会添加带有特定Ev_Custom1的行。第一列Ev_Message包含一个计算机ID,该ID使我可以将警报与其他计算机分开。(您不喜欢任意的列名吗?)超过900条独特的警报消息。 我希望查询返回的内容是这样的: 这将是两个日期之间过滤的查询。我可以更改进入表的数据,但是有9

  • 问题内容: 有谁知道(如果可能的话,也用破折号)通过对象键对对象数组进行分组然后根据分组创建新的对象数组的方法吗?例如,我有一系列汽车对象: 我想制作一组新的汽车对象,并按以下类别分组: 问题答案: 。简单,并允许在分组结构中的对象中进行一些重复。 但是,OP还要求删除重复的密钥。如果您想一路走下去: 产量: 如果您想使用Underscore.js进行此操作,请注意,其版本称为。