PDA

View Full Version : Add custom Widget into window (not using Designer)



invisible_uli
11th January 2010, 19:07
I'm a total newbie, so don't be mean if this is total bogus. I want to write a pretty complex GUI, but I really don't want to write all my code into one single class. Does everything that's going to be in one window has to be in one class ? From what I already read I can create custom Widgets and add them into my code. But when I try, it doesn't work: The custom widget is always a seperate window. So I hope anybody can help me. I'm assuming I'm making a trivial mistake. I just can't find a tutorial for this since everybody just creates one custom widget and opens it from main as a new window. But I want to include my custom widget *into* the window.
I made a real simple version of my problem. Just two groupBoxes each having a button which are supposed to be on top of each other within ONE window. The top button represents everything I want to add from myWidget, the bottom one stands for all the other stuff (propably other custom widgets). The problem is they are always in different windows. How can I get them into one? :confused: Please tell me why my thinking is wrong!
So here goes nothing:

#myWidget.cpp


#include "mywidget.h"

#include <QGroupBox>
#include <QHBoxLayout>
#include <QPushButton>

myWidget::myWidget(QWidget *parent) : QWidget(parent)
{
QGroupBox *grInMyW = new QGroupBox("Group In myWidget");
QHBoxLayout *layInMyW = new QHBoxLayout();
QPushButton *butInMyW = new QPushButton("Button in myWidget");

layInMyW->addWidget(butInMyW);
grInMyW->setLayout(layInMyW);
grInMyW->setVisible(true);
}


#main.cpp


#include "mywidget.h"

#include <QApplication>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QPushButton>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGroupBox *gr = new QGroupBox();
QVBoxLayout *layout = new QVBoxLayout();

myWidget *myW = new myWidget;
QPushButton* butInMain = new QPushButton("Button in Main");

layout->addWidget(myW);
layout->addWidget(butInMain);
gr->setLayout(layout);
gr->show();
return a.exec();
}


I don't know if I even need the GroupBoxes, but I read that for a custom widget i have to include some Layout, for its size to be clear. If there is an easier way, I'd really appreciate you telling me !
But I'd be thankful for any answer I can get !!

wysota
11th January 2010, 23:08
I'm a total newbie, so don't be mean if this is total bogus.
That's alright, we've all been beginners once.


Does everything that's going to be in one window has to be in one class ?
No, of course not.


But when I try, it doesn't work: The custom widget is always a seperate window.
A widget becomes a top-level window if it has no parent. You can set a parent in one of two ways - either by setting it explicitly (by passing a pointer to the parent to the constructor or using QWidget::setParent()) or by placing the widget inside a layout of another widget (this other widget becomes its parent widget then).


I'm assuming I'm making a trivial mistake.
Indeed. You just forgot to set a layout for the top-level widget and add all children to it.


How can I get them into one?

I'll give you a simpler example.


#include <QtGui>
int main(int argc, char **argv) {
QApplication app(argc, argv);
QWidget w; // top-level, no parent
QPushButton *topButton = new QPushButton; // no parent thus top-level so far
QPushButton *bottomButton = new QPushButton; // same as above
QVBoxLayout *l = new QVBoxLayout(&w); // adding a layout to "w"
l->addWidget(topButton); // sets a parent implicitly, becomes a child widget
l->addWidget(bottomButton); // same as above
w.show();
return app.exec();
}

If you comment lines 7-9, buttons will be separate windows as well.

All that is left to say is that all widgets behave the same - built-in or custom ones so you can replace QWidget or QPushButton with any other widget class. You can consider my "w" widget a custom one as well.


I don't know if I even need the GroupBoxes
No, you don't.

but I read that for a custom widget i have to include some Layout, for its size to be clear.
Not really but that's close to being true :)

invisible_uli
12th January 2010, 07:22
Thanks so much, wysota ! ;) I totally forgot to connect the Widgets in MyWidget to the parent.
I cleaned it up now:

myWidget.cpp


#include "mywidget.h"
#include <QPushButton>

myWidget::myWidget(QWidget *parent) : QWidget(parent)
{
QPushButton *butInMyW = new QPushButton("Button in myWidget");
butInMyW->setParent(parent);
}


It still didn't work with simply layout->addWidget(myW) in main.cpp. I guess it doesn't set a parent implicetly when using a custom Widget !? Because when using another Button instead of myWidget it works fine. But now I used an extra QWidget to be parent of myWidget:

here's just a snippet of main.cpp


QWidget helpWid;

myWidget *myW = new myWidget(&helpWid);
//QPushButton *myW = new QPushButton("other Button");

layout->addWidget(&helpWid);


Or is there another way without using the extraWidget, did I make another mistake :confused:
Well, I'm glad it works at least this way now. Thanks again wysota !!!

wysota
12th January 2010, 08:31
You didn't set a layout for your "myWidget" widget, that's one thing. Another is that the parent of butInMyW should be an instance of "myWidget" (i.e. "this") and not its parent. Follow the same principle like I did in my main().