JavaFx之场景交互(二十一)
有parent、son两个父子窗口,父窗口可以操作子窗口,父子可以相互调用对方的对象,下面我给出两种方案,我推荐使用第二种
一、构造传参
参数比较多的话代码不优雅、而且不太方便维护。
父
package top.oneit.jdownload.test;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
/**
* @author lingkang
*/
public class MyParent extends Application {
private MySonA sonA;
private Button button;
@Override
public void start(Stage primaryStage) throws Exception {
button = new Button("open子窗口A");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if (sonA==null){
sonA = new MySonA(primaryStage,button);
sonA.show();// 显示子窗口
}else{
sonA.show();
}
// 调用子接口对象
System.out.println(sonA.getButton().getText());
}
});
Button closeSon = new Button("关闭子窗口");
closeSon.setLayoutY(40);
closeSon.setOnAction(event -> {
sonA.close();
});
AnchorPane anchorPane = new AnchorPane(button, closeSon);
anchorPane.setPrefWidth(400);
anchorPane.setPrefHeight(300);
primaryStage.setScene(new Scene(anchorPane));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
子
package top.oneit.jdownload.test;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
/**
* @author lingkang
*/
public class MySonA extends Stage {
private Stage parent;
private Button button;
public MySonA(Stage parent,Button parentButton) {
this.parent = parent;
Label label = new Label("我是儿子A");
button = new Button("关闭父窗口");
button.setOnAction(event -> {
System.out.println(parent.getTitle());
parent.close();
});
button.setLayoutY(40);
Button open = new Button("打开父窗口");
open.setLayoutY(80);
open.setOnAction(event -> {
parentButton.setText("子调用父的对象");// 父子传参,构造方法
parent.show();
});
Button exit = new Button("exit");
exit.setLayoutY(120);
exit.setOnAction(event -> {
System.exit(0);
});
AnchorPane pane = new AnchorPane(label, button, open, exit);
pane.setPrefWidth(300);
pane.setPrefHeight(200);
setScene(new Scene(pane));
}
public Button getButton() {
return button;
}
public void setButton(Button button) {
this.button = button;
}
}
效果:
二、继承公共类
灵活,注意,创建多个同样的窗口带来的问题,还有获取对应stage为空的问题!提前判空
启动入口
import javafx.application.Application;
import javafx.stage.Stage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author lingkang
* @date 2021/11/18
*/
public class MyApp extends Application {
public static ConcurrentMap<String, Stage> stages = new ConcurrentHashMap<>();
@Override
public void start(Stage primaryStage) throws Exception {
new MyParent();//显示父窗口
}
public static void main(String[] args) {
launch(args);
}
}
公共类
import javafx.event.EventHandler;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
/**
* @author lingkang
* @date 2021/11/18
*/
public class MyStageCommon extends Stage {
private String thisClassName=getClass().getName();//将当前类名单独初始化
public MyStageCommon() {
super();
// 创建窗口时加入
MyApp.stages.put(thisClassName, this);
// x 掉窗口时将它移除
setOnCloseRequest(new EventHandler<WindowEvent>() {
@Override
public void handle(WindowEvent event) {
MyApp.stages.remove(thisClassName);
}
});
}
@Override
public void close() {
super.close();
MyApp.stages.remove(thisClassName);
}
/**
* 获取对象,,注意返回空值
*/
public <T> T getStage(Class<T> clazz) {
if (!MyApp.stages.containsKey(clazz.getName()))
return null;
return (T) MyApp.stages.get(clazz.getName());
}
}
父
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
/**
* @author lingkang
*/
public class MyParent extends MyStageCommon {
public Button button;
public MyParent() {
setTitle("父窗口!");
button = new Button("open子窗口A");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
if (getStage(MySonA.class) == null) {
new MySonA().show();// 显示子窗口
} else {
getStage(MySonA.class).show();
}
// 调用子接口对象
System.out.println(getStage(MySonA.class).button.getText());
}
});
Button closeSon = new Button("关闭子窗口");
closeSon.setLayoutY(40);
closeSon.setOnAction(event -> {
if (getStage(MySonA.class) != null)
getStage(MySonA.class).close();
});
AnchorPane anchorPane = new AnchorPane(button, closeSon);
anchorPane.setPrefWidth(400);
anchorPane.setPrefHeight(300);
setScene(new Scene(anchorPane));
show();
}
}
子
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import java.util.Date;
/**
* @author lingkang
*/
public class MySonA extends MyStageCommon {
public Button button;
public MySonA() {
setTitle("子窗口A");
MyParent parent = getStage(MyParent.class);
Label label = new Label("我是儿子A");
button = new Button("关闭父窗口");
button.setOnAction(event -> {
System.out.println(parent.getTitle());
parent.close();
});
button.setLayoutY(40);
Button open = new Button("打开父窗口");
open.setLayoutY(80);
open.setOnAction(event -> {
if (parent.button != null)
parent.button.setText("子调用父的对象" + new Date());// 父子传参
parent.show();
});
Button exit = new Button("exit");
exit.setLayoutY(120);
exit.setOnAction(event -> {
System.exit(0);
});
AnchorPane pane = new AnchorPane(label, button, open, exit);
pane.setPrefWidth(300);
pane.setPrefHeight(200);
setScene(new Scene(pane));
}
}
效果: