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