qt learning notes

Video link
https://www.bilibili.com/video/BV1Wf4y1Y7uh

Qt common tools

assistant: api manual
qmake: qt builder
designer: graphical interface design
uic: convert the interface designed by designer into C + + or py file
rcc: resource compiler
moc: meta object compiler
qtcreator: integrated development environment

Making the first GUI program with qmake

Create a project directory, enter and edit main Cpp file

mkdir Hello
cd Hello
vim main.cpp
#include <QApplication>
#include <QLabel>
int main(int argc, char **argv){
    //Create qt application object
    QApplication app(argc, argv);
    //Create label control
    QLabel label("hello world");
    //Show label controls
    label.show();
    //Let the application enter the event to prevent flash back
    return app.exec();
}

Use qmake to build the project file (the default generated pro project file is the same as the directory name)

qmake -project

Edit the project file and add a line of compilation options

vim Hello.pro
 add to	QT += widgets

Generate the Makefile compilation configuration file, compile it, and then run it

qmake
make
./Hello

An error is reported, and the solution of - lGL cannot be found
View the location of the library locate LIBGL so
Link sudo ln /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0 /usr/lib/libGL.so
Recompile make

Qt coding problem

By default, qt5 can correctly parse utf-8 encoding and automatically convert it to unicode encoding inside qt.
gbk coding is commonly used in windows, and the coding conversion needs to be realized through QTextCodec

QTextCodec *codec = QTextCodec::codecForName("GBK");
QString string = codec->toUnicode("Hello");

Qt control parent window

When creating a control, you can specify to dock on a parent window. At this time, the control will be bound inside its parent window as a child window, and move, hide, display and close with the parent window; Otherwise, the control will be displayed on the screen as a separate window and free from other windows
There are three common parent window classes:
QWidget
Qmainwindow (main window) / direct subclass of Qwidget
Qdialog (dialog box) / / direct subclass of QWidget

Sample code

#include <QApplication>
#include <QWidget>
#include <QDialog>
#include <QMainWindow>
#include <QLabel>
#include <QPushButton>
#include <QApplication>

int main(int argc, char **argv){
    QApplication app(argc, argv);

    //Define parent window
    //QWidget parent;
    //QMainWindow parent;
    QDialog parent;

    //Label control, docked above the parent window
    //Two definition methods
    QLabel label("this is title", &parent); //Stack
    QPushButton *button = new QPushButton("this is button", &parent);   //heap
    button->move(0, 50);

    parent.show();  //When the parent window is displayed, the controls docked above will also be displayed
    return app.exec();
}

Signal and slot

The slot function can be linked to a signal. When the signal is transmitted, the slot function will be started and executed. In addition, the slot function can also be called directly as an ordinary member function.

One signal can be linked to multiple slots, multiple signals can be connected to one slot, and two signals can also be directly linked.

Link between signal and slot

QObject::connect(const QObject *sender, const char *signal,
				const QObject *recviver, const char *method);
sender:Signal sending object pointer
signal:The signal function to be transmitted can make SIGNAL(..)Macro type conversion
receiver:Receiving object pointer of signal
method:The slot function to be executed after receiving the signal can be used SLOT(..)Macro type conversion

Code example, click the button to close the tab

#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QApplication>

int main(int argc, char **argv){
    QApplication app(argc, argv);

    QDialog parent; //parent window
    QLabel label("this is title", &parent); 
    QPushButton button("this is button", &parent);   
    button.move(0, 30);
    parent.show();  //When the parent window is displayed, the controls docked above will also be displayed

    //Link between signal and slot
    QObject::connect(&button, SIGNAL(clicked(void)), &label, SLOT(close(void)));
    return app.exec();
}

Code example, slider and selection box synchronization

#include <QApplication>
#include <QDialog>
#include <QSlider>
#include <QSpinBox>
#include <QApplication>

int main(int argc, char **argv){
    QApplication app(argc, argv);

    QDialog parent; //parent window
    QSlider slider(Qt::Horizontal, &parent);
    slider.move(20, 20);
    slider.setRange(0, 100);
    QSpinBox spin(&parent);
    spin.move(100, 20);
    spin.setRange(0, 100);
    
    QObject::connect(&slider, SIGNAL(valueChanged(int)), &spin, SLOT(setValue(int)));
    QObject::connect(&spin, SIGNAL(valueChanged(int)), &slider, SLOT(setValue(int)));

    parent.show();
    return app.exec();
}

