自定义组件 JavaFX 的自定义动作发射器 属性 - 怎么样?
Custom action emitter property for custom component JavaFX - How?
在开发 JavaFX 应用程序项目的过程中,这是我第一个真正的笨蛋,我什至不知道如何正确地说出我想做的事情,因为我不知道我尝试使用的技术的名称。
在我的应用程序中,我有多个自定义组件,因此我可以构建更复杂的场景。本题涉及3个控制组件;一个 PrimaryControl 组件 (SplitPane),它包含一个 MenuComponent 和一个 ActivityComponent(都是自定义的),它们根据在 MenuComponent 中设置的单选按钮的选择而改变。
如何让 MenuControl class 到 "emit" 当 ToggleGroup(来自该组件)中的单选按钮发生更改时执行的操作,然后将由父级中的函数处理组件 PrimaryControl 以便它可以更改哪个 ActivityComponent 是 visible/active?忍耐一下。
primary_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
<MenuControl onToggleGroupButtonSelectionChanged="#onChange"/>
<ActivityOneControl fx:id="one" isVisible="true"/>
<ActivityTwoControl fx:id="two" isVisible="false"/>
...
</fx:root>
menu_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.2-internal">
<GridPane alignment="CENTER" hgap="10" vgap="10">
<padding><Insets bottom="25" left="25" right="25" top="15" /></padding>
<Label text="Select A Task" GridPane.columnIndex="0" GridPane.rowIndex="0">
<font><Font name="System Bold" size="13.0" /></font>
</Label>
<fx:define>
<ToggleGroup fx:id="menuSelection"/>
</fx:define>
<RadioButton fx:id="one" text="one" GridPane.columnIndex="0" GridPane.rowIndex="1" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="two" text="two" GridPane.columnIndex="0" GridPane.rowIndex="2" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="three" text="three" GridPane.columnIndex="0" GridPane.rowIndex="3" toggleGroup="$menuSelection">
</RadioButton>
</GridPane>
</fx:root>
如何在我的 MenuControl java class 中创建一个侦听器,它将能够检测到 ToggleGroup 选择更改,然后将该更改发送到 onToggleGroupButtonSelectionChanged="#onChange"
以便我可以处理从 PrimaryControl java class 选择按钮?我记得在 Angular 做过这种事情,这很容易,但出于某种原因,我找不到任何关于如何做到这一点的信息 Java。这就是所谓的依赖注入吗?
我发现了这个 link 并尝试解决我的问题但没有成功,因为没有任何解释并且正在为 JavaFX 2.0 - create action handler for custom component in FXML 侦听不同的事件。
PrimaryController.java(与MenuControl.java相同)
public class PrimaryControl extends VBox {
public DashboardControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("primary_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
@FXML
protected void onChange() {
System.out.println("change activity");
}
}
提前感谢任何帮助我的人。
- 首先,创建一个代表可能选择的枚举:
public enum SelectionMode {
ONE, TWO, THREE
}
- 现在,将 属性 添加到您的 Menu 控件,使其他控件能够知道选择了什么,而无需暴露其背后的逻辑或使其可从其他控件更改(使用
ReadOnlyObjectProperty
) :
private ReadOnlyObjectWrapper<SelectionMode> selectionMode
= new ReadOnlyObjectWrapper<>(this, "selectionMode");
public final ReadOnlyObjectProperty<SelectionMode> selectionModeProperty() {
return selectionMode.getReadOnlyProperty();
}
private final SelectionMode getSelectionMode() {
return selectionMode.get();
}
- 将此 属性 绑定到菜单控制器 class 的
initialize
方法中选定的单选按钮。请注意,我使用的是 setUserData
和 getUserData
方法,否则,您需要为每个单选按钮添加一个 if 子句:
@Override
public void initialize(URL location, ResourceBundle resources) {
one.setUserData(SelectionMode.ONE);
two.setUserData(SelectionMode.TWO);
three.setUserData(SelectionMode.THREE);
selectionMode.bind(Bindings.createObjectBinding(() -> {
Toggle selectedToggle = menuSelection.getSelectedToggle();
return (SelectionMode) selectedToggle.getUserData();
}, menuSelection.selectedToggleProperty()));
}
- 您的主控制器 class 可以通过在
<MenuControl fx:id="menu"/>
中设置一个 ID 来访问其菜单控制器。
然后你可以只分配一个 ChangeListener
并在每次更改选择时得到通知:
menu.selectionModeProperty().addListener((observable, oldValue, newValue) -> {
// write your code here
});
注意:您可以像这样在您的 fxml 中初始化用户数据(而不是在 initialize
方法中这样做):
<RadioButton fx:id="one" text="one" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="ONE"/>
</userData>
</RadioButton>
<RadioButton fx:id="two" text="two" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="TWO"/>
</userData>
</RadioButton>
<RadioButton fx:id="three" text="three" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="THREE"/>
</userData>
</RadioButton>
在开发 JavaFX 应用程序项目的过程中,这是我第一个真正的笨蛋,我什至不知道如何正确地说出我想做的事情,因为我不知道我尝试使用的技术的名称。
在我的应用程序中,我有多个自定义组件,因此我可以构建更复杂的场景。本题涉及3个控制组件;一个 PrimaryControl 组件 (SplitPane),它包含一个 MenuComponent 和一个 ActivityComponent(都是自定义的),它们根据在 MenuComponent 中设置的单选按钮的选择而改变。
如何让 MenuControl class 到 "emit" 当 ToggleGroup(来自该组件)中的单选按钮发生更改时执行的操作,然后将由父级中的函数处理组件 PrimaryControl 以便它可以更改哪个 ActivityComponent 是 visible/active?忍耐一下。
primary_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
<MenuControl onToggleGroupButtonSelectionChanged="#onChange"/>
<ActivityOneControl fx:id="one" isVisible="true"/>
<ActivityTwoControl fx:id="two" isVisible="false"/>
...
</fx:root>
menu_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.2-internal">
<GridPane alignment="CENTER" hgap="10" vgap="10">
<padding><Insets bottom="25" left="25" right="25" top="15" /></padding>
<Label text="Select A Task" GridPane.columnIndex="0" GridPane.rowIndex="0">
<font><Font name="System Bold" size="13.0" /></font>
</Label>
<fx:define>
<ToggleGroup fx:id="menuSelection"/>
</fx:define>
<RadioButton fx:id="one" text="one" GridPane.columnIndex="0" GridPane.rowIndex="1" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="two" text="two" GridPane.columnIndex="0" GridPane.rowIndex="2" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="three" text="three" GridPane.columnIndex="0" GridPane.rowIndex="3" toggleGroup="$menuSelection">
</RadioButton>
</GridPane>
</fx:root>
如何在我的 MenuControl java class 中创建一个侦听器,它将能够检测到 ToggleGroup 选择更改,然后将该更改发送到 onToggleGroupButtonSelectionChanged="#onChange"
以便我可以处理从 PrimaryControl java class 选择按钮?我记得在 Angular 做过这种事情,这很容易,但出于某种原因,我找不到任何关于如何做到这一点的信息 Java。这就是所谓的依赖注入吗?
我发现了这个 link 并尝试解决我的问题但没有成功,因为没有任何解释并且正在为 JavaFX 2.0 - create action handler for custom component in FXML 侦听不同的事件。
PrimaryController.java(与MenuControl.java相同)
public class PrimaryControl extends VBox {
public DashboardControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("primary_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
@FXML
protected void onChange() {
System.out.println("change activity");
}
}
提前感谢任何帮助我的人。
- 首先,创建一个代表可能选择的枚举:
public enum SelectionMode {
ONE, TWO, THREE
}
- 现在,将 属性 添加到您的 Menu 控件,使其他控件能够知道选择了什么,而无需暴露其背后的逻辑或使其可从其他控件更改(使用
ReadOnlyObjectProperty
) :
private ReadOnlyObjectWrapper<SelectionMode> selectionMode
= new ReadOnlyObjectWrapper<>(this, "selectionMode");
public final ReadOnlyObjectProperty<SelectionMode> selectionModeProperty() {
return selectionMode.getReadOnlyProperty();
}
private final SelectionMode getSelectionMode() {
return selectionMode.get();
}
- 将此 属性 绑定到菜单控制器 class 的
initialize
方法中选定的单选按钮。请注意,我使用的是setUserData
和getUserData
方法,否则,您需要为每个单选按钮添加一个 if 子句:
@Override
public void initialize(URL location, ResourceBundle resources) {
one.setUserData(SelectionMode.ONE);
two.setUserData(SelectionMode.TWO);
three.setUserData(SelectionMode.THREE);
selectionMode.bind(Bindings.createObjectBinding(() -> {
Toggle selectedToggle = menuSelection.getSelectedToggle();
return (SelectionMode) selectedToggle.getUserData();
}, menuSelection.selectedToggleProperty()));
}
- 您的主控制器 class 可以通过在
<MenuControl fx:id="menu"/>
中设置一个 ID 来访问其菜单控制器。 然后你可以只分配一个ChangeListener
并在每次更改选择时得到通知:
menu.selectionModeProperty().addListener((observable, oldValue, newValue) -> {
// write your code here
});
注意:您可以像这样在您的 fxml 中初始化用户数据(而不是在 initialize
方法中这样做):
<RadioButton fx:id="one" text="one" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="ONE"/>
</userData>
</RadioButton>
<RadioButton fx:id="two" text="two" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="TWO"/>
</userData>
</RadioButton>
<RadioButton fx:id="three" text="three" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="THREE"/>
</userData>
</RadioButton>