Getting started with C++QT

C++QT

Article directory

1. QT Overview

1.1 What is QT

Qt is a cross-platform C++ graphical user interface application framework . It provides application developers with
all the functionality needed to create state-of-the-art graphical interfaces. It is fully object-oriented, easily extensible, and allows true component programming.

Common GUI:

QT: supports multi-platform development; supports css; has outstanding object-oriented features; and has good development trends.

MFC: can only be developed on Windows; running programs is efficient; library security is good;

1.2 Development History of QT

  • Qt was first developed by QQ Technology in 1991
  • Entering the commercial field in 1996, it is also the basis for the currently popular Linux desktop environment KDE.
  • In 2008, Trolltech was acquired by Nokia, and Qt was called Nokia’s programming language.
  • In 2012, Qt was acquired by Digia.
  • The cross-platform integrated development environment Qt Creator3.1.0 was released in April 2014, and the official version of Qt5.3 was distributed on May 20 of the same year.
  • So far, Qt has fully supported various platforms such as iOS, Android, and WP.
  • The current latest version of Qt is 5.13.2 (before 2019.12)

1.3 Supported platforms

  • Windows – XP、Vista、Win7、Win8、Win2008、Win10
  • Uinux/X11 – Linux, Sun Solaris, HP-UX, Compaq Tru64 UNIX, IBM AIX, SGI IRIX, FreeBSD,
    BSD/OS, and many other X11 platforms
  • Macintosh – Mac OS X
  • Embedded - Embedded Linux platform with framebuffer support, Windows CE

1.4 QT version

Qt is released in different versions, divided into commercial version and open source version

  • Commercial version: Commercial software provides development, they provide traditional commercial software distribution, and provide free upgrades and technical support services within the commercial validity period.
  • Open source version (LGPL): The open source LGPL version is an open source software designed for developing your own. It provides the same functions as the commercial version. It is free under the GNU General Public License.

1.5 Download and installation of Qt

  • http://www.qt.io/download-open-source/
  • http://download.qt.io/archive/qt/

image-20230617192318611

image-20230617192628524

You can install it by default.
Qt provides different versions of installation packages for different platforms. You can download and install them according to the actual situation. This document uses the
qt-opensource-windows-x86-mingw530-5.13.0 version for explanation (32-bit and 64-bit can be installed)

1.6 Advantages of QT

  • Cross-platform, supports almost all platforms

  • The interface is simple and easy to use. Learning the QT framework is a reference for learning other frameworks.

  • Simplified the memory recycling mechanism to a certain extent

  • The development efficiency is high and applications can be built quickly.

  • There is a good community atmosphere and the market share is slowly rising.

  • Embedded development is possible.

1.7 Success Stories

  • Linux desktop environment KDE
  • Skype VoIP
  • Google Earth Google Maps
  • VLC multimedia player
  • VirtualBox virtual machine software
  • Migu music
  • WPS Office
  • Need for Speed

2. Create QT project

2.1 Create using wizard

  • Open the Qt Creator interface and select
  • New Project or select the menu item [File]-[New File or Project] in the menu bar
  • The New Project dialog box pops up, select Qt Widgets Application

image-20230617205216497

image-20230617205254631

image-20230617215755059

2.2 Manual creation

  • Add an empty project

image-20230617220114633

  • Select [choose] to proceed to the next step. Set the project name and path—>Select the compilation package—>Modify class information—>Finish (same steps as above) and generate an empty project. Add files to an empty project: Right-click on the project name to pop up the right-click menu and select [Add New File]

image-20230617220131998

  • New file dialog box pops up

image-20230617220150476

2.3 .pro file

The application .pro file format generated using the Qt wizard is as follows:

QT += core gui //包含的模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于Qt4 版本才包含widget 模块
TARGET = QtFirst //应用程序名生成的.exe 程序名称
TEMPLATE = app //模板类型应用程序模板
SOURCES += main.cpp //源文件
mywidget.cpp
HEADERS += mywidget.h //头文件

.pro is the project file, which is the configuration file automatically generated by qmake for producing makefiles. The .pro file is
written as follows:

  • Comments
    start with "#" and end with this line.
  • Template variables tell qmake what kind of makefile to generate for this application. The following options are available: TEMPLATE = app,app - Creates a makefile for an application. This is the default value, so if no template is specified, this will be used.
  • lib - Makefile that builds a library.
  • vcapp - Create a VisualStudio project file for an application.
  • vclib - Create a library of Visual Studio project files.
  • subdirs - This is a special template that creates a makefile that goes into a specific directory and generates a makefile for a project file and calls make for it.
#指定生成的应用程序名:
TARGET = QtDemo
#工程中包含的头文件
HEADERS += include/painter.h
#工程中包含的.ui 设计文件
FORMS += forms/painter.ui
#工程中包含的源文件
SOURCES += sources/main.cpp sources
#工程中包含的资源文件
RESOURCES += qrc/painter.qrc
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
这条语句的含义是,如果QT_MAJOR_VERSION 大于4(也就是当前使用的Qt5 及更高版本)需要
增加widgets 模块。如果项目仅需支持Qt5,也可以直接添加“QT += widgets”一句。不过为
了保持代码兼容,最好还是按照QtCreator 生成的语句编写。
#配置信息
CONFIG 用来告诉qmake 关于应用程序的配置信息。
CONFIG += c++11 //使用c++11 的特性
在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那
样替换已经指定的所有选项更安全。
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 重新更新
    this->setWindowTitle("hello world"); // 更改UI内容
    this->resize(600,400);
}

Widget::~Widget()
{
    delete ui;
}


