当前位置: 首页 > 知识库问答 >
问题:

有没有办法在JAVAFX上实现类似“rendered”的属性?

姜嘉荣
2023-03-14

有没有办法只在满足条件时才在Javafx中“渲染”组件?我有兴趣做一个具有不同角色的用户界面,如果角色允许,只需添加一个组件,我也想继续使用FXML。我没有读过类似的东西。

共有1个答案

寿元白
2023-03-14

绑定可见性

将组件的visible属性绑定到BooleanExpression,该BooleanExpression表示该组件应可见的条件。

FXML可以进行绑定,但请注意,从JavaFX 2.2开始,“目前仅支持解析为属性值或页面变量的简单表达式。将来可能会添加对涉及布尔或其他运算符的更复杂表达式的支持。”

如果不在 FXML 中绑定,则可以使用 JavaFX API 在 Java 代码中绑定。

node.visibleProperty().bind(conditionProperty);

如果不想让不可见属性占用布局空间,也要先将托管属性绑定到可见属性。

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 UIs。它可能会有一些性能增强,并为定义基于角色的控制器添加一些方便的定义,以及为FXML中的角色定义添加缩写,但它似乎在原理上是可行的,并演示了一种基本方法。

 类似资料:
  • 问题内容: 首先,我阅读了埃里克森对“为什么不能在Java接口中定义静态方法?”的有用答复。。这个问题不是关于“为什么”的问题,而是关于“然后如何做”的问题。 编辑:我的原始示例不适当地,但我将其保留在下面。 虽然我现在确信在大多数情况下我想做的是过度矫kill过正,但在一种情况下可能需要这样做: 我再举一个例子。现在,让我们采用一个适合于查找表的复杂功能,例如Bessel函数。这必须进行初始化,

  • 假设有一个类库X的输入文件,其中包含一些接口。 为了使用这个库,我需要传递一个与。当然,我可以在源文件中创建相同的接口: 但这样一来,我就有了让它和库中的一个保持最新的负担,而且它可能非常大,并导致大量代码重复。 因此,有没有办法“提取”接口的这个特定属性的类型?类似于(这不起作用,导致“找不到名称I2”错误)。 编辑:在TS操场上玩了一会儿后,我注意到以下代码完全实现了我想要的: 但是,它需要声

  • 问题内容: 在Python中实现方法非常容易,这样它就可以处理这样的调用: 而且有很多相似的方法,你可以定义(,,等)。我知道Python类也是对象。 我的问题:例如,我可以以某种方式进行定义以使以下工作有效: 问题答案: 你正在寻找被称为“元类” ......就像是类的一个实例,是为好,被称为元类类的一个实例。默认情况下,Python类是该类的实例(唯一的例外是Python 2,它具有一些旧式的

  • 问题内容: 我知道您可以通过执行 node.requestFocus(); 来将焦点集中在javafx中的一个节点上 。 但是有没有办法从javafx中的节点上夺走焦点或阻止对某个对象的焦点? 问题答案: 我不认为有任何保证将始终有效,但是您可以尝试将焦点设置为本质上不接受键盘输入的内容(例如布局窗格):

  • 问题内容: 假设我们具有以下类层次结构: 如果像这样在ClassB上浏览 dict ,我只会看到bar属性: 输出为bar 我可以运用自己的方式来获取属性,不仅是指定类型,还包括其祖先。但是,我的问题是python是否已经有一种方法可以在不重新发明轮子的情况下做到这一点。 如下运行我的代码… …同时返回bar和foo。 请注意,我正在简化一些事情:名称冲突,在本例中可以使用dict时使用items

  • 我试图在java中使用Hibernate和TypedQuery。 我试图调用的方法有一个签名 我想像bellow一样调用它,但是用一个真实的实例替换null。 上面的代码经过编译,但显然带有空指针异常。 如果我对擦除的理解是正确的,那么只要我得到类对象的一个实例,这就行了,因为所有泛型类型信息在运行时都会丢失。 是否有任何方法,我可以得到一个类的实例,我可以分配给变量cls,使这个代码将工作?