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