2.4 Set parent object

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 重新更新
    this->setWindowTitle("hello world");
    // 设置 完成之后可以拉伸
    this->resize(600,400);
    // 设置固定大小
    this->setFixedSize(QSize(200,200));

    QPushButton *button =  new QPushButton;
    // 设置父亲对象
    button->setParent(this);
}

Widget::~Widget()
{
    delete ui;
}


image-20230618001225199

2.5 Button setting properties

2.5.1 Button setting text

button->setText("红红红!");

2.5.2 Setting up mobile

button->move(50,50);

2.5.3 Set fixed size

button->setFixedSize(QSize(400,400));

2.6 Another way to create buttons

2.6.1 Created during construction

      QPushButton *button2 = new QPushButton("第二个按钮",this); // 包括设置文本和父对象

2.6.2 The difference between post-initialization settings and constructor settings

  • Set after initialization, displayed as the default size of the window
  • Constructor settings will cause the window size to be the size of the button and need to be resized.

2.7 Object model (object tree)

When creating an object in Qt, a Parent object pointer will be provided. The following explains what this parent
does.

  • QObject is organized in the form of an object tree.

When you create a QObject object, you will see that the QObject constructor receives a QObject pointer as a parameter. This parameter is parent, which is the parent object pointer.
This is equivalent to when creating a QObject object, you can provide its parent object, and the QObject object we create will be automatically added to the children() list of its parent object.
n When the parent object is destroyed, all objects in this list will also be destroyed. (Note that the parent object here is not a parent class in the sense of inheritance!)

  • QWidget is the parent class of all components that can be displayed on the screen.

QWidget inherits from QObject and therefore inherits this object tree relationship. A child automatically becomes a child component of the parent component. Therefore, it will appear in the parent component's coordinate system, clipped by the parent component's bounds. For example, when the user closes a dialog box, the application deletes it, then we hope that the buttons, icons, etc. belonging to this dialog box should be deleted together. This is the case because these are subcomponents of the dialog.

  • Of course, we can also delete child objects ourselves, and they will be automatically removed from the list of their parent objects. For example, when we delete a toolbar, the main window where it is located will automatically delete the toolbar from its child object list, and automatically adjust the screen display.

image-20230619095633992

  • Qt introduces the concept of object tree, which solves the memory problem to a certain extent.
    • When a QObject object is created on the heap, Qt will also create an object tree for it. However, the order of objects in the object tree is not defined. This means that the order in which these objects are destroyed is also undefined.
    • When any QObject object in the object tree is deleted, if the object has a parent, it will be automatically deleted from the parent's children() list; if there are children, each child will be automatically deleted. Qt guarantees that no QObject will be deleted twice, which is determined by the order of destruction. Qt maintains the same behavior if the QObject is created on the stack. Under normal circumstances, this will not cause any problems.
    • The window as the parent component and the quit as the child component are both subclasses of QObject (in fact, they are both subclasses of QWidget, and QWidget is a subclass of QObject). This code is correct, the destructor of quit will not be called twice, because standard C++ requires that the order of destruction of local objects should follow the reverse process of their creation order. Therefore, when this code goes out of scope, it will first call the destructor of quit to delete it from the child object list of the parent object window, and then call the destructor of window.
    • In Qt, try to specify the parent object during construction, and boldly create it on the heap.

2.8 Qt window coordinate system

Coordinate system:
Taking the upper left corner as the origin (0,0), X increases to the right and Y increases downward.

image-20230619095748503

3 Signal and slot mechanism

3.1 Signals and Slots

Signals and slots are one of the proud mechanisms of the Qt framework. The so-called signal slot is actually the observer mode. When an event occurs, for example, a button detects that it has been clicked, it emits a signal. This kind of sending has no purpose and is similar to broadcasting. If an object is interested in this signal, it will use the connect function, which means that it will bind the signal it wants to process to one of its own functions (called a slot) to process the signal. That is to say, when the signal is emitted, the connected slot function will be automatically called back. This is similar to the observer pattern: when an event of interest occurs, an operation will be automatically triggered.

image-20230619100459070

3.2 The signals and slots provided by the system

The most commonly used general form of the connect() function: connect(sender, signal, receiver, slot);
Parameter explanation:

sender: the object that emits the signal
signal: the signal emitted by the sending object
receiver: the object that receives the signal
slot: the function (slot function) that the receiving object needs to call after receiving the signal

3.3 Commonly used signals

So how do you usually find the signals and slots that come with the system? You need to use the help document. In the help document, for example, for the click signal of the button above, enter QPushButton in the help document. First, we can look for keywords in Contents. signals, the meaning of signal, but we found that we did not find it. At this time, we should think that maybe this signal was inherited by the parent class, so we can find the keyword in its parent class QAbstractButton, click on signals to index to the system The built-in signals include the following:

image-20230619101434174

3.4 Custom slot function

#ifndef WIDGET_H
#define WIDGET_H
#include <QDebug>
#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
public slots: // 添加槽函数
    void print();

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 重新更新
    this->setWindowTitle("hello world");
    // 设置 完成之后可以拉伸
    this->resize(600,400);
    // 设置固定大小
    this->setFixedSize(QSize(600,400));

//    QPushButton *button =  new QPushButton;
    // 设置父亲对象
//    button->setParent(this);
//    button->setText("中国红!");
//    // 按钮移动
//    button->move(50,50);
//    // 设置按钮大小
//    button->setFixedSize(QSize(400,400));
      QPushButton *button2 = new QPushButton("第二个按钮(关闭)",this);
      # 定义信号函数
      connect(button2,&QPushButton::clicked,this,&Widget::print);


}

Widget::~Widget()
{
    delete ui;
}

void Widget::print(){
    qDebug()<<"hello world!"; // 槽函数实现
}

image-20230619110112323

3.5 Custom signals

image-20230619164419572

Things to note when customizing signal slots:

  • Both the sender and the receiver need to be subclasses of QObject (of course, except
    when the slot function is a global function, Lambda expression, etc. and does not require a receiver);
  • The return value of signal and slot functions is void
  • Signals only need to be declared, not implemented
  • Slot functions need to be declared and implemented
  • The slot function is an ordinary member function. As a member function, it will be affected by public, private, and protected;
  • Use emit to send signals at the right location;
  • Use the connect() function to connect signals and slots.
  • Any member function, static function, global function and Lambda expression can be used as a slot function
  • The signal and slot require that the parameters of the signal and the slot are consistent. The so-called consistency means that the parameter types are consistent.
  • If the parameters of the signal and the slot are inconsistent, it is allowed that the slot function can have fewer parameters than the signal. Even so, the
    order of the parameters of the slot function must be consistent with the first few of the signal. This is because you can
    choose to ignore the data from the signal in the slot function (that is, the slot function has fewer parameters than the signal).

image-20230619221022227

3.6 Signal slot expansion

  • A signal can be connected to multiple slots
    . If this is the case, the slots will be called one after another, but the order in which they are called is undefined.

  • Multiple signals can be connected to a slot,
    as long as any signal is emitted, the slot will be called

  • A signal can be connected to another signal.
    When the first signal is emitted, the second signal is emitted.
    Otherwise, there is no difference between this signal-signal form and the signal-slot form .

  • Slots can be unlinked.
    This does not happen very often, because when an object is deleted, Qt automatically unlinks all
    slots connected to this object.

  • The signal slot can be disconnected
    The signal slot can be disconnected by using the disconnect keyword

  • Using Lambda expressions
    When using Qt5, all compilers that can support Qt 5 support Lambda expressions.
    When connecting signals and slots, slot functions can be processed using Lambda expressions.

When overloading a signal, you need to use a function pointer to determine the slot function and signal function to be executed.

 void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
 void (Student:: *studentSignal)(QString) = &Student::treat;

3.6 How to write signals and slots in Qt4 version

connect(zt,SIGNAL(hungry(QString)),st,SLOT(treat(QString)));

The two macros SIGNAL and SLOT are used here to convert the two function names into strings. Note that both the signal and slot of the connect() function
accept strings. Once the connection fails, Qt4 will not compile errors (because everything
is a string, and the compile time does not check whether the string matches), and is giving an error at runtime. This will undoubtedly increase the instability of the program
.
Qt5 is fully syntactically compatible with Qt4, but the reverse is not possible.

3.7 Lambda expressions

Lambda expressions in C++11 are used to define and create anonymous function objects to simplify programming.

The basic components of Lambda expressions:

[capture](parameters) mutable ->return-type
{
statement
}
  • Function object parameters;
    [], identifies the beginning of a Lambda, this part must exist and cannot be omitted.
    Function object parameters are passed to the constructor of the function object class automatically generated by the compiler .
    Function object parameters can only use local variables that are visible in the scope of the Lambda until the Lambda is defined (including this of the class where the Lambda is located). Function object parameters have the following forms:
    • null. No function object parameters are used.
    • =. All visible local variables in the scope of the Lambda (including
      this of the class where the Lambda is located) can be used in the function body, and it is passed by value (equivalent to the compiler automatically passing all local variables by value for us).
    • &. All visible local variables in the scope of the Lambda (including
      this of the class where the Lambda is located) can be used in the function body, and it is passed by reference (equivalent to the compiler automatically passing all local variables by reference for us).
    • this. Member variables in the class where the Lambda is located can be used within the function body.
    • a. Pass a by value. When passing by value, the copy of a passed in cannot be modified in the function body, because
      the function is const by default. To modify the copy of a passed in, add the mutable modifier.
    • & a. Pass a by reference.
    • a, & b. Pass a by value and b by reference.
    • =, &a, &b. Except for a and b, which are passed by reference, all other parameters are passed by value.
    • &, a, b. Except for a and b which are passed by value, other parameters are passed by reference.
  • ② Operator overloaded function parameters;
    identifies the parameters of the overloaded () operator. If there are no parameters, this part can be omitted. Parameters can be passed by value (e.g.: (a,b))
    or by reference (e.g.: (&a,&b)).
  • Modifiable identifier;
    mutable statement, this part can be omitted. When passing function object parameters by value, after adding the mutable modifier,
    the copy passed in by value can be modified (note that the copy can be modified, not the value itself).
QPushButton * myBtn = new QPushButton (this);
QPushButton * myBtn2 = new QPushButton (this);
myBtn2->move(100,100);
int m = 10;
connect(myBtn,&QPushButton::clicked,this,[m] ()mutable { m = 100 + 10; qDebug() << m; });
connect(myBtn2,&QPushButton::clicked,this,[=] () { qDebug() << m; });
qDebug() << m;
  • Function return value;
    -> return value type, which identifies the type of function return value. When the return value is void, or there is only one return in the function
    body (at this time, the compiler can automatically infer the return value type), this part can be omitted.
  • Is the function body;
    {}, identifies the implementation of the function, this part cannot be omitted, but the function body can be empty.
3.7.1 Lambda passing parameters (no parameters)
    auto fun=[](){
       qDebug()<<"hello world!222";
    };
    fun();

image-20230620113414659

3.7.2 Lambda passing parameters (with parameters)
    auto fun2=[](int a,int b){
       qDebug()<<"hello world!333";
       return a+b;
    };
    ClassIsOver();
    qDebug()<<fun2(2,3);
3.7.3 Passing by value and address
    int a = 10;
    auto fun3= [](int &a,int b){
       qDebug()<<"hello world!333";
       qDebug()<<"a==="<<a;
       a = 20;
       return a+b;
    };

    ClassIsOver();
    qDebug()<<fun3(a,3);

image-20230620113312085

4. QMainWindow

4.1 Introduction

QMainWindow is a class that provides the main window program for users, including a menu bar (menu bar), multiple toolbars (toolbars), multiple riveting components (dock widgets), a status bar (status bar) and a central component ( central widget), which is the basis of many applications, such as text editors, image editors, etc.

image-20230621000022651

Corresponds to the menu bar, menu, and menu items respectively.

  • Create a menu bar and obtain the main window menu bar pointer through the menubar() function of the QMainWindow class
//创建菜单栏:
#include <QMenuBar>
QMenuBar --> QMenuBar(QWidget *parent = Q_NULLPTR)
//添加菜单栏:
QMainWindow --> void setMenuBar(QMenuBar *menuBar)
  • Create a menu and call the member function addMenu of QMenu to add the menu
//创建菜单:
#include <QMenu>
QMenu --> QMenu(const QString &title, QWidget *parent = Q_NULLPTR)
//添加菜单:
MenuBar --> QAction *addMenu(QMenu *menu)
  • Create a menu item and call the member function addAction of QMenu to add the menu item
//创建菜单项:
#include <QAction>
QAction --> QAction(const QString &text, QObject *parent = nullptr)
//添加菜单项:
QMenu --> addAction(const QAction *action)

Qt does not have a special menu item class, but uses a QAction class to abstract common actions. When we add the QAction object to the menu, it is displayed as a menu item, and when added to the toolbar, it is displayed as a tool button. The user can activate this action by clicking a menu item, clicking a toolbar button, or clicking a shortcut key.

#include "mainwindow.h"
#include <QMenuBar> //菜单栏
#include <QMenu> //菜单
#include <QAction> //菜单项
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
//**********窗口属性设置*****************
this->setWindowTitle("主窗口");
this->setFixedSize(800, 600);
//***********创建菜单栏******************
//创建菜单栏
//注意:如果只有菜单栏,则在窗口处没有现象
QMenuBar *menu_bar = new QMenuBar(this);
this->setMenuBar(menu_bar);
    千锋智能物联网学院
//创建菜单
QMenu *menu1 = new QMenu("文件", this);
menu_bar->addMenu(menu1);
QMenu *menu2 = new QMenu("编辑", this);
menu_bar->addMenu(menu2);
QMenu *menu3 = new QMenu("构建", this);
menu_bar->addMenu(menu3);
//创建菜单项
QAction *act1 = new QAction("新建文件或项目", this);
menu1->addAction(act1);
QAction *act2 = new QAction("打开文件或项目", this);
menu1->addAction(act2);
//添加分割线
menu1->addSeparator();
QAction *act3 = new QAction("保存", this);
menu1->addAction(act3);
QAction *act4 = new QAction("另存为", this);
menu1->addAction(act4);
QAction *act5 = new QAction("复制", this);
act5->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C));
menu2->addAction(act5);
QAction *act6 = new QAction("粘贴", this);
act6->setShortcut(QKeySequence(tr("Ctrl+V")));
menu2->addAction(act6);
QAction *act7 = new QAction("剪切", this);
menu2->addAction(act7);
//当单击菜单项时,做出相应的处理
connect(act5, &QAction::triggered, [=]{
qDebug()<<"复制正在执行";
});
connect(act6, &QAction::triggered, [=]{qDebug()<<"粘贴正在执行";
});
}
MainWindow::~MainWindow()
{
}

image-20230621001246177

4.2 Toolbar

There can be multiple toolbars on the toolbar of the main window. Usually, one menu corresponds to one toolbar, and the toolbars can also be divided as needed.

//创建工具栏:
#include <QToolBar>
QToolBar --> QToolBar(QWidget *parent = Q_NULLPTR)
//添加工具栏:
QMainWindow -->
void addToolBar(QToolBar *toolbar)
void addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
Qt::LeftToolBarArea 左边显示
Qt::RightToolBarArea 右边显示
Qt::TopToolBarArea 上边显示
Qt::BottomToolBarArea 下边显示


Directly call the addToolBar() function of the QMainWindow class to obtain the toolbar object of the main window. This function needs to be called once every time a toolbar is added .

  • Insert an action that belongs to the toolbar, that is, add an operation to the toolbar.
    Added through the addAction function of the QToolBar class.
  • The toolbar is a movable window, and its docking area is determined by QToolBar's allowAreas, including:
  • Qt::LeftToolBarArea docked to the left
  • Qt::RightToolBarArea docked to the right
  • Qt::TopToolBarArea docked at the top
  • Qt::BottomToolBarArea docked at the bottom
  • Qt::AllToolBarAreas The above four positions can be docked
  • Use the setAllowedAreas() function to specify the docking area:
    setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea)
  • Use the setMoveable() function to set the mobility of the toolbar:
    setMoveable(false) //The toolbar cannot be moved and can only be docked at the initialized position.
