当前位置: 首页 > news >正文

【javaFX基础】javaFX文档学习及基础编程实践

一、知识点

1、节点、根节点、场景的设置

1、 Button button = new Button(  "切换按钮1");//建节点
2、AnchorPane pane =new AnchorPane();//建根节点
3、 pane.getChildren().add(button);//将节点包含在根节点中
4、Scene scene =new Scene(pane,500,500);//建场景,设置大小,将根节点包含在场景中
5、primaryStage.setScene(scene);//显示场景

2、图片资源加载

getClass().getResourceAsStream() 是Java标准库方法,专门用于从classpath加载资源,它理解/开头的路径表示从classpath根目录开始,返回的InputStream可以直接被Image构造函数使用。

InputStream is = getClass().getResourceAsStream("/image/6手指光标.png");
scene.setCursor(new ImageCursor(new Image(is, 32, 32, true, true)));

3、JavaFX参考资料

官网文档:
(1)JavaFX API 文档跳转链接,最权威的API文档,包含所有类、方法、属性的详细说明
(2)OpenJFX 官方网站跳转链接,入门指南、教程、示例代码
(3)Oracle JavaFX 教程和文档跳转链接,虽然基于Java 8,但大部分内容仍然适用

常用类文档链接:

(1)Node 类 (setLayoutX, setOpacity等)跳转链接,包含:setLayoutX(double)、setLayoutY(double)、setOpacity(double)、setCursor(Cursor)、其他所有节点通用方法
(2) Scene 类跳转链接,包含:构造函数、setCursor()、setRoot()、事件处理等
(3)Pane 和 Layout 类跳转链接

代码示例网站:
(1)JavaFX Examples:https://github.com/javafxports/openjdk-jfx/tree/master/apps
(2)TutorialsPoint: https:http:////www.tutorialspoint.com/javafx/index.htm
(3)Jenkov.com: http://tutorials.jenkov.com/javafx/index.html

推荐的学习顺序:

(1)先学基础: Node → Parent → Scene → Stage
(2)再学控件: Button, Label, TextField 等基础控件
(3)然后布局: Pane, HBox, VBox, BorderPane 等布局管理器
(4)最后高级: 表格、树形、图表等复杂控件

建议从官方文档开始,遇到具体问题再查阅详细的API说明。

4、javaFX文档怎么查

新手可能和我一样,虽然收藏了很多文档和笔记的链接,但是这些资料之间有什么关联?怎么系统学习?零零散散地了解总如荒海觅洲,不知道目前学到哪里,未来还有哪些要学,每每遇到问题总是重新发起询问,收藏夹里的方法完美隐藏,当点击收藏时才发现曾经已经来过.......

 

再次感谢deepseek的解答!帮助了我更好了解文档的结构和内容:

javafx.base       // 数据绑定、属性系统
javafx.graphics   // 场景图、图形、效果
javafx.controls   // UI控件 (重点!)
javafx.fxml       // FXML相关
javafx.web        // Web组件
javafx.media      // 音视频

可以通过以下路径来定位需要的类,例如Button:
(1)访问官方文档:首先进入JavaFX某个模块的主页,例如控件的模块主页:https://openjfx.cn/javadoc/22/javafx.controls/module-summary.html。
(2)进入包(Package)视图:在模块主页中,找到并点击 "Packages" 部分。所有具体的类都按功能组织在不同的包里。
(3)找到具体类(Class):在包列表中,点击 javafx.scene.control,即可进入该包的摘要页,这里列出了所有可用的UI控件,包括Button、Label、TextField等。

搜索技巧:
(1)利用页面内搜索:进入具体的包或类页面后,可以使用浏览器自带的页面搜索功能(通常是 Ctrl+F 或 Cmd+F)快速定位方法或属性。
(2)类的继承关系:JavaFX拥有一个清晰的类继承结构。Node类是所有场景图节点的基类,因此很多通用属性(如layoutX、layoutY、opacity)和方法都在Node类中定义。
(3) 查找事件处理:在类的文档中,关注以 setOn... 开头的方法(例如 setOnAction、setOnMouseClicked),这些通常就是设置事件监听器的方法

控件、属性、方法、事件、监听的关系:

