zoukankan      html  css  js  c++  java
  • Qt中如何禁掉所有UI操作以及注意事项(转)

     刚做完的一个项目,在测试时出现了一个问题:由于多线程的存在,当进行语音识别时:如果用户点击程序界面上的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好。
  • 相关阅读:
    怎么与用户有效的沟通以获取用户的真实需求?
    面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?
    当下大部分互联网创业公司为什么都愿意采用增量模型来做开发?
    【第八周】回到起点,从头再来
    【第七周作业】项目开发心得
    【第六周作业】项目代码的编写规范
    【第五周作业】寸步难行
    【第四周作业】参加项目开发之后的一些体会
    【第三周作业】对于软件工程学的一些理解
    【第二周作业】面向过程(或者叫结构化)分析方法与面向对象分析方法到底区别在哪里?
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2646206.html
Copyright © 2011-2022 走看看