Tartalomjegyzék

< Java FX

Scene Builder

A SceneBuilder beszerzése

Ez csak a régi Java 8-hoz van:

Rendelkezésre áll:

A linuxos verzió telepítése:

dpkg -i SceneBuilder-19.0.0.deb

Az /opt könyvtárba telepszik.

Debian GNU/Linux 12-ön, telepítés előtt létre kell hozni egy desktop-directories könyvtárat:
sudo mkdir /usr/share/desktop-directories/

Nélküle a következő hibát kapjuk:

xdg-desktop-menu: No writable system menu directory found.

Visual Studio Code

Bővítmény

Bővítmény telepítése:

A parancs panelon keresztül konfiguráljuk. Gépeljük be:

Scene

Válasszuk a következőt:

Configure Scene Builder path

Keressük meg az előugró párbeszédablakban a futtatható SceneBuilder szerkesztőt.

Például:

/opt/scenebuilder

Amit ki kell választani:

/opt/scenebuilder/bin

VSCodium

Bővítmény

A következő bővítményre van szükség:

A bővítmény nem érhető el tárolóból. Ezért töltsük le innen:

Jobb oldalon találunk egy „Download Extension” linket.

Letöltés után, ha 1.0.1 verzónk van:

codium --install-extension bilalekrem.scenebuilderextension-1.0.1.vsix

VSCode és VSCodium beállítása

A parancs panelon keresztül konfiguráljuk. Gépeljük be:

Scene

Válasszuk a következőt:

Configure Scene Builder path

Keressük meg az előugró párbeszédablakban a futtatható SceneBuilder szerkesztőt.

Amit ki kell választani:

/opt/scenebuilder/bin

VSCode és VSCodium használat

Készítsünk egy üres állományt, például:

mainScene.fxml

vagy:

app.fxml

Az állományon jobb egér gomb, majd:

Az FXML betöltése

A következő sor szükséges az fxml fájl használatához.

Parent root = FXMLLoader.load(getClass().getResource("mainScene.fxml"));

Ezek után a Scene() konstruktorában megadjuk:

Scene scene1 = new Scene(root, 300, 250);

A teljes start() függvény:

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("mainScene.fxml"));
        Scene scene1 = new Scene(root, 300, 250);
        primaryStage.setScene(scene1);
        primaryStage.show();
    }

A kivételeket eldobtuk. A getResource() az IOException kivételt vált ki.

Eseménykezelés

Eseménykezeléshez meg kell adni:

Ha a MainController könyvtárban van, például egy controllers könyvtárban:

controllers.MainController

Vegyük észre a (.) pont karaktert, a (/) perjel vagy a (\) visszaperjel karakter helyett.

Eseménykezelő az App.java fájlon belül:

    @FXML
    protected void onClickMehetGomb(ActionEvent event) {
        System.out.println("Működik");
    }

Ha akcióknak van egy célkomponense azt szerepeltetni kell a SceneBuilder Code részén, a fx:id mezőben, egy tetszőleges névvel:

Ugyanennek a névnek szerepelnie kell az osztályban, ahol hivatkozni szeretnénk rá, egy FXML annotációval:

@FXML private Text celfelirat;

Együtt az eseménykezelővel:

    @FXML
    private Label celfelirat;
 
    @FXML
    protected void onClickMehetGomb(ActionEvent event) {
        celfelirat.setText("Működik");
    }

Teljes kód

App.java
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
 
public class App extends Application {
    public static void main(String[] args) {
        launch(args);
    }
 
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("app.fxml"));
        Scene scene1 = new Scene(root, 300, 250);
        primaryStage.setScene(scene1);
        primaryStage.show();
    }
 
    @FXML
    private Label celfelirat;
 
    @FXML
    protected void onClickMehetGomb(ActionEvent event) {
        celfelirat.setText("Működik");
    }
}
app.fxml
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
 
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="App">
   <children>
      <Label fx:id="celfelirat" text="Első Scene Builder" />
      <Button mnemonicParsing="false" onAction="#onClickMehetGomb" text="Mehet" />
   </children>
</VBox>

MVC

Adott egy projekt, ahol a kontroller külön osztályban van. A következő fájl és könyvtárszerkezet van:

