簡體   English   中英

有沒有辦法在JAVAFX上實現像“呈現”這樣的屬性?

[英]Is there a way to implement a property like “rendered” on JAVAFX?

如果條件滿足,有沒有辦法只在Javafx中“渲染”一個組件? 我感興趣的是做一個具有不同角色的用戶界面,如果角色允許,只需添加一個組件,我也想繼續使用FXML。 我沒有讀過類似的東西。

綁定可見性

將組件的visible屬性 綁定BooleanExpression,表示應該可見的條件。

FXML可以進行綁定 ,但請注意,從JavaFX 2.2開始“目前僅支持解析為屬性值或頁面變量的簡單表達式。將來可能會添加對涉及布爾值或其他運算符的更復雜表達式的支持。”

如果不在FXML中綁定,則可以使用JavaFX API綁定Java代碼。

node.visibleProperty().bind(conditionProperty);

如果您不希望不可見屬性占用布局空間,請先將托管屬性綁定到visible屬性。

node.managedProperty().bind(node.visibleProperty());

交替更改更改偵聽器中的可見性

請注意,為基於完整角色的系統設置綁定非常復雜,因此對於此類任務,最好使用更改偵聽器並使用Java編寫邏輯的一部分,而不是嘗試在FXML中執行所有操作。 您仍然可以在FXML中設計UI,但是您可以在控制器中添加一些代碼來管理哪些項目對於哪個角色是可見的。

基於示例角色的顯示

這是一個使用Java API的基於角色的解決方案。

解決方案根據所選角色顯示不同的標記圖片。

角色

import javafx.application.Application;
import javafx.beans.value.*;
import javafx.collections.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.*;

enum Role { father, son, mother, daughter, brother, sister }

class RoleManager {
    private final Map<Node, List<Role>> nodeRoles = new HashMap<>();
    private ObservableList<Role> activeRoles;

    public final ListChangeListener<Role> ACTIVE_ROLE_LISTENER = new ListChangeListener<Role>() {
        @Override
        public void onChanged(Change<? extends Role> c) {
            showActiveNodes();
        }
    };

    public void setActiveRoles(ObservableList<Role> activeRoles) {
        if (this.activeRoles != null) {
            this.activeRoles.removeListener(ACTIVE_ROLE_LISTENER);
        }
        this.activeRoles = activeRoles;
        this.activeRoles.addListener(ACTIVE_ROLE_LISTENER);
    }

    public void showActiveNodes() {
        for (Node node : nodeRoles.keySet()) {
            node.setVisible(isActive(node));
        }
    }

    public void assignRole(Node node, Role... roles) {
        nodeRoles.put(node, Arrays.asList(roles));
    }

    private boolean isActive(Node node) {
        if (activeRoles == null) {
            return false;
        }

        for (Role role: nodeRoles.get(node)) {
            if (activeRoles.contains(role)) {
                return true;
            }
        }

        return false;
    }
}

public class RoleVisibility extends Application {

    private RoleManager roleManager = new RoleManager();

    @Override
    public void start(Stage stage) {
        VBox layout = new VBox(10);
        layout.getChildren().setAll(
            getRoleChooser(),
            createContent()
        );
        layout.setStyle("-fx-padding: 10px; -fx-background-color: cornsilk;");

        roleManager.showActiveNodes();

        stage.setTitle("Role Selector");
        stage.setScene(new Scene(layout));
        stage.show();
    }

    private Node getRoleChooser() {
        ObservableList<Role> activeRoles = FXCollections.observableArrayList();

        VBox roleChooser = new VBox(10);
        for (final Role role: Role.values()) {
            CheckBox checkBox = new CheckBox(role.toString());
            checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> observable, Boolean wasSelected, Boolean isSelected) {
                    if (isSelected) {
                        activeRoles.add(role);
                    } else {
                        activeRoles.remove(role);
                    }
                }
            });

            roleChooser.getChildren().add(checkBox);
        }

        roleManager.setActiveRoles(
            activeRoles
        );

        return roleChooser;
    }

    private Pane createContent() {
        HBox content = new HBox(10);

        // icon license:
        //License: Free for non-commercial use.
        //Commercial usage: Not allowed
        //The products or characters depicted in these icons are © by Lucasfilm Ltd.

        content.getChildren().addAll(
            createLabel("Darth Vader",    "Vader-03-icon.png",          Role.father),
            createLabel("Queen Amidala",  "Padme-Amidala-icon.png",     Role.mother),
            createLabel("Luke Skywalker", "Luke-Skywalker-01-icon.png", Role.brother,  Role.son),
            createLabel("Princess Leia",  "Leia-icon.png",              Role.daughter, Role.sister)
        );

        return content;
    }

    private Label createLabel(String text, String graphic, Role... roles) {
        Label label = new Label(
            text,
            new ImageView(
                new Image(
                    "http://icons.iconarchive.com/icons/jonathan-rey/star-wars-characters/128/" + graphic
                )
            )
        );

        label.setContentDisplay(ContentDisplay.TOP);

        roleManager.assignRole(label, roles);

        return label;
    }


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

基於FXML的解決方案

我對使用FXML這樣的東西感興趣,所以我創建了一個小框架來處理基於角色的FXML UI 它可能有一些性能增強,並為定義基於角色的控制器添加一些便利定義以及FXML中角色定義的縮寫,但它似乎確實在原理上工作並演示了一種基本方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM