网站搭建好之后提示网页走丢了,现货交易十大平台,广州平台公司,室内设计大学排名榜目录
前言#xff1a;Qt与操作系统的关系
一、Qt事件
1.事件介绍
2.事件的表现形式
常见的Qt事件#xff1a;
常见的事件描述:
3.事件的处理方式
处理鼠标进入和离开事件案例
控件添加到对象树底层原理
二、鼠标事件
1.鼠标按下和释放事件#xff08;单击#x…目录
前言Qt与操作系统的关系
一、Qt事件
1.事件介绍
2.事件的表现形式
常见的Qt事件
常见的事件描述:
3.事件的处理方式
处理鼠标进入和离开事件案例
控件添加到对象树底层原理
二、鼠标事件
1.鼠标按下和释放事件单击
2.鼠标双击事件
3.鼠标移动事件
4.鼠标滚轮滚动事件
三、键盘事件
1.键盘按下单个按键事件
2.组合键按下事件
四、定时器事件
使用说明
Demo设置倒计时程序
五、窗口相关事件
1.窗口移动事件
2.窗口大小改变事件
六、事件分发器与事件过滤器 前言Qt与操作系统的关系 Qt与操作系统的关系虽然说Qt是一个跨平台的C开发框架但是Qt的很多能力其实都是操作系统提供的而且Qt应用程序也是运行在操作系统上的也需要操作系统的支持。只不过是Qt封装了系统调用的API而已不同平台下封装不同的系统调用实现了跨平台的能力。 对于事件、文件操作、多线程编程、网络编程等模块的编程下Qt也是无法独立完成的一定是需要操作系统的支持所以Qt的很多业务实现都需要操作系统提供很多的帮助。 一、Qt事件
1.事件介绍 对于信号槽来说用户进行的各种操作都可能会产生信号可以给信号绑定槽函数那么当信号触发的时候就会自动的调用执行对应的槽函数了。事件和信号槽很相似用户进行各种操作的时候也会产生事件同样可以给事件关联上处理函数或者说处理逻辑当事件触发的时候就能够执行对应的函数/逻辑了。 信号槽机制是Qt的机制而事件是操作系统的概念Qt同样把操作系统的事件机制进行了封装就变成了Qt的事件机制而信号槽机制其实也就是Qt事件的更一步的封装机制。在实际开发当中绝大多数的情况都是使用Qt的信号槽机制进行交互的。 但是会有一些特殊情况可能用户的一些行为操作Qt中没有提供对的信号也就没法关联信号槽了此时就需要通过重写事件处理函数的形式来手动处理事件的相应逻辑了。所以说事件机制可以让程序员根据实际的需求更加深度化的去定制用户操作对应的处理逻辑了。 2.事件的表现形式 Qt中的是使用一个对象来表示一个事件的所有的Qt事件类都是继承于QEvent抽象类。事件的发出是通过操作系统或者Qt平台本身在代码逻辑下发出的。一些事件是由用户操作后发出例如按下键盘按下鼠标等。还有一些事件是由程序或系统本身发出的例如定时器事件等。
常见的Qt事件 对于不同的事件关注的点是不一样的所以说类内部的实现提供的接口方法也是不一样的。
常见的事件描述:
事件说明鼠标事件鼠标左键、鼠标右键等各种按键、鼠标滚轮、鼠标移动、按键的按下和松开键盘事件 按键类型、按键按下和松开定时器事件定时事件到达进入离开事件 鼠标进入和离开区域滚轮事件鼠标滚轮滚动绘屏事件重绘屏幕的某些部分显示隐藏事件窗口的显示和隐藏移动事件窗口位置的变化窗口事件是否为当前窗口大小改变事件窗口大小改变焦点事件键盘焦点的移动 3.事件的处理方式 对于信号来说是定义槽函数并和信号进行关联而事件的处理不太一样需要重写该事件的处理函数来实现事件的处理。具体是使用多态的机制创建子类继承要监控的父类在子类中重写事件处理函数后续事件触发的时候就会通过多态的机制执行到重写的子类事件执行函数了。 为什么非要创建子类在子类中重写事件处理函数呢因为对于每个控件的相同事件有着不同的处理逻辑所以需要为每一个控件定制他自己独有的处理方法当然所有控件用一个也是可以的直接在QWidget类中重写事件处理函数就可以了这样就会使所有的控件同一事件的处理操作一样了。
处理鼠标进入和离开事件案例 首先创建子类然后再子类中定义上图中的两个事件处理函数enterEvent是鼠标进入事件leaveEvent是鼠标离开事件。之后可以代码中创建我们的子类控件也就是创建一个父类指针指向子类的对象然后鼠标进入和离开通过多态机制就会执行子类重写的函数了。 也可以通过ui界面的方式我们拖拽一个父类控件然后把控件提升为一个子类控件同时设置该控件的父类即可。原理和上述类似就是把标准控件变为了标准控件的自定义子类控件会继承标准控件的属性和功能。 控件添加到对象树底层原理 创建一个QPushButton之后他会调用QPushButton的构造函数QPushButton继承于QAbstractButton所以会调用QAbstractButton的构造函数QAbstractButton继承于QWidget所以对调用QWidget的构造函数会一直层层调用直到调用的QObject的时候位置他是所有类的基类那么调用之后parent参数也层层传递给了QObject类通过参数的值来判断是否要添加到对象树以及添加到什么位置上。 二、鼠标事件 Qt中的鼠标事件是由QMouseEvent类来实现的当鼠标移动和操作都会产生鼠标事件。
1.鼠标按下和释放事件单击 鼠标按下事件处理函数是mousePressEvent鼠标释放事件处理函数是mouseReleaseEvent他带了一个event参数内部就带有了鼠标的各种属性例如鼠标点击/释放的位置、哪个按键点击/释放的等等。 如何判断是操作的鼠标哪个键呢Qt中提供了一些MouseButton枚举变量对应的就是鼠标的哪一个按键了。Qt::LeftButton左键、Qt::RightButton右键、Qt::MidButton鼠标滚轮按键。 对于mousePressEvent处理函数来说 无论是鼠标的左键、右键、滚轮等等按键都能进行触发但是对于一些游戏鼠标的特殊按键是不一定的因为那些按键是通过特定的驱动程序转化为一些其他操作了不一定是原生的鼠标点击操作。 对于QPushButton的clicked()信号就是对应的一次鼠标按下和一次鼠标释放事件。
void Label::mousePressEvent(QMouseEvent *event)
{if(event-button() Qt::LeftButton){qDebug() 按下左键;}else if(event-button() Qt::RightButton){qDebug() 按下右键;}//当前ev对象就包含了鼠标点击位置的坐标qDebug() event-x() , event-y();//相对于屏幕左上角的坐标qDebug() event-globalX() , event-globalY();
}void Label::mouseReleaseEvent(QMouseEvent *event)
{if(event-button() Qt::LeftButton){qDebug() 释放左键;}else if(event-button() Qt::RightButton){qDebug() 释放右键;}//当前ev对象就包含了鼠标点击位置的坐标qDebug() event-x() , event-y();//相对于屏幕左上角的坐标qDebug() event-globalX() , event-globalY();
} 2.鼠标双击事件 鼠标双击事件的处理函数是mouseDoubleClickEvent函数使用方法和上述单击的没什么区别。对于双击左键的事件间隔是跟随系统的当鼠标双击的时候单击事件也会触发当第一次点击的时候就会触发单击操作第二次点击的时候会触发双击操作所以如果处理不好可以会出问题。 3.鼠标移动事件 鼠标移动的事件处理函数是mouseMoveEvent函数所有的操作和上述也都是一样的都是基于event参数进行的操作。但是我们实现完之后会发现我们想在鼠标移动的时候打印鼠标所处的位置却打印不出来是为什么呢 因为鼠标移动不同于鼠标点击操作因为鼠标移动会产生大量的事件在进行一些复杂的程序的时候一直触发鼠标移动事件会降低程序的效率所以说为了保证效率默认是不会对鼠标的移动进行追踪也就是说鼠标移动的时候不会调用鼠标移动处理函数。如何打开追踪呢 void setMouseTracking(bool enable); 鼠标移动事件的追踪是有区域限制的而且没有继承关系如果说在QPushButton中设置的那么QWidget的窗口是无法追踪的如果在QWidegt窗口设置的那么QPushButton是无法追踪的但是这样的化QWidget也是无法追踪的他会拦截事件。 4.鼠标滚轮滚动事件 鼠标滚轮滚动的事件处理函数是wheelEvent函数他的参数不是QMouseEvent类型了而是变成了一个QWheelEvent滚轮类。该类中保存了一个滚轮移动的距离正数表示向前移动负数表示向后移动可以使用该类中的delta()函数来获取滚动的距离。 intQGraphicsSceneWheelEvent::delta() const; 三、键盘事件 Qt中的键盘事件是由QKeyEvent类来实现的Qt中的QShortCut设置快捷键的类就是Qt信号槽机制封装过的一个用于获取键盘按键的一种方式。 键盘事件和鼠标事件最大的不同在于键盘事件的触发首先需要窗口获得焦点之后才会触发对应的键盘事件。
1.键盘按下单个按键事件 键盘按下事件的处理函数是KeyPressEvent函数函数中的参数就是键盘的各种属性内容参数内部就包含了用户具体输入的内容了。 可以通过QKeyEvent类中的key函数获取到输入的内容。 当我们打印key的返回值的时候会发现我们输入的内容都变成了一些数字在Qt中把键盘的所有按键都用一个枚举变量Key定义成了各种值的数字。使用Qt::xxx便是键盘按键。 void Widget::keyPressEvent(QKeyEvent *event)
{// 获取键盘输入按键int key event-key();//判断键盘是否输入的是按键Aif(key Qt::Key_A){qDebug() 按下了A键;}
}上述的枚举值Key_A等是不会区分大小写的键盘属于物理按键而大小写属于的是字符的概念通过检测键盘shift的状态来区分用户输入的大小写而并非这些枚举变量值区分大小写。 2.组合键按下事件 按下组合键也是属于键盘输入事件也是由keyPressEvent函数进行事件处理对于组合键一般都是ctrl、shift、alt等等组合操作。Qt内置了对于键盘输入是否使用了组合键的判断并不是直接判断而是把上述的ctrl、shift、alt等按键定义为了修改键并为这些修改键定义了在了Qt内部的KeyboardModifiter枚举变量中。同时在QKeyEvent类中提供了modifiers函数用来判断是否使用了修改键并返回修改键的值。通过判断是否使用修改键加上普通键就可以判断出来是否使用了组合键了。 Qt::KeyboardModifiers modifiers() const; void Widget::keyPressEvent(QKeyEvent *event)
{// 获取用户输入内容int key event-key();// 判断是否是ctrl Aif(key Qt::Key::Key_A event-modifiers() Qt::ControlModifier){qDebug() 按下了组合键 ctrl A;}
} 四、定时器事件 Qt中进行窗口程序的处理过程中经常要周期性的执行某些操作就需要用到定时器了定时器会在一定时间间隔后去执行某一个任务这种机制在很多场景中都会用到。
使用说明 在Qt中定时器事件类是QTimerEvent类。定时器事件的触发是由定时器完成的那么如何创建定时器呢QObject类中提供了startTimer函数会创建一个定时器对象同时启动定时器并返回一个定时器的唯一标识符对象后续就用该标识符操作定时器了。QObject类还提供了关闭定时器的函数killTimer传递的就是定时器的标识符。 当定时器的计时到了一个周期之后也就是到了设置的时间后会触发定时器事件timerEvent则是定时器定时器事件的处理函数参数就是定时器事件。 int startTimer(int interval, Qt::TimerType timerType Qt::CoarseTimer); // 启动定时器 void killTimer(int id); // 销毁定时器 还需要注意的一点是定时器在一个窗口/类中可以创建多个而这些定时器想要实现的操作是不一样的但是都会调用同一个定时器事件处理函数所以在触发定时器事件后首先要获取定时器事件的内部存放的定时器标识符然后用if-else来确定需要执行什么操作。 但是实际开发中一般都是使用封装好的QTimer类进行定时器的操作当触发定时器事件的时候会产生QTimer::timeout信号之后绑定槽函数实现定时器事件的处理会更方便一些。就不需要我们管理销毁定时器、以及区分是哪个定时器触发的事件了。 QTimer *timer new QTimer(this); connect(timer, QTimer::timeout, this, MyWidget::handleTimeout);timer-start(1000); // 启动定时器
Demo设置倒计时程序 创建一个LCDNumber控件和一个定时器设置定时时间为1s事件到了就调用定时器事件处理函数在函数内部操作LCDNumber控件的值-1就实现了倒计时。 int timerId() const { return id; } #include widget.h
#include ui_widget.hWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);//设置初始值ui-lcdNumber-display(10);//开启定时器_timerId this-startTimer(1000);
}Widget::~Widget()
{delete ui;
}//定时器事件处理函数
void Widget::timerEvent(QTimerEvent *event)
{//获取触发定时器事件是哪一个定时器if(event-timerId() ! this-_timerId){return;}int value ui-lcdNumber-intValue();if(value 0){this-killTimer(this-_timerId);return;}ui-lcdNumber-display(value - 1);
} 五、窗口相关事件
1.窗口移动事件 窗口移动事件的的处理函数是moveEvent函数会带有一个QMobeEvent类型的参数该类内部最主要的接口就是oldPos和pos分别代表的是旧的位置和移动后的新位置。并返回QPoint类型的变量内部就包含了xy坐标系的值。 const QPoint oldPos() coonst; const QPoint pos() const; 2.窗口大小改变事件 窗口大小改变事件的处理函数是resizeEvent函数参数是QResizeEvent和窗口移动事件类似类内部最主要的函数就是oldSize和size表示原来的大小和改变后的窗口大小。返回一个QSize类型的参数内部包含了长度和宽度等数值和上面的QSize合起来就是窗口的geomeory属性。 const QSize oldSize() coonst; const QSize size() const; 六、事件分发器与事件过滤器 事件分发和事件过滤也是属于Qt事件的机制之一对于事件分发器来说会重写一个event函数会直接获取到所有的事件并对这些事件在进行分发处理但是这样很有很大的危险如果说实现过程中某些逻辑不正确的化可能会导致很多的事件无法处理或者无法正确的处理所以说还是推荐对每个事件单独重写事件处理函数甚至说更推荐使用信号槽机制进行处理除非Qt中没有对应的信号机制在使用Qt的事件机制解决问题。 事件过滤会比事件分发好一些事件过滤器对于特定的一些事件就行事件处理不会涉及到所有事件的重写操作。但也不推荐使用也不常见。如果说一个程序在特定场景或特定操作中需要禁用用户的某些操作可以考虑使用事件过滤机制。 事件过滤器一般也是事件分发器使用的时候搭配使用的一个机制先过滤一些事件然后再进行事件的分发处理。