Code example, calculator program

calc.h

#ifndef __CALC_H
#define __CALC_H

#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QLineEdit>    
#Include < qhboxlayout > / / horizontal layout
#Include < qdoublevalidator > / / validator

class CalculatorDialog:public QDialog{
    Q_OBJECT    //moc of qt
public:
    CalculatorDialog(void);
public slots:
    //Enables the slot function of the equal sign button
    void enableButton(void);
    //Calculation results and displayed slot functions
    void calcClicked(void);
private:
    QLineEdit *m_editX; //Left operand
    QLineEdit *m_editY; //Right operand
    QLineEdit *m_editZ; //Display results
    QLabel *m_label;    //+
    QPushButton *m_button;  //=
};
#endif
calc.cpp

#include "calc.h"
CalculatorDialog::CalculatorDialog(void){
    //Interface initialization
    setWindowTitle("calc"); //Set window title
    m_editX = new QLineEdit(this);
    m_editX->setAlignment(Qt::AlignRight);  //Set text right alignment
    //Digital verifier
    m_editX->setValidator(new QDoubleValidator(this));

    m_editY = new QLineEdit(this);
    m_editY->setAlignment(Qt::AlignRight);
    m_editY->setValidator(new QDoubleValidator(this));

    m_editZ = new QLineEdit(this);
    m_editZ->setAlignment(Qt::AlignRight);
    m_editZ->setReadOnly(true);

    m_label = new QLabel("+", this);
    m_button = new QPushButton("=", this);
    m_button->setEnabled(false); //Initial setting disabled

    //Create a layout and automatically call the size and position of each control
    QHBoxLayout *layout = new QHBoxLayout(this);
    //Add controls to the layout in horizontal order
    layout->addWidget(m_editX);
    layout->addWidget(m_label);
    layout->addWidget(m_editY);
    layout->addWidget(m_button);
    layout->addWidget(m_editZ);
    setLayout(layout);

    //Signal and slot function link
    QObject::connect(m_editX, SIGNAL(textChanged(QString)),
            this, SLOT(enableButton(void)));
    QObject::connect(m_editY, SIGNAL(textChanged(QString)),
            this, SLOT(enableButton(void)));
    QObject::connect(m_button, SIGNAL(clicked()),
            this, SLOT(calcClicked(void)));
}

void CalculatorDialog::enableButton(void){
    bool bXOK, bYOK;
    m_editX->text().toDouble(&bXOK);
    m_editY->text().toDouble(&bYOK);
    m_button->setEnabled(bXOK && bYOK);
}

void CalculatorDialog::calcClicked(void){
    double res = m_editX->text().toDouble() + m_editY->text().toDouble();
    QString str = QString::number(res);
    m_editZ->setText(str);
}
main.cpp

#include <QApplication>
#include "calc.h"

int main(int argc, char **argv){
    QApplication app(argc, argv);
    CalculatorDialog calc;
    calc.show();
    return app.exec();
}

Qt designer

qt designer is used to drag and drop GUI controls through a graphical interface.
Use example
The terminal inputs the designer command to start
Make the following graphical interface

Use uic to turn this into a C + + code file

uic LoginDialog.ui -o ui_LoginDialog.h

Write logindialog H file

#ifndef __LOGINDIALOG_H
#define __LOGINDIALOG_H
#include "ui_LoginDialog.h"
#include <QMessageBox>
#include <QDebug>

class LoginDialog: public QDialog{
    Q_OBJECT
public:
    LoginDialog(void);
    ~LoginDialog(void);
public slots:
    void onAccepted(void);  //ok
    void onRejected(void);  //cancle
private:
    Ui::LoginDialog *ui;
};

#endif //__LOGINDIALOG_H

Write logindialog Cpp file

