[QT]Signal/Slot Problem über mehrere Klassen



  • Hallo zusammen,

    Ich schreibe gerade ein aufwendigeres Programm mit Oberfläche.
    Es geht nun darum, dass eine Auswahl aus einer QComboBox gelöscht werden soll. Die entsprechende Funktion dazu soll aufgerufen werden sobald eine Klasse ein bestimmtes Signal sendet.

    Zuerst einmal wo das Signal herkommt

    keycreate.hh
    class KeyCreate : public QWidget
    {
    	 Q_OBJECT
    //nicht relevanter Code
    
    signals:
    	void maxKeys(const QString &name); //dieses Signal wird naher gesendet
    
    private slots:
    	void createNewItemKey(const QString& name = ""); 
           //Das Signal kommt von dieser Funktion
    

    Nun die egentliche Funktion mit dem sendes des Signals

    keycreate.cc
    void KeyCreate::createNewItemKey(const QString& name)
    {
        QString tmpName;
        //nicht relevanter Code
    
    	if((keyTable->findItems(tmpName, Qt::MatchExactly)).size()!=0 && KeyTable->findItems(tmpName, Qt::MatchExactly).size()!=0)
    	{
    		emit maxKeys(tmpName); //hier wird also das Signal gesendet
                    //mit einer Variablen zusammen
    	}
    

    Jetzt die Klasse, die auf das Signal reagieren soll

    newkeydialog.hh
    #ifndef NEWKEYDIALOG_HH
    #define NEWKEYDIALOG_HH
    
    #include <QDialog>
    #include <QLabel>
    #include <QPushButton>
    #include <QComboBox>
    
    class KeyCreate;
    class NewKeyDialog : public QDialog
    {
    	 Q_OBJECT
          //nicht relevanter Code
    private slots:
    	void deleteFromNameList(const QString &name);
            //Diese Function soll ausgeführt werden wenn das Signal kommt
    
    private:
    	KeyCreate *keycreate;
    

    Jetzt Aufruf des connects und die Funktion

    newkeydialog.cc
    NewKeyDialog::NewKeyDialog(QWidget *parent) : QDialog(parent)
    {
    	qDebug() << "Programmstatus: In NewKeyDialog::NewKeyDialog";
    	this->setMaximumSize(240, 205);
    	this->setMinimumSize(240, 205);
    	this->setWindowTitle(tr("Add Key"));
    	this->setModal(true);
    
    	modes << tr("Pressed")
    		  << tr("Released");
    
    	createNameList();
    	createLabels();
    	createButtons();
    	createComboBoxes();
    
    	connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
    	connect(abortButton, SIGNAL(clicked()), this, SLOT(reject()));
    	connect(keycreate, SIGNAL(maxKeys(QString)), this, SLOT(deleteFromNameList(QString)));
    //Dies ist der betreffende connect Aufruf
    }
    void NewKeyDialog::deleteFromNameList(const QString &name)
    {
    	qDebug() << "Programmstatus: In NewKeyDialog::deleteFromNameList";
    	for(uint8_t i=0; i<nameList.size(); i++)
    	{
    		if(nameList[i]==name)  //name found --> delete from list
    		{
    			nameList.removeAt(i);
    //			nameList.sort();
    			comboName->clear();
    			comboName->addItems(nameList);
    			return;
    		}
    	}
    }
    

    Beim Kompilieren erscheint nun folgender Fehler in der newkeydialog.cc beim letzten connect Aufruf der quasi das Signal aus der anderen Klasse mit der Funktion verbinden soll

    no matching function for call to `NewKeyDialog::connect(KeyCreate*&, const char[18], NewKeyDialog* const, const char[29])'	newkeydialog.cc	/line 23	C/C++ Problem
    

    Verstehe jetzt eben nicht wieso der Fehler hier auftritt.
    Bin für jede Hilfe dankbar, falls noch Code oder Erklärungen fehlen einfach meckern 🙂



  • Ok, ich bin mir nicht sicher und kanns grad leider nicht nachprüfen, aber du deklarierst den Übergabeparameter sowohl beim Signal als auch beim Slot mit einer konstanten Referenz auf ein QStirng-Objekt, versuchst aber den Connect nur über den Parameter QString.

    Versuch mal die Zeile so zu ändern und versuch dann mal zu kompilieren:

    connect(keycreate, SIGNAL(maxKeys(const QString&)), this, SLOT(deleteFromNameList(const QString&)));
    

    Gruß
    Wulfgar



  • Hallo wulfgar,

    Das war auch meine erste Überlegung gewesen allerdings kommt dann beim kompilieren folgender Fehler

    no matching function for call to `NewKeyDialog::connect(KeyCreate*&, const char[25], NewKeyDialog* const, const char[36])'
    


  • The_EcKo schrieb:

    Hallo wulfgar,

    Das war auch meine erste Überlegung gewesen allerdings kommt dann beim kompilieren folgender Fehler

    no matching function for call to `NewKeyDialog::connect(KeyCreate*&, const char[25], NewKeyDialog* const, const char[36])'
    

    Ok, jetzt ist mir was bei der Fehlermeldung aufgefallen. Und zwar das "KeyCreate*&" sieht so aus als würde er dein keycreate als eine Referenz auf einen Pointer ansehen. Warum auch immer. Hast du vielleicht im Header irgendwas am Typ von keycreate geändert oder ist das immernoch KeyCreate*?



  • Nein habe nichts geändert
    ist immernoch

    KeyCreate *keycreate;
    

    in newkeydialog.hh



  • Wie initialisierst du keycreate?

    Ne, vergiss es, das ist Unsinn. Von Initialisierungen zur Laufzeit hat der Kompiler eh keine Ahnung. Ich fürchte im Moment kann ich dir nicht helfen. Hab grad keinen Rechner mit QT in der Nähe auf dem ich das mal testen könnte. Vielleicht kann dir ja ein anderer helfen, bis ich dazu komm.



  • Ok, eine Idee hab ich noch: Du deklarierst KeyCreate in der Header von NewKeyDialog vor, aber includierst du dann den Header von Keycreate in der Code-Datei von NewKeyDialog?
    Das ist was das ich sehr gerne vergesse und das gibt dann die merkwürdigsten Kompiler-Fehler.



  • Glaube der Fehler könnte daran liegen, dass ich
    in newkeydialog.hh lediglich eine Forwarddeklaration gemacht habe mit

    class KeyCreate;
    

    deswegen kann er auch die Funktion nicht finden die er aufrufen soll.

    Das nächste Problem dabei ist allerdings, newkeydialog.hh ist bereits in keycreate.hh includiert weil keycreate ein Signal von newkeydialog bekommt(Key erstellen)

    Wenn ich jetzt aber keycreate.hh in newkeydialog.hh includiere kommt mir

    ISO C++ forbids declaration of `KeyCreate' with no type	newkeydialog.hh
    

    in

    newkeydialog.hh
    Keycreate *keycreate;
    

    Haben wir wohl gerade denselben gedanken gehabt ^^



  • The_EcKo schrieb:

    Glaube der Fehler könnte daran liegen, dass ich
    in newkeydialog.hh lediglich eine Forwarddeklaration gemacht habe mit

    class KeyCreate;
    

    deswegen kann er auch die Funktion nicht finden die er aufrufen soll.

    Das nächste Problem dabei ist allerdings, newkeydialog.hh ist bereits in keycreate.hh includiert weil keycreate ein Signal von newkeydialog bekommt(Key erstellen)

    Wenn ich jetzt aber keycreate.hh in newkeydialog.hh includiere kommt mir

    ISO C++ forbids declaration of `KeyCreate' with no type	newkeydialog.hh
    

    in

    newkeydialog.hh
    Keycreate *keycreate;
    

    Haben wir wohl gerade denselben gedanken gehabt ^^

    Ja, das kommt daher, dass es C++ nicht mag, wenn sich Header gegenseitig verlinken. Dann musst du in der Header die Vorwärst-Deklaration machen und das include in der cpp machen, dann geht es.

    Aber bist du sicher, dass du NewKeyDialog in KeyCreate includieren musst? Das Signal/Slot-Konstrukt kommt von QT kommt doch normalerweise ohne sowas aus.



  • Super wulfgar jetzt geht es sehr geil danke 🙂

    Ja muss newkeydialog in keycreate bekommen weil das Signal accepted von newkeydialog wenn man auf "OK" drückt um einen Key zu erstellen an keycreate geht welches darauf hin die Funktion aufruft diesen Key tatsächlich zu erstellen.



  • Bitte schön. Freut mich doch, wenn ich helfen kann. 🙂



  • Servus ich bins nochmal 😃

    Also kompilieren klappt jetzt wunderbar nur beim ausführen kommt es jetzt zu Problemen:
    Und zwar stoppt das Programm jedesmal wenn es zum

    connect(keycreate, SIGNAL(maxKeys(QString)), this, SLOT(deleteFromNameList(QString)));
    

    in newkeydialog.cc kommt

    Der Debugger gibt mir folgende Meldung:

    Program received SIGSEGV, Segmentation fault.
    0x6a25bc00 in QObject::connect(QObject const*, char const*, QObject const*, char const*, QT::ConnectionType) 
    (sender=0xbaadf00d, signal=0x5a5257 "2maxKeys(QString)", receiver=0x72574e8, method=0x5a523a "1deleteFromNameList(QString)", type=AutoConnection)
    at kernel/qobject.cpp:2463
    2463 kernel/qobject.cpp : No such file or directory
    in kernel/qobject.cpp
    

    Denke es liegt daran, dass dieser connect Aufruf im Konstruktor erfolgt und auch noch irgendwie mit der Forwarddeklaration zusammenhängt. Kann das Puzzle aber nicht ganz zusammensetzen 🙂

    edit: DIe betreffende Zeile in qobject.cpp sieht so aus

    QMutexLocker locker(signalSlotLock(this));
    

Log in to reply