QTreeView实现圆角样式
实现 样式 圆角 QTreeView
2023-06-13 09:12:06 时间
大家好,又见面了,我是你们的朋友全栈君。
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中默认为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();
}
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/134345.html原文链接:https://javaforall.cn
相关文章
- 不同样式tooltip对话框小三角的css实现
- C语言中的链表:定义、操作与实现
- 基于redis实现分布式锁的原理与方法
- Linux下实现多线程互斥技术研究(linux多线程互斥)
- C++函数模板声明和实现
- 数据共享远距离:实现Oracle数据共享(远程连接oracle开启)
- Oracle多列统计:实现更丰富的数据分析(oracle多列统计)
- SQL Server解压版:实现云端数据保障(sqlserver解压版)
- Oracle实现高效数据存储:使用SSD技术提升性能(oraclessd)
- MSSQL行累加函数:简易实现(mssql 行累加函数)
- 分离借助Oracle实现冷热数据分离(oracle冷热数据)
- C语言连接Oracle数据库实现安全登录(c 连接oracle登录)
- 解锁MySQL不绑定端口实现更灵活的数据库管理(mysql不绑定端口)
- 借助Redis镜像实现高效部署(redis镜像设置)
- 一个简单但常用的javascript表格样式_鼠标划过行变色简洁实现
- asp.net中Datalist使用数字分页的实现方法
- 文本框input聚焦失焦样式实现代码
- jquery实现表格奇数偶数行不同样式(有图为证及实现代码)
- JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
- 修改file按钮的默认样式实现代码
- JQuery+DIV自定义滚动条样式的具体实现
- webcss实现整站样式互相切换
- Javascript实现返回上一页面并刷新的小例子
- 使用jquery+CSS实现控制打印样式
- js实现class样式的修改、添加及删除的方法
- Jquery实现table样式的设定