#include "LoginDialog.h"
LoginDialog::LoginDialog(void){
    ui = new Ui::LoginDialog;
    setupUi(this);
    ui->connect(ui->m_btn, SIGNAL(accepted(void)),
            this, SLOT(onAccepted(void)));
    ui->connect(ui->m_btn, SIGNAL(rejected(void)),
            this, SLOT(onRejected(void)));
}
LoginDialog::~LoginDialog(void){
    delete ui;
}
void LoginDialog::onAccepted(void){
    if (ui->m_username->text() == "admin" && ui->m_passwd->text()=="123456"){
        qDebug()<<"login success";
        close();
    }else{
        QMessageBox msgBox(
            QMessageBox::Critical,
            "Error",
            "username or password uncorrect",
            QMessageBox::Ok,
            this
        );
        msgBox.exec();  //Display the message prompt box and enter the event cycle
    }
}
void LoginDialog::onRejected(void){
    QMessageBox msgBox(
        QMessageBox::Question,
        "login",
        "want exit?",
        QMessageBox::Yes | QMessageBox::No,
        this
    );
    if (msgBox.exec()==QMessageBox::Yes){
        close();
    }
}

Write main Cpp file

#include <QApplication>
#include "LoginDialog.h"

int main(int argc, char **argv){
    QApplication app(argc, argv);
    LoginDialog login;
    login.show();
    return app.exec();
}

Qt Creator

qt is an integrated development environment

For the above login function, use creator to complete it. An example is as follows
After creating a new project, double-click logindialog UI file, edit the control, and then save it. After compilation, the UI will be generated in the build XX directory_ logindialog. H file, which is equivalent to the result of uic above.
logindialog.h is the header file of the main function, logindialog CPP is the implementation file of the main functions, and finally main CPP is a file that simply calls a custom class.

Comprehensive example - online chat room

Project architecture
In the client server architecture mode, first run the server listening port, and then run multiple client software to link.
The server and client are two projects created by qt creator respectively, which are placed in two directories and have no relationship with each other.

Server diagram

serverdialog.h file

#ifndef SERVERDIALOG_H
#define SERVERDIALOG_H

#include <QDialog>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>
#include <QTimer>

namespace Ui {
class ServerDialog;
}

class ServerDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ServerDialog(QWidget *parent = 0);
    ~ServerDialog();

private slots:
    //Create slot function corresponding to server button
    void on_createButton_clicked();
    //Slot function in response to client link request
    void onNewConnection();
    //Slot function that accepts client messages
    void onReadyRead();
    //Forward messages to other clients
    void sendMessage(const QByteArray& buf);
    //timer
    void onTimeout(void);
private:
    Ui::ServerDialog *ui;
    QTcpServer tcpServer;
    quint16 port;
    QList<QTcpSocket*> tcpClientList;   //Container: holds all sockets that communicate with clients
    QTimer timer;
};

#endif // SERVERDIALOG_H

serverdialog.cpp file

#include "serverdialog.h"
#include "ui_serverdialog.h"

ServerDialog::ServerDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ServerDialog)
{
    ui->setupUi(this);
    //When a client sends a link request to the server, it sends a signal
    connect(&tcpServer, SIGNAL(newConnection()),
            this, SLOT(onNewConnection()));

    connect(&timer, SIGNAL(timeout()),SLOT(onTimeout()));
}

ServerDialog::~ServerDialog()
{
    delete ui;
}
//Create slot function corresponding to server button
void ServerDialog::on_createButton_clicked(){
    port = ui->portEdit->text().toShort();
    if (tcpServer.listen(QHostAddress::Any, port)==true){
        qDebug()<<"create server success";
        //Disable operation
        ui->createButton->setEnabled(false);
        ui->portEdit->setEnabled(false);
        //Start timer
        timer.start(3000);
    }else{
        qDebug()<<"create server fail";
    }
}

//Slot function in response to client link request
void ServerDialog::onNewConnection(){
    //Get socket for client communication
    QTcpSocket *tcpClient = tcpServer.nextPendingConnection();
    //Save socket to container
    tcpClientList.append(tcpClient);
    //When the client sends a message to the server, the socket sends a signal
    connect(tcpClient, SIGNAL(readyRead()),
            this, SLOT(onReadyRead()));
}

//Slot function that accepts client messages
void ServerDialog::onReadyRead(){
    //Traverse the container to see which client sends messages to the server
    for (int i=0; i<tcpClientList.size(); i++){
        //bytesAvailable: gets the number of bytes of the current socket waiting to read the message
        if (tcpClientList.at(i)->bytesAvailable()){
            QByteArray buf = tcpClientList.at(i)->readAll();
            ui->listWidget->addItem(buf);
            ui->listWidget->scrollToBottom();
            sendMessage(buf);
        }
    }
}

