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

  这几天对于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. UBUNTU 下如何升级 gcc, g++

    正如大家所知道的GCC并不支持"make uninstall". 一种推荐安装方式就是把GCC 安装在你自己指定的一个路径,当你不须要某个GCC版本号的时候你仅仅须要移除相应版本号 ...

  2. AngularJs(八) 过滤器filter创建

    大纲 示例 过滤器的使用 创建过滤器 demo 这是整个示例demo 1.filter.js文件 angular.module("exampleApp", []) .constan ...

  3. bootstrap-js(2)下拉菜单

    1.下面的实例演示了在导航栏内和标签内的下拉菜单的用法: <!DOCTYPE HTML><html><head><link href="/style ...

  4. CRM odata方法如何使用$top

    odata方法 $top $top1 取1个 ¥top100取100个,放在$select前,中间用&符号隔开. 例如: var activeserviceReq = "/xrmse ...

  5. Csharp递归和循环实现折半查找

    static bool whilehalf(int n) { ; //低位 ; //高位 ; while(low <= hight) { if(n> arr[c]) { low = c + ...

  6. c++中basic_istream::getline()的返回值何时为真

    今天在看primer,17ch中的IO库再探,做课后练习,要求用ifstream.getline(char*, const unsigned, char)读取一个文件,用循环: while(ifs.g ...

  7. 获取ini文件所有的Sections和Keys

    获取ini文件中所有的Sections和Keys,并以pair对的方式存入到vector中 #include <iostream> #include <windows.h> # ...

  8. tomcat异常

    java.lang.UnsupportedClassVersionError: org/apache/lucene/store/Directory : Unsupported major.minor ...

  9. [LeetCode]题解(python):153-Find Minimum in Rotated Sorted Array

    题目来源: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ 题意分析: 在一个不重复的翻转的数组里面找到最小那个 ...

  10. 《转》JAVA中PriorityQueue优先级队列使用方法

    该文章转自:http://blog.csdn.net/hiphopmattshi/article/details/7334487 优先级队列是不同于先进先出队列的另一种队列.每次从队列中取出的是具有最 ...