QTreeView实现圆角样式

在QTreeView等继承于QAbstractItemView表格中,定制表格样式通常都是通过设置项目代理(ItemDelegate)来实现。在这种实现方法中,每个项目(Item)基本上是孤立的,无法有效判断己身周遭环境。
如果以此种方法来实现圆角样式,行首或许还能通过方法int QModelindex::column()来判断是否属于第一列来断定,然而行尾难道还要通过QAbstractItemModel QModelindex::*model()获取模型(Model)之后再来判断吗?且视图(View)本身可以隐藏、拖拽指定行、列,所以这种方式并不靠谱。
更正:
QStyleOptionViewItem提供了获取可视项目位置的接口,可通过

QStyleOptionViewItem::viewItemPosition

这个枚举值获取。更正此处错误描述并更新

QPainterPath TreeViewStyle::roundedPath(const QStyleOptionViewItem *o, const QWidget *w) const

样式表(StyleSheet)似乎也不支持此种操作。

继承QProxyStyle

为了保持与系统或部件所使用的样式一致,应当选择继承QProxyStyle而非QStyle及其它(QCommonStyle等)。

class TreeViewStyle : public QProxyStyle
{Q_OBJECT
public:explicit TreeViewStyle(QStyle *style = nullptr);
}

重载绘制函数

    void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;

绘制选中状态

    void drawPanelItemViewRow(const QStyleOption *opt, QPainter *p, const QWidget *w) const;

绘制行背景

行背景即列表背景,通常情况下没有绘制。一般仅在设置了行颜色交替的情况下绘制。

    void drawPanelItemViewItem(const QStyleOption *opt, QPainter *p, const QWidget *w) const;

绘制路径计算函数

计算绘制路径即选中状态、行背景所需绘制区域。

    QPainterPath roundedPath(const QStyleOptionViewItem *opt, const QWidget *w) const;

用法

QTreeView view = new QTreeView(this);
view->setStyle(new TreeViewStyle(view->style()));

效果

相关代码

TreeViewStyle.h

#ifndef TREEVIEWSTYLE_H
#define TREEVIEWSTYLE_H#include <QProxyStyle>class QStyleOptionViewItem;
class TreeViewStyle : public QProxyStyle
{Q_OBJECT
public:explicit TreeViewStyle(QStyle *style = nullptr);void drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const override;QPainterPath roundedPath(const QStyleOptionViewItem *opt, const QWidget *w) const;void drawPanelItemViewRow(const QStyleOption *opt, QPainter *p, const QWidget *w) const;void drawPanelItemViewItem(const QStyleOption *opt, QPainter *p, const QWidget *w) const;
};#endif // TREEVIEWSTYLE_H

TreeViewStyle.cpp

