qt creator 设置按键颜色_Qt编写自定义控件46-树状导航栏

一、前言

树状导航栏控件是所有控件中最牛逼最经典最厉害的一个,在很多用户中,使用频率也是最高,因为该导航控件集合了非常多的展示效果,比如左侧图标+右侧箭头+元素前面的图标设置+各种颜色设置等,全部涵盖了,代码量也比较多,该控件前后完善了三年,还提供了角标展示文字信息,纵观市面上web也好,cs架构的程序也好,这种导航条使用非常多,目前只提供了二级菜单,如果需要三级菜单需要自行更改源码才行。

二、实现的功能

* 1:设置节点数据相当方便,按照对应格式填入即可,分隔符,

* 2:可设置提示信息 是否显示+宽度

* 3:可设置行分隔符 是否显示+高度+颜色

* 4:可设置选中节点线条突出显示+颜色+左侧右侧位置

* 5:可设置选中节点三角形突出显示+颜色+左侧右侧位置

* 6:可设置父节点的 选中颜色+悬停颜色+默认颜色

* 7:可设置子节点的 选中颜色+悬停颜色+默认颜色

* 8:可设置父节点文字的 图标边距+左侧距离+字体大小+高度

* 9:可设置子节点文字的 图标边距+左侧距离+字体大小+高度

* 10:可设置节点展开模式 单击+双击+禁用

三、效果图

efa8147ad0c6c018398103b8afda06f8.gif

四、核心代码

void NavDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{ painter->setRenderHint(QPainter::Antialiasing); NavModel::TreeNode *node = (NavModel::TreeNode *)index.data(Qt::UserRole).toULongLong(); //定义变量存储区域 QRect optionRect = option.rect; int x = optionRect.x(); int y = optionRect.y(); int width = optionRect.width(); int height = optionRect.height(); int fontSize = nav->getParentFontSize(); //父节点和子节点颜色分开设置 bool parent = (node->level == 1); //根据不同的状态设置不同的颜色 bgColor-主背景色 textColor-主文字颜色 tipBgColor-提示信息背景颜色 tipTextColor-提示信息文字颜色 QColor bgColor, textColor, tipBgColor, tipTextColor, iconColor; if (option.state & QStyle::State_Selected) { bgColor = parent ? nav->getParentBgSelectedColor() : nav->getChildBgSelectedColor(); textColor = parent ? nav->getParentTextSelectedColor() : nav->getChildTextSelectedColor(); tipBgColor = parent ? nav->getParentTextSelectedColor() : nav->getChildTextSelectedColor(); tipTextColor = parent ? nav->getParentBgSelectedColor() : nav->getChildBgSelectedColor(); iconColor = parent ? nav->getParentTextSelectedColor() : nav->getChildTextSelectedColor(); } else if (option.state & QStyle::State_MouseOver) { bgColor = parent ? nav->getParentBgHoverColor() : nav->getChildBgHoverColor(); textColor = parent ? nav->getParentTextHoverColor() : nav->getChildTextHoverColor(); tipBgColor = parent ? nav->getParentTextSelectedColor() : nav->getChildTextSelectedColor(); tipTextColor = parent ? nav->getParentBgSelectedColor() : nav->getChildBgSelectedColor(); iconColor = parent ? nav->getParentTextHoverColor() : nav->getChildTextHoverColor(); } else { bgColor = parent ? nav->getParentBgNormalColor() : nav->getChildBgNormalColor(); textColor = parent ? nav->getParentTextNormalColor() : nav->getChildTextNormalColor(); tipBgColor = parent ? nav->getParentBgSelectedColor() : nav->getChildBgSelectedColor(); tipTextColor = parent ? nav->getParentTextSelectedColor() : nav->getChildTextSelectedColor(); iconColor = parent ? nav->getParentTextNormalColor() : nav->getChildTextNormalColor(); } //绘制背景 painter->fillRect(optionRect, bgColor); //绘制线条,目前限定子节点绘制,如果需要父节点也绘制则取消parent判断即可 int lineWidth = nav->getLineWidth(); if (!parent && nav->getLineVisible() && lineWidth > 0) { if ((option.state & QStyle::State_Selected) || (option.state & QStyle::State_MouseOver)) { //设置偏移量,不然上下部分会有点偏移 float offset = (float)lineWidth / 2; //计算上下两个坐标点 QPointF pointTop(x, y + offset); QPointF pointBottom(x, height + y - offset); if (!nav->getLineLeft()) { pointTop.setX(width); pointBottom.setX(width); } //设置线条颜色和宽度 painter->setPen(QPen(nav->getLineColor(), lineWidth)); painter->drawLine(pointTop, pointBottom); } } //绘制三角形,目前限定子节点绘制,如果需要父节点也绘制则取消parent判断即可 int triangleWidth = nav->getTriangleWidth(); if (!parent && nav->getTriangleVisible() && triangleWidth > 0) { if ((option.state & QStyle::State_Selected) || (option.state & QStyle::State_MouseOver)) { QFont font = iconFont; font.setPixelSize(fontSize + triangleWidth); painter->setFont(font); painter->setPen(nav->getTriangleColor()); //采用图形字体中的三角形绘制 if (nav->getTriangleLeft()) { painter->drawText(optionRect, Qt::AlignLeft | Qt::AlignVCenter, QChar(0xf0da)); } else { painter->drawText(optionRect, Qt::AlignRight | Qt::AlignVCenter, QChar(0xf0d9)); } } } //绘制行分隔符 if (nav->getSeparateVisible()) { if (node->level == 1 || (node->level == 2 && node->last)) { painter->setPen(QPen(nav->getSeparateColor(), nav->getSeparateHeight())); painter->drawLine(QPointF(x, y + height), QPointF(x + width, y + height)); } } //绘制文字,如果文字为空则不绘制 QString text = node->text; if (!text.isEmpty()) { //文字离左边的距离+字体大小 int margin = nav->getParentMargin(); if (node->level == 2) { margin = nav->getChildMargin(); fontSize = nav->getChildFontSize(); } //计算文字区域 QRect textRect = optionRect; textRect.setWidth(width - margin); textRect.setX(x + margin); QFont font; font.setPixelSize(fontSize); painter->setFont(font); painter->setPen(textColor); painter->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text); } //绘制提示信息,如果不需要显示提示信息或者提示信息为空则不绘制 QString tip = node->tip; if (nav->getTipVisible() && !tip.isEmpty()) { //如果是数字则将超过999的数字显示成 999+ //如果显示的提示信息长度过长则将多余显示成省略号 . if (tip.toInt() > 0) { tip = tip.toInt() > 999 ? "999+" : tip; } else if (tip.length() > 2) { tip = tip.left(2) + " ."; } //计算绘制区域,半径取高度的四分之一 int radius = height / 4; QRect tipRect = optionRect; tipRect.setHeight(radius * 2); tipRect.moveCenter(optionRect.center()); tipRect.setLeft(optionRect.right() - nav->getTipWidth() - 5); tipRect.setRight(optionRect.right() - 5); //设置字体大小 QFont font; font.setPixelSize(fontSize - 2); painter->setFont(font); //绘制提示文字的背景 painter->setPen(Qt::NoPen); painter->setBrush(tipBgColor); painter->drawRoundedRect(tipRect, radius, radius); //绘制提示文字 painter->setPen(tipTextColor); painter->setBrush(Qt::NoBrush); painter->drawText(tipRect, Qt::AlignCenter, tip); } //计算绘制图标区域 QRect iconRect = optionRect; iconRect.setLeft(parent ? nav->getParentIconMargin() : nav->getChildIconMargin()); //设置图形字体和画笔颜色 QFont font = iconFont; font.setPixelSize(fontSize); painter->setFont(font); painter->setPen(textColor); //绘制左侧图标,有图标则绘制图标,没有的话父窗体取 + - if (!node->icon.isNull()) { painter->drawText(iconRect, Qt::AlignLeft | Qt::AlignVCenter, node->icon); } else if (parent) { if (node->expand) { painter->drawText(iconRect, Qt::AlignLeft | Qt::AlignVCenter, QChar(0xf067)); } else { painter->drawText(iconRect, Qt::AlignLeft | Qt::AlignVCenter, QChar(0xf068)); } } //绘制父节点右侧图标 iconRect.setRight(optionRect.width() - 10); if (!(nav->getTipVisible() && !node->tip.isEmpty()) && nav->getRightIconVisible() && parent) { if (node->expand) { painter->drawText(iconRect, Qt::AlignRight | Qt::AlignVCenter, QChar(0xf054)); } else { painter->drawText(iconRect, Qt::AlignRight | Qt::AlignVCenter, QChar(0xf078)); } }}

六、控件介绍

1. 超过150个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。

2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。

3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等编译器,支持任意操作系统比如windows+linux+mac+嵌入式linux等,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。

4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。

5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。

6. 每个控件默认配色和demo对应的配色都非常精美。

7. 超过130个可见控件,6个不可见控件。

8. 部分控件提供多种样式风格选择,多种指示器样式选择。

9. 所有控件自适应窗体拉伸变化。

10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。

11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。

12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。

13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

14. 目前已经有qml版本,后期会考虑出pyqt版本,如果用户需求量很大的话。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
旋转仪表盘是一种常见的显示件,可以用来展示一些数据,如速度、油量、温度等,下面我将介绍如何使用Qt编写一个旋转仪表盘件。 首先,我们需要在Qt中创建一个新的自定义件类。可以通过Qt Creator中的“添加新文件”功能来创建一个QWidget派生类。在这个类中,我们需要实现paintEvent()函数来绘制仪表盘。 在paintEvent()函数中,我们可以使用QPainter来绘制仪表盘的各个部分,包括刻度线、指针、文字等。具体实现可以参考以下代码: ```C++ void RotatingDial::paintEvent(QPaintEvent *event) { // 设置背景色 QPalette pal(palette()); pal.setColor(QPalette::Background, Qt::white); setAutoFillBackground(true); setPalette(pal); // 绘制刻度线 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); painter.translate(width() / 2, height() / 2); painter.setPen(QPen(Qt::black, 2)); for (int i = 0; i < 60; i++) { painter.drawLine(0, -100, 0, -90); painter.rotate(6); } // 绘制指针 painter.save(); painter.rotate(m_angle); painter.setBrush(Qt::red); painter.setPen(Qt::NoPen); painter.drawConvexPolygon(m_pointer, 3); painter.restore(); // 绘制文字 QFont font("Arial", 12, QFont::Bold); painter.setFont(font); painter.drawText(-30, 50, "Speed"); } ``` 在上面的代码中,我们首先设置件的背景色为白色。然后使用QPainter绘制了60条刻度线,并旋转6度。接着,我们绘制了一个红色的指针,并根据m_angle属性来旋转指针的角度。最后,我们使用QPainter绘制了文字“Speed”。 在我们的自定义件中,我们需要一个属性来制指针的角度。我们可以使用Q_PROPERTY宏来定义这个属性,例如: ```C++ class RotatingDial : public QWidget { Q_OBJECT Q_PROPERTY(int angle READ angle WRITE setAngle) public: RotatingDial(QWidget *parent = nullptr); int angle() const; void setAngle(int angle); private: int m_angle; QPolygon m_pointer; }; ``` 在上面的代码中,我们使用Q_PROPERTY宏定义了angle属性,并提供了getter和setter函数。我们还定义了一个私有变量m_angle来存储当前的角度,以及一个QPolygon对象m_pointer来存储指针的形状。 在setAngle()函数中,我们设置m_angle属性,并根据新的角度计算指针的位置: ```C++ void RotatingDial::setAngle(int angle) { if (angle != m_angle) { m_angle = angle; m_pointer.setPoint(0, QPoint(0, -90)); m_pointer.setPoint(1, QPoint(5, 0)); m_pointer.setPoint(2, QPoint(-5, 0)); m_pointer.translate(0, 100); update(); } } ``` 在上面的代码中,我们首先判断新的角度是否与当前的角度相同。如果不同,我们就更新m_angle属性,并重新计算指针的位置。最后,我们调用update()函数来触发paintEvent()函数的调用,从而完成件的重绘。 最后,我们可以在MainWindow类中使用我们的自定义件,例如: ```C++ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { RotatingDial *dial = new RotatingDial(this); dial->setAngle(30); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(dial); setCentralWidget(new QWidget); centralWidget()->setLayout(layout); } ``` 在上面的代码中,我们创建了一个RotatingDial对象,并设置了初始角度为30度。然后,将其添加到QHBoxLayout布局中,并设置为主窗口的中央件。 至此,我们已经完成了一个简单的旋转仪表盘的自定义件。你可以根据需要对其进行扩展和优化,使其更加适合你的应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值