• 9710阅读
  • 3回复

keyEvent处理机制的奇怪问题 [复制链接]

上一主题 下一主题
离线sundp
 

只看楼主 倒序阅读 楼主  发表于: 2009-02-16
    单位一批联想家悦机器,前几年买的,CPU赛杨D,内存256M。最近准备在这些机器上跑Linux,首先在一台机器上试验。系统采用RedFlag 6.0 SP1,使用Qt4.4.3开发,IDE用了QDevelop 0.26。
    初次在Linux下进行大规模的开发,麻烦当然多多,但多数问题通过上网和查手册都能得到解决,却有一个奇怪的问题虽然解决了,我也仍然一头雾水。所以在这里写出来,请高手指点。
    一个录入界面上有一个lineEdit,用来录入代码进行检索,在它的returnPressed()信号上连接了一个槽。开发过程中的测试一直都是手工敲代码,没有任何问题。但实际工作是为了提高录入效率,使用了一个条码扫描器。开发过程中没连接扫描器,是因为扫描器是硬件层次上的东西,它把条码信息翻译成键盘码,从键盘接口送入计算机。从没想过这个东西会出现问题,但偏偏在实际测试是这里就出了问题。
    它送进lineEdit的数码顺序经常是不对的,大多数的数码里都有两个或多个相邻数位被交换。比如说,条码上的12345678,在lineEdit里显示的可能是13245678,或12354687之类的东西。
经过多种测试发现这件事与以下几个因素有关:
    1、机器配置:在高配置的机器上没有这种现象。
    2、操作系统:这些机器在跑XP时没有这个问题,Everest没问题,RedFlag有问题。
    3、应用软件:在出问题的机器上,扫描器送进lineEdit里的是乱码,但打开一个文本编辑器试验,送进来的却是正常码,直接在终端下测试,送进来的也是正常码。
    4、条码码制:我们用的条码码制是code128,在出问题的机器上用其它码制的条码试验,比如一本杂志上的条码,扫描结果却正常。
    我的问题是,码制不能改,因为有许多发出的去的病志本上已经贴好了条码。机器也不能升级,这批机器才用了几年,时间太短了不可能更换。只有在软件上想办法解决。
    我怀疑是Qt在处理键盘事件时有bug。因为在之后的测试中我直接重载了keyPressEvent,不好用,使用eventFilter也不好用,在底层截获的keyPress事件直接就是乱序的。
    还有个更底层的办法是截获notify,我想如果在notify里再不能解决问题的话,那我就彻底没办法了。
    在没重写notify之前,我突然想到keyRelease事件,keyPress是乱序的,那keyRelease怎么样呢?于是在eventFilter里面忽略了和那个lineEdit相关的所有事件,只保留keyRelease事件,结果发现keyRelease的顺序是正常的!
    后来我重装了系统,换了Everest0.52的系统,因为RedFlag除了正常工作以外,对其它的操作反应也很慢,换了系统之后,我特意又把程序改回原先有问题时的样子,这时问题又没有了。
    经过总结,感觉Qt的这个问题只在系统响应慢时才会发作。这时我又想起了上面用keyRelease解决办法,在截获keyRelease之前,我屏闭了所有其它的事件,会不会因为这个原因提高系统影响速度,才让keyRelease出现正常的呢?不想再试了,重装系统太麻烦。反正现在问题也没了。
    对Qt的keyEvent处理机制非常不解。
人境结庐<http://sundp70.blog.163.com>心远地偏
离线mumutouv

只看该作者 1楼 发表于: 2009-02-17
通过event->accept()也许可以解决你的问题,这个需要了解X的机制 + WM管理器等等,当然显卡驱动也有一定原因
离线duduqq

只看该作者 2楼 发表于: 2009-02-17
整个单位都有LINUX啊,不错不错。
看了这篇文章,觉得楼主分析问题好细致,值得学习。
离线lixinhua
只看该作者 3楼 发表于: 2009-03-31
你的知识结构确实不错哈,值得学习;
不过你在重新子类化QApplication类的notify方法之后不行的话?


你还可以用更底端的方法
   如:linux下的x11eventfilter() 也是重新实现一下,就ok 了

bool x11EventFilter(XEvent *xe) {
      switch (xe->type) {
    case ClientMessage:
          printf("Caught ClientMessage XEvent from Window %d \n", xe->xclient.window);
      printf("Receive message: %s\n", xe->xclient.data.s);
      return true;    
      }
      return false;
}



  window下也可以用对应的方法实现,毕竟是跨平台的哦[/b
快速回复
限100 字节
 
上一个 下一个