RichTextFX
RichTextFX copied to clipboard
VirtualScrollPane causes exception during initial layout "java.util.NoSuchElementException: Cell ## is not visible"
Expected Behavior
Scroll bars for my CodeArea
Actual Behavior
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1071)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.util.NoSuchElementException: Cell 2 is not visible
at org.fxmisc.flowless.CellPositioner.getVisibleCell(CellPositioner.java:37)
at org.fxmisc.flowless.Navigator.distanceFromGround(Navigator.java:373)
at org.fxmisc.flowless.Navigator.fillViewportFrom(Navigator.java:333)
at org.fxmisc.flowless.Navigator.visit(Navigator.java:131)
at org.fxmisc.flowless.StartOffStart.accept(TargetPosition.java:85)
at org.fxmisc.flowless.Navigator.layoutChildren(Navigator.java:80)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207)
at org.fxmisc.flowless.VirtualFlow.layoutChildren(VirtualFlow.java:257)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
at javafx.graphics/javafx.scene.Scene.preferredSize(Scene.java:1750)
at javafx.graphics/javafx.scene.Scene$2.preferredSize(Scene.java:393)
at javafx.graphics/com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:66)
at javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1086)
at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145)
at javafx.graphics/javafx.stage.Window.setShowing(Window.java:1174)
at javafx.graphics/javafx.stage.Window.show(Window.java:1189)
at javafx.graphics/javafx.stage.Stage.show(Stage.java:273)
Reproducible Demo
This example gives a slightly different exception during layout. The horizontal scrollbar is misplaced and the layout is broken. In my full application the exception happens earlier - there is no initial layout, the start method fails and the app exits. If I remove the VirtualScrollPane the issue goes away. I'm having a a hard time making a small example that gives the exact error above.
public class Bug extends Application {
public static void main(String [] args) {
launch(args);
}
public void start(Stage stage) {
CodeArea editor = new CodeArea();
try {
// Use the path of some file that doesn't fit in the view
editor.appendText(Files.readString(Path.of("\\pick\\a\\file\\Bug.java")));
} catch (IOException ex) {
System.err.println("Crap..." + ex);
}
editor.setParagraphGraphicFactory(LineNumberFactory.get(editor));
editor.setLineHighlighterOn(true);
Region wrapper = new Pane(new VirtualizedScrollPane<>(editor));
editor.prefWidthProperty().bind(wrapper.widthProperty());
editor.prefHeightProperty().bind(wrapper.heightProperty());
Tab tab = new Tab("Editor", wrapper);
TabPane tabs = new TabPane(tab);
SplitPane splitter = new SplitPane(new Label("placeholder"), tabs);
BorderPane bp = new BorderPane(splitter);
Scene scene = new Scene(bp);
stage.setScene(scene);
stage.setWidth(800);
stage.setHeight(600);
stage.setTitle("VirtualScrollPane Layout Issue");
stage.show();
}
}
Environment info:
- RichTextFX Version: 0.10.5
- Operating System: Windows 10 Pro 64-bit
- Java version: openjdk version "15.0.1" 2020-10-20 OpenJDK Runtime Environment Zulu15.28+51-CA (build 15.0.1+9) OpenJDK 64-Bit Server VM Zulu15.28+51-CA (build 15.0.1+9, mixed mode, sharing) ("JDK FX" version)
Current Workarounds
Have not been able to get VirtualScrollPane to work without issues. Scrolling works via trackpad without it though.
If I'm not mistaken a clunky workaround is to only add the VirtualizedScrollPane
to the Scene after the Stage is shown.
Sorry, a better workaround would be to only add/append the text to the editor AFTER the scene/stage is shown.
That does seem to work for the initial exception. However now I notice that scrolling is not as smooth, particularly in the horizontal direction, and I've seen several occurrences of this exception:
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "org.fxmisc.richtext.model.Paragraph.length()" because "this.paragraph" is null
at org.fxmisc.richtext.ParagraphText.getClampedCaretPosition(ParagraphText.java:319)
at org.fxmisc.richtext.ParagraphText.getCurrentLineStartPosition(ParagraphText.java:295)
at org.fxmisc.richtext.ParagraphBox.getCurrentLineStartPosition(ParagraphBox.java:179)
at org.fxmisc.richtext.GenericStyledArea.getCurrentLineStartInParargraph(GenericStyledArea.java:1185)
at org.fxmisc.richtext.GenericStyledArea.lambda$setLineHighlighterOn$36(GenericStyledArea.java:1255)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
When resizing the window, it eventually locks up the layout with this exception:
Exception in thread "JavaFX Application Thread" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:141)
at org.fxmisc.flowless.CellListManager.getPresentCell(CellListManager.java:65)
at org.fxmisc.flowless.CellPositioner.getVisibleCell(CellPositioner.java:33)
at org.fxmisc.flowless.Navigator.distanceFromGround(Navigator.java:373)
at org.fxmisc.flowless.Navigator.fillViewportFrom(Navigator.java:333)
at org.fxmisc.flowless.Navigator.visit(Navigator.java:131)
at org.fxmisc.flowless.StartOffStart.accept(TargetPosition.java:85)
at org.fxmisc.flowless.Navigator.layoutChildren(Navigator.java:80)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207)
at org.fxmisc.flowless.VirtualFlow.layoutChildren(VirtualFlow.java:257)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1207)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1214)
at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2476)
at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:413)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:412)
at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:439)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:563)
at javafx.graphics/com.sun.javafx.tk.quantum.PaintCollector.liveRepaintRenderJob(PaintCollector.java:327)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:883)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:843)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleViewEvent$15(GlassViewEventHandler.java:924)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleViewEvent(GlassViewEventHandler.java:923)
at javafx.graphics/com.sun.glass.ui.View.handleViewEvent(View.java:540)
at javafx.graphics/com.sun.glass.ui.View.notifyResize(View.java:880)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
I think the current master version (to be released as 0.10.6 end of January) addresses the NullPointerException and maybe also the NoSuchElementException.
Please test with the latest version (0.10.6) that's been released now, and give feedback if needed.
Please test with the latest version (0.10.6) that's been released now, and give feedback if needed.
@Jugen I still get these confusing exceptions in 0.10.8.
Ah, when I repeatedly open a file in my editor, when I use RichTextFX 0.10.8, an exception occurs probabilistically and the opening fails. Exceptions that may occur are NullPointerException
, NoSuchElementException·,
IndexOutOfBoundsExceptionand
ConcurrentModificationException`.
I just tried updating to 0.10.9 and I was surprised that these exceptions no longer occur, although this fix is not mentioned at all in the changelog. Unfortunately, I also need to be compatible with Java 8, so I can't upgrade for the time being.