How to make sure Qt Widget.repaint has finished running? - c++

I am currently having a problem with Qt graphics view framework namely, I want to clear my QGraphicScene background color and then run a function to take a webcam picture. So far when I use QWidget.repaint the screen only got repaint after about 1 second and by then the camera function has been called and the image captured is always off. Here is how my code currently look like.
//Scene is a QGraphicScene
//View is a QGraphicView
//Camera is a camera object
Scene.setBackgroundBrush(Qt::Blue)
View.repaint()
Camera.Capture()
I have tried wrapping the repaint() call with another function and use signal and slot call but it still fail. I want to know if there is a way to pause the program until the screen has been refreshed.

A QGraphicsView has a bit more going on than most QWidget subclasses and I'm not familiar enough with it to say what is going on for sure but I might venture a guess that your problem is related to the fact that the scene is actually rendered onto the view port widget. Perhaps calling viewport->repaint() will give you the results you are looking for?
Also, unless you really need to be using the webcam in this scenario, you could call ::render() on your scene and pass it a QImage which you could save directly to a file.

Related

how to get Qt Mouse Position all the time

So I have been struggling with this question for quite some time. I have tried many things, none of them seem to work.
So, I want to make a game in Qt, and one of the things I need is that player(QRectItem for now) rotate always to the mouse position. I just need to get readings of that position all the time, so not when i click or when I drag, all the time.
How can I do that?
I set
this->setMouseTracking(true);
on a class that inherits for QGraphicsView class, also I have set focus on it.
Dont know if the problem is with overriding functions(dont know which one to override) or with focus.
void Game::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << QCursor::pos();
}
Did this but it does not work at all.
Btw, I am noob it Qt, this is my first project.
Thanks in advance! :)
P.S.
I have really done research, but if I have somehow missed topic with same or similar question that can solve this problem, just paste it and accept my apologies. :)
EDITED
You can install an event filter on your QApplication object, examine the received events for mouse movement events, convert the resulting position into your scene, and then use it to orient your rectangle.
Look at QObject::installEventFilter. Event filters are pretty easy to use. When a mouse event is received by an object, its coordinates are in that object's coordinate space, so you'll need to convert from that to your graphics scene coordinates. There will probably be several conversions to get that because you'll need to map the received position to your QGraphicsView using mapTo and then map the result of that to your scene using QGraphicsView::mapToScene.
This should get you pretty close. Let me know if you need more help.

Qt5 QOpenglWidget How can I ensure the scene is updated immediately during mousemove envent?

I am currently working on a simple CAD-like drawing program using Qt and openGL.
What I am doing is that I maintain a list of objects which is on the canvas. The paintGL() function is just loop through the list and render the objects one by one.
objects are fed to the list via slot drawObject(Object obj), in which there is an update() function to schedule an update event to update the scene.
Now, I want to do some rubberband drawing of lines:
After pick one endpoint of the line, whenever I move the cursor, a mouseMoveEvent() is triggered and it will generate an object for the line and emit a signal to drawObject(Object) slot. what the slot does is to erase the old line by doing xor drawing, and draw the new line in xor mode as well.
What I expect to happen is that every time the mouse is Moved, a new object is rendered to the scene. However, it is not. For example, if I move the mouse
fast, then before the update() function actually update the scene, multiple mouseMove events has been triggered and it seems that these events are never been handled, i.e., the correspondence objects never goes to screen. What the program actually does is that a lot of random artifacts is left on the screen after a fast rubberband dragging.
It seems that this is due to the fact that what update() function of QOpenGLWidget does is that it generate an event to inform the widget to redraw later for performance purpose.
During the course of me writing this question, I discovered the repaint() function which do an immediate update. However, the lagging is quite significant: when I move the mouse fast, the rubberband line is not following.
So, my question is, how to implement the rubberband drawing so that it could take advantage of the update() machanism to boost the performance while not having those glitches on the screen?
I have searching around on this but I could find a single article talking about this fast-moving mouse stuff.
Thank you in advance!

How to display smooth video in FireMonkey (FMX, FM3)?

Has anyone figured out how to display smooth video (i.e. a series of bitmaps) in a FireMonkey application, HD or 3D? In VCL you could write to a canvas from a thread and this would work perfectly, but this does not work in FMX. To make things worse, the apparently only reliable way is to use TImage, and that seems to be updated from the main thread (open a menu and video freezes temporarily). All EMB examples I could find all either write to TImage from the main thread, or use Synchronize(). These limitations make FMX unusable for decent video display so I am looking for a hack or possibly bypass of FMX. I use XE5/C++ but welcome any suggestions. Target OS is both Windows 7+ & OS X. Thanks!
How about putting a TPaintbox on your form to hold the video. In the OnPaint method you simply draw the next frame to the paintbox canvas. Now put a TTimer on the form, set the interval to the frame rate required. In the OnTimer event for the timer just write paintbox1.repaint
This should give you regular frames no matter what else the program is doing.
For extra safety, you could increment a frame number in the OnTimer event. Now in the paintbox paint method you know which frame to paint. This means you won't jump frames if something else calls the paint method as well as the timer - you will just end up repainting the same frame for the extra call to OnPaint.
I use this for marching ants selections although I go one step further and use an overlaid canvas so I can draw independently to the selection and the underlying paintbox canvas to remove the need to repaint the main canvas when the selection changes. That requires calls to API but I guess you won't need it unless you are doing videos with a transparent colour.
Further research, including some talks with the Itinerant developer, has unfortunately made it clear that, due to concurrency restrictions, FM has been designed so that all GPU access goes through the main thread and therefore painting will always be limited. As a result I have decided FM is not suitable for my needs and I am re-evaluating my options.

DirectX Rendering

So I've created this program to render to a window using DirectX. It has an init() method which requires a HWND object so that it can initialize DirectX to the window, and then a render() method which is called inside of an infinite-loop, and then finally a cleanup() method to release DirectX-objects and devices. However, DirectX will render a couple of frames of a rotating cube (maybe enough for a half-rotation), and then the screen will go black. Then the cube will come back on, but it is still rotating during the black period. This continues in an on...off...on...off sort of pattern. Is DirectX maybe not rendering correctly to the window? What's wrong?
From my experience I think there is a good chance you need to explicitly implement the handling of the background erase event for your window (see this page), otherwise, the default implementation will kick in and get in your way (sometime erasing what DirectX just rendered as others suggested).
But well, as everybody mentioned already: this is only a little theory, and we would need some code to check this further :-).

How to have dynamic scene update in libqglviewer

I'm using libqglviewer for a project, I read input from a motion capture device through USB and display this as a human in the viewer. I draw the opengl things in the draw() method of the viewer, it works fine. However, when the motion controllers change, I actually get new position values and i draw these in the viewer, BUT i dont see this update until i click on the viewer screen. Is it possible to update the frames in the viewer by itself?
It looks like you just need to post an updateGL right after you get the new position values.
QGLWidget::updateGL()
void QGLWidget::updateGL () [virtual slot]
Updates the widget by calling glDraw().
For painting in 2D the function is called update.
Also, don't call it from inside your draw method (see updateGL in the libQGLViewer documentation).
This note comes from QWidget::paintEvent():
Note: Generally, you should refrain from calling update() or repaint() inside a paintEvent(). For example, calling update() or repaint() on children inside a paintevent() results in undefined behavior; the child may or may not get a paint event.
The same probably applies for QGLViewer.
You can also use repaint, but is isn't recommended (see QWidget::repaint()).