JavaFX: classe do controlador e fx: id em FXML



Parece-me que muitos artigos úteis não se justificam, não só não dedicam algumas palavras à questão mais candente quando você começa a trabalhar com o JavaFX, mas também os dedica, eles ainda não o divulgam totalmente. E a questão surge da seguinte maneira: como comunicar seus nós por seu fx: id e seu código. Como você os usa em diferentes partes do seu código para fazer referência à sua API? Isso é o que tentarei responder sob o corte



O que é fx: id e com o que é comido



- , StackOverFlow , , fx:id . . , , .



, , ( ), , StackOverFlow. , , fx:id, FXML . , . " node fx:id ".



, . NullPointerException. , , , id. , exception, , FXML - java-. , , .



, , , . MVC , JavaFX. , . , , javaFX FXML, java , . , , fx:id, .



, , , Oracle. , Oracle, fx:id. , , .



, , .



? , FXML , -, Application, start() ( Main, ) fx:id. . , , , .



, "hello world":



<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.Pane?>
<?import javafx.scene.control.Button?>
<Pane xmlns="http://javafx.com/javafx/1.8.0.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Main">
    <Button fx:id="fxButton" text="clickMe" onAction="#click"/>
</Pane>


public class Main extends Application {
    @FXML
    public Button fxButton;

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

    public void click(ActionEvent actionEvent) {
        System.out.println("Hello World");
        fxButton.setText("Hey!");
    }
}


. , FXML Pane, Button, fx:id="fxButton", , - onAction="#click". click .



, , . ? . , . . MVC - , , , , " ". , — …



, , , click , . start(), , fxButton (/ , , fx:id):



public class Main extends Application {
    @FXML
    public Button fxButton;

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
        //  ,      (  ):
        fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Hello World"));
    }
}


IDE



Exception

Exception in Application start method

java.lang.reflect.InvocationTargetException

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)

at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)

Caused by: java.lang.RuntimeException: Exception in Application start method

at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)

at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)

at java.lang.Thread.run(Thread.java:748)

Caused by: java.lang.NullPointerException

at sample.Main.start(Main.java:25)


at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)

at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)

at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)

at java.security.AccessController.doPrivileged(Native Method)

at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)

at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)

at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)

… 1 more

Exception running application sample.Main



Process finished with exit code 1



, , , . , FXML , , click , fx:id.

, FXML. java FXML, , , Button fxButton, — . , . , , ...



IDE, , IDEA, , ( FXML Controller, Main ). . , , Main , , .



, node FXML , , . , . , fx:id.



, ( , fx:id ), ( — ), NullPointerException , , WHY? - , fx:id, , , , - ? ?



, , ...



, , . , . , , , . , . javaFX, .



FXML. .



<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<Pane xmlns="http://javafx.com/javafx/1.8.261" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Controller">
    <VBox layoutX="14.0" prefHeight="50.0" prefWidth="50.0">
        <Button fx:id="fxButton" onAction="#click" text="clickMe" />
        <Label fx:id="labelFx" minHeight="17.0" minWidth="185.0" text="label" />
    </VBox>
</Pane>


Main. , , FXML



public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("YourFXML.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}


Controller. FXML java .



public class Controller extends View implements Initializable {
    @FXML
    private Button fxButton;
    @FXML
    private Label labelFx;
    @FXML
    Label localLabel;
    @FXML
    public void click(ActionEvent actionEvent) {
        System.out.println("Hello World");
        fxButton.setText("Hey!");
        labelLocalInitialize();
    }

    private void labelLocalInitialize(){
        localLabel = labelFx;
        localLabel.setText("local variable control");
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //      View  labelFx
        setViewLabelFxText("transfer of control in View \"labelFx\" variable");
        //  ,     ,    
        fxButton.addEventHandler(MouseEvent.MOUSE_CLICKED, mouseEvent -> System.out.println("Listener triggered"));
    }
}


View. , .



public class View {
    @FXML
    private Label labelFx;

    public void setViewLabelFxText(String text){
        labelFx.setText(text);
    }
}


View , fx:id.



  1. FXML .



  2. id node , node fx:id.





, . :



FXML labelFx, initialize() , , .



:



"Hello World", "Hey!", labelLocalInitialize(), labelFx. , labelFx .



:



  • initialize(), node fx:id. node, FXML. Controller View fx:id
  • onAction ( ) FXML, , , click, , initialize
  • fx:id , View, , View.
  • JavaFX FXML Controller, Main. , . , FXML. . , FXML , , .
  • Main.java — , FXML. , .
  • Controller.java — , java FXML . , . fx:id, , .


Em algum lugar acima, eu disse que há mágica no javaFX. Ele começa na classe View. Ao que parece, seria óbvio se fosse possível herdar classes do controlador para trabalhar com id, mas acontece o contrário ... Por que isso é feito, não entrei em detalhes, embora esteja curioso por que é assim. Se pessoas conhecedoras abrirem o véu do sigilo nos comentários, ficarei muito grato.




All Articles