//创建工具栏
//注意:工具栏可以添加多个
QToolBar *toolbar = new QToolBar(this);
//将工具栏添加到窗口
//this->addToolBar(toolbar);//默认在最上面显示
this->addToolBar(Qt::LeftToolBarArea, toolbar); //设置默认在左边显示
//工具栏添加菜单项和分割线
QAction *act_tool1 = new QAction("欢迎", this);
QAction *act_tool2 = new QAction("编辑", this);
toolbar->addAction(act_tool1);
toolbar->addSeparator();
toolbar->addAction(act_tool2);
//设置工具栏的浮动状态,true:可以悬浮在窗口false:不可以
toolbar->setFloatable(false);
//设置运行工具栏的位置,设置为左边或者右边
toolbar->setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea);

4.3 Status bar

  • Derived from the QWidget class, its usage is similar to that of QWidget. The QStatusBar class has common member functions: there can only be one status bar at most.
创建状态栏:
QStatusBar -->
将控件添加到左边栏
void addWidget(QWidget *widget, int stretch = 0)
将控件添加到右边栏
void addPermanentWidget(QWidget *widget, int stretch = 0)
添加状态栏:
QMainWindow --> void setStatusBar(QStatusBar *statusbar)
//创建状态栏
//状态栏只能有一个
QStatusBar *statusbar = new QStatusBar(this);
//添加状态栏
this->setStatusBar(statusbar);
//给状态栏中添加文字信息或者按钮=
QLabel *label1 = new QLabel("左边信息", this);
statusbar->addWidget(label1);
QLabel *label2 = new QLabel("右边信息", this);
statusbar->addPermanentWidget(label2);
QPushButton *button = new QPushButton("设置", this);
statusbar->addWidget(button);

4.4 Riveted components

创建铆接部件:
QDockWidget -->
QDockWidget(const QString &title, QWidget *parent = Q_NULLPTR)
添加铆接部件:
QMainWindow -->
void addDockWidget(Qt::DockWidgetArea area, QDockWidget
*dockwidget)
Qt::LeftDockWidgetArea 左边
Qt::RightDockWidgetArea 右边
Qt::TopDockWidgetArea 上边
Qt::BottomDockWidgetArea 下边
//创建铆接部件
QDockWidget *dockwidget = new QDockWidget("这是一个铆接部件", this);
this->addDockWidget(Qt::TopDockWidgetArea, dockwidget);

4.5 Central part

In addition to the above components, the components displayed in the center can be used as core components. For example, a notepad file can use QTextEdit as the core component.

添加中心部件:
QMainWindow --> void setCentralWidget(QWidget *widget)
QTextEdit *edit = new QTextEdit("文本编辑器", this);
this->setCentralWidget(edit);

4.6 Resource files

The Qt resource system is a cross-platform resource mechanism that is used to store the resources needed when the program is running in binary form inside the executable file. If your program needs to load specific resources (icons, text translations, etc.), then place them in resource files and you no longer need to worry about losing these files. In other words, if you store resources as resource files, they will be compiled into the executable file. Resource files can be easily created using Qt Creator. We can right-click on the project and select "Add New File..." and find "Qt Resource File" under the Qt category:

image-20230621005359980

4.7 Add background image

this->setAutoFillBackground(true);
//创建图片控件
QPixmap pix $=$ QPixmap(":/image/butterfly.png"). scaled(this->size());
// pix.load("://image/butterfly.png");
QPalette palette;
palette.setBrush(QPalette:: Background,QBrush(pix));
this->setPalette(palette);
this->setAutoFillBackground(true);
//创建图片控件
QPixmap pix = QPixmap(":/image/butterfly.png"). scaled(this->size());
// pix.load (":/image/butterfly.png");
QPalette palette;
palette.setBrush(QPalette:: Background, QBrush(pix));
this->setPalette(palette);

5. Dialog box

5.1 Basic concepts

Dialog boxes are an integral part of GUI programs. Many functional components that cannot or are not suitable to be placed in the main window must be set in the dialog box. A dialog box is usually a top-level window that appears at the top of the program and is used to implement short-term tasks or simple user interaction.

Dialog boxes are implemented in Qt using the QDialog class. Just like the main window, we usually design a class to inherit QDialog. QDialog (and its subclasses, and all classes of Qt::Dialog type) have additional interpretations for their parent pointers: if parent
is NULL, the dialog box will be used as a top-level window, otherwise it will be used as the parent component's Child dialog box (at this time, its default position is the center of the parent). The difference between a top-level window and a non-top-level window is that a top-level window will have its own position on the taskbar, while a non-top-level window will share the position of its parent component. Dialog boxes are divided into modal dialog boxes and non-modal dialog boxes.

  • A modal dialog box is one that blocks input from other windows in the same application.
    Modal dialogs are common, such as the "open file" function. You can try to open the file in Notepad. When the open file
    dialog box appears, we cannot operate on the window parts other than this dialog box.

  • The opposite is a non-modal dialog box, such as a search dialog box, we can continue to edit the contents of the notepad while the search dialog box is displayed .

5.2 Standard dialog box

The so-called standard dialog box is a series of dialog boxes built into Qt to simplify development. In fact, there are many dialog boxes that are common, such as opening files, setting colors, printing settings, etc. These dialog boxes are pretty much the same in all programs, so there is no need to implement such a dialog box in every program yourself. Qt's built-in dialogs are roughly divided into the following categories:

  • QColorDialog: select a color;
  • QFileDialog: Select a file or directory;
  • QFontDialog: select font;
  • QInputDialog: Allows the user to enter a value and returns its value;
  • QMessageBox: Modal dialog box, used to display information, ask questions, etc.;
  • QPageSetupDialog: Provides paper-related options for the printer;
  • QPrintDialog: printer configuration;
  • QPrintPreviewDialog: print preview;
  • QProgressDialog: Display the operation process.

5.2.1 Modal dialog box

QDialog dialog;
dialog.setWindowTitle(tr("Hello, dialog!"));
dialog.exec();

