QT 系统学习 day04 事件(鼠标,键盘), UDP 通信, TCP 通信,多个定时器,重写绘画事件
创始人
2024-03-26 01:42:26
0

1. 事件  (有 键盘按下, 鼠标按下, 鼠标双击等)

 1.重写键盘按下事件,

  函数: void keyPressEvent(QKeyEvent *event)    /*** 按键按下事件 ***/

   代码:

 void keyPressEvent(QKeyEvent *event) /*** 按键按下事件 ***/{qDebug() << "按下的按键个数:" << event->count() << endl;qDebug() << "按下的按键码:" << event->key() << endl; // 按键码需要参考 Qt:Key 按键枚举表qDebug() << "按下的按键字符:" << event->text() << endl; // 按下按键的字符}

   2.重写键盘 按键松开事件

函数: void keyReleaseEvent(QKeyEvent *event) /*** 按键松开事件 ***/

 void keyReleaseEvent(QKeyEvent *event) /*** 按键松开事件 ***/{qDebug() << "松开的按键个数:" << event->count() << endl;qDebug() << "松开的按键码:" << event->key() << endl; // 按键码需要参考 Qt:Key 按键枚举表qDebug() << "松开的按键字符:" << event->text() << endl; // 按下按键的字符}

3.重写 鼠标按下事件

函数:void mousePressEvent(QMouseEvent *event) /*** 鼠标按下事件 ***/

代码:

void mousePressEvent(QMouseEvent *event) /*** 鼠标按下事件 ***/{/***** 案例:我的鼠标有 左键,右键,前进键和后退键 ****/switch ((unsigned int)event->button()) { // 获取按下的按键case Qt::LeftButton:mouse_flag = true;qDebug() << "鼠标左键按下" << endl;break;case Qt::RightButton:qDebug() << "鼠标右键按下" << endl;//Menu->exec(QCursor::pos());         //QCursor::pos()获取鼠标的全局坐标//Menu->exec(event->globalPos());       //event->globalPos()获取鼠标的全局坐标break;case Qt::BackButton:qDebug() << "鼠标后退键按下" << endl;break;case Qt::ForwardButton:qDebug() << "鼠标前进键按下" << endl;break;case Qt::MiddleButton:qDebug() << "鼠标中间滚轮键按下" << endl;break;}}

4.重写 鼠标松开事件

函数: void mouseReleaseEvent(QMouseEvent *event)     /*** 鼠标松开事件 ***/

代码:

void mouseReleaseEvent(QMouseEvent *event)     /*** 鼠标松开事件 ***/{/***** 案例:我的鼠标有 左键,右键,前进键和后退键 ****/switch ((unsigned int)event->button()) { // 获取松开的按键case Qt::LeftButton:mouse_flag = false;qDebug() << "鼠标左键松开" << endl;break;}}

5.重写鼠标双击事件

函数:void mouseDoubleClickEvent(QMouseEvent *event); /*** 鼠标双击事件 ***/

代码:

void mouseDoubleClickEvent(QMouseEvent *event)//鼠标双击事件{qDebug()<<"鼠标双击事件";}

6.重写鼠标移动事件

函数:void mouseMoveEvent(QMouseEvent *event);        /*** 鼠标移动事件 ***/

代码:

因为要用到 this 所以我们在 .h 文件里面声明,.cpp 文件里面实现 .


void Widget::mouseMoveEvent(QMouseEvent *event)
{/***** 思考:为什么需要按键按下并鼠标移动才触发时间 ? ***** QWidget 默认关闭焦点,所以需要打开焦点* 使用这个函数:this->setMouseTracking(true); // 设置鼠标焦点使能* ***********************************************/if(this->mouse_flag){qDebug() << "全局坐标:" << event->globalPos() << endl;//全局变量是整个电脑屏幕 处在的位置qDebug() << "局部坐标:" << event->localPos() << endl;//局部变量是自己打开的窗口的处在的位置}
}

7.重写鼠标中间/滚轮事件

函数:  void wheelEvent(QWheelEvent *event)            /*** 鼠标中间/滚轮事件 ***/

代码:

 void wheelEvent(QWheelEvent *event)            /*** 鼠标中间/滚轮事件 ***/{/**** 获取滚动的距离 ******* QPoint angleDelta()* ******************************************************/QPoint point = event->angleDelta(); //获取距离qDebug() << "距离:" << point.y() << endl;qDebug() << "方向:" << (point.y() >= 0 ? "向前" : "向后") << endl;}

8.重写定时器事件 

函数:  void timerEvent(QTimerEvent *)

代码:

#include //定时器事件
public: /*** 定时器事件 ****/void timerEvent(QTimerEvent *){static int count = 0;//qDebug() << "闹钟的数量:" << ++count << endl;}

启动定时器事件的 代码

   /***** 定时器事件 *******/this->startTimer(1000); // 1000 毫秒 = 1秒钟 , 计数到1秒则触发事件 timerEvent

9. 重写绘图事件  (画圆,画点,画线,)

函数:  void paintEvent(QPaintEvent *) /**** 绘图事件 ***/

代码:

void paintEvent(QPaintEvent *) /**** 绘图事件 ***/{QPainter p(this);/***** 画刷 ********************************/QBrush Brush = p.brush(); // 获取画家手上的刷子Brush.setColor(QColor(255,0,0));p.setBrush(Brush);/***** 画笔 ********************************/QPen Pen = p.pen();Pen.setColor(QColor(0,255,0)); //设置画笔颜色Pen.setWidth(4); //设置画笔大小Pen.setStyle(Qt::DashLine); //设置画笔样式p.setPen(Pen);p.setFont(QFont("宋体",16));/**** 绘制形状 ****/p.drawPoint(200,200); //画点p.drawLine(QPoint(100,100),QPoint(200,200)); //画线p.drawRect(100,100,100,100); //画矩形 drawRect(int x, int y, int w, int h)p.drawEllipse(QPoint(150,150),50,50); //画圆 (const QPoint ¢er, int rx, int ry)p.drawImage(QPoint(200,200),QImage("://QQ图片20221125090254.png"));//画一张图片Pen.setColor(QColor(0,0,255)); //设置画笔颜色p.setPen(Pen);p.setFont(QFont("宋体",16));p.drawText(QPoint(300,20),"老师的牛逼");//形成一个文本框,里面写了 文字}


2.多个定时器

#include //定时器类

#include //时间类

1. 定义指针的变量     QTimer *Timer1;//定时器类对象

2.实列化对象    Timer1 = new QTimer(this);

3.建立信号连接 等定时器到了时间就, 发出信号     connect(Timer1,SIGNAL(timeout()),this,SLOT(slot_Timer1()));

4. 打开定时器  Timer1->start(100); // 100毫秒 = 0.1 毫秒 , 计数到0.1秒则触发 timeout() 信号


3.   将控件安装事件过滤器  (就是发生了事件  上面的事件都算, 重新交给一个人来处理,。  本来是交给他的父类的!! )

1.给控件加上  一个捕获事件的能力,(本来捕获事件的能力都是 widget 界面的)

  ui->progressBar->grabKeyboard();//设置键盘捕获事件

2.给控件安装事件过滤器

  /*** 将控件安装事件过滤器 ***/ui->progressBar->installEventFilter(this);;; //ui->progressBar 进度条控件的事件交给 Widget 去处理

   3.设置控件获取焦点 (因为平时焦点都是在 界面上 ,而我们需要让 控件获取焦点的能力)

焦点窗口

所谓的焦点窗口,指的是当前时刻拥有键盘输入的窗口。

补充两个概念,活动窗口和前景窗口。活动窗口,指的是当前时刻与用户进行交互的窗口;前景窗口,指的是显示器最顶层窗口,前景窗口永远在其他窗口上方,不被遮挡。
设置焦点可以让应用更便捷。比如当你打开百度主页或其他带有编辑框的页面时,不需要先用鼠标点击编辑框就可以直接输入文字等信息到其中。这就是由于搜索框设置了焦点。
这就是说 有了焦点,我们把鼠标放到控件上,窗口就知道我们操作的是 控件,假如没有焦点,那么窗口就不知道。
  ui->progressBar->setFocus();//控件获取焦点

4.重写 事件过滤器

函数:bool eventFilter(QObject *watched, QEvent *event); /**** 事件过滤 ****/

代码:


#include  /*** 调试类 ***/
#include  /*** 进度条类 ***/
#include     /*** 按键事件类 ****/
/*** 注意事项:没有处理就返回false,处理了就返回true   完成了也可以返回 false 可以让下一级来操作  ***/
bool Widget::eventFilter(QObject *watched, QEvent *event)
{if(watched == ui->progressBar) // 说明是我的 进度条控件 发出的事件{QProgressBar *ProgressBar = (QProgressBar *)watched;//把类型强转/*** QEvent 事件基类中有一个 type() 函数获取事件的类型,可以参考 QEvent::Type 枚举表 ****/if(event->type() == QEvent::KeyPress) /*** 按键事件 ****/{qDebug() << "进度条控件发出事件" << endl;QKeyEvent *KeyEvent = (QKeyEvent *)event;qDebug() << "按下的按键:" << KeyEvent->text() << endl;int x = ProgressBar->x();int y = ProgressBar->y();switch ((unsigned int)KeyEvent->key()) {case Qt::Key_Up:ProgressBar->move(x,y-10);return true;case Qt::Key_Down:ProgressBar->move(x,y+10);return true;case Qt::Key_Left:ProgressBar->move(x-10,y);return true;case Qt::Key_Right:ProgressBar->move(x+10,y);return true;}}}return false; /*** 没有处理 ***/
}


4.UDP 网络连接

1.在学习UDP的时候,我们需要在

 2. 学习UDP  的建立步骤

1.头文件 : #include /*** 网络模块 ***/
                        #include /** 标准对话框 ***/

 2. 建立UDP 网络套接字对象   QUdpSocket *UdpSocket; 

3.实列话对象  UdpSocket = new QUdpSocket(this);

4. 知道 UDP 的函数 并且运用 


/******************* QUdpSocket 类 ******************* 绑定:*      ip地址和端口号 : bool bind(const QHostAddress &address, quint16 port = 0, BindMode mode = DefaultForPlatform);*      默认本地ip:     bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform);* 发送:qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)* 接收:qint64 readDatagram(char *data, qint64 maxlen, QHostAddress *host = Q_NULLPTR, quint16 *port = Q_NULLPTR);* 信号函数:*      套接字有数据可读 : void readyRead()* **************************************************/

5. UDP 绑定 IP  和端口号 

我才用的 是 默认本地ip  的绑定


void Udp::slot_pushButton_bind()
{QString ip = ui->lineEdit_ip_bind->text();//获取自己写的 ip 地址int port = ui->lineEdit_port_bind->text().toInt();//获取端口号bool ok = false;//判断自己是否写了 ip 地址if(ip.isEmpty() == true){ok = UdpSocket->bind(port);//采用默认 IP地址绑定。}else{ok = UdpSocket->bind(QHostAddress(ip),port);//采取 自己写的 ip 地址和 端口号 来绑定}if(ok == true){ui->pushButton_bind->setText("绑定成功");ui->pushButton_bind->setEnabled(false);}else{QMessageBox::warning(this,"绑定警告","绑定失败,端口号以被使用");//警告消息对话框}
}

  6. UDP 发送数据

函数: writeDatagram(参数1,参数2,参数3) 

参数1,数据。 (类型需要转 UTF-8)

参数2 , 目标用户的 ip  

参数3   , 目标用户的port 

代码:

void Udp::slot_pushButton_send()
{QString ip = ui->lineEdit_ip_send->text();//获取  目标 的IPint port = ui->lineEdit_port_send->text().toInt();获取 目标的port QString text = ui->textEdit_write->toPlainText();// 获取发送的内容UdpSocket->writeDatagram(text.toUtf8(),QHostAddress(ip),port);//发送数据
}

7.UDP 接收信息,

1. 首先建立连接 

connect(UdpSocket,SIGNAL(readyRead()),this,SLOT(slot_UdpSocket_readyRead()));

参数1 : UDP 的指针, 参数2  有数据可以接收的信号,  

参数3   界面指针             参数4  自己写的槽函数,接收数据

2.直接接收数据


void Udp::slot_UdpSocket_readyRead()
{char *buf = new char[1024]; /*** 申请空间 ***/memset(buf,0,1024);//清除空间,防止有脏数据QHostAddress host; //对方的主机quint16 port;      //对方的端口UdpSocket->readDatagram(buf,1024,&host,&port);//我这里有一个疑问,接收的空间 ,没有数据大咋办,一次接收后,还会有第二次接收吗??ui->textEdit_read->append(buf);delete buf; /*** 释放空间 ***/
}


5.TCP 网络传输数据  (服务器部分)

1.头文件

#include   /** TCP 服务器类 ***/
#include   /** TCP 套接字类 ***/

2. 建立TCP  网络套接字对象   TCPsever *sevser

3.实列话对象   sevser = new TCPsever;

4. 知道 TCP 服务器  的函数 并且运用 


/********** QTcpServer 服务器类 ******** ①绑定监听 : bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)* ②等待响应|用户连入信号 : void newConnection()* ③接入已挂起的客户端 : QTcpSocket *QTcpServer::nextPendingConnection()* **********************************************************************************/
/********** QTcpSocket 套接字类 ********* 连接: void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite)* 断开: void disconnectFromHost()* 读取:*      QByteArray read(qint64 maxSize)     指定读取长度*      QByteArray readAll()                读取全部内容* 写入:*      qint64 write(const char *data)              发送字符串内容*      qint64 write(const QByteArray &byteArray)   发送QByteArray内容* 信号:*      void readyRead() 有数据可读发出信号*      void connected() 连接成功信号*      void disconnected() 断开连接信号* 数据函数:*      qint64 QAbstractSocket::readBufferSize() 缓存区大小*                              ***** 缓冲区可读内容长度** 获取IP地址:QHostAddress peerAddress() const* 获取端口号:quint16 peerPort() const* ***************************************************************************************/
/********************* QHostAddress 类 **************************************************** QHostAddress::Any 枚举值,双栈协议* QString QHostAddress::toString() const 的ip地址转字符串* **************************************************************************************/

5. 申请服务器TCP类空间 QTcpServer*  TcpServer = new QTcpServer(this);


6. TCP  绑定 ip 和端口号 

函数 :listen(QHostAddress::Any,port); 

参数1    QHostAddress类提供一个IP地址。

QHostAddress类  这个类提供一种独立于平台和协议的方式来保存IPv4和IPv6地址。

参数2  这个电脑可以绑定的 端口号 

代码:

void TCPsever::slot_pushButton_bind()
{QString ip = ui->lineEdit_ip->text();int port = ui->lineEdit_port->text().toInt();TcpServer->listen(QHostAddress::Any,port); //双栈绑定
}TCPsever::~TCPsever()
{delete ui;
}

7.为客户的连接 建立信号连接 (目的 当有客户连接的时候,我们可以知道并且获取 客户的 ip 和 端口号 )

  connect(TcpServer,SIGNAL(newConnection()),this,SLOT(slot_TcpServer()));

参数1    TCP类空间的指针 , 参数2  用户连接信号

8.读取数据 建立连接  

connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(slot_TcpSocket_readyRead()));

参数1   TCP类空间的指针      参数2  有数据可以读取的信号函数

9.发送过来的数据读取

代码:

void TCPsever::slot_TcpSocket_readyRead()
{QTcpSocket *TcpSocket = (QTcpSocket *)sender();QByteArray buf = TcpSocket->readAll();ui->textEdit->append(buf);
}



6.TCP 网络传输数据  (客户端部分)

这里只有函数可以讲

1.建立对象,并且实列化对象   QTcpSocket *TcpSocket; /*** TCP套接字类指针 **/ 

                                                     TcpSocket = new QTcpSocket(this);  

2.关于客户端的函数, 

/********** QTcpSocket 套接字类 ********* 连接: void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite)* 断开: void disconnectFromHost()* 读取:*      QByteArray read(qint64 maxSize)     指定读取长度*      QByteArray readAll()                读取全部内容* 写入:*      qint64 write(const char *data)              发送字符串内容*      qint64 write(const QByteArray &byteArray)   发送QByteArray内容* 信号:*      void readyRead() 有数据可读发出信号*      void connected() 连接成功信号*      void disconnected() 断开连接信号* 数据函数:*      qint64 QAbstractSocket::readBufferSize() 缓存区大小*                              ***** 缓冲区可读内容长度* ***************************************************************************************/

3.连接服务端 

函数:void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite)

参数1  IP   参数2  端口号

代码:

void TCPclient::slot_pushButton_connect()
{QString ip = ui->lineEdit_ip->text();//获取要连接的服务器的 ip int port = ui->lineEdit_port->text().toInt();//获取要连接的服务器的 端口号TcpSocket->connectToHost(QHostAddress(ip),port);//连接服务器
}

4. 为连接服务器成功做准备, 主要是建立一个信号连接,来知道,与服务器连接成功了

 connect(TcpSocket,SIGNAL(connected()),this,SLOT(slot_TcpSocket_connected()));

第二个参数 是 一个连接服务器成功的信号, 

代码:


void TCPclient::slot_TcpSocket_connected()
{ui->pushButton_connect->setText("连接成功");ui->pushButton_send->setEnabled(true); //使能发送按钮
}

5.为服务器断开连接做准备, 主要是建立一个信号连接,来知道,与服务器服务器断开连接了

 connect(TcpSocket,SIGNAL(disconnected()),this,SLOT(slot_TcpSocket_disconnected()));

代码:

void TCPclient::slot_TcpSocket_disconnected()
{ui->pushButton_connect->setText("已断开连接");ui->pushButton_send->setEnabled(false); //使能发送按钮
}

6.客户端向服务端发送数据 

函数:write(text.toUtf8());

代码:


void TCPclient::slot_pushButton_send()
{QString text = ui->textEdit_send->toPlainText();//读取要发送的数据TcpSocket->write(text.toUtf8());//向服务器发送数据
}

7.客户端 读取 服务端发送的数据 

建立连接

 connect(TcpSocket,SIGNAL(readyRead()),this,SLOT(slot_TcpSocket_readyRead()));//和之前一样

代码:

void TCPclient::slot_TcpSocket_readyRead()
{QByteArray buf = TcpSocket->readAll();//读取数据ui->textEdit_read->append(buf);
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...