摘要:創(chuàng)建窗口添加類(lèi)為元素間空隙與主窗口創(chuàng)建過(guò)程相同,新建布局及控件,最后使用的方法顯示出來(lái)。設(shè)置主窗口中的按鈕事件,點(diǎn)擊按鈕后會(huì)顯示一個(gè)窗口。這時(shí)我們可以通過(guò)函數(shù)設(shè)置窗口關(guān)閉時(shí)觸發(fā)的事件在關(guān)閉窗口時(shí),首先執(zhí)行這一事件處理函數(shù),再將窗口關(guān)閉。
前言
如今比較流行的桌面gui框架有WPF、WinForm、Qt、javafx等。其中WPF和WinForm目前還只能在運(yùn)行Winsows上。Qt(widget)是一個(gè)很強(qiáng)大的跨平臺(tái)C++框架(不只是UI),但用C++寫(xiě)界面實(shí)在有點(diǎn)蛋疼,且編譯出來(lái)的體積很大。
JavaFX是基于JAVA的開(kāi)源桌面框架,筆者曾學(xué)習(xí)過(guò)Qt,打算嘗試使用Java寫(xiě)桌面應(yīng)用,現(xiàn)在網(wǎng)上關(guān)于JavaFX的教程不時(shí)很多,因此在這里記錄一下學(xué)習(xí)過(guò)程。
安裝和配置JavaFX11的環(huán)境不包括在JDK中,因此要在配置好JDK11的基礎(chǔ)上多帶帶配置,具體方法可以參考JavaFX官網(wǎng)。
窗口構(gòu)成新建工程,在Main.java中輸入下列代碼:
public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception{ VBox layout = new VBox(); Label label = new Label("Hello world"); layout.getChildren().add(label); Scene scene = new Scene(layout, 300, 300); primaryStage.setTitle("Hello World"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
JavaFX中的Stage可以看作是窗口,Scene是窗口中的內(nèi)容,調(diào)用Stage的setScene函數(shù)來(lái)設(shè)置窗口內(nèi)容,窗口可以在運(yùn)行時(shí)切換顯示的Scene,實(shí)現(xiàn)Tab頁(yè)面的效果。
VBox是JavaFX中的一種布局,其中的元素縱向排列,向VBox中添加元素需要調(diào)用vbox.getChildren().add(control),如上所示。
構(gòu)造Scene時(shí)傳入頂層的布局(類(lèi)似Qt中QMainWindow的CentralWidget)及大小。最后調(diào)用show函數(shù)將窗口顯示出來(lái)。
按鈕控件控件(Control)是GUI框架中最重要的部分,也是用戶(hù)與程序進(jìn)行交互的媒介。
在JavaFX中使用控件需要導(dǎo)入包,例如
import javafx.scene.control.Label; import javafx.scene.control.*;
框架中不同控件的使用方法大同小異,這里用最常用的按鈕作為示例。
在窗口中添加按鈕構(gòu)造一個(gè)Button對(duì)象并添加到VBox中:
Button button = new Button("Click me"); VBox layout = new VBox(); layout.getChildren().add(button); Scene scene = new Scene(layout, 300, 300); primaryStage.setScene(scene);處理按鈕點(diǎn)擊事件 使用EventHandler接口
創(chuàng)建Handler類(lèi)實(shí)現(xiàn)EventHandler接口
class Handler implements EventHandler{ @Override public void handle(ActionEvent actionEvent) { if(actionEvent.getSource() instanceof Button) ((Button) actionEvent.getSource()).setText("Click me again"); } }
為按鈕注冊(cè)點(diǎn)擊方法
button.setOnAction(new Handler());
Button還有setOnMouseClicked,setOnTouchPressed等方法,這些是專(zhuān)門(mén)為處理鼠標(biāo)事件及觸摸事件,setOnAction函數(shù)用來(lái)處理按鈕觸發(fā)事件(不管按鈕被哪種方式觸發(fā),具體參考文檔)。
由代碼可以得出,setOnAction函數(shù)接收一個(gè)EventHandler接口,接口的handle方法用來(lái)處理事件。
使用匿名內(nèi)部類(lèi)與上一方法同理,我們可以使用匿名內(nèi)部類(lèi)創(chuàng)建接口
button.setOnAction(new EventHandler使用Lambda表達(dá)式() { @Override public void handle(ActionEvent actionEvent) { if(actionEvent.getSource() instanceof Button) ((Button) actionEvent.getSource()).setText("Click me again"); } });
Java中的一些接口可以由lambda表達(dá)式代替,因此可以在setOnAction中傳入lambda表達(dá)式:
button.setOnAction(actionEvent -> { if(actionEvent.getSource() instanceof Button){ ((Button) actionEvent.getSource()).setText("Click me again"); } });
這樣就可以在實(shí)現(xiàn)簡(jiǎn)單的事件處理器時(shí)不必再特意實(shí)現(xiàn)接口。
其他控件使用其他控件的方法也都類(lèi)似按鈕,使用時(shí)可以查詢(xún)文檔,或者根據(jù)IDE的代碼提示獲知函數(shù)簽名及使用方法。
多窗口在一個(gè)桌面程序中往往有多個(gè)窗口,下面介紹添加窗口的方法。
創(chuàng)建窗口添加MsgBox類(lèi)
public class MsgBox { public static void show(String title) { Stage window = new Stage(); window.setTitle(title); Button trueButton = new Button("True"); Button falseButton = new Button("False"); HBox hBox = new HBox(10); //10為元素間空隙 hBox.getChildren().addAll(trueButton, falseButton); Scene scene = new Scene(hBox, 100, 100); window.setScene(scene); window.show(); } }
與主窗口創(chuàng)建過(guò)程相同,新建stage、Scene、布局及控件,最后使用Stage的show方法顯示出來(lái)。
調(diào)用MsgBox類(lèi)的show方法即可顯示窗口,函數(shù)的參數(shù)為窗口的標(biāo)題。
設(shè)置主窗口中的按鈕事件,點(diǎn)擊按鈕后會(huì)顯示一個(gè)MsgBox窗口。
button.setOnAction(actionEvent -> MsgBox.show("SubWindow"));窗口模態(tài)
Stage對(duì)象可以使用initModality方法設(shè)置窗口模態(tài)類(lèi)型
window.initModality(Modality.WINDOW_MODAL);
類(lèi)型包括 Modality.NONE, Modality.WINDOW_MODAL, Modality.APPLICATION_MODAL。
Modality.NONE: 不阻塞任何窗口
Modality.WINDOW_MODAL: 窗口級(jí)別的模態(tài),僅僅阻塞與對(duì)話(huà)框關(guān)聯(lián)的窗口,用戶(hù)可以正常訪(fǎng)問(wèn)其他窗口,適合用于多窗口的程序。
Modality.APPLICATION_MODAL(默認(rèn)值): 應(yīng)用程序級(jí)別的模態(tài),窗口將阻塞整個(gè)程序,無(wú)法訪(fǎng)問(wèn)程序中其他的窗口
返回子窗口的值有時(shí)我們需要得到用戶(hù)在子窗口中的操作,例如在本文的例子中,獲知用戶(hù)點(diǎn)了哪一個(gè)按鈕。
接下來(lái)實(shí)現(xiàn)這樣的功能——點(diǎn)擊True按鈕就在控制臺(tái)打印true,否則打印"false"。
更改MsgBox中的代碼
public static boolean show(String title) { Stage window = new Stage(); window.setTitle(title); Button trueButton = new Button("True"); Button falseButton = new Button("False"); trueButton.setOnAction(actionEvent -> { answer = true; window.close(); }); falseButton.setOnAction(actionEvent -> { answer = false; window.close(); }); HBox hBox = new HBox(10); hBox.getChildren().addAll(trueButton, falseButton); Scene scene = new Scene(hBox, 100, 100); window.setScene(scene); window.showAndWait(); return answer; }
show函數(shù)返回一個(gè)boolean類(lèi)型的值,這個(gè)值是由點(diǎn)擊的按鈕決定的,按鈕點(diǎn)擊后會(huì)關(guān)閉窗口,返回布爾值。
設(shè)置主窗口中按鈕點(diǎn)擊事件
button.setOnAction(actionEvent -> { var result = MsgBox.show("SubWindow"); System.out.println(result); });showAndWait函數(shù)
這個(gè)函數(shù)會(huì)阻塞當(dāng)前事件,直到窗口被關(guān)閉后才會(huì)返回,并執(zhí)行接下類(lèi)的語(yǔ)句。在上例中,我們顯示窗口并等待,直到點(diǎn)擊按鈕使窗口被關(guān)閉,才執(zhí)行后面的return answer語(yǔ)句。
可以嘗試改為調(diào)用show方法,觀(guān)察返回的結(jié)果。
窗口的關(guān)閉有時(shí)在用戶(hù)關(guān)閉窗口時(shí),需要執(zhí)行一定的操作,例如保存設(shè)置、確認(rèn)是否退出等。
這時(shí)我們可以通過(guò)setOnCloseRequest函數(shù)設(shè)置窗口關(guān)閉時(shí)觸發(fā)的事件
window.setOnCloseRequest(windowEvent -> { System.out.println("The window will be closed!"); });
JavaFX在關(guān)閉窗口時(shí),首先執(zhí)行這一事件處理函數(shù),再將窗口關(guān)閉。但在某些情況下(例如確認(rèn)是否關(guān)閉),我們需要在處理事件時(shí)取消窗口的關(guān)閉,這種情況下可以調(diào)用windowEvent的consume方法,告訴事件系統(tǒng),此事件已經(jīng)被處理完畢,不必再執(zhí)行其他處理動(dòng)作(如關(guān)閉窗口)。
將主窗口的代碼改為:
@Override public void start(Stage primaryStage) throws Exception { Button button = new Button("Click me"); button.setOnAction(actionEvent -> { var result = MsgBox.show("SubWindow"); System.out.println(result); }); VBox layout = new VBox(); layout.getChildren().add(button); Scene scene = new Scene(layout, 300, 300); primaryStage.setScene(scene); primaryStage.setTitle("Hello World"); primaryStage.setOnCloseRequest(windowEvent -> { var result = MsgBox.show("Do you want to CLOSE?"); if (result == false) { windowEvent.consume(); } }); primaryStage.show(); }
當(dāng)用戶(hù)點(diǎn)擊關(guān)閉按鈕時(shí),將會(huì)彈窗詢(xún)問(wèn)是否關(guān)閉,若用戶(hù)點(diǎn)擊False按鈕窗口就不會(huì)被關(guān)閉。
鏈接推薦一個(gè)很好的JavaFX教程視頻:https://youtu.be/FLkOX4Eez6o
一個(gè)適合初學(xué)者的Qt教程:https://www.devbean.net/2012/...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77425.html
摘要:故可采用自定義控件的方式簡(jiǎn)化外部的代碼調(diào)用。自定義控件的設(shè)計(jì)版本之后,提供寫(xiě)法,此時(shí)要求必須繼承自節(jié)點(diǎn)對(duì)象,使用加載時(shí),必須調(diào)用方法。 「博客搬家」 原地址: 簡(jiǎn)書(shū) 原發(fā)表時(shí)間: 2017-05-21 有一個(gè)項(xiàng)目,需要模擬數(shù)千臺(tái)設(shè)備的工作情況,這數(shù)千個(gè)設(shè)備分為若干組,每組 100 臺(tái)。故需要設(shè)計(jì)一款 GUI 程序,包含 100 個(gè)自定義控件,模擬一組設(shè)備的工作情況,通過(guò) List...
摘要:本文探討使用構(gòu)建集成的可執(zhí)行程序的方法,以及根節(jié)點(diǎn)問(wèn)題。而使用后,可指導(dǎo)類(lèi)作為根節(jié)點(diǎn),避免了嵌套的情況。文件設(shè)計(jì)如下文件同時(shí)指明了根節(jié)點(diǎn)的類(lèi)型,資源文件對(duì)應(yīng)的設(shè)計(jì)如下此時(shí)可實(shí)現(xiàn)開(kāi)始時(shí),純代碼方式的自定義控件設(shè)計(jì)。 「博客搬家」 原地址: 簡(jiǎn)書(shū) 原發(fā)表時(shí)間: 2017-05-22 上一篇文章探討了使用 IntelliJ IDEA 創(chuàng)建 JavaFX 工程,進(jìn)而開(kāi)發(fā)了所需應(yīng)用程序。更...
摘要:中獲取并自定義窗口移動(dòng)與縮放邏輯由于去掉了平臺(tái)自帶了標(biāo)題欄,窗口就無(wú)法移動(dòng)和縮放了,需要我們自己來(lái)實(shí)現(xiàn)。 JavaFx中Controller獲取Stage并自定義窗口移動(dòng)與縮放邏輯 由于去掉了平臺(tái)自帶了標(biāo)題欄,窗口就無(wú)法移動(dòng)和縮放了,需要我們自己來(lái)實(shí)現(xiàn)。 去除窗口標(biāo)題欄 public class Main extends Application { @Override ...
匿名類(lèi) 匿名類(lèi)可以使你代碼更簡(jiǎn)潔,它們使你能夠同時(shí)聲明和實(shí)例化一個(gè)類(lèi),它們就像局部類(lèi),除了它們沒(méi)有名稱(chēng),如果你只需要使用局部類(lèi)一次,請(qǐng)使用它們。 聲明匿名類(lèi) 雖然局部類(lèi)是類(lèi)聲明,但匿名類(lèi)是表達(dá)式,這意味著你在另一個(gè)表達(dá)式中定義該類(lèi),以下示例HelloWorldAnonymousClasses在局部變量frenchGreeting和spanishGreeting的初始化語(yǔ)句中使用匿名類(lèi),但使用局部類(lèi)...
摘要:如果你想查看運(yùn)行時(shí)模塊的加載過(guò)程輸出結(jié)果表示為模塊,由于我限制了不再往下輸出了,而我們模塊又沒(méi)有別的額外依賴(lài),所以?xún)H有這行輸出。 jdk9模塊快速入門(mén) 列出自帶模塊:java --list-modulesmac多版本jdk共存:http://adolphor.com/blog/2016...模塊規(guī)則示意圖:showImg(https://segmentfault.com/img/bVb...
閱讀 3030·2021-11-24 10:21
閱讀 1601·2021-10-11 10:57
閱讀 2814·2021-09-22 15:24
閱讀 2678·2021-09-22 14:58
閱讀 2337·2019-08-30 13:16
閱讀 3489·2019-08-29 13:05
閱讀 3422·2019-08-29 12:14
閱讀 3461·2019-08-27 10:55