控件 (Control)↓ 包含
属性 (Properties) + 方法 (Methods)↓ 关联
事件 (Events) ← 监听 (Listeners)

控件 (Control) - 实体对象
属性 (Properties) - 控件的状态(在文档中查找: "Property Summary")
方法 (Methods) - 控件的行为(在文档中查找: "Method Summary")
事件 (Events) - 发生的事情(在文档中查找: "setOnXXX" 方法)
监听 (Listeners) - 响应事件的代码

Button btn = new Button();           // 1. 创建控件
btn.setText("保存");                 // 2. 设置属性// 3. 设置事件监听
btn.setOnAction(event -> {          // 4. 事件: ActionEvent// 5. 监听器: 这里的Lambda表达式String fileName = "document.txt";btn.setText("已保存: " + fileName); // 属性变化
});// 6. 属性变化监听
btn.textProperty().addListener((obs, oldText, newText) -> {System.out.println("按钮文本变化: " + oldText + " → " + newText);
});

二、问题及解决方法

1、问题描述
图片路径正确,但仍报错报错“Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found at javafx.graphics/javafx.scene.image.Image.validateUrl(Image.java:1119)
    ... 11 more.Exception running application cc.caiguang.hello.Main”

解决方法:

将:

scene.setCursor(new ImageCursor(new Image( "/image/5红蓝圈光标.png")));
scene2.setCursor(new ImageCursor(new Image( "file:image/6手指光标.png")));

替换为(使用InputStream):

String possiblePaths="/image/5红蓝圈光标.png";
String possiblePaths2="/image/6手指光标.png";
InputStream is = getClass().getResourceAsStream(possiblePaths);
InputStream is2 = getClass().getResourceAsStream(possiblePaths2);
scene.setCursor(new ImageCursor(new Image(is, 32, 32, true, true)));
scene2.setCursor(new ImageCursor(new Image(is2, 32, 32, true, true)));

原因分析:这两种方式的区别在于资源加载机制和路径解析的不同!

原方式:JavaFX的Image构造函数会将字符串直接作为URL处理,它期望一个完整的URL(如"http://example.com/image.png")或一个file:协议路(如"file:/path/to/image.png"),但对于classpath资源,它无法直接识别/image/...这种路径

修改后:getClass().getResourceAsStream() 是Java标准库方法,专门用于从classpath加载资源,它理解/开头的路径表示从classpath根目录开始,返回的InputStream可以直接被Image构造函数使用。完整代码见模块三的实践测试2。

三、实践测试

1、页面跳转

在scene与scene2能通过点击场景的按钮相互跳转

