2016-05-31 6 views
0

Я создал приложение JavaFX, которое почти завершено. Я экспортировал его как runnable JAR. При открытии этого JAR я вижу только пустое окно. Я выполнил некоторые другие ответы из stackoverflow, но я не получил его работу. Он работает только в среде Eclipse!Java: Экран не был загружен

Мои экраны контроллера:

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 { 
 

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

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

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

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

И здесь я использую его:

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; 
 
\t 
 
\t public static final String MAIN_SCREEN = "main"; 
 
\t public static final String MAIN_SCREEN_FXML = "gui\\MainMenu.fxml"; \t 
 
\t 
 
\t @Override 
 
\t public void start(Stage primaryStage) { 
 
\t \t 
 
\t \t this.mainStage = primaryStage; 
 
\t 
 
\t \t ScreensController mainContainer = new ScreensController(); 
 
\t \t 
 
\t \t mainContainer.loadScreen(MainMenu.MAIN_SCREEN, MainMenu.MAIN_SCREEN_FXML); \t 
 
\t \t 
 
\t \t mainContainer.setCoreService(MainMenu.coreService); 
 
\t \t 
 
\t \t mainContainer.setScreen(MainMenu.MAIN_SCREEN); 
 
\t \t Group root = new Group(); 
 
\t \t root.getChildren().addAll(mainContainer); 
 
\t \t Scene scene = new Scene(root); 
 
\t \t primaryStage.setScene(scene); 
 
\t \t primaryStage.setOnCloseRequest(confirmCloseEventHandler); 
 
\t \t primaryStage.show(); 
 
\t \t 
 
\t } 
 
\t 
 
    private EventHandler<WindowEvent> confirmCloseEventHandler = event -> { 
 
    \t //Source: http://stackoverflow.com/questions/29710492/javafx-internal-close-request 
 
     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(); 
 
     } 
 
    }; 
 
\t 
 
\t public static void main(String[] args, CoreService aService) { \t 
 
\t \t // Weitergeben des CoreServices 
 
\t \t coreService = aService; 
 
\t \t launch(args); 
 
\t } 
 

 
}

I не вижу, где ошибка. Когда я запускаю программу из командной строки, он говорит, что файл MainMenu.fxml не найден. В моем приложении оно находится в пакете gui. -> gui/MainMenu.fxml

Было бы хорошо, если бы кто-то нашел мою ошибку!

ответ

0

В сообщении об ошибке указано, что файл 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); 

... (и вам не нужны переменные file и f) ...

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

Некоторые ссылки:

  • Я был ответ here о том, как использовать getResource.
  • Также вы можете проверить documentation of getResource()
  • И вы можете проверить this вопрос о загрузке ресурсов из JAR
+0

Спасибо, я попытался почти то, что вы предложили, но я пропустил, чтобы добавить ведущую косую черту перед пути ! Спасибо за ответ! –

Смежные вопросы