JavaFX
1、JavaFX
javafx学习笔记
1.1、JavaFX应用程序架构
基本架构
一个窗口/舞台(stage)只能有一个场景(scene),一个场景里可以放根节点(一般都是布局),布局可以相互嵌套,布局里面存放节点,比如:label、button等
代码实例
代码运行顺序,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();
}
}
运行结果
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 result = alert.showAndWait();
if(result.get()==ButtonType.OK){
Platform.exit();
}
});
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();
}
}
案例
1.4、JavaFX的Pane
Pane
布局的父类,使用坐标定位,类似绝对布局,子控件使用layoutX,layoutY定位
BorderPane边框布局
将界面分割成上中下,中间部分又分成左中右,一共五部分,通过来设置内容。
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
对象
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() {
@Override
public void handle(ActionEvent event) {
text.setLayoutY(text.getLayoutY() - 10);
}
});
/*场景设置当键盘释放时触发事件*/
scene.setOnKeyReleased(new EventHandler() {
@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() {
@Override
public void handle(ActionEvent event) {
labeltext.setLayoutY(labeltext.getLayoutY() - 10);
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
}
1.7.2、fxml布局
fxml可以把视图层和控制层分离,方便管理和维护
1.新建fxml文件
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?>
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);
}
}
1.7.3、Scene Builder使用
1.安装下载
https://openjfx.cn/scene-builder/#download
2.创建空项目
3.拖入布局
4.常用节点设置
5.id和驱动设置
6.导出Controller代码
7.导出fxml
1.7.4、配合idea使用
1.idea创建javafx项目
2.项目导入视图fxml文件
3.修改Main文件引用的fxml
4.修改fxml,添加controller控制代码
5.修改controller,贴入scene Builder 生成的代码
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.启动测试
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?>
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 tableview;
@FXML
private TableColumn name;
@FXML
private TableColumn age;
public void initialize(){
ObservableList celldata = FXCollections.observableArrayList();
name.setCellValueFactory(new PropertyValueFactory("name"));
age.setCellValueFactory(new PropertyValueFactory("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.搞定
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?>
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);
}
}