Access other item contents within a QGraphicsScene - c++

I have a dialog.cpp file, it is within here I created my QGraphicsScene which uses the QGraphicsView.
I created two classes that inherit QGraphicsPixmapItem, "Vehicle" and "Junction". Both of these objects are added to the same QGraphicsScene in my dialog.cpp file.
I want to call a method which is a member of "Junction" from my "Vehicle" object. The method returns a boolean value which I need.
This is more of a c++ orientated question, as I'm sure there's an easy solution which makes use of accessing a parent.
Background info on project: Each "Vehicle" moves along a road and approaches a "Junction". The vehicle must then ask the junction "does my lane have a green light to go?", the junction will then reply "true/false".

After reviewing possible solutions via the QT documentation I have partly resolved the issue.
Calling this->scene() allows access to member functions of the scene, on which your object was added. Since I know the co-ordinates of my object I call, this->scene()->itemAt(240,0); to retrieve a pointer to the item.
The pointer returned is the uppermost item on the scene at the co-ordinates supplied. If this provides a problem alternately use scene()->items() to retrieve a list of all the items on the scene.
However, this only gives access to the item and not the vector in which the item is stored. I have been looking into using the ->parent() function and think this may be the solution, combined with dynamically casting it to the required pointer. Will update the answer if I find a full solution.

Related

Qt | creating a dynamic object in a customized scene

Good day to all!
I would like to learn from the respected community how it is possible using Qt Designer to create a simple GUI that performs what is shown in the attached image. Namely: after a single click of the LMB, a marker is placed at the place of the click, indicating the beginning of the polygon, and a temporary polygon of the desired type (but of different sizes) begins to follow the mouse cursor until we click on the LMB again, after which the final polygon will be built from the point of the first click of the LMB to the point of the second click. Such a ready-made polygon will have to be stored somewhere in memory for further work with it.
As a polygon here, I show a complex sector built on some calculated points, but as a simple example, you can take a straight line - I don't think that the essence of the program changes much.
I have already looked at many examples of different implementations of different things on QGraphicsScene, but I could not figure out exactly how to create an object in the way I needed. That is, I know that we need a separate class describing the polygon and calculating the coordinates of which it consists, but I don't quite understand how to implement the dynamics - with each mousemoveivent, delete the temporary polygon and draw a new one for the new coordinates, or how?
P.S. If it won't be so difficult, could someone also show how to implement what was conceived through the redefined paintScene class, replacing the standard QGraphicsScene class and inheriting from it? I am faced with the fact that when creating a custom class of the scene object, clicking on the objects attached to it is ignored by the program, and instead of, for example, dragging an object on the scene when clicking on it, the mousePressEvent of the scene, not the object, is triggered, and I do not understand what the problem is.
P.P.S. I apologize for my English and thank everyone for any help!

correct way of updating a QGraphicsView from QGraphicsScene

