QWidget constructor triggers processEvents (on Windows)?



  • I was experiencing a bug in my application that did not make much sense to me, and finally tracked it down.

    What was happening:
    This piece of code is executed in a dialog, in response to some signal. This entirely happens in the GUI thread. There are other threads working, but in no way could they be inducing a bug in this small piece of code (or so I thought...)
    @CurrentObject = new Object; // CurrentObject is a member of this class
    Q_ASSERT(CurrentObject);

        if (CurrentOperator)
        {
            //Create a widget instance
            Q_ASSERT(!CurrentObjectWidget);
    
             //Virtual method that returns a new QWidget subclass
            CurrentObjectWidget = CurrentObject->CreateConfigurationWidget(this);
    
            if (CurrentObjectWidget)
            {
                 Q_ASSERT(CurrentObject); //<<<< CurrentObject sometimes becomes null here?!?!?!
    

    @

    I tracked the bug down by watching when CurrentObject got modified. And to my surprise, it turns out that the constructor of QWidget seems to trigger a processEvents (or something equivalent), which makes it process some pending events, one of which triggers another signal that clears CurrentObject.

    Here's the call stack I got:
    @
    [ That particular message is forwarded to my dialog and happens to reset some data ]
    ....exe!...::...::OnMsgRefreshClientGui(unsigned int, long) Line 1428 C++
    mfc100ud.dll!CWnd::OnWndMsg(unsigned int, unsigned int, long, long *) Line 2383 C++
    ...
    mfc100ud.dll!AfxWndProcBase(HWND__ *, unsigned int, unsigned int, long) Line 420 C++
    user32.dll!75d062fa()
    user32.dll!75d06d3a()
    ...
    user32.dll!75d160dc()
    QtWinMigrate_x86_d4.dll!QMfcApp::winEventFilter(tagMSG *, long *) Line 414 C++
    QtCore_x86_d4.dll!QCoreApplication::filterEvent(void *, long *) Line 2510 C++
    QtGui_x86_d4.dll!QtWndProc(HWND__ *, unsigned int, unsigned int, long) Line 1484 C++
    user32.dll!75d062fa()
    user32.dll!75d07316()
    user32.dll!75d06ce9()
    user32.dll!75d06de8()
    user32.dll!75d0a740()
    ntdll.dll!7796010a()
    user32.dll!75d0a95d()
    user32.dll!75d0a8e8()
    user32.dll!75d0aa3c()
    user32.dll!75d08a5c() //CreateWindowEx
    QtGui_x86_d4.dll!QWidgetPrivate::create_sys(HWND__ *, bool, bool) Line 452 C++
    QtGui_x86_d4.dll!QWidget::create(HWND__ *, bool, bool) Line 1490 C++
    QtGui_x86_d4.dll!QWidgetPrivate::createWinId(HWND__ *) Line 2518 C++
    QtGui_x86_d4.dll!QWidgetPrivate::setParent_sys(QWidget *, QFlags<enum Qt::WindowType>) Line 648 C++
    QtGui_x86_d4.dll!QWidget::setParent(QWidget *, QFlags<enum Qt::WindowType>) Line 10098 C++
    QtGui_x86_d4.dll!QWidgetPrivate::init(QWidget *, QFlags<enum Qt::WindowType>) Line 1345 C++
    QtGui_x86_d4.dll!QWidget::QWidget(QWidget *, QFlags<enum Qt::WindowType>) Line 1155 C++
    ....dll!...::...::CreateConfigurationWidget(QWidget *) Line 128 C++
    ...
    QtGui_x86_d4.dll!QTreeWidget::setCurrentItem(QTreeWidgetItem *) Line 2803 C++
    ....dll!...::...::RefreshOperatorList(QTreeWidgetItem *, ...) Line 895 C++
    ...
    ....dll!...::...::DoReset() Line 1584 C++
    ....dll!...::...::qt_metacall(QMetaObject::Call, int, void * *) Line 203 C++
    ...
    QtGui_x86_d4.dll!QAbstractButton::clicked(bool) Line 204 C++
    [...]
    @
    As you can see, the click triggers a refresh, where I call the CreateConfigurationWidget method, which constructs a QWidget... but then it goes deep in low level methods, and then it processes some window message, which was really not expected.

    It's this call in QWidgetPrivate::create_sys that seems to trigger a processing of the pending events:
    @id = CreateWindowEx(exsty, reinterpret_cast<const wchar_t *>(windowClassName.utf16()),
    reinterpret_cast<const wchar_t *>(title.utf16()), style,
    data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(),
    parentw, NULL, appinst, NULL);@

    Is this expected behavior? That means everytime I create a widget, I'd have to expect that external messages that can affect my object will be processed at that point?
    Is there any way to avoid this?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.