package cc.caiguang.hello;
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.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.stage.StageStyle;
import org.w3c.dom.ls.LSOutput;
import java.util.Optional;public class Main extends Application{public static void main(String[] args){Application.launch(args);}@Overridepublic void start(Stage primaryStage) throws Exception{Button button = new Button(  "切换按钮1");Button button2 = new Button(  "弹窗按钮");button.setLayoutX(200);button.setLayoutY(300);button2.setLayoutX(200);button2.setLayoutY(350);Label label =new Label( "你好,JavaFX");label.setLayoutY(250);label.setLayoutX(200);Button button3 = new Button(  "切换按钮2");button3.setLayoutX(200);button3.setLayoutY(300);AnchorPane pane =new AnchorPane();AnchorPane pane2 =new AnchorPane();pane.getChildren().addAll(button,button2);pane2.getChildren().addAll(label,button3);Scene scene =new Scene(pane,500,500);Scene scene2 =new Scene(pane2,  500,500);button.setOnAction(e ->{//切换到界面2primaryStage.setScene(scene2);});button2.setOnAction(e ->{//点击出现新窗口Stage stage= new Stage();stage.setHeight(200);stage.setWidth(300);stage.initOwner(primaryStage);stage.initModality(Modality.APPLICATION_MODAL);//WINDOW_MODAL可移动按钮1弹出的窗口,APPLICATION_MODAL不能stage.show();});button3.setOnAction(e ->{//切换到界面1primaryStage.setScene(scene);});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.setScene(scene);primaryStage.setTitle("World");primaryStage.getIcons().add(new Image("Image/4红标.png"));primaryStage.setResizable(false);//固定窗口大小primaryStage.show();}@Overridepublic void init() throws Exception{super.init();System.out.println("init()...");}@Overridepublic void stop()throws Exception {super.stop();System.out.println("stop()...");}
}

2、跳转页面的光标样式
  

package cc.caiguang.hello;
import javafx.application.Platform;
import javafx.scene.Cursor;
import javafx.scene.ImageCursor;
import javafx.scene.Parent;
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.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.stage.StageStyle;
import org.w3c.dom.ls.LSOutput;import java.io.InputStream;
import java.util.Optional;public class Main extends Application{public static void main(String[] args){Application.launch(args);}@Overridepublic void start(Stage primaryStage) throws Exception{Button button = new Button(  "切换按钮1");Button button2 = new Button(  "弹窗按钮");button.setLayoutX(200);button.setLayoutY(300);button2.setLayoutX(200);button2.setLayoutY(350);Label label =new Label( "你好,JavaFX");label.setLayoutY(250);label.setLayoutX(200);Button button3 = new Button(  "切换按钮2");button3.setLayoutX(200);button3.setLayoutY(300);AnchorPane pane =new AnchorPane();AnchorPane pane2 =new AnchorPane();pane.getChildren().addAll(button,button2);pane2.getChildren().addAll(label,button3);Scene scene =new Scene(pane,500,500);Scene scene2 =new Scene(pane2,  500,500);// 使用测试程序setCustomCursor时取消以下注释符号//setCustomCursor(scene);//setCustomCursor(scene2);String possiblePaths="/image/5红蓝圈光标.png";String possiblePaths2="/image/6手指光标.png";InputStream is = getClass().getResourceAsStream(possiblePaths);InputStream is2 = getClass().getResourceAsStream(possiblePaths2);scene.setCursor(new ImageCursor(new Image(is, 32, 32, true, true)));scene2.setCursor(new ImageCursor(new Image(is2, 32, 32, true, true)));//scene.setCursor(new ImageCursor(new Image( "/image/5红蓝圈光标.png")));//此写法存在问题,使用上述InputStream方法button.setOnAction(e ->{//切换到界面2primaryStage.setScene(scene2);});button2.setOnAction(e ->{//点击出现新窗口Stage stage= new Stage();stage.setHeight(200);stage.setWidth(300);stage.initOwner(primaryStage);stage.initModality(Modality.APPLICATION_MODAL);//WINDOW_MODAL可移动按钮1弹出的窗口,APPLICATION_MODAL不能stage.show();});button3.setOnAction(e ->{//切换到界面1primaryStage.setScene(scene);});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.setScene(scene);primaryStage.setTitle("World");//primaryStage.getIcons().add(new Image("Image/4红标.png"));primaryStage.setResizable(false);//固定窗口大小primaryStage.show();}/* 测试程序private void setCustomCursor(Scene scene) {// 先测试一个简单的系统光标//scene.setCursor(Cursor.CROSSHAIR);//System.out.println("系统光标测试成功");// 然后尝试自定义光标String[] possiblePaths = {"/image/5红蓝圈光标.png","/resources/image/5红蓝圈光标.png","image/5红蓝圈光标.png"};for (String path : possiblePaths) {try {System.out.println("尝试路径: " + path);InputStream is = getClass().getResourceAsStream(path);if (is != null) {Image cursorImage = new Image(is, 32, 32, true, true);if (!cursorImage.isError()) {scene.setCursor(new ImageCursor(cursorImage));System.out.println("成功使用路径: " + path);return;}}} catch (Exception e) {System.out.println("路径 " + path + " 失败: " + e.getMessage());}}System.out.println("所有路径尝试失败,使用默认光标");scene.setCursor(Cursor.DEFAULT);}*/@Overridepublic void init() throws Exception{super.init();System.out.println("init()...");}@Overridepublic void stop()throws Exception {super.stop();System.out.println("stop()...");}
}

3、监听事件

(1)按钮图标监听事件
(2)键盘向下按键监听事件
(3)拖拽文件,文本框显示该文件绝对路径

package cc.caiguang.hello;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.ImageCursor;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.Dragboard;
import javafx.scene.input.KeyCode;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.application.Application;
import javafx.stage.StageStyle;
import org.w3c.dom.ls.LSOutput;import java.io.InputStream;
import java.util.Optional;public class Main extends Application{public static void main(String[] args){Application.launch(args);}@Overridepublic void start(Stage primaryStage) throws Exception {AnchorPane root=new AnchorPane();Scene scene = new Scene(root,500, 500);Label label = new Label( "Hello World");label.setLayoutX(200);label.setLayoutY(200);Button button = new Button( "向上移动");button.setLayoutX(300);button.setLayoutY(200);root.getChildren().addAll(label,button);//按钮图标监听事件button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent actionEvent) {label.setLayoutY(label.getLayoutY()-5);}});//键盘向下按键监听事件scene.setOnKeyReleased(event ->{KeyCode keyCode = event.getCode();if(keyCode.equals(KeyCode.DOWN)) {label.setLayoutY(label.getLayoutY()+5);}});//拖拽文件,文本框显示该文件绝对路径TextField textField = new TextField();textField.setLayoutX(100);textField.setLayoutY(100);textField.setMinWidth(300);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();}@Overridepublic void init() throws Exception{super.init();System.out.println("init()...");}@Overridepublic void stop()throws Exception {super.stop();System.out.println("stop()...");}
}

四、参考链接

1、问题1解决方法:https://blog.csdn.net/qq_44018692/article/details/127255765
(加path在路径前,但是我试过虽然运行不报错,但图标没有按需替换)

2、CSS使用教程:https://www.runoob.com/css/css-tutorial.html

3、javaFX样式:https://openjfx.cn/javadoc/24/javafx.graphics/javafx/scene/doc-files/cssref.html

4、javaFX笔记(博主NolanKy):https://blog.csdn.net/weixin_45644335/article/details/106712103

http://www.dtcms.com/a/486671.html

相关文章:

  • [c++语法学习]Day10:c++引用
  • iOS App 上架全流程详解:证书配置、打包上传、审核技巧与跨平台上架工具 开心上架 实践
  • C++设计模式_行为型模式_迭代器模式Iterator
  • [iOS] KVC 学习
  • 网站开发中用到的英文单词舅舅建筑网
  • 怎么做交易网站seo整体优化
  • 基于卷积神经网络的苹果叶片病虫害识别系统,resnet50,vgg16,resnet34【pytorch框架,python代码】
  • 【计算机组成原理】第七章:输入/输出系统
  • 深入理解 Linux NUMA:拓扑、分配策略与调优实践
  • logstash常遇问题(logstash Address already in use 5044)
  • 断点调试介绍与使用案例
  • Kafka在美团数据平台的实践
  • 【完整源码+数据集+部署教程】Aura棕榈油果实分割系统: yolov8-seg-C2f-DCNV2-Dynamic
  • 蛋白表达标签:提升重组蛋白研究与生产的关键工具
  • 网站备案编号查询wordpress 集成paypal
  • 数学口算练习抖音快手微信小程序看广告流量主开源
  • 【开题答辩过程】以《泰山珍稀动植物信息管理平台的设计与实现》为例,不会开题答辩的可以进来看看
  • wordpress 淘宝客页面seo网络培训班
  • 哪些公司做网站wordpress单选框php
  • 什么是程序计数器?
  • GEO实战之GEO 在营销生态中的定位:社交媒体、PR、内容营销的整合策略
  • 10.13 Tabs选项卡布局
  • 深圳比较好网站制作公司有哪些设置wordpress网页私有
  • seo1视频发布会优化关键词的公司
  • Uniapp微信小程序开发:onPullDownRefresh
  • 如何优化CMS的缓存机制?
  • h5游戏免费下载:Emoji自定义表情编辑器
  • AbMole小课堂丨重组R-spondin-3(RSPO3)的作用机理及其在类器官和干细胞研究中的应用
  • springboot 实现websocket通信
  • 深度学习实战:python动物识别分类检测系统 计算机视觉 Django框架 CNN算法 深度学习 卷积神经网络 TensorFlow 毕业设计(建议收藏)✅