QT knowledge points

QT

1. How to convert between QString and basic data types (such as int, etc.)?

1) QString to int

Call the toInt() function directly

QString str("100");

int tmp = str.toInt();

or:

bool ok;

QString str("100");

int tmp = str.toInt(&ok);

Note: ok indicates whether the conversion is successful, ok is true if it succeeds, and ok is false if it fails.

2) int to QString

QString::number();

example:

int tmp = 100;

QString str = QString::number(tmp);

2. Modify the size, text color and other attributes of QPushButton.

1) Modify the button background color directly through the code

ui.loginBtn->setStyleSheet(“color: rgb(255, 255, 255); background-color: rgb(255, 0, 0);”);

2) First create a GUI application

Open the interface file, or create a new one

img

Drag pushbutton in

img

Find the stylesheet in the property bar, click the ellipsis next to it

img

Click [Add Color], select color to modify the text color, and select background-color to modify the background color.

img

3. There are several commonly used layouts, how to adaptively zoom?

Mainly through the UI designer Qt Designer to complete.

1. When creating an interface, you need to create a base class for the interface. There are 3 kinds of base classes to choose from:
QMainWindow is the main window class, the main window has a main menu bar, toolbar and status bar, similar to the main window of a general application;

QWidget is the base class of all visual interface classes. The interface created by selecting QWidget can support various interface components;

QDialog is a dialog box class, you can create a dialog-based interface.

Classes that use Qt's signal and slot (signal and slot) mechanisms must add the macro Q_OBJECT; add it in the header file. How to show:

img

2. Layout of interface components

If you want the interface to adapt to the resolution of the computer or change the size of the interface, all components on the interface can also be changed accordingly. In this case, the "Layout function" can be used. The so-called layout is the arrangement of the components on the interface. Using the layout, the components can be distributed regularly, and the size and relative position can be automatically adjusted with the size of the form.
1) Good use of container classes can make the interface more beautiful. Such as QGroupBox, QTabWidget, QFrame, etc.

2) Layout management

In the UI designer, there are two component panels, Layouts and Spacers, in the component panel.

The function of each layout component:

Vertical Layout: Layout in the vertical direction, the components are automatically distributed in the vertical direction.

Horizontal Layout: Layout in the horizontal direction, the components are automatically laid out in the horizontal direction.

Grid Layout: Grid layout, when the size of the grid layout changes, the size of each grid changes.

Form Layout: Form layout, similar to grid layout, but only the rightmost column of grids will change size.

Horizontal Spacer: A space for horizontal separation.

Vertical Spacer: A space for vertical separation.

4. What is the signal slot mechanism

Signals and slots

The signal slot is a mechanism used for communication between objects in QT, and it is also the core mechanism of QT. In GUI programming, we often need to notify another component to respond while changing a component.

In the early days, communication between objects was implemented using callbacks. Callbacks are actually implemented using function pointers. When we want the processing function to be notified when something happens, we need to pass the pointer of the callback function to the processing function, so that the processing function will call the callback function at the appropriate time. Callbacks have two obvious disadvantages:

They are not type safe, and we cannot guarantee that the parameters passed by the handler function to the callback function are correct.

The callback function and the processing function are tightly coupled, because the processing function must know which function is called back.

The so-called signals and slots are actually functions

QT components predefine a lot of signals and slots, and in GUI programming, we are used to inherit those components and add our own slots after inheritance to handle signals in our way. A slot is almost the same as a normal C++ member function. It can be a virtual function, it can be overloaded, it can be shared, private or protected, and it can also be called by other member functions. Its function parameters can also be of any type. The only difference is that the slot can also be connected to the signal.
Unlike callbacks, the signal slot mechanism is type-safe . This is reflected in the fact that the function signature of the signal and the function signature of the slot must match before the signal can be transmitted. In fact, the number of parameters of the slot can be less than the number of parameters of the signal, because the slot can ignore the extra parameters in the signal parameter. Signals and slots are loosely coupled: the class sending the signal does not care which classes will receive its signal. QT's signal slot mechanism, here at the right time, the slot can receive the parameters of the signal and call it. Both signals and slots can have any number of parameters, and they are all type-safe.

An example of custom signals and slots

