二Qt定时器与文本编辑器制作《QT 入门到实战》
Posted 1_bit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二Qt定时器与文本编辑器制作《QT 入门到实战》相关的知识,希望对你有一定的参考价值。
学习目标
- 了解 qt 的 pixmap
- 了解 qt 的 label 如何显示图片
- 了解定时器的开启
- 了解定时器的关闭
- 了解文件如何进行读取
- 了解 QFileDialog 的使用
- 了解了一个文本编辑器的基本编写
- 巩固了 connect 的使用
一、制作一个图片浏览器
1.1 Pixmap
在 Qt 中使用 Label 可以显示文本,但 Label 不止可以显示文本,还可以用于图片的显示。
首先我们双击 ui 文件,随后在弹出的设计窗口中创建一个 Label :
接着拖动这个 label 的宽高,拖动至一个比较好展示图片的大小:
接着我们需要创建一个 QPixmap 对象。
QPixmap 类是一个用于处理图像的类,创建一个 QPixmap 传入对应的路径即可得到这个这个类对于这个图片处理的对象,QPixmap 更适合处理小图片。
如下就是一个创建 QPixmap 类对象的方法:
QPixmap pix("D:\\\\developer\\\\QT\\\\pro\\\\01\\\\04\\\\04\\\\img\\\\1.png");
在此传入了一张图片进行对象初始化,接下来就可以直接将这个图片显示在 label 之上。
使用 ui 指定需要显示图片的控件 label,在 label 中有一个 setPixmap 方法,通过 setPixmap 传入 QPixmap 的对象 pix 即可对图片进行设置:
代码如下:
ui->label->setPixmap(pix);
此时代码如下:
以上的报错都是 bug,其实代码是正确的,我们此时只需要点击运行,那么即会弹出一个窗口,上面使用了 label 显示一张图片:
1.2 定时器
现在已经知道了如何使用 label 显示图片,那么接下来我们制作一个图片的自动切换功能,那么必然是需要定时去执行图片切换,又或者说我们需要一个功能可以去触发图片的切换,并且多张图片的话,切换是重复执行的,那么就需要一个定时重复执行某个操作的功能。
好消息是在 Qt 中自带了定时器,定时器是一个用于对任务执行定时操作的功能,定时器本身存在于 QWidget 基类之中,由于我们在创建对应的项目后,其类是 QWidget 的子类,那么我们在这个类中就可以直接使用定时器。
那么此时我们需要两个按钮,一个用于定时器的开启,另一个按钮用于定时器的关闭,在此创建两个 pushButton 在 Qt 界面之上,并且更改对应的文本:
接着我们点击开始按钮触发定时器,那么必然是有一个信号(点击),与一个槽函数,在此右键开始按钮选择转到槽,选择 click 事件:
转到槽函数后,我们可以使用以下的代码开启定时器:
this->startTimer();
以上代码中的 startTimer就是表示开启一个定时器,startTimer 在此还需要传入一个间隔参数用来设定间隔的时间,这个时间是以毫秒为单位的,若你设置1s 那么则需要写成 1000:
this->startTimer(1000);
那接下来如何完成图片的切换呢?这时我们需要重写一个方法 timerEvent,timerEvent 方法时定时器响应后所执行的函数,其本身存在但需要重写。
此时我们回到 .h 头文件中声明:
virtual void timerEvent(QTimerEvent *event);
接着回到 .cpp 文件中对此方法进行重写:
void MainWindow::timerEvent(QTimerEvent *event)
在 .cpp 文件中添加以上函数后,我们需要在这个函数中编写切换图片的代码。
此时假如我们有一个文件夹是用于存储需要切换的图片地址,那么我们创建一个 QString 对象进行存储:
QString path("D:\\\\developer\\\\QT\\\\pro\\\\01\\\\04\\\\04\\\\img\\\\");
此时我对应的目录下,文件名是如下格式:
那么在此我可以创建一个变量,这个变量是一个整形变量,用于代表文件名,但是由于每次都需要在之前的名称基础上往上加1,那么我就不能这个定时器触发函数内进行创建,需要在外部创建这个变量,首先到头文件中进行声明:
int picId;
接着再到 cpp 文件中赋初值:
picId=1;
那么此时对于一个图片路径的编写就可以由最开始的 path 文件夹路径加上文件名已经文件名后缀即可,那么就可以写成:
path+=QString::number(picId);
path+=".png";
由于 picId 是 number 类型,并不能直接的对字符串进行拼接,在这里使用 QString::number()
方法对其进行类型转化。
现在图片路径有了,那么接下来必然是现实对应的图片,现实图片我们跟之前的方式一样,创建一个 QPixmap 并且指定对应的 ui 对象 label 对其进行显示即可,代码如下:
QPixmap pix(path);
ui->label->setPixmap(pix);
接下来图片的名称进行增加:
picId++;
这样就可以继续下一张图片了,但在此需要注意,咱们的图片只有3张,那么我们需要使图片索引在超过上限时从头开始,那么就需要进行判断:
picId++;
if(4==picId)
picId=1;
此时该函数的所有代码如下:
void MainWindow::timerEvent(QTimerEvent *event)
QString path("D:\\\\developer\\\\QT\\\\pro\\\\01\\\\04\\\\04\\\\img\\\\");
path+=QString::number(picId);
path+=".png";
QPixmap pix(path);
ui->label->setPixmap(pix);
picId++;
if(4==picId)
picId=1;
此时运行项目点击开始后,图片会发生改变:
1.3 结束定时
接下来我们还需要使这个定时器结束定时,我们需要使用 killTimer 方法,这个方法本身继承自 QWidget 父类,所以直接使用 this 调用即可,那么代码如下:
this->killTimer();
但此时使用 killTimer 会出现错误,killTimer 需要一个某个定时器的 id 作为参数,指定你 kill 掉这个定时器。那定时器 id 如何拿到呢?其实在 startTimer 时将会返回一个定时器 id ,将这个 id 存储起来即可,由于是不同函数内都需要使用这个 id,那么此时我们需要在头文件中创建一个变量对这个 id 进行存储:
接着使用这个变量存储定时器的 id:
接着给结束按钮一个槽函数:
在这个函数中使用 killTimer 方法传入定时器 id 即可:
void MainWindow::on_pushButton_2_clicked()
this->killTimer(timerId);
二、文本编辑器制作
在本章第二点的学习中,我们通过学习文本编辑器制作,从而了解 一般的文件、QFileDialog 以及 巩固自定义事件与槽的知识。
2.1 UI 设计
在正式敲代码之前,我们创建一个项目,设计一下整体的文本编辑器页面。创建好项目后,我们拖动一个 text 的控件拖动到界面之中:
在一般的文本编辑器中,一般以文本编辑为主要功能,接下来我们需要使整个文本编辑器占据整个 UI 的空间区域,那如何进行操作呢?若我们直接设置大小使文本编辑控件以及对应的窗口大小相等,那么这个程序的整个窗口都不能够进行拖放,当在某些设备上整体窗口会导致一些困扰;例如程序界面过大、过小等情况,由于不可拖动大小对用户并不友好。此时我们可以点击整个整个窗口,给整个窗口一个垂直布局,给与垂直布局后,这个窗体内的所有空间将会遵从于这个布局,会使整个空间占据整个宽度,那么在运行之后拖动窗体改变窗体大小,由于窗体内的控件遵循垂直布局的规则,那么窗体内的控件将会遵循父窗体的大小而发生改变,这样就很好的解决了窗口过大、过小而不能更改的问题了。
此时点击整个窗体程序:
选中整个窗体后,这个窗体将会在周围又蓝色小点代表选中,接下来我们点击对应的垂直布局:
点击完毕后整个空间将会占满窗体(这是因为只有一个控件的原因):
接着我们给与对应的菜单添加按钮功能。双击菜单(menubar)可更改名称:
输入如下截图的内容:
按下 enter 键后对应的 &(取地址符)将会消失:
这是因为此时在此处输入对应的取地址符加上某一个“按键”,那么则表示对应的快捷键,例如你在程序之中按下 F 那么将会与点击这个 menu 有相同的操作。
接着我们加入打开文件的 menu :
再接着添加对应的另存为 menu :
还有一个新建文件 menu 忘记添加了,在此添加上:
再接着我们更改一下对应的菜单名称,在 ui 设计窗口右上角更改对应的打开和另存为 menu 名称:
2.2 新建文件
接下来咱们开始编写新建文件操作的功能。
一般新建文件指的是在在窗体之内新建一个文件文档,此时对于文本编辑框的内容是需要清空的,并且文件名也要做一个提示,此时我们给与这个 new_Action 一个自定义的事件与槽。
因为此时你右键这些 menu 并不能直接转到对应的事件槽,所以此时我们需要对应的 connect 函数进行自定义。
此时我们回到 .h 头文件中,对我们自定义的槽函数进行声明:
private slots:
void newActionSlot();
由于此时我们没有给某一个控件一个槽函数,所以此时我们需要自己编写 private 对槽函数的权限进行修饰,并且声明对应的函数。
接着定义完毕后我们需要在 cpp 文件中对其进行实现:
void MainWindow::newActionSlot()
实现后我们使用 connect 对 new_Action 新建文件操作 ui 绑定对应的槽函数:
connect(ui->new_Action,&QAction::triggered,this,&MainWindow::newActionSlot);
此时 connect 中 &QAction::triggered
是指 action 的点击事件,并且绑定了一个 newActionSlot 槽函数,有关 QAction 我们可以在 ui 设计框右上角可以看到 new_Action 是属于一个 Action 对象:
接着,当点击了新建文件的 action 后,我们需要对应的清空文本编辑框的内容,并且更改当前的 Windows 程序的窗体 title,使其有一个提示,那么槽函数的代码可以写成如下:
void MainWindow::newActionSlot()
ui->textEdit->clear();
this->setWindowTitle("新建文本.txt");
以上代码中 setWindowTitle 表示设置当前的窗体程序的标题。我们此时运行程序,在文本编辑框中输入一些内容,随后点击文件选择新建文件,之后将会看见窗体程序的标题发生了改变,并且文本编辑框的内容已被清空:
2.3 打开文件
打开文件的前置操作跟新建文件的操作一样,需要在头文件中声明槽函数、在 cpp 文件中实现槽函数 以及使用 connect 方法连接 menu 以及槽函数。
首先在 .h 文件中声明:
接着就是在 cpp 文件中实现以及使用 connect 自定义事件与槽:
那么接下来我们如何打开文件呢?此时我们需要使用 QFileDialog 类的一个方法打开一个资源选择框,这个方法是 getOpenFileName;首先我们需要在头文件中使用 include 对其引入:
#include <QFileDialog>
随后在 openActionSlot 槽函数中使用 QFileDialog 调用 getOpenFileName,其中 getOpenFileName 一般接收 4 个参数,第一个是资源选择框的父对象是谁,我们可以指定为 this 表示当前程序;第二个参数是一个提示语;第三个参数为资源选择框打开后的默认路径;第四个参数是打开后显示哪些文件。
那么此时代码写成:
QFileDialog::getOpenFileName(this,"选择一个文本",QCoreApplication::applicationFilePath(),"*.txt");
以上代码中的 QCoreApplication::applicationFilePath()
则是表示取到当前的文件路径,最后一个参数则是表示打开后指定显示 txt 类型文件,此时运行程序后,点击打开将会出现资源选择框:
当我们选择某一个文件后,将会弹出对应的文件绝对路径,我们可以使用一个 QString 进行存储,方便接下来读取到所选文件的内容:
QString filename = QFileDialog::getOpenFileName(this,"选择一个文本",QCoreApplication::applicationFilePath(),"*.txt");
若选择文件时并未选中某个文件(取消选择操作、关闭对话框等),其返回值为空,那么在正式读取文件操作之前,我们需要对应的判断当前是否选中文件,此时直接使用 if 判断 filename 的内容是否为 Empty 即可:
if(!filename.isEmpty())
此时表示当 filename 不为空时发生操作。接着在 if 判断内,创建一个 file 对象用于接下来对文件的读取,并且在创建时就需要传入 filename:
QFile file(filename);
接着使用 open 方法对已“装载”路径的 file 对象进行 open,但是由于 open 对象时需要指定你是用什么模式进行读取,可以进行只读、只写等操作,在这里只需要只读,所以使用 QIODevice 方法传入 ReadOnly 作为参数即可:
file.open(QIODevice::ReadOnly);
接着使用 file 对象的 readAll 方法可以一次性读取其文本的内容,并且使用 QByteArray 进行存储;但是要注意,在大文件下不建议这样操作,当前只是作为示例:
QByteArray buf = file.readAll();
最后直接将这个 buf 转为 string 后设置为 textEdit 的文本内容并且关闭 file 读取即可,此时这个槽函数的所有代码如下:
void MainWindow::openActionSlot()
QString filename = QFileDialog::getOpenFileName(this,"选择一个文本",QCoreApplication::applicationFilePath(),"*.txt");
if(!filename.isEmpty())
QFile file(filename);
file.open(QIODevice::ReadOnly);
QByteArray buf = file.readAll();
ui->textEdit->setText(QString(buf));
file.close();
接着我们运行一下程序,选择一个文本文件后进行打开,内容将会显示在当前的 textedit 之上:
2.3 另存为
另存为功能的前置操作跟之前两个功能一致,分别是头文件声明、cpp文件下实现以及connect 链接,在此简述一下步骤。
声明:
void saveActionSlot();
实现:
void MainWindow::saveActionSlot()
链接:
connect(ui->save_Action,&QAction::triggered,this,&MainWindow::saveActionSlot);
前置操作完毕后,我们着重了解如何实现保存功能。
保存功能跟打开文本文件操作类似,都是使用 QFileDialog 进行位置选择,并且最终的保存也是使用 file 对象进行操作,毕竟一个是读一个是写都属于 IO 操作。
既然类型,那么我们在进行保存时的流程都是要打开资源选择框,选择某一个位置进行内容保存,那么铁定是使用 Dialog,在之前是使用 getOpenFileName,是 open操作,那么此时就是 save ,那么就使用 getSaveFileName 方法:
QString filename = QFileDialog::getSaveFileName(this,"选择一个文件",QCoreApplication::applicationFilePath(),"*.txt");
接着同样是判断是否为空:
if(!filename.isEmpty())
接着是使用 file 文件对所选择的位置和保存文件名进行操作,并且此时不是 read 而是 write :
QFile file(filename);
file.open(QIODevice::WriteOnly);
接着使用一个 QString 获取当前的textEdit 的文本:
QString text = ui->textEdit->toPlainText();
创建一个 QByteArray 对象,并且将 textEdit 的文本转为 QByteArray:
QByteArray ba=text.toUtf8();
随后写入文件,并且关闭文件即可,完整代码如下:
void MainWindow::saveActionSlot()
QString filename = QFileDialog::getSaveFileName(this,"选择一个文件",QCoreApplication::applicationFilePath(),"*.txt");
if(!filename.isEmpty())
QFile file(filename);
file.open(QIODevice::WriteOnly);
QString text = ui->textEdit->toPlainText();
QByteArray ba=text.toUtf8();
file.write(ba);
file.close();
此时我们点击保存后将会出现一个资源选择框,我们选择桌面路径,随后点击保存即可对文件进行另存为操作:
查看桌面,文件保存成功并且内容已写入:
总结
本章节主要介绍了如何使用 qt 创建一个图片浏览器以及一个文本编辑器,并且在其中使用 qt QFileDialog 对文件进行选择已经保存,巩固了 qt 项目创建的基本流程;在此基础上巩固了信号与槽,在制作的过程中使用了垂直布局直接并有效的布局了整个 ui 界面。在此基础上还学习了什么是 menu 以及什么是 menu 的 action,并且在 action 上通过使用取地址符的方式创建了对应的快捷按钮,使其文本编辑器的操作更加的方便,这一节还学习了对应的定时器,了解了通过定时器可以对应的创建定时任务,例如制作一个壁纸切换的桌面、定时执行一些重复操作等。
以上是关于二Qt定时器与文本编辑器制作《QT 入门到实战》的主要内容,如果未能解决你的问题,请参考以下文章