Почему в JavaFX 8 ломаются процедуры перетаскивания моего приложения JavaFX?

У меня есть код, который позволит мне перетащить экземпляр StackPane. Код прекрасно работает в JavaFX v2.2, но StackPane остается в положении по умолчанию и не перемещается в JavaFX v8.

Вот код:

private void initDragRoutine(final Node source,
                             final boolean replaceSource,
                             final Node replaceWith,
                             final Pane replaceFrom)
{
    /*
     * add the draggable pane and create its text
     */
    source.setOnDragDetected(new EventHandler<MouseEvent>()
    {
        @Override
        public void handle(MouseEvent mouseEvent)
        {
            System.out.println("drag initialized");

            //update the content of the draggable instance with that of the fixed position source
            if (mouseEvent.getSource() instanceof StringPane)
                draggablePane.setOverlay(((StringPane) mouseEvent.getSource()).getOverlay());

            //update position
            Point2D localPoint = questionInfoNode.sceneToLocal(
                    new Point2D(mouseEvent.getSceneX(), mouseEvent.getSceneY()));
            draggablePane.relocate(
                    (int) (localPoint.getX() - draggablePane.getBoundsInLocal().getWidth() / 2),
                    (int) (localPoint.getY() - draggablePane.getBoundsInLocal().getHeight() / 2)
            );
            //add to scene
            styledRootNode.getChildren().add(draggablePane);

            draggablePane.startFullDrag();

            //replace source
            if (replaceSource && replaceFrom != null)
                for (int index = 0; index < replaceFrom.getChildren().size(); index++)
                    if (replaceFrom.getChildren().get(index) == source)
                        replaceFrom.getChildren().set(index, replaceWith);

            mouseEvent.consume();
        }
    });

    /*
     * update the position
     */
    source.setOnMouseDragged(new EventHandler<MouseEvent>()
    {
        @Override
        public void handle(MouseEvent mouseEvent)
        {
            System.out.println("dragged");

            //update position
            Point2D localPoint = questionInfoNode.sceneToLocal(
                    new Point2D(mouseEvent.getSceneX(), mouseEvent.getSceneY()));
            System.out.println("x" + mouseEvent.getSceneX() + "y" + mouseEvent.getSceneY());
            draggablePane.relocate(
                    (int) (localPoint.getX() - draggablePane.getBoundsInLocal().getWidth() / 2),
                    (int) (localPoint.getY() - draggablePane.getBoundsInLocal().getHeight() / 2)
            );
            //draggablePane.relocate(450, 1000);

            //source.setCursor(Cursor.NONE);
            mouseEvent.consume();
        }
    });

    /*
     * adjust cursor on entry
     */
    source.setOnMouseEntered(new EventHandler<MouseEvent>()
    {
        public void handle(MouseEvent e)
        {
            source.setCursor(Cursor.HAND);
            e.consume();
        }
    });

    /*
     * adjust cursor on pressed
     */
    source.setOnMousePressed(new EventHandler<MouseEvent>()
    {
        public void handle(MouseEvent e)
        {
            System.out.println("mouse pressed");

            source.setMouseTransparent(true);
            draggablePane.setMouseTransparent(true);
            source.setCursor(Cursor.CLOSED_HAND);

            e.consume();

            System.out.println("mouse pressed done");
        }
    });

    /*
     * adjust cursor on released
     */
    source.setOnMouseReleased(new EventHandler<MouseEvent>()
    {
        public void handle(MouseEvent e)
        {
            System.out.println("mouse released");

            source.setMouseTransparent(false);
            draggablePane.setMouseTransparent(false);
            source.setCursor(Cursor.DEFAULT);
            styledRootNode.getChildren().remove(draggablePane);

            e.consume();

            System.out.println("mouse released done");
        }
    });
}

Я попытался просто жестко запрограммировать обновление позиции в качестве теста, который также не может переместить панель. Если у кого-то есть какие-либо идеи, даже малейшие, я бы с удовольствием попробовал. Я застрял на этом в течение нескольких дней. Благодарю.

2 ответа

Решение

У меня нет времени, чтобы создать полный пример с ошибкой вашего кода. Итак, вот один из моих собственных примеров, дополненных StackPane, чтобы показать вам, как это работает:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Ellipse;
import javafx.stage.Stage;

public class DragExample extends Application {

    Circle circle_R, circle_G, circle_B;
    WrappedInStackPane wrapped;
    double orgSceneX, orgSceneY;
    double orgTranslateX, orgTranslateY;

    @Override
    public void start(Stage primaryStage) {

        // Create Circles
        circle_R = createCircle( 50, Color.RED, 100, 100);
        circle_G = createCircle( 50, Color.GREEN, 400, 100);
        circle_B = createCircle( 50, Color.BLUE, 700, 100);

        wrapped = new WrappedInStackPane();

        Group root = new Group();
        root.getChildren().addAll(circle_R, circle_G, circle_B, wrapped);

        primaryStage.setResizable(true);
        primaryStage.setScene(new Scene(root, 1600, 900));
        primaryStage.show();
    }

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

    public Circle createCircle( double radius, Color color, double x, double y) {

        Circle circle;

        circle = new Circle(50.0f, color);
        circle.setCursor(Cursor.MOVE);
        circle.setTranslateX(x);
        circle.setTranslateY(y);
        circle.setOnMousePressed(onMousePressedEventHandler);
        circle.setOnMouseDragged(onMouseDraggedEventHandler);

        return circle;
    }
    EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent t) {
            orgSceneX = t.getSceneX();
            orgSceneY = t.getSceneY();
            orgTranslateX = ((Node) (t.getSource())).getTranslateX();
            orgTranslateY = ((Node) (t.getSource())).getTranslateY();
        }
    };

    EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {

        @Override
        public void handle(MouseEvent t) {
            double offsetX = t.getSceneX() - orgSceneX;
            double offsetY = t.getSceneY() - orgSceneY;
            double newTranslateX = orgTranslateX + offsetX;
            double newTranslateY = orgTranslateY + offsetY;

            ((Node) (t.getSource())).setTranslateX(newTranslateX);
            ((Node) (t.getSource())).setTranslateY(newTranslateY);
        }
    };

    public class WrappedInStackPane extends StackPane {

        public WrappedInStackPane() {

            setStyle("-fx-background-color: orange;");

            Ellipse ellipse = new Ellipse(100, 50);
            ellipse.setFill(Color.YELLOW);

            Label label = new Label( "Inside StackPane");

            getChildren().addAll(ellipse, label);

            setOnMousePressed(onMousePressedEventHandler);
            setOnMouseDragged(onMouseDraggedEventHandler);

            relocate(200, 200);

        }
    }
}

Я предлагаю вам установить стиль фона на вашей StackPane, чтобы увидеть, что-то не так.

Короче говоря, обработка слушателей меняется между FX2.2 и FX8.0. Раньше я удалял и объект со сцены и добавлял другой. В FX2.2 объект не будет собирать мусор, но в FX8.0 появляется, что он есть (и когда это так, процедура перетаскивания останавливается). При выполнении замены вместо удаления исходного объекта при начале перетаскивания ссылка сохраняется, а затем исходный объект может быть уничтожен в обработчике завершения перетаскивания.

Другие вопросы по тегам