The first thing we need to know is that all inherited from QObject or its subclasses (such as QWidget) can contain signal slots. The class we write must inherit from QObject (or its subclasses). All classes that contain signal slots must contain the Q_OBJECT macro at the top of the declaration.

//MyStr.h
# ifndef  MYSTR
# define  MYSTR
#include<QObject>
#include<QString>
 
class MyStr :public QObject
{
    Q_OBJECT //必须包含的宏
 
public:
    MyStr (){m_value = "zero";}
 
    QString value() const {return  m_value;}
 
public slots :
    void setValue(QString value );
 
    signals: //信号
    void valueChanged(QString newValue); 
private:
    QString m_value;
};
 
#endif 
  • In this simple class, we can see that slots are used to represent slots and signals are used to represent signals. In fact, they are not so mysterious, they are all macro definitions, and even signals are just public macro definitions:
#     define signals public
  • Signal code will be automatically generated by moc, and developers must not implement it in their own C++ code.
  • On the contrary, the slot should be implemented by the programmer. A possible implementation of MyStr::setVaule() is provided below
#include"MyStr.h"
void MyStr::setValue(QString value)
{
    if(value != m_value)
    {
        m_value = value;
        emit valueChanged(value);
    }
}

The setValue function first compares whether the value of the new parameter is the same as the value of the data member (the reason for this is explained later), if not, set the value of the data member m_value, and then send the signal valueChanged(). To whom? The class is not written. This is not what the class designer cares about, nor is it what the class cares about. It just sends the signal out. Then, let's set up who will receive this signal.

int main(int argc, char *argv[])
{
    MyStr a;
    MyStr b;
    QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));
    a.setValue("this is A");
    return 0;
}

We define two class objects a/b, and use the QObject::connect() function to specify the sender, signal, receiver, slot and other information. The format of the connect function is as follows:

 QObject::connect(    发送方,    SIGNAL(...),    接收方,    SLOT(..)    );

When we call the member function setValue of a, the function not only sets a.m_value to "this is A", but also sends out the signal valueChanged(), which is received by b.setValue, thus setting b.m_value to " this is A", and b.setValue sends out the valueChanged signal, but this signal is not received by an object because we have not established any connection with b as the sender. At this point, you should understand why you need to judge value != m_value before emit, because if there is no such step, and it happens to be set

QObject::connect(&b,SIGNAL(valueChanged(QString)),&a,SLOT(setValue(QString)));

Then the signal of b is received by a, and the signal sent by a is received by b, thus entering an endless loop.

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
 
    MyStr  a;
    MyStr  b;
    QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));
    a.setValue("this is A");
 
    QLabel* label = new QLabel;
    label->setText( b.value());
    label->show();
    return app.exec();
}

We use the label output to see if b receives the signal of a. If it is, the content of b should be "this is A", output on the label, and the result of the program:

img

detail

connection

To successfully connect the signal to the slot, their parameters must have the same order and the same type, or allow the signal to have more parameters than the slot, the slot will automatically ignore the extra parameters and call.

One signal can connect to multiple slots

Use QObject::connect to connect a signal to multiple slots, and when the signal is emitted, the slots will be called in the order in which the contact was declared.

 MyStr  a;
 MyStr  b;
 MyStr  c;
//信号连接到两个槽
 QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SLOT(setValue(QString)));
 QObject::connect(&a,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));
 a.setValue("this is A");
//依次调用b.setValue()、c.setValue()

Multiple signals can be connected to the same slot

Similarly, multiple signals can be connected to the same slot, and the sending of each signal will call that slot.

 MyStr  a;
 MyStr  b;
 MyStr  c;
//两个信号连接到同一个槽
 QObject::connect(&a,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));
 QObject::connect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));
//下面的操作皆会调用到槽c.setValue()
 a.setValue("this is A");
b.setValue("this is B");

One signal can be connected to another signal

When the first signal is transmitted, the second signal will also be sent out one by one.

 MyStr  a;
 MyStr  b;
 MyStr  c;
//两个信号相连接
 QObject::connect(&a,SIGNAL(valueChanged(QString)),&b,SIGNAL(valueChanged(QString)));
//再建立b与c的连接
 QObject::connect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));
//下面的操作同时发送了信号a.valueChanged与b.valueChanged
 a.setValue("this is A");
//从而信号b.valueChanged被槽c.setValue所接收

Connection can be removed

//移除b 与 c之间的连接
  QObject::disconnect(&b,SIGNAL(valueChanged(QString)),&c,SLOT(setValue(QString)));

In fact, when an object is deleted, all its associated links will become invalid, and QT will automatically remove all links to this object.

Since Qt's unique keywords and macros are used in the sample, and Qt itself does not include a C++ compiler, if you use popular compilers (such as Visual C++ under Windows or gcc under Linux), you cannot directly compile this For a piece of code, the Qt intermediate compiler tool moc.exe must be used to convert the piece of code into C++ code without special keywords and macros to be parsed, compiled and linked by these compilers.

When using signals, you should also pay attention: The definition process of signals is implemented in the definition process of the class, that is, the header file. For the normal operation of the intermediate compilation tool moc, do not define a signal in the source file (.cpp), and the signal itself should not return any data type, that is, a null value (void).

The reason why the designers of Qt want to do this estimation is for the strictness of the matching between the signal and the reaction tank. Since there is no difference between reaction slots and regular functions in execution, it can also be defined as public slots, protected slots, and private slots. If necessary, we can also define the reaction tank as a virtual function so that subclasses can implement different implementations, which is very useful.

5. How do multiple threads communicate?

​ Method 1:

Create a class derived from the QThread class

Rewrite the run function in the child thread class and write the processing operation into the function

Create a child thread object in the main thread, start the child thread, and call the start() function

Method Two:

Abstract business processing into a business class, and create a business processing function in this class

Create a QThread class object in the main thread

Create a business class object in the main thread

Move business class objects to child threads

Start the child thread in the main thread

Execute the business processing functions in the business class by way of signal slots

Under multithreading, in which thread the signal slot is executed, and how to control it

The fifth parameter of connect can be used to control the thread where the signal slot is executed

Connect has several connection methods, direct connection and queue connection, automatic connection

Direct connection: The signal slot is executed in the same thread as the signal sender

Queue connection: the signal is executed in the thread where the signal sender is located, and the slot function is executed in the thread where the signal receiver is located

Automatic connection: it is a queue connection function when it is multi-threaded, and it is a direct connection function when it is single-threaded.

6. What database has been used, how does qt operate the database (addition, deletion, modification, etc.)

The general steps are as follows:

(1) Add sql module

Add a statement in the .pro file: QT += core gui sql

(2) Add MySql database

1     QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");

(3) Connect to the database

1     db.setHostName("127.0.0.1");  //数据库服务器IP
2     db.setUserName("root");    //数据库用户名
3     db.setPassword("123456");  //密码
4     db.setDatabaseName("test");  //使用哪个数据库

(4) Open the database

1     if (db.open() == false) {
2         QMessageBox::warning(this, "错误", db.lastError().text());
3         return;
4     }

(5) Execute sql statement

1     //操作sql语句
2     QSqlQuery query;
3     query.exec("create table student(id int primary key, name varchar(255), age int, score int);");
img

At this time, we copy the files under the installation path of MySql to the installation directory of Qt, close Qt, and open it again without error:

2. How to use 2

When adding MySql, we give the database connection a name, the second parameter of the addDatabase function, so that multiple connections can be established for a database.

1 QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "mydb");

In this way, when we use QSqlQuery to execute MySql statements, we must specify the database name:

1 1 //操作sql语句
2 2     QSqlQuery query(db);
3 3     query.exec("insert into student(id, name, age, score) values(1, 'mike', 18, 59);");

1. Realize the database insertion operation to MySql

QSqlQuery query(dbconn);
query.prepare("INSERT INTO faceimage(FaceData,StrName,Sijian,Shijian)" "VALUES(:FaceData,:StrName,:Sijian,:Shijian)");  
query.bindValue(":FaceData",this->ui->ImageLabel->text());  
query.bindValue(":StrName",this->ui->userName->text());
query.bindValue(":Sijian",this->ui->idNumber->text());
query.bindValue(":Shijian",Catchtime);
query.exec();    

2. Realize the database deletion operation on MySql