5.2.2 Modeless dialog box

QDialog dialog(this);
dialog.setWindowTitle(tr("Hello, dialog!"));
dialog.show();

Did it backfire? The dialog box flashed by! This is because the show() function does not block the current thread, the dialog box is displayed, and then the function returns immediately and the code continues execution. Note that the dialog is built on the stack, the show() function returns, the MainWindow::open() function ends, and the dialog is destructed beyond the scope, so the dialog box disappears. Once we know the reason, we can easily change it. We change the dialog to be created on the heap . Of course, this problem disappears:

QDialog *dialog = new QDialog;
dialog->setWindowTitle(tr("Hello, dialog!"));
dialog->show();

There is a problem with the above code: there is a memory leak in the dialog! dialog uses new to allocate space on the heap, but it has never been deleted.

The solution is also very simple: assign the MainWindow pointer to the dialog. Remember the Qt object system we talked about earlier? However, there is a problem with this: What if our dialog box does not appear in an interface class? Since the parent of QWidget must be a QWidget pointer, this restricts us from passing an ordinary C++ class pointer to the Qt dialog box. In addition, if there are strict restrictions on memory usage, when we use the main window as the parent, the dialog box will not be destroyed if the main window is not closed, so it will always occupy memory. In this scenario, we can set the WindowAttribute of the dialog:

QDialog *dialog = new QDialog;
dialog->setAttribute(Qt::WA_DeleteOnClose); // 在这里
dialog->setWindowTitle(tr("Hello, dialog!"));
dialog->show();

The setAttribute() function automatically destroys the dialog box when the dialog box is closed.

5.3 Message dialog

QMessageBox is used to display message prompts. We generally use several static functions provided by it:

  • Show about dialog
void about(QWidget * parent, const QString & title, const QString & text)

This is the simplest dialog box, its title is title, the content is text, and the parent window is parent. The dialog box has only one OK button.

  • Displays the About Qt dialog box. This dialog box is used to display information about Qt.
void aboutQt(QWidget * parent, const QString & title = QString()):
  • Similar to QMessageBox::critical(), except that this dialog box provides a normal message icon.
