[gelöst]Signal-Slot-Seiteneffekte

Alles rund um die Programmierung mit Qt
Antworten
Codiac
Beiträge: 21
Registriert: 23. Mai 2013 11:00

[gelöst]Signal-Slot-Seiteneffekte

Beitrag von Codiac »

Hallo Ihr fleissigen Programmierer,

in meiner Datenbankanwendung habe ich einige Connects erstellt, die bspw. beim Signal 'currentIndexChanged' einer QCombobox oder 'cellChanged' eines QTableWidget Methoden zur Aktualisierung aufrufen. Leider bekomme ich dadurch einige Seiteneffekte wie Mehrfachaufrufe oder Endlosschleifen und habe deshalb eine Methode 'setConnected(bool state)', mit der ich vor jeder Aktion nun alle Events zentral (dis-)connecten kann.

Ich finde diesen Weg nicht sehr elegant, darum meine Frage: Gibt es in Qt so etwas wie 'disconnect.all' und 'connects.restore'? Gibt es Lektüre, wie man das ganze Event-Handling richtig angeht und solche Fallstricke umgeht?
Für ein paar Tipps wäre ich echt dankbar.

Grüße,
Codiac
Zuletzt geändert von Codiac am 20. November 2013 12:41, insgesamt 1-mal geändert.
woody
Beiträge: 85
Registriert: 1. April 2011 21:13

Re: Signal-Slot-Seiteneffekte

Beitrag von woody »

Hallo,
es wäre mal die Frage zu klären, warum du überhaupt immer alles neu connectest?

Ein Codeausschnitt wäre gut.

mfg
veeman
Beiträge: 280
Registriert: 3. Oktober 2012 01:43
Kontaktdaten:

Re: Signal-Slot-Seiteneffekte

Beitrag von veeman »

Wenn du weißt das eine Änderung der Elemente zu einer Signalschleife führt dann musst du gezielt mit blockSignals arbeiten.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Re: Signal-Slot-Seiteneffekte

Beitrag von RHBaum »

Aber selbst das würd ich auch unelegant finden ...

Vielleicht versuchst es mal mit einem QTableView und einem eigenen Model drunter .... da hasst viel mehr Kontrolle.
Zumindest bin ich bisher noch nie in die versuchung gekommen, Signal-Slot-Verbindungen temporaer zu deaktivieren :-)

Ciao ...
Codiac
Beiträge: 21
Registriert: 23. Mai 2013 11:00

Re: Signal-Slot-Seiteneffekte

Beitrag von Codiac »

Hallo,

um noch eine Beispielsituation anzuhängen:

Ich habe eine QComboBox mit allen Artikeln meiner Applikation. Ändert sich dort der CurrentIndex, wird über ein Signal eine Methode aufgerufen, die zum Artikel passende Infos in einer Tabelle anzeigt. Diese wird beim Befüllen der QComboBox für jeden Eintrag ausgeführt, was ich nicht möchte.

Danke für den Hinweis mit blockSignals, war mir noch nicht bekannt.

Ich habe meine Methode setconnected(bool state) noch etwas erweitert. Sie zählt die Anzahl (dis-)connect-Versuche mit und connected erst wieder, wenn beide Aufrufe gleich oft statt gefunden haben. Damit kann ich verhindern, dass Aufrufe aus Unterfunktionen den Eventhandler zu früh wieder wecken. Ist immer noch nicht so schick, läuft aber ganz gut. (Mein innerer Schweinehund hält mich erstmal von weiteren Überlegungen ab... :D ). Vielleicht hilft es Jemandem:

Code: Alles auswählen

void quali::setConnected(bool state)
{
    static int disCalls = 0;                                                                                                    //Anzahl Disconnect-Versuche mitzählen

    if(state)                                                                                                                   //Verbindungen herstellen
    {
        if(disCalls > 0)
        {
            disCalls--;
        }

        if(disCalls == 0)
        {
            connect(actProtMode,SIGNAL(triggered()),this,SLOT(protChangeShown()));
            connect(actProtAdd,SIGNAL(triggered()),this,SLOT(protAdd()));
            connect(actProtEdit,SIGNAL(triggered()),this,SLOT(protEdit()));
            connect(actProtDel,SIGNAL(triggered()),this,SLOT(protDel()));
            connect(actProtOk,SIGNAL(triggered()),this,SLOT(protOk()));
            connect(actProtEsc,SIGNAL(triggered()),this,SLOT(protEsc()));
            connect(ui->cmbProtArt,SIGNAL(currentIndexChanged(int)),this,SLOT(protRefreshOrders()));
            connect(ui->cmbProtOrder,SIGNAL(currentIndexChanged(int)),this,SLOT(protRefreshOrderData()));
            ...
        }
    }
    else                                                                                                                        //Verbindungen trennen
    {
        if(disCalls == 0)
        {
            disconnect(actProtMode,SIGNAL(triggered()),this,SLOT(protChangeShown()));
            disconnect(actProtAdd,SIGNAL(triggered()),this,SLOT(protAdd()));
            disconnect(actProtEdit,SIGNAL(triggered()),this,SLOT(protEdit()));
            disconnect(actProtDel,SIGNAL(triggered()),this,SLOT(protDel()));
            disconnect(actProtOk,SIGNAL(triggered()),this,SLOT(protOk()));
            disconnect(actProtEsc,SIGNAL(triggered()),this,SLOT(protEsc()));
            disconnect(ui->cmbProtArt,SIGNAL(currentIndexChanged(int)),this,SLOT(protRefreshOrders()));
            disconnect(ui->cmbProtOrder,SIGNAL(currentIndexChanged(int)),this,SLOT(protRefreshOrderData()));
            ...
        }

        disCalls++;
    }
}
Danke jedenfalls für Eure Tipps,
Marcel
Antworten