JavaFX使用ObversableList.getItems(). addall()不能多次使用



我试图用checkMenuItems的arrayList在javaFX中填充多个菜单按钮。要添加复选菜单项,我正在做:

myMenuButton.getItems().addAll(ChecKMenuItemList);

我的代码是这样的

class Scratch {

private void updateClassList(ArrayList<Class> classArrayList) {
ArrayList<String> classCodeList = new ArrayList<>();
ArrayList<CheckMenuItem> checkMenuItemList = new ArrayList<>();
ArrayList<CheckMenuItem> checkMenuItemList2 = new ArrayList<>();
ArrayList<String> classNameList = new ArrayList<>();
//Create Arrays of class elements
for(Class aClass : classArrayList){
checkMenuItemList.add(new CheckMenuItem(aClass.getClassCode()));
}
//Clear Class Lists
addStudentsToClassClassListView.getItems().clear();
assignClassesToTeachersClassListView.getItems().clear();
//Populate dropdown lists
addStudentSelectClassesMenuButton.getItems().setAll(checkMenuItemList);
addTeacherSelectClasses.getItems().setAll(checkMenuItemList);
}
}

该函数在用户输入json文件后从另一个函数调用,该json文件被解析为数据。

我遇到的问题是,当我尝试使用.getItems().addAll()时,它只工作一次,在我的代码中,如果你注释两行中的一行,另一行将工作,反之亦然,这很奇怪,因为它们自己工作,但不能一起工作

因为它们都是自己工作的,我不确定是什么问题导致它不太更新。没有错误或异常,什么都没有发生。在这两行代码执行完之后,在调试过程中,在函数完成之前,它显示两个菜单按钮都有6个项目,但是当你点击菜单按钮时,什么也没有发生

问题不在这里:

ObservableList.getItems().addAll()不能多次使用

绝对可以多次使用。

ObservableList<Integer> list = FXCollections.observableArrayList(1, 2, 3);
list.addAll(4, 5, 6);
list.addAll(7, 8, 9);
System.out.println(list);

将按预期输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

但是,您需要在上下文中正确使用api。

场景图中的项目一次只能出现在一个位置。CheckMenuItem不是一个节点,但它可能由节点支持,因此像一个节点,所以我不会一次将单个实例添加到多个菜单中。

相反,创建另一个CheckMenuItem实例,使用相同的数据,并添加它。双向绑定可用于确保,如果选中了一个菜单项,则更新另一个菜单项的状态以反映选中,反之亦然。

查看场景javadoc:

一个节点在场景图的任何地方最多只能出现一次。具体来说,一个节点在Parent的子列表中或作为node的剪辑出现的次数不得超过一次。有关这些限制的更多详细信息,请参阅Node类。

节点javadoc:

如果程序将子节点添加到父节点(包括Group, Region等),并且该节点已经是不同父节点的子节点或场景的根节点,则该节点将自动(并且无声地)从其先前的父节点中删除。.

看来CheckMenuItem也有同样的作用。如果Menu文档规定项目一次只能出现在一个菜单中,可能会更好。

故障和修复示例

在本例中,创建了两个菜单,并将相同的项添加到两个菜单中。在执行时,只有一个菜单(最后一个添加项目的菜单)将包含添加的项目。

在系统错误控制台中,执行警告您有问题。

Dec 13, 2022 4:00:27 PM javafx.scene.control.Menu$6 onChanged
WARNING: Adding MenuItem Check 1 that has already been added to Menu 1
Dec 13, 2022 4:00:27 PM javafx.scene.control.Menu$6 onChanged
WARNING: Adding MenuItem Check 2 that has already been added to Menu 1
<<p>破代码/em>
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class MenuItemApp extends Application {
@Override
public void start(Stage stage) throws Exception {
MenuItem[] menuItems = createCheckMenuItems();
Menu menu1 = new Menu("Menu 1");
menu1.getItems().addAll(menuItems);
Menu menu2 = new Menu("Menu 2");
menu2.getItems().addAll(menuItems);
MenuBar menuBar = new MenuBar(menu1, menu2);
Scene scene = new Scene(menuBar);
stage.setScene(scene);
stage.show();
}
private MenuItem[] createCheckMenuItems() {
return new MenuItem[] {
new CheckMenuItem("Check 1"),
new CheckMenuItem("Check 2")
};
}
public static void main(String[] args) {
Application.launch();
}
}

我们可以通过为每个菜单创建新的检查菜单项来解决这个问题。

Menu menu1 = new Menu("Menu 1");
menu1.getItems().addAll(createCheckMenuItems());
Menu menu2 = new Menu("Menu 2");
menu2.getItems().addAll(createCheckMenuItems());

但是现在检查菜单项是不同步的,如果你改变一个,另一个不会自动改变。如果你也想要这种行为,你可以使用带有共享绑定的MVC方法。

修复了与模型属性双向绑定的代码

import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class MenuItemApp extends Application {
class Model {
private final BooleanProperty boolean1 = new SimpleBooleanProperty();
private final BooleanProperty boolean2 = new SimpleBooleanProperty();
public BooleanProperty boolean1Property() {
return boolean1;
}
public BooleanProperty boolean2Property() {
return boolean2;
}
}
@Override
public void start(Stage stage) throws Exception {
Model model = new Model();
Menu menu1 = new Menu("Menu 1");
menu1.getItems().addAll(createCheckMenuItems(model));
Menu menu2 = new Menu("Menu 2");
menu2.getItems().addAll(createCheckMenuItems(model));
MenuBar menuBar = new MenuBar(menu1, menu2);
Scene scene = new Scene(menuBar);
stage.setScene(scene);
stage.show();
}
private MenuItem[] createCheckMenuItems(Model model) {
return new MenuItem[] {
createCheckMenuItem(1, model.boolean1Property()),
createCheckMenuItem(2, model.boolean2Property()),
};
}
private CheckMenuItem createCheckMenuItem(int n, BooleanProperty modelProperty) {
CheckMenuItem checkMenuItem = new CheckMenuItem("Check " + n);
checkMenuItem.selectedProperty().bindBidirectional(modelProperty);
return checkMenuItem;
}
public static void main(String[] args) {
Application.launch();
}
}

最新更新