JavaFX

1、JavaFX

javafx学习笔记

1.1、JavaFX应用程序架构

基本架构

一个窗口/舞台(stage)只能有一个场景(scene),一个场景里可以放根节点(一般都是布局),布局可以相互嵌套,布局里面存放节点,比如:label、button等

image-20220520143948382

代码实例

代码运行顺序,main方法--》Application的launch()方法--》start方法

package com.akkacloud;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        /*main函数调用Application*/
        Application.launch(args);
    }
    /*程序开始时运行*/
    @Override
    public void start(Stage primaryStage) throws Exception {
        /*标签*/
        Label label = new Label("我是个标签");

        /*布局*/
        BorderPane borderPane = new BorderPane(label);//borderPane布局会把场景分成上下左右中,默认放在中间

        /*场景*/
        Scene scene = new Scene(borderPane,1000,600);

        /*主要的舞台/窗口*/
        primaryStage.setTitle("HelloJavaFX");
        /*窗口设置场景*/
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

运行结果

image-20220520144319149

1.2、JavaFX的stage

Stage类是一个窗口

常用类

/*主要的舞台/窗口*/
primaryStage.setTitle("HelloJavaFX");
/*设置icon*/
primaryStage.getIcons().add(new Image("images/icon.png"));
/*窗口设置场景*/
primaryStage.setScene(scene);
primaryStage.show();

设置关闭窗口是询问是否关闭

primaryStage.setOnCloseRequest(event -> {
  event.consume();
  Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
  alert.setTitle("退出程序");
  alert.setHeaderText(null);
  alert.setContentText("确认退出程序?");
  Optional<ButtonType> result = alert.showAndWait();
  if(result.get()==ButtonType.OK){
    Platform.exit();
  }
});

image-20220520154246643

1.3、JavaFX的scene

场景

Scene scene = new Scene(borderPane,1000,600);//在一个场景放入一个节点树的根节点(布局),然后是宽高

然后放入舞台/窗口后才可以显示

使用案例

点击button跳转到新的场景

package com.akkacloud;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.awt.*;
import java.util.Optional;

public class Main extends Application {
    public static void main(String[] args) {
        /*main函数调用Application*/
        Application.launch(args);
    }
    /*程序开始时运行*/
    @Override
    public void start(Stage primaryStage) throws Exception {
        /*标签*/
        Label label = new Label("场景1");
        label.setLayoutX(200);
        label.setLayoutY(200);
        Button button = new Button("跳转场景");
        button.setLayoutX(200);
        button.setLayoutY(250);
        /*标签*/
        Label label1 = new Label("场景2");
        label1.setLayoutX(200);
        label1.setLayoutY(200);
        Button button1 = new Button("返回");
        button1.setLayoutX(200);
        button1.setLayoutY(250);

        /*布局*/
        AnchorPane root = new AnchorPane();
        root.getChildren().addAll(label,button);

        /*场景*/
        Scene scene = new Scene(root,1000,600);

        /*布局*/
        AnchorPane newroot = new AnchorPane();
        newroot.getChildren().addAll(label1,button1);
        Scene newscene = new Scene(newroot,1000,600);


        button1.setOnAction(event -> {
            primaryStage.setScene(scene);
        });


        button.setOnAction(event -> {
            primaryStage.setScene(newscene);
        });





        /*主要的舞台/窗口*/
        primaryStage.setTitle("HelloJavaFX");
        /*设置icon*/
        primaryStage.getIcons().add(new Image("images/icon.png"));
        /*窗口设置场景*/
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

案例

image-20220520160659271

image-20220520160706513

1.4、JavaFX的Pane

Pane
布局的父类,使用坐标定位,类似绝对布局,子控件使用layoutX,layoutY定位

BorderPane边框布局
将界面分割成上中下,中间部分又分成左中右,一共五部分,通过<top><left><center><right><bottom>来设置内容。

HBox 水平布局
将控件水平排列,不换行。

VBox 垂直布局
将控件垂直排列,不换行。

FlowPane 流式布局
默认水平排列,排满一行之后会换行,提供属性设置水平还是垂直

GridPane 网格布局
类似HTML的table布局,按表格分布,可以合并单元格,  columnConstraints定义列,rowConstraints定义行。

AnchorPane 锚点布局
类似相对布局,可以指定子控件在布局的左下角等位置,可设置相对距离

ScrollPane 滚动布局
提供滚动内容。

StackPane 堆栈布局
所有子控件叠加在一起,可单独指定某个子控件位置。

TilePane 磁贴布局
把所有子控件放在一个网格中,每格大小一样,节点可以按水平或垂直排列,排到边界处会自动换行。

DialogPane 对话布局
弹窗。

1.5、JavaFX的Note

Note本身为抽象类,不可以直接使用,应该调用其子类使用,如:Label、Button

note通用属性设置

/*标签*/
Label label = new Label("场景1");
label.setLayoutX(200);
label.setLayoutY(200);
label.setStyle("-fx-background-color: blue;-fx-border-color: red;-fx-border-width: 2px");
/*设置节点的长宽*/
label.setPrefWidth(200);
label.setPrefHeight(50);
/*设置节点内容居中*/
label.setAlignment(Pos.CENTER);
/*设置透明度*/
label.setOpacity(0.5);

1.6、JavaFX的事件驱动

setOnAction方法

鼠标点击事件,该方法的参数需要EventHandler<ActionEvent>()对象

setOnKeyReleased

键盘释放事件

package com.akkacloud;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;


public class Main extends Application {
    public static void main(String[] args) {
        /*main函数调用Application*/
        Application.launch(args);
    }
    /*程序开始时运行*/
    @Override
    public void start(Stage primaryStage) throws Exception {

        Label text = new Label("text");
        text.setLayoutX(200);
        text.setLayoutY(200);
        Button button = new Button("向上移动");
        button.setLayoutX(400);
        button.setLayoutY(200);
        AnchorPane root = new AnchorPane();


        root.getChildren().addAll(text,button);
        Scene scene = new Scene(root,900,600);


        /*按钮点击事件*/
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                text.setLayoutY(text.getLayoutY() - 10);
            }
        });

        /*场景设置当键盘释放时触发事件*/
        scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                /*获取键盘事件*/
                KeyCode keyCode = event.getCode();
                /*判断是不是向下*/
                if(keyCode.equals(keyCode.DOWN)){
                    text.setLayoutY(text.getLayoutY() + 10);
                }
            }
        });


        primaryStage.setScene(scene);
        primaryStage.show();


    }
}

