简体   繁体   English

有没有办法在JAVAFX上实现像“呈现”这样的属性?

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

Is there a way to only "render" an component in Javafx if a condition is met? 如果条件满足,有没有办法只在Javafx中“渲染”一个组件? I am interested in doing a user interface with different roles and just add a component if the role allows it, also I would like to keep working with FXML. 我感兴趣的是做一个具有不同角色的用户界面,如果角色允许,只需添加一个组件,我也想继续使用FXML。 I haven't read about anything like that. 我没有读过类似的东西。

Bind visibility 绑定可见性

Bind the visible property of your component to a BooleanExpression representing the condition under which it should be visible. 将组件的visible属性 绑定BooleanExpression,表示应该可见的条件。

FXML can do binding , but note that as of JavaFX 2.2 "Only simple expressions that resolve to property values or page variables are currently supported. Support for more complex expressions involving boolean or other operators may be added in the future." FXML可以进行绑定 ,但请注意,从JavaFX 2.2开始“目前仅支持解析为属性值或页面变量的简单表达式。将来可能会添加对涉及布尔值或其他运算符的更复杂表达式的支持。”

If you don't bind in FXML, you can bind in Java code using the JavaFX API. 如果不在FXML中绑定,则可以使用JavaFX API绑定Java代码。

node.visibleProperty().bind(conditionProperty);

If you don't want the invisible property to take up layout space, also first bind the managed property to the visible property. 如果您不希望不可见属性占用布局空间,请先将托管属性绑定到visible属性。

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

Alternately change visibility in change listeners 交替更改更改侦听器中的可见性

Note that setting up a binding for a full role based system is pretty complex, so for such a task you are better off using change listeners and coding part of your logic in Java rather than trying to do everything in FXML. 请注意,为基于完整角色的系统设置绑定非常复杂,因此对于此类任务,最好使用更改侦听器并使用Java编写逻辑的一部分,而不是尝试在FXML中执行所有操作。 You will still be able to design your UI in FXML, but you can add some code in your controller to manage what items are visible for what role. 您仍然可以在FXML中设计UI,但是您可以在控制器中添加一些代码来管理哪些项目对于哪个角色是可见的。

Sample role based display 基于示例角色的显示

Here is a role based solution using the Java API. 这是一个使用Java API的基于角色的解决方案。

The solution shows different labeled pictures depending on the selected roles. 解决方案根据所选角色显示不同的标记图片。

角色

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 Based Solution 基于FXML的解决方案

I was interested in what it would take to get something like this to work with FXML, so I created a small framework to handle role based FXML UIs . 我对使用FXML这样的东西感兴趣,所以我创建了一个小框架来处理基于角色的FXML UI It could perhaps have some performance enhancements and add some convenience definitions for defining role based controllers as well as shorthands for role definitions in the FXML, but it does seem to work in principle and demonstrate a basic approach. 它可能有一些性能增强,并为定义基于角色的控制器添加一些便利定义以及FXML中角色定义的缩写,但它似乎确实在原理上工作并演示了一种基本方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM