Why do we pass "this" pointer to setupUi function? - c++

I'm fairly new in QT. Taking below fairly simply explain from qt docs :
class CalculatorForm : public QWidget
{
Q_OBJECT
public:
CalculatorForm(QWidget *parent = 0);
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
private:
Ui::CalculatorForm ui;
};
and implementation of constructor
CalculatorForm::CalculatorForm(QWidget *parent)
: QWidget(parent) {
ui.setupUi(this); // <-- Question below
}
Q: I was wondering why do we pass this pointer to setupUi function?, what does it do ?

So that the dialog will have the caller as parent, so that eg when the parent is closed the dialog can be closed automatically. Generally all gui elements have a pointer to their parent.
private slots:
void on_inputSpinBox1_valueChanged(int value); //why is that slots are private?
These are auto generated slots which exactly match the naming of the gui elments in QtDesigner. They are only meant to do the direct hookup to those gui elements and so should be dealt with in this class. If these signals were extended to other classes then any change in the gui would require changing a lot of other code which doesn't need to know details of the gui.
In the handler slot for the specific gui element you can then emit another more general signal to the rest of the app.

The only widget that setupUi doesn't create is the widget at the top of the hierarchy in the ui file, and as the Ui::CalculatorForm class instance doesn't know the widget it has to fill, it (this) has to be passed explicitly to the class at some point.
this or any other widget you would pass to it, is used as the parent to all other subwidgets. For example, you could fill a widget without inheritance like this:
QWidget *widget = new QWidget;
Ui::CalculatorForm *ui = new Ui::CalculatorForm;
ui->setupUi(widget);
widget->show();
But really, it would be easier to understand if you read the content of the uic generated file (probably named ui_calculatorform.h).

setupUi creates the instances of widgets (QLabel, QTextEdit and so on). The [user interface compiler] (http://qt-project.org/doc/qt-4.8/uic.html) gets information for you from the .UI form and generates widget-creation code in the generated moc source files.
The manual way of creating widgets without using the Qt Designer or a UI file would be like so:
QWidget* pWidget = new QWidget(this);

I think it is to add the caller widget to the layout of this UI.
This widget will be the toplevel widget.
Martin Beckett answer might be correct as well, as what he described is a common behavior in Qt (cf the 'parent' argument in most of widget's derived class constructor)

Note that you have alternative ways how designer can auto-generate code.
In this case you have a separate 'UI' class for this code which is not QObject so it also is not a QWidget.
Auto generated code needs information about parent widget and to make auto-conections of slots and signals so this is why you have to pass this.
This pater is less intrusive then other pasterns (that is why it is default). You can also try alternative patters (check Qt Creator Designer options), but I recommend you to see what is generated by designer tools in default settings.

Related

Accessing widgets inside QStackedWidget

I am developing a Qt app with QtDesigner.
Previously it was quite easy to access specific widgets to do something with them like connecting signals. After I added QStackedWidget I can no longer access specific widgets with something like ui->stack->page1->widget.
Is there a way to do it somehow? Or should I always call findChild method? Or maybe it is possible to at least assign some of the nested widgets in stack widget to properties of the main windwo class?
QStackedWidget provides a method to get child widgets by index, as well as the current widget.
A quick example is as follows:
MOCed Header
class MyWidget: QWidget
{
Q_OBJECT
public:
using QWidget::QWidget
QWidget *ptr;
};
Source File
QStackedWidget *stackedWidget = new QStackedWidget;
stackedWidget->addWidget(new MyWidget); // index 0
stackedWidget->addWidget(new QWidget); // index 1
stackedWidget->addWidget(new MyWidget); // index 2
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(stackedWidget);
setLayout(layout);
// do something specific with the first widget's ptr element
auto* widget = stackedWidget->widget(0);
auto* mywidget = qobject_cast<MyWidget*>(widget);
if (mywidget) {
mywidget->ptr->setObjectName("FirstPage");
}
Now, Qt uses virtual interfaces by default, so if you have a custom subwidget you need to extract, you can use qobject_cast. qobject_cast is basically a fast dynamic_cast, and works even without RTTI. In template-driven code, dynamic_cast is a bit of a code-smell: it means you lost useful type information too early. With virtual interfaces, the exact opposite is true: you should use qobject_cast as needed.
Why you get the widget layer by layer, if your widgets are added in Qt designer, you can get it by ui->widget directly.

C++ Qt Derived Classes

I'm trying to learn Qt and C++ and having some trouble understanding the C++ this keywork. I've seen examples where a class is derived from QMainWindow and then within the class member functions, a QMenu is added. One example is the "Simple menu" program described on this page:
http://www.zetcode.com/gui/qt4/menusandtoolbars/
In that example, a quit action is created with
QAction *quit = new QAction("&Quit", this);
However, imagine I want to also derive a class from QMenu and use that to create my menu.
mymenu.h
class MainWindow; // forward declaration
class MyMenu : QMenuBar
{
public:
MyMenu(MainWindow *main_window);
};
mymenu.cpp
#include "mymenu.hpp"
MyMenu::MyMenu(MainWindow *main_window) : QMenuBar()
{
QAction *quit = new QAction("&Quit", main_window); // Notice here I replaced
// 'this' with 'main_window'
QMenu = *file;
file = menuBar()->addMenu("&File");
file->addAction(quit);
connect(quit, SIGNAL(triggered()), qApp, SLOT(quit()));
}
Unfortunately this doesn't work because QAction expects a QObject as a parent. All that being said, there are a couple things that don't make sense to me:
If the class MainWindow inherits from QMainWindow, doesn't that make 'MainWindow' a QObject?
What is the difference between passing 'this' to QAction from within the class MainWindow, as opposed to passing 'main_window' which is (as far as I can tell) also a pointer to the instance from within the MyMenu class?
I apologize for such a long winded question, but if any of you have made it to the end with me, I would love any suggestions as to what I am missing here. The end goal here is just to create a derived class of QMenu (MyMenu here) and add it to the QMainWindow derived class (MainWindow here) existing in a separate class. Thank you for your time.
If the class MainWindow inherits from QMainWindow, doesn't that make 'MainWindow' a QObject?
Yes, MainWindow is a QMainWindow which is a QObject (you can see this by browsing the inheritance tree on the API docs).
You have only forward declared MainWindow. Since the compiler does not have a definition for the class MainWindow it can only do miminal things with a pointer to MainWindow. In order for the compiler to "know" that MainWindow is a QMainWindow which is a QObject, you must provide a class definition for MainWindow. You can solve your compiler error with:
#include "MainWindow.h"
No dynamic cast is needed
Also, in Qt land to make something "really" a QObject you should put the Q_OBJECT macro on the object:
class MyMenu : QMenuBar
{
Q_OBJECT
public:
MyMenu(MainWindow *main_window);
};
It might save you a few headaches later on if you ever plan to use the object for signal/slots or other Qt stuff.
What is the difference between passing 'this' to QAction from within the class MainWindow, as opposed to passing 'main_window' which
is (as far as I can tell) also a pointer to the instance from within
the MyMenu class?
this is a pointer to your custom MyMenu class which is also a QMenuBar. main_window is a pointer to your custom MainMenu class which is also a a QMainMenu. So, two different objects in memory. The second argument of the QAction constructor takes a pointer to a parent widget. The parent widget is responsible for managing the memory of its children. Since it takes a QObject its reasonable to pass in either this or main_menu.
Also you should probably pass a parent to the QMenu constructor.
MyMenu::MyMenu(MainWindow *main_window) : QMenuBar(main_window)
This way MyMenu is correctly deleted when the MainWindow is deleted.
The usual Qt paradigm is:
MyMenu::MyMenu(<arg1>, <arg2>, ... QObject * parent) : QMenuBar(parent)
But in this case forwarding along main_window is good enough.

Using a factory to create QT promoted widgets

Promoting widgets is one of the best features in the QT Designer. But when using the designer, it 'new's the object there it self ( inside setupUi ). This limits the ability to extend the interface file.
Is it possible to use a factory of some sort to get the promoted widgets, so that when a sub class of a promoted widget is required, this could be achieved via changing the factory and returning the sub class of the widget.
requirement:
NamePanel* myPanel;
void setupUi(QWidget* pWidget)
{
myPanel = Factory::CreateNamePanel();
}
Is there a work around to achieve this?
Unfortunately it seems not to be possible to add a factory into the Ui files. A workaround would be to have a QWidget with an attached layout in the ui and add the factory generated widget to this layout.
The code would look like this:
ui->setupUi(this);
QWidget *panel = Factory::CreateNamePanel();
ui->namePanelContainer->layout()->addWidget(panel);

Qt doesn't display child widget

How can i access ui files of children of a class. Lets say MainWindow class has twoa child dialog. I want to access LINEEDIT of dialog so that i can take text from there. Similarly how can i access ui files of parent inside child class in QT. Note: I havn't inherited any thing from Parent class.
I have writen the following code, in order to display a dialog but it won't show!
void MainWindow::displaydialog()
{
ItemDialog dialog= new ItemDialog(this);
dialog->show(); // it is not displaying the dialog
}
and how can i access the ui widgets like check whether ListWidget item has been selected or not.
Here is the code of itemdialog,
#include "itemdialog.h"
#include "ui_itemdialog.h"
#include "mainwindow.h"
ItemDialog::ItemDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ItemDialog)
{
ui->setupUi(this);
setWindowTitle("Status Dialog");
setFixedSize(QWidget::sizeHint());
}
ItemDialog::~ItemDialog()
{
delete ui;
}
void ItemDialog::on_pushButton_clicked()
{
MainWindow obj;
obj.okbuttonclicked(ui->lineEdit->text());
}
Please review an example such as this: http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
It explains how to use the ui files that you generate from Qt Designer. You shouldn't really think of them as "ui files" in the sense of accessing them on the widgets in your class. The idea is that you include them, and then use their setupUi() function to apply them to your given class. At that point, everything you created in qt designer, and that is in that ui file, is now a member of your class. They can be accessed via the naming you used in qt designer.
As for why your dialog isn't showing...I don't know because you only included 3 lines of code as an example. Theoretically it should show if Mydialog was properly set up. You could just try changing it to a QDialog to make sure you didn't do anything wrong with your custom class.
It depends what you want that dialog for. Either it's a modal dialog - some kind of a information display or retrival that blocks the function of your program until user reacts, or it's somekind of toolbox or similar, in which case you probably should not use QDialog.
If a modal dialog with a line edits and/or additional features is what you want, you should read up on QDialog in the doc. See the exec() function. Basic usage would go like this:
void MainWindow::displaydialog()
{
ItemDialog *dialog = new ItemDialog();
if (dialog->exec() == someApropriateReturnStatus)
{
QString somevalue = dialog->someValue();
int dialog->someOtherValue();
//do something with the value
}
delete dialog;
}
The point is that the ItemDialog class handles the UI internally and implements the getter functions accordingly, you should not (in most typical cases) access it's UI from outside.
If a simple line edit is all you want, you'd be better off using one of the standard dialogs already implemented in Qt, have a look at the Standard Dialogs Example

qt GUI connecting

I am just starting out with QT. I have read through some tutorials, and I think I have an understanding of signals and slots. I am writing a GUI that has various buttons that change the state of my main program. So for example in a drawing app, you would pick different drawing tools (using various buttons).
What is the best way to go about this? My first thought was to try to connect the clicked signal of the PushButton to some function that sets a current_tool variable. I did some searching and couldn't find a way to connect a QObject signal to a regular function.
This leads me to believe that there is probably a different approach. One where I create a new QObject (my own extension that is) that has various GUI properties. I would then define my slots here for the various buttons.
What is the best way to do this in QT. I am new and do not know of the preferred practice.
Any info would be useful,
thanks
You can define these "normal functions" as slots. Slots are just normal functions that can also be called by signals:
class ToolSelector : public QObject {
Q_OBJECT
public:
Tool *selected;
public slots:
void selectBrush();
void selectPen();
void selectFill();
};
ToolSelector::selectBrush() {
delete selected;
selected = new Brush();
}
ToolSelector::selectPen() {
// ...
}
// ...
toolsel = new ToolSelector();
brushButton = new QPushButton();
connect(brushButton, SIGNAL(clicked()), toolsel, SLOT(selectBrush()));
Inherit from the class that uic generates, creating, say, a MyAppWindow class. Provide extra METHODs in that class, as well as a Document or Drawing object. Connect these methods to the signals you're interested in, and them alter a member variable that contains the drawing state.