JavaFX, HelloWorld + CSS + FXML. Ending

    HelloWorld from an example provided by Oracle in "Getting Started with JavaFX" on a Windows PC. Transforming the login and password input window using CSS, creating a form in FXML, and also using CSS in an FXML form. Again the command line and subtleties that we were not told about in the tutorial.



    The first section of Getting Started with JavaFX describes how to create a simple JavaFX application, which you can get using the command line here . In the second section, it is proposed to make a login and password entry window. It is made from the first application here . As a result, the code has slightly increased in size.
    HelloWorld.java
    package helloworld;
    import javafx.application.Application;
    import javafx.event.ActionEvent;
    import javafx.event.EventHandler;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    import javafx.scene.layout.GridPane;
    import javafx.geometry.*;
    import javafx.scene.text.*;
    import javafx.scene.control.*;
    import javafx.scene.paint.*;
    import javafx.scene.layout.HBox;
    public class HelloWorld extends Application {
    	public static void main(String[] args) {
    		launch(args);
    	}
    	@Override
    	public void start(Stage primaryStage) {
    		primaryStage.setTitle("JavaFX Welcome");
    		GridPane grid = new GridPane();
    		grid.setAlignment(Pos.CENTER);
    		grid.setHgap(10);
    		grid.setVgap(10);
    		grid.setPadding(new Insets(25, 25, 25, 25));
    //		grid.setGridLinesVisible(true);
    		Text scenetitle = new Text("Welcome");
    		scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
    		grid.add(scenetitle, 0, 0, 2, 1);
    		Label userName = new Label("User Name:");
    		grid.add(userName, 0, 1);
    		TextField userTextField = new TextField();
    		grid.add(userTextField, 1, 1);
    		Label pw = new Label("Password:");
    		grid.add(pw, 0, 2);
    		PasswordField pwBox = new PasswordField();
    		grid.add(pwBox, 1, 2);
    		Button btn = new Button("Sign in");
    		HBox hbBtn = new HBox(10);
    		hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
    		hbBtn.getChildren().add(btn);
    		grid.add(hbBtn, 1, 4);
    		final Text actiontarget = new Text();
    			grid.add(actiontarget, 1, 6);
    		btn.setOnAction(new EventHandler() {
    		    @Override
    		    public void handle(ActionEvent e) {
    			actiontarget.setFill(Color.FIREBRICK);
    			actiontarget.setText("Sign in button pressed");
    		    }
    		});
    		Scene scene = new Scene(grid, 300, 275);
    		primaryStage.setScene(scene);
    		scene.getStylesheets().add
    		     (HelloWorld.class.getResource("HelloWorld.css").toExternalForm());
    		primaryStage.show();
    	}
    }
    

    The commands to compile, run, package in jar and run jar, each in its own CMD file, remain the same.
    Command line
    @"C:\Program Files\Java\jdk1.7.0_40\bin\javac" -d out -classpath "C:\Program Files\Java\jre7\lib\jfxrt.jar" src\helloworld\HelloWorld.java
    @"C:\Program Files\Java\jdk1.7.0_40\bin\java" -classpath "C:\Program Files\Java\jre7\lib\jfxrt.jar;.\out" helloworld.HelloWorld
    @"C:\Program Files\Java\jdk1.7.0_40\bin\javafxpackager" -createjar -appclass helloworld.HelloWorld -srcdir .\out -outfile HelloWorld -v
    @"C:\Program Files\Java\jre7\bin\java.exe" -jar HelloWorld.jar
    @pause
    

    Let's deal with the third section. Tutorial suggests using the blank from the second section. And we’ll do it, only we don’t have Login.java, but HelloWorld.java. It's time to create a CSS file.

    Ignore those paragraphs of the instruction (in the tutorial) that relate to working with the IDE. The fourth paragraph proposes to create a CSS file in the src \ login folder, in our case it turns out src \ helloworld. Well, for now we’ll do just that, just call him, since we continue to greet the world, HelloWorld.css. Although this is not important.

    The sixth paragraph tells what changes need to be made to java code: after the lines
    Scene scene = new Scene(grid, 300, 275);
    primaryStage.setScene(scene);
    
    need to insert
    scene.getStylesheets().add
     (HelloWorld.class.getResource("HelloWorld.css").toExternalForm());
    
    (adjusted for the names of files and classes), exactly before
    primaryStage.show();
    

    In addition, so that text objects can be somehow controlled by the CSS file, you must give these objects the corresponding identifiers. To do this, find the lines
    scenetitle.setFont(Font.font(“Tahoma”, FontWeight.NORMAL, 20));  
    
    and
    actiontarget.setFill(Color.FIREBRICK);
    
    and replace them with
    scenetitle.setId("welcome-text");
    
    and
    actiontarget.setId("actiontarget");
    
    respectively. And it’s better not to replace it just in case, but to close it with a comment, and write down the correction line below.

    And, of course, you need to fill in the file with style sheets.
    HelloWorld.css
    .root {
         -fx-background-image: url("background.jpg");
    }
    .label {
        -fx-font-size: 12px;
        -fx-font-weight: bold;
        -fx-text-fill: #333333;
        -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
    }
    #welcome-text {
       -fx-font-size: 32px;
       -fx-font-family: "Arial Black";
       -fx-fill: #818181;
       -fx-effect: innershadow( three-pass-box , rgba(0,0,0,0.7) , 6, 0.0 , 0 , 2 );
    }
    #actiontarget {
      -fx-fill: FIREBRICK;
      -fx-font-weight: bold;
      -fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );  
    }
    .button {
        -fx-text-fill: white;
        -fx-font-family: "Arial Narrow";
        -fx-font-weight: bold;
        -fx-background-color: linear-gradient(#61a2b1, #2A5058);
        -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 5, 0.0 , 0 , 1 );
    }
    .button:hover {
        -fx-background-color: linear-gradient(#2A5058, #61a2b1);
    }
    

    He filled immediately with everything that the text of the third section is proposed to stick gradually, while admiring the result - background image, text effects, button effects.

    Oh yes, you also need a picture for the background image ... Well, I did not download or draw, but copied the first one. The first came the background (ironically, just in place) from the folder “My drawings \ Samples of drawings” - Sunset.jpg. Renamed it to background.jpg and put it next to the CSS file.

    We compile. Successfully. We start. Does not work! We study the error output. The frequently encountered Unknown source, therefore, an unknown source, is alarming. Plus, there are familiar letters in the midst of all this disgrace:
    at helloworld.HelloWorld.start(HelloWorld.java:68)
    

    And in the sixty-eighth line, we just pick out the styles from the CSS file. Which is laid down according to the instructions in src \ helloworld. In the contest of this “research”, I don’t even want to consider why for NetBeans this file is required in the source folder (although I guess). But, since we never indicated the path to the stylesheet anywhere, it should lie directly next to the one who uses it. And the unpacked program from the HelloWorld.class file is launched, which is in out \ helloworld \. Let's get there and throw it along with the picture.

    Now compiles and runs. True, the background picture is very different from the tutorial one, and the red-brick message about the pressed button on the red background is hard to see, but these are trifles, this can be changed. Another thing is funny - let's now give the packing command to jar and try to run the jar file.

    Does not start! And if they were launched by a console command, and not by clicking on the file itself, then errors are visible, and some of them are familiar ... Let's climb into the jar, as if it were an archive. There lies the folder structure com \ javafx \ main, which is provided by the javafxpackager utility, and META-INF with a manifest, this is not very interesting now. And the helloworld folder is interesting, in which there is no HelloWorld.css, but there is HelloWorld.bss! It turns out that the packer cheekily, without our team, repackaged CSS in a binary form. Check it out? Let's replace the .css extension with .bss in the sixty-eighth line, compile it, but we won’t run it right away, but pack it and run jar right away.

    Now it starts. But, what a shame, it does not start from HelloWorld.class! Do not keep the same two sets of source codes for different cases. Moreover, bss is just recommended for faster downloads. Add the command that we write to the css2bss.cmd file:
    @"C:\Program Files\Java\jdk1.7.0_40\bin\javafxpackager" -createbss -srcdir .\src\helloworld -outdir .\out\helloworld -srcfiles HelloWorld.css -v
    @pause
    

    We’ll throw the CSS and background image files into src \ helloworld \ (as we demanded from the very beginning), in the source file we’ll leave in the line where getStylesheets (), the extension .bss. We compile. We make bss. We pack in jar. Now run from both HelloWorld.class and HelloWorld.jar. And to figure out which styles are responsible for what, and how they can be changed in various ways, I propose on my own. This topic is not directly related to JavaFX.

    Well, the fourth section of the tutorial is FXML. The program code changes so much that it is easier to rewrite it again. And even create a copy of the project in a neighboring folder, for example, GetStartFXML. There you need to copy already five batch files and create the out and src \ helloworld folders, and put the source in the last one.
    HelloWorld.java
    package helloworld;
    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    import javafx.scene.*;
    import javafx.fxml.*;
    public class HelloWorld extends Application {
    	public static void main(String[] args) {
    		launch(args);
    	}
    	@Override
    	public void start(Stage stage) throws Exception {
    	    Parent root = FXMLLoader.load(getClass().getResource("fxml_example.fxml"));
    	    Scene scene = new Scene(root, 300, 275);
    	    stage.setTitle("FXML Welcome");
    	    stage.setScene(scene); 
    	    stage.show();
    	}
    }
    

    Next, you need to collect the file fxml_example.fxml, scattered in the fourth section. Since the data from it will be picked up on the fly, as well as from the CSS file, it is worth making it immediately next to the HelloWorld.class file that uses it, which does not yet exist. That is, in out \ helloworld, so we will create a subfolder in out ourselves ourselves, before the first compilation.
    fxml_example.fxml

    This file immediately includes working with CSS, but why pull something? Therefore, put next to the newly created HelloWorld.css and background.jpg. There is still not enough button event handling. The fourth section proposes to use the separate file mentioned in FXML: GridPane fx: controller = "helloworld.FXMLExampleController".
    FXMLExampleController.java
    package helloworld;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.scene.text.Text;
    public class FXMLExampleController {
    @FXML private Text actiontarget;
    @FXML protected void handleSubmitButtonAction(ActionEvent event) {
    actiontarget.setText("Sign in button pressed");
    }
    }
    

    And of course, do not forget to compile it too, for which we add an additional line to compile.cmd. In addition, I removed the “dog” before the compilation commands to see that both started and worked:
    "C:\Program Files\Java\jdk1.7.0_25\bin\javac" -d out -classpath "C:\Program Files\Java\jre7\lib\jfxrt.jar" src\helloworld\HelloWorld.java 
    "C:\Program Files\Java\jdk1.7.0_40\bin\javac" -d out -classpath "C:\Program Files\Java\jre7\lib\jfxrt.jar" src\helloworld\FXMLExampleController.java
    @pause
    

    We compile. We collect jar. We start class or we launch jar. It works, no differences in appearance and behavior from the previous example are visible. But it turned out to divide the application into a bunch of modules - a separate main class that creates a scene, a separate description of the form, a separate event handler, and separate element styles. Moreover, the style sheets and the description of the form can be changed without recompiling the class, for example, interchanging elements in the cells of the GridPane table or changing the background image.

    However, although it works, but let's take a look at the jar archive. There, by the way, there is no HelloWorld.css file, but there is a .bss, as in the example from the third section. Fxml_example.fxml mentions HelloWorld.css. However, both class and jar work. Let's, as in the previous example, transfer HelloWorld.css and background.jpg from out \ helloworld to src \ helloworld (we will leave the FXML file in place). We compile. We make bss from css. We collect jar. We start class, and then we launch jar. It works again! But what is it - to her in general, or something, no difference? And let's, since the extension of the stylesheet file does not matter, in fxml_example.fxml will we erase it cleanly? Instead
    will do

    But the program doesn’t really give a damn about the extension of the stylesheet - just show it with your finger and then it will figure it out. Funny right?

    Now there is a training ground for bullying - you can try all kinds of style changes, design, event processing and all that. You can try to run this workpiece not on the desktop, but in the browser - a little is mentioned in the sixth section of the tutorial. But there is a little and uninteresting, about the deployment of applications there is a separate guide. I don’t want to tackle the fifth section either, on Habré it was already well said about the visual effects of JavaFX right here , and the examples given in the tutorial do not at all fit into the framework of the blanks of the first four sections.

    I consider the HelloWorld theme in JavaFX based on jfxpub-overview to be exhausted.

    Also popular now: