有没有办法在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> nodeRoles = new HashMap<>(); private ObservableList activeRoles; public final ListChangeListener ACTIVE_ROLE_LISTENER = new ListChangeListener() { @Override public void onChanged(Change c) { showActiveNodes(); } }; public void setActiveRoles(ObservableList 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 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() { @Override public void changed(ObservableValue 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中角色定义的缩写,但它似乎在原则上起作用并演示了一种基本方法。