QSqlQuery query(dbconn);
query.prepare(QString("DELETE FROM faceimage WHERE Faceid=?"));
query.addBindValue(Faceid);
query.exec();

3. Realize the update operation of the MySql database

query.prepare("update faceimage set StrName=?,Sijian=? where Faceid=?");
query.addBindValue(this->ui->XGuserName->text());
query.addBindValue(this->ui->XGidNumber->text());
query.addBindValue(Faceid);
query.exec();

4. Realize the traversal operation of the MySql database

 QSqlQuery query(dbconn);
 query.prepare(sql);
 while(query.next())
 {
   m_model->setItem(i,0,new QStandardItem(query.value(0).toString()));
   m_model->setItem(i,1,new QStandardItem(query.value(3).toString()));
   m_model->setItem(i,2,new QStandardItem(query.value(6).toString()));
   m_model->setItem(i,3,new QStandardItem(query.value(2).toString()));
   i++;
 }

7. The process of Qt Socket communication

QT's TCP Socket communication is still divided into server and client. The server monitors whether there is a client connection by monitoring a certain port. If there is a connection, a new SOCKET connection is established; the client connects to the server through IP and PORT. After the connection is successfully established, data can be sent and received. Up. It should be noted that in QT, QT treats SOCKET as an input and output stream, and data is sent and received through read() and write(), which needs to be distinguished from our common send() and recv() .

To carry out SOCKET communication in QT, you need to enter QT += network in the project name .pro file

a): Server-side communication mechanism

​ On the server side, two classes QTcpServer and QTcpSocket are needed to establish SOCKET communication. Among them, QTcpServer is the Server-side object used to establish QT, and QTcpSocket is the Socket socket object used to establish SOCKET communication.

1): Create an object of the QTcpServer class

2): Monitor

In QT, listen to the port is established through listen(). The usage is as follows: mp_TCPServer->listen (address type, port number);

3): Associate receiving connection signal and slot function

​ The server uses the signal SIGNAL: newConnection() to determine whether a new connection is received. When the server receives a client connection, it triggers the signal newConnection(), and then calls the corresponding slot function (such as a custom function) : ServerNewConnection()) save the newly received connection; so it is necessary to establish a connection between the signal and the slot function after the server monitors the port. Connect through the connect function

4): Receive data

​ In QT, QT uses the signal SIGNAL: readyRead() to determine whether there is data coming in. When the client successfully sends data to the server, the readyRead() signal is triggered on the server, and the corresponding custom is called at this time The slot function (such as: ServerReadData()) saves the received data; the connection between the signal readyRead() and the slot function ServerReadData() is established through the connect function:

5): Send data

​ In QT, send data to the outside through the write function

b): Client communication mechanism

​ The communication mechanism of the client is relatively simple compared with the server, and only a class of QTcpSocket is used.

1): Create an object of the QTcpSocket class

Create a socket for Socket:

2): Connect to the server

The client connects to the server through the connectToHost(IP, Port) function

3): Receive data

​ The mechanism for the client to receive data is the same as that for the server to receive data. Determine whether there is data incoming by whether the readyRead() signal is triggered. If the signal is triggered, call a custom function (such as ClientRecvData()) to save the received data. Through the connect() function, the signal readyRead() is mapped to the slot function ClientRecvData().

In the slot function ClientRecvData(), the data is received through the read() function. For the specific usage method, please refer to the server receiving data.

4): Send data

The client sends data through the write() function. For specific usage, please refer to the server sending data

8. Program packaging

After the development of the Qt project is completed, the release program needs to be packaged, and because there is no Qt configuration environment on the user's computer, the exe file generated by the release and the dependent dll file need to be copied to a folder, and then packaged with the Inno Setup packaging tool Into an exe installation package, you can publish it.

The icon of the exe file that we compiled is a white box that comes with Qt, which is not very beautiful. How can I set the icon of the program by myself? First create an ico format file. There are many online png or jpg pictures that can be converted into ico format icon files, and then put the ico file in the source code directory, which is the same folder as the .pro file.

Add in the .pro project file:

RC_ICONS = car.ico // 这里的car.ico是我的ico文件的名字,改成你自己的ico文件名

After adding, be sure to re-qmake again, and then run your program again, so that the exe file in your debug or release folder will have the icon you set.