【问题标题】:Dragging an undecorated Stage in JavaFX在 JavaFX 中拖动未装饰的舞台
【发布时间】:2013-09-18 12:36:40
【问题描述】:

我希望将舞台设置为“UNDECORATED”,使其可拖动和最小化。问题是我找不到这样做的方法,因为我遇到的示例是通过插入主方法中的方法来实现的。

我想通过在控制器类中声明的方法来完成这项工作,就像我如何使用下面的“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();
    }
}

【问题讨论】:

标签: java javafx


【解决方案1】:

创建这个 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 和 mousedragged。

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

【讨论】:

    【解决方案2】:

    从 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

    【讨论】:

      【解决方案3】:

      策略

      您已经在 start 方法中引用了阶段。

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

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

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

      示例实现

      应用程序启动方法的一些伪代码如下:

      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;
        }
      }
      

      【讨论】:

      • 我不知道从哪里得到这些EffectUtilities?!
      • 附上一份EffectUtilities示例代码(也是linked in the answer)。
      猜你喜欢
      • 1970-01-01
      • 2013-08-12
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 2014-12-29
      • 2015-03-21
      • 2013-05-14
      相关资源
      最近更新 更多