刚做完的一个项目,在测试时出现了一个问题:由于多线程的存在,当进行语音识别时:如果用户点击程序界面上的button或者其他接受点击事件后会发出信号的widget时,程序会crash ! 后来尝试着从多线程上去解决,但是比较困难;后来只能从另外一条路来解决,那就是:当语音识别进行时:禁掉一切用户操作!

所谓的禁掉一切UI操作,在手机等手持设备上,尤其是纯触摸屏的设备上,主要就是指的禁止mouse操作!当然了:也可能是禁止键盘操作等。那如何去做这一点呢?

方法:我们可以截获禁止操作的窗口的所有event事件,而后将他们全部抛掉而不进行处理,这样就可以了。那在Qt中要实现这一点有很多种方法,比较常用的方式就是使用eventFilter事件过滤器。

这其中不可避免要说到Qt中的事件传递顺序,其要经过很多层()对于我而言:我用的比较多的层次就是QApplication的eventFilter这一层 , 各个widget的eventFilter这一层 各个widget的event()这一层以及 各个widget里边的各个事件处理函数这一层(这四层的传递顺序是从前往后)

这里我们只需要使用各个widget的eventFilter即可! 可以如下写:

bool iEnableOperator = true;
myWidget::eventFilter(QObject *obj, QEvent *event)
{
if (iEnableOperator == true)
{
if(event->type() == QEvent::paint)
{
return false;
}
else
{
return true;
}
}
else
{
return QWidget::eventFilter(obj, event);
}
}

而后我们只需要改变iEnableOperator 这个变量的值 即可决定允许不允许进行UI操作!
//-------------------------------------------------------------------------------------------------------------------------------------------
这里有以下几点注意:
1:当禁止UI操作时:并不是要把所有event都要拦截掉,而是要把paint绘制事件给漏过去(正如上边所做的那样),因为我们仅仅是要禁止
UI操作,而不是不再更新绘制! 比如:在做语音识别的时候,我们再界面上显示一个进度条,其上边的值是逐渐增大的。 当禁止UI操作时:如果
我们同时拦截了paint绘制事件,那进度条也无法更新显示了! 基于以上理由,我们需要把paint事件给漏过去!
2:这里有一个特殊的空间:QTextEdit 。当我们后来对所有的窗口不见都做如上操作后发现:几乎所有窗口的UI操作都顺利禁掉了,唯独QTextEdit
的没有,导致程序还会发生crash! 后来追了一下这个问题发现:无论是在windows下还是symbian下,QTextEdit的事件传递过程都很另类!对于
所有的mouse事件,其在传递过程中不经过任何一个其注册的eventFilter事件过滤器,也不经过自身重写的event(),而是直接进入到了自己的
事件处理函数中(mousePressEvent()等等。。)!
对于这一点:我一直觉得没什么道理可言,因为别的空间,比如QPushButton都是经过的,唯独它不经过!Maybe这是QTextEdit的另外一个bug!!
后来我们用如下方法禁掉了QTextEdit的mouse事件:
①:首先准备一个标准的QWidget对象,将其透明度设为0.1,大小与QTextEdit相同,位置设置为QTextEdit对象的位置,亦即:让二者是一种前后
重叠的关系。初始时将这个窗口hide掉!
②: 当需要禁止QTextEdit的UI操作时(以我们的项目为例:就是当开始语音识别时),将前边创建的半透明窗口raise并show在QTextEdit
的前边来遮挡住QTextEdit本身。而当要允许QTextEdit的UI操作时则再将其hide掉!
其实道理也很简单:将QTextEdit挡住了,那事件就传递不到它上边,从而也就禁止掉了。由于我们将这个窗口透明度设置为0.1,几近全透明,
用户根本体验不到是我们在上边覆盖了一个窗口。

//-------------------------------------------------------------------------------------------------------------------------------------------
再补充一个关于QTextEdit的bug: QTextEdit这个控件在windows和symbian下的表现是很不一样的!
在windows下其表现很正常,但是在symbian下:其scrollBar上边的slider滑块长度大小永远不发生变化,按理说:其文字所占的屏数越多,
滑块的长度越短才对。 这一点就让用户无法通过滑动这个slider来达到翻屏的效果。
但是symbian下的QTextEdit却给出了几个菜单:当常按两个方向箭头时:其会跳出一个menu来,上边有几个选项:主要就是让滚动到
开头处,滚动到结尾处等。 它通过这种方式弥补了滑动块长度大小不变的问题。但是我觉得这个的用户体验度始终没有用slider好。

http://blog.csdn.net/nrc_douningbo/article/details/5646247

04-30 05:56