StandardButton information(QWidget * parent,
const QString & title,
const QString & text,
StandardButtons buttons = Ok,
StandardButton defaultButton
  • Similar to QMessageBox::critical(), except that this dialog box provides a question mark icon and the buttons it displays are "Yes" and "No".
StandardButton question(QWidget * parent,const QString & title,
const QString & text,
StandardButtons buttons = StandardButtons( Yes | No ),
StandardButton defaultButton = NoButton)
  • Similar to QMessageBox::critical(), except that this dialog box provides a yellow exclamation point icon.
StandardButton warning(QWidget * parent,
const QString & title,
const QString & text,
StandardButtons buttons = Ok,
StandardButton defaultButton = NoButton)

QMessageBoxDemo

if (QMessageBox::Yes == QMessageBox::question(this,
tr("Question"), tr("Are you OK?"),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::Yes))
{
QMessageBox::information(this, tr("Hmmm..."),
tr("I'm glad to hear that!"));
}
else
{
QMessageBox::information(this, tr("Hmmm..."),
tr("I'm sorry!"));
}

The parent window of this dialog box is this. QMessageBox is a subclass of QDialog, which means that its initial display position will be in the center of the parent window.  The second parameter is the title of the dialog box. The third parameter is what we want to display.  The fourth parameter is the associated button type. We can use the OR operator (|) to specify the button that the dialog box should appear. For example, we want a Yes and a No. The last parameter specifies the button selected by default. This function has a return value that is used to determine which button the user clicked. According to the way we write it, it should be easy to see that this is a modal dialog box, so we can get its return value directly. The advantage of the static function of the QMessageBox class is that it is easy to use, but the disadvantage is also obvious: it is very inflexible.

We can only use a few simple forms. In order to be able to customize the details of QMessageBox, we must use the QMessageBox's property setting API. If we want to make a dialog box asking whether to save, we can use the following code:

QMessageBox msgBox;
msgBox.setText(tr("The document has been modified."));
msgBox.setInformativeText(tr("Do you want to save your changes?"));
msgBox.setDetailedText(tr("Differences here..."));
msgBox.setStandardButtons(QMessageBox::Save
| QMessageBox::Discard
| QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Save:
qDebug() << "Save document!";
break;
case QMessageBox::Discard:
qDebug() << "Discard changes!";
break;
case QMessageBox::Cancel:
qDebug() << "Close document!";
break;
}

msgBox is a QMessageBox instance created on the stack. We set its main text information to "The document has been modified.", and informativeText is a simple explanatory text that will be displayed in the dialog box. Below we use a detailedText, which is detailed information. When we click the detailed information button, the dialog box can automatically display more information. The dialog box we defined has three buttons: Save, Discard and Cancel. Then we used exec() to make it a modal dialog box, and perform corresponding operations based on its return value.

6. Layout Manager

The GUI interface, in the final analysis, is just the superposition of a bunch of components. We create a window, put buttons on it, and put icons on it, so it becomes an interface. The position of components is particularly important when placing them. We have to specify where to place the component so that the window renders the way we need it to. This involves the mechanism of component positioning.

Qt provides two component positioning mechanisms: absolute positioning and layout positioning .

  • Absolute positioning is the most primitive positioning method: giving the coordinates and length and width values ​​of this component.
  • This way, Qt knows where to place the component and how to size it. But one problem caused by this is that if the user changes the window size, such as clicking the maximize button or dragging the edge of the window with the mouse, the absolutely positioned component will not respond in any way. This is also natural, because you don't tell Qt whether and how the component should update itself when the window changes. Or, there's an easier way: disable the user from resizing the window. But this is not always a long-term solution.
  • Layout positioning: You only need to put components into a certain layout, and the layout is managed by a dedicated layout manager. When the size or position needs to be adjusted, Qt uses the corresponding layout manager to adjust. Layout positioning perfectly solves the defects of using absolute positioning.

Among the layouts provided by Qt, the following three are our most commonly used:

  • QHBoxLayout: layout from left to right in the horizontal direction;
  • QVBoxLayout: layout from top to bottom in the vertical direction;
  • QGridLayout: layout in a grid, similar to HTML table;

6.1 System layout

The layout controls provided by the system

image-20230621211019387

6.2 Use widgets for layout

The second layout method is to use the widgets in the control to do the layout. In Containers

image-20230621211211302

The controls in the widget can perform horizontal, vertical, grid layout and other operations, which is relatively flexible. While re-layout, we need to flexibly use the characteristics of spring to make our layout more beautiful. Below is a login window. Using widgets, we can build the following login interface:

image-20230621211307819

7. Commonly used controls

Qt provides a series of controls for our application interface development. Below we introduce the two most commonly used controls. We can obtain the usage methods of all controls through the help documentation.

7.1 QLabel

QLabel is one of our most commonly used controls. It is very powerful and we can use it to display text, pictures and animations.

7.1.1 Display text (normal text, html)

Set the displayed content through the setText function of the QLabel class:

void setText(const QString &)
  • Can display plain text strings
QLable *label = new QLable;
label->setText(“Hello, World!”);
  • You can display a string in HTML format
    , such as displaying a link:
QLabel * label = new QLabel(this);
label ->setText("Hello, World");
label ->setText("<h1><a href=\"https://www.baidu.com\">百度一下</a></h1>");
label ->setOpenExternalLinks(true);

Among them, the setOpenExternalLinks() function is used to set whether to automatically open the link after the user clicks the link. If the parameter is specified as true, it will be opened automatically.

7.1.2 Display pictures

You can use the member function setPixmap of QLabel to set the picture.

void setPixmap(const QPixmap &)

First define the QPixmap object, load the image, and set it to QLabel

QPixmap pixmap;
pixmap.load(":/Image/boat.jpg");
QLabel *label = new QLabel;
label.setPixmap(pixmap);

7.1.3 Display animation

You can use the member function setMovie of QLabel to load animations and play files in gif format.

void setMovie(QMovie * movie)

First define the QMovied object and initialize it:

QMovie *movie = new QMovie(":/Mario.gif");
//播放加载的动画:
movie->start();
//将动画设置到QLabel 中:
QLabel *label = new QLabel;
label->setMovie(movie);

7.2 QLineEdit

Single-line text editing box provided by Qt.

7.2.1 Set/get content

Use text() to get the content of the edit box. The function is declared as follows:

QString text() const
  • Set edit box content
void setText(const QString &)

7.2.2 Set display mode

Use the setEchoMode () function of the QLineEdit class to set the text display mode. Function declaration:

void setEchoMode(EchoMode mode)

EchoMode is an enumeration type that defines four display modes:

  • QLineEdit::Normal mode display mode, displays according to the input content.

  • QLineEdit::NoEcho does not display anything. User input cannot be seen in this mode.

  • QLineEdit::Password password mode, the entered characters will be converted into special characters according to the platform.

  • QLineEdit::PasswordEchoOnEdit Displays characters when editing otherwise displays characters as password.
    In addition, when we use QLineEdit to display text, we hope to leave a blank area on the left side. Then, we can use the
    setTextMargins function provided by QLineEdit:

    void setTextMargins(int left, int top, int right, int bottom)
    

    Use this function to specify the number of pixels between the displayed text and the upper, lower, left and right boundaries of the input box.

// smallwidget.h
class SmallWidget : public QWidget
{
Q_OBJECT
public:
explicit SmallWidget(QWidget *parent = 0);
signals:
public slots:
private:
QSpinBox* spin;
QSlider* slider;
};
// smallwidget.cpp
SmallWidget::SmallWidget(QWidget *parent) : QWidget(parent)
{
spin = new QSpinBox(this);
slider = new QSlider(Qt::Horizontal, this);
// 创建布局对象
QHBoxLayout* layout = new QHBoxLayout;
// 将控件添加到布局中
layout->addWidget(spin);
layout->addWidget(slider);
// 将布局设置到窗口中
setLayout(layout);
// 添加消息响应
connect(spin,
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),slider, &QSlider::setValue);
connect(slider, &QSlider::valueChanged,
spin, &QSpinBox::setValue);
}

image-20230621225927166

8. Qt message mechanism and events

8.1 Event handling process

Events are emitted at different times by the system or Qt itself. When the user presses the mouse, types on the keyboard, or when the window needs to be redrawn, a corresponding event will be emitted.

Some events are emitted in response to user operations, such as keyboard events; other events are emitted automatically by the system, such as timer events. Event handling process:

  1. Inside Qt, Qt continuously grabs events in the event queue through the main event loop started by QApplication::exec().
  2. When an event occurs, Qt creates an event object. All event classes in Qt inherit from QEvent.
  3. After the event object is created, Qt passes the event object to QObject's event() function. The event() function does not handle events directly,
    but dispatches them to a specific event handler according to the type of the event object.
    The event() function is mainly used for event distribution:

8.2 Common event processing

In QWidget, the parent class of all controls, many callback functions for event processing are defined. These functions are protected virtual, that is, we can reimplement these functions in subclasses. The implementation of the function must follow the grammatical rules of the virtual function, and the consistency of the function name and parameters is guaranteed in the custom class.

