需求:
我现在是这样的需求,我正在开发一款嵌入式IDE中,编辑器中光标改变,右侧的符号大纲能对应的改变选中项。
这里的过程是这样的,鼠标位置改变事件函数里,通过光标行号,计算得到当前处于的符号(这是个耗时过程),然后在右侧的大纲里选中对应符号。
问题:
用户可能会快速的改变光标位置,导致一连串的鼠标位置改变事件需要处理,从而光标位置改变就是卡顿的。
这个问题的处理方法:
1. 就串行处理,事件函数里判断光标所在行是不是和上次仍然相同,如果所在行相同,那么就不更新大纲位置了。这样来加快不必要的更新。
2. 用一个定时器,当光标位置停下来了100ms后,再处理这个符号位置更新。这样能让连续事件得到丢弃处理。但是光标停下来了,此时如果定时到了,正在处理大纲,光标刚好又动了,此时光标就被卡住了。这个情况发生的可能性还是很小的。
3. 多线程方式,每次更新前就启动一个线程,而且先判断前一个线程是否还未完成,如果还未完成,先停止前一个线程。
4. 在处理过程中调用qt的事件处理循环(这样会产生事件重入),同时结合两个标志变量,就能解决问题重入了,此时只有最后一次的重入才会更新界面。中途处理系统事件了,界面也不会卡顿了。本方法见本文末尾。
总结:
方法1逻辑最清晰,在性能无明显影响的情况下,当然就用这个啦。方法2也不错,实现复杂一点,但是比方法1性能好。方法3有点重量化了,需要开线程。方法4逻辑复杂,但是比方法1和2的性能都强。
这里我的符号表不大,所以方法1是可以满足性能了的,所以就用这个。
方法4伪代码与示意图:
int level = 0;
bool can'tUpdate = false;
void cursorChangeEvent(int line)
{
level++;
耗时计算(line);
QApplication::processEvent();
if(can'tUpdate == false)
更新符号大纲();
level--;
if(level > 0)
can'tUpdate = true;
}