//Forward messages to other clients
void ServerDialog::sendMessage(const QByteArray& buf){
    for (int i=0; i<tcpClientList.size(); i++){
        tcpClientList.at(i)->write(buf);
    }
}

void ServerDialog::onTimeout(void){
    for (int i=0; i<tcpClientList.size(); i++){
        if (tcpClientList.at(i)->state()==QAbstractSocket::UnconnectedState){
            tcpClientList.removeAt(i);
            i--;
        }
    }
}

Client diagram

clientdialog.h file

#ifndef CLIENTDIALOG_H
#define CLIENTDIALOG_H

#include <QDialog>
#include <QTcpSocket>
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>

namespace Ui {
class ClientDialog;
}

class ClientDialog : public QDialog
{
    Q_OBJECT

public:
    explicit ClientDialog(QWidget *parent = 0);
    ~ClientDialog();

private slots:
    //send
    void on_sendButton_clicked();
    //connect
    void on_connectButton_clicked();
    //Slot function executed when the connection with the server is successful
    void onConnected();
    //Slot function executed when the server disconnects
    void onDisconnected();
    //Slot function for receiving chat messages
    void onReadyRead();
    //Slot function executed by network exception
    void onError();

private:
    Ui::ClientDialog *ui;
    bool status;    //Online and offline
    QTcpSocket tcpSocket;   //
    QHostAddress serverIp;
    quint16 serverPort;
    QString username;
};

#endif // CLIENTDIALOG_H

clientdialog.cpp file

#include "clientdialog.h"
#include "ui_clientdialog.h"

ClientDialog::ClientDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ClientDialog)
{
    ui->setupUi(this);
    status = false; //li xian
    connect(&tcpSocket, SIGNAL(connected()), this, SLOT(onConnected()));
    connect(&tcpSocket, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
    connect(&tcpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(&tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(onError()));

}

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

//send
void ClientDialog::on_sendButton_clicked()
{
    QString msg = ui->messageEdit->text();
    if (msg == ""){
        return;
    }
    msg = username += ":" + msg;
    tcpSocket.write(msg.toUtf8());
    ui->messageEdit->clear();
}
//connect
void ClientDialog::on_connectButton_clicked(){
    if (status == false){
        serverIp.setAddress(ui->serverIpEdit->text());
        serverPort = ui->serverPortEdit->text().toShort();
        username = ui->usernameEdit->text();
        //Send a link request to the server, successfully sent connected, failed to send error
        tcpSocket.connectToHost(serverIp, serverPort);

    }else{
        //If online, click to disconnect the link
        QString msg = username + ":Leave the chat room";
        tcpSocket.write(msg.toUtf8());
        //Close the link and send a signal disconnected
        tcpSocket.disconnectFromHost();
    }
}
//Slot function executed when the connection with the server is successful
void ClientDialog::onConnected(){
    status = true;
    ui->sendButton->setEnabled(true);
    ui->serverIpEdit->setEnabled(false);
    ui->serverPortEdit->setEnabled(false);
    ui->usernameEdit->setEnabled(false);
    ui->connectButton->setText("disconnect");

    QString msg = username + ":Enter the chat room";
    tcpSocket.write(msg.toUtf8());
}

//Slot function executed when the server disconnects
void ClientDialog::onDisconnected(){
    status = false;
    ui->sendButton->setEnabled(false);
    ui->serverIpEdit->setEnabled(true);
    ui->serverPortEdit->setEnabled(true);
    ui->usernameEdit->setEnabled(true);
    ui->connectButton->setText("connect");
}

//Slot function for receiving chat messages
void ClientDialog::onReadyRead(){
    if (tcpSocket.bytesAvailable()){
        QByteArray buf = tcpSocket.readAll();
        ui->listWidget->addItem(buf);
        ui->listWidget->scrollToBottom();
    }
}

//Slot function executed by network exception
void ClientDialog::onError(){
    //errorString() gets the cause of the network exception
    QMessageBox::critical(this, "ERROR", tcpSocket.errorString());

}

Operation effect

Keywords: Qt Machine Learning Decision Tree

Added by andym01480 on Mon, 07 Mar 2022 03:36:36 +0200