8.2.1 Mouse events

//重写父类的虚函数
protected:
virtual void mousePressEvent(QMouseEvent *); //鼠标点击事件
virtual void mouseReleaseEvent(QMouseEvent *); //鼠标抬起事件
virtual void mouseDoubleClickEvent(QMouseEvent *); //鼠标双击事件
virtual void mouseMoveEvent(QMouseEvent *); //鼠标移动事件

8.2.2 Wheel event (QWheelEvent)

//virtual void wheelEvent(QWheelEvent *); //鼠标滚轮滑动
//鼠标滚轮滑动
void Widget::wheelEvent(QWheelEvent *e)
{
if(e->orientation()== Qt::Vertical) //如果方向是垂直
{
QPoint point = e->angleDelta();
QString str = QString("滚轮垂直滑动(%1, %2)")
.arg( point.x() ).arg(point.y());
ui->label->setText(str);
}
}

8.2.3 Keyboard event (QKeyEvent)

//virtual void keyPressEvent(QKeyEvent *); //键盘按下事件
//virtual void keyReleaseEvent(QKeyEvent *); //键盘抬起事件
//键盘按下事件
void Widget::keyPressEvent(QKeyEvent *e)
{
QString str;
    switch(e->modifiers()) //修饰键盘
{
case Qt::ControlModifier:
str = "Ctrl+";
break;
case Qt::AltModifier:
str = "Alt+";
break;
}
switch(e->key()) //普通键
{
case Qt::Key_Left:
str += "Left_Key Press";
break;
case Qt::Key_Right:
str += "Rigth_Key Press";
break;
case Qt::Key_Up:
str += "Up_Key Press";
break;
case Qt::Key_Down:
str += "Down_Key Press";
break;
case Qt::Key_Z:
        str += "Z_Key Press";
break;
}
ui->label->setText(str);
}

8.2.4 Size change event (QResizeEvent)

当窗口大小发生变化时被调用,参考代码:
//virtual void resizeEvent(QResizeEvent *); //大小改变事件
//大小改变事件
void Widget::resizeEvent(QResizeEvent *e)
{
//变化前的窗口大小
qDebug() << "e->oldSize() = " << e->oldSize();
//变化后的窗口大小
qDebug() << "e->size() = " << e->size();
}

8.2.5 Entering and leaving area events (enterEvent, leaveEvent)

//virtual void enterEvent(QEvent *); //进入事件
//virtual void leaveEvent(QEvent *); //离开事件
//进入事件
void Widget::enterEvent(QEvent *)
{qDebug() << "enterEvent";
}
//离开事件
void Widget::leaveEvent(QEvent *)
{
qDebug() << "leaveEvent";
}

9 Drawing

9.1 Qt drawing mechanism

Qt's drawing mechanism provides a unified API interface for screen display and print display, mainly composed of three parts: QPainter class, QPaintDevice class
and QPaintEngine class
l QPainter class provides various interfaces for drawing operations, which can be conveniently drawn various graphics.
l The QPaintDevice class provides space for drawing and a drawing container. The lPaintEngine class is an abstract class that provides an abstract interface for how QPainter draws to a specified device on a specified platform, and is generally not used
by developers .

image-20230621233533906

9.2 Drawing events

void Widget::paintEvent(QPaintEvent *e)
{
qDebug()<<"in paintEvent"<<"recet"<<e->rect(); //得到需要重新绘制的区域
QPainter paint(this); //定义画家(请了一个画家来画画),画在主窗口上
//画家画图片,作为背景图片
paint.drawPixmap(0,0,this->width(),this->height(),
QPixmap("../Image/bk.jpg"));
QPen pen; //定义一只画笔
pen.setColor(QColor(255,0,255)); //设置画笔的颜色
pen.setWidth(5); //设置画笔的宽度
pen.setStyle(Qt::DashDotLine); //设置画笔线条的风格
paint.setPen(pen); //画家使用这只画笔
paint.drawLine(30,30,500,30);//画家画水平的线条
paint.drawLine(30,30,30,500);//画家画垂直的线条
pen.setColor(Qt::yellow);//设置画笔的颜色
pen.setStyle(Qt::SolidLine);//设置画笔线条的风格
pen.setWidth(3);//设置线条的宽度
paint.setPen(pen);//画家使用这只画笔
QBrush brush(Qt::blue);//定义一把蓝色的画刷
brush.setStyle(Qt::DiagCrossPattern);//设置画刷的风格
paint.setBrush(brush);//画家使用这把画刷
paint.drawRect(50,50,150,200);//画家画矩形
paint.setPen(QPen());
paint.setBrush(QBrush(QColor(255,187,255),Qt::Dense3Pattern));
paint.drawEllipse(280,60,180,250);//画家画椭圆
}

9.3 Refresh the drawing area

//绘图事件
void Widget::*paintEvent*(QPaintEvent *)
 {
QPainter p(this); //在窗口上绘图
 p.drawPixmap(x,200,100,100,QPixmap("../Image/face.png"));
 p.drawPixmap(i,j,100,100,QPixmap("../Image/face.png"));
}
void Widget::on_pushButton_clicked()
{
 x += 20;
 if(x > this->width())
 {
 x = 0;
 }
 this->update(); //刷新绘图区
}
void Widget::*mousePressEvent*(QMouseEvent *e)
{i = e->pos().x();
j = e->pos().y();
this->update(); //刷新绘图区域
}

Reference learning video

Guess you like

Origin blog.csdn.net/weixin_42917352/article/details/131335496