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

  这几天对于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. linux系统的性能问题排除分析

    需要结合sar和top进行检查. top下关注load,%wa,%idle等 sar -u -o cpureport 10 3 每10秒采集3次 放在同目录下的文件cpureport 里 检查io s ...

  2. Error occured processing XML &#39;Cannot find class [springmvc.extention.BeanArgumentResolver]&#39;.

    <Description Resource Path Location Type Error occured processing XML 'Cannot find class [springm ...

  3. 怎样安装pip--python的包管理工具

    pip是python的包管理工具,使用它来安装python的模块很方便. pip支持的操作系统:Unix/Linux, OS X, and Windows. 支持的python版本号:2.6, 2.7 ...

  4. C# webservice开发

      一.Webservice简介Web Service也叫XML Web Service. Web Service是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量 ...

  5. 《think in python》学习-1

    高能提示:本文大量编程术语与释义,一些释义如有偏差恕不讨论. 纠结学Python 很久了,一年的纠结过程中慢慢的积累了一点对python的认知,但实际语法都未曾接触过,研究backbone的一个例子的 ...

  6. .NET面试题解答

    抽象类和接口有什么区别?使用时候有什么需要注意的吗?答:相同点:都不能被直接实例化,都通过继承实现其抽象方法: 不同点: 1) 接口支持多继承:抽象类不能实现多继承: 2) 接口只能定义行为:抽象类既 ...

  7. 解决VS2010打开Web页面时经常由于内存较低而导致VS2010自动关闭的问题

    在使用VS2010 开发Web应用程序的时候,经常打开一个Web页面进行编辑前台代码的时候要等待很久(甚至等了半天结果还挂掉,简直令人抓狂), 之前也在网上找了很多相关的方法,都没办法解决,今天无意中 ...

  8. 20151203--filter

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/htm ...

  9. Linux网络管理——端口作用

    1. 网络基础 .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB",&q ...

  10. C#递归树

    protected void Page_Load(object sender, EventArgs e) { bindtree(PopId); } private void bindtree() { ...