数据线|界面设计之路,自定义控件,不一样的单选列表框

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片

数据线|界面设计之路,自定义控件,不一样的单选列表框

文章图片


一般来说 , 在项目中 , 基于Qt进行界面的开发 , 通常是使用Qt的基础控件 , 稍微复杂的界面 , 可以组合Qt的基础控件来实现 , 而外观 , 则可以通过更改样式来满足需求 。
但是 , 最近的项目中 , 要求实现的界面样式 , 仅仅通过Qt提供的基础控件是无法实现的 。 那么Qt有什么方法能够实现吗 , 那就需要paintEvent事件登场 , 在这个事件中 , 重新绘制所有的控件 , 并且可以绘制任意的图形 , 所以需要开发人员具备更高的开发设计能力 。
本文将会从问题现象出发 , 描述需求的场景 , 然后分析解决的思路 , 最后详细说明实现的细节 , 最后再进行概括总结 。

一、问题现象对于一个功能来说 , 如果有多个选项 , 并且是互斥的 , 那么通常使用单选按钮来实现 , 其效果图如下所示 。

但是新项目中 , 要求变更单选框的样式 , 其效果如下 , 功能不变 , 具备单选互斥的属性 。

二、解决思路从效果图看 , 通过修改单选框的样式是无法满足需求的 。 所以 , 考虑的方案是自定义实现 。 那么实现方案是怎样的呢 , 首先可能会想到从左往右来绘制单选框 , 但是这样又存在一个问题 , 就是左右两侧的单选框 , 它不是长方形 , 如何绘制呢 。
经过考虑和验证 , 最终的解决思路为:paintEvent事件中 , 先绘制背景 , 然后再绘制文本 , 最后再绘制方框 。 其中 , 需要考虑的点是 , 鼠标按下释放事件以及文本超出了怎么处理的问题 。
接下来结合代码和效果图来详细说明实现的细节 。
三、实现细节下面会从五个步骤来说明实现的细节 , 这五个步骤分别是画背景、画文本、画方框、可见区、鼠标事件 。
paintEvent事件中实现了画背景、画文本、画方框的三个步骤 。
首先定义如下需要使用的成员变量

画背景画背景的逻辑是 , 如果当前设置的单选数量为零 , 那么直接绘制一个矩形背景 , 否则循环遍历单选字符串列表 , 并且根据是否是当前索引来绘制不同的矩形背景 。

画文本绘制文本的时候 , 做了优化 , 当文本长度超长的时候 , 文本右侧用省略号代替 。

文本超长的显示效果如下图第三个单选框所示 。

画方框首先调用drawRoundedRect绘制最外围的有圆角的方框 , 然后再依次画出中间的每一个竖线 。

最终绘制的效果图如下所示 , 但是仔细看会发现四个角有凸出的地方 , 这个下一小节会说明如何解决 。

可见区为了解决上面的问题 , 解决办法是在showEvent和resizeEvent的时候 , 重新设置可见区域 。 如下代码所示 , 使用QPainterPath绘制一个有圆角的方框 , 然后转化为多边形QPolygon , 接着创建QRegion , 最后调用setMask设置掩码 , 简单来说 , 就是设置遮罩 , 只显示遮罩内部区域 。

鼠标事件最后就是要处理鼠标事件 , 当鼠标释放的时候 , 需要做什么处理 。 IndexAtPos的功能是根据当前坐标来获取具体的索引值 , 即当前位于那个单选框 , 当收到鼠标释放事件的时候好 , 重新设置当前索引 , 并更新图形 。

最终运行的效果 , 如下图所示 , 切换单选框的时候 , 背景色跟着变化 。

四、总结【数据线|界面设计之路,自定义控件,不一样的单选列表框】QT界面的设计 , 虽然技术难度不是很大 , 但是涉及很多的知识点 , 并且也要处理很多细节 , 对于不善于处理界面 , 并且经验不是很多的开发者来说 , 也是有很大的难度 。 所以 , 平时需要多梳理总结各种界面设计技巧 , 有了丰富的知识储备之后 , 才能以不变应万变 。 另外 , 在工作过程中 , 可以经常留意公司内部的牛人 ,看看他们实现的功能 , 这样的话 , 才能少走弯路 。


    推荐阅读