Qt - Layout

Barade

Barade

Kellerkind
Hiho,
ich lese zurzeit ein Qt-Buch und wollte mal eine kleine Anwendung schreiben.
Jetzt habe ich aber schon zu Beginn ein Problem.
Mit folgendem Code im Konstruktor will ich das Layout des MainWindows bestimmen:
Code:
	QHBoxLayout *layout = new QHBoxLayout;
	layout->addWidget(startNumberLabel);
	layout->addWidget(startNumber);
	layout->addWidget(endNumberLabel);
	layout->addWidget(endNumber);
	setLayout(layout);
Zur Laufzeit tritt dann aber folgender Fehler auf:
Code:
QWidget::setLayout: Attempting to add QLayout "" to MainWindow "", which already has a layout
Das Ganze passiert natürlich nicht, wenn ich die Methode setLayout nicht aufrufe. Hab ich was verpasst, haben Widgets standardmäßig schon ein Layout oder wieso funktioniert das nicht?
 
Schau Dir mal die Beschreibungen der Konstruktoren an. Da gibt es nur zwei Möglichkeiten:
  1. Du steckst ein Layout in ein bereits vorhandenes. Hierzu verwendest Du entweder den zweiten Konstruktor alleine - oder den dritten und fügst das Layout einem anderem hinzu.
  2. Du erzeugst ein "top-level layout"; hierbei mußt Du den ersten gezeigten Konstruktor verwenden.
Wenn Du keine Parameter angibst, wird der Compiler den dritten Konstruktor wählen, weil dieser alle Parameter mit Vorgabewerten belegt und daher zur Not auch ohne Parameter aufgerufen werden kann.

Du brauchst aber den Konstruktor #1, z.B.:
Code:
topLayout = new QHBoxLayout(this, 0, 5, "topLayout");
topLayout->addWidget(foobarLabel);
//kein setLayout(layout);

Zudem ist häufig ratsam, den GUI-Entwurf mit dem Programm designer durchzuführen. (Ist bei manchen Systemen nicht im Suchpfad.)

Manche Details wird man zwar später von Hand machen, aber Vorlagen (Positionierung, Variablennamen der Widgets etc) lassen sich damit bequem erstellen.
 
Danke für die schnelle Antwort.
Leider bin ich jetzt etwas verwirrt. Ich dachte eigentlich, dass ich die Version 4.3 von Qt verwenden würde und da sehen die Konstruktoren so aus: Klick mich.
Deine beziehen sich ja auf Version 3.3, so wie ich das sehe.
Mein Buch handelt ebenfalls von Qt 4.
Entweder habe ich jetzt nicht richtig nachgesehen oder sie unterscheiden sich wirklich.
edit: Zum Designer:
Ja, mir geht es momentan auch darum es von Hand (Darunter eben auch die Verwendung von Layouts) zu lernen. Falls es mir mal eher um die Zeit und den Aufwand geht, werde ich sicher bei trivialeren Programmen auf den Designer zurückgreifen.
 
Zuletzt bearbeitet:
Ach du meine Güte, da haben die von Trolltech beim Wechsel von 3.x auf 4.x wirklich mal ein paar Sachen mehr verändert. Ich werde das wohl mal über kurz oder lang installieren müssen.

Aber ich wette, die Sache mit dem "top level-layout" wird sich nicht verändert haben. Versuche mal den Konstruktor Nr. 2:
QHBoxLayout::QHBoxLayout ( QWidget * parent );

Schreib' mal, ob's dann klappt.
 
So müsste es auch gehen:

Code:
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(startNumberLabel);
layout->addWidget(startNumber);
layout->addWidget(endNumberLabel);
layout->addWidget(endNumber);

ZentralWidget = new QWidget;
ZentralWidget->setLayout(layout);
setCentralWidget(ZentralWidget);

So mache es ich zumindest immer
 
Auch nicht schlecht :) Das klappt dann aber vermutlich nur bei QMainWindow.

(Komisch, bisher war Qt meistens "aufwärtskompatibel". Da kommt wohl noch eine Menge Arbeit auf mich zu, falls jemand mal ein paar Updates haben möchte :( )
 
Danke für die Hilfe.
Also, ich brauche es auch für das MainWindow.
Im Buch war es für ein QDialog oder sowas, weshalb es da wohl wahrscheinlich geht.
Der zweite Konstruktor geht auch nicht (Wahrscheinlich wegen des MainWindows).
Benötigt man dann immer ein zentrales Widget in MainWindows?
Und wie sieht es mit der Speicherverwaltung aus?
Wird das CentralWidget automatisch freigegeben, muss man sich darum kümmern?
 
Also ich habe jetzt in der Dokumentation (QT Assistent) nochmals nachgesehen. Dort ist eigentlich ziemlich genau beschrieben wie eine QMainWindow-Instanz aufgebaut ist:

QMainWindow provides a main application window, with a menu bar, tool bars, dock widgets and a status bar around a large central widget, such as a text edit, drawing canvas or QWorkspace (for MDI applications).
Note that QMainWindow comes with its own customized layout and that setting a layout on a QMainWindow, or creating a layout with a QMainWindow as a parent is considered an error. You should set your own layout on the central widget instead.

Auf deutsch: du mußt den Umweg über das CentralWidget gehen, da QMainWindow sein eigenes Layout mitbringt.

Wenn du QDialog verwendest, wie es scheinbar in deinem Buch gemacht worden ist, müsste deine ursprüngliche Version mit der Benutzung von setLayout auch funktionieren.

Um die Speicherverwaltung kümmert sich normalerweise QT. So werden untergeordnete Objekte automatisch gelöscht, wenn das übergeordnete Element gelöscht wird. Und alle Widgets und Layouts, die sich in einem Fenster befinden, sind ja nachkommen dieses Fensters. Das gilt allerdings nur für die QT-Klassen. Um selbst erstellte Klassen musst du dich schon selbst kümmern.
 
Hier noch mal ein interessanter Link zu MainWindow inklusive eine Gegenüberstellung von Qt3 und Qt4.

Um selbst erstellte Klassen musst du dich schon selbst kümmern.

Zum Beispiel, indem Du sie zuerst von QObject ableitest und Deinem Objekt den Zeiger des Elternobjekts übergibst. Wird dann das Elternobjekt gelöscht, kann anhand des Objektbaums erkannt werden, daß das "Kindsobjekt" auch zu löschen ist.

Früher galt die Einschränkung, daß man auf Objekte, die von QObject abgeleitet wurden, nicht mehrfachvererben kann. Wird wahrscheinlich auch noch für Qt 4 gelten.

Falls Du es so machen willst, schau Dir auch mal diese Bemerkung zum Q_OBJECT-Makro an; dieses müßtest Du dann nämlich auch einbinden.
 
Zuletzt bearbeitet:
Hi,
ich hab mal noch eine frage dazu,

ich habe eine main
int main(int argc, char *argv[]){
QApplication app(argc, argv);
Layout *xyz = new Layout;

eine layout klasse
Layout::Layout(QWidget *parent){
Buttons *buttons = new Buttons;
}

und die Klasse mit dem beenden button
Buttons::Buttons(){
QHBoxLayout* buttonLayout = new QHBoxLayout(this);
QPushButton* exitButton = new QPushButton(tr("Beenden"));
buttonLayout->addStretch();
buttonLayout->addWidget(exitButton);

QObject::connect( &exitButton,SIGNAL( clicked() ),
&app, SLOT( quit () ) );
}

Wie bekomme ich es hin, das exitButton app zum beenden kennt?

vielen dank im vorraus
rdg
 
Ich bin mir nicht ganz sicher, ob ich dein Problem richtig verstanden habe, aber für mich sieht dein Aufbau etwas merkwürdig aus.

Für was brauchst du z.B. die eigene Layoutklasse. Normalerweise wird das ja so gelöst, dass du ein Layout erzeugst (also QHBoxLayout, QVBoxLayout oder QGridLayout, je nachdem was du haben willst) und diesem Layout dann Widgets, also hier deine Buttons zuweist. Das ganze kannst du dann auch noch Verschachteln, so dass du ein Layout im Layout hast und somit alle möglichen Fensterlayouts erzeugen kannst.

Das fertige Layout kannst du dann einem Widget zuweisen. Das kann wie weiter oben im Thread ein Zentrales Widget eines QMainWindow sein, oder auch direkt ein QDialog.

Jetzt zum eigentlichen Problem:

Wenn du es so machst wie ich gerade beschrieben habe hast du zwei Möglichkeiten dein Programm über einen Button zu beenden.

1. Du machst es direkt in der main-Funktion, legst also deine ganzen Widgets und Layouts an und connectest direkt auf die Instanz der Applikation. Also ugefähr so:

Code:
int main(...)
{
   [...]
   QWidget *window = new QWidget;
   QPushButton *button = new QPushButton("quit");

   QVBoxLayout *layout = new QVBoxLayout;

   layout->addWidget(button);

   window->setLayout(layout);

   QObject::connect(button, SIGNAL(clicked()), &app, SLOT(quit()));
   window->show();
   return app.exec();
}

2. Du hast ein etwas komplexeres Fenster, z.B einen QDialog. Dann erstellst du im Konstruktor die ganzen Widgets und gibst als Parent immer den this-Pointer an. Damit hast du erreicht, dass alle Objekte, also Buttons, Layouts etc. Kindobjekte des Fensters sind. Beim connecten kannst du dann einfach das Fenster schließen, wenn dein Button gedrückt wird. Wenn es das letzte Fenster war, wird die Anwendung automatisch geschlossen.
 
Ja aber weil der Qcode mir zu lang wird habe ich es in Klassen unterteilt um sie auch handhaberer zu machen.

dank Dir vielmals mit dem this hast Du mich auf den richtigen Weg gebracht.

vielen dank!!!
 
Zuletzt bearbeitet:
Hiho,
ich lese zurzeit ein Qt-Buch und wollte mal eine kleine Anwendung schreiben.

Für den Anfang probier mal den Designer. Ich bin zwar kein Fan von IDE's aber wenn man schnell mal ne Form braucht ist es nicht schlecht.
Designer zu Qt3:
Ist bis auf paar bugs recht gut aber mir z.T. zu automatisch.
Designer zu Qt4
Benutze ihn nur für ne Form (.ui) und Quelltext per Kwrite

BTW wenn du willst kann ich dir n Prog von mir mailen, das erstellt ein Programm aus einer Config und einer .ui (Kann man sogar interaktiv per shellskripte machen) evtl kannst du dir da paar Sachen abgucken. Schreib einfach ne mail oder pm (bzw wenn sich jmd andester dafür interessiert einfach melden)
 

Ähnliche Themen

GB-errinerung in QT hat Speicherzugrifsfehler

CentOS 6.3 RADIUS - Keine Verbindung möglich

Squid nur zum maskieren der eigenen IP, nicht für Webserver auf port 80

Pure-ftpd mit Postgre

HD Parameter setzen Suse 10.3, lahmer gehts kaum!

Zurück
Oben