这个原理简单,就是调用QWidget::setMask(...)设置窗口的掩膜实现异形窗口。下面的代码环境是VS2015和Qt5.9。其运行效果图如下,就是下图中显示“显示气球控件”文本的窗口:
头文件:
class MBalloonTip : public QWidget { Q_OBJECT public: static void showText(const QPoint& pos, const QString& itext, int msec = 5000); static void showText(QWidget* widget, const QString& itext, int msec = 5000); private: MBalloonTip(QWidget* parent = 0); ~MBalloonTip(); void paintEvent(QPaintEvent *event) override; QBitmap raiseShape(); void setAutoCloseTimer(int msec); private: static const QPoint hotspot; QBitmap bitmap; QString text; };
CPP文件。下方将窗口设为Popup型的,这个类型的窗口没有边框并且失去活动焦点会自动关闭:
const QPoint MBalloonTip::hotspot(30, 0); MBalloonTip::MBalloonTip(QWidget* parent) : QWidget(parent) { setWindowFlags(Qt::Popup | Qt::WindowStaysOnTopHint); setAttribute(Qt::WA_DeleteOnClose); } MBalloonTip::~MBalloonTip() { qDebug() << "delete"; } void MBalloonTip::showText(QWidget* widget, const QString& itext, int msec) { QSize size = widget->size(); QPoint pos = widget->mapToGlobal(QPoint(size.width() / 2, size.height())); showText(pos, itext, msec); } void MBalloonTip::showText(const QPoint& pos, const QString& itext, int msec) { MBalloonTip *tips = new MBalloonTip; tips->text = itext; QFontMetrics fm = tips->fontMetrics(); QSize sz = fm.size(0, itext); sz.setWidth(qMax(sz.width(), 48)); /* 最小宽度48 */ /* 尺寸之宽高。宽边距18,高边距18加上上方箭头13像素 */ tips->setGeometry(pos.x() - hotspot.x(), pos.y() - hotspot.y(), sz.width() + 18, sz.height() + 31); tips->bitmap = tips->raiseShape(); tips->setMask(tips->bitmap); /* 这个掩膜是白色隐藏黑色显示 */ tips->show(); /* 自动关闭 */ tips->setAutoCloseTimer(msec); } void MBalloonTip::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(QPen(Qt::black, 1)); painter.setBrush(QColor(255, 255, 232)); QPainterPath ppath1; /* 之所以是14为了跟content矩形相交 */ /* content矩形的上边y轴坐标是13 */ QVector<QPointF> points = { { 30, 0 },{ 30, 14 },{ 44, 14 } }; ppath1.addPolygon(points); QPainterPath ppath2; QRectF content(0, 13, width(), height() - 13); ppath2.addRoundedRect(content, 6, 6); painter.drawPath(ppath1 | ppath2); painter.setPen(Qt::black); painter.setBrush(Qt::NoBrush); painter.drawText(content, Qt::AlignCenter, text); } void MBalloonTip::setAutoCloseTimer(int msec) { /* 定时关闭窗口 */ QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this]() { close(); }); timer->setInterval(msec); timer->start(); } QBitmap MBalloonTip::raiseShape() { QBitmap bitmap(size()); bitmap.fill(Qt::white); QPainter painter(&bitmap); painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); const QPointF points[] = { { 30, 0 }, { 30, 14 }, { 44, 14 } }; painter.drawPolygon(points, 3); QRectF rectangle(0, 13, width(), height() - 13); painter.drawRoundedRect(rectangle, 6, 6); return bitmap; }
标签:窗口,Qt,异形,msec,MBalloonTip,const,tips,painter From: https://www.cnblogs.com/mengxiangdu/p/17894390.html