Seite 1 von 1

[teilw. gelöst]Signal/Slot über mehrere Klassen

Verfasst: 20. November 2009 10:56
von The_EcKo
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

Code: Alles auswählen

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

Code: Alles auswählen

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

Code: Alles auswählen

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

Code: Alles auswählen

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

Code: Alles auswählen

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 :)

Verfasst: 20. November 2009 11:22
von Christian81
Da Du KeyCreate.h nicht includierst weiss der Compiler nicht dass KeyCreate von QObject abgeleitet ist und kann demnach auch nicht casten.

Verfasst: 20. November 2009 11:33
von The_EcKo
Hallo Christian81,

Danke für die schnelle Antwort, das problem ist aber dass keycreate
newkeydialog.hh includiert hat weil keycreate auf ein Signal von diesem Dialog reagieren muss(Key erstellen).
Wenn ich jetzt keycreate.hh in newkeydialog icludiere bekomme ich folgenden Fehler

Code: Alles auswählen


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

in der Zeile
KeyCreate *keycreate;
Das wollte ich ja umgehen indem ich in newkeydialog.hh ganz oben

Code: Alles auswählen

class KeyCreate
gemacht habe.

Verfasst: 20. November 2009 12:13
von RHBaum
Verstehe jetzt eben nicht wieso der Fehler hier auftritt.
- "class KeyCreate; " iss nen wunderschoener Forward
- connect iss eine Methode, die internas an QOBject Instanzen aufruft, um die über die Signal Slot Methoden zu verbinden. Das Connect ruft also intern an den übergebenen Instanzen Methoden von QOBject auf. deshalb will es als Parameter QObject Zeiger haben !

du uebergibst aber Keyclass Zeiger. Das connect an der stelle sieht aber nur das "class KeyCreate; " Damit weiss es zwar, das es KeyCreate gibt, aber ned das das auch nen QOBject ist.

Der Forward in deinem Header iss schon schoen !!!
Aber das connect hat mehr anforderungen, deshalb braucht das connect die Deklaration von KeyCreate.
Das gute ist aber, der connect ist in der cpp, also braucht es nur intern die Deklaration. Was bedeutet, das du das #include "Keyclass.h" in deiner NewKeyDialog.cpp machen kannst. Was weitaus weniger Abhaengigkeiten von Keyclass erzeugt.
Die Folge, alle klassen die NewKeyDialog deklariert brauchen, brauchen keinerlei infos ueber Keyklass, nur das es die Klasse gibt (forward) wird ihnen mitvererbt, aufn ersten blick vielleicht unschoes, aufn 2. blick gar ned mal so schlecht, weil es unter umstanden vor doppelten Definitionen schuetzt. der Compiler meckert dann scho etwas eher, falls man irgendwo noch ein anderes global zugaengliches Keyclass definiert.

Also einfach das include in die cpp noch rein, und alles ist perferkt

war das einigermassen verstaendlich ?

noch was
.cc
.hh
wer verwendet solche Endungen ??? ^^

Edit: grad nachgeschaut, im gcc werden die .cc und .hh als c++ interpretiert. Also vergiss den Einwand, alles ok !
Kam mir nur etwas "ungewöhnlich" vor :-)


Ciao ....

Verfasst: 20. November 2009 12:25
von The_EcKo
@RHBaum

Ahhh jetzt geht es vielen vielen Dank =)

wegen cc und hh mein Vorgänger bei diesem Projekt hat das Ganze so eingerichtet von daher einfach weitergemacht^^

Verfasst: 23. November 2009 10:07
von The_EcKo
Servus ich bins nochmal :D

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

Code: Alles auswählen

connect(keycreate, SIGNAL(maxKeys(QString)), this, SLOT(deleteFromNameList(QString)));
in newkeydialog.cc kommt

Der Debugger gibt mir folgende Meldung:

Code: Alles auswählen

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 qobect.cpp sieht so aus

Code: Alles auswählen

QMutexLocker locker(signalSlotLock(this));

Verfasst: 23. November 2009 15:46
von RHBaum
QMutexLocker locker(signalSlotLock(this));
wenn der auf diese Zeile fliegt, dann ist deine connection aber queued ... das heisst dein signal wird in nem anderen Thread gefeuert, als wie der Slots es empfaengt, richtig ???

Ciao ...

Verfasst: 23. November 2009 16:52
von The_EcKo
Hm soweit ich das überblicke werden aber im restlichen Programm keine Threads gestartet die das Signal beeinträchtigen könnten.
Oder hab ich dich falsch verstanden?

Verfasst: 23. November 2009 17:08
von AuE
Ansonsten ist ein Mutex naja sagen wir sinnlos. Daher hatte er die Vermutung. Mutex is ja zum Schutz bei Multithreaded da.

Verfasst: 24. November 2009 08:55
von The_EcKo
Hab mein Ursprungsproblem jetzt ohne Signale gelöst weil ich nicht mehr so die Zeit hatte mich damit zu beschäftigen :D
Aber trotzdem danke an alle die geholfen haben.