Qt如何绘制带小三角的消息框

一、简述

本篇文章讲述的是如何绘制出一个带小三角的窗口,请看下图,说白了就是绘制一个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。

这里写图片描述 这里写图片描述

猜你喜欢

转载自blog.csdn.net/goforwardtostep/article/details/80056236