【QT】系统-上
欢迎来到Cefler的博客😁
🕌博客主页:折纸花满衣
🏠个人专栏:QT
目录
- 👉🏻事件
- QWidget中常见的事件
- 👉🏻处理鼠标事件:leaveEvent和enterEvent
- 👉🏻处理定时器事件
- 👉🏻QFile
- 代码练习
👉🏻事件
QT事件的基本概念是QT框架中用于处理各种动作或状态变化的重要机制。以下是对QT事件基本概念的详细介绍:
🌈一、事件的定义
在QT中,事件(Event)是指由特定对象发生的动作或状态变化,这些动作或变化可以来源于用户操作(如鼠标点击、键盘输入)、系统信号(如定时器超时、网络数据到达)或其他程序内部的事件。事件是QT实现“事件驱动(Event Driven)”程序设计的基础。
🌈二、事件的分类
QT中的事件可以根据其来源和类型进行分类,包括但不限于以下几种:
- 用户输入事件:如鼠标点击(mousePressEvent、mouseReleaseEvent、mouseMoveEvent、mouseDoubleClickEvent等)、键盘输入(keyPressEvent、keyReleaseEvent等)。
- 系统事件:如窗口显示、窗口关闭、定时器事件(QTimerEvent)等。
- 自定义事件:开发者可以根据需要创建并发送自定义的事件。
🌈三、事件的处理机制
QT中的事件处理机制基于事件循环,即应用程序不断地从操作系统接收事件并进行处理。具体过程如下:
- 事件捕获:QT从可能产生事件的地方(如操作系统、定时器、网络等)捕获事件,并将其转化为带有事件信息的对象(QEvent及其子类)。
- 事件分发:QT调用
QCoreApplication::notify()
函数对事件进行分发,将事件对象发送给需要处理事件的对象。 - 事件处理:QObject对象调用
QObject::event()
函数接收事件。event()函数根据事件的类型,调用对应的事件处理函数(如mousePressEvent、keyPressEvent等)。如果事件处理函数返回true,则表示事件已被处理;否则,事件可能会继续传递给父对象或进行其他处理。
🌈 四、事件处理函数的重写
在QT中,几乎所有的事件处理函数都是虚函数,开发者可以在子类中重新实现这些函数以自定义事件的处理逻辑。例如,可以在QWidget的派生类中重写mousePressEvent()函数来处理鼠标按下事件。
🌈 五、事件过滤器
除了重写事件处理函数外,QT还提供了事件过滤器(Event Filter)机制,允许对象在事件到达事件处理函数之前对事件进行拦截和处理。通过安装事件过滤器,开发者可以在不修改原有代码的情况下增加对事件的处理逻辑。
🌈 六、事件与信号槽的区别
虽然事件和信号槽都是QT中用于处理对象间通信的机制,但它们之间存在一些区别:
- 触发时机:事件通常是由系统或用户操作触发的,而信号则是由对象内部状态变化触发的。
- 处理方式:事件处理通常需要开发者显式地编写事件处理函数来响应,而信号槽则通过连接信号与槽函数来实现自动响应。
- 灵活性:事件处理提供了更高的灵活性,因为开发者可以在事件处理函数中执行更复杂的逻辑,并可以通过事件过滤器对事件进行拦截和处理。而信号槽则更加简洁和直观,适用于对象间简单的通信。
综上所述,QT事件是QT框架中用于处理各种动作或状态变化的重要机制。通过理解事件的基本概念、分类、处理机制以及事件处理函数的重写和事件过滤器的使用,开发者可以更加灵活地设计并实现QT应用程序中的交互逻辑。
QWidget中常见的事件
在Qt框架中,QWidget
是所有用户界面对象的基类,它提供了大量的事件处理机制,允许开发者对用户的操作、系统事件等进行响应。以下是一些在QWidget
中常见的事件类型及其简要介绍:
-
键盘事件(Keyboard Events)
keyPressEvent(QKeyEvent *event)
: 当有按键被按下时触发。keyReleaseEvent(QKeyEvent *event)
: 当按键被释放时触发。keyPressEvent
和keyReleaseEvent
允许你处理键盘输入,比如识别用户按下了哪个键。
-
鼠标事件(Mouse Events)
mousePressEvent(QMouseEvent *event)
: 当鼠标按钮被按下时触发。mouseReleaseEvent(QMouseEvent *event)
: 当鼠标按钮被释放时触发。mouseMoveEvent(QMouseEvent *event)
: 当鼠标在窗口内部移动时触发。mouseDoubleClickEvent(QMouseEvent *event)
: 当鼠标双击时触发。
这些事件使得开发者可以响应用户的鼠标点击、移动和双击等操作。
-
焦点事件(Focus Events)
focusInEvent(QFocusEvent *event)
: 当控件获得焦点时触发。focusOutEvent(QFocusEvent *event)
: 当控件失去焦点时触发。
这些事件允许开发者处理控件获得或失去焦点时的行为。
-
定时器事件(Timer Events)
timerEvent(QTimerEvent *event)
: 当定时器触发时调用。你可以通过startTimer()
方法启动一个定时器,并在timerEvent
中处理定时任务。
-
重绘事件(Paint Events)
paintEvent(QPaintEvent *event)
: 当控件需要被重绘时触发。在这个事件中,你应该使用QPainter
来绘制控件的内容。
-
大小改变事件(Resize Events)
resizeEvent(QResizeEvent *event)
: 当控件的大小改变时触发。
-
移动事件(Move Events)
moveEvent(QMoveEvent *event)
: 当控件的位置改变时触发。
-
关闭事件(Close Events)
closeEvent(QCloseEvent *event)
: 当控件接收到关闭请求时触发(例如,用户点击了窗口的关闭按钮)。你可以在这个事件中阻止窗口的关闭。
-
拖放事件(Drag and Drop Events)
- 拖放事件包括
dragEnterEvent
,dragMoveEvent
,dragLeaveEvent
,dropEvent
等,允许你实现复杂的拖放功能。
- 拖放事件包括
-
其他事件
- Qt还提供了许多其他类型的事件,如滚轮事件(
wheelEvent
)、显示和隐藏事件(showEvent
,hideEvent
)、上下文菜单事件(contextMenuEvent
)等,以满足不同的应用需求。
- Qt还提供了许多其他类型的事件,如滚轮事件(
这些事件处理函数通常需要在你的QWidget派生类中重写,以实现对特定事件的自定义响应。通过事件处理,你可以创建出更加丰富和交互性强的用户界面。
👉🏻处理鼠标事件:leaveEvent和enterEvent
从文档说明可以看到,我们如果想重写leaveEvent和enterEvent方法并使用,必须先创建控件的子类,并在子类中重写。
如果我们在ui中添加的是QLabel控件,而自定义了一个MyLabel子类(继承于QLabel),此时重写了事件方法,如果我们想让事件触发,必须将QLabel控件提升为我们自定义的MyLabel类型
之后如果我们想要处理其它事件,就按照这样的套路即可:
比如处理鼠标点击事件,参考下事件方法原型去做
👉🏻处理定时器事件
#include "widget.h"
#include "ui_widget.h"
#include<QKeyEvent>
#include<QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
timeId = this->startTimer(1000);//打开定时器;timeId相当于文件描述符
}
Widget::~Widget()
{
delete ui;
}
void Widget::timerEvent(QTimerEvent *event)
{
if(timeId==event->timerId())
{
int value = ui->lcdNumber->intValue();
if(value<=0)
{
this->killTimer(timeId);//关掉定时器
}
else
{
value-=1;
ui->lcdNumber->display(value);
}
}
}
👉🏻QFile
QFile
是 Qt 框架中用于文件操作的一个类,它提供了对文件系统进行读写操作的接口。QFile
类使得对文件的打开、读写、关闭等操作变得简单而直接。它是 Qt 核心模块(QtCore)的一部分,因此在使用时需要包含对应的头文件 <QFile>
。
🌏 主要特点
- 文件操作:
QFile
提供了对文件的打开、关闭、读写等基本操作。 - 二进制或文本模式:可以指定文件以二进制模式或文本模式打开,以适应不同的数据需求。
- 错误处理:提供了丰富的错误处理机制,可以通过
error()
函数获取最后发生的错误,通过errorString()
获取错误的描述字符串。 - 文件信息:可以获取文件的名称、大小、最后修改时间等基本信息。
- 灵活性:可以与 QIODevice 类的其他子类(如 QBuffer, QTcpSocket 等)一起使用,实现更复杂的文件和网络操作。
🌏 常用成员函数
QFile::QFile(const QString &name)
:构造函数,通过文件名构造一个QFile
对象。bool QFile::open(OpenMode mode)
:打开文件。OpenMode
是一个枚举类型,可以指定文件的打开模式,如只读、只写、追加等。bool QFile::close()
:关闭文件。qint64 QFile::size()
const:返回文件的大小(以字节为单位)。bool QFile::exists()
const:检查文件是否存在。QString QFile::fileName()
const:返回文件的名称。QFile::FileError QFile::error()
const:返回最后发生的错误。QString QFile::errorString()
const:返回最后一次错误的描述字符串。qint64 QFile::read(char *data, qint64 maxlen)
:从文件中读取数据到缓冲区data
中,最多读取maxlen
字节。qint64 QFile::write(const char *data, qint64 len)
:向文件中写入数据。
🌏 使用示例
下面是一个简单的示例,展示了如何使用 QFile
读取文件内容:
#include <QFile>
#include <QTextStream>
#include <QDebug>
int main() {
QFile file("example.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Cannot open file for reading:" << file.errorString();
return -1;
}
QTextStream in(&file);
QString line;
while (!in.atEnd()) {
line = in.readLine();
qDebug() << line;
}
file.close();
return 0;
}
在这个示例中,我们首先尝试以只读和文本模式打开名为 “example.txt” 的文件。如果文件成功打开,我们使用 QTextStream
来逐行读取文件内容,并通过 qDebug()
输出每一行。最后,我们关闭文件。注意,这里使用了 QIODevice::Text
标志来指定以文本模式打开文件,这对于处理文本文件(如 CSV、TXT 等)很有用。如果处理的是二进制文件,则应该省略此标志。
代码练习
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QTextEdit>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void handle1();
void handle2();
private:
Ui::MainWindow *ui;
QTextEdit* edit;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QMenuBar>
#include<QMenu>
#include<QStatusBar>
#include<QAction>
#include<QTextEdit>
#include<QFileDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建菜单栏
QMenuBar* manubar = this->menuBar();
//创建菜单
QMenu* menu1 = new QMenu("文件");
manubar->addMenu(menu1);
//添加菜单选项
QAction* action1 = new QAction("打开");
QAction* action2 = new QAction("保存");
menu1->addAction(action1);
menu1->addAction(action2);
//指定一个输入框
edit = new QTextEdit();
QFont font;
font.setPixelSize(20);
edit->setFont(font);
this->setCentralWidget(edit);
//连接Action的信号槽
connect(action1,&QAction::triggered,this,&MainWindow::handle1);
connect(action2,&QAction::triggered,this,&MainWindow::handle2);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::handle1()
{
//1.读取打开文件的文件路径
QString path = QFileDialog::getOpenFileName();
//2.将读取到的文件路径显示到状态栏
QStatusBar* statusbar = this->statusBar();
statusbar->showMessage(path);
//3.根据用户选择的路径,构造一个QFile对象,并打开文件
QFile file(path);
bool ret = file.open(QIODevice::ReadOnly);
if(!ret)
{
//如果打开失败
statusbar->showMessage(path + " 打开失败!");
}
//4.读取文件内容
QString text = file.readAll();
//5.关闭文件
file.close();
//6.将读取的内容显示到输入框中
edit->setText(text);
}
void MainWindow::handle2()
{
//1.读取打开文件的文件路径
QString path = QFileDialog::getSaveFileName();
//2.将读取到的文件路径显示到状态栏
QStatusBar* statusbar = this->statusBar();
statusbar->showMessage(path);
//3.根据用户选择的路径,构造一个QFile对象,并打开文件
QFile file(path);
bool ret = file.open(QFile::WriteOnly);//
if(!ret)
{
//如果打开失败
statusbar->showMessage(path + " 打开失败!");
}
//4.输写文件内容
const QString& text = edit->toMarkdown();
//5.将输写的内容写进新文件中
file.write(text.toUtf8());
//6.关闭文件
file.close();
}
如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长