关于编辑器实现原理知识,请先看我这篇博客 QPlainTextEdit等 自制 文本或者代码 编辑器控件 是如何 自定义 实现的?_标biao的博客-CSDN博客
我们可知,整个编辑器是一个QWidget。
由于 QScintilla 类(也称为QsciScintilla)提供的信号,最相关的只有
void marginClicked(int margin, int line, Qt::KeyboardModifiers state); //鼠标左键点击
void marginRightClicked(int margin, int line, Qt::KeyboardModifiers state); //鼠标右键点击(所以这些信号肯定是在鼠标右键事件中发射的,scitinall源码中嵌套层次太深,我就没有追踪了)
所以鼠标右键在文本编辑(显示)区是没有反应的,解决这个问题有两种方法:
ui->ed->setContextMenuPolicy(Qt::CustomContextMenu); connect(ui->ed, &QsciScintilla::customContextMenuRequested,this, &MainWindow::onEditorContextMenu); 设置QScintilla 发射鼠标右键信号出来(这时候QScintilla 就不会执行自己的contextMenuEvent()事件函数里面后面的内容了),从而拿到鼠标右键在整个编辑器(也就是一个qwidget)位置等信息,完全交给我们进行处理。
因此,拿到了鼠标右键的坐标了,那就好办了,请继续往下看
关于鼠标事件函数知识,看我这博客:qt事件和信号区别于联系以及其它知识点笔记_标biao的博客-CSDN博客_qt信号与事件 区别
qt事件的触发原理_标biao的博客-CSDN博客_qt触发事件
实现鼠标右键在编辑器的文本显示区,margin区(比如行号栏等),能区分出来。
安装上面说的两种方式中的一种,拿到鼠标右键坐标信息,然后与编辑器对象里面的maigin坐标进行比较判断,从而知道鼠标右键在margin区还是文本显示区。如果我们看 小熊猫IDE的编辑器控件类 SynEdit 就会发现,里面就是这样干的(里面的gutter就是QsciScintilla编辑器中的gutter的玩意),在函数 bool SynEdit::pointToCharLine(const QPoint &point, BufferCoord &coord)中,可以去瞅瞅。QsciScintilla编辑器当然也可以这样干,但是我们获取每个margin的区域坐标,操作如下:
int s = ui->ed->margins(); for (int i = 0; i < s; ++i) qDebug()<ed->marginWidth(i);
然后我们就可以拿着这些margin的区域值去判断当前鼠标右键在哪个位置啦。
这里仅针对 QScintilla ,我们也可以按照上面的方式1。我们发现QScintilla提供了marginRightClicked信号(右键在marigin栏才会有)在鼠标右键按下时候就触发,而customContextMenuRequested信号是鼠标右键弹起时候才触发的,所以我们可以这样,鼠标右键点击时候,设置flag为true,此时处理customContextMenuRequested信号的函数中判断这个flag就能知道,是按在了marigin上了。就能区分开鼠标右键的位置了。
哪种方法好呢,各有优点,方法1更灵活,更符合自然想法。方法2不需要子类化QScintilla,从而也很灵活。