Почему в 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 появляется, что он есть (и когда это так, процедура перетаскивания останавливается). При выполнении замены вместо удаления исходного объекта при начале перетаскивания ссылка сохраняется, а затем исходный объект может быть уничтожен в обработчике завершения перетаскивания.