javafx显示多个窗口以及javafx多窗口之间数据交互传输

在进入主题先推荐一个javafx群:518914410,我也在这个群里面欢迎进来跟大家交流;

正式进入主题:

友情提示:中心想法将需要操作的舞台与控制器的引用保存到map中,使用完毕后将这个map里面的引用删除,不排除java不释放内存导致泄漏;

首先先给项目清单项目的基本结构:

control里面分别是3个窗口的控制器,util里面是窗口(stage)的管理类,resoureces资源文件夹里面是3个窗口的界面fxml文件;

项目源文件下载地址:点击打开链接

程序入口清单:

 

package application;

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

public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			Parent root = FXMLLoader.load(Thread.currentThread().getContextClassLoader().getResource("Index.fxml"));
			primaryStage.setTitle("第一个窗口");
			primaryStage.setScene(new Scene(root));
			primaryStage.show();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

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

 

 

 

首先需要有stage管理类就叫他StageManager一目了然,里面只有两个静态属性,一个是stage的map,一个是控制器的map,

StageManager清单:

 

package util;

import java.util.HashMap;
import java.util.Map;

import javafx.stage.Stage;

public class StageManager {
	public static Map<String, Stage> STAGE=new HashMap<String, Stage>();
	public static Map<String, Object> CONTROLLER=new HashMap<String, Object>();
}

有了舞台管理器后我们就可以开始编写我们的控制器

 

首先先看控制器index的清单:

 

package control;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import util.StageManager;

public class IndexControl implements Initializable{
    @FXML
    private Button btnOpenTwoWin;
    @FXML
    public TextField txtData;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // TODO Auto-generated method stub
    }
    
    /**
     * 打开第二个窗口
     * @param event
     * @throws Exception 
     */
    public void open(ActionEvent event) throws Exception {
        Stage stage=new Stage();  
        Parent root = FXMLLoader.load(Thread.currentThread().getContextClassLoader().getResource("Second.fxml"));
        stage.setTitle("第二个窗口");
        stage.setScene(new Scene(root));
        stage.show();
        //将第二个窗口保存到map中
        StageManager.STAGE.put("second", stage);
        //将本窗口保存到map中
        StageManager.CONTROLLER.put("indexControl", this);
    }

}



这个清单里面有两个注意点,第一个是TextField因为在第一个窗口要操作这个控件所以这个控件需要设置为共有的,重点就在在打开第二个窗口的Open方法中(这个方法btnOpenTwoWin的点击事件)

 

首先需要new 一个Stage然后加载fxml文件做一些相关的设置后显示,重点在两个备注中我们将刚刚new出来的stage保存到舞台管理类里面(如果别的窗口不需要对打开的窗口进行操作可以不需要这一步,因为我需要通过按钮关闭窗口,所以需要这一步),

再将第一个窗口的控制器保存到舞台管理类中(这一步是数据交互的时候使用,不需要可以可以不用这一步),这样我们打开第二个窗口就完事,正常显示我们第二个窗口了;

接下来我们来看第二个窗口的控制器清单:

 

package control;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import util.StageManager;

public class SecondControl implements Initializable {
    @FXML
    private Button btnOpenThrid;
    @FXML
    private Button btnCloseThis;
    //普通的字符串,不过这里用于将该数据发送到第一个窗口
    private String tranDataToIndex;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        // TODO Auto-generated method stub

    }
    
    /**
     * 打开第三个窗口
     * @param event
     * @throws Exception 
     */
    public void openThrid(ActionEvent event) throws Exception {
        Stage stage=new Stage();  
        Parent root;
            root = FXMLLoader.load(Thread.currentThread().getContextClassLoader().getResource("Thrid.fxml"));
            stage.setTitle("第三个窗口");
            stage.setScene(new Scene(root));
            stage.show();
            //将第二个窗口保存到map中
            StageManager.STAGE.put("thrid", stage);
            //将本窗口保存到map中
            StageManager.CONTROLLER.put("secondControl", this);
    }
    
    /**
     * 关闭当前窗口
     * @param event
     */
    public void closeThis(ActionEvent event) {
        if (this.tranDataToIndex!=null) {
            IndexControl index=(IndexControl) StageManager.CONTROLLER.get("indexControl");
            this.tranDataToIndex="第三个窗口";
            index.txtData.setText("来自second:"+this.tranDataToIndex);
        }
        StageManager.STAGE.get("second").close();
        //删除map中的引用
        StageManager.STAGE.remove("second");
        StageManager.CONTROLLER.remove("indexControl");
    }

    
    //--------------get/set---------------
    public String getTranDataToIndex() {
        return tranDataToIndex;
    }

    public void setTranDataToIndex(String tranDataToIndex) {
        this.tranDataToIndex = tranDataToIndex;
    }

    
}


