Re: JavaFX Anchorpane and Tab resize and erasure of underlying screen elements
After reading Stack Overflow postings -
here: JavaFX Panel inside Panel auto resizing
and here: Resize JavaFX tab when double click
I was able to get the JavaFX code shown below to resize a tab to its maxium AnchorPane allowable size; the if() block worked. But on the else block execution the underlying pane (main stage's scene) gets erased/clipped by the Tab minimization. I have looked for many hours and tried various things to refresh the main stage's screen but all UI elements are still not shown. I could reload the stage as from the program startup but all the the user data on the erased screen would have to be saved, etc.
I thought about refreshing, repainting, etc., but I really don't know what to do in this case. Like I said, I search thoroughly for this information (esp. various stack overflow postings.)
Thanks for your comments.
if (mouseEvent.getClickCount() == 2) {
if (!isTabMaximized) {
TabPane tabPane = (TabPane) namespace.get("tabPane");
AnchorPane applAnchorPane =
(AnchorPane) namespace.get("applAnchorPane");
applAnchorPane.getChildren().forEach( node -> {
System.out.println("Node: " + node.getId());
});
applAnchorPane.setLeftAnchor(tabPane, 0.0d);
applAnchorPane.setTopAnchor(tabPane, 0.0d);
applAnchorPane.setRightAnchor(tabPane, 0.0d);
applAnchorPane.setBottomAnchor(tabPane, 0.0d);
applAnchorPane.getChildren().setAll(tabPane);
isTabMaximized = true;
}else {
TabPane tabPane = (TabPane) namespace.get("tabPane");
AnchorPane applAnchorPane =
(AnchorPane) namespace.get("applAnchorPane");
applAnchorPane.setLeftAnchor(tabPane, 0.0d);
applAnchorPane.setTopAnchor(tabPane, 495.0d);
applAnchorPane.setRightAnchor(tabPane, 0.0d);
applAnchorPane.setBottomAnchor(tabPane, 0.0d);
//not used commented out -->
// applAnchorPane.getChildren().setAll(tabPane);
isTabMaximized = false;
applAnchorPane.toBack();
applAnchorPane.getChildren().forEach( node -> {
node.toFront();
System.out.println("Node: " + node.getId());
node.setVisible(true);
});
}
}
My console output from println() in the if():
Node: mainFlowPane
My console output from println() in the else:
Node: tabPane
My fxml has the following structure (before the TabPane maximize):
AnchorPane
FlowPane - named mainFlowPane
HBox - contained in FlowPane
GridPane - contained in FlowPane
TabPane - contained in FlowPane, named tabPane
The FlowPane/name does not get printed in the else output to console, just the TabPane/name
It seems like the following has happened: My fxml has the following structure (after the TabPane minimized):
AnchorPane
- TabPane - contained in FlowPane, named tabPane
I debugged the code again and the FlowPane looks like it still exists. But I get the following exception when I try to printout the FlowPane Node fx:id's :
Node: null Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
Here is my stacktrace:
Node: null
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.checkForComodification(VetoableListDecorator.java:714)
at com.sun.javafx.collections.VetoableListDecorator$VetoableIteratorDecorator.hasNext(VetoableListDecorator.java:682)
at java.lang.Iterable.forEach(Iterable.java:74)
at wordcounterfxapp.WordCounterFXApp$4.handle(WordCounterFXApp.java:963)
at wordcounterfxapp.WordCounterFXApp$4.handle(WordCounterFXApp.java:897)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Thread.java:745)
Deleting directory C:\NetBeans\workspace8_0\WordCounterFXApp\dist\run2084430703
jfxsa-run:
BUILD SUCCESSFUL (total time: 13 seconds)
I found that I had omitted the fx:id's from the FlowPane's HBox and GridPane: once I added these the exception goes away. Now my output is the following:
jfx-project-run:
Executing
C:\NetBeans\workspace8_0\WordCounterFXApp\dist\run923058183\WordCounterFXApp.jar using platform C:\Program Files\Java\jdk1.8.0_101\jre/bin/java
Before TabPane maximized - Node: applAnchorPane
Before TabPane maximized - Node: mainFlowPane
Before TabPane maximized - Node: flowPaneHBox
Before TabPane maximized - Node: flowPaneGridPane
Before TabPane maximized - Node: tabPane
After TabPane minimized - Node: applAnchorPane
After TabPane minimized - Node: tabPane
After TabPane minimized - Node: mainFlowPane
After TabPane minimized - Node: flowPaneHBox
After TabPane minimized - Node: flowPaneGridPane
Deleting directory C:\NetBeans\workspace8_0\WordCounterFXApp\dist\run923058183
jfxsa-run:
BUILD SUCCESSFUL (total time: 10 seconds)
This printout shows that the FlowPane with its child Nodes are pushed below the TabPane?
So, this might show what's going on. That the FlowPane might be outside of the visible region. At this point I don't know how to fix it however...
10/26/2016
To wrap up this debugging exercise...
The problem: JavaFX AnchorPane and Tab resize and erasure of underlying screen elements
The analysis: On TabPane minimization, the JavaFx UI does not render my FlowPane properly with its 3 nodes of structure:
AnchorPane
FlowPane - named mainFlowPane
HBox - contained in FlowPane
GridPane - contained in FlowPane
TabPane - contained in FlowPane, named tabPane
On TabPane maximization, the UI relocates the TabPane Node from within the FlowPane to under the AnchorPane. On minimization the following Node hierachy results:
AnchorPane
- TabPane - contained in FlowPane, named tabPane
FlowPane - named mainFlowPane
HBox - contained in FlowPane
GridPane - contained in FlowPane
Thus, the JavaFx UI places the TabPane as shown. And, thus, the FlowPane with its Node elements are pushed out of UI stage/scene visual display. Why does the UI do this, rather than relocate/minimize the display, and not move the TabPane Node???
The solution:
I found a solution, with adding two lines of code at end of the else block:
flowPane.getChildren().add(tabPane);
applAnchorPane.getChildren().add(flowPane);
I have done some investigation so the UI should be fixed for now. I am now able to do both maximize and minimize a TabPane with is associated Tab Nodes. As far as I can tell, the JavaFx Node hierarchy is now the same after a min/max Tab as the Node structure was before these 2 operations. The problem was probably not a coding issue. Should JavaFx UI render things the way it does, to re-order the various nodes? I could not find any documentation for this in about 5-7 hours of research. Hopefully, my notes about this will help others in a similar situation.
Thanks to Blip/StackExchange commentor, I was able to debug this issue to a successful outcome. Hat's off to Blip! Thanks so much for your help.