Signale zwischen Klassen

Alles rund um die Programmierung mit Qt
Antworten
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Signale zwischen Klassen

Beitrag von oberschlingel »

Hallo,

ich hätte da eine grundsätzliche Frage zu Widget-Klassen und Signalen:
Angenommen, ich definiere selbst eine Widget-Klasse A (eine Klasse, die von Widget erbt).
In dieser wiederum eine Widget-Klasse B.
Erst in dieser erstelle ich dann Buttons etc.
Wie kann ich nun der übergeordneten Klasse A das Signal des Buttons aus Klasse B mitteilen, ohne das Signal erst an B, und dort über eine emit-Funktion an Klasse A mitzuteilen?

Die Ebenen etwas übersichtlicher:
  • QApplication
    • QWidget A
      • QWidget B
        • QButton
Danke!
Goos
Beiträge: 360
Registriert: 17. August 2004 10:10
Wohnort: Black Forest

Beitrag von Goos »

Es schreibt dir keiner vor, dass du die Signale deiner Buttons zwingend mit Slots aus Klasse B verbinden musst ;)

Goos
FlorianBecker
Beiträge: 1213
Registriert: 2. Dezember 2004 10:54
Kontaktdaten:

Beitrag von FlorianBecker »

in Class WidgetB:

...
connect( widgetA -> meinButton, SIGNAL( ...

Ich nehme mal an, dass hilft dir.
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Beitrag von oberschlingel »

Aber woher kennt Widget B Widget A? Ist dann das *parent-Widget, dass ich im Konstruktor übergebe?
Ausserdem dachte ich, connections sind nur innerhalb einer Klasse erlaubt?

Merci
Goos
Beiträge: 360
Registriert: 17. August 2004 10:10
Wohnort: Black Forest

Beitrag von Goos »

Du hebst im Widget B einen Pointer auf dein Parent (Widget a) als Member auf.

Goos
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Beitrag von oberschlingel »

Ok, vielen Dank. Das mach ich dann mal so.
Aber geht da nicht eigentlich der Zweck verloren, dass Klassen nur erzeugt werden und dann mit Signalen verbunden. Damit die Klasse individuell einsetzbar bleibt?
Denn auf die Weise mit dem parent-Widget, benötigt Klasse B ja immer den Slot von Klasse A, oder?
Goos
Beiträge: 360
Registriert: 17. August 2004 10:10
Wohnort: Black Forest

Beitrag von Goos »

Noe, deine Signale gehen dann immer auf das Parent von Widget B, welches aber nicht zwingend A sein muss. Ob dir das in deinem Fall so sinnvoll ist oder nicht, das musst du selbst entscheiden :D

Goos
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Beitrag von oberschlingel »

Ja, aber das Parent braucht dann doch immer einen gleichnamigen Slot.
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Beitrag von oberschlingel »

Und kann ich auch mit dem parent vom parent verbinden?
Goos
Beiträge: 360
Registriert: 17. August 2004 10:10
Wohnort: Black Forest

Beitrag von Goos »

Richtig, du weisst also, dass du in deine Klasse X den entsprechenden Slot einbauen musst/kannst, wenn du in X die Klasse B mit den Buttons benutzen willst.

Goos
oberschlingel
Beiträge: 85
Registriert: 11. April 2006 09:25
Wohnort: Berlin

Beitrag von oberschlingel »

Goos hat geschrieben:Richtig, du weisst also, dass du in deine Klasse X den entsprechenden Slot einbauen musst/kannst, wenn du in X die Klasse B mit den Buttons benutzen willst.

Goos
Ok, super. Danke für Dein Wissen und Deine Zeit!
mikro
Beiträge: 60
Registriert: 19. April 2006 09:23
Wohnort: Erlangen
Kontaktdaten:

Beitrag von mikro »

hallo,
ich stehe vor einer gleichen Problematik und schaffs aber mit der Erläuterung noch nicht:
meine Parenklasse ist abgeleitet von QMainWindow und hat ein neues Attribut db bekommen. Das ist ein Pointer auf ein QSqlDatabase.

Code: Alles auswählen

class MainWindow : public QMainWindow, public Ui::MainWindow
{
	Q_OBJECT
	//
public:
	static MainWindow* self( QWidget* = 0 );
	QSqlDatabase* db;
...
QMainWindow ruft eine Klasse OpenProjectDialog auf. Dabei wird eine factory-Funktion verwendet und ein Pointer auf das MainWindow übergeben.

Code: Alles auswählen

class OpenProjectDialog : public QDialog, public Ui::OpenProjectDialog {
	Q_OBJECT
//
public:
	static OpenProjectDialog* self( MainWindow* = 0 );
private:
	OpenProjectDialog(MainWindow* = 0 );
..
irgendwann will ich dann aus dem OpenProjectDialog das db im MainWindow ändern:

Code: Alles auswählen

MainWindow* parent = static_cast<MainWindow *>( this->parent());
parent->db->setDatabaseName(LE_Server->text());
wie man sieht, probier ich schon das Ergebnis von this->parent() wieder zum MainWindow zu machen. Dabei bekomme ich aber die Fehlermeldung dass der static_cast illegal wäre.
Ursprünglich hatte ich es ohne static_cast und mit parentWidget() probiert. Das gibt nur ein QWidget zurück, somit beschwert er sich, dass er das QWidget nicht in MainWindow umwandeln kann.
Ich dachte dann, ich müsste wohl die parentWidget() - Funktion so überladen, dass sie ein MainWindow zurückgibt und habe mir qwidget.h angeschaut, wo die Funktion definiert wird:

Code: Alles auswählen

inline QWidget *QWidget::parentWidget() const
{ return static_cast<QWidget *>(QObject::parent()); }
daher dachte ich, ich müsste entsprechend mit meinem Code oben ein MainWindow zurückbekommen. Wie macht man das dann?
Goos
Beiträge: 360
Registriert: 17. August 2004 10:10
Wohnort: Black Forest

Beitrag von Goos »

mikro hat geschrieben:

Code: Alles auswählen

MainWindow* parent = static_cast<MainWindow *>( this->parent());
parent->db->setDatabaseName(LE_Server->text());
Von der Sache her funktioniert das schon so. Dein Kompiler mag das aber scheinbar nicht?
Was spricht er dann bei nem
MainWindow* parent = (MainWindow *)( this->parent());

Goos
mikro
Beiträge: 60
Registriert: 19. April 2006 09:23
Wohnort: Erlangen
Kontaktdaten:

Beitrag von mikro »

ich verwende übrigens MingW als Compiler und damit liessen sich die Quellen von Qt ja auch übersetzen, wo ich mir das mit dem static_cast abgeschaut habe. Ich tät ja gerne probieren ob er deine Version akzeptiert, aber ich scheitere gerade kläglich daran, dass er die forward declaration der parent-Klasse nicht akzeptieren will.
also: MainWindow ist parent, im Qt-Designer habe ich ihm gesagt er soll die .h von OpenProjectDialog inkludieren (macht er auch in der ui_MainWindow.h).
Nachdem ich in OpenProjectDialog ja sowas schreiben will:

Code: Alles auswählen

	static OpenProjectDialog* self( MainWindow* = 0 );
muss ich ihm erklären, was MainWindow ist. Ein

Code: Alles auswählen

#include MainWindow
kanns ja nicht sein, weil ich sonst im Kreis inkludiere. Also habe ich eine Vorwärtsdeklaration verwendet:

Code: Alles auswählen

class MainWindow;
//
class OpenProjectDialog : public QDialog, public Ui::OpenProjectDialog {
...
für die Zeilen in der .cpp in der ich MainWindow verwende kommt dann die Fehlermeldung:
ui\OpenProjectDialog.cpp: In member function `void OpenProjectDialog::on_pBOpen_clicked()':
ui\OpenProjectDialog.cpp:134: error: invalid use of undefined type `struct MainWindow'
ui\/OpenProjectDialog.h:24: error: forward declaration of `struct MainWindow'
Wieso hält er meine Vorwärtsdeklaration für ein Struct? in zwei anderen Dateien habe ich das genauso formuliert und es funktioniert. :(
mikro
Beiträge: 60
Registriert: 19. April 2006 09:23
Wohnort: Erlangen
Kontaktdaten:

Beitrag von mikro »

hey, es funktioniert!
hab parallel ein bischen gegoogelt und gelesen man braucht doch die ganze deklaration der Klasse wenn man auf Methoden zugreifen will. Also habe ich jetzt doch ein
#include "MainWindow.h"
gemacht und er kompiliert. :lol:
[EDIT]: funktionieren tuts deswegen trotzdem nicht *grummel* hab dafür aber mal einen neuen Thread aufgemacht, hat ja doch nicht mehr recht was mit diesem zu tun:
http://www.qtforum.de/forum/viewtopic.php?t=2025
Antworten