{"id":15055985,"url":"https://github.com/ifarkhshatov/javafx-tutorial","last_synced_at":"2025-04-10T04:06:18.750Z","repository":{"id":38399808,"uuid":"335681871","full_name":"ifarkhshatov/JavaFX-Tutorial","owner":"ifarkhshatov","description":"This tutor shows how to build .exe JavaFx application","archived":false,"fork":false,"pushed_at":"2021-02-04T11:07:24.000Z","size":462,"stargazers_count":17,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-10T04:06:12.922Z","etag":null,"topics":["fxml","java","javafx","javafx-desktop-apps","javafx-project","scenebuilder"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ifarkhshatov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-03T16:13:53.000Z","updated_at":"2025-03-23T20:57:40.000Z","dependencies_parsed_at":"2022-08-25T06:11:29.828Z","dependency_job_id":null,"html_url":"https://github.com/ifarkhshatov/JavaFX-Tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifarkhshatov%2FJavaFX-Tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifarkhshatov%2FJavaFX-Tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifarkhshatov%2FJavaFX-Tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ifarkhshatov%2FJavaFX-Tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ifarkhshatov","download_url":"https://codeload.github.com/ifarkhshatov/JavaFX-Tutorial/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248154983,"owners_count":21056543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fxml","java","javafx","javafx-desktop-apps","javafx-project","scenebuilder"],"created_at":"2024-09-24T21:47:31.215Z","updated_at":"2025-04-10T04:06:18.727Z","avatar_url":"https://github.com/ifarkhshatov.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Building desktop app (.exe) with JavaFX \n## Introduction\nIn this guide, you will learn how to build an executable **JavaFX** desktop application and later can run it without IDE by just clicking *.exe* file.  \nThe problem with JavaFX is that Oracle is ruining this awesome tool by making it harder to execute on JDK 11, but referencing this [link](https://stackoverflow.com/questions/61555515/intellij-idea-javafx-export-cant-build-artifact-fxdeploy-is-not-available) I have just chosen to download JDK 8 since it is building JavaFX without any issues.\n## Install JDK 8\nTo do that go [there](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html) and download a particular version for your OS\n## Install SceneBuilder for building GUI for our app  \nGo to the [site](https://gluonhq.com/products/scene-builder/) and download the app.\n## Download JavaFX  \nGo to the [site](https://gluonhq.com/products/javafx/) and download JavaFX Windows SDK.\nThen you unzip in your chosen directory. You will source this for each JavaFX project. (Unfortunately each time the same steps).\n\n## Run your first JavaFX app via IntelliJ  \n1.  Click **[+ New Project]** -\u003e **[Java FX]** -\u003e **[Project SDK]** -\u003e **[Corretto-11 java version “11.0.8”]** -\u003e **[Next]** -\u003e **[Name and propject location]** -\u003e **[Finish]**  \n2.  Go to **[File]** -\u003e **[Project Structure…]** *or Ctr+Alt+Shift+S* -\u003e **[Libraries]** -\u003e **[New Project Library (+) sign]** -\u003e **[Java]** -\u003e **[Choose the directory of unzipped SDK folder lib]** -\u003e **[Press okay]**  \n3.  Go to **[Run]** -\u003e In Application/Main in *Configuration* tab under field **[VM Options:]** you have to place the following fields:\n```shell\n--module-path \\javafx-sdk-11.0.2\\lib --add-modules javafx.controls,javafx.fxml\n```\nInstead of *\\javafx-sdk-11.0.2\\lib* you need to set your own directory of JavaFX lib folder.\n\n4.  Run (shift + f10) Main.java and you will see this window if you do all these steps correctly.   \n![empty_window](screens/empty_window.PNG)\n\n## Build a JavaFX app with SceneBuilder\nFor the sake of simplicity, I will build a simple currency converter app which will use API.   \n ![example](screens/example.PNG)\n1.\tOpen SceneBuilder\n2.\tChoose **Open Project**\n3.\tFind in a directory of the app (in src folder) **.fxml** file and open it\n4.\tFor the moment we will drop default GridPane (0x0)    \n![gridpane](screens/GridPane.png)\n5.\tDrag AnchorPane and move to the main screen. This is the main window of our application.    \n![anchorpane](screens/AcnhorPane.PNG)\n6.\tWe can adjust the size of the window as well as colour and style if you are familiar with *CSS*\n7.\tWe can use the search window to quickly find an object, for example, “Text”. Drag to the main screen and adjust the size of Text area and styling.  \n![text_style](screens/Properties.PNG)\n8.\tThen keep filling like you wish the App. And at the end, the layout should look similar to this:  \n![final_layout](screens/final_layout.PNG)  \n\nYou now can preview the app, go to **[Preview]** -\u003e **[Show Preview in Window]** or simply *Ctrl+P*\nNow steps to use this template in our app as well as set-up IDs for further uses.\n1.\tTo further use an object in code and provide the reactivity for that we need to set **fx:id**. Select the object and on the right side of the SceneBuilder click tab **[Code]**. You will see the **fx:id** fill the id of the object. Place IDs for other objects.  \n![fx_id](screens/fx_id.PNG)\n2.\tI built three empty text objects and assign **fx:id** for them to display the information about currency rate; conversion and date when button “Convert” is clicked.  \n![empty_text](screens/empty_text.PNG)\n3.\tIn button left side click **[Controller]** and in field **[Contoller class]** and provide the root to Controller.java. For example **[sample.Controller]**  \n![fx_id](screens/fx_id.PNG)\n4.\tAfter previous steps, we save the changes (Ctrl + S) it will replace **.fxml** layout to our built layout in SceneBuilder.\n5.\tFinally, we need to click **[View]** -\u003e **[Show Sample Controller Skeleton]** -\u003e click in right button **[Full]** then Copy and paste in the app directory *Controller.java*  \n![skeleton](screens/skeleton.PNG)\nI got something like this:\n```Java\npackage sample;\n\nimport java.net.URL;\nimport java.util.ResourceBundle;\nimport javafx.fxml.FXML;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.TextField;\nimport javafx.scene.text.Text;\n\npublic class Controller {\n\n    @FXML\n    private ResourceBundle resources;\n\n    @FXML\n    private URL location;\n\n    @FXML\n    private TextField amountField;\n\n    @FXML\n    private TextField ccyOne;\n\n    @FXML\n    private TextField ccyTwo;\n\n    @FXML\n    private Button applyBtn;\n\n    @FXML\n    private Text rateCcy;\n\n    @FXML\n    private Text conversionTotal;\n\n    @FXML\n    private Text dateStamp;\n\n    @FXML\n    void initialize() {\n        assert amountField != null : \"fx:id=\\\"amountField\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert ccyOne != null : \"fx:id=\\\"ccyOne\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert ccyTwo != null : \"fx:id=\\\"ccyTwo\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert applyBtn != null : \"fx:id=\\\"applyBtn\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert rateCcy != null : \"fx:id=\\\"rateCcy\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert conversionTotal != null : \"fx:id=\\\"conversionTotal\\\" was not injected: check your FXML file 'sample.fxml'.\";\n        assert dateStamp != null : \"fx:id=\\\"dateStamp\\\" was not injected: check your FXML file 'sample.fxml'.\";\n\n    }\n}\n\n```\n## Coding application\nFirstly, let's quickly fix **Main.java**:  \n1. Set title: ``primaryStage.setTitle(\"Currency Converter\");``\n2. Place size from SceneBuilder in object **Scene**:\n    `` primaryStage.setScene(new Scene(root, 384, 283));``\n3. Fix the window to not be scaled:\n    ``primaryStage.setResizable(false);``\n\nNow we can go to Contoller.java and do all work there.  \nThere you could see the ``initialize()``. From this method we can drop warnings and rewrite the code to check is our template is functional or not. Let’s just add **sout** command to get output in the console by clicking the button:\n\n```Java\n@FXML\n void initialize() {\n    applyBtn.setOnAction(event -\u003e {\n    System.out.println(\"IT WORKS!\");\n    });\n }\n```  \n\n![itworks](screens/sout_itworks.PNG)\n\nYou might notice the red warning. This is because of compitability issues of JavaFX. Just go to **.fxml** file in **AnchorPane** and replace ``xmlns=\"http://javafx.com/javafx/15.0.1\"`` to which version it asks (``xmlns=\"http://javafx.com/javafx/11.0.2\"``)\n\n## Install jar for JSON Parsing\nNext let's install JSON jar from [here](https://mvnrepository.com/artifact/org.json/json/20201115) or [here](https://repo1.maven.org/maven2/org/json/json/20201115/json-20201115.jar). Store it in any directory and go to **[File]** -\u003e **[Project Structure…]** *or Ctr+Alt+Shift+S* -\u003e **[Libraries]** -\u003e **[New Project Library (+) sign]** -\u003e **[Java]** -\u003e **[Choose jar file]** -\u003e **[Press okay]** \n\n## Working with API\nyou actually can do any other API if you like. I choose first [link](https://currencylayer.com/) in google. I won't explain how to set-up - it is easy. But once you logged in go to how to start and find the api link with your assigned token like i did http://data.fixer.io/api/latest?access_key=27ad197ccf98251c14ebc0b13134de39\u0026symbols=USD  \nEven if you click this link it will open JSON object in your browser, so we can now use it in our application.\n\nBefore we need to build a class **getUrlContent** which will buffer data from the GET.\n\n```Java\n    private static String getUrlContent(String urlAddress) {\n        StringBuffer content = new StringBuffer();\n        try {\n            URL url = new URL(urlAddress);\n            URLConnection urlConn = url.openConnection();\n\n            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));\n            String line;\n            while ((line = bufferedReader.readLine()) != null) {\n                content.append(line + \"\\n\");\n            }\n            bufferedReader.close();\n        } catch (Exception e) {\n            System.out.println(\"Error in conversion\");\n        }\n        return content.toString();\n    }\n```\n\nNow in the method **initialize()** we can build up our parser and output insted of sout function:\n\n```Java\n    @FXML\n    void initialize() {\n        applyBtn.setOnAction(event -\u003e {\n            String output = getUrlContent(\"http://data.fixer.io/api/latest?access_key=\" +\n                    \"27ad197ccf98251c14ebc0b13134de39\u0026symbols=\"+ccyOne.getText().toUpperCase()+\",\"+ccyTwo.getText().toUpperCase());\n            if(!output.isEmpty()) {\n                JSONObject obj = new JSONObject(output);\n                dateStamp.setText(obj.getString(\"date\"));\n                double ccyTwoValue = obj.getJSONObject(\"rates\").getDouble(ccyTwo.getText()) /\n                        obj.getJSONObject(\"rates\").getDouble(ccyOne.getText());\n                String ccyTwoStr = String.format(\"%.2f\", ccyTwoValue) + \" \" + ccyTwo.getText();\n\n                rateCcy.setText(ccyTwoStr);\n\n                double amount = Double.parseDouble(amountField.getText());\n                double total = ccyTwoValue * amount;\n                String totalStr = String.format(\"%.2f\", total) + \" \" + ccyTwo.getText();\n                conversionTotal.setText(totalStr);\n            }\n        });\n    }\n```\n\nAnd finally if it works then you can convert any currency and amount you would like. \n\n### !!! Be awere to use indexes for currncy like EUR - for euro or USD - for US Dollar.\n\n## Build a self contained .exe file\nIf everything works then we can finally build our application as .exe file to use it without IDE.\n1. Go to **[File]** -\u003e **[Project Structure…]** *or Ctr+Alt+Shift+S* -\u003e **[Project]** -\u003e set Project as 1.8 and project language level as 8   ![java8](screens/java8.PNG)\n2. Go to **[Artifacts]** -\u003e **+ Add** or Alt+Insert -\u003e **JavaFX Application** -\u003e **From module..**.\n3. In output tab move JSON jar and lib from JavaFX to the left into .jar of your project  ![Artifacts](screens/Artifacts.PNG)\n4. Go to tab **Java FX** in **Application class:** set your main class or click folder icon and choose, for example *sample.Main*, in **Native bundle:** choose all option and press ok.\n5. Go to **[Build]** -\u003e **[Build Artifacts..]**\n\nIf there is no errors it should create in **out.artifacts** folder bundle. Go there and you will the last folder where is .exe file. You can move this folder out of directory and it can works without IDE.  \n ![exe](screens/exe1.PNG)  \n \n![exe2](screens/exe2.PNG)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fifarkhshatov%2Fjavafx-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fifarkhshatov%2Fjavafx-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fifarkhshatov%2Fjavafx-tutorial/lists"}