首页 > 编程学习 > 编辑器库QsciScintilla的indicator点击没有按键信息的bug解决

问题描述:

我正在做IDE(嵌入式系统用的集成开发环境)的代码跳转功能,也就是按下 ctrl+鼠标左键释放 实现一个标识符跳转到 定义/声明 的功能(eclipse,vscode,qtcreator等IDE都具备这个功能)。遇到了这个问题。

    
首先看我这个博客了解一下信号:QScintilla的信号汇总和解释_我是标同学的博客-CSDN博客

//一个是关联qsci这个封装层的信号
connect(this, &QsciScintilla::indicatorReleased, this, &EditorCpp::onIndicatorReleased);    

//或者关联qsciBasei这个封装层的信号
connect(this, &QsciScintillaBase::SCN_INDICATORRELEASE, this, &EditorCpp::onIndicatorReleasedSci); 

这两个信号传出的参数都是一样的,这里以qsci这个封装层为例,如下:

void indicatorReleased(int line, int index, Qt::KeyboardModifiers state);

其中state指明了,我们鼠标点击这个indicator释放鼠标的时候我们按下的ctrl、alt、shift键的状态。但是我运行,始终打印出来的按键都是0???

但是我实测,关联那个按下信号 void indicatorClicked(int line, int index, Qt::KeyboardModifiers state);就能正确打印出按键信息的。

查找问题过程:(追踪qsci的源码)

首先看这个信号发射出来的位置

因此,我们看到,QsciScintilla的信号,其实就是更底层的 QsciScintillaBase的信号来的。所以,我们需要追踪 SCN_INDICATORRELEASE 这个信号又是怎么来的。


此时来到了Scintilla这个底层开源库这边了(关于这个库的继承结构,可以看我这个博客:QScintilla学习大全_我是标同学的博客-CSDN博客_qscintilla)

我们可以看到,其实 NotifyParent()这个函数发出的信号,也就是这里就是底层库 Scintilla 和qt的QsciScintilla 的接口处了,被qt全部转为对应的信号了。如果不是用qt进行封装,那么就可能是通过回调函数形式把这个接口暴漏出去了。很明显,qt的信号和槽机制很好用,清晰,灵活。

继续追踪这个 NotifyIndicatorClick()函数被谁调用,我们发现是 :(一个是鼠标按下,一个是鼠标弹起,这两个函数都会调用到NotifyIndicatorClick()函数,从上面一张图可以看到,是靠第一个参数 true,表示按下,false表示弹起,来区分状态的)

void Editor::ButtonUpWithModifiers(Point pt, unsigned int curTime, int modifiers)
void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers)

原因:

到这里,其实仍然会传进来按键的状态modifiers的,但是,我们可以看到鼠标弹起这里,直接传入的是0作为ctrl,alt、shift等的按键状态值,导致我们在qt那边程序的槽函数中,打印出来的按键值始终是0,这里终于找到原因了。真是坑啊!!!

而鼠标按下这个消息,就是正确的传入了按键信息,这就解释了我文章开头说的实测的结果:鼠标按下indicator能检测到ctrl、alt、shift等按键状态的,但是鼠标弹起时,检测到的始终是0了。

解决方法:

主要有两个方法:

  1. qt自己是可以获取到按键信息的,自己记录下来使用就行了。推荐用这个方法。
  2. 把这个库这里修改一下,让modifiers变量给传进去。但是如果我们使用QsciScintilla这个dll库来使用的话(看我这个博客 QScintilla如何安装和入门(初学者)_我是标同学的博客-CSDN博客_qscintilla),就还得重新编译这个库,是个麻烦事,所以不推荐这个方法了。

从下图中可以看出,而另一个样式hostpot触发,人家就是按键状态给带着的。关于hostpot资料可以看这个 https://qscintilla.com/#clickable_text/hotspots

 

总结:

在我们用别人的库的时候,其实这些库难免也可能是有bug的,有出现问题的地方的,所以我们最好是把它对应的源码也搞到,这样有些用法上的疑惑,或者遇到问题,我们直接追踪它这个库的源码,就能方便的解决很多问题了。如果仅仅是网上搜索答案,可能别人也没遇到过,所以找不到答案的。

而且自己去追踪源码这个过程,也是提高我们代码能力(欣赏一下别人的源码的写法),而且最重要的是要具备解决问题的能力(遇到问题不要慌,仔细分析原因,思考解决方法),这正是作为程序员进阶需要具备的能力。

前几天,qt的事件处理循环过程我一直有些疑惑,网上和官方的资料看了,还是有些疑惑解答不通,所以我自己追踪了qt的源码,看了一下,就搞明白了。可以看我这个博客 qt源码解析1--事件循环原理(重写事件函数,事件过滤器等)_我是标同学的博客-CSDN博客

Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式