效果图
代码
接口定义尽可能的详细备注到 .h 文件中。
// ArrowWidget.h
#ifndef ARROWWIDGET_H
#define ARROWWIDGET_H
#include <QWidget>
#include <QGraphicsDropShadowEffect>
#include <QLabel>
const int SHADOW_WIDTH = 30; // 窗口阴影宽度;
const int TRIANGLE_WIDTH = 30; // 小三角的宽度;
const int TRIANGLE_HEIGHT = 10; // 小三角的高度;
const int BORDER_RADIUS = 15; // 窗口边角的弧度;
class ArrowWidget : public QWidget
{
Q_OBJECT
public:
ArrowWidget(QWidget* parent = 0);
enum Derection{
left,
right,
up,
down
};
// 设置小三角起始位置;
void setStartPos(int startX);
// 设置小三角宽和高;
void setTriangleInfo(int width, int height);
// 设置展示文本
void setText(QString s);
// 设置小三角的位置
void setDerection(Derection d);
//
QString text();
// 比起左上角的位置 用户更关心小三角的尖尖的位置 重载move以便用户更容易定位气泡框的位置
// x,y 是气泡窗口小贱贱的坐标
void myMove(int x, int y);
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent (QMouseEvent *);
private:
// 小三角的偏移量;
int m_offset;
// 小三角的宽度;
int m_triangleWidth;
// 小三角高度;
int m_triangleHeight;
Derection derect;
QLabel *lb_text;
};
#endif // ARROWWIDGET_H
// ArrowWidget.cpp
#include "arrowwidget.h"
#include <QWidget>
#include <QHBoxLayout>
#include <QPoint>
#include <QPainter>
#include <QImage>
#include <QVariant>
ArrowWidget::ArrowWidget(QWidget *parent):
QWidget(parent),
m_offset(50),
m_triangleWidth(TRIANGLE_WIDTH),
m_triangleHeight(TRIANGLE_HEIGHT)
{
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
QHBoxLayout* hMainLayout = new QHBoxLayout;
setLayout(hMainLayout);
lb_text = new QLabel();
lb_text->setProperty("class", "font14px");
lb_text->setWordWrap(true);
lb_text->setAlignment(Qt::AlignTop);
lb_text->setFixedWidth(304);
lb_text->setStyleSheet("padding: 16px 16px 16px 16px;");
hMainLayout->addWidget(lb_text);
}
// 设置小三角显示的起始位置;
void ArrowWidget::setStartPos(int startX)
{
m_offset = startX;
repaint();
}
void ArrowWidget::setTriangleInfo(int width, int height)
{
m_triangleWidth = width;
m_triangleHeight = height;
}
void ArrowWidget::setText(QString s)
{
lb_text->setText(s);
adjustSize();
}
void ArrowWidget::setDerection(ArrowWidget::Derection d)
{
derect = d;
}
QString ArrowWidget::text()
{
return lb_text->text();
}
void ArrowWidget::myMove(int x, int y)
{
int top_left_x, top_left_y;
switch (derect) {
case down:
top_left_x = x - m_offset - m_triangleWidth / 2 - lb_text->x();
top_left_y = y - m_triangleHeight - lb_text->height() - lb_text->y();
move(QPoint(top_left_x, top_left_y));
break;
case up:
top_left_x = x - m_offset - m_triangleWidth / 2 - lb_text->x();
top_left_y = y + m_triangleHeight - lb_text->y();
move(QPoint(top_left_x, top_left_y));
break;
case left:
top_left_x = x + m_triangleHeight - lb_text->x();
top_left_y = y - m_offset - m_triangleWidth / 2 - lb_text->y();
move(QPoint(top_left_x, top_left_y));
break;
case right:
top_left_x = x - m_triangleHeight - lb_text->width() - lb_text->x();
top_left_y = y - m_triangleWidth / 2 - m_offset - lb_text->y();
move(QPoint(top_left_x, top_left_y));
break;
default:
break;
}
}
void ArrowWidget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(0, 0, 0, 38));
QPainterPath drawPath;
// 小三角区域;
QPolygon trianglePolygon;
QRect myRect(lb_text->x(), lb_text->y(), lb_text->width(), lb_text->height());
// 设置小三的具体位置
int tri_pos_x, tri_pos_y;
switch (derect)
{
case up:{
// 小三角左边的点的位置
tri_pos_x = myRect.x() + m_offset;
tri_pos_y = myRect.y();
trianglePolygon << QPoint(tri_pos_x, tri_pos_y);
trianglePolygon << QPoint(tri_pos_x + m_triangleWidth, tri_pos_y);
trianglePolygon << QPoint(tri_pos_x + m_triangleWidth / 2, tri_pos_y - m_triangleHeight);
}
break;
case left:{
// 小三上边点的位置
tri_pos_x = myRect.x();
tri_pos_y = myRect.y() + m_offset;
trianglePolygon << QPoint(tri_pos_x, tri_pos_y);
trianglePolygon << QPoint(tri_pos_x - m_triangleHeight, tri_pos_y + m_triangleWidth / 2);
trianglePolygon << QPoint(tri_pos_x, tri_pos_y + m_triangleWidth);
}
break;
case right:{
// 小三上边点的位置
tri_pos_x = myRect.x() + myRect.width();
tri_pos_y = myRect.y() + m_offset;
trianglePolygon << QPoint(tri_pos_x, tri_pos_y);
trianglePolygon << QPoint(tri_pos_x + m_triangleHeight, tri_pos_y + m_triangleWidth / 2);
trianglePolygon << QPoint(tri_pos_x, tri_pos_y + m_triangleWidth);
}
break;
case down:{
// 小三左边点的位置
tri_pos_x = myRect.x() + m_offset;
tri_pos_y = myRect.y() + myRect.height();
trianglePolygon << QPoint(tri_pos_x, tri_pos_y);
trianglePolygon << QPoint(tri_pos_x + m_triangleWidth / 2, tri_pos_y + m_triangleHeight);
trianglePolygon << QPoint(tri_pos_x + m_triangleWidth, tri_pos_y);
}
break;
default:
break;
}
drawPath.addRoundedRect(myRect, BORDER_RADIUS, BORDER_RADIUS);
drawPath.addPolygon(trianglePolygon);
painter.drawPath(drawPath);
}
void ArrowWidget::mousePressEvent(QMouseEvent *)
{
// this->close ();
}