Article Directory
Preface
In view of the previous experience of learning Android, I divided Qt learning into the following steps:
- UI
- Signals and slots
- globalization
- Multithreading
- Drawing
- File operations
- database
- network programming
- …
If you are familiar with the UI, signals and slots, you should be able to write something that looks like a dog.
Qt commonly used controls and classification
It is recommended to get familiar with Qt Designer directly , there are not many controls, and no coding is required.
Those who are interested are familiar with the following control properties, etc. If not interested, learn to pull out a calculator...
If you still want to listen to other people tell us, then direct look at this crazy Aberdeen Embedded - qt creator of entry (a)
How to get the control object created in Qt Designer
How should we obtain the controls created in Qt Designer ?
For example mainwindow.ui
, a label is generated
in mainwindow.cpp
, and you can find it by checking its properties. Then in , we can ui->ObjectName(类似控件ID)
get the control in the constructor .
It should be noted that the operation to obtain the control must be written ui->setupUi(this)
after.
//mainwindow.h
#include <QLabel>
//.....
class MainWindow : public QMainWindow
{
///.....
private:
Ui::MainWindow *ui;
QLabel *m_label;
};
//mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_label = ui->label;
}
Add controls purely manually
mainwindow.h
Define the control variables used in it;
Note that the control is defined as 控件类型 *控件变量名
.
In the mainwindow.cpp
file, ui->setupUi(this)
create the control afterwards;
Note that the method of creating control variables is 控件变量名 = new 控件类型
.
If necessary, you can set control properties here.
Finally, remember to add the controls to the layout, currently only found only layout with a addWidget()
method.
//mainwindow.h
#include <QLabel>
//.....
class MainWindow : public QMainWindow
{
///.....
private:
Ui::MainWindow *ui;
QLabel *m_label;
};
//mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//新建一个Label
m_label = ui->label;
//设置属性
m_label->setText("Hello");
//添加到布局,verticalLayout为Qt Designer中添加的一个布局
ui->verticalLayout->addWidget(m_label);
}
How does Qt Designer work
When you are familiar with Qt Designer
after, and manually add controls, not just your heart whether it will generate such confusion: we know that Qt is C++
based, and we Qt Designer
generated *.ui
, in edit mode, you can find that it is similar to html
the tabbed Code . Then our *.ui
how it works?
Indeed, using Qt Designer
the design *.ui
files can be uic工具
converted to a *.h
file (generated automatically at compile time such a ui_*.h
file)
I found my mainwindow.cpp
existence following:
#include "ui_mainwindow.h"
Note: ui_xxx.h
based on Qt Designer
automatically generated, because the compiler will regenerate again, modify it manually is not meaningful. Therefore, it generally does not appear in our project catalog.
ui_xxx.h
Generally include the following:
-
A class is defined
ui_xxxx
to encapsulate the visual design interface. -
The definition of the member variables of each component of the interface is automatically generated. In the
public
portion of each component is defined as a pointer variable interface, the class name is ourQt Designer
set interfaceObjectName
.Note: It is generally not recommended to change the class name of the form; the instance name needs to be defined in the form code.
-
Defined
setupUi()
function ( circled focus ), I believe must be very familiar to the function, itmainwindow.cpp
is called will. Front also said, want toC++
get get codeU控件
must be here after. -
setupUi()
It is also calledretranslateUi(Widget)
to set the text content properties of each component of the interface, such as label text, button text, and window title. -
setupUi()
Also called a line of code that looks special (it is simply a firework with a different color)QMetaObject::connectSlotsByName(MainWindow);
The official description of this function is as follows: in
short: search for the subclass used, and link the corresponding signal and slot.
Read about the source, I can not find Qt Creator
a method to jump directly, the last only alternative Woboq online C / C ++ browser without having to download, ready to use, run out and ran.
QMetaObject::connectSlotsByName
The source code has the following content:
void QMetaObject::connectSlotsByName(QObject *o)
{
if (!o)
return;
const QMetaObject *mo = o->metaObject();
Q_ASSERT(mo);
const QObjectList list = // list of all objects to look for matching signals including...
o->findChildren<QObject *>(QString()) // all children of 'o'...
<< o; // and the object 'o' itself
// for each method/slot of o ...
for (int i = 0; i < mo->methodCount(); ++i) {
const QByteArray slotSignature = mo->method(i).methodSignature();
const char *slot = slotSignature.constData();
Q_ASSERT(slot);
// ...that starts with "on_", ...
if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
continue;
// ...we check each object in our list, ...
bool foundIt = false;
for(int j = 0; j < list.count(); ++j) {
const QObject *co = list.at(j);
const QByteArray coName = co->objectName().toLatin1();
// ...discarding those whose objectName is not fitting the pattern "on_<objectName>_...", ...
if (coName.isEmpty() || qstrncmp(slot + 3, coName.constData(), coName.size()) || slot[coName.size()+3] != '_')
continue;
const char *signal = slot + coName.size() + 4; // the 'signal' part of the slot name
// ...for the presence of a matching signal "on_<objectName>_<signal>".
const QMetaObject *smeta;
int sigIndex = co->d_func()->signalIndex(signal, &smeta);
if (sigIndex < 0) {
// if no exactly fitting signal (name + complete parameter type list) could be found
// look for just any signal with the correct name and at least the slot's parameter list.
// Note: if more than one of thoses signals exist, the one that gets connected is
// chosen 'at random' (order of declaration in source file)
QList<QByteArray> compatibleSignals;
const QMetaObject *smo = co->metaObject();
int sigLen = qstrlen(signal) - 1; // ignore the trailing ')'
for (int k = QMetaObjectPrivate::absoluteSignalCount(smo)-1; k >= 0; --k) {
const QMetaMethod method = QMetaObjectPrivate::signal(smo, k);
if (!qstrncmp(method.methodSignature().constData(), signal, sigLen)) {
smeta = method.enclosingMetaObject();
sigIndex = k;
compatibleSignals.prepend(method.methodSignature());
}
}
if (compatibleSignals.size() > 1)
qWarning() << "QMetaObject::connectSlotsByName: Connecting slot" << slot
<< "with the first of the following compatible signals:" << compatibleSignals;
}
if (sigIndex < 0)
continue;
// we connect it...
if (Connection(QMetaObjectPrivate::connect(co, sigIndex, smeta, o, i))) {
foundIt = true;
// ...and stop looking for further objects with the same name.
// Note: the Designer will make sure each object name is unique in the above
// 'list' but other code may create two child objects with the same name. In
// this case one is chosen 'at random'.
break;
}
}
if (foundIt) {
// we found our slot, now skip all overloads
while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
++i;
} else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
// check if the slot has the following signature: "on_..._...(..."
int iParen = slotSignature.indexOf('(');
int iLastUnderscore = slotSignature.lastIndexOf('_', iParen-1);
if (iLastUnderscore > 3)
qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
}
}
}
The core logic is to traverse the sub-objects, search for the signals caused by the sub-objects, match them with on_control name (ID)_signal name, and use connect() to connect if it matches.
To summarize: setUi( )
The creation of components on the form, property settings, and the association of signals and slots are realized.
- Finally, there is a namespace
Ui
.
namespace Ui {
class MainWindow: public Ui_MainWindow {
};
} // namespace Ui
It can be found inside a MainWindow
class inherits from Ui_MainWindow
.
And we mainwindow.h
also have a MainWindow
class, just mainwindow.h
in order to declare.
So that we can MainWindow
use class ui 指针
interface components to access the visual design.