【问题标题】:StackOverflowError loading a FXML fileStackOverflowError 加载 FXML 文件
【发布时间】:2014-09-12 12:20:42
【问题描述】:

大家好,我通过 FXMLLoader 加载 fxml 文件总是出错。我有这个课程:

package mediabox.app.model;

import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import mediabox.app.controller.Controller;

/**
 * Objekte diser Klasse repräsentieren Fenster
 * @author Christian
 */
public class Window {

    private final Stage stage;

    /**
     * 
     * @param resourceURL Pfad der zu ladenden FXML Datei
     * @param controller Controller des Fensters
     * @param height Höhe des Fensters
     * @param width  Breite des Fensters
     * @param resizable Gibt an ob das Fenster maximierbar sein soll
     * @param fullscreen Gibt an ob das Fenster als Vollbild geöffnet wird
     * @throws IOException 
     */
    public Window(String resourceURL, Controller controller, int height, int width, boolean resizable, boolean fullscreen) throws IOException{
        FXMLLoader loader = new FXMLLoader(getClass().getResource(resourceURL)); //Lädt die zugehörige FXML
        loader.setController(controller);
        Parent root = (Parent)loader.load();
        Scene scene = new Scene(root, height, width);
        stage = new Stage();
        stage.setResizable(resizable);
        stage.setFullScreen(fullscreen);
        stage.setScene(scene);
    }


    /**
     * Zeigt das Fenster
     */
    public void show(){
        stage.show();
    }

    /**
     * Versteckt das Fenster
     */
    public void hide(){
        stage.hide();
    }
}

这是我的窗口类。

        package mediabox.app.controller;

import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.VBox;
import javafx.scene.media.MediaView;
import javax.naming.NamingException;
import mediabox.app.model.DatabaseConnector;
import mediabox.app.model.Music;
import mediabox.app.model.Window;
import mediabox.app.model.exceptions.ConnectionException;

/**
 * FXML Controller class
 * Diese Klasse repräsentiert den MusicscreenController. Er steuert alle Aktion
 * die auf auf dem Musicscreen getätigt werden. D.h auch die Aktionen die
 * innerhalb der Tabelle(Datenbank) und der Playlist ausgeführt werden.
 * @author Christian
 */
public final class MusicscreenController extends Controller implements Initializable {

    @FXML private VBox box;

    //@FXML private Node playlistNode;
    @FXML private final TableView libraryNode;
    @FXML private MediaView mediaPlayerView;


    private final Window musicscreen;

    public MusicscreenController() throws IOException {
        musicscreen = new Window("/mediabox/app/view/MusicscreenView.fxml", this, 0, 0, false, true);
        musicscreen.show();
        libraryNode = new TableView();
        initLibrary();
        libraryNode.requestFocus();
        libraryNode.getSelectionModel().selectFirst();

    }

    /**
     * Initialisiert die Bibliothek
     */
    @Override
    protected void initLibrary(){
        try {
            DatabaseConnector.connectTo("src/mediabox/database/database");
            libraryNode.getItems().addAll(DatabaseConnector.loadEntries("Music")); // Einträge der Datenbank 
                                                                            // auslesen und der library Node hinzufügen 
        } catch (SQLException | ConnectionException | NamingException | ClassNotFoundException ex) {
            Logger.getLogger(MusicscreenController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }


    @FXML
    public void onLibraryRequest(KeyEvent e){
        if(e.getCode().equals(KeyCode.ENTER)){
            try {
                MediaPlayerController mediaPlayerController = new MediaPlayerController((Music)libraryNode.getSelectionModel().getSelectedItem());
            } catch (IOException ex) {
                Logger.getLogger(MusicscreenController.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    }


}

这是我的控制器类。

我在这段代码中找不到任何错误。几天后,代码运行良好....

-GhostfaceChilla-

【问题讨论】:

    标签: controller javafx fxml


    【解决方案1】:

    当您加载 FXML 时,FXML 加载器会在根元素中看到 fx:controller="mediabox.app.controller.MusicscreenController" 属性。这指示它实例化new MusciscreenControllerMusicscreenController 的构造函数调用Window 构造函数。 Window 构造函数创建一个新的FXMLLoader 并调用它的load() 方法,该方法解析FXML,导致它创建一个新的MusicscreenController

    所以你有无限递归。

    您可能只需要完全从控制器中删除构造函数,并将大部分逻辑放在 initialize() 方法中:

    @Override
    public void initialize(URL url, ResourceBundle rb) {
       initLibrary();
        libraryNode.requestFocus();
        libraryNode.getSelectionModel().selectFirst();
    }
    

    您不能真正从控制器显示窗口,因为在您有机会将根节点从 FXML 添加到 Scene 之前,构造函数和 initialize 方法都保证完成。 (此外,您希望您的 FXML-Controller 对足够灵活,以便能够在它们不是 Scene 的根时使用。)

    因此,您要么只从Window 构造函数调用show(),要么从调用Window 构造函数的任何位置调用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 2014-02-03
      • 2016-01-07
      • 2017-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多