文章目录
- 信号槽与事件
- QT多线程
- 概述
- 原理
- 完成倒计时程序
- UDP回显服务器
- 服务端
- 客户端
信号槽与事件
在之前的信号槽中,已经有了一个基本的认识,那么对于QT中事件的理解其实就非常的类似,当用户进行某种操作的时候,就会触发事件,去执行一些对应的方法
QT对于事件又进行了封装,就有了信号槽,所以信号槽本身就是对于事件的封装,但是在有些情况下可能信号槽不能覆盖到,所以就需要自己来重写事件的情况,来进行处理该事件
比如当鼠标进入和离开某个区域时,都会有对应的事件,如果此时这个事件不满足用户的要求,就可以对于这些事件进行对应的处理
QT多线程
概述
本质上来说,这个线程和Linux的多线程是一样的,和线程相关的原理和一些注意点都是Linux线程有关,因此这里不再讲述Linux多线程,只是对于QT中的Linux多线程的用法
原理
在QThread中,一个原理是实例一个对象,然后指定线程的入口函数,创建一个子类,重写其中的run函数,这样就可以使用多态的原理来进行调用
完成倒计时程序
创建一个新的线程,在新线程中进行计时,每一个循环就减一次,然后打印到界面上,就可以完成一个倒计时的效果
重写Thread类
#include "thread.h"Thread::Thread()
{}// 重写run函数
void Thread::run()
{// 只允许一个线程来更新界面// 因此基本思路是每到了一秒就去提醒一下信号槽,让主界面去更新for(int i = 0; i < 10; i++){sleep(1);emit notify();}
}
设置主线程
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 连接信号槽connect(&thread, &Thread::notify, this, &MainWindow::handle);// 启动线程thread.start();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{// 在这里处理基本逻辑,当遇到信号后,就获取屏幕的值,再-1后设置回去int value = ui->lcdNumber->intValue();ui->lcdNumber->display(value - 1);
}
UDP回显服务器
服务端
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QNetworkDatagram>
#include <QString>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);socket = new QUdpSocket(this);this->setWindowTitle("服务器");// 连接信号槽connect(socket, &QUdpSocket::readyRead, this, &MainWindow::handle);// 绑定端口号bool ret = socket->bind(QHostAddress::Any, 8888);if(!ret){QMessageBox::critical(this, "服务器错误", socket->errorString());return;}
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::handle()
{// 处理逻辑主要就是,接收消息,封装响应,把响应发回去// 接收消息const QNetworkDatagram& netDataPro = socket->receiveDatagram();const QString& request = netDataPro.data();// 封装响应const QString& response = process(request);// 把响应发回去QNetworkDatagram responseprogram(response.toUtf8(), netDataPro.senderAddress(), netDataPro.senderPort());socket->writeDatagram(responseprogram);// 把日志打印到界面上QString log = "[" + netDataPro.senderAddress().toString() + ":" + QString::number(netDataPro.senderPort()) + "] req: " + request + ", resp: " + response;ui->listWidget->addItem(log);
}const QString &MainWindow::process(const QString &request)
{return request;
}
客户端
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QString>
#include <QNetworkDatagram>const QString& serverip = "127.0.0.1";
const quint16 serverport = 8888;MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("客户端");socket = new QUdpSocket(this);// 添加到信号槽connect(socket, &QUdpSocket::readyRead, this, [=](){// 先把信息收回来const QNetworkDatagram responsedatagram = socket->receiveDatagram();// 把信息提取出来const QString& text = responsedatagram.data();// 加到列表中ui->listWidget->addItem("服务端: " + text);});
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_clicked()
{// 先获取输入框信息const QString& text = ui->lineEdit->text();// 把信息打包成请求QNetworkDatagram requestdatagram(text.toUtf8(), QHostAddress(serverip), serverport);// 把请求发过去socket->writeDatagram(requestdatagram);// 添加到列表框ui->listWidget->addItem("客户端: " + text);// 把消息框清空ui->lineEdit->setText("");
}