#include "TreeViewStyle.h"#include <QStyleOption>
#include <QPainter>
#include <DStyle> //仅用于获取部件设置的圆角大小,非Dtk用户请删除此行TreeViewStyle::TreeViewStyle(QStyle *style) : QProxyStyle(style)
{}void TreeViewStyle::drawPrimitive(QStyle::PrimitiveElement pe, const QStyleOption *opt, QPainter *p, const QWidget *w) const
{switch (pe) {case PE_PanelItemViewRow:drawPanelItemViewRow(opt, p, w);break;case PE_PanelItemViewItem:drawPanelItemViewItem(opt, p, w);break;default:QProxyStyle::drawPrimitive(pe, opt, p, w);break;}
}QPainterPath TreeViewStyle::roundedPath(const QStyleOptionViewItem *o, const QWidget *w) const
{int radius = Dtk::Widget::DStyle::pixelMetric(this, Dtk::Widget::DStyle::PM_FrameRadius, o, w); //用于获取部件设置的圆角大小,非Dtk用户请直接设置radius的值,Dtk中默认为8QPainterPath path;path.setFillRule(Qt::WindingFill);QRect corner(0, 0, radius, o->rect.height());switch (o->viewItemPosition) {case QStyleOptionViewItem::Beginning:path.addRoundedRect(o->rect, radius, radius);corner.moveTopRight(o->rect.topRight());path.addRect(corner);break;case QStyleOptionViewItem::End:path.addRoundedRect(o->rect, radius, radius);corner.moveTopLeft(o->rect.topLeft());path.addRect(corner);break;case QStyleOptionViewItem::OnlyOne:path.addRoundedRect(o->rect, radius, radius);break;case QStyleOptionViewItem::Middle:path.addRect(o->rect);break;case QStyleOptionViewItem::Invalid:break;}
//    path.addRoundedRect(o->rect, radius, radius);
//    QRect corner;
//    corner.setSize({radius, radius});
//    if (o->rect.right() != w->rect().right()) {//        corner.moveTopRight(o->rect.topRight());
//        path.addRect(corner);
//        corner.moveBottomRight(o->rect.bottomRight());
//        path.addRect(corner);
//    }
//    if (o->rect.left() != w->rect().left()) {//        corner.moveTopLeft(o->rect.topLeft());
//        path.addRect(corner);
//        corner.moveBottomLeft(o->rect.bottomLeft());
//        path.addRect(corner);
//    }return path;
}void TreeViewStyle::drawPanelItemViewRow(const QStyleOption *opt, QPainter *p, const QWidget *w) const
{p->save();if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {p->setRenderHint(QPainter::Antialiasing);QPainterPath path = roundedPath(vopt, w);QPalette::ColorGroup cg = (w ? w->isEnabled() : (vopt->state & QStyle::State_Enabled))? QPalette::Normal : QPalette::Disabled;if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))cg = QPalette::Inactive;if ((vopt->state & QStyle::State_Selected) &&  proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, w))p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));else if (vopt->features & QStyleOptionViewItem::Alternate)p->fillPath(path, vopt->palette.brush(cg, QPalette::AlternateBase));}p->restore();
}void TreeViewStyle::drawPanelItemViewItem(const QStyleOption *opt, QPainter *p, const QWidget *w) const
{p->save();if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(opt)) {p->setRenderHint(QPainter::Antialiasing);QPainterPath path = roundedPath(vopt, w);QPalette::ColorGroup cg = (w ? w->isEnabled() : (vopt->state & QStyle::State_Enabled))? QPalette::Normal : QPalette::Disabled;if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))cg = QPalette::Inactive;if (vopt->showDecorationSelected && (vopt->state & QStyle::State_Selected)) {p->fillPath(path, vopt->palette.brush(cg, QPalette::Highlight));} else {if (vopt->backgroundBrush.style() != Qt::NoBrush) {QPointF oldBO = p->brushOrigin();p->setBrushOrigin(vopt->rect.topLeft());p->fillPath(path, vopt->backgroundBrush);p->setBrushOrigin(oldBO);}if (vopt->state & QStyle::State_Selected) {QRect textRect = subElementRect(QStyle::SE_ItemViewItemText,  opt, w);p->fillRect(textRect, vopt->palette.brush(cg, QPalette::Highlight));}}}p->restore();
}

联系方式

QQ群:236510798

