前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Qt源码笔记】浅谈 Qt 中的控件绘制

【Qt源码笔记】浅谈 Qt 中的控件绘制

作者头像
Harper
发布2021-07-27 10:12:12
2K1
发布2021-07-27 10:12:12
举报
文章被收录于专栏:Harper的碎碎念Harper的碎碎念

在工作中经常要根据 UI 提供的稿子做自绘控件,而且在新项目中,我自己基于 Qt 做了一套项目自用控件库,还会涉及到换肤,所以对 Qt 的控件绘制,着重的研究了一下。看过代码之后,觉得 Qt 项目本身,确实是做 UI 发家,绘制流程清晰,可以说是做界面的范本了。将流程梳理记录一下。

分类

对于自绘控件的分类,我将其分为两大类:

  • 基于 Qt 控件类派生
  • 基于 QWidget 派生

除非是行为跟 Qt 本身的控件相差太多,或者是缺少需要的交互逻辑,否则的话尽可能从 Qt 现有的控件类派生,这是一条基本的原则。因为绘制上来说重写 paintEvent 方法,基本就可以达到想要的目的,而控件类本身会提供一些现成的控件逻辑,这样会大大减少开发难度。

绘制流程

其实提起绘制流程来说,无非就是重写 paintEvent 方法。但是如果要做一整套 UI 库,没有结构,都在 paintEvent 里边写死,在后期加换肤,或者是在代码整洁度上都会大打折扣。 Qt 本身的控件绘制,就可以给我们很大的启示。以绘制事件方法代码最简单的 QPushbutton 为例,足见一斑:

代码语言:javascript
复制
void QPushButton::paintEvent(QPaintEvent *)
{
    QStylePainter p(this);
    QStyleOptionButton option;
    initStyleOption(&option);
    p.drawControl(QStyle::CE_PushButton, option);
}

可以简单理解为两个流程:

  1. 装配绘制必要上下文
  2. 绘制

Qt 考虑到对于按钮样式,开发者有着自己的需求,而对于逻辑状态可能开发者可以用现成的。所以 initStyleOption 是一个保护方法,如果开发者没有对按钮状态的特殊要求,用这个方法,就可以把图标,按钮的点击状态什么的放进这个 option 中。在绘制的时候直接拿来用。

而下边的绘制,可以看到这里是用了 QStylePainter 而不是常规的 QPainter。不过 QStylePainterQPainter 差别不大,前者只是在里边保存了当前 QWidget::style()的指针。所以这段代码改成:

代码语言:javascript
复制
QPainter p(this);
QStyleOptionButton option;
initStyleOption(&option);
style()->drawControl(QStyle::CE_PushButton, option, &p, this);

也是一样的。如果你翻看其他控件,比方说 QMenu 就是下边这种用法,可能是开发人员的不同习惯,但是他们逻辑是一致的。

Qt 的绘制精髓就在于此。对于绘制, Qt 控件是交给 style 来管理的。打开源码路径 qtbase\src\widgets\styles 这里边保存了 Qt 绘制的基本样式。为什么说是基本样式呢,因为还有一部分 qtbase\src\plugins\styles 在这个目录下,这所有的加一起就是全部样式了。话说回来, Qt 正是因为将绘制逻辑都保存在了 style 中,所以 Qt 才可以在不同平台都表现的像一个原生控件一样,“千平台千面”。

走到这里,就不得不一探 QStyle 的究竟了。QStyle 是一个抽象类,头文件因为包含了太多枚举,所以特别长,就不粘了。里边关于绘制的几个方法是纯虚的,在绘制方法中,通过传进去的枚举类型,来找到对应控件的绘制逻辑。除了绘制方法,还有一些是计算绘制区域大小的方法,以及 hitTest 获取子控件的方法。这就是整个 Qt 绘制的大本营了。而对于 Qt 控件的实际绘制逻辑,其实也对做自绘控件库也十分有帮助,不过既然是浅谈,也就不再罗嗦。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分类
  • 绘制流程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档