所以我一直在研究一个项目,我有一个CharmListView,它填充了要使用的任务的名称。我可以通过登录屏幕登录,访问CharmListView并单击我想要打开的任务。当我测试它时,它会在桌面上打开,但在Android中它会失败,说找不到位置,并且:
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.gluonhq.charm.glisten.mvc.View.setName(java.lang.String)' on a null object reference
以下是我的魅力课程:
这个本质上是任务模型。
public class CharmHomeNavTask {
private String taskName;
private String taskDesc;
private static final Image IMAGE_ADMIN = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/admin.png"));
private static final Image IMAGE_AUDIT_TOOL = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/auditTool.png"));
private static final Image IMAGE_CONSOLIDATE_PACKAGE = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/consolidatePackage.png"));
private static final Image IMAGE_DISPOSAL = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/disposal.png"));
private static final Image IMAGE_EQUIP_MANGAGE = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/equipmentManagement.png"));
private static final Image IMAGE_INTRA_TRANSFER = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/intratransfer.png"));
private static final Image IMAGE_PICKUP = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/pickup.png"));
private static final Image IMAGE_TRU_WASTE_PREP = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/truWastePrep.png"));
private static final Image IMAGE_VISUAL_INSPECTION = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/visualInspection.png"));
private static final Image IMAGE_WALL2WALL = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/wall2wall.png"));
private static final Image IMAGE_WASTE_ID = new Image(WcatsAndroidDemo.class.getResourceAsStream("/gov/lanl/taskImages/wasteIdentification.png"));
private static Image[] listOfImages = {IMAGE_WASTE_ID, IMAGE_VISUAL_INSPECTION, IMAGE_TRU_WASTE_PREP, IMAGE_CONSOLIDATE_PACKAGE, IMAGE_INTRA_TRANSFER, IMAGE_PICKUP, IMAGE_DISPOSAL, IMAGE_ADMIN, IMAGE_WALL2WALL,
IMAGE_EQUIP_MANGAGE, IMAGE_AUDIT_TOOL };
public CharmHomeNavTask(String taskName, String taskDesc){
this.taskName = taskName;
this.taskDesc = taskDesc;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getTaskDesc() {
return taskDesc;
}
public void setTaskDesc(String taskDesc) {
this.taskDesc = taskDesc;
}
public static void setListOfImages(Image[] listOfImages) {
listOfImages = listOfImages;
}
public static Image[] getListOfImages(){
return listOfImages;
}
public static Image getSingleImageFromList(int index){
return listOfImages[index];
}
}
这是将任务创建为ObservableList
public class CharmHomeNavTasks {
public static ObservableList<CharmHomeNavTask> tasksList = FXCollections.observableArrayList(
new CharmHomeNavTask("Waste Identification", "Identify you waste from this screen."),
new CharmHomeNavTask("TRU Visual Inspection", "Visual Inspection of TRU waste."),
new CharmHomeNavTask("TRU Drum Preparation", "Prepare your TRU drums here."),
new CharmHomeNavTask("Consolidation/Packaging", "Consolidate and package your waste."),
new CharmHomeNavTask("Intra-Facility Transfer", "Transferring of waste within the same facility."),
new CharmHomeNavTask("Inter-Facility Pickup", "Picking up waste within the same facility."),
new CharmHomeNavTask("Disposal Tasks", "Disposal of waste tasks."),
new CharmHomeNavTask("Administrative Tasks", "Administrators have special tasks they can perform here."),
new CharmHomeNavTask("Wall-Wall Inventory", "Wall to Wall inventory tasks."),
new CharmHomeNavTask("Equipment Management", "Waste related equipment tasks."),
new CharmHomeNavTask("Audit Support Tool", "Tool for audit related tasks."));
public static ObservableList<CharmHomeNavTask> getTasksList() {
return tasksList;
}
}
这是给我带来麻烦的,因为我在这里有我的onMouseClicked事件,我将项目(或任务)设置为选中。这似乎在Android上运行正常,因为我可以让系统告诉我哪个项目被点击了。
public class CharmHomeNavTaskCell extends CharmListCell<CharmHomeNavTask> {
private final ListTile tile;
private final ImageView imageView;
private CharmHomeNavTask item;
public CharmHomeNavTask carryOverItem;
public CharmHomeNavTaskCell(CharmListView listView){
tile = new ListTile();
imageView = new ImageView();
tile.setPrimaryGraphic(imageView);
carryOverItem = item;
tile.setOnMouseClicked(e -> {
System.out.println("******************* Item clicked " + item.getTaskName());
listView.setSelectedItem(item);
});
setText(null);
}
@Override
public void updateItem(CharmHomeNavTask item, boolean empty){
super.updateItem(item, empty);
this.item = item;
imageView.setFitWidth(32);
imageView.setFitHeight(32);
if (item != null && !empty) {
tile.textProperty().setAll(item.getTaskName() + " ", item.getTaskDesc());
tile.setWrapText(true);
final Image[] image = CharmHomeNavTask.getListOfImages();
super.setStyle("-fx-font-weight: bold");
switch (item.getTaskName()) {
case "Waste Identification":
imageView.setImage(image[0]);
break;
case "TRU Visual Inspection":
imageView.setImage(image[1]);
break;
case "TRU Drum Preparation":
imageView.setImage(image[2]);
break;
case "Consolidation/Packaging":
imageView.setImage(image[3]);
break;
case "Intra-Facility Transfer":
imageView.setImage(image[4]);
break;
case "Inter-Facility Pickup":
imageView.setImage(image[5]);
break;
case "Disposal Tasks":
imageView.setImage(image[6]);
break;
case "Administrative Tasks":
imageView.setImage(image[7]);
break;
case "Wall-Wall Inventory":
imageView.setImage(image[8]);
break;
case "Equipment Management":
imageView.setImage(image[9]);
break;
case "Audit Support Tool":
imageView.setImage(image[10]);
break;
}
setGraphic(tile);
} else {
setGraphic(null);
}
}
}
这是AppViewManager类。我正在使用Glisten和Afterburner让你知道。
public class AppViewManager {
private static String getLoggedInUser(User user){
if (user != null) {
return user.getId();
} else {
return "Not Logged In";
}
}
public static final AppViewRegistry REGISTRY = new AppViewRegistry();
public static final AppView PRIMARY_VIEW = view("Home", PrimaryPresenter.class, MaterialDesignIcon.HOME, SHOW_IN_DRAWER, HOME_VIEW);
public static final AppView SECONDARY_VIEW = view("Task List", SecondaryPresenter.class, MaterialDesignIcon.LIST, SHOW_IN_DRAWER);
public static final AppView SETTINGS_VIEW = view("Settings", SettingsView.class, MaterialDesignIcon.SETTINGS_APPLICATIONS, SHOW_IN_DRAWER);
public static final AppView INTRAFACILITYTRANSFER_VIEW = view("Intra-Facility Transfer", IntraFacilityView.class, MaterialDesignIcon.EDIT_LOCATION);
private static AppView view(String title, Class<? extends GluonPresenter<?>> presenterClass, MaterialDesignIcon menuIcon, AppView.Flag... flags ) {
return REGISTRY.createView(name(presenterClass), title, presenterClass, menuIcon, flags);
}
private static String name(Class<? extends GluonPresenter<?>> presenterClass) {
return presenterClass.getSimpleName().toUpperCase(Locale.ROOT).replace("PRESENTER", "");
}
public static void registerViewsAndDrawer(MobileApplication app) {
for (AppView view : REGISTRY.getViews()) {
view.registerView(app);
}
Image image = new Image(WcatsAndroidDemo.class.getResourceAsStream("/icon.png"));
NavigationDrawer.Header header = new NavigationDrawer.Header("\nWCATS" + "- " + getLoggedInUser(WcatsAndroidDemo.getInstance().getLoggedUser()),
"Waste Management System", new ImageView(image));
// TODO: Add a footer to the drawer that contains settings, help & feedback, and About
NavigationDrawer.Footer footer = new NavigationDrawer.Footer("No tasks currently need to be synchronized.", null);
//Create the sub items for the drawer
NavigationDrawer.Item about = new NavigationDrawer.Item("About", MaterialDesignIcon.INFO.graphic());
NavigationDrawer.Item logOut = new NavigationDrawer.Item("Logout", MaterialDesignIcon.EXIT_TO_APP.graphic());
// TODO: make the rest of the submenu items that go in the header.
DefaultDrawerManager drawerManager = new DefaultDrawerManager(app, header, REGISTRY.getViews()) {
{
NavigationDrawer drawer = getDrawer();
drawer.visibleProperty().addListener((observable, oldValue, newValue) -> {
if (newValue){
header.setTitle("\nWCATS - " + getLoggedInUser(WcatsAndroidDemo.getInstance().getLoggedUser()));
}
});
// Add items
drawer.setFooter(footer);
footer.setStyle("-fx-text-size: 6");
drawer.getItems().addAll(new Separator(), about, logOut, new Separator());
// TODO: provide action based on item selected
drawer.selectedItemProperty().addListener(((observable, oldValue, newValue) -> {
if(newValue.equals(about)) {
System.out.println("test");
} else if (newValue.equals(logOut)){
WcatsAndroidDemo.getInstance().userLogout();
} else if (newValue.equals(SECONDARY_VIEW.getMenuItem())){
if (getLoggedInUser(WcatsAndroidDemo.getInstance().getLoggedUser()).equals("Not Logged In")) {
AppViewManager.PRIMARY_VIEW.switchView();
} else {
AppViewManager.SECONDARY_VIEW.switchView();
}
}
} ));
}
};
drawerManager.installDrawer();
}
}
最后,这是我要导航的视图的Presenter类,并希望转到所选的任务。
public class SecondaryPresenter extends GluonPresenter<WcatsAndroidDemo> {
@FXML
private View homeView;
@FXML
public CharmListView<CharmHomeNavTask, Integer> charmListView;
public void initialize() {
homeView.setShowTransitionFactory(BounceInRightTransition::new);
AppBar appBar = getApp().getAppBar();
homeView.showingProperty().addListener((observable, oldValue, newValue) -> {
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> getApp().showLayer(DRAWER_LAYER)));
appBar.setTitleText("Task Selection");
});
charmListView.setFloatingHeaderVisible(false);
charmListView.setItems(CharmHomeNavTasks.getTasksList());
charmListView.setCellFactory(param -> new CharmHomeNavTaskCell(charmListView));
charmListView.selectedItemProperty().addListener((observable, oldValue, newValue) -> {
if (newValue.getTaskName().equals("Intra-Facility Transfer")){
AppViewManager.INTRAFACILITYTRANSFER_VIEW.switchView(ViewStackPolicy.SKIP);
}
});
}
}
万一你确实需要它来解决这个问题,我试图导航到这个视图。
public class IntraFacilityView extends GluonPresenter<WcatsAndroidDemo> {
@FXML
public ChoiceBox facilityCMBox;
@FXML
public ChoiceBox storageUnitOrgCMBox;
@FXML
public ChoiceBox storageUnitDestCMBox;
@FXML
public ChoiceBox gridXCMBox;
@FXML
public ChoiceBox gridYCMBox;
@FXML
public ChoiceBox gridZCMBox;
@FXML
public CheckBox organizeUnitCHKBox;
@FXML
public Button viewMoreReqsBTN;
@FXML
public Button viewPendingMovesBTN;
@FXML
public Button resumeTaskBTN;
@FXML
private View intrafacility;
public void initialize(){
intrafacility.setShowTransitionFactory(BounceInRightTransition::new);
intrafacility.showingProperty().addListener((observable, oldValue, newValue) -> {
if (newValue) {
AppBar appBar = getApp().getAppBar();
appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> {
getApp().showLayer(DRAWER_LAYER);
}));
appBar.setTitleText("Intra-Facility Transfer");
appBar.getActionItems().add(MaterialDesignIcon.CLOSE.button(e -> {
AppViewManager.SECONDARY_VIEW.switchView();
}));
}
});
}
public void handleOrganizeUnitsCHKBox(ActionEvent actionEvent) {
}
public void handleViewMoreReqs(ActionEvent actionEvent) {
}
public void handleResumeTask(ActionEvent actionEvent) {
}
public void handlevVewPendingMoves(ActionEvent actionEvent) {
}
}
我知道有些Android设备并不是JavaFxPorts的最佳设备,但我还没有看到任何有关像三星这样的已知问题的松下硬盘。我确实需要做一些笨拙的东西让abdroid设备将这些触摸注册为点击,但现在看起来工作正常。
这让我陷入停顿,因为我无法弄清楚为什么Android无法找到该位置,但它在桌面上运行良好。
这是文件结构: