Qt Programming-Initial Advancement
Preface
- Through the previous article, we have a preliminary understanding of Qt, Qt Programming (1)-Understanding
- Here we start to study Qt in depth. As we know before, the important things in Qt are signals and slots, which are connected through the connect() function. Here we take a closer look at signals and slots
1. Qt custom signals and slots
1. Custom signals and slots
- 1. First, you need to create two classes, a signal class and a slot function class. Right-click the project->Add New, and create a new class
- 2. Set the attributes of the class: class name, parent class, location.
In the declared slot function, right-click the function name, select Refactor->Add definition in the .cpp file.
Custom signal class:
Add a signal declaration in the header file of ZMSignals. , no need to implement
a custom slot function class:
add the definition and implementation of the custom slot function in the header file and source file of the ZMSlots class.
- 3. Connect signals and slots.
Signals and slots need to be connected through a window, eg: widget, window, etc.
//emit是发送信号的标识,不写会报警告,版本问题,(非必须)
emit zmSignal.zm_sig_start();
2. Customized signal band parameter overloading problem
- 1. Add overloaded signal and slot functions
- 2. It was found that an error was reported when connecting. It was because there was ambiguity in the context overloading function when connecting.
- 3. We can use a function pointer with parameters to point to the function we want to point to to eliminate ambiguity. I personally recommend the first of the following two methods.
#if 1 //两个方式一样,只是指针函数开放与不开放的问题
//方法一:
//设置两个带参数的函数指针
void (ZMSignals::*str_sig_start)(QString) = &ZMSignals::zm_sig_start;
void (ZMSlots::*str_slot_accept)(QString) = &ZMSlots::zm_slot_accept;
//关联带参数的函数指针
w.connect(&zmSignal, str_sig_start, &zmSlot, str_slot_accept);
#else
//方法二:强制转换型,代码可读性低
w.connect(&zmSignal, ( void (ZMSignals::*)(QString)) &ZMSignals::zm_sig_start, &zmSlot, (void (ZMSlots::*)(QString)) &ZMSlots::zm_slot_accept);
#endif
3. Summary of function overloading issues
- Pay attention to which function the signal overloaded function pointer points to. When connecting the signal of the overloaded function, you must indicate which slot function is connected.
4. Extension of signals and slots
1. Signal connection:
- We trigger a signal by clicking a button, and then trigger the slot function corresponding to the signal through the connect connection between the signal and the slot. That is: signals connect signals. A message signal can be bound to multiple slots. Similarly, a slot function can also be bound to multiple message signals. ( Many-to-many relationship )
eg: Triggering a button click simultaneously triggers the execution of the slot function corresponding to ZMSlots, and triggers the closing slot function corresponding to MainWindow.
2. Signal disconnection:
- The connection can be disconnected through the disconnect function, which is used in the same way as the signal connection connect.
- disconnect(signal sender, signal, signal receiver, slot function);
3. Parameters of signals and slots
- What the signal sends is what the slot function receives, and the types must be consistent.
- The number of parameters of the signal can be more than the number of parameters of the slot function, but the parameter types of the same number of parameters must correspond one to one. The reverse is not possible.
2. Lambda function
- In order to solve the problem of transmission and connection of various signals in the project, in large projects, excessive use of signal connection and transmission will reduce the readability of the project and increase the cost of familiarity.
1. Understanding Lambda functions
- Lambda function, also called Lambda expression, is an anonymous function (function without a name), which is different from traditional functions.
- Lambda expressions are a concept introduced after C++11 and are used to define and create anonymous function objects.
2. Lambda expression structure:
[Capture list] (parameter) mutable-> return type {function body},
eg:
[](){
qDebug("Hello Qt");
}
- [], identifies the beginning of a Lambda anonymous function. This must be present and cannot be omitted. The function object parameter is passed to the constructor of the function object class automatically generated by the compiler. Function object parameters can only use local variables visible in the scope where the Lambda is defined, including this of the class where the Lambda is located.
- [] The corresponding parameters in the square bracket function object have the following forms:
- Empty , no function object parameters are used
- = , the function body uses visible local variables in the scope of Lambda, including the value-passing method of this of the class, which is equivalent to the compiler giving all local variables in the scope of Lambda**Assignment**One copy for the Lambda function
- & , the function body uses visible local variables in the scope of Lambda, including the reference method of this of the class, which is equivalent to the compiler giving all local variables in the scope of Lambda**quote**One copy for the Lambda function
- this, the member variable inside the Lambda can be used in the function body
- a , not a letter, but refers to a specific variable a, copy a variable a in Lambda and use it
- &a , reference variable a in Lambda
- a, &b , copy a, reference b
- =, &a, &b , except for a and b references, other variables are copied.
- &,a,b , except for copies of a and b, other variables are referenced.
- mutable: mark can be changed
3. Why use Lambda function?
- Some functions are only used temporarily and their business logic is very simple, so there is no need to give them names. Some operations can also be simplified in Qt.
4. Lambda instance
3. Lambda function extension
1. Lambda return value
The program can output the result normally: 40;
- important point:
- -> is a sign with a return value, int is the return value type, and is returned directly in the function.
- The last () is to call the function. Without (), it is not a function call. The function here can be called directly after being defined.
Lambda expression, realizing Fibonacci numbers
//斐波那契数:Fibonacci数
int a=0, b=1;
[](int& a,int& b, int count){
int ret = 0;
for (int i =0; i<count; i++) {
ret = a+b;
a=b,b=ret;
qDebug()<<ret;
}
}(a, b, 10);//函数调用时,传a,b进到Lambda表达式里
operation result:
2. Application of Lambda
- A signal without parameters calls a slot function with parameters. At this time, Lambda is used to
implement the principle analysis: because the button click has no parameters, the anonymous function also has no parameters, but a signal with parameters is called in the anonymous function.
3. QString to char*
- Because QDebug will include the double quotes of QString when printing.
- Among some public methods in the QString class, there is a toUtf8 method, which returns a QByteArray and is first converted into a byte array. Then there is a data method, which calls the data method and then converts the array into char*
4. Lambda meaning
- 1. Make the code more concise and efficient
- 2. If connect, the receiver of the signal is this, this can be omitted.
connect(btn, &QPushButton::clicked,[=](){
//信号接收者为this,可以省略不写
this->close();
});//发送信号
4. Commonly used controls
1. QTextEdit control
- QTextEdit: text edit box,
- Example:
2,QMainWindow
- QMainWindow is the main window class that provides an interface for users, including a menu bar (menubar), multiple toolbars (toobar), multiple riveted components (dockwidgets floating windows), a status bar (status), and a central widget (centralwidget) , is the basis of the app, eg: text editor, picture editor, etc.
3. Menu bar (QMenuBar)
- There is only one menu bar, and the setting method is: setMenuBar
4. Add toolbar (QToolbar)
- The toolbar can be dragged at will, and can be placed on the left, upper, lower, or right side of the software, or even float in the app interface.
- The difference between a toolbar and a menu bar : there can only be one menu bar, and it is at the top; while there can be multiple toolbars, and their positions are diverse. So the setting method is addToolBar
5. Add status bar (QStatusBar)
-
There is and can only be one status bar added, so the setting method is setStatusBar.
-
Add status bar,Due to differences in systems and when the number of Chinese characters and Chinese symbols is an odd number, garbled characters may easily appear.,
-
Solution 1: Reset the encoding rules in the editor, and add all Chinese characters in front of themu8, that’s it
-
Solution 2: Use the QStringLiteral() method, because it is implemented internally using Lambda expressions, and high-frequency calls affect performance.
-
6. Riveting components and central components (QDockWidget, centralWidget)
1. Riveted components (dockWidget)
-Riveted components, central components, and floating windows have the same meaning. By checking the Qt Assistant documentation, we see that QDockWidget is based on QWidget.There can be multiple floating windows, so addDockWidget:
- When there is a riveted component, it will become floating when dragged to the middle, and the default docking place is a bit strange. This is because, in QMainWindow, we have not added the center widget. The default center widget is empty, so it is directly at the top.
- For the settings of riveted parts, query the Qt assistant documentation, which is the same as the toolbar.
2. CentralWidget
- In QMainWindow, there is a central component, but this central component is not a specific central component. Instead, we can set a specific component as the central component.There can only be one central widget, so setCentralWidget
5. Engineering and interface UI
1. UI designer
- There will be a .ui file in every project, which is actually a Qt interface file. When the file is opened, the Qt ui designer is automatically launched. Editing controls in this designer will be much more convenient and intuitive, and greatly improve development efficiency.
- After adding a tableview
and setting a new action, drag the action directly to the corresponding position. - Pay more attention to the use of property settings, the use of signals and slots, and the use of right-click property settings.
2. Add Qt resource files
- There are two ways to add resources: source code addition, and adding using UI designer. For example: a QAction object, add an icon to it, or set an icon. You can add multiple representatives. Generally speaking, a tool or a tab is one Icon, therefore, we should set the icon, that is, set the icon, then the method is set at the beginning, setIcon
1. How to add source code
- Adding images to the source code is limited to paths. Using relative paths requires some settings, and once the path is modified, the images may not be loaded.
2. How to add UI designer
- To add a prerequisite, you need to create a Resource File, right-click the project->add New->Qt->Qt Resource File, create a new project resource file, and then put the image resources into it.
- After creating the resource file, set the prefix and add image resources. Remember to save after adding the resources.
- After saving the resources added in the previous step, open the UI designer and add an icon to the "Save" option.
- After selecting the icon, you can see it directly in the UI designer.
- After adding the resource file, we can also use code to access the resource file.
When constructing QIcon, we need ": + prefix name + resource path"
3. Dialog box – modal & non-modal
- In graphical user interfaces, dialog boxes are distinctive views used to display information to the user or obtain user input responses when needed. constitutes human-computer interaction.
- Standard dialog boxes are a series of dialog tools built into Qt to simplify development.
- Qt's built-in dialog boxes include:
- QColorDialog select color dialog
- QFileDialog selects a file or directory
- QFontDialog select font
- QInputDialog allows the user to enter values and returns them
- MessageBoxDialog modal dialog box, used to display information, consultation or warning, etc.
- etc.
- Modal: User interaction is blocked in the current dialog box
- Non-modal: The user can jump out of the current dialog box and interact in other dialog boxes.
1,QDialog
- Qt's entry main function returns an exec, which keeps Qt's main window displayed. At that time, there is an infinite loop in exec. It waits for control messages until it receives the closing message, and then exits the window. Otherwise, it keeps looping. Blocked in the message, so that the original window cannot continue to execute.
- Note, the problem of lambda expression scope, (stack)
- Pay attention to the hidden dangers of memory leaks and add methods to delete components.
2,QMessageBox
- 1. Get to know
- QMessageBox is a modal dialog box , which is mainly used in apps to provide display information, pop-up queries, warnings, etc. For example: when we edit text in Notepad and click Close if it is not saved, the app will pop up a QMessageBox dialog box to ask whether to save the text.
- QMessageBox is a dialog box based on the QDialog class
- 2. Use
- Example:
QMessageBox::information(this, "ask", "what are you doing?");, information, question, warn, and ceramic are all static functions and have their own memory controls, so they can be called directly using classes. No need to create it in the heap anymore
- Pay attention to the return type of static member functions and how to call them
- The meaning of parameters
- Part of the source code:
- Example:
connect(ui->pb02, &QPushButton::clicked, [=](){
//在堆中创建msg,需要控制释放,但对于模态来说,会阻塞函数不能结束,如果用户触发结束后,自动跟随函数释放内存。因此不建议这么写
// QMessageBox* msg = new QMessageBox(this);
// msg->information(this, "询问","你在干嘛?");
//比较合理的编写方式,information为静态函数,因此可以直接使用类调用
int ret = QMessageBox::information(this, "提示","你上班摸鱼5分钟了,请合理安排时间!", QMessageBox::Yes|QMessageBox::No);
if (ret == QMessageBox::Yes) {
qDebug()<<"好的,知道了!";
} else {
qDebug()<<"就是为了让老板知道!";
}
});
connect(ui->pb03, &QPushButton::clicked, [=](){
//比较合理的编写方式,question为静态函数,因此可以直接使用类调用
QMessageBox::question(this, "询问","你在干嘛?");
});
connect(ui->pb04, &QPushButton::clicked, [=](){
//比较合理的编写方式,warning为静态函数,因此可以直接使用类调用
QMessageBox::warning(this, "警告","注意:你上班摸鱼10分钟了,可能要被老板发现了");
critical_func(this);
});
void critical_func(QWidget* widget)
{
// QMessageBox::critical(widget, "致命","不好,你摸鱼被老板发现了!");
QMessageBox* msg = new QMessageBox(widget);
msg->resize(200,100);
QPushButton* btn = new QPushButton();
btn = msg->addButton("确定", QMessageBox::AcceptRole);
msg->show();
widget->connect(btn,&QPushButton::clicked,widget, [=](){
msg->critical(widget, "致命","不好,你摸鱼被老板发现了!");
});
}
3,QColorDialog
- In the static function area in QColorDialog:
- Four parameters: color, parent class, title name, ColorDialogOptions color options, if you only call getColor(), defaults are added respectively. The return value is QColor.
static QColor getColor(const QColor &initial = Qt::white,
QWidget *parent = nullptr,
const QString &title = QString(),
ColorDialogOptions options = ColorDialogOptions());
4,QFileDialog
- Search QFileDialog in the Qt Assistant, static function area, getOpenFileName and getOpenFileNames are the two methods we use to obtain the file path + file name. To operate the file, we only need to obtain the path + file name:
- Two functions, one returns QString without adding s, and the other function adding s returns a QStringList, that is, one returns a specific file and the other returns a file list.
static QString getOpenFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
Options options = Options());
Corresponding to five parameters:
parent class: usually this
caption: title
dir: default path
selectedFilter: file filtering, filtering and displaying files with suffixes that meet the conditions
opthons: filer, the default is enough
- Simple example:
6. Summary
- 1. Through a preliminary understanding of Qt, we learned about some common controls developed in Qt interface, the inheritance relationship of controls and the open methods in the controls.
- 2. There are two ways in engineering development. When programming, we use code or use UI designer to design according to different demand scenarios (a game between performance and development speed)
- 3. The Qt Assistant document is very practical and it is recommended to use it more.
- 4. Here we only have some understanding of Qt, involving programming design patterns and more aspects of optimizing performance, which have not been reflected in this content. Subsequent accounts will be continuously updated. Interested students please also pay attention.