JavaFX TabPane初始化时仅含1个Tab且Tab为空,调用方法触发空指针异常
问题
场景刚打开时,FXML里定义的TabPane只认默认选中的那个Tab,调用tabpane.getTabs().size()一直返回1,其他Tab调用getTabPane()全是null,执行权限控制代码直接抛空指针。切过Tab之后功能就正常,但我得在切换前就把Tab权限控制好。
代码片段
public TabPane tabpane; public Tab sellScreenTab; public Tab buyScreenTab; public Tab stockControlTab; public Tab logTab; public Tab userTab; public Tab statisticsTab; public void editTabsForUsers(){ System.out.println(tabpane.getTabs().size()); if (!Session.user.sellScreenPerm){ sellScreenTab.getTabPane().getTabs().remove(sellScreenTab); }if (!Session.user.entryScreenPerm){ buyScreenTab.getTabPane().getTabs().remove(buyScreenTab); }if (!Session.user.historyScreenPerm){ logTab.getTabPane().getTabs().remove(logTab); }if (!Session.user.statsScreenPerm){ statisticsTab.getTabPane().getTabs().remove(statisticsTab); }if (!Session.user.trackStockScreenPerm){ stockControlTab.getTabPane().getTabs().remove(stockControlTab); }if (!Session.user.usersScreenPerm){ userTab.getTabPane().getTabs().remove(userTab); } }
抛出的异常
Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TabPane.getTabs()" because the return value of "javafx.scene.control.Tab.getTabPane()" is null
原因
JavaFX为了优化性能,场景初始化时只会加载默认选中的Tab,其他没被选中的Tab还没和TabPane建立关联,也没被加入到TabPane的tabs列表里,所以这些Tab的getTabPane()返回null,tabpane.getTabs().size()自然只有1。
解决办法
别通过Tab自己的getTabPane()去拿列表,直接操作TabPane的tabs集合就行,而且操作前先判断Tab是否在集合里,避免报错。
修改后的editTabsForUsers():
public void editTabsForUsers(){ if (!Session.user.sellScreenPerm && tabpane.getTabs().contains(sellScreenTab)){ tabpane.getTabs().remove(sellScreenTab); } if (!Session.user.entryScreenPerm && tabpane.getTabs().contains(buyScreenTab)){ tabpane.getTabs().remove(buyScreenTab); } if (!Session.user.historyScreenPerm && tabpane.getTabs().contains(logTab)){ tabpane.getTabs().remove(logTab); } if (!Session.user.statsScreenPerm && tabpane.getTabs().contains(statisticsTab)){ tabpane.getTabs().remove(statisticsTab); } if (!Session.user.trackStockScreenPerm && tabpane.getTabs().contains(stockControlTab)){ tabpane.getTabs().remove(stockControlTab); } if (!Session.user.usersScreenPerm && tabpane.getTabs().contains(userTab)){ tabpane.getTabs().remove(userTab); } }
另外,要在场景初始化完成后调用这个方法,比如在控制器的initialize()方法里执行:
@Override public void initialize(URL url, ResourceBundle resourceBundle) { editTabsForUsers(); }
要是发现有些Tab没被自动加到TabPane的列表里,就手动加进去(确保FXML里的Tab都已经绑定到控制器的对应字段):
@Override public void initialize(URL url, ResourceBundle resourceBundle) { tabpane.getTabs().addAll(sellScreenTab, buyScreenTab, stockControlTab, logTab, userTab, statisticsTab); editTabsForUsers(); }
内容的提问来源于stack exchange,提问作者rotroq
相关产品推荐
相关产品推荐

