PDA

View Full Version : Call a function at a dialog execution



Nesbit
17th April 2012, 16:13
I'm writing an application in which I need to open a dialog and execute automatically (without clicking on a push button for example) some animation function.

For opening the dialog, the main windows has a push button that is connected to a slot, which contains


//Open the dialog
dialog dlg=new Dlg ;
dlg.exec();
//Get data from the dialog after it is closed
...

My dialog class is something like the following, where functionToBeCalled() is the function to be called:

class Dlg : public QDialog
{
/* ...other attributes and methods here... */

public:
void functionToBeCalled();
}

Could anybody tell me how to do that please?

Thank you in advance for your help.

wysota
17th April 2012, 16:47
Either reimplement QDialog::exec() or QWidget::showEvent()

Nesbit
18th April 2012, 10:50
Thank you wysota for your reply.

But could you please be more specific?

Someone suggested me with the following code:

int Dlg::exec()
{
functionToBeCalled();
return QDialog::exec();
}
but the problem is that, my functionToBeCalled() is a function that does some animation (inside a QGraphicsView), so if we call this function before the exec() function, the user will not see the animation.
I have got an idea but could not make it work. In the following code, I re-implement completely the exec() function, by just copying the source code of QDialog::exec() and adding functionToBeCalled() after show():

int Dlg::exec()
{
Q_D(QDialog);

if (d->eventLoop) {
qWarning("QDialog::exec: Recursive call detected");
return -1;
}

bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
setAttribute(Qt::WA_DeleteOnClose, false);

d->resetModalitySetByOpen();

bool wasShowModal = testAttribute(Qt::WA_ShowModal);
setAttribute(Qt::WA_ShowModal, true);
setResult(0);

//On Windows Mobile we create an empty menu to hide the current menu
#ifdef Q_WS_WINCE_WM
#ifndef QT_NO_MENUBAR
QMenuBar *menuBar = 0;
if (!findChild<QMenuBar *>())
menuBar = new QMenuBar(this);
if (qt_wince_is_smartphone()) {
QAction *doneAction = new QAction(tr("Done"), this);
menuBar->setDefaultAction(doneAction);
connect(doneAction, SIGNAL(triggered()), this, SLOT(_q_doneAction()));
}
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM

bool showSystemDialogFullScreen = false;
#ifdef Q_OS_SYMBIAN
if (qobject_cast<QFileDialog *>(this) || qobject_cast<QFontDialog *>(this) ||
qobject_cast<QWizard *>(this)) {
showSystemDialogFullScreen = true;
}
#endif // Q_OS_SYMBIAN

if (showSystemDialogFullScreen) {
setWindowFlags(windowFlags() | Qt::WindowSoftkeysVisibleHint);
setWindowState(Qt::WindowFullScreen);
}
show();

/****** MY ANIMATION HERE *******/
functionToBeCalled();

#ifdef Q_WS_MAC
d->mac_nativeDialogModalHelp();
#endif

QEventLoop eventLoop;
d->eventLoop = &eventLoop;
QPointer<QDialog> guard = this;
(void) eventLoop.exec(QEventLoop::DialogExec);
if (guard.isNull())
return QDialog::Rejected;
d->eventLoop = 0;

setAttribute(Qt::WA_ShowModal, wasShowModal);

int res = result();
if (deleteOnClose)
delete this;
#ifdef Q_WS_WINCE_WM
#ifndef QT_NO_MENUBAR
else if (menuBar)
delete menuBar;
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM
return res;
}
The first error I got is _'QDialog::d_func' : cannot access private member declared in class 'QDialog'_.
Hope somebody can help.
Have a nice day !

wysota
18th April 2012, 11:02
but the problem is that, my functionToBeCalled() is a function that does some animation (inside a QGraphicsView), so if we call this function before the exec() function, the user will not see the animation.
The function should only start the animation and not "perform" it. I'm not going to explain it here how Qt event system works, you should read that in the docs.

Nesbit
20th April 2012, 14:57
Hmm... did you mean we cannot do what I wanted to do, wysota?
I tried something like

dialog.display();
animation();
It works, but lacks some features I need from dialog.exec() :(

P/s: You replied so quickly wysota, thank you so much :D

wysota
20th April 2012, 15:37
Qt is an event-driven framework. If you say "show me that dialog", it does not mean the dialog is actually shown at this particular moment in time. Instead an event is generated that at some point in future will be processed and will result in initializing surface for the widget and eventually showing it on screen. The same goes with animations -- an animation usually behaves in such a way that it changes some property (like position or color) of an object. If you want to visualize such a change, you call update() on the widget which again causes an event to be generated that at some later point in time is processed and the widget is redrawn. Some time later you have to change that property again to have an effect of smoothly changing that value. The way to do this is again through events, this time triggered by a timer that tells you a specified period of time has passed. Thus your "animation()" call doesn't actually perform the animation but only schedules the first frame of the animation and subsequent frames are scheduled and performed "some time later". Thus the order of calls (like starting the animation and calling exec) does not matter since both of them are not processed immediately.

If you were thinking of doing the animation this way:


for(int i=0;i<1000;++i) item->setPos(i, 200);

then obviously this will not work since by the time the widget is updated through events, the item will already have position set to (999,200) and thus you will only see the last frame of the animation.