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()).
Related
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!
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.
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.
I have a QGLWidget which draws both 3D and 2D graphics (just like in Qt's overpainting example).
The thing is after I added drawing 2D graphics (moved code from paintGL() to paintEvent(), etc.), the widget stopped redrawing most of the times. It didn't redraw after resiging, after loading, and so on. So I put repaint() calls, it helped in some cases, but doesn't help in e.g. resizing.
So which function should I use to refresh the widget? Is it update() or updateGL() or repaint()? Or maybe there is a way to set some mode to enable automatic redrawing after resizing/load/...?
Thanks.
You should usually use 'update', as this will allow multiple queued paint events to be 'collapsed' into a single event. The update method will call updateGL for QGLWidgets. The 'repaint' method should be used if you want an immediate repaint.
If you have hooked up a timer to periodically call 'update', then failure to repaint regularly usually indicates that you're putting stress on the CPU.
Posting some of the code might make it easier to understand issues with resize/initialisation.
I am trying to create a custom CStatic control in vc++ and have a few problems.
I originally was just using a CStatic control with the SS_BLACKRECT style. This was good for the situation until I needed to display an image over the control on demand.
I figured out all the logistics behind actually drawing the image onto the control but I cant seem to figure out how to do so without interfering with other things.
Basically I want the control to function as a normal CStatic with the SS_BLACKRECT style most of the time.
Then I need to be able to call a method that will cause it to draw an image over the control instead. I am doing the drawing using GDI and have tried it both in the OnPaint() method and the DrawItem() method without success. I can get it to draw in the OnPaint() but when I call the base CStatic::OnPaint() it draws over my image.
I need to be able to allow it to draw like normal but then just throw an image in on top. When I tried to do it in the DrawItem() method I had a problem because obviously it was not drawing using the SS_BLACKRECT style but waiting for me to draw the control like its supposed to.
I guess what I think I'm looking for is one of three things. A way to draw using GDI after the base OnPaint() method finishes. A way to have the control draw the default SS_BLACKRECT style and then OWNERDRAW the image afterwards. Or the code to mimic the drawing of SS_BLACKRECT.
The last one might be the easiest but I just don't know all the things I need to set up to draw a CStatic control like the default DrawItem.
Try calling Default() in your OnPaint() handler.
Then, depending on whether you're drawing your image, you can then draw over the top of the standard CStatic control.
Here's a couple ideas:
If CStatic::OnPaint() draws over your image, then try calling it first and drawing your image afterwards.
Otherwise, from what little I've seen of SS_BLACKRECT, you should be able to replicate it's drawing simply be calling CDC::FillSolidRect() passing the rectangle of your control obtained through GetClientRect() and using the color returned by GetSysColor(COLOR_WINDOWFRAME)