QT实现聊天气泡样式的绘制利用QPainterPath 绘制一个Rect + Triangle

0 1108
索鸟 2021-03-19
需要:0索币

一、简述

本篇文章讲述的是如何绘制出一个带小三角的窗口,请看下图,说白了就是绘制一个Rect + Triangle ,然后添加外部阴影效果。


二、代码之路

ArrowWidget.h

#ifndef WIDGET_H

#define WIDGET_H

#include <QWidget>

class ArrowWidget : public QWidget

{

    Q_OBJECT


public:

    ArrowWidget(QWidget *parent = 0);


    // 设置小三角起始位置;

    void setStartPos(int startX);


    // 设置小三角宽和高;

    void setTriangleInfo(int width, int height);


    // 设置中间区域widget;

    void setCenterWidget(QWidget* widget);


protected:

    void paintEvent(QPaintEvent *);


private:

    // 小三角起始位置;

    int m_startX;

    // 小三角的宽度;

    int m_triangleWidth;

    // 小三角高度;

    int m_triangleHeight;

};  


#endif


ArrowWidget.cpp

#include "ArrowWidget.h"

#include <QHBoxLayout>

#include <QPainter>

#include <QGraphicsDropShadowEffect>


#define SHADOW_WIDTH 15                 // 窗口阴影宽度;

#define TRIANGLE_WIDTH 15               // 小三角的宽度;

#define TRIANGLE_HEIGHT 10              // 小三角的高度;

#define BORDER_RADIUS 5                 // 窗口边角的弧度;


ArrowWidget::ArrowWidget(QWidget *parent)

    : QWidget(parent)

    , m_startX(50)

    , m_triangleWidth(TRIANGLE_WIDTH)

    , m_triangleHeight(TRIANGLE_HEIGHT)

{

    setWindowFlags(Qt::FramelessWindowHint);

    setAttribute(Qt::WA_TranslucentBackground);


    // 设置阴影边框;

    auto shadowEffect = new QGraphicsDropShadowEffect(this);

    shadowEffect->setOffset(0, 0);

    shadowEffect->setColor(Qt::gray);

    shadowEffect->setBlurRadius(SHADOW_WIDTH);

    this->setGraphicsEffect(shadowEffect);


    setFixedSize(150, 200);

}


void ArrowWidget::setCenterWidget(QWidget* widget)

{

    QHBoxLayout* hMainLayout = new QHBoxLayout(this);

    hMainLayout->addWidget(widget);

    hMainLayout->setSpacing(0);

    hMainLayout->setContentsMargins(SHADOW_WIDTH, SHADOW_WIDTH + TRIANGLE_HEIGHT, SHADOW_WIDTH, SHADOW_WIDTH);

}


// 设置小三角显示的起始位置;

void ArrowWidget::setStartPos(int startX)

{

    m_startX = startX;

}


void ArrowWidget::setTriangleInfo(int width, int height)

{

    m_triangleWidth = width;

    m_triangleHeight = height;

}


void ArrowWidget::paintEvent(QPaintEvent *)

{

    QPainter painter(this);

    painter.setRenderHint(QPainter::Antialiasing, true);

    painter.setPen(Qt::NoPen);

    painter.setBrush(QColor(255, 255, 255));


    // 小三角区域;

    QPolygon trianglePolygon;

    trianglePolygon << QPoint(m_startX, m_triangleHeight + SHADOW_WIDTH);

    trianglePolygon << QPoint(m_startX + m_triangleWidth / 2, SHADOW_WIDTH);

    trianglePolygon << QPoint(m_startX + m_triangleWidth, m_triangleHeight + SHADOW_WIDTH);


    QPainterPath drawPath;

    drawPath.addRoundedRect(QRect(SHADOW_WIDTH, m_triangleHeight + SHADOW_WIDTH,\

                                width() - SHADOW_WIDTH * 2, height() - SHADOW_WIDTH * 2 - m_triangleHeight),\

                                BORDER_RADIUS, BORDER_RADIUS);

    // Rect + Triangle;

    drawPath.addPolygon(trianglePolygon);

    painter.drawPath(drawPath);

}

测试代码

    QLabel* textLabel = new QLabel;

    textLabel->setAlignment(Qt::AlignCenter);

    textLabel->setText("ArrowWidget");


    ArrowWidget w;

    w.setStartPos(60);

    w.setTriangleInfo(20, 12);

    w.setFixedSize(QSize(150, 80));

    w.setCenterWidget(textLabel);

    w.show();


本例子提供了设置三个接口.


(1)setStartPos

设置小三角在底部的起始位置,注意不能设置为0,因为整个窗口外部加了阴影边框,所以你所看到的白色矩形区域的起始点为阴影边框宽度。


(2)setTriangleInfo

设置小三角的宽和高,这里可以任意调整小三角的宽高,但是得注意设置整个窗口的宽高,使其比例适中。


(3) setCenterWidget

设置窗口中间区域的widget,这里我们可以将自己写好的widget使用此方法设置到窗口的内部。上图中我们嵌入了一个带文字的QLabel。

原文链接:https://blog.csdn.net/GoForwardToStep/article/details/80056236

回帖
  • 消灭零回复
相关主题
2020年最新最新Kubernetes视频教程(K8s)教程 2
程序员转型之制作网课变现,月入过万告别996 1
索鸟快传2.0发布啦 1
两个不同网络的电脑怎么实现文件的互相访问呢? 1
网盘多账号登录软件 1
Java实战闲云旅游项目基于vue+element-ui 1
单点登录技术解决方案基于OAuth2.0的网关鉴权RSA算法生成令牌 1
QT5获取剪贴板上文本信息QT设置剪贴板内容 1
springboot2实战在线购物系统电商系统 1
python web实战之爱家租房项目 1
windows COM实用入门教程 1
C++游戏开发之C++实现的水果忍者游戏 1
计算机视觉库opencv教程 1
node.js实战图书管理系统express框架实现 1
C++实战教程之远程桌面远程控制实战 1
相关主题
PHP7报A non well formed numeric value encountered 0
Linux系统下关闭mongodb的几种命令分享 0
mongodb删除数据、删除集合、删除数据库的命令 0
Git&Github极速入门与攻坚实战课程 0
python爬虫教程使用Django和scrapy实现 0
libnetsnmpmibs.so.31: cannot open shared object file 0
数据结构和算法视频教程 0
redis的hash结构怎么删除数据呢? 0
C++和LUA解析器的数据交互实战视频 0
mongodb errmsg" : "too many users are authenticated 0
C++基础入门视频教程 0
用30个小时精通C++视频教程可能吗? 0
C++分布式多线程游戏服务器开发视频教程socket tcp boost库 0
C++培训教程就业班教程 0
layui的util工具格式时间戳为字符串 0
C++实战教程之远程桌面远程控制实战 1
网络安全培训视频教程 0
LINUX_C++软件工程师视频教程高级项目实战 0
C++高级数据结构与算法视频教程 0
跨域问题很头疼?通过配置nginx轻松解决ajax跨域问题 0