JavaFX Container Draggable
Методы setX и setY, которые вы вызываете, задают положение всплывающего окна в координатах экрана. Вызовы me.getX() и me.getY() дают вам координаты мыши относительно контейнера. Когда вы перемещаете всплывающее окно, контейнер также перемещается, поэтому положение мыши изменилось относительно контейнера. Таким образом, ваши вычисления не будут согласованы с одним событием перетаскивания на другое.
Исправление состоит в том, чтобы вычислять позиции относительно неподвижного. Поскольку вы перемещаете всплывающее окно, которое является окном, фиксированная система координат является системой координат экрана. MouseEvent имеет методы getScreenX и getScreenY, которые вы можете использовать, чтобы их легко получить.
Мне нравится выполнять перетаскивание, сохраняя последнее местоположение мыши, а затем вычисляя расстояние, перемещаемое при перетаскивании. Существуют и другие (возможно, менее подробные) способы сделать это, но для меня это яснее:
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class DraggingPopup extends Application {
@Override
public void start(Stage primaryStage) {
Button button = new Button("Show popup");
button.setOnAction(event -> showDraggablePopup(primaryStage));
StackPane root = new StackPane(button);
Scene scene = new Scene(root, 250, 75);
primaryStage.setScene(scene);
primaryStage.show();
}
private void showDraggablePopup(Stage owner) {
Popup popup = new Popup();
Button closeButton = new Button("Close");
closeButton.setOnAction(event -> popup.hide());
StackPane container = new StackPane(closeButton);
container.setStyle("-fx-background-color: steelblue;");
container.setMinWidth(300);
container.setMinHeight(125);
// Dragging implementation:
ObjectProperty<Point2D> mouseLocation = new SimpleObjectProperty<>();
container.setOnMousePressed(event ->
mouseLocation.set(new Point2D(event.getScreenX(), event.getScreenY())));
container.setOnMouseDragged(event -> {
if (mouseLocation.get() != null) {
double x = event.getScreenX();
double deltaX = x - mouseLocation.get().getX() ;
double y = event.getScreenY();
double deltaY = y - mouseLocation.get().getY() ;
//in case of 2 or more computer screens this help me to avoid get stuck on 1 screen
if(Math.abs(popup.getX()-x)>popup.getWidth()){
popup.setX(x);
popup.setY(y);
}else {
popup.setX(popup.getX() + deltaX);
popup.setY(popup.getY() + deltaY);
}
mouseLocation.set(new Point2D(x, y));
}
});
container.setOnMouseReleased(event -> mouseLocation.set(null));
popup.getScene().setRoot(container);
popup.show(owner);
}
public static void main(String[] args) {
launch(args);
}
}
Это работает очень хорошо, у меня есть еще один вопрос о всплывающем окне. На данный момент возможно, что PopUp может выйти из основной сцены ... Возможно ли связать PopUp на главной сцене. Нельзя оставлять окно основного этапа ... Есть ли решение для него, я много пробовал, но я не знаю, как я могу решить эту проблему. –
Просто проверьте положение основного этапа, его ширины и высоты, а также ширины и высоты всплывающего окна перед перемещением. –
Спасибо за ваш ответ, нет встроенной автоматической функции? Я должен решить проблему с математикой? –