QTreeView实现圆角样式相关推荐

  1. 【响应式Web前端设计】css如何设置边框的圆角样式?border-radius属性设置圆角样式(图 文)

    border-radius包含5种设置圆角样式方式: border-radius :同时设置4个边框的圆角样式. border-top-left-radius :设置左上角边框的圆角样式. borde ...

  2. div css 圆角样式

    代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3. ...

  3. 二维码彩色广告招牌的切割制作问题(C#.net下对彩色二维码圆角样式及改进)...

    原文:二维码彩色广告招牌的切割制作问题(C#.net下对彩色二维码圆角样式及改进) 我们知道,目前二维码还很少用于广告招牌的制作.但随着智能手机越来越普及,互联网等网络的应用也越来越广泛,作为连接物理 ...

  4. html设置input圆角矩形_css怎么实现按钮圆角样式的展示效果?(示例)

    在网页设计过程中,一般标签属性默认的效果都不是太美观,就比如按钮样式,默认状态是极其普通毫无美感.那么本篇文章就给大家介绍关于css设置按钮样式之圆角按钮效果的相关操作示例. 代码如下: 或者 效果如 ...

  5. CSS制作类似浏览器标题栏的圆角样式

    制作一个类似浏览器标题栏的tab切换效果CSS样式 圆弧的样式由 元素本身 + 左右两个小角 组成 首先,将元素设置 相对定位 + 圆角边框,以及宽高设为: position: relative; / ...

  6. DIV设置圆角样式属性

    原始JS版本 <!DOCTYPE html> <html> <head> <style> div { text-align:center; border ...

  7. css 边框和圆角样式

    边框设置border:solid npx; 边框为npx的实线border:solid npx 颜色; 边框的颜色border-radius: npx ; 边框角为npx的弧度border-radiu ...

  8. php input框圆角样式,CSS如何实现边框圆角

    CSS实现边框圆角需要用到CSS中的border-radius属性,下面我们就来看看CSS实现圆角边框的详细内容. 我们下来看一个没有圆角的边框实现代码 这是一个框架 效果如下: 接下来我们就来具体看 ...

  9. android 内凹的圆角,css实现内凹圆角样式

    最新开发遇到一个弹框,弹框中间有两个内凹的半圆,而且还是透明的,不能遮挡到底层的内容.基于这个需求,找到了一个比较好的实现方法. 先上一下demo效果图: image.png 实现这个效果主要是用了b ...

  10. css 类似优惠券邮票那样的内抠圆角样式,内凹圆角处理

    1.优惠券如图这样: 实现: <!DOCTYPE html> <html lang="en"> <head><meta charset=& ...

最新文章

  1. LRU算法 -- 链表 完整实现
  2. yum 代理_教你如何在5分钟轻松部署nginx反向代理
  3. 可以获取python整数类型帮助的是什么-Python 的数值类型(整数、长整数、浮点数和复数)...
  4. STM32-中断优先级
  5. 基于QGraphics的简易画板1
  6. Amazon Lambda支持以简单队列服务作为事件源了
  7. object-fit 解决图片指定大小被压缩问题
  8. PHP password_hash 与 password_verify 使用
  9. 第五章:Flask数据库操作
  10. 抖音数据统计_【数据】2018抖音大数据报告(完整版)
  11. 11:c# oop思想面向对象编程(by-朝夕)
  12. 从原理到实战,一份详实的 Scrapy 爬虫教程
  13. 工作3年以上的程序员现在都在做什么工作?
  14. 现代黑科技版“指鹿为马:使用CycleGAN实现男女“无痛变性”
  15. 程序员应该如何对待面试?
  16. 从NIB中加载VIEW
  17. PHP 将数组按照Key分组
  18. 美国芯片后悔莫及,中国芯片自主制造取得突破,芯片出口猛增
  19. c语言经典01背包问题——洛谷P2871
  20. 各类通信协议归纳整理(偏硬件)

热门文章

  1. 【Matlab绘图】plot3函数绘制三维点或线图
  2. 计算机文化基础心得体会1500字,《计算机文化基础教学改革与实践》工作总结报告.docx...
  3. 计算机文化基础练习题及答案
  4. c语言节点的作用,C语言试题
  5. 《符号学:原理与推演》(一)符号的构成
  6. 什么是车辆识别代码(VIN)
  7. 安徽宣城职业技术学院引入USB Server远程管理加密狗
  8. Java工作流有哪些?如何快速掌握Java技术
  9. nas918+支持的cpu_cpu拷机软件推荐:cpu烤机用什么软件
  10. Ribbon界面开发:如何创建Ribbon样式的应用程序框架