app01/
  |-lib/
  |-src/
  |  |-controllers/
  |  |  `-MainController.java
  |  |-models/
  |  |  `-MainModel.java
  |  |-views/
  |  |  `-MainScene.fxml
  |  `-App.java
  `-README.md

A kontroller a controllers/MainController.java fájlban van. A nézet a mainScene.fxml fájlban.

Mivel írni akarjuk a TextField mezőt, adnunk kell egy fx:id azonosítót:

Megmondjuk a kontroller osztály nevét:

controllers/MainController.java
package controllers;
 
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
import models.MainModel;
 
public class MainController {
    MainModel mainModel;
 
    @FXML
    private TextField textfield1;
 
    public MainController() {
        this.mainModel = new MainModel();
    }
 
    @FXML
    protected void onClickMehetGomb(ActionEvent event) {
        System.out.println("Működik");
        Integer num = this.mainModel.getNum();
        textfield1.setText(num.toString());
    }
 
}
models/MainModel.java
package models;
 
public class MainModel {
    public int getNum() {
        return 15;
    }    
}
views/MainScene.fxml
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.layout.*?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
 
 
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.MainController">
   <children>
      <Label text="Label" />
      <TextField fx:id="textfield1" />
      <Button mnemonicParsing="false" onAction="#onClickMehetGomb" text="Button" />
   </children>
</VBox>
App.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
public class App extends Application {
    public static void main(String[] args)  throws Exception  {
        launch(args);
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("views/MainScene.fxml"));
        Scene scene1 = new Scene(root, 300, 250);
        primaryStage.setScene(scene1);
        primaryStage.show();
    }
 
}

Példa GitHubon

VSCode beépített projektkészítő

A Maven bekéri a verziót:

A VSCode feldob egy ablakot, van rajta egy [Open] gomb. A gombra kattintva a projekt megnyílik.

Kontrollerek könyvtára

src/main/java/module-info.java
module com.example {
    requires javafx.controls;
    requires javafx.fxml;
 
    opens com.example to javafx.fxml;
    exports com.example;
}

Hozzuk létre egy controllers könyvtárat, abban például egy MainController.java fájlt:

src/main/java/com/example/controllers/MainController.java
package com.example.controllers;
 
public class MainController {
 
}

Ha szeretnénk létrehozni egy controllers könyvtárat, amit a FXML-ben (SceneBuilder-ben) szeretnénk használni fel kell vennünk ebbe a fájlba:

src/main/java/module-info.java
module com.example {
    requires javafx.controls;
    requires javafx.fxml;
 
    opens com.example to javafx.fxml;
    opens com.example.controllers to javafx.fxml;
    exports com.example;
}

Így beállítható a kontroller a SceneBuilder felületén:

com.example.controllers.MainController

Táblázat

Implementálni kell az Initializable interfészt:

public class UserController implements Initializable {
 
}

Az egyes osztlopok beállítása:

  @Override
  public void initialize( URL url, ResourceBundle rb ) {
    this.idcol.setCellValueFactory(new PropertyValueFactory<>("id"));
    this.usernamecol.setCellValueFactory(new PropertyValueFactory<>("username"));
    this.passwordcol.setCellValueFactory(new PropertyValueFactory<>("password"));
    this.admincol.setCellValueFactory(new PropertyValueFactory<>("admin"));
    this.enabledcol.setCellValueFactory(new PropertyValueFactory<>("enabled"));
  }

Teljeskód egy UserController.java fájlban:

UserController.java
package lan.zold;
 
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.CheckBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
 
public class UserController implements Initializable {
 
  @FXML
  private TextField username;
 
  @FXML
  private PasswordField password;
 
  @FXML
  private CheckBox admin;
 
  @FXML
  private CheckBox enabled;
 
  @FXML
  private TableView<Employee> usertable;
 
  @FXML
  private TableColumn<Employee, Integer> idcol;
 
  @FXML
  private TableColumn<Employee, String> usernamecol;
 
  @FXML
  private TableColumn<Employee, String> passwordcol;
 
  @FXML
  private TableColumn<Employee, Boolean> admincol;
 
  @FXML
  private TableColumn<Employee, Boolean> enabledcol;
 
  @Override
  public void initialize( URL url, ResourceBundle rb ) {
    this.idcol.setCellValueFactory(new PropertyValueFactory<>("id"));
    this.usernamecol.setCellValueFactory(new PropertyValueFactory<>("username"));
    this.passwordcol.setCellValueFactory(new PropertyValueFactory<>("password"));
    this.admincol.setCellValueFactory(new PropertyValueFactory<>("admin"));
    this.enabledcol.setCellValueFactory(new PropertyValueFactory<>("enabled"));
  }
 
 
  @FXML
  private void addUser() {
    if(this.username.getText().isEmpty() || 
       this.password.getText().isEmpty()) {
      Alert alert = new Alert(Alert.AlertType.ERROR);
      alert.setTitle("Hiba!");
      alert.setHeaderText("Hiba!");
      alert.setContentText("A felhasználónév vagy a jelszó üres!");
      alert.showAndWait();
      return;
    }
    System.out.println("Add user");
    String username = this.username.getText();
    String password = this.password.getText();
    boolean admin = this.admin.isSelected();
    boolean enabled = this.enabled.isSelected();
    System.out.println("User added: " + 
    username + " " + password + " " + 
    admin + " " + enabled);
 
    Employee employee = new Employee();
    employee.id = 0;
    employee.username = username;
    employee.password = password;
    employee.admin = admin;
    employee.enabled = enabled;
    usertable.getItems().add(employee);
 
    this.username.clear();
    this.password.clear();
    this.admin.setSelected(false);
    this.enabled.setSelected(false);
  }
 
  @FXML
  private void deleteUser() {
    if(usertable.getSelectionModel().getSelectedItem() == null) {
      Alert alert = new Alert(Alert.AlertType.ERROR);
      alert.setTitle("Hiba!");
      alert.setHeaderText("Hiba!");
      alert.setContentText("Nincs kijelölt elem!");
      alert.showAndWait();
      return;
    }
    System.out.println("Delete user");
 
    usertable.getItems().remove(usertable.getSelectionModel().getSelectedItem());
  }
 
  @FXML
  private void updateUser() {
    if(usertable.getSelectionModel().getSelectedItem() == null) {
      Alert alert = new Alert(Alert.AlertType.ERROR);
      alert.setTitle("Hiba!");
      alert.setHeaderText("Felhasználó módosítása");
      alert.setContentText("Nincs kijelölt elem!");
      alert.showAndWait();
      return;
    }
    System.out.println("Update user");
 
    Employee employee = usertable.getSelectionModel().getSelectedItem();
    employee.username = this.username.getText();
    employee.password = this.password.getText();
    employee.admin = this.admin.isSelected();
    employee.enabled = this.enabled.isSelected();
 
    usertable.refresh();
  }
 
  @FXML
  private void closeUserStage() throws IOException {
    App.setRoot("main");
  }
}