作业
1> 登录框实现注册功能,将注册的结果放入文件中(君子作业)
2> 完成文本编辑器的保存工作
void Widget::on_saveBtn_clicked()
{QString fileName = QFileDialog::getSaveFileName(this,"另存为","./","*.txt");if(fileName.isNull()){QMessageBox::information(this,"提示","用户取消了另存文件");return;}QFile file(fileName);if(!file.isOpen()){if(!file.open(QIODevice::WriteOnly)){QMessageBox::critical(this,"错误","打开失败");return;}}QString text = ui->textEdit->toPlainText();file.write(text.toUtf8());file.close();
}
3>
widget.h:
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QDebug>
#include <QTimer>
#include <QTime>
#include <QTextToSpeech>
#include <QMessageBox>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTvoid timerEvent(QTimerEvent *e)override;public:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_startBtn_clicked();void on_stopBtn_clicked();private:Ui::Widget *ui;int time_id1;int time_id2;QTextToSpeech *speecher;
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
#include "ui_widget.h"void Widget::timerEvent(QTimerEvent *e)
{if(e->timerId() == time_id1){QTime sys_t = QTime::currentTime(); //获取系统时间//将QTime类对象转换为字符串QString t = sys_t.toString("hh:mm:ss");//展示到ui界面ui->timeLabel->setText(t);}if(e->timerId() == time_id2){QTime sys_t = QTime::currentTime(); //获取系统时间//将QTime类对象转换为字符串QString t = sys_t.toString("hh:mm:ss");if(t == ui->timeEdit->text()){QString text = ui->textEdit->toPlainText();speecher->say(text.toUtf8());}}
}Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);time_id1 = startTimer(1000);ui->timeLabel->setAlignment(Qt::AlignCenter);ui->timeEdit->setAlignment(Qt::AlignCenter);speecher = new QTextToSpeech(this);
}Widget::~Widget()
{delete ui;
}//启动按钮
void Widget::on_startBtn_clicked()
{time_id2 = startTimer(1000);//提示信息QMessageBox box(QMessageBox::Information,"提示","已启动",QMessageBox::Ok,this);box.exec();
}//停止按钮
void Widget::on_stopBtn_clicked()
{killTimer(time_id2);//提示信息QMessageBox box(QMessageBox::Information,"提示","已停止",QMessageBox::Ok,this);box.exec();
}
效果图:
一、事件处理机制
1.1 事件处理简介
1. 什么是事件? (重点)事件是由窗口系统或者自身产生的,用以响应所发生的
各类事情,比如用户按下并释放了键盘或者鼠标、窗口因
暴露而需要重绘、定时器到时而应有所动作,等等从某种意义上讲,事件比信号更原始,甚至可以认为大多
数信号其实都是由事件产生的。比如一个下压式按钮首先
感受到的是鼠标事件,在进行必要的处理以产生按钮下沉
继而弹起的视觉效果之后,才会发射 clicked()信号2. 如何处理事件? (重点)myWnd(自定义类) -继承-> QWidget -继承-> QObject 1> 当事件发生时,首先被调用的是QObject类中的虚函数event(),其 QEvent型参数标识了具体的事件类型bool QObject:: event (QEvent* e){if (e == mouseEvent){void QWidget::mousePressEvent (QMouseEvent* e)void QWidget:: mouseReleaseEvent (QMouseEvent* e)}if(e == keyEvent){void QWidget::keyPressEvent (QMouseEvent* e)void QWidget:: keyReleaseEvent (QMouseEvent* e)}}2> 作为QObject类的子类, QWidget类覆盖了其基类中的event()虚函数,并根据具体事件调用具体事件处理函数void QWidget::mousePressEvent (QMouseEvent* e)void QWidget::mouseReleaseEvent (QMouseEvent* e)void QWidget::keyPressEvent (QMouseEvent* e)void QWidget:: keyReleaseEvent (QMouseEvent* e)void QWidget::paintEvent (QPaintEvent* e):3> 而这些事件处理函数同样也是虚函数,也可以被 QWidget类的子类覆盖,以提供针对不同窗口部件类型的事件处理4> 组件的使用者所关心的往往是定义什么样的槽处理什么样的信号,而组件的实现者更关心覆盖哪些事件处理函数
1.2 事件处理函数由来
QObject类 提供了那些可以重写的虚函数[virtual] bool QObject::event(QEvent *e) // 参数:事件的类型QWidgets类, 提供了那些可以重写的虚函数[override virtual protected] bool QWidget::event(QEvent *event)[virtual protected] void QWidget::keyPressEvent(QKeyEvent *event)[virtual protected] void QWidget::keyReleaseEvent(QKeyEvent *event)[virtual protected] void QWidget::mouseMoveEvent(QMouseEvent *event)[virtual protected] void QWidget::mousePressEvent(QMouseEvent *event)[virtual protected] void QWidget::mouseReleaseEvent(QMouseEvent *event)[virtual protected] void QWidget::mouseDoubleClickEvent(QMouseEvent *event)[virtual protected] void QObject::timerEvent(QTimerEvent *event)QPainter类 ---> 画家类void SimpleExampleWidget::paintEvent(QPaintEvent *){QPainter painter(this);painter.setPen(Qt::blue);painter.setFont(QFont("Arial", 30));painter.drawText(rect(), Qt::AlignCenter, "Qt");}
1.3 鼠标和键盘事件
1> 事件处理函数
//重写自己的键盘事件处理函数void keyPressEvent(QKeyEvent *event) override; //键盘按下事件处理函数void keyReleaseEvent(QKeyEvent *event) override; //键盘抬起事件处理函数//重写自己的鼠标事件处理函数void mousePressEvent(QMouseEvent *event) override; //鼠标按下事件处理函数void mouseReleaseEvent(QMouseEvent *event) override; //鼠标抬起事件处理函数void mouseDoubleClickEvent(QMouseEvent *event) override; //鼠标双击事件处理函数void mouseMoveEvent(QMouseEvent *event) override; //鼠标移动事件处理函数
2> 案例
1、ui界面
2> 头文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QKeyEvent> //键盘事件处理类
#include<QDebug> //信息调试类
#include<QMouseEvent> //鼠标事件处理类QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//重写自己的键盘事件处理函数void keyPressEvent(QKeyEvent *event) override; //键盘按下事件处理函数void keyReleaseEvent(QKeyEvent *event) override; //键盘抬起事件处理函数//重写自己的鼠标事件处理函数void mousePressEvent(QMouseEvent *event) override; //鼠标按下事件处理函数void mouseReleaseEvent(QMouseEvent *event) override; //鼠标抬起事件处理函数void mouseDoubleClickEvent(QMouseEvent *event) override; //鼠标双击事件处理函数void mouseMoveEvent(QMouseEvent *event) override; //鼠标移动事件处理函数private:Ui::Widget *ui;
};
#endif // WIDGET_H
3> 源文件
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//开启鼠标追踪功能this->setMouseTracking(true);
}Widget::~Widget()
{delete ui;
}//键盘按下事件处理函数的实现
void Widget::keyPressEvent(QKeyEvent *event)
{qDebug()<<"有键盘被按下了,键值为"<<event->key()<<" text:"<<event->text();//可以对事件的键值进行判断switch(event->key()){case 'W':{if(ui->label->y() <= 0-ui->label->height()) //说明该组件已经全部脱离界面{ui->label->move(ui->label->x(), this->height()); //将组件放到最下面}ui->label->move(ui->label->x(), ui->label->y()-1);}break;}}//键盘抬起事件处理函数的实现
void Widget::keyReleaseEvent(QKeyEvent *event)
{qDebug()<<"有键盘被抬起了";
}//鼠标按下事件处理函数的定义
void Widget::mousePressEvent(QMouseEvent *event)
{//判断是哪个鼠标被按下if(event->button() == Qt::LeftButton){qDebug()<<"鼠标左键被按下,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::RightButton){qDebug()<<"鼠标右键被按下,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::MidButton){qDebug()<<"鼠标中间键被按下,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else{qDebug()<<"鼠标其他键被按下,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}
}
//鼠标抬起事件处理函数的定义
void Widget::mouseReleaseEvent(QMouseEvent *event)
{//判断是哪个鼠标被抬起if(event->button() == Qt::LeftButton){qDebug()<<"鼠标左键被抬起,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::RightButton){qDebug()<<"鼠标右键被抬起,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::MidButton){qDebug()<<"鼠标中间键被抬起,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else{qDebug()<<"鼠标其他键被抬起,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}
}
//鼠标双击事件处理函数的定义
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{//判断是哪个鼠标被双击if(event->button() == Qt::LeftButton){qDebug()<<"鼠标左键被双击,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::RightButton){qDebug()<<"鼠标右键被双击,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->button() == Qt::MidButton){qDebug()<<"鼠标中间键被双击,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else{qDebug()<<"鼠标其他键被双击,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}
}
//鼠标移动事件处理函数的定义
void Widget::mouseMoveEvent(QMouseEvent *event)
{//判断是哪个鼠标被移动qDebug()<<"鼠标全局位置:"<<event->globalPos()<<" 组件内位置:"<<event->pos();ui->label->move(event->pos()); //将组件跟随鼠标移动if(event->buttons() == Qt::LeftButton){qDebug()<<"鼠标左键被移动,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->buttons() == Qt::RightButton){qDebug()<<"鼠标右键被移动,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else if(event->buttons() == Qt::MidButton){qDebug()<<"鼠标中间键被移动,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}else{qDebug()<<"鼠标其他键被移动,全局坐标点:"<<event->globalPos()<<" 组件内坐标:"<<event->pos();}
}
1.4 鼠标事件案例
1> 头文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QDebug>
#include<QMouseEvent>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();//重写鼠标事件处理函数void mouseMoveEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;private:Ui::Widget *ui;QPoint p; //记录鼠标相对于组件的位置
};
#endif // WIDGET_H
2> 源文件
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//设置纯净窗口this->setWindowFlag(Qt::FramelessWindowHint);
}Widget::~Widget()
{delete ui;
}//鼠标移动事件处理函数
void Widget::mouseMoveEvent(QMouseEvent *event)
{this->move( event->globalPos() - p );
}//鼠标按下事件处理函数
void Widget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){p = event->globalPos() - this->pos();// 鼠标的全局坐标 组件的全局坐标//qDebug()<<this->pos()<<endl;}else if(event->button() == Qt::RightButton){this->close();}
}
1.5 定时器
1> 所谓定时器,就是当定时器启动后,系统会每隔给定的时间自动调用某些函数
2> 定时器的实现有两个版本:基于属性版本和事件处理版本
3> 基于事件处理函数版本
1、无需实例化对象,调用的函数都是自身提供的
2、调用自身的成员函数startTimer(sec),启动一个定时器,那么系统就会每隔sec毫秒,自动调用自身的定时器事件处理函数,该函数返回创建的定时器id
3、调用自身成员函数killTimer(id)
4、重写定时器事件处理函数:void timerEvent(QTimerEvent *event);
案例
1、ui界面
2、头文件
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QTimerEvent> //定时器事件处理类
#include<QTime>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void timerEvent(QTimerEvent *e) override; //定时器事件处理函数private slots:void on_startBtn_clicked();void on_closeBtn_clicked();private:Ui::Widget *ui;int timer_id; //定时器的id号};
#endif // WIDGET_H
3、源文件
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}//启动定时器按钮对应的槽函数
void Widget::on_startBtn_clicked()
{timer_id = this->startTimer(1000);//功能:启动一个定时器//参数:超时时间,每隔给定的时间后,自动调用定时器事件处理函数//返回值:当前定时器的id号}//关闭定时器按钮对应的槽函数
void Widget::on_closeBtn_clicked()
{this->killTimer(timer_id); //关闭给定的定时器
}//定时器事件处理函数
void Widget::timerEvent(QTimerEvent *e)
{if(e->timerId() == timer_id) //说明定时器1到位{QTime sys_t = QTime::currentTime(); //获取系统时间//将QTime类对象转换为字符串QString t = sys_t.toString("hh:mm:ss");//展示到ui界面ui->timeLab->setText(t);}// if(e->timerId() == timer_id_1) //说明定时器1到位
// {// }
}