More efficient central widget in a QMainWindow: QGLWidget VS QGraphicsView - qt

I am using a QMainWindow for my app and want to do some openGL rendering. 2 approaches:
1) set as central widget a QGLWidget and do all the rendering there,
OR
2) set as central widget a QGraphicsView, set the viewport to my QGLWidget to create the rendering context and do the rendering in my scene.
Which one would be preferable when it comes to efficiency? (I will be adding some other objects later which in the former case are going to be QGLWidgets (as child widgets) and in the latter QGaphicsItems)

Using a QGLWidget and rendering with OpenGL directly will in most cases be more efficient, but it will require more work to manage a dynamic set of rendered items. Using the QGraphicsView framework will have some overhead, but it provides many features for managing rendered items. The amount of overhead for QGraphicsView will depend upon various details, but in most cases it will not be a bottleneck and it can be adjusted for various usage patterns.

Related

Qt custom widget update big overhead

We are trying to use Qt 4.8.5 for some Linux-based embedded devices in our company. I use Qt embedded without X server. I need to plot measured data and update them very often (20-30fps, but only a small portion of the widget). The system is ARM based, 400Mhz, have no GPU and no FPU. I subclassed QWidget and overridden the paintEvent(). I have WA_OpaquePaintEvent and WA_StaticContents set. For testing, my paint event is empty, and I call the update() function of the widget form a timer set to 50ms. My problem is that the empty update is eating up 30% of the CPU. The amount varies with the area of the update, so I think QT may redraw something in the background. I have read many posts but I cannot find the solution for my problem. If I comment out the update call, the CPU usage drops to ~1% (even if I generate a sine in the timer for testing the widget, which should be much more complex than an empty function call). My widget is rectangular, is not transparent and I want to handle the full drawing procedure from the paint event.
Is it possible to reduce this overhead, and handle the whole painting process by my own?
The "empty update" is not empty - it repaints the whole window :)
Have you read the below?
To rapidly update custom widgets with simple background colors, such as real-time plotting or graphing widgets, it is better to define a suitable background color (using setBackgroundRole() with the QPalette::Window role), set the autoFillBackground property, and only implement the necessary drawing functionality in the widget's paintEvent().
You should also be using QWidget::scroll(), since internally it does scroll the backing store of the window, and that's much more efficient than repainting the entire thing if only a tiny slice is added to it.

OSG +QT switching to full screen and back

