The difference between isDown() and isChecked() is as follows. When the user clicks a toggle button to check it, the button is first pressed then released into the checked state. When the user clicks it again (to uncheck it), the button moves first to the pressed state, then to the unchecked state (isChecked() and isDown() are both false).
If autoRepeat is enabled, then the pressed(), released(), and clicked() signals are emitted at regular intervals when the button is down. autoRepeat is off by default. The initial delay and the repetition interval are defined in milliseconds by autoRepeatDelay and autoRepeatInterval.
这里的autoRepeat 是通过其virtual void timerEvent(QTimerEvent * e)函数实现的,如果我们重写了QPushButton的该函数而不调用默认处理,则导致即使设置了所用autoRepeat参数,也不能生效。timerEvent是QObject的函数,它配合startTimer(), killTimer(), and event().使用,在派生类QPushButton中必有此time的控制。说道这里,插一嘴物理键盘按键的事件响应--
当单次按下物理按键W时,其事件响应过程大约如下:
1> KeyPress and isAutoRepeat false 2> KeyRelease and isAutoRepeat false
当持续按下物理按键W时,其事件响应过程大约如下:
1> KeyPress and isAutoRepeat false 2> KeyRelease and isAutoRepeat true
3> KeyPress and isAutoRepeat true 4> KeyRelease and isAutoRepeat true
....... all isAutoRepeat true end> KeyRelease and isAutoRepeat false
当单次或持续按下修饰按键Shift时(按下其他按键,对Shift自身事件无影响):
1> KeyPress and isAutoRepeat false QFlags(0x2000000) 2> KeyRelease and isAutoRepeat false QFlags(empty)
Test Analyse:软QPushButton的autoRepeat属性相关功能,其表现是与物理按键的事件表现一致的,所谓的持续按下,就是循环的制造按下与抬起事件。当持续按下Shift物理按键时,它不会存在autoRepeat现象,也不影响W按键的原有事件,不管是否持续按下。我们再回到QPushButton的isChecked属性的研究上 - -
在一篇关于软键盘实现的博客中,博主派生了QLabel类来实现了Button的isChecked和isAutoRepeat功能,实现中仅有shift、alt、ctrl三个button设置了Checked属性,由此我粗陋的理解到Checked属性的基本含义。setCheckable设置按钮为开关按钮(toggle button),按下/谈起 ,默认情况下Button为触发按钮(trigger button),按下去马上弹起来。
setCheckable() sets whether the button is a toggle button or not.The QAbstractButton::toggled() signal is emitted whenever a checkable button changes its state. See An Official Example:https://doc.qt.io/qt-5/qtwidgets-dialogs-extension-example.html
理论上QPushButton类比QLabel类要复杂,所以其创建耗时上会有所差距,下面是一些测试结果(PC-Wind7-i5):
1> 不指定父对象顺序创建2000个Qwidget耗时 32ms / 2000个QLabel耗时 41ms / 2000个QPushButton耗时 56ms
2-1> 不指定父对象顺序创建2000个QPushButton耗时 75ms / 2000个QLabel耗时 77ms / 2000个Qwidget耗时 48ms
2-2> 不指定父对象顺序创建2000个QPushButton耗时 71ms / 2000个QLabel耗时 65ms / 2000个Qwidget耗时 45ms
2-3> 不指定父对象顺序创建2000个QPushButton耗时 70ms / 2000个QLabel耗时 70ms / 2000个Qwidget耗时 55ms
3-1> 不指定父对象顺序创建2000个Qwidget耗时 53ms / 2000个Qwidget耗时 47ms / 2000个Qwidget耗时 37ms
3-2> 不指定父对象顺序创建2000个Qwidget耗时 47ms / 2000个Qwidget耗时 47ms / 2000个Qwidget耗时 47ms
3-3> 不指定父对象顺序创建2000个Qwidget耗时 40ms / 2000个Qwidget耗时 50ms / 2000个Qwidget耗时 46ms
但是这个结果并靠不住,细细分析下,QLabel从QFrame继承而来,加上他自身的属性,总的类属性占有内存并不比QPushButton少。而且多次测试结果下,同一环境下,同一次程序运行,第一创建2000QWidget与第二次创建2000个QWidget所消耗的时间并不稳定。多说几句:创建一个对象要消耗多少时间,与父类构造方法、自身构造、类成员等有关:所以通常类层次越深、类构造方法越复杂、成员数量越多,创建对象越耗时。记得曾经读到过几篇类实例化过程的文章,贴一下来:
参考1> C++ 成员函数在内存中的存储 https://blog.csdn.net/fuzhongmin05/article/details/59112081
参考2> ... more develop...
有几个问题:
QA:代码区这块内存是什么时候创建的?与编译有关?跟全局变量一样先于main创建好还是第一次实例化类时创建?
QB:
3-4> 指定父对象顺序创建2000个Qwidget耗时 420ms / 2000个Qwidget耗时 621ms / 2000个Qwidget耗时 888ms
我们可以发现,当指定父窗口时,使用的parent所包含的children窗口越多,则在新指定的创建过程中,将会耗时更多。且,相比较而言,指定父对象进行窗口创建的过程比不指定父对象创建的过程耗时上要大非常多。
在讨论这个函数的作用前,先来看点别的:普通按钮Btn1,我们点击它,之后按住鼠标左键不放,此时Mouse事件的ButtonPress、ButtonRelease、MouseMove事件捕获者均Btn1,不管MoveMouse到哪。可能有这样一种需求:从Btn1按住鼠标左键Move到Btn2时,若想响应Btn2的MouseRelease事件(这之前还包含Btn1的release及Btn2的MousePress),这时候,我们的事件重构处理过程中将势必用到childAt函数(依据位置判断控件);
多说一句,这个函数的一个好伴侣:qobject_cast(QObject * object)
Returns the given object cast to type T if the object is of type T (or of a subclass); otherwise returns 0. If object is 0 then it will also return 0.The class T must inherit (directly or indirectly) QObject and be declared with the Q_OBJECT macro.单从强制类型转换这层意思来看的话,它可以把一个有效指针强制的转换成了NULL(实际是检查不通过,所以我们在进行QWidget控件类型强制转换的时候不要再去使用static_cast<..>()这种风险转换方式啦!!);
再重新学习一遍:#https://blog.csdn.net/liang19890820/article/details/52044639
一些附加功能:#https://blog.csdn.net/liang19890820/article/details/50357523