Getting started with Qt-UI layout and controls

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

Insert picture description here
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
Insert picture description here
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.hDefine the control variables used in it;

Note that the control is defined as 控件类型 *控件变量名.

In the mainwindow.cppfile, 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 Designerafter, and manually add controls, not just your heart whether it will generate such confusion: we know that Qt is C++based, and we Qt Designergenerated *.ui, in edit mode, you can find that it is similar to htmlthe tabbed Code . Then our *.uihow it works?

Indeed, using Qt Designerthe design *.uifiles can be uic工具converted to a *.hfile (generated automatically at compile time such a ui_*.hfile)

I found my mainwindow.cppexistence following:

#include "ui_mainwindow.h"

Note: ui_xxx.hbased on Qt Designerautomatically 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_xxxxto encapsulate the visual design interface.

  • The definition of the member variables of each component of the interface is automatically generated. In the publicportion of each component is defined as a pointer variable interface, the class name is our Qt Designerset interface ObjectName.

    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, it mainwindow.cppis called will. Front also said, want to C++get get code U控件must be here after.

  • setupUi()It is also called retranslateUi(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
    Insert picture description here
    short: search for the subclass used, and link the corresponding signal and slot.

Read about the source, I can not find Qt Creatora 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 MainWindowclass inherits from Ui_MainWindow.
And we mainwindow.halso have a MainWindowclass, just mainwindow.hin order to declare.

So that we can MainWindowuse class ui 指针interface components to access the visual design.

Guess you like

Origin blog.csdn.net/weixin_40774605/article/details/105149204