请注意,本文是探讨文章而不是教程,是根据实验和分析得出的结果,可能是错的,因此欢迎别人来探讨和纠正。

  这几天对于Qt的事件较为好奇,平时并不怎么常用,一般都是用信号,对于事件的处理,一般都是需要响应键盘按键事件的时候,也用得毫无问题,因此也没怎么注意过,翻了下一般qt的教材《精通Qt4编程(第二版)》,里面12.1是这么说的。

当用户按下一个鼠标键时,这个事件首先被发给当前拥有焦点的窗口部件。

  看到这里,我第一反应是,真的是这样吗,我表示十分地好奇,于是就赶忙试验了一下。代码比较简单,没有注释,相信都能看懂,main函数省略,没什么改动。

  父窗口.h

#ifndef DIALOG_H
#define DIALOG_H #include <QDialog> namespace Ui {
class Dialog;
} class myButton; class Dialog : public QDialog
{
Q_OBJECT public:
explicit Dialog(QWidget *parent = );
~Dialog(); private:
Ui::Dialog *ui;
myButton* btn;protected:
void mousePressEvent(QMouseEvent *);
// bool eventFilter(QObject *, QEvent *);
}; #endif // DIALOG_H

  父窗口.CPP

#include "dialog.h"
#include "ui_dialog.h"
#include "mybutton.h"
#include <QApplication>
#include <QDebug>
#include <QMouseEvent> Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
btn=new myButton(tr("测试父按钮"),this);
} Dialog::~Dialog()
{
delete ui;
} void Dialog::mousePressEvent(QMouseEvent *e)
{
qDebug()<<"void Dialog::mousePressEvent(QMouseEvent *)";
}

  子窗口.h

#ifndef MYBUTTON_H
#define MYBUTTON_H #include <QPushButton> class myButton : public QPushButton
{
Q_OBJECT
public:
myButton(const QString &str,QWidget *parent); signals: public slots: protected: void mousePressEvent(QMouseEvent *e);
}; #endif // MYBUTTON_H

  父窗口.cpp

#include "mybutton.h"
#include <QEvent>
#include <QDebug> myButton::myButton(const QString &str, QWidget *parent) :
QPushButton(str,parent)
{
} void myButton::mousePressEvent(QMouseEvent *e)
{
qDebug()<<"void myButton::mousePressEvent(QMouseEvent *e)";
}

  子窗口和父窗口都安装了鼠标按下事件的响应函数,好了,试一下吧。

  结果是这样的,可以看到,是父窗口的事件处理器被触发了,而焦点窗口应该是子窗口的按钮,那么是否是Qt的某些机制,使得鼠标按键造成了焦点的转移呢,难道其实焦点在按下鼠标之后转移到了父窗口上?还是还试一下吧。

  把父窗口和子窗口的mousePressEvent修改为

qDebug()<<"void Dialog::mousePressEvent(QMouseEvent *)"<<hasFocus();
qDebug()<<"void myButton::mousePressEvent(QMouseEvent *e)"<<hasFocus();

  再来运行下,看下结果

  可以看到,父窗口依旧是没有焦点的,所以上面的猜测是错误的吗?

  继续向自己提问,是否是因为父窗口的原因呢,如果鼠标按下的是子窗口会怎么样,继续尝试

  在父窗口的构造函数最后增加一行代码

setFocus();

  继续尝试,在子窗口按钮上按下鼠标,会是什么结果呢。

  结果很奇怪,在父窗口中点击鼠标,确实是获得焦点的,然后再点子窗口,按钮子窗口也获得了焦点,然后再点父窗口,再也获得不到焦点了。

  继续写代码测试,这次子类化一个QWidget,然后重写mousePressEvent,因为QWidget默认是分发事件的,因此稍作修改,让他阻断事件。

void myWidget::mousePressEvent(QMouseEvent *e)
{
e->accept();
qDebug()<<"void myWidget::mousePressEvent(QMouseEvent *e)"<<hasFocus();
}

  然后新窗口构造函数中对新窗口稍微修改下样式,以区分2个窗口

