我一直在开发一个具有mainPane窗格的应用程序,该窗格在其中存储了多个较小的窗格。首先,我为每个按下的按钮添加一个侦听器,在按下某个特定按钮后,应该会出现一个相关窗格。一切正常,直到我意识到每次按下按钮都会添加一个新的窗格实例,并最终在后台某处最初选择的窗格上失去进度。从那以后,我尝试尝试从主父窗格的getChildren()方法中加载现有窗格,但是我在此方面没有取得太大的成功。我试图在这里到处找到解决方案,但是找不到与我的问题相关的任何东西,或者如果发现了某些东西,我可能根本不理解。我的问题如下:如果我可以将子窗格添加到父窗格以使用mainPane.getChildren().add(root)开头,那么我添加了一个简单的布尔型开关,如果添加了该窗格并且该类型的窗格已经被设置添加了-尝试使其与mainPane.getChildren().get(intArray[0]).toFront();一起显示。但是,将其添加到所有其他按钮处理程序时,.toFront()方法似乎按照添加窗格的顺序显示窗格。因此,如果我最初按按钮trackerButton,progressButton,communityButton,blockerButton-然后按trackerButton 4次,则窗格将显示-> trackerPane,progressPane,communityPane,,然后再按一次,再次遍历这些内容。有没有一种更干净的方法可以实现此目的,因此如果我多次按一个按钮,它只会加载它的关联窗格,而不用blockerPane添加它的新实例?任何帮助将不胜感激,我在下面粘贴了我的代码:public class MainController {private Client client;@FXMLTrackerPaneController trackerPaneController;@FXMLProgressController progressController;@FXMLCommunityController communityController;@FXMLBlockerController blockerController;@FXMLSettingsController settingsController;@FXMLLabel userLabel;@FXMLButton logoutButton;@FXMLButton trackerButton;@FXMLButton progressButton;@FXMLButton communityButton;@FXMLButton blockerButton;@FXMLButton settingsButton;@FXMLPane mainPane;Integer[] intArray = new Integer[4];final Boolean[] booleanArray = {true,true,true,true,true};@FXMLprivate void handlePanelButtonAction(ActionEvent event) throws IOException { if(event.getSource() == trackerButton) { if(booleanArray[0]) { FXMLLoader trackerLoader = new FXMLLoader(getClass().getResource("/view/TrackerPane.fxml")); Parent root = (Parent) trackerLoader.load(); trackerPaneController = trackerLoader.getController(); trackerPaneController.setClient(client); mainPane.getChildren().add(root); intArray[0] = mainPane.getChildren().indexOf(root); } mainPane.getChildren().get(intArray[0]).toFront(); booleanArray[0]=false; } else if(event.getSource() == progressButton) { if(booleanArray[1]) { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/ProgressPane.fxml")); Parent root = (Parent) loader.load(); progressController = loader.getController(); progressController.setClient(client); mainPane.getChildren().add(root); intArray[1] = mainPane.getChildren().indexOf(root); } mainPane.getChildren().get(intArray[1]).toFront(); booleanArray[1]=false; } else if(event.getSource() == communityButton) { if(booleanArray[2]) { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/CommunityPane.fxml")); Parent root = (Parent) loader.load(); communityController = loader.getController(); communityController.setClient(client); mainPane.getChildren().add(root); intArray[2] = mainPane.getChildren().indexOf(root); } mainPane.getChildren().get(intArray[2]).toFront(); booleanArray[2]=false; } else if(event.getSource() == blockerButton) { if(booleanArray[3]) { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/BlockerPane.fxml")); Parent root = (Parent) loader.load(); blockerController = loader.getController(); blockerController.setClient(client); mainPane.getChildren().add(root); intArray[3] = mainPane.getChildren().indexOf(root); } mainPane.getChildren().get(intArray[3]).toFront(); booleanArray[3]=false; } else if(event.getSource() == settingsButton) { if(booleanArray[4]) { FXMLLoader loader = new FXMLLoader(getClass().getResource("/view/SettingsPane.fxml")); Parent root = (Parent) loader.load(); settingsController = loader.getController(); settingsController.setClient(client); mainPane.getChildren().add(root); intArray[4] = mainPane.getChildren().indexOf(root); } mainPane.getChildren().get(intArray[4]).toFront(); booleanArray[4]=false; } else if(event.getSource() == logoutButton) { client.logout(); Platform.exit(); }}}我觉得对于具有适当技能的人来说,解决方案非常简单,但是我对JavaFX还是很陌生,任何帮助将不胜感激。亲切的问候 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 问题在于,在toFront上调用Node会导致该节点移动到父布局的最后一个索引。这导致在某些情况下某些索引变得错误。要解决此问题,只需将Node而不是索引存储在数据结构中即可。还要注意,基本上所有加载代码看起来都一样,除了一些细微的差别。您应该避免重复代码,因为这会使您的代码难以维护。通过向控制器添加接口,可以轻松删除重复的代码。@FXMLprivate void handlePanelButtonAction(ActionEvent event) throws IOException { if(event.getSource() == trackerButton) { ... } else if(event.getSource() == progressButton) { ... } else if(event.getSource() == communityButton) { ... } else if(event.getSource() == blockerButton) { ... } else if(event.getSource() == settingsButton) { ... } else if(event.getSource() == logoutButton) { ... }}不要做这样的事情。如果逻辑完全不同,则Button应该接收它自己的事件处理程序方法。即使代码足够相似,您也应避免与某些节点检查源的引用是否相等。相反,您可以将信息存储在userData的properties或Node中。建议与您的控制器实现以下接口:public interface ClientContainer { void setClient(Client client);}用userData初始化按钮的URL:public class MainController { ... private void setResource(Node node, String resource) { URL url = getClass().getResource(resource); if (url == null) { throw new IllegalArgumentException("Resource not available: " + resource); } node.setUserData(url); } private static URL getResource(Object source) { return (URL) ((Node) source).getUserData(); } @FXML private void initialize() { setResource(trackerButton, "/view/TrackerPane.fxml"); setResource(progressButton, "/view/ProgressPane.fxml"); setResource(communityButton, "/view/CommunityPane.fxml"); setResource(blockerButton, "/view/BlockerPane.fxml"); setResource(settingsButton, "/view/SettingsPane.fxml"); }}使用此数据和Map避免重新加载场景。 (您还需要将用于处理logoutButton单击的代码移到其他方法。)private final Map<URL, Node> loadedContent = new HashMap<>();@FXMLprivate void handlePanelButtonAction(ActionEvent event) { loadedContent.computeIfAbsent(getResource(event.getSource()), url -> { try { FXMLLoader loader = new FXMLLoader(url); Node result = loader.load(); ClientContainer controller = loader.getController(); controller.setClient(client); mainPane.getChildren().add(result); return result; } catch (IOException ex) { throw new RuntimeException(ex); } }).toFront();} (adsbygoogle = window.adsbygoogle || []).push({});
07-24 20:32