I am integrating a single osgQt::GLWidget in a Qframe and using the pattern here: http://trac.osgeo.org/ossim/browser/trunk/ossimPlanetQt/src/gui/ossimPlanetQtMainWindow.cpp to switch between full-screen mode and back. Basically consuming the keystrokes within the widget and setting full screen from there.
I also have an event consumer in osgViewer::Viewer - osgViewer::WindowSizeHandler which handles the viewer size switch.
Is there a better pattern to implement this ?
Basically, what you do (or, what is done in the example) seems fine. (Note that I am assuming that you refer to void ossimPlanetQtMainWindow::on_viewToggleFullScreen_triggered(bool ))
However, in the example, the QGLWidget theGLWidget is reparented between tabWidget and theFullScreenFrame. Under Windows, reparenting a QGLWidget will lead to a recreation of the QGLContext. (see QGLWidget documentation
The workaround suggested by the docs is to wrap the GL widget in a dummy widget (a simple QWidget) and reparent that instead of the GL widget.
In my experience, this works fine.

qt equivalent for docking control to it's container in winforms

I'm trying out qt creator lately and i hate reading hours of docs and tutorials just for doing simple tasks.
So, in winforms i can drag & drop a control from toolbox and set the dock property so it automatically maximizes itself to it's container's size.
What is the equivalent of this behaviour in qt?
I googled this and found it strange that nobody wondered the same before.
There are differences between the concepts of WinForms and Qt. You need to study the concept of layouts. Take a look at the relevant part of the documentation of Qt Designer: Using Layouts in Qt Designer
Before a form can be used, the objects on the form need to be placed
into layouts. This ensures that the objects will be displayed properly
when the form is previewed or used in an application. Placing objects
in a layout also ensures that they will be resized correctly when the
form is resized.
Qt uses layouts. Add QHBoxLayout or QVBoxLayout to the parent widget.

QGLWidget for graphics and QT for GUI

I am trying to implement a custom OpenGL scene (wrapped in a QGLWidget), but still use QT controls (such as slide bars and buttons). I tried to make my main widget a QGLWidget, which has QWidgets as children. The child widgets seem to work (when I click a pulldown menu, its options appear), but the widget fails to draw (I see a white square). I changed the base class of my children widgets from QWidget to QGLWidget, and now QPainter calls work, but QT GUI stuff is still not displaying...
Some claim that a QGLWidget can not have QWidgets as children... I am not sure about that and I'm not willing to give up. By the way, I am using Visualization Library to draw the OpenGL scene, but it is just an OpenGL wrapper...
Any clues where the problem might be? Also, key events stop being processed for some reason when I add subwidgets to the GQLWidget.
Update:
I tried various combinations of widgets and layouts. It seems that the QGLWidget just gets drawn on top of anything. I even tried with raise() to arrange Z-depth of the widgets, to no avail. Is overlayGL() the only way to draw on top of an OpenGL widget?
Update 2
After months of trying, I figured out it is something related to QT. Whenever a QGLWidget is drawn on top of another QGLWidget, the first's background() function is not called. So a button is there and can be clicked, but it's not drawn. My workaround was to draw everything myself using QPainter - that works. What I found curious is, one has to use QPainter::startNativePainting() in order to draw with it. One would expect that they would overload start() in QPainter to call startNativePainting() whenever a QGLWidget is the painting device...
Another (maybe useful) fact is that QPainter calls CHANGE the Opengl context. So if you have another tool in cooperation with QPainter (in my case Visualization Library), chances are that one of them will crash (in my case VL which checks if the context state has been cleared before each frame).
There is a labs example of rendering Qt widgets using opengl it's a little old and I haven't tried it with the improved qglwidget in 4.8
There is also an issue with drawing over the top of a fullscreen QGLwidget - it was supposedly a bug in NVidia's openGL driver. It doesn't seem to have been resolved
https://bugreports.qt-project.org/browse/QTBUG-7556
If I were you I would use the QGLWidget as a viewport for a QGraphicsScene, then you can draw your widgets using a QGraphicsProxyWidget. That way you get a proper OpenGL viewport with the ability to put widgets in and manipulate them easily.
Did u try to call update() explicitly? I find that sometimes QGLWidget update the display stuff kind of slow.
This is an old question, but I recently had quite a bit of trouble with this, and this is what helped me -
Use QML/QT Quick. QML is a javascript-like language that allows you to layout your widget elements on a window and do basic processing on events like mouse clicks. There are a few other cool features, but the one that is most relevant to this question is that you can import qt widgets from C++ code.
So you can make a custom QGLWidget, import it into the QML window, and set the size/position/stick widgets on top of it in whatever you want, very easily. QT's Scenegraph example does a great job explaining this. Scenegraph's code is also included as an example in at least Qt Creator 3.2.1 Open Source (that's the version I have anyway)

Drawing QPixmap Rects Over QWidget with QPainter

I'll get serialized QPixmap Rects over the socket. I'll unserialize them and draw the rects in a QWidget Now my question is which QWidget should I use for this purpose ? is there any recontamination about how should I proceed ? at the moment I've decided to use a QPainter and draw using drawPixmap am I going in a wrong direction ?
It sounds like you might want use QGraphicsPixmapItem instances drawn on a QGraphicsScene with a QGraphicsView.
See Qt Graphics View Framework:
Graphics View provides a surface for
managing and interacting with a large
number of custom-made 2D graphical
items, and a view widget for
visualizing the items, with support
for zooming and rotation.
The framework includes an event
propagation architecture that allows
precise double-precision interaction
capabilities for the items on the
scene. Items can handle key events,
mouse press, move, release and double
click events, and they can also track
mouse movement.
Graphics View uses a BSP (Binary Space
Partitioning) tree to provide very
fast item discovery, and as a result
of this, it can visualize large scenes
in real-time, even with millions of
items.

Resources