JAVA-GUI工具的编写-----简易框架篇

news2024/11/27 20:22:52

好久没写东西了,毕竟一个屁民没那么多东西写的,来来回回就老三样,扯犊子的也不想写,今天给大家来个都感兴趣的-------如何编写自己的GUI工具?

在这里插入图片描述
当然了,IDEA怎么去破解,这里就不多比比,为什么用JAVA写,而不是用pyqt5写,那是因为pyqt5笔者也不是很会,而且相对于pyqt5,笔者这一次给大家看的要简单得多

有朋友可能要问,那我不会java或者是就只有一丢丢的java基础,我能写吗?

我的回答是,必须能

java特性是什么?

封装-继承-多态!

即使你不会java,只要会copy别人写好的核心就可以了,直接调用就行!

maven项目的创建

maven这个东西,大家暂时不用管他是啥,使用idea默认的就行,我们不创建javafx项目,直接用maven就行,这样的话我们缺少插件的话,直接用pom里添加会方便很多
在这里插入图片描述
不用git哈,大家不需要理会
在GuiDemo/src/main/java目录下新建javaclass项目
在这里插入图片描述

GUI框架初现​-属性​

import javafx.application.Application;
import javafx.stage.Stage;

public class GuiDemo extends Application {      //创建一个GuiDemo类,GuiDemo继承Application类
    public void start(Stage GuiDemo) {          //创建一个无返回的start方法,Stage GuiDemo是JAVAFX里面的一个属性

    }

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

从代码里我们可以看到,分别是GuiDemo类,start无返回的方法和main主方法;void就是不需要返回值,若是需要返回值需要给他一个返回值的类型,也就是String、Int等类型,并且需要一个return,这里不做过多介绍,后续会讲

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class GuiDemo extends Application {      //创建一个GuiDemo类,GuiDemo继承Application类
    public void start(Stage GuiDemo) {          //创建一个无返回的start方法,Stage GuiDemo是JAVAFX里面的一个属性
        //设置title
        GuiDemo.setTitle("GUI小DEMO  by:vlan911 ");  //设置小工具的标题
        GuiDemo.setMaxWidth(700);   //设置小工具的最大宽度
        GuiDemo.setMaxHeight(500);  //设置小工具的最大高度

        //添加一个pane,用来装填按钮等插件
        AnchorPane anchorPane = new AnchorPane();   //添加一个pane,用来装后面的小插件
        anchorPane.getChildren().addAll();  //调用getChildren方法的addAll方法,写死就行
        Scene scene = new Scene(anchorPane, 600, 700);  //社子和Pane的默认宽度、高度,不能超过设置的窗口临界值
        GuiDemo.setScene(scene);    //把窗口的属性填进去
        GuiDemo.show();    //显示窗口,否则运行的话是没有东西的
    }

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

大家直接看注释就行,设置界面的临界值的好处就是,不管你用多大的显示器,我最大页面就这么点,不会出现小插件偏移、页面太难看的作用
我们Ctrl + Shift + F10 快捷键运行项目
在这里插入图片描述
现在是个白页,那是因为我们没有添加任何的文本框和按钮

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class GuiDemo extends Application {      //创建一个GuiDemo类,GuiDemo继承Application类
    public void start(Stage GuiDemo) {          //创建一个无返回的start方法,Stage GuiDemo是JAVAFX里面的一个属性
        //设置title
        GuiDemo.setTitle("GUI小DEMO  by:vlan911 ");  //设置小工具的标题
        GuiDemo.setMaxWidth(700);   //设置小工具的最大宽度
        GuiDemo.setMaxHeight(500);  //设置小工具的最大高度

        //设置icon
        GuiDemo.getIcons().add(new Image("22.jpg"));    //设置GUI的小图标,图标需要放在classes目录下或是网上的在线图片

        //添加URL文字提示
        Label l = new Label("请输入URL");      //设置一个lable,用来显示提示文字
        l.setLayoutX(5);        //设置lable的横坐标
        l.setLayoutY(10);       //设置lable的纵坐标
        l.setPrefWidth(70);     //设置lable的宽度
        l.setPrefHeight(20);    //设置lable的高度
        
        //添加URL文本框
        TextArea textArea = new TextArea();     //添加一哥文本框,用来接收URL
        textArea.setLayoutX(75);        //设置文本框的横坐标
        textArea.setLayoutY(5);         //设置文本框的纵坐标
        textArea.setPrefWidth(220);     //设置文本框的宽度
        textArea.setPrefHeight(20);     //设置文本框的高度

        //添加下拉按钮
        String strings[] = {"Kyan RCE", "Sapido RCE", "Vigor 2960 RCE"};    //添加一个字符串数组
        ChoiceBox choiceBox = new ChoiceBox(FXCollections.observableArrayList(strings));    //添加一个下拉列表,内容就是上面的字符串数组
        choiceBox.setLayoutX(315);  //设置下拉列表的横坐标
        choiceBox.setLayoutY(10);   //设置下拉列表的纵坐标
        choiceBox.setPrefHeight(20);    //设置下拉列表的高度
        choiceBox.setPrefWidth(70);     //设置下拉列表的宽度

        //添加确定按钮
        Button button = new Button("确定");   //添加一个按钮
        button.setLayoutX(405);     //设置按钮的横坐标
        button.setLayoutY(10);      //设置按钮的纵坐标
        button.setPrefHeight(20);   //设置按钮的高度
        button.setPrefWidth(50);    //设置按钮的宽度

        //添加一个pane,用来装填按钮等插件
        AnchorPane anchorPane = new AnchorPane();   //添加一个pane,用来装后面的小插件
        anchorPane.getChildren().addAll(textArea,choiceBox,button,l);  //调用getChildren方法的addAll方法,写死就行,括号里的就是我们添加的插件名字
        Scene scene = new Scene(anchorPane, 600, 700);  //社子和Pane的默认宽度、高度,不能超过设置的窗口临界值
        GuiDemo.setScene(scene);    //把窗口的属性填进去
        GuiDemo.show();    //显示窗口,否则运行的话是没有东西的
    }

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

我们在这里添加了一个lable,用来显示提示文字,一个用于接收URL地址的文本框,一个可供选择的下拉列表,以及一个确定按钮
在这里插入图片描述
光有接收,没有显示怎么能行?

我们再添加一个用于接收返回内容的文本框吧

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class GuiDemo extends Application {      //创建一个GuiDemo类,GuiDemo继承Application类
    public void start(Stage GuiDemo) {          //创建一个无返回的start方法,Stage GuiDemo是JAVAFX里面的一个属性
        //设置title
        GuiDemo.setTitle("GUI小DEMO  by:vlan911 ");  //设置小工具的标题
        GuiDemo.setMaxWidth(700);   //设置小工具的最大宽度
        GuiDemo.setMaxHeight(500);  //设置小工具的最大高度

        //设置icon
        GuiDemo.getIcons().add(new Image("22.jpg"));    //设置GUI的小图标,图标需要放在classes目录下或是网上的在线图片

        //添加URL文字提示
        Label l = new Label("请输入URL");      //设置一个lable,用来显示提示文字
        l.setLayoutX(5);        //设置lable的横坐标
        l.setLayoutY(10);       //设置lable的纵坐标
        l.setPrefWidth(70);     //设置lable的宽度
        l.setPrefHeight(20);    //设置lable的高度

        //添加URL文本框
        TextArea textArea = new TextArea();     //添加一哥文本框,用来接收URL
        textArea.setLayoutX(75);        //设置文本框的横坐标
        textArea.setLayoutY(5);         //设置文本框的纵坐标
        textArea.setPrefWidth(220);     //设置文本框的宽度
        textArea.setPrefHeight(20);     //设置文本框的高度

        //添加下拉按钮
        String strings[] = {"Kyan RCE", "Sapido RCE", "Vigor 2960 RCE"};    //添加一个字符串数组
        ChoiceBox choiceBox = new ChoiceBox(FXCollections.observableArrayList(strings));    //添加一个下拉列表,内容就是上面的字符串数组
        choiceBox.setLayoutX(315);  //设置下拉列表的横坐标
        choiceBox.setLayoutY(10);   //设置下拉列表的纵坐标
        choiceBox.setPrefHeight(20);    //设置下拉列表的高度
        choiceBox.setPrefWidth(70);     //设置下拉列表的宽度

        //添加确定按钮
        Button button = new Button("确定");   //添加一个按钮
        button.setLayoutX(405);     //设置按钮的横坐标
        button.setLayoutY(10);      //设置按钮的纵坐标
        button.setPrefHeight(20);   //设置按钮的高度
        button.setPrefWidth(50);    //设置按钮的宽度

        //添加回显文本框
        TextArea textArea1 = new TextArea();        //添加一个回显文本框
        textArea1.setLayoutX(5);        //设置文本框的横坐标
        textArea1.setLayoutY(100);      //设置文本框的纵坐标
        textArea1.setPrefHeight(300);   //设置文本框的高度
        textArea1.setPrefWidth(500);    //设置文本框的宽度

        textArea1.setWrapText(true);    //设置文本框里的文字自动换行
        textArea1.setText("Kyan信息泄露漏洞\n" +
                "Kyan命令注入漏洞\n" +
                "Sapido命令执行漏洞\n" +
                "Vigor 2960命令执行\n" +
                "博华网龙RCE\n" +
                "西迪特WirelessRCE");


        //添加一个pane,用来装填按钮等插件
        AnchorPane anchorPane = new AnchorPane();   //添加一个pane,用来装后面的小插件
        anchorPane.getChildren().addAll(textArea, choiceBox, button, l,textArea1);  //调用getChildren方法的addAll方法,写死就行,括号里的就是我们添加的插件名字
        Scene scene = new Scene(anchorPane, 600, 700);  //社子和Pane的默认宽度、高度,不能超过设置的窗口临界值
        GuiDemo.setScene(scene);    //把窗口的属性填进去
        GuiDemo.show();    //显示窗口,否则运行的话是没有东西的
    }

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

我们添加了新的插件的时候,记得在下面的内容里加进去哦

anchorPane.getChildren().addAll(textArea, choiceBox, button, l,textArea1);  //调用getChildren方法的addAll方法,写死就行,括号里的就是我们添加的插件名字​

在这里插入图片描述
嘿嘿,这个时候有小伙子要问了,那我命令执行不能执行我想要的,那叫啥EXP?很好,我们接下来添加用于接收我们自定义命令的按钮和文本框吧

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class GuiDemo extends Application {      //创建一个GuiDemo类,GuiDemo继承Application类
    public void start(Stage GuiDemo) {          //创建一个无返回的start方法,Stage GuiDemo是JAVAFX里面的一个属性
        //设置title
        GuiDemo.setTitle("GUI小DEMO  by:vlan911 ");  //设置小工具的标题
        GuiDemo.setMaxWidth(700);   //设置小工具的最大宽度
        GuiDemo.setMaxHeight(500);  //设置小工具的最大高度

        //设置icon
        GuiDemo.getIcons().add(new Image("22.jpg"));    //设置GUI的小图标,图标需要放在classes目录下或是网上的在线图片

        //添加URL文字提示
        Label l = new Label("请输入URL");      //设置一个lable,用来显示提示文字
        l.setLayoutX(5);        //设置lable的横坐标
        l.setLayoutY(10);       //设置lable的纵坐标
        l.setPrefWidth(70);     //设置lable的宽度
        l.setPrefHeight(20);    //设置lable的高度

        //添加URL文本框
        TextArea textArea = new TextArea();     //添加一哥文本框,用来接收URL
        textArea.setLayoutX(75);        //设置文本框的横坐标
        textArea.setLayoutY(5);         //设置文本框的纵坐标
        textArea.setPrefWidth(220);     //设置文本框的宽度
        textArea.setPrefHeight(20);     //设置文本框的高度

        //添加下拉按钮
        String strings[] = {"Kyan RCE", "Sapido RCE", "Vigor 2960 RCE"};    //添加一个字符串数组
        ChoiceBox choiceBox = new ChoiceBox(FXCollections.observableArrayList(strings));    //添加一个下拉列表,内容就是上面的字符串数组
        choiceBox.setLayoutX(315);  //设置下拉列表的横坐标
        choiceBox.setLayoutY(10);   //设置下拉列表的纵坐标
        choiceBox.setPrefHeight(20);    //设置下拉列表的高度
        choiceBox.setPrefWidth(70);     //设置下拉列表的宽度

        //添加确定按钮
        Button button = new Button("确定");   //添加一个按钮
        button.setLayoutX(405);     //设置按钮的横坐标
        button.setLayoutY(10);      //设置按钮的纵坐标
        button.setPrefHeight(20);   //设置按钮的高度
        button.setPrefWidth(50);    //设置按钮的宽度

        //添加回显文本框
        TextArea textArea1 = new TextArea();        //添加一个回显文本框
        textArea1.setLayoutX(5);        //设置文本框的横坐标
        textArea1.setLayoutY(100);      //设置文本框的纵坐标
        textArea1.setPrefHeight(300);   //设置文本框的高度
        textArea1.setPrefWidth(500);    //设置文本框的宽度

        textArea1.setWrapText(true);    //设置文本框里的文字自动换行
        textArea1.setText("Kyan信息泄露漏洞\n" +
                "Kyan命令注入漏洞\n" +
                "Sapido命令执行漏洞\n" +
                "Vigor 2960命令执行\n" +
                "博华网龙RCE\n" +
                "西迪特WirelessRCE");


        //添加执行命令文字提示
        Label l1 = new Label("请输入命令");
        l1.setLayoutX(5);
        l1.setLayoutY(62);
        l1.setPrefWidth(70);
        l1.setPrefHeight(20);
        //添加命令文本框
        TextArea textArea2 = new TextArea();
        textArea2.setLayoutX(75);
        textArea2.setLayoutY(55);
        textArea2.setPrefHeight(20);
        textArea2.setPrefWidth(220);

        //添加执行按钮
        Button button1 = new Button("执行");
        button1.setLayoutX(315);
        button1.setLayoutY(62);
        button1.setPrefHeight(20);
        button1.setPrefWidth(50);

        textArea2.setText("请输入命令...");

        //添加一个pane,用来装填按钮等插件
        AnchorPane anchorPane = new AnchorPane();   //添加一个pane,用来装后面的小插件
        anchorPane.getChildren().addAll(textArea, choiceBox, button, l, textArea1,textArea2,l1);  //调用getChildren方法的addAll方法,写死就行,括号里的就是我们添加的插件名字
        Scene scene = new Scene(anchorPane, 600, 700);  //社子和Pane的默认宽度、高度,不能超过设置的窗口临界值
        GuiDemo.setScene(scene);    //把窗口的属性填进去
        GuiDemo.show();    //显示窗口,否则运行的话是没有东西的
    }

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

在这里插入图片描述

此时我们还没有键入任何的事件,就是说,我们这个时候点击下拉框、按钮是没有认识事件的,关于事件,我们需要联动我们的具体请求

所以这节先不说,我们下期讲HTTP、HTTPS请求​的时候一起弄,嘻嘻嘻

我们先给他编译成可以直接执行的jar包吧

JAR包的封装

我们这样封装,是百分百起不来的!

所以,我们重新写一个主main

public class router {

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

}

在这里插入图片描述

它的作用很简单,那就是我们进行打包的时候用
Ctrl+shift+Alt+S 添加打包的类​
在这里插入图片描述
我们选择文件夹,这样的话就可以自定义选择项目
在这里插入图片描述

在这里插入图片描述
此时我们继续默认即可
点击OK后,我们点击build->Artifacts->build
在这里插入图片描述
在这里插入图片描述
我们返回我们的项目文件夹
D:\variablejava\GuiDemo\out\artifacts\GuiDemo_jar
需要注意的是,每个人的项目文件夹都是不一样的,同时我们需要关注我们的图标文件是不是在classes文件夹里,有很多次笔者都是因为图片没了所以项目起不来,报错
在这里插入图片描述

今天就先到这吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/42105.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java基础一:基础概念、面向对象

目录 1.基础概念 2.IDEA 开发工具 2.1 JDK环境配置 2.2 注释和变量 2.3 标识符 2.4 数据类型 2.5 算术运算符 2.6 赋值运算符 2.7 关系运算符 2.8 逻辑运算符 2.9 三元运算符 2.10 流程控制 3. 面向对象 3.1类和对象 3.2 静态 static 3.3 package 包 3.4 impor…

Spark系列之Spark概述

title: Spark系列 What is Apache Spark™? Apache Spark™ is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters. 第一章 Spark概述 1.1 Spark的产生背景 1.1.1 MapReduce的发展 1.1.…

【Flink】时间语义和水位线的概念和使用

文章目录一 时间语义与Wartermark1 Flink中的时间语义2 EventTime的引入3 Watermark(水位线)(1)基本概念(2)水位线测试a 代码编写b 计算水位线c 计算结果d 深入分析(3)水位线时间测试…

【web前端期末大作业】html网上在线书城大学生静态网页 大学生html当当书城仿站 网上书城购物网页作业HTML

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

智慧城市解决方案典型应用

4.2.智慧城市建设目标 4.2.1.高标准的智慧城市基础设施 智慧城市的基础设施主要包括城市信息基础设施和城市空间数据基础设施两个方面。智慧城市建设的首要目标是要建立起完善的、高标准的智慧城市基础设施,并在此基础上建立完备的城市基础信息资源。高标准的城市…

微软文本转语音「免费网页版」

网站地址:Text To Speech - 在线文本转语音 大家好~今天给小伙伴们安利一个AI配音小工具:TTS-文本转语音 【闲话】 疫情三年,很多人都失去工作,有的也是断断续续。很多人负债累累,在全球形势严峻,经济下滑…

【FreeRTOS(三)】任务状态

文章目录任务状态任务挂起 vTaskSuspend取消任务挂起 vTaskResume挂起任务调度器 vTaskSuspendAll取消挂起任务调度器 xTaskResumeAll代码示例:任务挂起、取消任务挂起代码示例:挂起任务调度器、取消挂起任务调度器任务状态 freeRTOS任务的状态有四种&am…

【POJ No. 3321】 子树查询 Apple Tree

【POJ No. 3321】 子树查询 Apple Tree 北大OJ 题目地址 【题意】 在卡卡的房子外面有一棵苹果树,树上有N 个叉(编号为1~N ,根为1),它们通过分支连接。苹果在叉上生长,两个苹果不会在同一个叉…

1000道最新高频Java面试题,覆盖25个技术栈,从底层原理到架构

最近感慨面试难的人越来越多了,一方面是市场环境,更重要的一方面是企业对Java的人才要求越来越高了。 基本上这样感慨的分为两类人,第一,虽然挂着3、5年经验,但肚子里货少,也没啥拿得出手的项目&#xff0c…

【外卖项目实战开发四】

文章目录菜品管理业务开发文件上传下载文件上传介绍文件下载介绍文件上传代码实现文件下载代码实现新增菜品需求分析数据模型代码开发-准备工作代码开发-梳理交互过程菜品信息分页查询需求分析代码开发-梳理交互过程修改菜品需求分析代码开发-梳理交互过程停售/起售菜品&#x…

阿里P8大牛总结的Java锁机制入门笔记,堪称教科书式天花板

前言 锁机制无处不在,锁机制是实现线程同步的基础,锁机制并不是Java锁独有的,其他各种计算机语言中也有着锁机制相关的实现,数据库中也有锁的相关内容。这篇文章就是从Java入手,深入学习、理解Java中的锁机制&#xf…

【Android App】实战项目之实现你问我答的智能语音机器人(超详细 附源码)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 一、需求描述 想必大家都见过商场里的智能语音机器人,你对它提问时它可以自动回答你的问题,接下来我们也实现这样一个机器人,它依靠语音技术完成问询服务 基本功能如下 1:接收人们…

智能家居—— 树莓派摄像头捕捉人脸并识别

文章目录下载安装mjpg-streamer树莓派安装libcurl库树莓派安装openssl库语音控制开启摄像头线程拍照代码及步骤语音控制摄像头拍照camera.ccontrolDevice.h下载安装mjpg-streamer 参考博文:智能家居 —— 树莓派下载安装mjpg-streamer(完成拍照录像监控…

市面上真正的全光谱灯品牌有哪些?全光谱护眼照明灯的作用很明显

众所周知,人眼感知任何事物都离不开光线的照射,但很多人可能不知道,光线不仅可以使我们“看得见”,还可以决定我们是否看得“真实”,这是怎么回事呢?其实这就是光线的色谱丰富度的问题。 人眼感知最舒适的光…

堆、堆排序、堆应用

一、概述 “堆”(Heap),原地排序、时间复杂度O(nlogn)的排序算法。 堆是一个完全二叉树;堆中每一个节点的值都必须大于等于(或者小于等于)其子树中每个节点的值; 二、如何实现一个堆 使用数…

第2-4-7章 docker安装WorkBench-规则引擎Drools-业务规则管理系统-组件化-中台

文章目录8. WorkBench8.1 WorkBench简介8.2 安装方式8.2.1 传统方式安装8.2.2 docker安装drools workbench8.3 使用方式8.3.1 创建空间、项目8.3.2 创建数据对象8.3.3 创建DRL规则文件8.3.4 创建测试场景8.3.5 设置KieBase和KieSession8.3.6 编译、构建、部署8.3.7 在项目中使用…

Intel PAUSE 指令变化如何影响 MySQL 的性能

导读 x86、arm指令都很多,无论是应用程序员还是数据库内核研发大多时候都不需要对这些指令深入理解,但是 Pause 指令和数据库操作太紧密了,本文通过一次非常有趣的性能优化来引入对 Pause 指令的理解,期望可以事半功倍地搞清楚 C…

微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪

咱们以前单体应用里面有很多的应用和功能,依赖各个功能之间相互调用,使用公共的代码包等等,排查问题,使用类似于 gdb/dlv 工具或者直接查看代码日志,进行定位和分析 但是现在我们基本上都是微服务架构了,将…

Node.js 入门教程 20 查看 npm 包安装的版本 21 安装 npm 包的旧版本

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录,不存在任何商业用途,如侵删 文章目录Node.js 入门教程20 查看 npm 包安装的版本21 安装 npm 包的旧版本20 查看 npm 包安装的版本 若要查看所有已安装的 npm 软件包&#xff08…

JetpackCompose Navigation导航快速上手

Navigation 快速上手 下面案例简要展示使用 Compose 版本的 Navigation 库来实现两个页面之间的跳转 这是完整的结构(忽略掉红线划过的那个包) 编写欲跳转的两个页面 编写 Demo1 页面 子页面使用多个 composable 组件相组合的方法一一装配起来 Demo1m…