简体   繁体   English

在 JavaFX 中拖动未修饰的舞台

[英]Dragging an undecorated Stage in JavaFX

I would like to have a Stage set to "UNDECORATED" made draggable and minimizable.我希望将舞台设置为“UNDECORATED”,使其可拖动和最小化。 The problem is that I can't find a way to do so since the examples I come accross that do this do so via methods inserted inside the main method.问题是我找不到这样做的方法,因为我遇到的例子是通过插入到 main 方法中的方法来做到这一点的。

I would like to have this done via a method declared in the controller class, like how I managed to do with the "WindowClose()" method below.我希望通过在控制器类中声明的方法来完成此操作,就像我如何设法使用下面的“WindowClose()”方法一样。

This is my second day working with JavaFX, if this seems too much of a common knowledge question.这是我使用 JavaFX 的第二天,如果这似乎是一个太多的常识问题。 Thank you all in advance.谢谢大家。

// Main Class/ Method

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Fxmltableview extends Application {

    public static String pageSource = "fxml_tableview.fxml";
    public static Scene scene;

    @Override
    public void start(Stage stage) throws Exception {
        stage.initStyle(StageStyle.UNDECORATED);
        stage.initStyle(StageStyle.TRANSPARENT);

        Parent root = FXMLLoader.load(getClass().getResource(pageSource));

        scene = new Scene(root, Color.TRANSPARENT);

        stage.setScene(scene);
        stage.show();
    }

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

.. ..

// The Controller

import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

public class FXMLTableViewController {
    @FXML private TableView<Person> tableView;
    @FXML private TextField firstNameField;
    @FXML private TextField lastNameField;
    @FXML private TextField emailField;

    @FXML
    protected void addPerson (ActionEvent event) {
        ObservableList<Person> data = tableView.getItems();
        data.add(new Person(
                firstNameField.getText(),
                lastNameField.getText(),
                emailField.getText()
                ));

        firstNameField.setText("");
        lastNameField.setText("");
        emailField.setText("");   
    }

    public void WindowClose (ActionEvent event) {
            Platform.exit();
    }
}

Strategy战略

You already have a reference to the stage in your start method.您已经在 start 方法中引用了舞台。

What you need is to be able to pass the stage to your controller, so that the controller can make the stage draggable by a given node.您需要的是能够将舞台传递给您的控制器,以便控制器可以使舞台可被给定节点拖动。

  1. The "Passing Parameters Directly From the Caller to the Controller" method may be used to pass a stage reference to your controller: Passing Parameters JavaFX FXML . “直接从调用者向控制器传递参数”方法可用于将阶段引用传递给您的控制器: 传递参数 JavaFX FXML

  2. Use the makeDraggable method from this sample code to allow the stage to be dragged by a given node.使用此示例代码中makeDraggable 方法允许舞台由给定节点拖动。

Sample Implementation示例实现

Some psuedo-code for the Application start method follows:应用程序启动方法的一些伪代码如下:

stage.initStyle(StageStyle.UNDECORATED);
stage.initStyle(StageStyle.TRANSPARENT);

FXMLLoader loader = new FXMLLoader(
  getClass().getResource(
    "fxml_tableview.fxml"
  )
);

stage.setScene(
  new Scene(
    (Parent) loader.load()
  )
);

FXMLTableViewController controller = 
  loader.<FXMLTableViewController>getController();
controller.registerStage(stage);

stage.show();

And for the Controller's new registerStage method:对于 Controller 的新 registerStage 方法:

@FXML private Rectangle dragNode;

public void registerStage(Stage stage) {
  EffectUtilities.makeDraggable(stage, dragNode)
}

EffectUtilities.makeDraggable() comes from the sample code I linked earlier. EffectUtilities.makeDraggable()来自我之前链接的示例代码。

Update your fxml_tableview.fxml file to include the required new dragNode referenced in the controller.更新您的fxml_tableview.fxml文件以包含控制器中引用的所需的新dragNode

Alternate implementation替代实现

In the initialize method of the controller, add a change listener on the dragNode's sceneProperty and the changed scene's window property to get notified of the stage change so that you can invoke makeDraggable.在控制器的 initialize 方法中,在 dragNode 的 sceneProperty 和改变的场景的 window 属性上添加一个更改监听器,以获取舞台更改的通知,以便您可以调用 makeDraggable。

Sample Code EffectUtilities.makeDraggable(stage, byNode)示例代码EffectUtilities.makeDraggable(stage, byNode)

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import javafx.util.Duration;

/** Various utilities for applying different effects to nodes. */
public class EffectUtilities {
  /** makes a stage draggable using a given node */
  public static void makeDraggable(final Stage stage, final Node byNode) {
    final Delta dragDelta = new Delta();
    byNode.setOnMousePressed(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent mouseEvent) {
        // record a delta distance for the drag and drop operation.
        dragDelta.x = stage.getX() - mouseEvent.getScreenX();
        dragDelta.y = stage.getY() - mouseEvent.getScreenY();
        byNode.setCursor(Cursor.MOVE);
      }
    });
    byNode.setOnMouseReleased(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent mouseEvent) {
        byNode.setCursor(Cursor.HAND);
      }
    });
    byNode.setOnMouseDragged(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent mouseEvent) {
        stage.setX(mouseEvent.getScreenX() + dragDelta.x);
        stage.setY(mouseEvent.getScreenY() + dragDelta.y);
      }
    });
    byNode.setOnMouseEntered(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent mouseEvent) {
        if (!mouseEvent.isPrimaryButtonDown()) {
          byNode.setCursor(Cursor.HAND);
        }
      }
    });
    byNode.setOnMouseExited(new EventHandler<MouseEvent>() {
      @Override public void handle(MouseEvent mouseEvent) {
        if (!mouseEvent.isPrimaryButtonDown()) {
          byNode.setCursor(Cursor.DEFAULT);
        }
      }
    });
  }

  /** records relative x and y co-ordinates. */
  private static class Delta {
    double x, y;
  }
}

From FXML set the id of your controller or component you want to use to drag your Application从 FXML 设置要用于拖动应用程序的控制器或组件的 id

    <Pane onMousePressed="#panePressed" onMouseDragged="#paneDragged"/>

From class Controller.java来自类Controller.java

    @FXML public void panePressed(MouseEvent me){
        delta.x = getStage().getX() - me.getScreenX();
        delta.y = getStage().getY() - me.getScreenY();
    }

    @FXML public void paneDragged(MouseEvent me){
        getStage().setX(delta.x + me.getScreenX());
        getStage().setY(delta.y + me.getScreenY());
    }

You must have delta class which will stored the value of delta x and y您必须有 delta 类,它将存储 delta x 和 y 的值

    public class Delta{
        public double x,y;
    }

To get the stage just create mutator and accessor, for more information about casting just go here要获得舞台,只需创建 mutator 和 accessor,有关转换的更多信息,请转到此处

Create this Delta class.创建这个 Delta 类。

public class Delta {
    double x,y;
}
 

In controller class , make instance of Delta class and add these two methods.在控制器类中,创建 Delta 类的实例并添加这两个方法。

public void panepressed(MouseEvent me)
    {
     stage = (Stage)((Node)me.getSource()).getScene().getWindow();
     delta.x= stage.getX()- me.getScreenX();
     delta.y= stage.getY()- me.getScreenY();


    }
    public void panedraged(MouseEvent me)
    {
     stage = (Stage)((Node)me.getSource()).getScene().getWindow();
     stage.setX(delta.x+me.getScreenX());
     stage.setY(delta.y+me.getScreenY());


    }

Next add these two methods in your fxml file or scene builder respectively for mousepressed and mousedragged.接下来在你的 fxml 文件或场景构建器中分别为 mousepressed 和 mousedragging 添加这两个方法。

<AnchorPane  onMouseDragged="#panedraged" onMousePressed="#panepressed" prefHeight="274.0" prefWidth="250.0" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM