Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)

文章目录

  • 一、JavaFx介绍
    • 1、JavaFx简介
    • 2、可用性
    • 3、主要特征
    • 4、UI控件
  • 二、JavaFx概述
    • 1、JavaFx结构图
    • 2、JavaFx组件
      • (1)舞台
      • (2)场景
        • ① 场景图
        • ② 节点
      • (3)控件
      • (4)布局
      • (5)图表
      • (6)2D图形
      • (7)3D图形
      • (8)声音
      • (9)视频
  • 三、JavaFx快速入门
    • 1、IDEA配置JavaFx环境
    • 2、编码与运行
  • 四、组件功能介绍
    • 1、Application
    • 2、Stage舞台(窗口)
      • (1)创建舞台
      • (2)展示舞台
      • (3)在舞台上设置场景
      • (4)舞台标题
      • (5)舞台位置
      • (6)舞台宽度和高度
      • (7)舞台风格
      • (8)舞台全屏模式
      • (9)阶段生命周期事件
      • (10)键盘或鼠标事件
    • 3、Scene场景
      • (1)创建场景
      • (2)在舞台上设置场景
      • (3)场景鼠标光标
    • 4、Node节点 UI控件的通用属性
      • (1)控件节点坐标系
      • (2)设置控件坐标
      • (3)设置控件风格
      • (4)设置控件首要背景宽度和高度
      • (5)设置文本居中
      • (6)设置是否显示/隐藏该控件
      • (7)设置控件半透明值
      • (8)设置控件旋转角度
      • (9)设置控件X轴和Y轴平移量
    • 5、UI控件的属性绑定和属性监听
    • 6、JavaFx应用里的事件驱动编程
    • 7、Color、Font、Image
      • (1)Color颜色
      • (2)Font字体
      • (3)Image图片
  • 五、FXML
    • 1、FXML布局文件的使用
    • 2、Scene Builder里构建fxml布局文件
    • 3、Controller里的initialize方法
    • 4、在Application里操作Controller
  • 六、JavaFx多线程操作Platform.runLater

JavaFx是Java图形化界面技术AWT、Swing技术的新替代品,如果想系统学习JavaFx,推荐一个B站UP主:https://space.bilibili.com/5096022/channel/collectiondetail?sid=210809
如果是想快速入门JavaFx,推荐视频:
https://www.bilibili.com/video/BV1H14y1g7ji/
https://www.bilibili.com/video/BV1Qf4y1F7Zv/

如果你因毕设或项目中用到图形化界面技术JavaFx,赶时间都不想看,请看下面的文字版,通过多个案例,直接带你快速入门JavaFx,轻松上手看懂并学会使用!


一、JavaFx介绍

1、JavaFx简介

JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。
JavaFX允许开发人员快速构建丰富的跨平台应用程序。JavaFX通过硬件加速图形支持现代GPU。
JavaFX允许开发人员在单个编程接口中组合图形,动画和UI控件。
图表编程语言可用于开发互联网应用程序(RIA)。JavaFX技术主要应用于创建Rich internet applications(RIAs)。当前的JavaFX包括JavaFX脚本和JavaFX Mobile (一种运营于行动装置的操作系统),今后JavaFX将包括更多的产品。JavaFX Script编程语言 (以下称为JavaFX) 是一种声明性的、静态类型脚本语言。
JavaFX技术有着良好的前景,包括可以直接调用Java API的能力。因为JavaFX Script是静态类型,它同样具有结构化代码、重用性和封装性,如包、类、继承和单独编译和发布单元,这些特性使得使用JavaFX技术创建和管理大型程序变为可能。

JavaFx官网:https://openjfx.io/
image.png
下面是基于JavaFx实现的一些第三方开发案例和应用场景:
image.png

2、可用性

JavaFX APIJava SE运行时环境(JRE)和Java开发工具包(JDK)绑在一起。
JDK可用于所有主要的桌面平台,WindowsMac OS XLinux
JavaFX应用程序可以在所有主要的桌面平台上编译和运行。
JDK for ARM平台包括JavaFx的基础,图形和控件组件。

3、主要特征

JavaFX中包含以下功能-

  • JavaFX是用Java编写的,JavaFX应用程序代码可以从任何Java库引用API。
  • JavaFX应用程序的外观和感觉可以定制。因此可以使用级联样式表(CSS)来对JavaFX应用程序进行风格化。平面设计师可以通过CSS自定义外观和样式。
  • 还可以在FXML脚本语言中描述UI的表示方面,并使用Java对应用程序逻辑进行编码。
  • 通过使用JavaFX Scene Builder,可以通过拖放来设计Ul。Scene Builder将创建可以移植到集成开发环境(IDE)的FXML标记,以便开发人员可以添加业务逻辑。
  • JavaFX有一个称为WebView的控件,可以呈现复杂的网页。WebView支持JavaScript,我们可以从Java API在Web页面中调用Javascript。 WebView不支持额外的HTML5功能,包括Web套接字,Web Workers和Web字体,还可以从WebView打印网页。
  • Swing互操作性。现有的Swing应用程序可以使用JavaFX类,例如图表和WebView。还可以使用SwingNode类将Swing内容嵌入到我们应用程序中。
  • 3D图形功能。JavaFX支持Shape,如Box,Cylinder,MeshView和Sphere子类,SubScene,Material,PickResult,AmbientLight和PointLight。
  • Canvas API。 使用Canvas API,可以在JavaFX场景上绘制。
  • 打印APl。 javafx.print包提供了JavaFX Printing API的类。
  • 富文本支持。JavaFX支持增强的文本,包括双向文本和复杂的文本脚本,例如泰语和印度教的控件,以及多行,多种风格的文本。
  • 多点触控支持,JavaFX提供对多点触摸操作的支持。
  • JavaFX支持Hi-DPI显示。

4、UI控件

以下列出了JavaFX API中提供的一些内置JavaFX UI控件:

  • Label
  • Button
  • Radio Button
  • Toggle Button
  • Checkbox
  • ChoiceBox
  • Text Field
  • Password Field
  • Scroll Bar
  • Scroll Pane
  • List View
  • Table View
  • Tree View
  • Tree Table View
  • Combo Box
  • Separator
  • Slider
  • Progress Bar
  • Progress Indicator
  • Hyperlink
  • Tooltip
  • HTML Editor
  • Titled Pane
  • AccordionMenu
  • Color Picker
  • Date Picker
  • Pagination Control
  • File Chooser

JavaFX允许UI控制节点和形状节点在场景图上共存。
我们可以像任何其他JavaFX节点一样处理任何UI控件,例如可以缩放,旋转,样式和添加效果。


二、JavaFx概述

1、JavaFx结构图

一般来说,JavaFX应用程序包含一个或多个对应于窗口的阶段。每个阶段都有一个场景。每个场景都可以有一个控件、布局等附加到它的对象图,称为场景图。这些概念都将在后面更详细地解释。下面是JavaFX应用程序的般结构的图示:
image.png
image.png

2、JavaFx组件

(1)舞台

舞台是JavaFX应用程序的外部框架。舞台通常对应于一个窗口。在 JavaFX 可以在浏览器中运行的早期阶段,舞台还可以指网页内 JavaFX 可用于绘制自身的区域。
由于 Java 浏览器插件的弃用,JavaFX 主要用于桌面应用程序。在这里,JavaFX 取代了 Swing 作为推荐的桌面GUI 框架。而且JavaFX 看起来比 Swing 更加一致且功能丰富。
在桌面环境中使用时,JavaFX 应用程序可以打开多个窗口。每个窗口都有自己的舞台。
每个阶段都由StageJavaFX 应用程序中的一个对象表示。StageJavaFX 应用程序有一个由JavaFX 运行时为您创建的主对象。如果 JavaFX 应用程序Stage需要打开其他窗口,它可以创建其他对象。例如,对于对话框、向导等。

(2)场景

要在JavaFX 应用程序的舞台上显示何内容,您需要一个场景。一个舞台一次只能显示一个场景,但可以在运行时交换场景。就像剧院中的舞台可以重新安排以在戏剧期间显示多个场景一样,JavaFX 中的舞台对象可以在JavaFX 应用程序的生命周期内显示多个场景 (一次一个) 。
您可能想知道为什么 JavaFX 应用程序的每个阶段会有多个场景。想象一个电脑游戏。一个游戏可能有多个“屏幕”向用户显示。例如,初始菜单屏幕、主游戏屏幕(玩游戏的地方)、游戏结束屏幕和高分屏幕。这些屏幕中的每一个都可以由不同的场景来表示。当游戏需要从一屏切换到下一屏时,它只需将相应的场景附加到StageJavaFX 应用程序的对象上即可。
场景由SceneJavaFX 应用程序中的对象表示。JavaFX 应用程序必须创建Scene它需要的所有对象。

① 场景图

所有视觉组件(控件、布局等)都必须附加到要显示的场景,并且该场景必须附加到舞台才能使整个场景可见。附加到场景的所有控件、布局等的总对象图称为场景图。

② 节点

附加到场景图的所有组件都称为节点。所有节点都是JavaFX 类的子类,称为javafx.scene.Node。
有两种类型的节点:分支节点和叶节点。分支节点是可以包合其他节点(子节点)的节点。分支节点也称为父节点,因为它们可以包含子节点。叶节点是不能包含其他节点的节点。

(3)控件

JavaFX 控件是 JavaFX 组件,它们在JavaFX 应用程序中提供某种控制功能。例如,按钮、单选按钮、表格、树
为了使控件可见,它必须附加到某个Scene对象的场景图中。
控件通常嵌套在一些 JavaFX 布局组件中,这些组件管理控件相对于彼此的布局。
JavaFX 包含以下控件:

  • 手风琴
  • 按钮
  • 复选框
  • 选择框
  • 选色器
  • 组合框
  • 日期选择器
  • 标签
  • 列表显示
  • 菜单
  • 菜单栏
  • 密码字段
  • 进度条
  • 单选按钮
  • 滑块
  • 微调器
  • 拆分菜单按钮
  • 拆分窗格
  • 表视图
  • 选项卡窗格
  • 文本区域
  • 文本域
  • 标题窗格
  • 切换按钮
  • 工具栏
  • 树表视图
  • 树视图

这些控件中的每一个都将在单独的文本中进行解释。

(4)布局

JavaFX 布局是其中包含其他组件的组件。布局组件管理嵌套在其中的组件的布局。JavaFX 布局组件有时也称为父组件,因为它们包含子组件,而且布局组件是JavaFX 类的子类javafx.scene.Parent。
布局组件必须附加到某个Scene对象的场景图才能可见。
JavaFX 包含以下布局组件:

  • 团体
  • 地区
  • 窗格
  • HBox
  • 盒子
  • 流窗格
  • 边框窗格
  • 边框窗格
  • 堆栈窗格
  • 瓷砖窗格
  • 网格窗格
  • 锚点窗格
  • 文本流

这些布局组件中的每一个都将在单独的文本中进行介绍。

(5)图表

JavaFX 带有一组内置的即用型图表组件,因此您不必每次需要基本图表时都从头开始编写图表代码。
JavaFX 包含以下图表组件:

  • 面积图
  • 条形图
  • 气泡图
  • 折线图
  • 饼形图
  • 散点图
  • 堆积面积图
  • 堆积条形图

(6)2D图形

JavaFX 包含可以轻松在屏幕上绘制2D 图形的功能。

(7)3D图形

JavaFX 包含可以轻松在屏幕上绘制 3D 图形的功能。

(8)声音

JavaFX 包含使在 JavaFX 应用程序中播放音频变得容易的功能。这通常在游戏或教育应用中很有用。

(9)视频

JavaFX 包合使在 JavaFX 应用程序中播放视频变得容易的功能。这通常在流媒体应用程序、游戏或教育应用程序中很有用。

JavaFX 包含一个WebView能够显示网页 (HTML5、CSS 等)的组件。JavaFXWebView组件基于 WebKit-Chrome 和 Safari 中也使用的网页染引擎。
该WebView组件使得将桌面应用程序与 Web 应用程序混合成为可能。有时这很有用。例如,如果您已经有一个不错的 Web 应用程序,但需要一些只有桌面应用程序才能提供的功能一一例如磁盘访问、与 HTTP 以外的其他网络协议 (例如 UDP、IAP 等) 的通信。


三、JavaFx快速入门

JavaFx中文官方网站:https://openjfx.cn/

1、IDEA配置JavaFx环境

JDK8集成了JavaFx,而JDK11后就不自带JavaFx了,需要自己下载jar包进行导入。
如果使用的是Java8,请直接跳到下面第二步。

2、编码与运行

image.png
创建以下包目录结构、主入口Main类:
image.png
编写一个JavaFx基本结构代码:

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

// 继承Application抽象类,重新start方法
public class Main extends Application {
    public static void main(String[] args) {
        // 入口函数里调用Application的静态方法launch,之后会自动调用start方法
        Application.launch(args);
    }

    /**
     * @param primaryStage 主窗口
     */
    @Override
    public void start(Stage primaryStage) throws Exception {
        // 设置一个场景,场景里添加一个树形组件图,先创建一个标签
        Label label = new Label("Hello JavaFx!");
        // 创建布局,将标签放入布局里,BorderPane布局把场景划分为上下左右中,默认加入的控件在中间位置
        BorderPane pane = new BorderPane(label);
        // 创建场景,将布局放入场景里,设置宽度和高度
        Scene scene = new Scene(pane, 300, 300);
        // 将场景设置到窗口里
        primaryStage.setScene(scene);
        // 设置标题
        primaryStage.setTitle("我是窗口");
        primaryStage.show();
    }
}

运行main方法,测试结果:
image.png


四、组件功能介绍

1、Application

  1. Application是JavaFx程序的入口,任何JavaFx应用程序程序都要继承该类并重写start()方法。
public class Main extends javafx.application.Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
    }
}
  1. 通过main()执行Application的launch(String… args)方法,当然该方法不传入任何值也是可以执行的。launch()方法会默认执行本类下的init()、start()、stop()方法。执行下面的main()方法后显示顺序为:
import javafx.application.Application;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
        System.out.println("这是main方法");
    }

    @Override
    public void init() {
        System.out.println("这是初始化方法");
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.show();
        System.out.println("这是start()方法");
    }

    @Override
    public void stop() throws Exception {
        System.out.println("这个是stop()方法");
    }
}

可以看出只有当stop()方法被调用时(即Application应用程序被正常关闭,也可以是图形界面右上角的❌被点击时),launch()方法才执行完毕。(通过Platform.exit()退出界面也是属于正常退出)
通过IDE控制台终止应用程序属于非正常终止,它是通过关闭JVM从而关闭应用程序的。

  1. 也可以在其他类中的main()方法中调用launch()方法,但要传入相应的参数,第一个参数指定一个Application的子类,从而调用该类下的init()、start()、stop()方法,第二个参数制定一个String类型的值。

该方法launch(Class<? extends Application> appClass, String… args)也可以不指定String类型的值。

  1. Application类下的getHostServices()方法,该方法返回一个HostServices实例,该实例的showDocument()方法可以指定一个网站地址或者URI,从而以系统默认的浏览器打开该URI。getDocumentBase()返回一个String类型的当前文档所在的路径。
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        HostServices hostServices = getHostServices();
        hostServices.showDocument("www.baidu.com");
        System.out.println(hostServices.getDocumentBase());
    }
}

image.png

也可以写一个按钮,点击触发事件后弹出默认浏览器进入网站:

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

public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button button = new Button("点击进入百度");
        BorderPane pane = new BorderPane(button);
        button.setOnAction(e -> {
            getHostServices().showDocument("www.baidu.com");
        });
        Scene scene = new Scene(pane, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.setTitle("JavaFx App");
        primaryStage.show();
    }
}

image.png

另外线程方面,执行main()方法时是主线程,当调用init()方法时是JavaFX-Launcher线程,当调用start()方法时是JavaFX Application Thread线程,当调用stop()方法时依然是JavaFX Application Thread线程。
因此,我们可以在init()方法中做一些连接数据库等初始化工作,可与start()方法的不同线程同步进行,提高运行效率。


2、Stage舞台(窗口)

JavaFx Stage:javafx.stage.Stage表示JavaFx桌面应用程序中的窗口。在JavaFx中,窗口Stage可以插入一个场景Scene,它表示在窗口内显示的内容。
当JavaFx应用程序启动时,它会创建一个根Stage对象,该对象将传递给 start(Stage primaryStage) JavaFx应用程序的根类的方法。此Stage对象代表JavaFx应用程序的主窗口。您可以在应用程序生命周期的后期创建新Stage对象,以防应用程序需要打开更多窗口。

(1)创建舞台

像创建任何其他Java对象一样创建Stage对象:

Stage stage = new Stage();

(2)展示舞台

简单地创建Stage对象不会显示它,为了使Stage可见,必须调用它的show()或showAndWait()方法:

Stage stage = new Stage();
stage.show();

(3)在舞台上设置场景

JavaFX在Stage中显示任何场景内容,必须在Stage显示前将Scene创建,并设置在Stage中:

VBox VBox = new VBox(new Label("A JavaFx Label"));
Scene scene = new Scene(vBox);

Stage stage = new Stage();
stage.setScene(scene);
// ...
// stage.show();

(4)舞台标题

通过setTitle()方法设置Stage标题,将显示在Stage窗口的标题栏中:

stage.setTitle("JavaFx stage window Title");

(5)舞台位置

通过其setX()和setY()方法设置窗口左上角的位置(X, Y),即启动后窗口在屏幕中的坐标:

stage.setX(100);
stage.setY(100);

注意,如果设置X和Y位置,可能还需要设置宽度和高度,否则舞台窗口可能会变得非常小。

(6)舞台宽度和高度

通过其setWidth()和setHeight()方法,设置JavaFx的宽度和高度:

stage.setWidth(600);
stage.setHeight(300);

一般我们不需要单独设置舞台宽高,只需通过场景的宽高设置来影响舞台的宽高。

(7)舞台风格

通过其initStyle()方法,参数为枚举类StageStyle设置JavaFx的样式,可以选择一组不同的样式:

  • DECORATED:默认装饰Stage是带有操作系统装饰(标题栏和最小化/最大化/关闭按钮)和白色背景的标准窗口。
  • UNDECORATED:未装饰Stage是没有操作系统装饰的标准窗口,但仍具有白色背景。
  • TRANSPARENT:透明Stage是具有透明背景的未装饰窗口。
  • UNIFIED:统一Stage就像一个装饰的舞台,只是装饰区域和主要内容区域之间没有边界。
  • UTILITY:实用程序Stage是装饰过的窗口,但装饰最少。
stage.initStyle(StageStyle.DECORATED);	// 默认窗口样式
//stage.initStyle(StageStyle.UNDECORATED);	// 无装饰窗口样式,自定义窗口时常用
//stage.initStyle(StageStyle.TRANSPARENT);	// 透明窗口样式,与无装饰类似
//stage.initStyle(StageStyle.UNIFIED);	// 和默认窗口效果差不多
//stage.initStyle(StageStyle.UTILITY);	// 简单窗口样式,只有Title和关闭

(8)舞台全屏模式

通过其setFullScreen()方法将窗口设置为全屏模式:

stage.setFullScreen(true);

(9)阶段生命周期事件

Stage可以发出一些可以监听的事件,这些舞台事件是:

Close Request
Hiding
Hidden
Showing
Shown

关闭阶段事件监听器
可以在舞台上侦听关闭事件,当用户单击舞台窗口右上角的关闭按钮时,触发回调事件。
如需要在主Stage窗口关闭后清理一些资源、停止一些线程等。监听Stage关闭事件会很有用:

stage.setOnCloseRequest(event -> System.out.println("closing stage"));
  • 小案例:设置关闭窗口监听事件,当用户单击舞台窗口右上角的关闭按钮时,触发回调事件弹出确认框,点击确认后关闭窗口,点击取消不做动作。
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.stage.Stage;

import java.util.Optional;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        // 设置关闭窗口的监听事件,首先操作系统默认的关闭事件取消掉
        Platform.setImplicitExit(false);    // 取消操作系统默认退出事件,点击关闭后系统不结束运行
        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();    // 退出程序
                primaryStage.close(); // 仅关闭窗口,不退出程序
            }
        });
        primaryStage.setTitle("设置关闭窗口的监听事件Demo");
        primaryStage.show();
    }
}

(10)键盘或鼠标事件

可以在Stage上设置侦听键盘事件,可以捕获在舞台具有焦点时发生的所有键盘事件。

stage.addEventHandler(KeyEvent.KEY_PRESSED, e -> System.out.println("键盘按下的键:" + e.getCode().getName()));
stage.addEventHandler(MouseEvent.MOUSE_PRESSED, e -> System.out.println("鼠标按下的键:" + e.getButton()));
  • 小案例:WASD控制图片移动
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

import java.io.FileInputStream;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("WASD控制图片移动");
        stage.getIcons().add(new Image("images/测试图片.png"));
        FileInputStream input = new FileInputStream("src/resources/images/测试图片.png");
        Image image = new Image(input);
        ImageView imageview = new ImageView(image);
        imageview.setFitWidth(100);
        imageview.setFitHeight(100);

        Group group = new Group(imageview);
        Scene scene = new Scene(group, 600, 600);
        stage.setScene(scene);

        stage.addEventHandler(KeyEvent.KEY_PRESSED, event -> {
            if ("W".equals(event.getCode().getName())) {
                imageview.setLayoutY(imageview.getLayoutY() - 10);
            }
            if ("S".equals(event.getCode().getName())) {
                imageview.setLayoutY(imageview.getLayoutY() + 10);
            }
            if ("A".equals(event.getCode().getName())) {
                imageview.setLayoutX(imageview.getLayoutX() - 10);
            }
            if ("D".equals(event.getCode().getName())) {
                imageview.setLayoutX(imageview.getLayoutX() + 10);
            }
        });

        stage.show();
    }
}

效果图:
image.png


3、Scene场景

场景对象是场景图的根。换句话说,场景包含其中的所有可视的GUI组件。场景由类表示javafx.scene.Scene。必须在Stage上设置Scene对象才能可见。
场景图是一种树状数据结构,用于排列(和分组)图形对象,以便于逻辑表示。它还允许图形引擎通过完全或部分跳过最终图像中看不到的对象,以最有效的方式渲染对象。下图显示了JavaFX场景图体系结构的一个示例:
image.png

(1)创建场景

Scene您可以通过其构造函数创建对象。需要传递根组件作为参数,下面是创建Scene对象的示例:

VBox vBox = new VBox();
Scene scene = new Scene(vBox);

(2)在舞台上设置场景

为了使Scene可见,必须在Stage上设置它:

VBox vBox = new VBox(new Label("A JavaFx Label"));
Scene scene = new Scene(vBox);

Stage stage = new Stage();
stage.setScene(scene);

注意:Stage一次只能显示一个Scene。

(3)场景鼠标光标

可以在Scene上设置鼠标光标。鼠标光标是显示在鼠标光标(指针)位置的小图标。Scene您可以通过setCursor()方法设置鼠标的光标。

  • 小案例:设置两个场景,通过按钮绑定事件,实现场景和鼠标光标的互相转换:
public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button button0 = new Button("点击切换场景");
        button0.setLayoutX(200);
        button0.setLayoutY(200);
        AnchorPane root = new AnchorPane();
        root.getChildren().add(button0);
        Scene scene = new Scene(root, 500, 500);
        scene.setCursor(new ImageCursor(new Image("images/测试图片1.png")));

        Label label = new Label("你好,JavaFx");
        label.setLayoutX(200);
        label.setLayoutY(200);
        Button button1 = new Button("返回原场景");
        button1.setLayoutX(200);
        button1.setLayoutY(250);
        AnchorPane root1 = new AnchorPane();
        root1.getChildren().addAll(label, button1);
        Scene scene1 = new Scene(root1, 500, 500);
        scene1.setCursor(new ImageCursor(new Image("images/测试图片2.png")));

        button0.setOnAction(event -> {
            primaryStage.setScene(scene1);
        });

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

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

效果图:鼠标光标图片也会切换
image.png

image.png


4、Node节点 UI控件的通用属性

Node类是所有控件的父类,下面通过其控件子类示例演示Node节点的UI控件的通用属性。

(1)控件节点坐标系

每个 JavaFX 节点都有自己的笛卡尔坐标系。与常规笛卡尔坐标系的唯一区别是Y轴是相反的。也就是说,坐标系的原点在坐标系的左上角。随着Y值的增加,该点从坐标系的顶部向下移动。Y轴的这种反转在2D图形坐标系中是正常的。

image.png

JavaFX 节点可能具有负X和Y坐标。
每个节点都有自己的坐标系。此坐标系用于在父节点内定位子节点实例,或者在 JavaFX 画布上绘图时。这意味着,作为另一个节点的子节点的节点都有自己的坐标系,以及在其父节点坐标系中的位置 (X,Y)。
以下是父节点坐标系的示例,其中子节点位于父节点坐标系中的(25,25)处。子节点也有它自己的坐标系,它有它的 (0,0),其中子节点位于父坐标系中-意思是在父节点坐标系中的(25,25)。
image.png

(2)设置控件坐标

Label label = new Label("你好,JavaFx");
label.setLayoutX(200);  // 设置控件X轴坐标
label.setLayoutY(200);  // 设置控件Y轴坐标

(3)设置控件风格

与css语法类似,只是前面加上-fx,设置红色背景,蓝色边框和边框宽度为3个像素:

label.setStyle("-fx-background-color: red; -fx-border-color: blue; -fx-border-width: 3px"); // 设置控件风格,与css语法类似,只是前面加上-fx

(4)设置控件首要背景宽度和高度

label.setPrefWidth(200);    // 设置控件背景宽度
label.setPrefHeight(50);    // 设置控件背景高度

(5)设置文本居中

label.setAlignment(Pos.CENTER); // 设置文本居中

(6)设置是否显示/隐藏该控件

true:默认显示控件,false:隐藏控件

label.setVisible(false);    // 是否显示该控件

(7)设置控件半透明值

label.setOpacity(0.5);  // 设置控件半透明值

(8)设置控件旋转角度

label.setRotate(70);    // 设置控件旋转角度

(9)设置控件X轴和Y轴平移量

label.setTranslateX(60);    // 设置X轴平移量
label.setTranslateY(100);   // 设置Y轴平移量
  • 案例演示:
public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label("你好,JavaFx");
        label.setLayoutX(200);  // 设置控件X轴坐标
        label.setLayoutY(200);  // 设置控件Y轴坐标
        label.setStyle("-fx-background-color: red; -fx-border-color: blue; -fx-border-width: 3px"); // 设置控件风格,与css语法类似,只是前面加上-fx
        label.setPrefWidth(200);    // 设置控件背景宽度
        label.setPrefHeight(50);    // 设置控件背景高度
        label.setAlignment(Pos.CENTER); // 设置文本居中
        //label.setVisible(false);    // 是否显示该控件
        label.setOpacity(0.5);  // 设置控件半透明值
        label.setRotate(70);    // 设置控件旋转角度
        label.setTranslateX(60);    // 设置X轴平移量
        label.setTranslateY(100);   // 设置Y轴平移量
        AnchorPane root = new AnchorPane();
        root.getChildren().add(label);
        Scene scene = new Scene(root, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

image.png


5、UI控件的属性绑定和属性监听

  • 小案例:在场景中画一个圆,利用属性单向绑定,使拖动边框大小时,圆始终保持在中心位置。并且设置X轴属性监听器,使得横向拖动边框时,控制台打印移动数据值,而Y轴不设置属性监听,纵向拖动时不打印数据值。
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);

        Circle circle = new Circle();
        circle.setCenterX(250);
        circle.setCenterY(250);
        circle.setRadius(100);
        circle.setStroke(Color.BLACK);
        circle.setFill(Color.WHITE);
        // 设置属性单向绑定,使圆始终保持在中心位置
        circle.centerXProperty().bind(scene.widthProperty().divide(2));
        circle.centerYProperty().bind(scene.heightProperty().divide(2));

        // 设置X轴属性监听器
        circle.centerXProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                System.out.println("x轴中心点改变了,原来是:" + oldValue + ",现在是:" + newValue);
            }
        });

        root.getChildren().add(circle);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

image.png

image.png


6、JavaFx应用里的事件驱动编程

image.png

  • 小案例:利用事件驱动,实现将一个任意文件拖拽到文本框中后,拖拽时显示移动,拖拽松开后文本框显示文件的绝对路径。
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);
        TextField textField = new TextField();  // 文本框
        textField.setLayoutX(150);
        textField.setLayoutY(200);

        textField.setOnDragOver(event -> {
            event.acceptTransferModes(TransferMode.ANY);
        });

        textField.setOnDragDropped(event -> {
            Dragboard dragboard = event.getDragboard();
            if (dragboard.hasFiles()) {
                String path = dragboard.getFiles().get(0).getAbsolutePath();
                textField.setText(path);
            }
        });
        root.getChildren().add(textField);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png

image.png


7、Color、Font、Image

本介绍直接采用案例演示法,具体参数方法请参阅JavaFx API文档。

(1)Color颜色

  • 案例演示:利用Color类设置圆的边框颜色和内部填充颜色
public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);

        Circle circle = new Circle();
        circle.setCenterX(250); // 设置圆心X轴位置
        circle.setCenterY(250); // 设置圆心Y轴位置
        circle.setRadius(100);  // 设置半径
        //circle.setFill(Color.rgb(100, 50, 100));    // 设置内部填充颜色
        circle.setFill(Color.web("#f66a08"));   // 设置内部填充颜色,与CSS颜色语法一样
        circle.setStroke(Color.BLUE);  // 设置描边颜色
        circle.setStrokeWidth(10);    // 设置圆边框宽度

        root.getChildren().add(circle);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png

(2)Font字体

在C:\Windows\Fonts下可查阅系统字体。
image.png

image.png

  • 案例演示:为Label标签设置Font字体风格
public class Main12 extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);

        Label label = new Label("文本Font演示");
        label.setLayoutX(150);
        label.setLayoutY(150);
        //label.setFont(new Font(30));  // 设置字体
        label.setFont(Font.font("华文行楷", FontWeight.BOLD, 30));   // 参数:字体名称,字重(斜体,黑体,粗体等),字体大小


        root.getChildren().add(label);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png

(3)Image图片

Image图片支持BMP/GIF/JPEG/PNG

  • 案例演示:通过Image和ImageView类显示图片
public class Main13 extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);

        ImageView imageView = new ImageView();
        Image image = new Image("images/背景.png");
        imageView.setImage(image);

        root.getChildren().add(imageView);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png


五、FXML

FXML是一种可编写的、基于XML的用于构造JavaFX场景图的标记语言。在FXML中,一个FXML标签代表以下类型之一:

  • 某个类的实例
  • 某个类实例的属性
  • 某个静态属性
  • 一个定义代码块
  • 一个脚本代码块

一个FXML属性表示以下类型之一:

  • 某个类实例的属性
  • 某个静态属性
  • 事件处理程序

image.png
Introduction to FXML:https://openjfx.cn/javadoc/18/javafx.fxml/javafx/fxml/doc-files/introduction_to_fxml.html


1、FXML布局文件的使用

  • 案例演示:将下面的JavaFx文件代码中的容器、组件和监听事件,改写为FXML文件的格式,简化和方便管理JavaFx类的编写。
public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        AnchorPane root = new AnchorPane();
        Scene scene = new Scene(root, 500, 500);

        Label label = new Label("按键盘↓向下移动");
        label.setLayoutX(100);
        label.setLayoutY(150);
        label.setFont(new Font(30));
        Button button = new Button("点击按钮向上移动");
        button.setLayoutX(350);
        button.setLayoutY(200);

        button.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                label.setLayoutY(label.getLayoutY() - 5);
            }
        });

        scene.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent event) {
                KeyCode keyCode = event.getCode();
                if (keyCode.equals(KeyCode.DOWN)) {
                    label.setLayoutY(label.getLayoutY() + 5);
                }
            }
        });

        root.getChildren().addAll(label, button);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

改写为FXML:

public class Demo extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        // 使用FXMLLoader类的load方法来加载FXML文件,并将其与Controller类进行关联。
        //Pane root = FXMLLoader.load(getClass().getClassLoader().getResource("com/aizen/javafx/fxml/demo.fxml"));
        Pane root = FXMLLoader.load(getClass().getResource("demo.fxml"));
        Scene scene = new Scene(root, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

public class DemoController {
    @FXML
    Label la;

    @FXML
    Button bu;


    public void handleButtonAction() {
        la.setLayoutY(la.getLayoutY() - 5);
    }

    public void handleKeyReleased(KeyEvent event) {
        KeyCode keyCode = event.getCode();
        if (keyCode.equals(KeyCode.DOWN)) {
            la.setLayoutY(la.getLayoutY() + 5);
        }
    }
}
<?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.aizen.javafx.fxml.DemoController"
            onKeyReleased="#handleKeyReleased"
            prefHeight="400.0" prefWidth="600.0">
    <children>
        <Label fx:id="la" text="按键盘↓向下移动" layoutX="100" layoutY="150">
            <font>
                <Font size="30"/>
            </font>
        </Label>

        <Button fx:id="bu" text="点击按钮向上移动" layoutX="350" layoutY="200" onAction="#handleButtonAction"/>
    </children>
</AnchorPane>

2、Scene Builder里构建fxml布局文件

官方下载链接:https://openjfx.cn/scene-builder/
image.png

点击下一步,完成安装
image.png

选择空项目
image.png

布局和组件直接拖拽进场景即可,保存后可生成对应的fxml文件。
image.png


3、Controller里的initialize方法

有时我们是无法在fxml文件里填充数据的,并且有些内容需要初始化时就填充(如表格),而不是触发事件后填充,此时就可以使用initialize方法,做一些初始化的工作。

initialize()方法需要自定义,定义完之后会自动调用,该方法调用的时机是加载好fxml文件,并绑定好控件id之后,才会自动调用一次。

需要注意的是在initialize()方法中是无法访问Scene场景的。

  • 演示案例:使用initialize()方法初始化时填充完TableView的数据。
public class Main extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Pane root = FXMLLoader.load(getClass().getResource("hello.fxml"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

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

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}


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> cellDate = FXCollections.observableArrayList();
        name.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));
        age.setCellValueFactory(new PropertyValueFactory<Person, Integer>("age"));
        cellDate.add(new Person("张三", 18));
        cellDate.add(new Person("李四", 19));
        cellDate.add(new Person("王五", 23));
        cellDate.add(new Person("赵六", 15));
        tableView.setItems(cellDate);
    }
}

<?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="com.aizen.javafx.fxml_02.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" prefHeight="400.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>

效果图:
image.png


4、在Application里操作Controller

  • 案例演示:和之前圆的案例一样,要求圆的中心点自适应边框大小,使用fxml实现。
public class JavaFxApplication extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader();   // 使用FXMLLoader获取布局里面的Controller的引用
        fxmlLoader.setLocation(getClass().getResource("hello.fxml"));
        Parent root = fxmlLoader.load();
        Scene scene = new Scene(root);
        // 在Application中操作Controller进行属性绑定
        Controller controller = fxmlLoader.getController();
        controller.circleLocationBind(scene);

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

public class Controller {
    @FXML
    private Circle ci;

    public void circleLocationBind(Scene scene) {
        // 获得X和Y中心点的可绑定对象,设置中心点自适应边框大小
        ci.centerXProperty().bind(scene.widthProperty().divide(2));
        ci.centerYProperty().bind(scene.heightProperty().divide(2));
    }
}

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

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


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

效果图:
image.png

image.png


六、JavaFx多线程操作Platform.runLater

当我们执行一些耗时操作时,如加载资源。我们为了防止这些耗时操作占用JavaFx的主线程资源,下面的代码无法执行造成软件界面加载卡顿,我们通常使用JavaFx支持的多线程操作来解决这个问题。

  • 案例演示1:使用多线程技术实现点击Button按钮获取姓名数据(模拟数据库获取数据)显示在Label文字布局上。
public class Main extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label("姓名是?");
        label.setLayoutX(200);
        label.setLayoutY(350);
        Button button = new Button("点击获取姓名");
        button.setLayoutX(200);
        button.setLayoutY(400);
        button.setOnAction(event -> {
            new Thread(() -> {
                String name = "Aizen";	// 模拟数据库获取值的操作,这里直接定义
                label.setText(name);	// 更新UI控件的操作
            }).start();
        });
        AnchorPane pane = new AnchorPane();
        pane.getChildren().addAll(label, button);
        Scene scene = new Scene(pane, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

如果直接这样运行,点击后会报出非法状态异常,不在JavaFx的Application线程中,更新UI控件必须在Fx Application主线程中。
image.png

想要避免这个问题,需要使用到JavaFx提供的静态方法Platform.runLater(Runnable runnable),其中参数需要一个Runnber对象,runLater方法将Runnable放在任务队列里面,在Application线程空闲的时候,会执行队列里的任务。

public class Main0 extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Label label = new Label("姓名是?");
        label.setLayoutX(200);
        label.setLayoutY(350);
        Button button = new Button("点击获取姓名");
        button.setLayoutX(200);
        button.setLayoutY(400);
        button.setOnAction(event -> {
            // 报错案例:
            /*new Thread(() -> {
                String name = "Aizen";  // 模拟数据库获取值的操作,这里直接定义
                label.setText(name);    // 更新UI控件的操作
            }).start();*/
            
            // 正确案例:
            // runLater方法将Runnable放在任务队列里面,在Application线程空闲的时候,会执行队列里的任务
            new Thread(() -> {
                String name = "Aizen";  // 模拟数据库获取值的操作,这里直接定义
                Platform.runLater(() -> {
                    label.setText(name);    // 更新UI控件的操作
                });
            }).start();
        });
        AnchorPane pane = new AnchorPane();
        pane.getChildren().addAll(label, button);
        Scene scene = new Scene(pane, 500, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png

image.png

其实在JavaFx很多控件的事件里面都内部调用了runLater()方法,比如下面这个案例:

  • 案例演示2:使用多线程技术实现点击Button按钮通过url加载图片,并显示图片和加载进度(模拟耗时操作)。
public class Main1 extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        ImageView imageView = new ImageView();
        imageView.setLayoutX(100);
        imageView.setLayoutY(20);

        Label label = new Label();
        label.setLayoutX(400);
        label.setLayoutY(350);

        Button button = new Button("点击获取图片");
        button.setLayoutX(400);
        button.setLayoutY(410);

        button.setOnAction(event -> {
            // 通过url加载图片,这种操作可能会比较耗时通常会另开一个线程去执行,而不占用主线程
            Thread thread = new Thread(() -> {
                Image image = new Image("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F0a0caee4-4afd-4fbf-bcf8-8269315c7915%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1715148006&t=f254957770daea43b9b1f4cdb6c2c987", true);
                // 该监听器的changed方法在底层已经封装了Platform.runLater()方法
                image.progressProperty().addListener(new ChangeListener<Number>() {
                    @Override
                    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                        int process = (int) (newValue.doubleValue() * 100);
                        // 显示图片联网加载进度
                        label.setText("图片加载了:" + process + "%");
                    }
                });
                imageView.setImage(image);
            });

            thread.setName("线程1");
            thread.start();
        });
        AnchorPane pane = new AnchorPane();
        pane.getChildren().addAll(imageView, label, button);
        Scene scene = new Scene(pane, 950, 500);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

效果图:
image.png

image.png


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络安全产品---数据库防火墙/审计

数据库防火墙 防火墙的类型繁多&#xff0c;即使下一代防火墙或者说AI防火墙集成功能再多&#xff0c;我觉得waf与数据库防火墙也有其无法被替代的理由&#xff0c;以此记录我对数据库防火墙的理解 what 数据库防火墙是基于数据库协议分析与访问行为控制的数据库安全防护产品…

【QT学习】7.事件,把文本显示在页面中(文本可变),鼠标指针切换,鼠标左键右键按下,qt设置背景样式

0.创建项目&#xff0c;事件的创建 1.事件的位置 2.这就是多态&#xff0c;子类重写父类函数&#xff0c;子类调用子类函数&#xff0c;也可以调用父类函数。但同函数名 1.要求&#xff1a;文本显示在页面中&#xff08;文本可变&#xff09; 1.文本显示在页面的核心代码 主要步…

齐次变换矩阵、欧拉角

齐次变换矩阵 因为老是忘记齐次变换矩阵的含义以及方向&#xff0c;每次推导公式都很费劲&#xff0c;写下这篇文章用于快速回顾齐次变换矩阵。 表示的是&#xff1a;坐标系A到坐标系B的齐次变换矩阵&#xff0c;也是坐标系B在坐标系A下的位姿。 对于这个矩阵&#xff0c;有三…

万兆网络的十字路口:电口还是光模块?

&#x1f335;在构建高速、高效的网络系统时&#xff0c;选择正确的连接技术至关重要。万兆电口&#xff08;10GBASE-T&#xff09;和万兆光模块&#xff08;SFP&#xff09;是目前市场上两种主流的高速网络解决方案。它们各有优势&#xff0c;但在不同的应用场景和需求下&…

[阅读笔记18][CITING]LARGE LANGUAGE MODELS CREATE CURRICULUM FOR INSTRUCTION TUNING

这篇论文是23年10月提交到arxiv上的&#xff0c;也是用大模型蒸馏小模型的思路。 作者在这篇论文中提出了课程指令微调&#xff0c;大体流程如下图所示&#xff0c;教师模型给出一个问题&#xff0c;让学生模型回答一下&#xff0c;这时候学生回答大概率不够准确&#xff0c;这…

多因子模型的因子分组-克隆巴赫α系数

优质博文&#xff1a;IT-BLOG-CN 在建立我们的Alpha模型之前&#xff0c;我们得先知道什么是Alpha&#xff1f;Alpha是一条或者一系列能够预测股票走势的信息资讯组合。而这每一条非随机的信息资讯&#xff0c;我们称之为多因子模型的因子。多因子模型因子的选择需要避免系统性…

Lobechat 的基本使用流程

一、安装 下载lobechart的页面代码 $ git clone https://github.com/lobehub/lobe-chat.git $ cd lobe-chat $ pnpm install $ pnpm run dev注意&#xff1a;node环境要18以上 二、使用本地模型 1.安装ollama 2.通过ollama 下载本地模型 llama2&#xff08;选择合适的本地模型…

基于Springboot的职称评审管理系统

基于SpringbootVue的获取源码 联系方式 &#x1f447;&#x1f3fb;的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 评审条件 论坛信息 系统公告 后台登录…

多模态视觉语言模型:BLIP和BLIP2

1. BLIP BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation BLIP的总体结构如下所示&#xff0c;主要包括三部分&#xff1a; 单模态编码器&#xff08;Image encoder/Text encoder&#xff09;&#xff1a;分别进…

【6】mysql查询性能优化-关联子查询

【README】 0. 先说结论&#xff1a;一般用inner join来改写in和exist&#xff0c;用left join来改写not in&#xff0c;not exist&#xff1b;&#xff08;本文会比较内连接&#xff0c;包含in子句的子查询&#xff0c;exist的性能 &#xff09; 1. 本文总结自高性能mysql 6…

局域网无法连接怎么办?

局域网连接是我们日常生活和工作中常用的方式之一&#xff0c;但有时我们可能会遇到局域网无法连接的问题。这给我们的工作和生活带来了很大的困扰。本文将介绍局域网无法连接的常见原因&#xff0c;并推荐一款名为【天联】的组网产品&#xff0c;它能够解决不同地区间的局域网…

软件设计师软考中项学习(二)之计算机系统基础知识

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 学习目标学习内容学习笔记学习总结 学习目标 计算机系统硬件基本组成 中央处理…

开源博客项目Blog .NET Core源码学习(16:App.Hosting项目结构分析-4)

本文学习并分析App.Hosting项目中前台页面的文章专栏页面和文章详情页面。< 文章专栏页面 文章专栏页面总体上为左右布局&#xff0c;左侧显示文章列表&#xff0c;右侧从上向下为关键词搜索、分类导航、热门文章等内容。整个页面使用了layui中的面包屑导航、表单、模版、流…

【1425】java 外籍人员管理系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 外籍人员管理系统是一套完善的java web信息管理系统 采用serlvetdaobean&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff…

【从浅学到熟知Linux】基础IO第三弹=>文件系统介绍、软链接与硬链接(含磁盘结构、文件系统存储原理、软硬链接的创建、原理及应用详解)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 理解文件系统物理角度认识磁盘逻辑角度认识磁盘磁盘寻址磁盘中的寄存器 磁盘存储管理 软链接与硬链接软链接…

【AI自媒体制作】【AI工具】Midjourney中文站

Midjourney Midjourney中文站, MJ中文站 - 专业AI绘图网站 广场 绘画广场&#xff1a; 包含大量其他用户生成好的图片&#xff0c;可以自由保存。 视频广场&#xff1a; 普通用户目前只支持查看&#xff0c;无法下载 画夹广场&#xff1a; 有很多免费的画夹&#xff0c;比…

JS学习归纳8

这是JS基础学习的最后一部分&#xff0c;我们介绍一下简单数据类型和复杂数据类型。 一、 简单数据类型和复杂数据类型 如果有个变量我们以后打算存储为对象&#xff0c;暂时没想好放啥&#xff0c; 这个时候就给 null 1. 简单数据类型 是存放在栈里面 里面直接开辟一个空间存…

03 华三交换机的基础配置

用户登录设备后,直接进入用户视图。用户视图下可执行的操作主要包括查看操作、调试操作、文件管理操作、设置系统时间、重启设备、FTP和Telnet操作等。 从用户视图可以进入系统视图。系统视图下能对设备运行参数以及部分功能进行配置,例如配置夏令时、配置欢迎…

zabbix自定义监控、自动发现和注册以及代理设置

前言 监控项的定制和新设备的注册往往需要大量手动操作&#xff0c;这会导致维护成本的增加和监控效率的降低。本文将介绍如何利用 Zabbix 的自定义功能&#xff0c;实现监控项的动态发布和新设备的自动注册以及代理设置、从而简化运维工作并实现更高效的监控管理。 Zabbix 监…

Pytorch的下载安装

本文为自己整理的Pytorch下载相关的内容笔记&#xff0c;以便日后查阅 一. 基本命令 1.查看conda版本 conda --version2.创建conda新环境 conda create –n 名称 python版本3.查看已经创建的conda环境 conda info --envs4.进入虚拟环境 conda activate 环境名称 为了避免…