孤山的javafx教程——javafx简单入门 - 知乎

java fx是什么

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

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

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

java 11及以后使用javafx的方法

jdk 11+的使用

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

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

gluonhq.com

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

 <dependency>
       <groupId>org.openjfx</groupId>
       <artifactId>javafx-controls</artifactId>
       <version>19-ea+8</version>
 </dependency>

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

开发文档

老版本的fx文档

新版本的fx文档

fx基本

java fx的两种写法和helloworld

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

 import javafx.application.Application;
 import javafx.stage.Stage;
 ​
 public class _1helloJfx extends Application {
     public static void main(String[] args) {
         launch(args);  //调用start
     }
 ​
     @Override
     public void start(Stage primaryStage) throws Exception {
         primaryStage.setTitle("javafx"); //设置标题
         primaryStage.show(); //展示窗口
 ​
     }
 ​
 }

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

 import javafx.application.Application;
 ​
 public class App{
     public static void main(String[] args) {
         Application.launch(Window.class, args);
     }
 }
 import javafx.application.Application;
 import javafx.stage.Stage;
 ​
 public class Window extends Application {
     @Override
     public void start(Stage arg0) throws Exception {
         // TODO Auto-generated method stub
         arg0.show();
     }
 }
 ​

javafx的分层

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

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

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

javafx的生命周期

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

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

     @Override
     public void init() throws Exception {
         System.out.println("开始");
         System.out.println("init():" + Thread.currentThread().getName());
     }
 ​
     @Override
     public void start(Stage primaryStage) throws Exception {
         System.out.println("运行");
         primaryStage.show();
         System.out.println("start():" + Thread.currentThread().getName());
     }
 ​
     @Override
     public void stop() throws Exception {
         System.out.println("结束");
         System.out.println("stop():" + Thread.currentThread().getName());
     }

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

fx窗口

Stage类

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

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

  @Override
     public void start(Stage primaryStage) throws Exception {
         Stage stage = new Stage();
 ​
         stage.setHeight(500);
         stage.setWidth(500);
         
         stage.show();
 ​
     }

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宽度高度监听和位置监听

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

窗口大小监听

  @Override
     public void start(Stage primaryStage) throws Exception {
         Stage stage = new Stage();
 ​
         stage.heightProperty().addListener(new ChangeListener<Number>() {
             @Override
             public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
                 System.out.println("高度 = "+arg2.doubleValue());
             }
             
         });
 ​
         stage.widthProperty().addListener(new ChangeListener<Number>() {
             @Override
             public void changed(ObservableValue<? extends Number> arg0, Number arg1, Number arg2) {
                 System.out.println("宽度 = "+arg2.doubleValue());
             }
             
         });    
         stage.show();
 ​
 }

窗口位置监听

  @Override
     public void start(Stage primaryStage) throws Exception {
         
         primaryStage.setY(100);
         primaryStage.setX(100);
         primaryStage.setWidth(200);
         primaryStage.setHeight(200);
 ​
         primaryStage.xProperty().addListener(new ChangeListener<Number>() {
 ​
             @Override
             public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                 System.out.println("举例屏幕左边有 = "+newValue.doubleValue()+" px");
             }
 ​
         });
 ​
         primaryStage.yProperty().addListener(new ChangeListener<Number>() {
 ​
             @Override
             public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                 System.out.println("举例屏幕上面有 = "+newValue.doubleValue()+" px");
             }
         });
        
         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

形状和描述

1

HBoxHBox布局将应用程序中的所有节点排列在一个水平行中。

2

VBoxVBox布局将我们应用程序中的所有节点排列在一个垂直列中。

3

BorderPane边框窗格布局将应用程序中的节点排列在顶部,左侧,右侧,底部和中心位置。

4

StackPane堆栈窗格布局将应用程序中的节点排列在另一个上面,就像在堆栈中一样。

5

TextFlow文本流布局在单个流中排列多个文本节点。

6

AnchorPane“锚点”窗格布局将应用程序中的节点锚定在距窗格特定距离处。

7

TilePaneTile窗格布局以均匀大小的tile的形式添加应用程序的所有节点。

8

GridPane网格窗格布局将应用程序中的节点排列为行和列的网格。

9

FlowPane流窗格布局包装流中的所有节点。

监听

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

单击

方式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<ActionEvent>() {
            @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<MouseEvent>() {

            @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<KeyEvent>(){

            @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();

    }

    
}

原网址: 访问
创建于: 2024-02-18 17:33:23
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论