QHBoxLayout *layout=new QHBoxLayout;
QLabel *label=new QLabel(tr("新窗口"));
layout->addWidget(label);
setLayout(layout);
resize(,);

  在父窗口中注释掉原来的button子窗口,new一个新的widget子窗口,现在父窗口和子窗口都是QWidget

    w=new myWidget(this);
w->setStyleSheet("background-color:red;");

  运行下看看,发现两个窗口都没有焦点

  在父窗口构造函数中加上

setFocus();

  然后交叉点击父窗口和子窗口,你会发现焦点永远在父窗口上,如果setFous在子窗口,就永远在子窗口,如果都加了,就按照代码顺序。

  可见,这是按钮一个默认机制,焦点的夺回,如果别的窗体设置了焦点,然后点击鼠标按下按钮,按钮会夺回焦点,再也不还了,除非你再次设置焦点。

  再次尝试下,发现即使焦点在子窗口,点击父窗口,消息不会路由到子窗口上。

  在这里得出一个结论,鼠标事件的获得与处理,是根据鼠标点击的窗体所决定的,而不是像书本上说的路由到焦点所在窗体(键盘事件则确实如此,以后再谈),如果子窗口处理鼠标事件的时候,使用ignore分发(默认是accept截获),会再向父窗口传递,直到事件被截获或者到达顶层窗口。

  QPushButton等有click信号的窗体控件,如果处理mousePressEvent,click信号还会被响应吗

  父窗口的构造函数修改为

    ui->setupUi(this);
//w=new myWidget(this);
//w->setStyleSheet("background-color:red;");
btn=new myButton(tr("测试父按钮"),this);

  父窗口的mousePressEvent修改为

void Widget::mousePressEvent(QMouseEvent *e)
{
qDebug()<<"void Widget::mousePressEvent(QMouseEvent *e)"<<hasFocus(); }

  子窗口的按钮构造函数为空白,mousePressEvent修改为(注意,此时子窗口已经变回按钮了)

void myButton::mousePressEvent(QMouseEvent *e)
{ qDebug()<<"void myButton::mousePressEvent(QMouseEvent *e)";
}

  然后给按钮子窗口安装一个槽函数,响应按钮的cilck信号,槽函数自由发挥,能显示是否被调用就行

  可以看到,如果处理了鼠标按键后调用父类方法,是可以响应click消息的,如果注释掉return,则没有click消息,可以自行测试。

  最后一个问题,我不调用父类方法,而是使用ignore分发,能有click消息吗?

  注释掉return,如果你刚才没注释掉的话,在按钮的mousePressEvent里加上一句代码

e->ignore();

  然后运行程序,点击按钮

  可以看见,父窗口收到了子窗口传来的鼠标事件,但是click信号并没有被触发。

  今天就到这吧,我写本文的原因不是教别人,而是阐述疑惑与观点,因为一句话说不清,在这里求教育求指正,有什么错误尽管提,谢谢各位了。

  过几天再和大家讨论下键盘事件的路由,拖放事件的看法,以及过滤器的一些疑惑与测试。

浅谈Qt事件的路由机制:鼠标事件的更多相关文章

  1. 事件监听机制——鼠标事件MouseEvent

    鼠标事件 鼠标事件包括鼠标的双击.左击.右击.中间键等等,本文进行事件加载进行简单介绍,具体可以参考键盘事件. import java.awt.*; import java.awt.event.*; ...

  2. 【ASP.NET MVC系列】浅谈ASP.NET MVC 路由

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  3. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

  4. Qt事件系统之二:鼠标事件和滚轮事件

    在Qt中,事件作为一个对象,继承自 QEvent 类,常见的有键盘事件 QKeyEvent.鼠标事件 QMouseEvent 和定时器事件 QTimerEvent 等,与 QEvent 类的继承关系图 ...

  5. 浅谈 Qt 布局那些事

    Qt 布局那些事是本文介绍的内容,直接进入主题.GridLayout是一个非常强大的布局管理器,它可以实现很多复杂的布局,名字中暗示它将所有控件放置在类似网格的布局中.^__^GridLayout有两 ...

  6. Qt 隐藏标题栏 窗口移动 鼠标事件

    摘要 隐藏标题栏 头文件声明鼠标移动虚函数 .cpp文件实现功能 1 setWindowFlags(Qt::FramelessWindowHint | windowFlags()); 无标题栏移动窗体 ...

  7. 浅谈SQL Server内部运行机制

    对于已经很熟悉T-SQL的读者,或者对于较专业的DBA来说,逻辑的增删改查,或者较复杂的SQL语句,都是非常简单的,不存在任何挑战,不值得一提,那么,SQL的哪些方面是他们的挑战 或者软肋呢? 那就是 ...

  8. 13-jQuery事件绑定和常用鼠标事件

    # 关于事件 ## 事件绑定 1.**基本绑定** > $(element).click(function(){})>> $(element).dblclick(function() ...

  9. 浅谈Linux中的信号处理机制(一)

    有好些日子没有写博客了,自己想想还是不要荒废了时间,写点儿东西记录自己的成长还是百利无一害的.今天是9月17号,暑假在某家游戏公司实习了一段时间,做的事情是在Windows上用c++写一些游戏英雄技能 ...

随机推荐

  1. OceanBase中主备Rootserver如何管理切换

    主RootServer会不断给备RootServer发送lease.被RootServer收到该lease后会保存到几个变量中: int ObCheckRunnable::renew_lease(co ...

  2. css3设置box-pack和box-align让div里面的元素垂直居中

    只要设置元素的box-pack和box-align即可,这两个属性当前只有webkit和moz支持,要设置垂直居中的话只需要将这两个属性的值都设置为center即可,需要的朋友可以参考下   以前处理 ...

  3. CSS或者JS实现鼠标悬停显示另一元素

    想达到鼠标悬停到元素a上,显示另一个元素b,可以通过css实现也可以通过js实现.js:写两个函数:mouseenter,mouseleave,例如:其中 $("#a").mous ...

  4. Android源码大全

    JavaApk-安卓应用游戏APP源码下载 - Android App Games Source Download. http://www.javaapk.com/  700多个 Android 例子 ...

  5. Android : Activity 和 TabActivity 共用一个OptionMenu

    在虚拟机上我可以用menu键打开OptionMenu,但是到了真机上没有menu键了.OptionMenu没有办法打开,所以只能采用google推荐到ActionBar.用右上角到三个点代替实体到me ...

  6. 谁能告诉我为什么sum_area输出总是0(多边形重心问题)

    多边形重心问题 时间限制:3000 ms  |  内存限制:65535 KB 难度:5   描述 在某个多边形上,取n个点,这n个点顺序给出,按照给出顺序将相邻的点用直线连接, (第一个和最后一个连接 ...

  7. NodeJS爬虫系统初探

    NodeJS爬虫系统 NodeJS爬虫系统 0. 概论 爬虫是一种自动获取网页内容的程序.是搜索引擎的重要组成部分,因此搜索引擎优化很大程度上是针对爬虫而做出的优化. robots.txt是一个文本文 ...

  8. ExtJS4.x Grid 单元格鼠标悬停提示

    //每一个列都会出现鼠标悬浮上去显示内容 /** * //适用于Extjs4.x * @class Ext.grid.GridView * @override Ext.grid.GridView * ...

  9. 什么是位、字节、字、KB、MB

    什么是位.字节.字.KB.MB 位:"位(bit)"是电子计算机中最小的数据单位.每一位的状态只能是0或1. 字节:8个二进制位构成1个"字节(Byte)",它 ...

  10. 优盘(U 盘) 采用TLC, MLC, SLC芯片 的区别 与使用寿命

    最近一直在看大家在讨论sandisk,pny,金士顿等大厂都开始用tlc的芯片问题,让大家基本都不敢用U盘存数据了按照之前的擦写参数TLC        1000次MLC       10000次SL ...