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 <QTimerEvent>//定时器事件
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 <QTimer> //定时器类
#include <QTime> //时间类
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 <QDebug> /*** 调试类 ***/
#include <QProgressBar> /*** 进度条类 ***/
#include <QKeyEvent> /*** 按键事件类 ****/
/*** 注意事项:没有处理就返回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 <QUdpSocket> /*** 网络模块 ***/
#include <QMessageBox> /** 标准对话框 ***/
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();//获取 目标 的IP
int 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 <QTcpServer> /** TCP 服务器类 ***/
#include <QTcpSocket> /** 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);
}