1.7、javafx的fxml布局使用

1.7.1、原部署方式

package com.akkacloud;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;


public class Main extends Application {
    public static void main(String[] args) {
        /*main函数调用Application*/
        Application.launch(args);
    }
    /*程序开始时运行*/
    @Override
    public void start(Stage primaryStage) throws Exception {

        Label labeltext = new Label("hello world");
        labeltext.setLayoutX(200);
        labeltext.setLayoutY(200);
        labeltext.setFont(new Font(30));
        Button button = new Button("向上移动");
        button.setLayoutX(400);
        button.setLayoutY(200);


        AnchorPane root = new AnchorPane();
        root.getChildren().addAll(labeltext,button);
        Scene scene = new Scene(root,900,600);


        /*按钮点击事件*/
        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                labeltext.setLayoutY(labeltext.getLayoutY() - 10);
            }
        });


        primaryStage.setScene(scene);
        primaryStage.show();


    }
}

image-20220521202603988

1.7.2、fxml布局

fxml可以把视图层和控制层分离,方便管理和维护

1.新建fxml文件

image-20220521202914971

2.编写视图层

此处还没写controller

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<?import javafx.scene.text.Font?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="com.akkacloud.DemoController"
            prefHeight="400.0" prefWidth="600.0">


    <children>
        <!--标签名对应对象名,id为属性名-->
        <Label fx:id="la" text="hello fxml" layoutX="200" layoutY="200">
            <font>
                <Font size="30"></Font>
            </font>
        </Label>

        <!--onAction里用#指定controller类的方法名-->
        <Button fx:id="bu" text="向上移动" layoutX="400" layoutY="200" onAction="#onUp"></Button>

    </children>

</AnchorPane>

3.编写主类

package com.akkacloud;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;


public class Main extends Application {
    public static void main(String[] args) {
        /*main函数调用Application*/
        Application.launch(args);
    }
    /*程序开始时运行*/
    @Override
    public void start(Stage primaryStage) throws Exception {

        Pane root = FXMLLoader.load(getClass().getResource("demo.fxml"));

        Scene scene = new Scene(root,900,600);
        primaryStage.setScene(scene);
        primaryStage.show();


    }
}

4.编写Controller层

package com.akkacloud;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;

public class DemoController {

    @FXML
    Label la;//对应fxml文件的节点id为la

    @FXML
    Button bu;//对应fxml文件的节点id为la

    public void onUp(ActionEvent actionEvent) {//对应fxml点击事件的方法名,
        la.setLayoutY(la.getLayoutY()-5);
    }
}

image-20220521210207502

1.7.3、Scene Builder使用

1.安装下载

https://openjfx.cn/scene-builder/#download

2.创建空项目

image-20220521212647762

3.拖入布局

image-20220521212809320

4.常用节点设置

image-20220521213204857

5.id和驱动设置

image-20220521214529545

6.导出Controller代码

image-20220521214646724

image-20220521220232020

7.导出fxml

image-20220521215032979

1.7.4、配合idea使用

1.idea创建javafx项目

image-20220521215136205

2.项目导入视图fxml文件

image-20220521215458400

3.修改Main文件引用的fxml

image-20220521215755978

4.修改fxml,添加controller控制代码

image-20220521220432292

5.修改controller,贴入scene Builder 生成的代码

image-20220521220608395

6.添加action代码逻辑操作语句

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Controller {

    @FXML
    private Button bu;

    @FXML
    private TextField textfiled;

    @FXML
    private Label label;

    @FXML
    void action(ActionEvent event) {
        textfiled.setText("提交成功");
    }
}

7.启动测试

image-20220521220743499

1.8、Controller的initialize方法

在绑定组件后会调用该方法,常用于加载静态文件的内容

1.实体类编写(展示在表格中的类)

package sample;

public class Person {
    private String name;
    private Integer age;

		Getter、setter、constructor....
}

2.scene Builder创建视图(fxml设置对应的controller)

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TableView fx:id="tableview" layoutX="1.0" layoutY="-4.0" prefHeight="407.0" prefWidth="600.0">
        <columns>
          <TableColumn fx:id="name" prefWidth="75.0" text="name" />
          <TableColumn fx:id="age" prefWidth="75.0" text="age" />
        </columns>
      </TableView>
   </children>
</AnchorPane>

3.controller导入和逻辑编写(initialize)

package sample;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;

public class Controller {

    @FXML
    private TableView<Person> tableview;

    @FXML
    private TableColumn<Person,String> name;

    @FXML
    private TableColumn<Person, Integer> age;


    public void initialize(){
        ObservableList<Person> celldata = FXCollections.observableArrayList();

        name.setCellValueFactory(new PropertyValueFactory<Person,String>("name"));
        age.setCellValueFactory(new PropertyValueFactory<Person,Integer>("age"));

        celldata.add(new Person("张三",14));
        celldata.add(new Person("李四",24));
        celldata.add(new Person("王五",44));
        celldata.add(new Person("赵六",22));
        tableview.setItems(celldata);
    }
}

4.修改主类导入对应fxml

package sample;

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) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("test.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }


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

5.搞定

image-20220521224345160

1.9、Application里调用Controller

实现场景的内的note随边框的变化而变化大小

1.scene Builder里创建视图,导入fxml

  <?xml version="1.0" encoding="UTF-8"?>

  <?import javafx.scene.layout.AnchorPane?>
  <?import javafx.scene.shape.Circle?>

  <AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
     <children>
        <Circle fx:id="ci" centerX="250.0" centerY="250.0" fill="DODGERBLUE" radius="100.0" stroke="BLACK" strokeType="INSIDE" />
     </children>
  </AnchorPane>

2.设置controller

package sample;

import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.shape.Circle;

public class Controller {

    @FXML
    private Circle ci;

    public void CircleCenterBind(Scene scene){
        /*绑定的中心点为场景的宽度除2*/
        ci.centerXProperty().bind(scene.widthProperty().divide(2));
        ci.centerYProperty().bind(scene.heightProperty().divide(2));
    }

}

3.设置Application类(Main)

package sample;

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) throws Exception{

        FXMLLoader fxmlLoader = new FXMLLoader();
        /*导入fxml视图*/
        fxmlLoader.setLocation(getClass().getResource("test.fxml"));

        /*获取根节点*/
        Parent root  = fxmlLoader.load();
        /*创建场景放入根节点(布局)*/
        Scene scene = new Scene(root);

        /*获取controller*/
        Controller controller = fxmlLoader.getController();
        /*调用controller方法设置节点*/
        controller.CircleCenterBind(scene);

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(scene);
        primaryStage.show();
    }


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

image-20220521232856722

posted @ 2022-05-21 23:31  akka1  阅读(358)  评论(0编辑  收藏  举报