Java: 屏幕尚未加载

Java: Screen has not been loaded

我创建了一个即将完成的 JavaFX 应用程序。我将它导出为可运行的 JAR。打开这个 JAR 时,我只看到一个空白 window。我遵循了 Whosebug 的其他一些答案,但我没有让它工作。 它只适用于 Eclipse IDE!

我的屏幕控制器:

package gui;

import java.io.File;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;

public class ScreensController extends StackPane {

 private HashMap<String, Node> screens = new HashMap<>();
 public static String sourcePath = "";
 private CoreService coreService;
 
 public ScreensController(){
  super();
 }
 
 
 public void addScreen(String name, Node screen) { 
        screens.put(name, screen); 
    } 
 
 public boolean loadScreen(String name, String resource) { 
  System.out.println("ID: "+name);
  System.out.println("Resource: "+resource);

  String file = System.getProperty("user.dir")+"\bin\"+resource;
//  System.out.println(file);
  
     try { 
        FXMLLoader myLoader = new FXMLLoader();
        File f = new File(file);
        URL url = f.toURI().toURL();
        myLoader.setLocation(url);
//        System.out.println("Location: "+myLoader.getLocation());
        
        Parent loadScreen = (Parent) myLoader.load(); 
        ControlledScreen myScreenControler = 
               ((ControlledScreen) myLoader.getController()); 
        myScreenControler.setScreenParent(this); 
        addScreen(name, loadScreen); 
        System.out.println("Anzahl Screens: "+screens.size());
        return true; 
      }catch(Exception e) { 
       System.out.println("Fehler beim Laden von "+file);
       System.out.println(e.getMessage()); 
       return false; 
      }
      
 } 

 
 public boolean setScreen(final String name) { 
  @SuppressWarnings("unused")
  Node screenToRemove;
        if(screens.get(name) != null){   //screen loaded
          if(!getChildren().isEmpty()){    //if there is more than one screen
            getChildren().add(0, screens.get(name));     //add the screen
            screenToRemove = getChildren().get(1);
            getChildren().remove(1);                    //remove the displayed screen
          }else{
           getChildren().add(screens.get(name));       //no one else been displayed, then just show
         }
         return true;
         }else {
          System.out.println("Screen hasn't been loaded!!! \n");
          return false;
         }     
 }
 
 public boolean unloadScreen(String name) { 
  if(screens.remove(name) == null) { 
   System.out.println("Screen didn't exist!!!"); 
         return false; 
       } else { 
            return true; 
        } 
 }

 public void print() {
  Set<String> keys = screens.keySet();
  Iterator<String> it = keys.iterator();
  while (it.hasNext()){
   System.out.println("Key: "+it.next());
  } 
  
 } 
 
 public CoreService getCoreService(){
  return this.coreService;
 }
 
 public void setCoreService(CoreService coreService){
  this.coreService = coreService;
 }
 
}

我在这里使用它:

package gui;


import java.util.Optional;

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;

public class MainMenu extends Application {

    private Stage mainStage;
    private static CoreService coreService;
 
 public static final String MAIN_SCREEN = "main";
 public static final String MAIN_SCREEN_FXML = "gui\MainMenu.fxml"; 
 
 @Override
 public void start(Stage primaryStage) {
  
  this.mainStage = primaryStage;
 
  ScreensController mainContainer = new ScreensController();
  
  mainContainer.loadScreen(MainMenu.MAIN_SCREEN, MainMenu.MAIN_SCREEN_FXML); 
  
  mainContainer.setCoreService(MainMenu.coreService);
  
  mainContainer.setScreen(MainMenu.MAIN_SCREEN);
  Group root = new Group();
  root.getChildren().addAll(mainContainer);
  Scene scene = new Scene(root);
  primaryStage.setScene(scene);
  primaryStage.setOnCloseRequest(confirmCloseEventHandler);
  primaryStage.show();
  
 }
 
    private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
     //Source: 
        Alert closeConfirmation = new Alert(
                Alert.AlertType.CONFIRMATION,
                "Are you sure you want to exit?"
        );
        Button exitButton = (Button) closeConfirmation.getDialogPane().lookupButton(
                ButtonType.OK
        );
        exitButton.setText("Exit");
        closeConfirmation.setHeaderText("Confirm Exit");
        closeConfirmation.initModality(Modality.APPLICATION_MODAL);
        closeConfirmation.initOwner(mainStage);

        closeConfirmation.setX(mainStage.getX() + 150);
        closeConfirmation.setY(mainStage.getY() - 300 + mainStage.getHeight());

        Optional<ButtonType> closeResponse = closeConfirmation.showAndWait();
        if (!ButtonType.OK.equals(closeResponse.get())) {
            event.consume();
        }
    };
 
 public static void main(String[] args, CoreService aService) { 
  // Weitergeben des CoreServices
  coreService = aService;
  launch(args);
 }

}

我看不出错误在哪里。 当我从命令行启动程序时,它说找不到 MainMenu.fxml 文件。 在我的应用程序中,它位于 gui 包中。 -> gui/MainMenu.fxml

如果有人发现我的错误就太好了!

错误消息告诉您,找不到 FXML 文件。

您可以尝试:

改变这个...

public static final String MAIN_SCREEN_FXML = "gui\MainMenu.fxml"; 

...到...

public static final String MAIN_SCREEN_FXML = "/gui/MainMenu.fxml"; 

并改变这个...

FXMLLoader myLoader = new FXMLLoader();
File f = new File(file);
URL url = f.toURI().toURL();
myLoader.setLocation(url);

... 至(并且您不需要变量 filef)...

FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));

部分参考资料:

  • 我有一个关于如何使用 getResource 的答案
  • 您也可以查看 documentation of getResource()
  • 你可以查看this关于从 JAR 加载资源的问题