QTreeView实现圆角样式

QTreeView实现圆角样式QTreeView实现圆角样式在QTreeView等继承于QAbstractItemView表格中,定制表格样式通常都是通过设置项目代理(ItemDelegate)来实现。在这种实现方法中,每个项目(Item)基本上是孤立的,无法有效判断己身周遭环境。如果以此种方法来实现圆角样式,行首或许还能通过方法intQModelindex::column()来判断是否属于第一列来断定,然而行尾难道还要通过QAbstractItemModelQModelindex::*model()获取模型(Model)之后再

大家好,又见面了,我是你们的朋友全栈君。

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()));

效果

圆角样式的QTreeView,选中行的色块与颜色交替行的色块四角都是圆角

相关代码

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中默认为8
QPainterPath 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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/134345.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 提问智慧的oracle问题

    提问智慧的oracle问题提问的智慧Oracle版0。尝试在google,论坛,metalink,onlinedocument里搜索。1。写清楚你的执行log,报错信息,写清楚DBversion,OS 2。Instance方面的问题,请贴出alertlog3。network的问题,贴出server的listener.ora,sqlnet.ora并运行lsnrctlservice,贴出cl

  • 介绍书中人物(笼中月介绍)

    远程对象的基础接口,是一个为了在执行进程中和进程间调用时的高性能,而设计的轻量级远程调用机制的核心部分。这个接口描述了和远程对象交互的抽象协议。不要直接实现这个接口,而是通过继承 Binder来实现。IBinder的关键API是与 Binder.onTransact() 相匹配的transact() .这个方法分别允许你给IBinder对象发出一个请求,并接收一个进入一个Binde

  • 最近才有机会接触aspnetmvc框架

    最近才有机会接触aspnetmvc框架最近公司有个新的项目,我是项目团队的leader,主要负责项目需求分析、系统的设计、数据库设计和整个系统框架的编写。准备采用aspnetmvc+entityframework+jueryeasyui进行开发。以后我会公布开发过程和心得!期待哦。

  • double转BigDecimal精度丢失的解决方案。

    double转BigDecimal精度丢失的解决方案。因为double有精度丢失的问题,所以关于小数点的计算通常使用BigDecimal来计算。但直接调用BigDecimal的构造函数,会出现精度丢失问题。publicBigDecimal(doubleval){this(val,MathContext.UNLIMITED);}例子:publicclassDemo1{publicstaticvoidmain(String[]args){//输出结果:4.7999999999999998223

  • mac配置IDEA热部署[通俗易懂]

    mac配置IDEA热部署[通俗易懂]1、pom文件中添加依赖<!–开启热部署–><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional&gt

  • PHP fopen/file_get_contents与curl性能比较

    PHP fopen/file_get_contents与curl性能比较

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号