Felhasználói eszközök

Eszközök a webhelyen


oktatas:programozas:java:java_fx:scene_builder

< Java FX

Scene Builder

A SceneBuilder beszerzése

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

Rendelkezésre áll:

  • Windowsos .msi csomag. Például: SceneBuilder-19.0.0.msi
  • Linuxos .deb csomag. Például: SceneBuilder-19.0.0.deb

Windowson

Windowson az .msi fájl alapértelmezetten profilba telepszik.

Linuxon

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:

  • SceneBuilder extension for Visual Studio Code

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

Windows esetén, egy lehetséges útvonal:

c:\Users\janos\AppData\Local\SceneBuilder\

VSCodium

Bővítmény

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

  • SceneBuilder extension for Visual Studio Code

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:

  • Open in Scene Builder

A SceneBuilder 21 esetén ha main.fxml nevet adok a fájlnak, akkor megnyitáskor eltűnik az ablak keret minden vezérlővel.

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:

  • A kezelő metódus nevét a jobboldalon a Button „Code” tulajdonságainál.
  • Bal oldalon a „Controller” tulajdonságoknál meg kell adni a kontroller osztályt.
    • Ha még nincs kontroller megadható, például az App osztály.

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ő

  • F1
  • Java: Create Java Project…
  • JavaFX - (create from archetype) (Provided by Maven for Java)
  • group Id: com.example
  • artifact Id: demo
  • Kiválasztjuk milyen könyvtárban hozzuk létre a projektet [Kiválasztás]

A Maven bekéri a verziót:

  • 'version' 1.0-SNAPSHOT: :
  • javafx-version: 13 Y: :
  • Enter

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

A modell osztályban kötelező a getter, setter metódusok létrehozása.

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");
  }
}

ObservableList

@FXML
private TableView<Employee> empTable;
 
//...
 
ArrayList<Employee> emps = employeeSource.getEmployees();
ObservableList<Employee> observableEmps = FXCollections.observableArrayList(emps);
empTable.setItems(observableEmps);

Gomb szelekcióhoz kötése

startButton.disableProperty()
    .bind(table.getSelectionModel()
    .selectedItemProperty().isNull());
src/main/java/com/example/MainController.java
package com.example;
 
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
 
public class MainController {
 
    @FXML
    private TableView<Employee> table;
 
    @FXML
    private TableColumn<Employee, Integer> idCol;
 
    @FXML
    private TableColumn<Employee, String> naemCol;
 
    @FXML
    private Button startButton;
 
    @FXML
    private void initialize() {
        idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
        naemCol.setCellValueFactory(new PropertyValueFactory<>("name"));
 
        ObservableList<Employee> data = FXCollections.observableArrayList();
        data.add(new Employee(1, "name1"));
        data.add(new Employee(2, "name2"));
        data.add(new Employee(3, "name3"));
        data.add(new Employee(4, "name4"));
        table.setItems(data);
 
        startButton.disableProperty()
        .bind(table.getSelectionModel()
        .selectedItemProperty().isNull());
    }
 
    @FXML
    void onClickStartButton(ActionEvent event) {
 
    }
 
}

Gomb mező értéke alapján

Nem csak kiválasztottnak kell lennie, de a kiválasztott sor értéke ne legyen „name3”:

startButton.disableProperty()
    .bind(table.getSelectionModel()
    .selectedItemProperty().isNull()
    .or(
        Bindings.select(
            table.getSelectionModel()
            .selectedItemProperty(), "name")
            .isEqualTo("name3")
    )
);
oktatas/programozas/java/java_fx/scene_builder.txt · Utolsó módosítás: 2024/10/11 18:26 szerkesztette: admin