0
点赞
收藏
分享

微信扫一扫

QPlainTextEdit等 自制 文本或者代码 编辑器控件 是如何 自定义 实现的?


我们会发现这些编辑器控件,都是继承自  QAbstractScrollArea 类,比如 QPlainTextEdit,大名鼎鼎的 QsciScintilla 编辑器控件,小熊猫IDE的 SynEdit 编辑器控件等。

QAbstractScrollArea是提供一个可以滚动的窗口,里面可以容纳很多子控件。

文本如何实现显示的呢?

那就是我们的子类需要重新实现 paintEvent 事件函数。


void paintEvent(QPaintEvent *event) override;


这个函数里面需要我们自己定义 QPainter 对象去执行具体的绘制工作,过程如下:

  • 定义一个 QPainter 对象
  • painter->fillRect(AClip,edit->mGutter.color()); 填充一个矩形,应该是为了设置背景色
  • painter->setFont(edit->mGutter.font()); 设置绘制文本的字体
  • painter->setPen(edit->mGutter.activeLineTextColor()); 设置画笔的颜色
  • painter->drawText(string) 绘制出这些文本了

一个编辑器的区域组成

同理,画其它区域也是如此,比如画编辑器的边缘margin(有的编辑器也叫做 Gutter),比如显示箭头,断点,行号等。也是通过绘制实现的,而不是直接搞个QWiget并排放置在那儿。具体过程机制如下:

通过在编辑器内里,创建两个专门管理不同区域坐标的对象(注意:这些对象不是继承自QWidget,因为它们仅仅是用于管理不同区域的坐标范围信息,比如长宽等),比如小熊猫IDE的 SynEdit 编辑器类里就有成员:


SynGutter mGutter; 其中继承关系【 class SynGutter : public QObject 】


在绘制的时候,就通过这些对象来实现分别控制绘制的动作了,比如哪些地方该绘制矩形,哪些地方该绘制指定的图片,哪些地方该绘制文本。

所以,一整个编辑器控件只是一个QWidget,而不是说margins(或者叫做gutter栏,例如行号栏)是一个并排放置的QWidget(当然自制编辑器网上也有人这么干的)。

因此,当我们在编辑器中鼠标右键时,我们发现 contextMenuEvent(QContextMenuEvent *event) 函数总是能得到触发,而不管我们右键在行号栏还是文本显示区。但是我们可能希望右键在行号栏,文本显示区时候能区分出来,怎么做呢?只需要判断event->pos的和margin的区域坐标的关系,就能知道有没有右键在margin区了,从而显示不同的菜单。大家可以看我这个博客,对上述两个编辑器的分析 ​​QsciScintilla等编辑器实现不同区域鼠标右键处理方式不同的方法_标biao的博客-CSDN博客​​

附录:QPainter类有哪些函数呢?


void drawPoint(const QPointF &pt); 画点函数 void drawLine(const QLineF &line); 画线函数 void drawRect(const QRectF &rect); 画矩形 drawPixmap                         画图片 void drawText(const QPointF &p, const QString &s); 画文本 ...... 等


举报

相关推荐

0 条评论