Animation in Qt 4.6 - c++

I've a block of code where I've used Qt's new animation framework. I needed the animation just in that block of code and I don't need the animation related variables in other places. Clearly, the animation won't work if it is destroyed before the animation completed. For example, the following doesn't work:
if (animate)
{
QPropertyAnimation animation(_piece_images[svg_index].getImage(), "pos");
animation.setDuration(200);
animation.setEndValue(getCellPos(row, col));
animation.setEasingCurve(QEasingCurve::InOutSine);
animation.start();
}
So I'm using animation using pointer:
if (animate)
{
QPropertyAnimation *animation = new
QPropertyAnimation(_piece_images[svg_index].getImage(), "pos");
animation->setDuration(200);
animation->setEndValue(getCellPos(row, col));
animation->setEasingCurve(QEasingCurve::InOutSine);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
My question is, is there any memory leak in the above solution? Please provide reference if possible, probably I've missed something.

By passing in QAbstractAnimation::DeleteWhenStopped to the start() method, you should be covered so long as you allow the animation to run to completion, manually call stop(), or explicitly call delete at some point. Though if your loop count is -1 (infinite) then you must make the manual call to stop() or delete.
The documentation for the DeletionPolicy parameter to start() makes this as explicit as I'd think one would need. But you can certainly put some debug code in to check and make sure the destructor gets called when you think it should.
Moreover, it couldn't hurt to regularly run Valgrind or another leak-checker. Good to get in the habit sooner rather than later!
UPDATE: If you're curious as to how an object is able to "delete this", the trick is that there's something called QObject::deleteLater(). It queues the deletion so that it happens the next time the event loop runs. If you're ever curious about the mechanics of a Qt routine, don't be afraid to go look at the source... it's usually very clear:
http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/animation/qabstractanimation.cpp#line599

Related

Would this QChangesOpacityEffect usage cause a potential memory leak? (but only way to force repaint...)

So, I am working with some QWidgets inside a QMdiArea, and i want to play with the opacity og a graphicview inside the QWidgets with a dial, using the QGraphicsOpacityEffect.
This is the slot that receives the dial signal to set the new opacity:
void MainWindow::changeWindow1Transparency(int dialValue)
{
QGraphicsOpacityEffect* op = new QGraphicsOpacityEffect(ui->graphicsView); //Potential memory leak here
op->setOpacity(qreal(dialValue)/255);
ui->graphicsView->setGraphicsEffect(op);
ui->graphicsView->repaint();
}
This is the only way i've managed to make the opacity change immediately when turning the dial. But I fear that this might cause a memory leak because of the new constantly creating new effects.
I have tried to set this QGraphicOpacityEffect *op as an attribute of the class. But then, when I turn the dial, the opacity doesn't change immediately but only when I move the window around the QMdiArea. The same happens when calling the QGraphicsView->GraphicsEffects().. Any ideas on why this is happening? how could I prevent the memory leak and at the same time force that the opacity changes immediately with the dial?
Thanks!
There shouldn't be a memory leak as long as you pass a parent object to your QGraphicsOpacityEffect or set a widget with the effect.
The way you've set it up ui->graphicsView->setGraphicsEffect(op), According to QWidget::setGraphicsEffect:
Sets effect as the widget's effect. If there already is an effect installed on this widget, QWidget will delete the existing effect before installing the new effect.
You've got yourself a guarantee that the intermediate objects will be deleted. With regards to the final GraphicsEffect, as your ui->graphicsView widget is destroyed, so does the GraphicsOpacityEffect (see Qt Object Trees and Ownership).
As for forcing the opacity changes to your dial, try adding repaint(); to your slot. This will repaint your entire widget. (And after that, also try parentWidget()->repaint() as the parent sometimes needs a little nudging.)
As Jeremy Friesner mentions in the comments and as you've tried before, it may be more efficient to set QGraphicOpacityEffect *op as a member of the class, calling op->setOpacity(x) in your slot without having to create a new effect each time the slot is triggered. Keep in mind the repaint semantics above.

GTK+, how to update widgets into mainloop?

My program work with 2 threads (boost::thread) and, of course, 1 mainloop.
The problem is that I currently update 2 widgets at the end of each threads, and thoses updates sometime provoke segmentations faults.
I use the function "gtk_widget_queue_draw" to update widgets into my threads.
I saw somewhere on the web that we must update all of our widgets into the main loop and never into threads, so my question is simple, how do I do that ?
With signals maybe ?
I already tried with the fundtion "g_idle_add" but it don't work either.
It seems that I can also use gtk_thread_enter and gtk_thread_leave but thoses two functions are deprecated.
Thanks
Edit: I almost forgot; if I want to update manually my widgets, it's because they don't updates automatically (and one of thoses widgets is a chart drawn with cairo)
"g_idle_add" seem to be the good way to do that, but it ends up with segmentation fault too.
Here is the way I implemented this:
In my thread:
g_idle_add ((GSourceFunc)update_label_monitor_cpu, &string_cpu);
And the function itself:
void update_label_monitor_cpu(std::string *str)
{
std::string tmp = *str;
gtk_label_set_label(GTK_LABEL(label_monitor_cpu), (gchar*)tmp.c_str());
}
g_idle_add() is the correct way to do this. You get a segmentation fault because your strings go out of scope, and are destroyed, before the idle callback ever runs. You'll need to manually manage the memory for the strings in your idle callback; for instance, using g_strdup() and g_free().

Lifecycle of an OpenGLAppComponent in Juce

I can't seem to get a good grasp on how these OpenGLAppComponents come and go. Can someone please correct my thinking if it is wrong?
Object is created that inheirts from OpenGLAppComponents and Timer. Object exists in the AudioProcessorEditor.
Call initialise() (This is where we attach to an openGLContext? A timer is started.)
addAndMakeVisible(&my_gl_appcomponent); is called from the editor, telling it that this will be drawn.
my_gl_appcomponent.setBounds(...) is called specifying the size and location of the GL component.
The timer callback calls repaint() repeatedly, updating your display.
When the editor is closed, we call shutdown(), where we detach from the openGLContext.
Delete my_gl_component, calling shutdownOpenGL() in the destructor
We are free to open the editor again, goto 2.
Am I missing anything? Do I have extra things? I've been trying to find the cause of this GL_INVALID_FRAMEBUFFER_OPERATION error for the second day in a row and I'm getting pretty frustrated.

QT Managing OpenGL context in a separate thread

I have learned about setting up separate rendering thread for Qt QGLWidget here ,here and here .
I also managed to get a kind of "working" setup: clearing color in the viewport.Seems to be ok.But I am getting the following warning:
QOpenGLContext::swapBuffers() called with non-exposed window, behavior
is undefined
I first create a widget that inherits from QGLWidget.Where I also setup OpenGL Format:
In the Widget constructor:
QGLFormat format;
format.setProfile(QGLFormat::CompatibilityProfile);
format.setVersion(4,3);
format.setDoubleBuffer(true);
format.setSwapInterval(1);
setFormat(format);
setAutoBufferSwap(false);
Then I init the rendering thread in the same Widget:
void GLThreadedWidget::initRenderThread(void){
doneCurrent();
context()->moveToThread(&m_renderThread);
m_renderThread.start();
}
and from that point the whole rendering is done inside that thread:
RenderThread constructor:
RenderThread::RenderThread(GLThreadedWidget *parent)
:QThread(),glWidget(parent)
{
doRendering = true;
}
RenderThread run() method:
void RenderThread::run(){
glWidget->makeCurrent();
GLenum err = glewInit();
if (GLEW_OK != err) {
printf("GLEW error: %s\n", glewGetErrorString(err));
} else {
printf("Glew loaded; using version %s\n", glewGetString(GLEW_VERSION));
}
glInit();
while (doRendering){
glWidget->makeCurrent();
glClear(GL_COLOR_BUFFER_BIT );
paintGL(); // render actual frame
glWidget->swapBuffers();
glWidget->doneCurrent();
msleep(16);
}
}
Anyone can point out where is the issue?And if that message can be discarded? Also a straightforward and concise explanation on render thread setup in Qt would be extremely helpful.Using Qt 5.2 (Desktop OpenGL build)
With what you've shown, it looks like that message handler warning you were getting was because you started triggering buffer swaps "too soon" in the window setup sequence, either directly through QGLContext::/QOpenGLContext::swapBuffers() or indirectly through a number of possible ways, none of which are really detectable outside of manual debugging. What I mean by too soon is before the widget's parent window was marked "exposed" (before it was being displayed by the windowing system).
As far as whether the message can be discarded, it can...but it's not safe to do, as in it's possible to get undefined behavior for the 1st few frames or so where you do it and the window's not ready (especially if you're immediately resizing to different extents at startup than your .ui file specifies). Qt documentation says that before your window's exposed, Qt has to basically tell OpenGL to paint according to what are effectively non-trustworthy extents. I'm not sure that's all that can happen though personally.
With the code you showed, there's an easy fix--avoid even starting your render logic until your window says it's exposed. Detecting exposure using QGLWidget isn't obvious though. Here's an example roughly like what I use, assuming your subclass from QGLWidget was something like 'OGLRocksWidget', it was a child of a central widget, and that central widget was a child of your implementation of QMainWindow (so that your widget would have to call parentWidget()->parentWidget() to get at its QMainWindow):
OGLRocksWidget::paintGL()
{
QMainWindow *window_ptr =
dynamic_cast<QMainWindow *>(parentWidget() ? parentWidget()->parentWidget() : 0);
QWindow *qwindow_ptr = (window_ptr ? window_ptr->windowHandle() : 0);
if (qwindow_ptr && qwindow_ptr->isExposed())
{
// don't start rendering until you can get in here, just return...
// probably even better to make sure QGLWidget::isVisible() too
}
}
Of course you don't have to do this in your implementation of QGLWidget::paintGL(), but in your particular setup you're better off not even starting your render thread until your window tells you it's exposed.
It looks like you have might have slightly bigger problems than that though. You weren't hooking the right GL activity into the right places in your code vs QGLWidget's intent. I feel for the position you were in because the documentation on this is a little spotty and scattered. For that part, QGLWidget's detailed description down where it says "Here is a rough outline of how a QGLWidget subclass might look" is a good place to start getting the idea. You'll want to override any of the key virtuals in there that you have related code for and move them into those calls.
So for example, your widget's constructor is doing setup work that is probably safer to put in an initializeGL() override, since QGLWidget's intent is to signal you when it's safely time to do that through that call. What I mean by safer whenever I say that here is that you won't get seemingly random debug exceptions (that in release builds can silently wreak havok on your runtime stability).
Side advice: install Qt source, point your debugger at it, and watch your code run, including into Qt. Your setFormat() call, last time I watched it, actually deletes the current underlying QOpenGLContext. That's probably good to know because you'll want to create a new one soon after or at least test out your options.
The risk of instability is why I'm trying to put together at least some kind of answer here a year later. I just learned this through a lot (too much) debugging. I love what the Qt team's done with it, but Qt will be much better off when they finish migrating everything over to QOpenGL* calls (or wherever they see a final proper place for their OpenGL support including permanent considerations for it and windowing support together).
A QOpenglWidget comes with its own context. If you want a background thread to do the rendering, you have to pass a shared context to the thread and do a few steps correct.
Details in: https://stackoverflow.com/a/50368372/3082081

Changing QLineEdit TextBox's inside of loop dynamically

I'm building some code where I'm running a while loop and, within the loop, am trying to change the contents of a couple of textboxes with QLineEdit's setText(). However, merely calling setText within the loop does not work; the textboxes only change their actual value once the code has run through, instead of at each iteration.
I have little experience with C++ or Qt, but the project I'm working on must use them. Any help?
EDIT: I'm guessing this must be something simple that I simply am having troubles because of my lack of familiarity/knowledge, but if more information is needed I'll gladly provide it!
The problem is that QT needs control to return to the UI thread's event loop in order to update the QLineEdit's visual appearance. The quick and dirty way to run the event loop is to add QCoreApplication::processEvents() after each call to setText(). The proper way to fix it is to move the blocking process that sets the value of the text box into another thread, expose an updateText(QString text) signal, connect it to the TextBox's setText(const QString & text) slot and emit that signal whenever you want the text to be updated.
Please see my answer to a similar question for more detail: unexplained delay after QProgressBar finish loading
You might also want to check out some of the documentation on QThreads and the Qt signal slot system: http://harmattan-dev.nokia.com/docs/library/html/qt4/threads-qobject.html
In my case, calling only repaint() or processEvents() won't do the job.
Within your function loop, call both QCoreApplication::processEvents(); and repaint();:
for (i;...)
{
//do your calculations
//...
QCoreApplication::processEvents();
repaint();
}
Calling ui->mywidget->update() didn't make any different as well.
(Tested for Qt4.8.3 on Kubuntu 12.10 and Qt5.0.1 on Windows XP)