Вложенные пользовательские компоненты javafx - ClassNotFoundException - PullRequest
0 голосов
/ 25 апреля 2020

Так что я знаю, что уже есть много постов о подобных проблемах, но этот немного странный, и, поскольку я уже потратил 5 часов на эту проблему, я обращаюсь к своему последнему средству.

Все, что я пытаюсь сделать, - это создать 2 пользовательских компонента и поместить один из них в другой из файла f xml. Это должно быть очень просто, и я делал это раньше с другими типами компонентов, но по какой-то причине сейчас это не нравится. Взгляните,
SecondaryInterface.kt

import javafx.fxml.FXMLLoader
import javafx.scene.control.Label
import javafx.scene.layout.GridPane
import java.io.IOException

class SecondaryInterface : GridPane() {

    @FXML private lateinit var label: Label

    init {

        println("From SecondaryInterface: ")
        println("\t" + MainInterface::class.java)
        println("\t" + javaClass.getResource("main_interface.fxml"))
        println("\t" + javaClass.getResource("SecondaryInterface.kt"))
        println("\t" + javaClass.getResource("secondary_interface.fxml"))

        val fxmlLoader = FXMLLoader(javaClass.getResource("secondary_interface.fxml"))
        fxmlLoader.setRoot(this)
        fxmlLoader.setController(this)
        try {
            fxmlLoader.load<Any>()
        } catch (exception: IOException) {
            throw RuntimeException(exception)
        }
    }

}

вторичный_интерфейс.f xml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<fx:root type="javafx.scene.layout.GridPane" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml">

    <Label fx:id="label" text="This is the secondary interface"></Label>

</fx:root>

Вторичным интерфейсом является вложенный компонент. Что-нибудь смотришь? Далее
MainInterface.kt

import javafx.fxml.FXML
import javafx.fxml.FXMLLoader
import javafx.scene.layout.GridPane
import java.io.IOException

class MainInterface : GridPane() {

    @FXML private lateinit var secondInterface: SecondaryInterface

    init {
        println("From MainInterface: ")
        println("\t" + MainInterface::class.java)
        println("\t" + javaClass.getResource("main_interface.fxml"))
        println("\t" + javaClass.getResource("SecondaryInterface.kt"))
        println("\t" + javaClass.getResource("secondary_interface.fxml"))

        val fxmlLoader = FXMLLoader(javaClass.getResource("main_interface.fxml"))
        fxmlLoader.setRoot(this)
        fxmlLoader.setController(this)
        try {
            fxmlLoader.load<Any>()
        } catch (exception: IOException) {
            throw RuntimeException(exception)
        }
    }
}

main_interface.f xml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import SecondaryInterface?>

<fx:root type="javafx.scene.layout.GridPane"
         xmlns="http://javafx.com/javafx"
         xmlns:fx="http://javafx.com/fxml">

    <Label text="This is primary interface"></Label>
    <SecondaryInterface fx:id="secondInterface"></SecondaryInterface>

</fx:root>

Вывод / Ошибка StackTrace

From MyApplication: 
    class MainInterface
    file:/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/main_interface.fxml
    null
    file:/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/secondary_interface.fxml
From MainInterface: 
    class MainInterface
    file:/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/main_interface.fxml
    null
    file:/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/secondary_interface.fxml
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException: 
/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/main_interface.fxml

    at MainInterface.<init>(MainInterface.kt:24)
    at MyApplication.start(MyApplication.kt:24)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    ... 1 more
Caused by: javafx.fxml.LoadException: 
/E:/Programming/Tests/NestedCustomComponents/out/production/NestedCustomComponents/main_interface.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
    at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2863)
    at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.processProcessingInstruction(FXMLLoader.java:2676)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2542)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
    at MainInterface.<init>(MainInterface.kt:22)
    ... 10 more
Caused by: java.lang.ClassNotFoundException
    at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2914)
    at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2861)
    ... 16 more

Process finished with exit code 1

Я слишком долго анализировал это и не смог извлечь из этого ничего полезного -_-
Вот что я пробовал до сих пор:

  • Двойная проверка соглашений об именах (имена пакетов в нижнем регистре и имена классов начинаются с заглавных букв)
  • Повторная сборка проекта несколько раз
  • Проверка правильности импорта
  • Печать отладочного текста, такого как classpath, как видно из кода и вывода, чтобы проверить, заметны ли требуемые файлы (почему он не может найти мои файлы .kt, но может найти мои файлы .f xml?)
  • Указание контроллера fx: в файлах .f xml
  • Использование internal constructor() (после имени класса)
  • Объявление классов как open
  • Добавление аргументов VM
    --module-path
    C:\javafx-sdk-11.0.2\lib
    --add-modules
    javafx.controls,javafx.fxml

Это был более крупный проект, над которым я работаю. Я сократил все, чтобы упростить проблему.
Вот другие классы, которые вам нужны, если вы хотите попробовать сами,

Main.kt

import javafx.application.Application

fun main(args: Array<String>) {
    Application.launch(MyApplication::class.java)
}

MyApplication.kt

import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.layout.Pane
import javafx.stage.Stage
import MainInterface //Not imported because in same package

class MyApplication : Application() {

    fun main(args: Array<String>) { launch(*args) }

    override fun start(primaryStage: Stage) {

        val mainScene = Scene(Pane(), 475.0, 425.0)
        ScreenController.stage = primaryStage
        ScreenController.scene = mainScene
        ScreenController.bindSceneWithStage()

        println("From MyApplication: ")
        println("\t" + MainInterface::class.java)
        println("\t" + javaClass.getResource("main_interface.fxml"))
        println("\t" + javaClass.getResource("/SecondaryInterface.kt"))
        println("\t" + javaClass.getResource("secondary_interface.fxml"))

        ScreenController.addScene("mainInterface", MainInterface()) //Crashes here

        ScreenController.stage!!.show()
        ScreenController.activateScene("mainInterface")
    }
}

ScreenController.kt

import javafx.scene.Scene
import javafx.scene.layout.Pane
import javafx.stage.Stage
import java.util.*

object ScreenController {

    var stage: Stage? = null
    var scene: Scene? = null
    private val mapOfCustomPanes = mutableMapOf<String, Pane>()

    fun bindSceneWithStage() {
        stage!!.scene = scene!!
    }

    fun addScene(name: String, pane: Pane) {
        mapOfCustomPanes[name] = pane
    }

    fun removeScene(name: String?) {
        mapOfCustomPanes.remove(name)
    }

    fun activateScene(name: String?) {
        scene!!.root = mapOfCustomPanes[name]
    }
}

Любая помощь будет принята с благодарностью, так как я серьезно растерялся с этим. Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...