JavaGUI---JavaFX---未完結

一、Java事件處理機制的應用

JavaFX:JavaFX是Java平臺上的一個GUI工具包,它提供了一些內置的事件處理機制。

Swing:Swing是Java平臺上的另一個GUI工具包,它也提供了一些內置的事件處理機制。

二、JavaFX和Swing的關鍵區別:

以下是JavaFX和Swing之間的一些關鍵區別:

  • JavaFX是比Swing更新的技術,旨在最終取代它。
  • JavaFX旨在比Swing更現代和視覺上更吸引人,支持動畫、3D圖形和其他高級功能。
  • JavaFX使用場景圖模型進行渲染,而Swing使用更傳統的基于小部件的方法。
  • JavaFX比Swing更好地支持CSS樣式,使創建視覺上一致的UI更容易。
  • JavaFX比Swing更好地支持多媒體和Web內容。

三、 使用idea創建JavaFX應用

在這里插入圖片描述
BootstrapFX:https://github.com/kordamp/bootstrapfx

提供特殊的CSS樣式表用于美化JavaFX的GUI

ControlsFX:https://controlsfx.github.io/ 提供更多JavaFX中沒有的組件

FormsFX:https://github.com/dlsc-software-consulting-gmbh/FormsFX/ 可以快速創建和設計表單

FXGL:https://github.com/AlmasB/FXGL?tab=readme-ov-file

Ikonli:https://kordamp.org/ikonli/

圖標包

TilesFX:https://github.com/HanSolo/tilesfx?tab=readme-ov-file
游戲開發框架

ValidatorFX: https://github.com/effad/ValidatorFX

用于表單驗證等

三、筆記

本筆記大部分根據此視頻整理:https://www.bilibili.com/video/BV1Qf4y1F7Zv/?spm_id_from=333.337.search-card.all.click&vd_source=4085910f7c5c4dddcc04446ebf3aed6b

1. 基本機構

在這里插入圖片描述

一個javaFX程序一般會有一個或多個窗口(Stage類的實例),
窗口可以設置一個場景(Scene類的實例),窗口可以切換不同的場景,但是一次只能設置一個,每個場景中可以添加一個或多個節點(node),每個node中也可以嵌套多個(node),node需有一個根節點

基本代碼結構

Test就相當于程序的入口類,這個入口類必須繼承Application,然后重寫Application中的start方法,start方法中有個Stage 參數,這個就是表示的程序的窗口類,然后在重寫的start方法中去實現一些場景,布局,節點等。

public class Test extends Application {public static void main(String[] args) {launch(args);}@Overridepublic void start(Stage stage) throws Exception {//窗口stage.setTitle("我時窗口");//標簽Label label = new Label("我是標簽");//場景Scene scene = new Scene(label,300 , 300);stage.setScene(scene);stage.show();}
}

2. 涉及類介紹

Application

Application類是程序入口類繼承之后,重寫其中的start()方法即可,但如果你要在窗口的創建前后做一些其他事情,那可以重寫其init()方法和stop()方法,因為Application的生命周期為init() ----->start() ----->stop()(窗口關閉時自動調用)。

在idea中使用alt+insert ,點擊Override Method 重寫 init() 和stop()

Stage

窗口
常用方法:

  • Title

  • icon 設置程序的
    在這里插入圖片描述

    此icon圖片在resources下的images目錄,resources目錄的屬性為 Rsources Root
    在這里插入圖片描述

stage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/img.png"))));
  • resiziable
    窗口大小是否可變,默認true可變,false 不可變

    stage.setResizable(false);
    
  • x,y,width,height
    窗口的寬高,一般不設置,都是設置場景的寬高

  • StageStyye
    窗口樣式,比如不顯示關閉和圖片等外邊樣式。

    //默認樣式,系統樣式
    stage.initStyle(StageStyle.DECORATED);
    

    具體查看StageStyle中的其他枚舉

  • Modality
    窗口的模態,也就是窗口之間的影響關系,比如子窗口打開之后不能點擊父窗口這種功能。

    stage.initModality(Modality.NONE);
    

    具體查看Modality中的其他枚舉

  • event
    事件

       //設置關閉窗口時,程序是否退出 默認為true 退出 false 不退出Platform.setImplicitExit(false);stage.setOnCloseRequest(event -> {System.out.println("關閉窗口");//取消默認關閉窗口事件event.consume();Alert alert = new Alert(Alert.AlertType.CONFIRMATION);alert.setTitle("退出程序");alert.setHeaderText(null);alert.setContentText("點擊確定退出");alert.showAndWait().ifPresent(response -> {if (response == ButtonType.OK) {stage.close();Platform.exit();}});});

Scene

場景

