Clone a Scene in JavaFX - javafx

Is there a way to clone a scene in JavaFX ?
I currently want to keep a reference of the previous scene but can't find a simple way of doing it (except passing in the previous scene as a parameter to every new class responsible for scene creation).
Heres what I was thinking of doing (this is a snipped of my view controller)
public void switchScene(Scene newScene){
previousScene = currentScene; // something which achieves this without aliasing
currentScene = newScene;
window.setScene(newScene);
}.
However as one can observe this leads to aliasing problems.
Any way to solve this problem ?

Related

How do I refer to the top Node in TestFX?

Just getting started with TestFX and I'm wondering how to refer to the top Node (i.e. the Stage).
Here I see it says
All TestFX tests should use verifyThat(Node, Matcher, Function) when
writing tests, so that the developer can use DebugUtils to provide
additional info as to why a test failed.
This is a useful pointer... so say I want to say verify that "the JavaFX dialog/window is at least 600 pixels wide and at most 400 pixels high"?
NB for what it's worth I'm using the org.junit approach because the examples on the TestFX github site seem to. Actually I'm a Groovy fan and would hope to switch to the Spock TestFX implementation before too long.
NB2 it occurs to me that one way to get the Stage in testing code is to make the Stage a field of the class under test:
class ClickApplication extends Application {
Stage allTheWorldsA
public void start(Stage stage) {
Parent sceneRoot = new ClickPaneGG()
Scene scene = new Scene(sceneRoot, 500, 1000)
stage.setScene(scene)
stage.show()
allTheWorldsA = stage
}
... but somehow this feels the wrong way to do things: if the Stage is passed as a parameter of start it feels like the designers didn't want you to make a class field of it.

JavaFx scene lookup returning null

Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
Node nds = itemSection.lookup("‪#‎testId‬");
What is wrong with above code?? I am getting nds=null it should be btn
Lookups in conjunction with applyCSS
Lookups are based on CSS. So CSS needs to be applied to the scene for you to be able to lookup items in the scene. See the applyCSS documentation for more information. To get accurate results from your lookup, you might also want to invoke layout, as the layout operation can effect scene graph attributes.
So you could do this:
Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
itemSection.applyCss();
itemSection.layout();
Node nds = itemSection.lookup("‪#‎testId‬");
Alternate lookup after showing a stage
Note that some operations in JavaFX, such as initially showing a Stage or waiting for a pulse to occur, will implicitly execute a CSS application, but most operations will not.
So you could also do this:
Button btn = new Button("ohot");
btn.setId("testId");
itemSection.getChildren().add(btn);
stage.setScene(new Scene(itemSection);
stage.show();
Node nds = itemSection.lookup("‪#‎testId‬");
On CSS based lookups VS explicit references
Storing and using explicit references in your code is often preferred to using lookups. Unlike a lookup, using an explicit reference is type safe and does not depend upon a CSS application. Generating explicit references can also be facilitated by using JavaFX and FXML with the #FXML annotation for type-safe reference injection. However, both lookup and explicit reference approaches have valid use cases, so it is a really just a matter of using the right approach at the right time.

Element lookup by ID has no result

With the Scene Builder 2 I created a scene with following structure:
BorderPane -> SplitPane -> AnchroPane -> SplitPane -> AnchorBane. (http://pastebin.com/7LTNh1Jv)
The AnchorPane in the second SplitPane has the ID workbench-anchor. Now I try to get a reference of this AnchorPane via:
final BorderPane rootPane = loader.load();
final Node node = rootPane.lookup("#workbench-anchor");
But node is always NULL.
Does anyone know what I am doing wrong?
Thanks a lot in advance!
Lookups won't work until CSS has been applied, which typically happens on the first frame rendering. You can try performing the lookup after showing the stage. You may also be able to force this by calling
rootPane.applyCSS();
before doing the lookup.
In general, lookups are not a very robust way of finding elements of the scene graph (imho). It's probably better to do any initialization work you need in a controller class, using #FXML injections to reference the nodes.

QGraphicsScene::clear() clearing scene but not the view

I use a custom class (Configuration) derived from QGraphicsItem and I add its objects to a QGraphicsScene, which is then displayed in a QGraphicsView. Usual stuff. What Im doing exactly is drawing a tree, in multiple steps, one level a step, each node beeing my custom QGraphicsItem.
Here a screenshot. The tree happens to be sequential in the simple case.
I first draw the root node. The signal that triggers that is fired after the user entered a string.
void MainWindow::drawRootSlot(ConfigTreeBuilder & builder)//this is a slot
{
c_scene->clear(); //the clear cause headache. i'll expain
Configuration* conf = new Configuration(builder.getNodesX(), builder.getNodesY(),builder.getNodesConfig());
//code
c_scene->addItem(conf);
//code
}
Each subsequent Configuration is draw inside another slot.
void MainWindow::configTreeSlot(ConfigTreeBuilder & builder) //SLOT!!!
{
while(builder.chooseNextNode()) {
Configuration* conf = new Configuration(builder.getNodesX(), builder.getNodesY(), builder.getNodesConfig());
//code, while loop
QGraphicsLineItem *edge = c_scene->addLine(QLineF(*(parentsPoint), conf->getLeftOrigin()));
edge->setZValue(-1); //below the Configuration item
c_scene->addItem(conf);
}
}
All works fine when done for the first time. When I enter a new string, resetting the tree, dark magic happens. What I expected to it do is: call drawRootSlot(), deleting the whole tree (c_scene->clear()), draw a new root node. And, if I put a debugger breakpoint inside drawRootSlot() this is exactly what happens! But when I run it (without breakpoints), what I get is this:
The previous tree got mangled, but not deleted. The scene gets indeed cleared of its items (printed that) but the view does not reflect that. But again, when I put a breakpoint inside drawRootSlot() thhe view and the scene are in sync.
I tried to delete the scene object, and instaciate a new one instead of calling c_scene->clear(), to guarantee it empty. Then the changes are reflected on the view (the first time drawing always works).
So, I have no idea what to deduce from these symptoms. It works as expected with a breakpoint or with a freshh QGraphicsScene object. It does not when just using c_scene->clear(). One couldsay I just messed up the parent-object/child-object relation, but clear() does remove items from the view... I tried calling it right after c_scene->addItem().
What is this sorrcery? One that makes me believe I'm not actually stupid?
EDIT: Whats interesting and may be a hint to the real problem, is that when c_scene->clear() is called, the edges of the tree, which are normal QGraphicsLineItems, are indeed deleted in all cases (breakpoint or not). Something to do with them not beeing custom?
Ok, calling QGraphicsView::viewport().update() after QGraphicsScene::clear() solved my problems.
But does anyone have an explanaition to the behavior described above?
EDIT: Upon doing doing something else I stumbled upon the actual core of the problem: I messed up the boundingRect() of my GraphicItems, so it was below the visble item, touching only its lower edge (which got deleted, as seen on the screenshot). So now no calls to any update() methods are neccesary.
I think when you call this fitInView() for the graphicsview it cleans up the view from any artifacts that remain from a previous scene.
You can clear both scene and Graphics View
scene->clear();
ui->graphicsView->items().clear();
graphicsView = name of your graphics view
This code will delete both scene and graphics view

Sharing same model in two QGraphicScene instances in Qt

I have an application that displays an editor for a diagram using QGraphicsScene object. I would like to create a read only version of the same dialog but have ability for user to see both at the same time.
SimScene* pScene1 = new SimScene(model); // adds model to scene
SimScene* pScene2 = new SimScene(model); // adds model to scene
QGraphicsView* pView1 = new QGraphicsView();
pView1->setScene(pScene2);
QGraphicsView* pView1 = new QGraphicsView();
pView2->setScene(pScene2);
When I create 2 instances of QGraphicsScene and use addItem on the second one it removes all the items from the first one. Does Qt support any sort of sharing of model between scenes? Is my only choice to have same scene and try to customize the view? Later one doesn't seem to work because object selection information is within the graphics items being shared so if I disable flags on them they become read only in both views. Any advice is appreciated. Thanks.
If you just want an interactive and a read-only view on your model you can use a single QGraphicsScene and 2 QGraphicsViews. You just have to call QGraphicsView::setInteractive(false) on one of them. That way you don't have to change any item flags.
I think that you're storing QSceneItems in model classes. Because of that pScene1 and pScene2 are trying to share not only the model itself, but also the scene items. This won't work because any scene item can be placed only on one scene at any given moment.
How to fix it? Make model not aware of any GUI. Let it issue changed() notifications whenever something interesting happens.
Then let each SimScene wrap model into whatever QSceneItems it wants, and process changed() notifications.
Example:
Model:
Graph,
Edge,
Vertex
GUI
SimScene,
QEdge,
QVertex,
QSimInfo,
Qbackground, and so on ...
Also, you add pScene2 twice:
...
pView1->setScene(pScene2);
...
pView2->setScene(pScene2);
And allocate memory for the same pointer twice:
QGraphicsView* pView1 = new QGraphicsView();
...
QGraphicsView* pView1 = new QGraphicsView();

Resources