在这个控制器中有两个重点的地方,第一个就是第一个窗口的控制器private IndexControl index;第二个是closeThis的点击事件方法;

 

首先如果我们需要数据交互,那么我们就需要将第一个窗口作为第二个窗口的一个属性,因为这个你才能操作第一个窗口;我们可以看到closeThis的点击事件中,如果要传输的数据不为空,那么我们就将舞台控制器里面的第一个窗口的控制器取出来,赋值给当前窗口的index属性,这样我们就可以操作第一个窗口的数据了,在判断里面我们就将第二个窗口的数据设置到第一个窗口的TextField中;

然后我们要通过按钮关闭当前也就是第二个窗口我们就需要将舞台管理器map里面的第二个窗口的舞台取出来,将这个舞台关闭;

到这里多个窗口数据交互与管理就已经结束了;

总结:

第一点也是最重要也是最简单的就是一个舞台管理类,里面两个静态属性一个舞台管理的map,一个是控制器的map;

第二点:将控制器作为另外一个控制器的属性;

第三点:将要被操作的控件改为public共有修饰;

第四点:取出控制器赋值给控制器属性;

第五点:关闭窗口通过取出舞台关闭(不需控件操作直接用X关闭的不需要这点);

完事就这么简单;

最后再给第三个窗口的清单因为第二个窗口的数据来自第三个窗口:

 

 
package control;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import util.StageManager;

public class ThridControl implements Initializable {
    @FXML
    private Button btnCloseThis;
    @FXML
    private Button btnVoidData;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
    }
    
    
    /**
     * 关闭当前窗口
     * @param event
     */
    public void closeThis(ActionEvent event) {
        StageManager.STAGE.get("thrid").close();
        StageManager.STAGE.remove("thrid");
    }
    
    /**
     * 给第二个窗口数据
     */
    public void voidData() {
        SecondControl secondControl=(SecondControl) StageManager.CONTROLLER.get("secondControl");
        secondControl.setTranDataToIndex("第三个窗口的数据");
        //如果本窗口还使用该控制器先不remove这个控制器;
        StageManager.CONTROLLER.remove("secondControl");
        
    }

    
}

 

 

运行效果图:

 

 

 

 

 

 

  • 17
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
Javafx两个窗口之间数据传输可以通过以下几种方式实现: 1. 在第一个窗口中定义一个静态变量,存储需要传输数据。在第二个窗口中,通过类名.变量名的方式获取数据。但是这种方式不够灵活,无法处理多个实例的情况。 2. 在第一个窗口中定义一个公共方法,用于获取需要传输数据。在第二个窗口中,通过第一个窗口的引用调用该方法获取数据。但是这种方式不够优雅,需要手动传递窗口引用。 3. 在第一个窗口中定义一个事件,用于触发数据传输。在第二个窗口中,监听该事件并获取数据。这种方式比较灵活,可以处理多个实例的情况,但需要手动触发事件。 4. 在第一个窗口中定义一个全局的数据存储对象,可以使用JavaFX的Application类或者Spring框架的ApplicationContext来实现。在第二个窗口中,通过该对象获取需要传输数据。这种方式比较优雅,可以处理多个实例的情况,但需要引入额外的框架。 下面是一种实现方式,通过Application类实现全局数据存储: ```java public class MyApp extends Application { private String data; public String getData() { return data; } public void setData(String data) { this.data = data; } @Override public void start(Stage primaryStage) throws Exception { // ... } } ``` 第一个窗口: ```java public class FirstController { public void sendData() { MyApp app = (MyApp) Application.getInstance(); app.setData("Hello World"); } } ``` 第二个窗口: ```java public class SecondController { @FXML private Label label; public void initialize() { MyApp app = (MyApp) Application.getInstance(); String data = app.getData(); label.setText(data); } } ``` 其中,Application.getInstance()可以获取Application类的实例,因为Application类是单例的。这样,当第一个窗口中的sendData方法被调用时,会将数据存储到全局的MyApp对象中。当第二个窗口初始化时,会从MyApp对象中获取数据显示在界面上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值