Неуловимое исключение, вызванное вызовом Stage.show () - PullRequest
0 голосов
/ 23 марта 2020

Редактировать: Мне повезло, что James_D быстро идентифицировал и объяснил это явление в своих комментариях ниже. Теперь, найдя альтернативу использованию PropertyValueFactory (для Groovy пользователей), я решил добавить свой собственный ответ, чтобы помочь кому-нибудь, кому не повезет, и в будущем он будет сбит с толку.


Спецификации Java: 11. ОС: Linux Mint 18.3. Весь этот код приложения и тестирования написан в Groovy (2.5.10), но это не должно быть особенно актуальным (то есть такое же явление должно происходить с эквивалентным проектом, написанным в Java).

У меня есть метод, вызванный из App.start(), где App расширяет javafx.application.Application (поэтому он работает в потоке приложений JAT / JavaFX):

class GraphBuilder {
...
def attachAndShow(Stage stage, Node rootNode) {
    try {
        App.instance.fxmlController.treeTableView.root = rootTreeItem
        App.instance.fxmlController.treeTableView.showRoot = false
        stage.scene = new Scene(rootNode, 1200, 800)
        stage.show()
    }catch( Throwable t ){
        log.error( "got throwable in attachAndShow... $t.message", t )
    }
}

Я TDD продвигаюсь вперед по модели «пика» (непроверенного кода, где я только что мчался вперед), где TreeTableView заполняется. Я подчеркиваю, что нет никаких признаков того, что что-то не так с шипом.

Intrinsi c Чтобы сделать это, нужно установить для столбцов TreeTableView "фабрики значений ячеек", в которых указано имя поле экземпляров класса которого будет установлено как значение TreeItem s.

Класс значения называется Task ... и его первое поле - String title. Я добавил первую фабрику для этого. Но (поскольку я продолжаю с TDD), я добавил фабрику для второго столбца, свойство dueDate, но я еще не включил это поле в Task. Естественно, проверка, чтобы убедиться, что фабрика была установлена ​​с правильным именем свойства, не проходит. Но меня больше интересует, что происходит, когда я делаю Gradle installDist (т. Е. Распространяю автономный исполняемый файл) в этот момент.

Это выполняется: окно отображается. Я вижу, что TreeItem были даны правильные названия. В Терминале я вижу трассировку стека, вызванную моей неспособностью включить обязательное поле (dueDate) в Task экземплярах:

Mar 23, 2020 6:16:25 PM javafx.scene.control.cell.TreeItemPropertyValueFactory getCellDataReflectively
WARNING: Can not retrieve property 'dueDate' in TreeItemPropertyValueFactory: javafx.scene.control.cell.TreeItemPropertyValueFactory@2d1e69d0 with provided class type: class core.Task
java.lang.IllegalStateException: Cannot get property dueDate
    at com.sun.javafx.property.PropertyReference.getProperty(PropertyReference.java:194)
    at javafx.scene.control.cell.TreeItemPropertyValueFactory.getCellDataReflectively(TreeItemPropertyValueFactory.java:185)
    at javafx.scene.control.cell.TreeItemPropertyValueFactory.call(TreeItemPropertyValueFactory.java:158)
    at javafx.scene.control.cell.TreeItemPropertyValueFactory.call(TreeItemPropertyValueFactory.java:136)
    at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:576)
    at javafx.scene.control.TreeTableColumn.getCellObservableValue(TreeTableColumn.java:561)
    at javafx.scene.control.TreeTableCell.updateItem(TreeTableCell.java:632)
    at javafx.scene.control.TreeTableCell.indexChanged(TreeTableCell.java:457)
    at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:120)
    at javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:539)
    at javafx.scene.control.skin.TreeTableRowSkin.updateCells(TreeTableRowSkin.java:276)
    at javafx.scene.control.skin.TableRowSkinBase.<init>(TableRowSkinBase.java:159)
    at javafx.scene.control.skin.TreeTableRowSkin.<init>(TreeTableRowSkin.java:102)
    at javafx.scene.control.TreeTableRow.createDefaultSkin(TreeTableRow.java:529)
    at javafx.scene.control.Control.doProcessCSS(Control.java:897)
    at javafx.scene.control.Control.access$000(Control.java:83)
    at javafx.scene.control.Control$1.doProcessCSS(Control.java:89)
    at com.sun.javafx.scene.control.ControlHelper.processCSSImpl(ControlHelper.java:67)
    at com.sun.javafx.scene.NodeHelper.processCSS(NodeHelper.java:145)
    at javafx.scene.Node.processCSS(Node.java:9529)
    at javafx.scene.Node.applyCss(Node.java:9616)
    at javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1715)
    at javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1692)
    at javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1801)
    at javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2639)
    at javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1245)
    at javafx.scene.Parent.layout(Parent.java:1204)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.scene.Scene.doLayoutPass(Scene.java:576)
    at javafx.scene.Scene.preferredSize(Scene.java:1748)
    at javafx.scene.Scene$2.preferredSize(Scene.java:393)
    at com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:66)
    at javafx.stage.Window$12.invalidated(Window.java:1086)
    at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
    at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
    at javafx.stage.Window.setShowing(Window.java:1174)
    at javafx.stage.Window.show(Window.java:1189)
    at javafx.stage.Stage.show(Stage.java:273)
    at javafx.stage.Stage$show.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:119)
    at core.GraphBuilder.attachAndShow(main.groovy:111)
    at core.GraphBuilder$attachAndShow$4.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:115)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:135)
    at core.App.start(main.groovy:56)
    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.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:277)
    at java.base/java.lang.Thread.run(Thread.java:834)

Это Throwable (IllegalState - RuntimeException) не попадает в вышеперечисленное try ... catch. Почему бы нет? Есть ли способ отловить такие исключения?

Похоже, это JAT: вы можете увидеть App.start() в этой трассировке стека (а также GraphBuilder.attachAndShow())

Я только что выполнил пару экспериментов: бросив сначала RuntimeException а затем стандартный Exception в этом методе attachAndShow(), перед любой из 4 строк метода .

В обоих случаях (распределенное) приложение не удалось запустить, и ничего не отображалось ... но сообщение журнала действительно было зарегистрировано, т.е. они оба были перехвачены. Полностью ожидаемое поведение, поэтому кажется, что сам JAT не является "преступником".

Я также отмечаю, что приведенная выше трассировка не является "нормальной" трассировкой стека: первые две строки указывают, что что-то обрабатывается это и, кажется, весьма к сожалению глотание это. По крайней мере, я хотел бы иметь возможность регистрировать такие проблемы!

1 Ответ

0 голосов
/ 23 марта 2020

Базовый c ответ: здесь .

Groovy пользователи могут самодовольно пробираться сквозь огромный лес заостренных скобок: мое решение стало:

fxmlController.treeTableView.columns.get( 0 ).cellValueFactory =
new Callback() {
    @Override
    Binding call(Object cellDataFeatures ) {
        // NB it turns out that the first "value" is a TreeItem
        Task task  = cellDataFeatures.value.value
        Bindings.createStringBinding({ task.title })
    }
}

или добавьте несколько минимальных значений в:

fxmlController.treeTableView.columns.get( 0 ).cellValueFactory =
new Callback<TreeTableColumn.CellDataFeatures, ObservableValue>() {
    @Override
    Binding call(TreeTableColumn.CellDataFeatures cellDataFeatures ) {
        Task task  = cellDataFeatures.value.value
        Bindings.createStringBinding({ task.title })
    }
}

Для замены Groovy "Java lambda", не удивительно, что мы используем замыкание:

fxmlController.treeTableView.columns.get( 0 ).cellValueFactory 
    = { cellDataFeatures -> cellDataFeatures.value.titleProperty() }

NB это включает в себя небольшое понимание JavaFX Property (см. здесь ) и небольшую адаптацию класса, экземпляры которого отображаются.

...