Nachricht (Event) von einem Dialog an seinen Parent schicken



  • Hallo zusammen,

    ich versuche von einem Dialog eine Event an seinen parent zu schicken, dass er gerade erzeugt wurde. Leider kommt im parent dieses Event nicht an oder ich versuche auf die falsche Art und Weise das Event auszulesen. Kann mir da jemand helfen?

    d_Error::d_Error(QWidget *parent) : QDialog(parent), m_ui(new Ui::d_Error)
    {
        QWidget* qw = parentWidget();
    
        QApplication::postEvent(qw, &QEvent(QEvent::ChildAdded));
        QApplication::sendPostedEvents();
    
        m_ui->setupUi(this);
    
        cErrorConsoleSIT::getInstance().registerDialog(this);
    }
    

    Hier die folgenden beiden Arten in der ich versucht habe das Event zu empfangen:

    void mw_PAIDMain::changeEvent(QEvent* e)
    {
        switch(e->type())
        {
            case QEvent::LanguageChange :    ui->retranslateUi(this);
                                             break;
            case QEvent::ChildAdded :        ui->cb_basicData_Player->addItem(QString("Done"));
                                             break;
            default:                         break;
        }
    }
    
    bool mw_PAIDMain::eventFilter(QObject* object, QEvent* event)
    {
        bool rv = false;
    
        if(object == this->uiError)
        {
            switch(event->type())
            {
                case QEvent::ChildAdded :   rv = true;
                                            ui->cb_basicData_Player->addItem(QString("Done"));
                                            break;
                default:                    break;
            }
        }
    
        return rv;
    }
    

    uiError ist in meiner Headerdatei folgendermaßen definiert:

    d_Error  *uiError;
    

    und wird so instanziiert:

    this->uiError = new d_Error(this);
    

    Und für alle die jetzt denken: Was will er denn? Er erzeugt den Dialog durch den parent und will dann nochmal ein extra Event werfen?!
    Ich brauche das äquivalent später für die Zerstörung des Kindfensters, fand es jedoch einfacher das Prinzip bei der Erzeugung des Fensters zu testen.

    Oder gibt es einen noch einfacheren Weg in parent zu merken, ob ein Kind erzeugt oder zerstört wurde?

    Edit: Vielleicht wird das ChildAdded / ChildRemoved Event ja auch automatisch an den parent gesendet und ich bin nur zu .... um es richtig abzufangen. 🙂



  • changeEvent ist auch das falsche, du suchst childEvent.
    Und gib doch keine Referenz auf ein temporäres Objekt zurück...
    Das erstellst du VOR dem Funktionsaufruf brav auf dem Stack und dann gibst du die Referenz weiter.

    Des weiteren sollte eigentlich das childEvent selber gesendet werden, da musst du gar nicht manuell posten! Also lass das postEvent() mal weg und versuch es nur mit einem QObject::childEvent() implementieren.



  • Stimmt, ich brauche das ChildEvent.

    Ich habe jetzt allerdings das Problem, dass nie ein event->removed() für den Dialog gesendet wird, wenn ich ihn schließe. Ich habe für das schließen bereits rejected, done und close ausprobiert. Mit welchem Befehl schließe ich denn das Kind, so das removed überhaupt zurück gegeben wird?

    Bisher schickt er immer nur die Events QEvent::ChildInserted und QEvent::Polished.



  • Richard schrieb:

    Ich habe jetzt allerdings das Problem, dass nie ein event->removed() für den Dialog gesendet wird, wenn ich ihn schließe.

    Schließen != removed!
    removed könnte eintreten (hab ich jetzt nicht getestet), wenn das dialog-Objekt zerstört wird. Ist das bei dir der Fall? Wie öffnest du deinen Dialog?
    Du kannst ja mal probehalber mit setParent() versuchen, das Child von dem alten parent wegzukriegen.



  • Ich zeige den Dialog mit show() an, da es sich um einen nicht modalen Dialog handeln soll.

    Also wenn ich den Code folgendermaßen umschreibe geht es:

    void d_Error::on_pb_Close_clicked()
    {
        this->done(0);
        this->~d_Error();
    }
    

    Allerdings scheint das etwas gewagt zu sein.



  • Richard schrieb:

    Ich zeige den Dialog mit show() an, da es sich um einen nicht modalen Dialog handeln soll.

    Also wenn ich den Code folgendermaßen umschreibe geht es:

    void d_Error::on_pb_Close_clicked()
    {
        this->done(0);
        this->~d_Error();
    }
    

    Allerdings scheint das etwas gewagt zu sein.

    1. Outch 😉
    2. geht das auch schöner:
    this->setAttribute(Qt::WA_DeleteOnClose);
    

    Im Konstruktor deines Dialogs. Das zerstört dann das Objekt, sobald das Fenster geschlossen wird (sofern das CloseEvent akzeptiert wurde), und somit wird auch das ChildEvent versandt.



  • Danke das hat mir zumindest für das ::Removed erstmal geholfen und funktioniert soweit auch.

    Ein Problem hab ich nur weiterhin mit dem ::Added. Ich sehe zwar, dass ein Kind hinzugefügt wird, jedoch hat es zu dem Zeitpunkt noch keinen Namen und damit kann ich es einfach nicht identifizieren. Ich habe auch schon versucht als erstes Statement im Konstruktor des Kindes setObjectName() zu verwenden, aber das hilft leider nicht.



  • Richard schrieb:

    Ein Problem hab ich nur weiterhin mit dem ::Added. Ich sehe zwar, dass ein Kind hinzugefügt wird, jedoch hat es zu dem Zeitpunkt noch keinen Namen und damit kann ich es einfach nicht identifizieren. Ich habe auch schon versucht als erstes Statement im Konstruktor des Kindes setObjectName() zu verwenden, aber das hilft leider nicht.

    Bei solchen Problemen würde ich sagen:
    Mütze abnehmen, durchatmen, evtl. nen Kaffe oder Tee, Doku aufschlagen und unvoreingenommen durchblättern 😛
    Dann kommt man auf solche abwegigen Konstrukte 😛

    MyDialog::MyDialog(QWidget* parent)
    // hier keinen Basisinitialisierer aufrufen.
    {
        setObjectName("p0wned");
        setParent(parent);
    }
    

    Und schon sollte da ein Objekt samt Namen auftauchen 🙂



  • Bei solchen Problemen würde ich sagen:
    Mütze abnehmen, durchatmen, evtl. nen Kaffe oder Tee, Doku aufschlagen und unvoreingenommen durchblättern 😛
    Dann kommt man auf solche abwegigen Konstrukte 😛

    MyDialog::MyDialog(QWidget* parent)
    // hier keinen Basisinitialisierer aufrufen.
    {
        setObjectName("p0wned");
        setParent(parent);
    }
    

    Und schon sollte da ein Objekt samt Namen auftauchen 🙂

    Super Sache, darauf muss man wirklich erstmal kommen. Etwas möchte ich der Vollständigkeit halber noch ergänzen: Das Eintragen des Elternfensters sollte durch die entsprechenden Attribute ergänzt werden, die vorher durch den Basisklasseninitialisierer gesetzt wurden. In meinem Fall war das lediglich die Eigenschaft "Window".

    // set parent window
        this->setParent(parent, Qt::Window);
    


  • Richard schrieb:

    Das Eintragen des Elternfensters sollte durch die entsprechenden Attribute ergänzt werden, die vorher durch den Basisklasseninitialisierer gesetzt wurden.

    Ich frag mich wo da was anderes gesetzt wurde 😉

    // im Header:
    explicit QDialog(QWidget *parent = 0, Qt::WindowFlags f = 0);
    // im CPP:
    QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
        : QWidget(*new QDialogPrivate, parent,
                  f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
    {
    #ifdef Q_WS_WINCE
        if (!qt_wince_is_smartphone())
            setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
    #endif
    }
    

    Es sollte also bei den Flags keinen Unterschied machen, ob du Basisinitialisiserung explizit mit dem parent-Argument aufrufst, oder automatisch die Basisinitialisierung durchführen lässt und gar nix angibst (parent = 0, windowFlags=0).

    Ich kann zumindest aus den Sourcen nicht erkennen, wie du darauf kommst dass QDialog(parent) noch das "Qt::Window"-Flag setzt.


Anmelden zum Antworten