作业
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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
void 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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
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到位
// {
// }
}