• 珍藏的javafx教程——简单了解


    java fx是什么

    是java实现图形界面的一种方式,其他还有java的awt、swing,但是逐渐被淘汰。

    javafx可以实现逻辑和样式的分离,可以使用xml和css来编写样式。

    在学习之前请确保你已经熟练掌握面向对象、包装类、枚举、注解、匿名对象等内容的概念和使用。

    java 11及以后使用javafx的方法

    jdk 11+的使用

    自从java11以后,jdk已经不内置javafx库,已交给开源社区管理,所以我们需要自己导入。

    可以到这个网址去下载 jar 包。注意下载的类型是sdk。

    gluonhq.com

    使用maven的同学可以使用以下语句导入

    1. <dependency>
    2. <groupId>org.openjfx</groupId>
    3. <artifactId>javafx-controls</artifactId>
    4. <version>19-ea+8</version>
    5. </dependency>

    本教程使用的java版本是18,因此可能与java8的写法有所出入。

    开发文档

    老版本的fx文档

    新版本的fx文档

    fx基本

    java fx的两种写法和helloworld

    第一种写法把fx app实现方法和main方法写在一个类里面,在java 11之后这个方式就失效了。

    1. import javafx.application.Application;
    2. import javafx.stage.Stage;
    3. public class _1helloJfx extends Application {
    4. public static void main(String[] args) {
    5. launch(args); //调用start
    6. }
    7. @Override
    8. public void start(Stage primaryStage) throws Exception {
    9. primaryStage.setTitle("javafx"); //设置标题
    10. primaryStage.show(); //展示窗口
    11. }
    12. }

     第二种方法把两个方法分开放置,在launch里面传入有start方法类的反射。

    1. import javafx.application.Application;
    2. public class App{
    3. public static void main(String[] args) {
    4. Application.launch(Window.class, args);
    5. }
    6. }
    7. import javafx.application.Application;
    8. import javafx.stage.Stage;
    9. public class Window extends Application {
    10. @Override
    11. public void start(Stage arg0) throws Exception {
    12. // TODO Auto-generated method stub
    13. arg0.show();
    14. }
    15. }

    javafx的分层

    一个javafx程序有三层,最外面的是Stage层,一个Stage就是一个独立的窗口。

    在往里是Scene层,一个Scene就是一个窗口内部的一个状态。

    在往里就是一个一个的node节点,节点可以是按钮、标签、文本等组件。

    javafx的生命周期

    任何一个事物都有产生、发展、消亡的过程,人是这样,程序也不例外。

    javafx的生命周期分为init、start和stop,分别是初始化,正在运行和结束。

    1. @Override
    2. public void init() throws Exception {
    3. System.out.println("开始");
    4. System.out.println("init():" + Thread.currentThread().getName());
    5. }
    6. @Override
    7. public void start(Stage primaryStage) throws Exception {
    8. System.out.println("运行");
    9. primaryStage.show();
    10. System.out.println("start():" + Thread.currentThread().getName());
    11. }
    12. @Override
    13. public void stop() throws Exception {
    14. System.out.println("结束");
    15. System.out.println("stop():" + Thread.currentThread().getName());
    16. }

    运行后发现init是一个独立的线程,start和stop同属一个JavaFX Application Thread线程,关闭窗口后就会进入stop,我们可以在这个方法里放一些停止连接之类的函数。

    fx窗口

    Stage类

    一个Stage类代表一个窗口,我们可以不使用方法提供的Stage,再写一个.

    另外,Stage的setHeight()和setWidth()方法用来设置窗口的宽高。

    1. @Override
    2. public void start(Stage primaryStage) throws Exception {
    3. Stage stage = new Stage();
    4. stage.setHeight(500);
    5. stage.setWidth(500);
    6. stage.show();
    7. }

    Stage类的其他方法如下表所示

    方法作用
    setMaxHeight(int);窗口最大高度
    setMaxWidth(int);窗口最大宽度
    setResizable(boolean);是否允许改变大小
    setMinHeight(int);窗口最小高度
    setMinWidth(int);窗口最小宽度
    setMaximized(boolean);是否最大化
    setIconified(boolean);是否最小化
    setFullScreen(boolean);是否全屏
    setAlwaysOnTop(boolean);窗口是否保持置顶
    setY(int)窗口出生距离屏幕上面的高度
    setX(int)窗口出生举例屏幕左边的宽度
    primaryStage.setOpacity();透明度
    setTitle(String)设置窗口标题
    initStyle(StageStyle);设置窗口样式,只要知道三个常用的函数,StageStyle.DECORATED是正常,StageStyle.UTILITY没有最大最小化,StageStyle.TRANSPARENT是透明就行;
    setScene(Scene)给窗口设置场景
    close();关闭窗口

    Srage宽度高度监听和位置监听

    可以用监听来做界面自适应之类的东西。

    窗口大小监听

     

    1. Stage类的其他方法如下表所示
    2. 方法 作用
    3. setMaxHeight(int); 窗口最大高度
    4. setMaxWidth(int); 窗口最大宽度
    5. setResizable(boolean); 是否允许改变大小
    6. setMinHeight(int); 窗口最小高度
    7. setMinWidth(int); 窗口最小宽度
    8. setMaximized(boolean); 是否最大化
    9. setIconified(boolean); 是否最小化
    10. setFullScreen(boolean); 是否全屏
    11. setAlwaysOnTop(boolean); 窗口是否保持置顶
    12. setY(int) 窗口出生距离屏幕上面的高度
    13. setX(int) 窗口出生举例屏幕左边的宽度
    14. primaryStage.setOpacity(); 透明度
    15. setTitle(String) 设置窗口标题
    16. initStyle(StageStyle); 设置窗口样式,只要知道三个常用的函数,StageStyle.DECORATED是正常,StageStyle.UTILITY没有最大最小化,StageStyle.TRANSPARENT是透明就行;
    17. setScene(Scene) 给窗口设置场景
    18. close(); 关闭窗口
    19. Srage宽度高度监听和位置监听
    20. 可以用监听来做界面自适应之类的东西。
    21. 窗口大小监听

     窗口位置监听

     

    1. @Override
    2. public void start(Stage primaryStage) throws Exception {
    3. primaryStage.setY(100);
    4. primaryStage.setX(100);
    5. primaryStage.setWidth(200);
    6. primaryStage.setHeight(200);
    7. primaryStage.xProperty().addListener(new ChangeListener<Number>() {
    8. @Override
    9. public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    10. System.out.println("举例屏幕左边有 = "+newValue.doubleValue()+" px");
    11. }
    12. });
    13. primaryStage.yProperty().addListener(new ChangeListener<Number>() {
    14. @Override
    15. public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    16. System.out.println("举例屏幕上面有 = "+newValue.doubleValue()+" px");
    17. }
    18. });
    19. primaryStage.show();

    窗口图标设置

    在对应的包下放置文件,然后在getIcons的add方法里面填写相对路径。

    package com.javafx;
    
    import javafx.application.Application;
    import javafx.scene.image.Image;
    import javafx.stage.Stage;
    
    public class Window extends Application{
    @Override
        public void start(Stage primaryStage) throws Exception {
            primaryStage.getIcons().add(new Image("com/javafx/ico-01.png"));
    
            stage.show();
        }
    }

    子窗口

    可以用initOwner()方法来设置一个窗口的父窗口,子窗口不关父窗口不会响应

        public void start(Stage primaryStage) throws Exception {
            // 模态化窗口。
    
            Stage s1 = new Stage();
            s1.setTitle("s1");
    
            Stage s2 = new Stage();
            s2.setTitle("s2");
            // s1有s2;
            s2.initOwner(s1);
    
            s1.show();
            s2.show();
    
        }

    Scene类

    在之前的练习中你可能发现了,窗口放大或缩小后,有些地方变成黑色,就是因为还没有添加一个Scene场景。

    Group group = new Group();
    Scene scene = new Scene(group); //创建一个场景
    primaryStage.setScene(scene);//给窗口设置场景

    创建一个场景需要传入一个参数,这个参数可以是一个布局,也可以是一个控件。

    group是控件的集合,本身不是布局。

    常用组件

    添加组件的方法

    布局或集合组件.getChildren().add(组件对象1); //添加一个组件
    布局或集合组件.getChildren().addAll(组件对象1, 组件对象2); //添加多个组件

    常用组件添加

    常用信息输出组件

    Label()标签
    Text()文本
    TextFlow()文本域,fx8版本后出现
    ImageView图片框
    ProgressBar进度条

    常用控制组件

    Button()按钮

    常用信息输入组件

    TextField()文本单行输入框
    TextField()文本多行输入域
    RadioButton()单选按钮
    checkBox()多选按钮
    PasswordField()密码框
    slider()滑条
    package com.javafx;
    
    import javafx.application.Application;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.CheckBox;
    import javafx.scene.control.Label;
    import javafx.scene.control.PasswordField;
    import javafx.scene.control.ProgressBar;
    import javafx.scene.control.RadioButton;
    import javafx.scene.control.TextArea;
    import javafx.scene.control.TextField;
    import javafx.scene.image.Image;
    import javafx.scene.image.ImageView;
    import javafx.scene.layout.FlowPane;
    import javafx.scene.text.Text;
    import javafx.scene.text.TextFlow;
    import javafx.stage.Stage;
    
    public class Window extends Application{
        @Override
        public void start(Stage primaryStage) throws Exception {
    
    
            Button btn = new Button("b1");
            Label lab=new Label("标签");
            Text t1=new Text("文本。。。");
            Text t2=new Text();
            t2.setText("文本2。。。");
    
            TextFlow tf=new TextFlow();
            tf.getChildren().addAll(t1,t2);
            
            ProgressBar pb=new ProgressBar();
            pb.setProgress(0.25);
            ImageView iv=new ImageView();
            iv.setImage(new Image("com/javafx/ico-01.png", 100, 100, true, true, true));
    
            RadioButton rb1=new RadioButton();
            RadioButton rb2=new RadioButton();
            rb2.setLayoutX(20);
            CheckBox cb=new CheckBox();
            cb.setLayoutX(40);
            Group group=new Group();
            group.getChildren().addAll(rb1,rb2,cb);
    
            TextField tfIn=new TextField();
            TextArea ta=new TextArea();
            PasswordField psf=new PasswordField();
    
            FlowPane pane=new FlowPane();
            pane.getChildren().addAll(btn,lab,tf,pb,iv,group,tfIn,ta,psf);
    
    
            Scene scene=new Scene(pane);
            
            primaryStage.setScene(scene);
            primaryStage.setY(100);
            primaryStage.setX(100);
            primaryStage.setWidth(1000);
            primaryStage.setHeight(600);
            primaryStage.show();
    
        }
    }

    布局

    布局请自行了解。这些布局之间可以互相嵌套,就像html里面的div一样。

    S.No形状和描述
    1HBoxHBox布局将应用程序中的所有节点排列在一个水平行中。
    2VBoxVBox布局将我们应用程序中的所有节点排列在一个垂直列中。
    3BorderPane边框窗格布局将应用程序中的节点排列在顶部,左侧,右侧,底部和中心位置。
    4StackPane堆栈窗格布局将应用程序中的节点排列在另一个上面,就像在堆栈中一样。
    5TextFlow文本流布局在单个流中排列多个文本节点。
    6AnchorPane“锚点”窗格布局将应用程序中的节点锚定在距窗格特定距离处。
    7TilePaneTile窗格布局以均匀大小的tile的形式添加应用程序的所有节点。
    8GridPane网格窗格布局将应用程序中的节点排列为行和列的网格。
    9FlowPane流窗格布局包装流中的所有节点。

    监听

    在所有节点上,都可以添加监听,以下是所有节点都通用的监听事件。

    单击

    方式1

    package com.javafx;
    
    import javafx.application.Application;
    import javafx.event.ActionEvent;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.FlowPane;
    import javafx.stage.Stage;
    
    public class Window extends Application{
        @Override
        public void start(Stage primaryStage) throws Exception {
    
    
            Button btn = new Button("b1");
            btn.setOnAction(new javafx.event.EventHandler() {
                @Override
                public void handle(ActionEvent event) {
                    Button bu = (Button) event.getSource();
    
                    System.out.println(bu.getText() + "单击");
                }
            }); 
    
            FlowPane pane=new FlowPane();
            pane.getChildren().add(btn);
    
            Scene scene=new Scene(pane);
            
            primaryStage.setScene(scene);
            primaryStage.setWidth(500);
            primaryStage.setHeight(500);
            primaryStage.show();
        }   
    }

    双击

    这个方法也可以改成单击

    package com.javafx;
    
    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.input.MouseButton;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.FlowPane;
    import javafx.stage.Stage;
    
    public class Window extends Application{
        @Override
        public void start(Stage primaryStage) throws Exception {
    
    
            Button btn = new Button("b1");
            btn.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler() {
    
                @Override
                public void handle(MouseEvent arg0) {
                    System.out.println("鼠标按键 = " + arg0.getButton().name());
                    Button bu = (Button) arg0.getSource();
                    //连续点击只有两次且用的是鼠标左键
                    if(arg0.getClickCount() == 2 &&
                    arg0.getButton().name().equals(MouseButton.PRIMARY.name())){
                        System.out.println(bu.getText()+"双击");
                    }
            }
                
                
            });
            FlowPane pane=new FlowPane();
            pane.getChildren().add(btn);
    
            Scene scene=new Scene(pane);
            
            primaryStage.setScene(scene);
            primaryStage.setWidth(200);
            primaryStage.setHeight(200);
            primaryStage.show();
    
        }
    
        
    }

    键盘

    如果想监测到多个键同时按到,需要用另外一个方法,这个后面会讲

    package com.javafx;
    
    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.input.KeyCode;
    import javafx.scene.input.KeyEvent;
    import javafx.scene.layout.FlowPane;
    import javafx.scene.text.Font;
    import javafx.scene.text.Text;
    import javafx.stage.Stage;
    
    public class Window extends Application{
        public Text text;
        @Override
        public void start(Stage primaryStage) throws Exception {
    
            text=new Text("你按下了 “ ” 键。");
            text.setFont(Font.font(25));
            
            FlowPane pane=new FlowPane();
            pane.getChildren().add(text);
    
            Scene scene=new Scene(pane);
    
    
            scene.setOnKeyPressed(new EventHandler(){
    
                @Override
                public void handle(KeyEvent arg0) {
                    if (arg0.getCode().getName().equals(KeyCode.A.getName())) {
                        System.out.println("A被按下");
                    }
                    text.setText("你按下了“"+arg0.getCode().getName()+"”键。");             
                }   
            });
            primaryStage.setScene(scene);
            primaryStage.setWidth(300);
            primaryStage.setHeight(100);
            primaryStage.show();
    
        }
    
        
    }
    
  • 相关阅读:
    牛客网刷题记录 || C++入门
    如何使用SMS向客户传递服务信息?指南在这里!
    Clang-format格式化及配置参数
    非零基础自学Java (老师:韩顺平) 第6章 数组、排序和查找 6.4 数组应用案例 && 6.5 数组赋值机制 && 6.6 数组拷贝
    存储器IP核与DDS信号发生
    你觉得好的代码可能并不是最优的解决方案
    Compose Canvas饼图效果绘制
    <四>构造函数初始化列表
    迭代器模式在金融业务中的应用及其框架实现
    无法打开文件(xxx.apk)(无法成功完成提作,因为文件包含病毒或潜在的垃圾软件。) 问题解决
  • 原文地址:https://blog.csdn.net/qq_41221596/article/details/128214788