在JavaFX中拖动未修饰的舞台

时间:2013-09-13 18:23:51

标签: java javafx

我希望将舞台设置为“UNDECORATED”,使其可拖动且可最小化。问题是我无法找到这样做的方法,因为我通过插入main方法中的方法来实现这一点。

我希望通过控制器类中声明的方法完成此操作,就像我设法使用下面的“WindowClose()”方法一样。

这是我第二天使用JavaFX,如果这似乎是一个常见的知识问题。提前谢谢大家。

// 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();
    }
}

3 个答案:

答案 0 :(得分:4)

策略

您已经在start方法中引用了舞台。

您需要的是能够将舞台传递给您的控制器,以便控制器可以使舞台可以由给定节点拖动。

  1. “直接从调用者传递参数到控制器”方法可用于将阶段引用传递给控制器​​:Passing Parameters JavaFX FXML

  2. 使用makeDraggable method from this sample code允许由给定节点拖动舞台。

  3. 示例实施

    Application start方法的一些伪代码如下:

    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();
    

    对于Controller的新registerStage方法:

    @FXML private Rectangle dragNode;
    
    public void registerStage(Stage stage) {
      EffectUtilities.makeDraggable(stage, dragNode)
    }
    

    EffectUtilities.makeDraggable()来自我之前链接的示例代码。

    更新您的fxml_tableview.fxml文件,以包含控制器中引用的所需新dragNode

    替代实施

    在控制器的initialize方法中,在dragNode的sceneProperty和更改的场景的window属性上添加一个更改侦听器,以获得阶段更改的通知,以便您可以调用makeDraggable。

    示例代码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;
      }
    }
    

答案 1 :(得分:0)

从FXML设置要用于拖动应用程序的控制器或组件的ID

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

来自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());
    }

您必须具有delta类,该类将存储delta x和y的值

    public class Delta{
        public double x,y;
    }

要进入阶段,只需创建mutator和accessor,有关转换的更多信息,请转到here

答案 2 :(得分:0)

创建这个 Delta 类。

public class Delta {
    double x,y;
}
 

在控制器类中,创建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());


    }

接下来在您的 fxml 文件或场景构建器中分别为 mousepressed 和 mousedragging 添加这两个方法。

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