Should I use QGraphicsScene for an interactive movie? - qt

I have a lot of 2D, time-variant data (aka a movie) that I'd like to visualise inside a Qt interface. The idea is that the results can be viewed as a movie, browsed using a time-slider and then individual data points should be selectable to get more information about that point. (The data being shown is generated from simulations, and then converted to RGB through some colormap, so I'm not really looking for a component that plays mp4)
I have some experience using a QGraphicsScene, which makes it easy to get the cursor location & react to mouse events. But is it suitable for video? Or am I better off with some kind of QImage directly on a widget?

Ok, so it works well in PyQt, not so well in PySide.
I'm using a QPixmap wrapped in a QPixmapItem that gets added to the scene. To update the frame, I change the contents of the pixmap object and call update() on the scene.
Performance is good enough for video (although I don't need high frame rates for this project).
In PySide I ran into weird issues when I used more than 1 pixmap item, in PyQt it works just fine.

Related

Share rendered texture between Unity and Qt

I have a 3D environment done in Unity which I wan't to have as an Item in Qt (QML). I've tried a few different paths, but none has proved to be efficient enough or I'm unable to get it to work.
My current working solution is to do the following each frame
In Unity, use ReadPixels of my RenderTexture (GPU) to get a regular Texture (RAM).
Encode to JPG and send bytearray through TCP socket.
In Qt, instantiate a QImage from the data and save it for later use.
In the render function of QQuickFramebufferObject::Renderer, use glTexImage2D to render the image to my active texture.
Obviously this is not an optimal solution. This performs maybe 10 fps with a 128x64 texture size (for testing). My understanding is that the bottleneck is transferring data from gpu and back.
In my latest attempts I have tried to get the ID of the RenderTexture using renderTexture.GetNativeTexturePtr(). Then in Qt I'm trying to get the pixel data through glGetTexImage, but I keep getting 0's in the data. When later using glDrawPixels, the Qt application crashes.
So my question now is, do anyone know if it's possible to share the texture between processes and if so, how?

Qt OpenGL data synchronization / Model/View implementation

I am trying to develop an application with Qt 5.5 and OpenGL. The basic work of the application will be to load simple objects, modify their positions in a scene and save them together with other attributes (material, name, parents/child relations etc...).
The only thing I am struggling about for a week now is that I really don't know how I should take on the problem of synchronizing data. Let's say I have some kind of SceneGraph class which takes care of all SceneObjects. Those SceneGraphs should be rendered in a SceneView-Widget which can be used to modify it's Objects via transformations. Now how would I tell every SceneView that an Object changed it's position?
I thought of the Model/View architecture for a moment but I am not really sure how this implementation should look like.
What would be the best way to handle Objects like that in different Windows/Widgets but still have one single piece of data?
SceneObject:
Holds the mesh-information (verticies, uvs, etc..)
Has a name (QString)
Has a material
Has a transform storing position, rotation and scaling information
(Important: these datatypes should be synchronized in all views)
SceneGraph:
Contains different SceneObjects and is passed to SceneViews
SceneView:
The QWidget responsible for drawing the Scene correctly in any QWindow.
Has it's own camera to move around.
Handles UserInput and allows transformation of SceneObjects.
You could use the signal and slot to observe position updates of SceneObjects and process them in SceneView.

How to do chalk style drawing with Qt

I want to use Qt to draw lines in chalk style, as you typically see on a blackboard. Here is an example of what I have in mind:
What is the best way to achieve this rendering style? Do I need to draw a lot of little lines with a special brush, or is there a better way to get the "curvy" style you see in the sample image?
And where is the best place to integrate this? Theoretically it would be ideal to get this underneath QPainter, e.g. in a custom QPaintEngine, so that e.g. all the various QPainter::drawLine calls end up using the chalk style. However, it seems while the QPaintEngine interface looks perfect for this, the class itself isn't meant to be used for this purpose...
Thanks in advance for any help.
Greetings,
Fabian
I have solved the problem in a different way. Using textured brushes didn't provide good results (maybe my fault). QGraphicsEffect was unfortunately not an option since my rendering is not based on QGraphicsView.
What I have done in the end:
Derived an own class from QPainter (i.e. ChalkPainter)
Added a new drawChalkLine() method to ChalkPainter. This method takes the passed line, splits it into smaller chunks and renders these chunks as bezier curves via QPainter::drawPath. For each bezier curve chunk I randomly shift the control point orthogonal to the line.
Next I added additional rendering methods to the ChalkPainter class, such as drawChalkRect(), all internally using the drawChalkLine() method.
This is not the most elegant method since I can't use the QPainter methods directly, but it provides good results for my purpose. Here is an example:
I would start looking in QGraphicsEffect's way.. I think it should be possible to develop such a filter which will produce similar effect..
I'll update in here answer on your comment.
No, QGraphicsEffect can be applied 'per graphics item'. If you have a look on QGraphicsItem you will see that there is a setGraphicsEffect method, so you can design an effect which works on QGraphicsLineItem for example and set it only on lines you want to look chalky..
Important thing is that you don't have to operate on pre-drawn image, you can either make it completely owner-draw item with graphicsEffect (for example make an assumption that effect is only applicable on QGraphicsLineItem) pre-draw it using drawSource() and then modify OR draw it completely from scratch..
I would love to help you with some coding, probably will do it somewhere around next week, since I will need similar thing for project I am working on now.. but physically don't have time next few days..
I'll update an answer with sources link as soon as it's done.
Custom brush also looks really promising..

How do I get the QDrag hotspot value in the dropEvent function?

I'm somewhat new to Qt, and I'm using Qt 4.8 to implement a graphical editor of sorts. Right now I've implemented dragging of rectangles around my widget using drag&drop. In my mousePressEvent function I generate a QDrag with appropriate MIME data (similar to the puzzle sample), and I just added a 'setHotSpot' call.
The dragging works just fine, but in my dropEvent function, I can't figure out a way to get back to the hot-spot setting in the original QDrag object - I don't appear to have access to it.
I've solved it for the moment by stuffing the hot-spot point into my MIME data (it's custom data anyway), but that seems wrong to me - it seems to me that there'd be some way within the Qt framework for me to get that hot-spot data in my dropEvent function.
please check the following example in Qt.
http://doc.qt.io/qt-4.8/qt-draganddrop-fridgemagnets-example.html
this example shows how to use drag an drop events in Qt.
In that example we see that adding the hot-spot's point to the MIME data does in fact appear to be the recommended way to get the hot-spot point from where the drag is initiated do the dropEvent.
I don't understand what you are trying to achieve...
The "hotspot" point is just an offset point relative to the pixmap representing the data being dragged, and thus is constant during the whole drag.
If you are looking for the initial drag point, you should indeed encode it into the mime data.

Cross-platform custom cursors for Qt, cursor in resource file

I feel like I'm missing something since I can't see any way to easily do a cross-platform cursor in Qt. That is, I'd like to use a standard cursor editor, or just a common cursor file type, and stick it in the resource file.
I see a couple platform specific manners providing handles (meaning I couldn't load from a resource) or a generic way taking a pixmap. In the pixmap method I would then have to find someway to store the hotspot along with the pixmap.
I don't want animated cursors, just a plain color image (32x32).
What is the easiest way to handling this?
I'm currently working on an application where I'd like to have some nice custom cursors. The way I'm doing that is:
Add an image to a Qt resource file (*.qrc) - I am working with PNG with transparency exported from an SVG (always have your original art sources in SVG for things like this in case you need scaling)
<RCC>
<qresource prefix="/">
<file alias="default">cursors/cursor_default.png</file>
</qresource>
</RCC>
This will allow you to ship your cursors along with your application since Qt resource files are converted to C++ sources, which are then added to your binary
In your source code do:
QPixmap cursor_pixmap = QPixmap(":cursor_default");
QCursor cursor_default = QCursor(cursor_pixmap, 0, 0);
setCursor(cursor_default);
There are two important things to notice here both related to the constructor of the QCursor - the pixmap you add to it and the hotspot coordinates (here both set to 0 which is the top left corner of the pixmap that represents the shape of your cursor). There are actually 2 constructors for QCursor which are imho useful here:
- `QCursor::QCursor(const QBitmap &bitmap, const QBitmap &mask, int hotX = -1, int hotY = -1)` - this allows you to use a mask to manipulate the pixels of your cursor
- `QCursor::QCursor(const QPixmap &pixmap, int hotX = -1, int hotY = -1)` - if you are working with a PNG or other supported image format which allows transparency you can omit the mask as it is in my case.
The hotspot is a very essential part of a cursor - it tells your application which part of your cursor is the "trigger" that is the spot which does something compared to the rest which is just fancy visuals and nothing functional.
While looking for resources on Qt customization of cursors I found this article (the image above is from it), which I can totally recommend every one, interested in this topic, to read.
In terms of storing the hotspot I don't think that something like this is necessary. After all your resource files are compiled and added to the binary hence when you assign a hotspot to a cursor inside your code it will be there. I doubt that any OS actually has a format (let alone multi-platform one) that stores both the cursor and its hotspot due to the fact that depending on the application you may want to change the hotspot (for example due to scaling the bitmap itself in order to have multiple sizes) which would be a lot more difficult if you have it bound to the cursor's bitmap. If you really want to go the distance with this (I would advise against it) you can create your own custom file format which contains both. Since the Qt resource files are - to my knowledge - meant for managing images you would have to implement the whole IO mechanics in order to support your custom format.
Hope this helps. The solution above is as cross-platform as you can get with the Qt framework. Note however that the custom QCursor will only be available inside your application and wherever you have set it in. Cursor that is above the window frame for example is considered OS-specific due to the fact that the window frame itself is an OS-specific feature and if you want to alter its behaviour you will have to go a lot deeper (and also outside Qt's safe zone) meaning check how cursors are handled on an OS-level.

Resources