  1. 場景切換

創建button --> 設置button位置—>把button放入錨點布局中—>創建場景,把錨點布局放入場景中 —>給button設置事件(因為是切換場景,所以給button設置事件要有第二個場景對象,所以此處給button設置事件寫在最后,也就是第二個場景創建完成之后)

    public void start(Stage stage) throws Exception {//創建一個buttonButton button0 = new Button("切換場景");//設置button的位置button0.setLayoutX(150);button0.setLayoutY(150);//把button放入錨點布局 AnchorPane anchorPane = new AnchorPane(button0);//創建場景,把錨點布局放入場景Scene scene = new Scene(anchorPane, 300, 300);Button button1 = new Button("返回場景");button1.setLayoutX(150);button1.setLayoutY(150);//標簽Label label = new Label("我是標簽");label.setLayoutX(100);label.setLayoutY(100);AnchorPane anchorPane1 = new AnchorPane(button1, label);//場景2Scene scene2 = new Scene(anchorPane1, 300, 300);//給button0 添加事件button0.setOnAction(event -> {stage.setScene(scene2);});button1.setOnAction(event -> {stage.setScene(scene);});//窗口stage.setTitle("我時窗口");stage.getIcons().add(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/img.png"))));stage.setScene(scene);stage.show();}
  1. 鼠標箭頭的樣式
scene.setCursor(new ImageCursor(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/1xxx.png")))));
scene2.setCursor(new ImageCursor(new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/2xxx.png")))));

Node

Node類是一個抽象類,所有控件都是的父類都是最終繼承的Node抽象類,包括但不限于 按鈕、復選框、顏色選擇、日期選擇、文字輸入框、導航欄以及所有的可見控件。
常用方法
下面以Label標簽為例來展示Node中的一些常用方法

        //標簽Label label = new Label("我是標簽");//設置標簽的位置label.setLayoutX(100);label.setLayoutY(100);//設置標簽的樣式label.setStyle("-fx-font-size: 20px; -fx-border-color: blue; -fx-border-width: 3px");//設置標簽的寬高label.setPrefWidth(200);label.setPrefHeight(50);//設置標簽的對齊方式label.setAlignment(Pos.CENTER);//設置標簽的可見性
//        label.setVisible(false);//設置標簽的混合模式 比如兩個圖層交叉部分的混合樣式,不常用
//        label.setBlendMode(BlendMode.ADD);//設置標簽的透明度label.setOpacity(0.5);//設置標簽的旋轉角度label.setRotate(45);//設置標簽的平移label.setTranslateX(20);label.setTranslateY(20);//設置3D的旋轉角度label.setScaleX(2);label.setScaleY(2);label.setScaleY(2);//獲取父節點Parent parent = label.getParent();//獲取節點所在的場景Scene scene1 = label.getScene();//獲取節點的idString id = label.getId();

Node屬性的 單向綁定 和 監聽器

Circle circle = new Circle();circle.setCenterX(50);circle.setCenterY(50);circle.setRadius(25);circle.setFill(Color.WHITE);circle.setStroke(Color.BLACK);//Node屬性的 單向綁定 ,例如 當scene的寬高改變時,circle的寬高也會改變circle.centerXProperty().bind(scene2.widthProperty().divide(2));circle.centerYProperty().bind(scene2.heightProperty().divide(2));//Node屬性的 監聽器 ,監聽屬性的變化circle.centerXProperty().addListener((observable, oldValue, newValue) -> {System.out.println("X 軸位置改變了,原來是 "+oldValue+",現在是 "+newValue);});circle.centerYProperty().addListener((observable, oldValue, newValue) -> {System.out.println("Y 軸位置改變了,原來是 "+oldValue+",現在是 "+newValue);});

控件事件綁定

控件也就是繼承node的那些控件,比如按鈕,文本框,標簽等,見上面Node介紹。
控件事件綁定就是給按鈕綁定點擊事件,鍵盤事件,鼠標事件,拖拽等。
其使用方法基本都是 控件.setOn事件(event) ,具體使用查看文檔,事件非常多。

示例為給按鈕綁定點擊事件,給場景綁定鍵盤按下釋放時的事件

        Button button3 = new Button("向上移動");//設置button的位置button3.setLayoutX(200);button3.setLayoutY(200);//button3按鈕綁定事件 label 向上移動5px   ---- 主要方法button3.setOnAction(event -> {label.setLayoutY(label.getLayoutY()-5);});AnchorPane anchorPane1 = new AnchorPane(button1, label,circle,button3);//場景2Scene scene2 = new Scene(anchorPane1, 300, 300);//給場景2添加鍵盤事件 如果按鍵盤向下鍵擊,label 向下移動5pxscene2.setOnKeyReleased(event -> {KeyCode code = event.getCode();if (code == KeyCode.DOWN){label.setLayoutY(label.getLayoutY()+5);}});

Color、Font、Image

color

        Color black = Color.BLACK;Color rgb = Color.rgb(255, 0, 0);Color hsb = Color.hsb(0, 0, 0);Color web = Color.web("#ff0000");

Font

      Font font1 = new Font("微軟雅黑", 20);Font font = Font.font("微軟雅黑", 20);// 字體,自重(bold是加粗),大小Font font2 = Font.font("仿宋", FontWeight.BOLD, 20);//使用資源文件種的字體 或者加載網絡中的字體Font font3 = Font.loadFont(Objects.requireNonNull(Test.class.getResource("")).toExternalForm(), 20);

Image
可以使用本地或者網絡中的圖片

  ImageView imageView = new ImageView();Image image = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/images/img.png")));imageView.setImage(image);

3. FXML布局文件

在這里插入圖片描述
想寫什么控件,就用什么標簽,標簽里的屬性與寫類代碼時的屬性一直

4. SceneBuilder

首先下載SceneBuilder: https://openjfx.cn/scene-builder/
一路下一步安裝,安裝之后在idea中配置
在這里插入圖片描述
配置完之后在idea中打開fxml使用SceneBuilder打開方式
在這里插入圖片描述
在SceneBuilder中創建FXMl,拖拽創建控件,然后修改控件屬性,綁定事件
在這里插入圖片描述
出現控制器中的代碼
在這里插入圖片描述
file–>save 保存 FXML

5. Controller中的initialize方法

布局文件 和 此controller 設置的屬性和事件都初始化完畢,則會自動調用 initialize
也就是說,在initialize 方法中,可以獲取布局文件中的控件,并做相應的初始化,如果布局文件中控件已經設置了對應的屬性或事件,則initialize方法中會覆蓋。

示例:以下代碼中initialize會覆蓋moveLable方法。因為moveLable是bu在FXMl中綁定的setOnAction事件,但是initialize又給bu綁定了另一個setOnAction事件,又因為initialize是在控件所有屬性和事件都初始化完畢之后才執行的,所以就覆蓋掉了之前綁定的事件。

public class HelloController2 {@FXMLpublic Label la2;@FXMLpublic Button bu;@FXMLvoid moveLable() {System.out.println("點擊");
//        la2.setLayoutY(la2.getLayoutY() - 10);}//布局文件 和 此controller 設置的屬性和事件都初始化完畢,則會自動調用 initialize//也就是說, 在initialize 方法中,可以獲取布局文件中的控件,并做相應的初始化,如果布局文件中控件已經設置了對應的屬性或事件,則initialize方法中會覆蓋public void initialize() {bu.setOnAction(event -> {System.out.println("xxxxxx");});}
}

6. 入口類Application中操作controller

比如,當需要圖形根據scene 的大小的變化而變化時,也就是scene 的操作需要影響控件。
主要方法:fxmlLoader.getController()

public class HelloApplication extends Application {@Overridepublic void start(Stage stage) throws IOException {FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("demo.fxml"));Scene scene = new Scene(fxmlLoader.load(), 600, 400);//-----主要方法HelloController2 controller = fxmlLoader.getController();//circleBind 為controller中自己定義的方法controller.circleBind(scene);//---主要方法stage.setTitle("Hello!");stage.setScene(scene);stage.show();}public static void main(String[] args) {launch();}
}
public class HelloController2 {@FXMLprivate Circle uu;public void circleBind(Scene scene){//單向數據綁定uu.centerYProperty().bind(scene.heightProperty().divide(2));uu.centerXProperty().bind(scene.widthProperty().divide(2));}}

7. Platform.runLater()

javaFX程序中,為了避免其他線程污染ui界面,其不允許除主線程以外的其他線程去更改或刷新ui,也就是說,刷新界面只能通過main方法來實現,也就是繼承Application那個類。

如果想在主線程刷新ui界面,可以使用Platform.runLater(),該方法給讓主線程空閑時候允許Platform.runLater()隊列里的內容。也就是說把對ui操作的代碼放在Platform.runLater()中。

Platform.runLater() 不是開啟多線程,因為其和主線程的線程名稱都一樣。
參考:https://blog.csdn.net/weixin_57792864/article/details/127025819

很多控件的事件方法其實內部都是使用了Platform.runLater()

錯誤示例:

Exception in thread "Thread-3" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
public class Test2 extends Application {@Overridepublic void start(Stage stage) throws Exception {Button button = new Button("獲取姓名");button.setLayoutX(200);button.setLayoutY(200);Label label = new Label("我的姓名是");label.setLayoutX(200);label.setLayoutY(100);//錯誤代碼  ----------------------------button.setOnAction(event -> {new Thread(() -> {label.setText("我的姓名是 - 王二小");}).start();});AnchorPane anchorPane  = new AnchorPane(button,label);Scene scene = new Scene(anchorPane,400,400);stage.setScene(scene);stage.show();}public static void main(String[] args) {launch(args);}
}

正確示例:

public class Test2 extends Application {@Overridepublic void start(Stage stage) throws Exception {Button button = new Button("獲取姓名");button.setLayoutX(200);button.setLayoutY(200);Label label = new Label("我的姓名是");label.setLayoutX(200);label.setLayoutY(100);//主要代碼 -----------------------------------button.setOnAction(event -> {Platform.runLater(() -> {label.setText("我的姓名是 - 王二小");});});AnchorPane anchorPane  = new AnchorPane(button,label);Scene scene = new Scene(anchorPane,400,400);stage.setScene(scene);stage.show();}public static void main(String[] args) {launch(args);}
}

8. Canvas 畫布

https://www.bilibili.com/video/BV1Qf4y1F7Zv?p=14

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13356.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13356.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13356.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

20232906 2023-2024-2 《網絡與系統攻防技術》第十次作業

20232906 2023-2024-2 《網絡與系統攻防技術》第十次作業 1.實驗內容 一、SEED SQL注入攻擊與防御實驗 我們已經創建了一個Web應用程序,并將其托管在http://www.seedlabsqlinjection.com/(僅在SEED Ubuntu中可訪問)。該Web應用程序是一個簡…

算法day08

第一題 1. 兩數之和 由上述題意所知,本題要采用二分法的解題思路,二分法主要是面向有序的數組且也滿足二段性的數組,所謂二段性就是在一定的規則下能把該數組分成兩個部分; 本題注意要點: 1、循環結束的條件&#xff…

行為決策樹

系列文章目錄 提示:這里可以添加系列文章的所有文章的目錄,目錄需要自己手動添加 TODO:寫完再整理 文章目錄 系列文章目錄前言行為決策樹前言 認知有限,望大家多多包涵,有什么問題也希望能夠與大家多交流,共同成長! 本文先對** 行為決策樹**做個簡單的介紹,具體內容后…

從國內盲盒小程序看國外市場的發展機遇與挑戰

近年來,隨著國內電商市場的蓬勃發展,盲盒小程序作為一種新興的電商模式,以其獨特的購物體驗和創新的營銷策略,迅速贏得了廣大消費者的喜愛。然而,隨著國內市場逐漸趨于飽和,許多盲盒小程序開始尋求海外市場…

【Leetcode每日一題】 綜合練習 - 括號生成(難度??)(76)

1. 題目解析 題目鏈接:22. 括號生成 這個問題的理解其實相當簡單,只需看一下示例,基本就能明白其含義了。 2.算法原理 問題描述 我們需要找出所有可能的、有效的括號序列。一個有效的括號序列指的是一個僅由(和)組成的字符串,…

ssm132醫院住院綜合服務管理系統設計與開發+vue

醫院住院綜合服務管理系統的設計與實現 摘 要 互聯網發展至今,無論是其理論還是技術都已經成熟,而且它廣泛參與在社會中的方方面面。它讓信息都可以通過網絡傳播,搭配信息管理工具可以很好地為人們提供服務。針對醫院住院信息管理混亂&…

【高階數據結構(四)】圖的最短路徑問題

💓博主CSDN主頁:杭電碼農-NEO💓 ? ?專欄分類:高階數據結構專欄? ? 🚚代碼倉庫:NEO的學習日記🚚 ? 🌹關注我🫵帶你學習更多數據結構 ? 🔝🔝 高階數據結構 1. 前言2. 單源最短…

第八篇 Asciidoc 輸出 All In One HTML 解決圖片無法顯示問題

問題:我的圖片顯示不出來了 小明使用 Asciidoc 來記筆記,他將筆記輸出為 HTML 文件。小麗向小明借筆記。小明將 Asciidoc 筆記輸出為 HTML文件,并拷貝給了小麗。 但是,小麗發現,圖片都顯示不出來了。 小麗:小明,你給我的筆記,圖片都顯示不出來啊。 小明:是我給你的…

析構函數詳解

目錄 析構函數概念特性對象的銷毀順序 感謝各位大佬對我的支持,如果我的文章對你有用,歡迎點擊以下鏈接 🐒🐒🐒 個人主頁 🥸🥸🥸 C語言 🐿?🐿?🐿? C語言例題 &…

yolov8實戰之 .pt 轉. tensorRT

1 yolo 訓練 1.1修改自己的數據集合 我是有3個類別,差不多這么些數據 1.2 訓練 from ultralytics import YOLO # Load a model model YOLO("yolov8m.yaml") # build a new model from scratch #model YOLO(E:/pythonCode/pythonProject1/runs/detec…

風電功率預測 | 基于PSO-BP神經網絡實現風電功率預測(附matlab完整源碼)

風電功率預測 風電功率預測完整代碼風電功率預測 基于粒子群優化算法(Particle Swarm Optimization, PSO)的BP神經網絡是一種常見的方法,用于實現風電功率預測。下面是一個基于PSO-BP神經網絡實現風電功率預測的一般步驟: 數據準備:收集與風電場發電功率相關的數據,包括…

農林科學SCI期刊,IF=6+,影響力高,對國人非常友好!

一、期刊名稱 Crop Journal 二、期刊簡介概況 期刊類型:SCI 學科領域:農林科學 影響因子:6.6 中科院分區:1區 出版方式:開放出版 版面費:$900 三、期刊征稿范圍 《作物雜志》是一份雙月刊、國際、同…

PHP使用Browsershot進行網頁截圖

Browsershot是什么 Spatie Browsershot 是一個開源PHP庫,它允許開發者在PHP應用程序中生成網頁的截圖。 這個庫特別適用于Laravel框架,但也可以在其他 PHP 應用程序中使用。 主要特點 無頭瀏覽器截圖:使用無頭版本的 Chrome 或 Chromium 瀏…

整理好了!2024年最常見 100 道 Java基礎面試題(四十九)

上一篇地址:整理好了!2024年最常見 100 道 Java基礎面試題(四十八)-CSDN博客 九十七、Class.forName 和 ClassLoader 的區別? Class.forName 和 ClassLoader 是Java中用于加載類的兩個不同的概念,它們在類…

10W 3KVAC隔離 寬電壓輸入 AC/DC 電源模塊 ——TP10AF系列

TP10AF系列輸出功率為10W,具有可靠性高、更小的體積、性價比高等特點,廣泛用于工控和電力儀器、儀表、智能家居等相關行業。

SMB攻擊利用之-mimikatz上傳/下載流量數據包逆向分析

SMB協議作為windows環境下最為常見的一種協議,在歷史上出現過無數的通過SMB協議進行網絡攻擊利用的案例,包括針對SMB協議本身以及通過SMB協議實施網絡攻擊。 本文將介紹一種通過SMB協議的常見利用方式,即向遠程主機傳輸mimikatz,作為我的專欄《SMB攻擊流量數據包分析》中的…

Oracle數據塊之數據行中的SCN

從Oracle 10g開始,如果在表級別打開ROW DEPENDENCIES,業務數據行發生更改時會在數據塊中進行登記。 可以通過DUMP數據塊來觀察上述SCN: (1)創建測試表,插入3條測試數據,插入一條提交一次。并調用…

解析建筑裝飾乙級資質標準及申請流程

建筑裝飾乙級資質標準 資歷與信譽 必須具備獨立的企業法人資格。社會信譽良好,注冊資本不少于100萬元人民幣。 技術條件 專業技術人員配備齊全、合理,滿足相應資質標準中對主要專業技術人員數量和專業的具體要求。通常包括但不限于室內設計、建筑、環境藝…

jar包增量更新分析

jdk自帶工具jdeps,可分析class依賴關系(依賴的其它類和jar)。 團隊,可以在此工具結果的基礎上再詳細分析對比出增量文件; 思路如下: jdeps分別分析出舊包和新包的文件依賴關系。并對比出新增的文件列表、…