I have implemented a QGraphicsScene to contain instances of QGraphicsItem of a few different classes implemented by me. What I still don't understand is how the QGraphicsView associated with this scene is updated.
When I call addItem(QGraphicsItem) the scene seems to redraw displaying the newly added items.
When I change properties of my QGraphicsItem instances (e.g. calling setVisible(bool)) it seems that the view is not updated automatically.
I currently call QGraphicsScene::update() without any arguments to draw the new state. this works in most cases, however in some of them it fails ( QGraphicsItem's paint() method is not called. I set a breakpoint there but whether it is reached or not depends on the zoom level in the QGraphicsView. I have to zoom out to a certain level for it to get called again).
It doesn't work when I pass the bounding box of the changed item (scene coordinates) to QGraphicsScene::update(QRect). I can't see objects changing.
Can anybody give me a hint what is the correct way of implementing this? How do I notify the view correctly of changes in certain areas, what does the behaviour depend on. I think there's something wrong with my assumptions about coordinate systems. Thanks a lot for your explanations.

VTK - Interacting with multiple objects

I am fairly new to VTK and I really enjoy using it.
Now, I want to interact with multiple objects independently. For example, if I have 5 objects in a render window, I want to only move, rotate and interact with the one selected object; whilst the rest of the 4 objects stay where it is.
At the moment, the camera is doing the magic and as I rotate the independent object, other objects move at the same time and I don't want that to happen.
I also want to store all the objects in memory.
I intend to use C++.
This is my sort of class structure...
class ScreenObjects
{
vtkActor (LinkedList); // I intend on using a linkedlist to store all the actors
public:
ScreenObjects(); // Constructor. Initializes vtkActor to null.
void readSTLFile(); // Reads the STL File
bool setObject(); // Sets current object, so you can only interact with the selected object
}
I am missing quite a lot of functions and detail in my class, as I don't know what else to include that would be of use. I was also thinking of joining two objects together, but again, I don't know how to incorporate that in my class; any information on that would be appreciated.
Would really appreciate it if I could be given ideas. This is something of big interest to me and it would really mean a lot to me, and I mean this deep down from my heart.
First of all you should read some tutorials and presentations like this one for example:
http://www.cs.rpi.edu/~cutler/classes/visualization/F10/lectures/03_interaction.pdf
I say that cause it looks like you're currently just moving the camera.
Then you should look into the VTK examples. They are very helpful for all VTK classes.
Especially for your problem have a look at:
http://www.vtk.org/Wiki/VTK/Examples/Cxx/Interaction/Picking
Basicly you have to create a vtkRenderWindowInteractor derived class to get the mouse events (onMouseDown,onMouseUp,onMouseMove,...).
And a vtkPropPicker to shoot a ray from your mouse position into the 3D view and get the vtkActor.
Now you can store onMouseDown inside your vtkRenderWindowInteractor derived class the vtkActor you'd like to move and the currentMouse position. When the user release the mouse (onMouseUp) just get the new mouse position and use the difference of the onMouseDown/onMouseUp positions to modify the vtkActor position.

Refresh of a QGraphicsScene / QGraphicsView

I am troubled by the following:
I am working with an interactive QGraphicsScene that needs to render the graphical representation of an SQL query, based on the users' operations, such as: add something to the query (a table, a new column, something else) or remove something from the query (a keyword, a table, a column ...). The changes of the scene must be displayed after the operation, and also the "logic layer" of the application needs to track the operations the user did, since the "rendering" of the query is done by the "logic" layer (ie: the "logic layer" creates all the QGraphicsItemGroup derived objects which at a later stage, after all the logic layer components were built, are being added to the graphics scene of the query and put on the window).
The problem that occurs is the following: right now I did not manage to find any usable solution to present a query after a change in the smoothest possible way.
Allow me to link in a screenshot for further explanation:
Let's suppose the user wants to remove the PERSON.NAME column from the query. What happens in the application:
the user clicks on the "remove" (small red X after the column name) button of the PERSON.NAME columns' graphic item
the Graphics View senses this operation, sends the REMOVE column from the graphic system to the "logic layer" (the "model")
the logic layer on its turn removes the corresponding "logic layer" object representing the PERSON.NAME column,
And here the trouble starts:
the entire graphic (yes, everything) is re-rendered by the logic layer creating the graphic items for the same query, without PERSON.NAME
then I have to create a new window which has a new QGraphicsScene object together with a QGraphicsView
insert the re-rendered objects' graphic items representing the query, (but now without the PERSON.NAME column) into the new QGraphicsScene with addItem()
and now replace the central widget of the application with the new window.
and now you can see, that indeed, in the query the PERSON.NAME is not there anymore and all the graphic elements that were below PERSON.NAME were moved up on the screen.
Obviously this is not a good solution, there is an ugly flickering when I change the window, but I simply did not find a better solution to this problem till now.
So I am asking for your help in order to identify what improvements can be done to this methodology of updating the screen upon removal (addition) of a new element knowing the background information above, without a new window. Obviously other, mroe generic graphic related comments are welcome too.
Thanks,f
Based on the information from the question and the comments, a couple of things you could consider:
First thing is that you need to get rid of creating a new Window and a new QGraphicsView when refreshing.
I suppose this is the main reason for flickering. Keep your UI structure unmodified and only modify the scene.
You could use one of these approaches:
Either create a new QGraphicsScene and set it as the view's scene, or call clear() on
the existing scene. Then recreate your QGraphicsItems from your native model and make sure that all your pointers and references are updated.
Another approach would be to have the QGraphicsScene update your native model when something changes, to avoid the need to recreate the whole scene from scratch. For example, let the QGraphicsScene handle the deletion of the QGraphicsItem when the user clicks the delete icon, and then let the scene update your native model to reflect this change.
Yet another approach would be to discard your native model, and use the QGraphicsScene with its QGraphicsItems as your model. Implement serialization etc. in the scene class. This avoids the need to synchronize the two models. The drawback is that your graphics independant logic is then much tighter coupled to the QGraphicsScene, which you might not want. Depending on your code size, this might also be a lot of work.
I would start with 1., since it seems to be the easiest way to go based on your existing approach. If you still come across weird issues with pointers and object ownership, try to isolate them and ask on SO :)

c++ list of pointers to QGraphicsItem

I'm experimenting with the QT library and QGraphicsScene.
I can add my own objects to the scene and all that is fine.
What I would like to have now are some lists outside QGraphicsScene of the objects.
Let's say Squares, Circles and Triangles.
They all live in the scene, and are (if I'm correct) copied and owned by the scene when I add them.
The question is: what kind of list template containers would be best for implementing my outside lists.
I guess they would need to be pointers so I figured boost::ptr_container.
I know I would need a system to make sure the lists are in sync with the scene once I start deleting items. that means removing the pointer form the lists just before removing the object from the scene.
Any ideas on how i should build this system would be very nice.
You don't need it, Qt does everything for you.
Once you add an item into QGraphicsScene,the scene takes ownership of the item. Which means, the scene is now responsible for storing the item, and freeing the memory occupied by the item when it's needed (usually when you delete an item manually with deleteItem(), or when the scene itself is deleted).
Whenever you want you can ask for the list of all items that have been added to the scene by calling the items() function:
MyGraphicScene.items();
This function returns a list of pointers to all of the scene's items as a QList< QGraphicsItem * >, which is exactly what you need.