先上效果图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e4fb6d9eb20ce99ff50873877fe1e3ba.gif#pic_center)
代码实现
带小三角的悬浮提示窗口
#ifndef TIPLABEL_H
#define TIPLABEL_H
#include <QLabel>
class TipLabel : public QLabel
{
Q_OBJECT
public:
TipLabel(const QString& text, QWidget *parent = nullptr);
bool eventFilter(QObject*,QEvent*) override;
QSize sizeHint() const override;
void updatePos(const QPoint& pos);
using CallBackType = std::function<QPoint ()>;
void setCallBack( CallBackType updatePosCallBack);
void setTopWindow(QWidget* w);
protected:
void paintEvent(QPaintEvent*) override;
private:
CallBackType updatePosCallBack;
QWidget* top_widget{nullptr};
};
#endif
#include "tiplabel.h"
#include <QApplication>
#include <QMouseEvent>
#include <QPainter>
#include <QPolygon>
namespace {
const int kTriangleHeight = 8;
const int kTriangleWidth = 20;
const int kTriangleLeftMargin = 30;
}
TipLabel::TipLabel(const QString &text, QWidget *parent)
:QLabel(parent, Qt::ToolTip | Qt::FramelessWindowHint | Qt::BypassGraphicsProxyWidget)
{
setText(text);
setAttribute(Qt::WA_TranslucentBackground, true);
setAttribute(Qt::WA_TransparentForMouseEvents, true);
qApp->installEventFilter(this);
}
bool TipLabel::eventFilter(QObject *o, QEvent *e)
{
if(o == parent()){
switch(e->type()){
case QEvent::WindowDeactivate:
hide();
default:
break;
}
}
if(top_widget && this->updatePosCallBack && o == top_widget){
if(e->type() == QEvent::Move) {
updatePos(updatePosCallBack());
}
}
return false;
}
QSize TipLabel::sizeHint() const
{
return QSize(120, 34);
}
void TipLabel::updatePos(const QPoint &pos)
{
move(pos- QPoint(kTriangleLeftMargin + kTriangleWidth/2, 0));
}
void TipLabel::setCallBack(CallBackType updatePosCallBack)
{
this->updatePosCallBack = updatePosCallBack;
}
void TipLabel::setTopWindow(QWidget *w)
{
top_widget = w;
}
void TipLabel::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPolygon polygon_triangle, polygon;
polygon_triangle << QPoint(kTriangleLeftMargin, kTriangleHeight)
<< QPoint(kTriangleLeftMargin + kTriangleWidth/2, 0)
<< QPoint(kTriangleWidth + kTriangleLeftMargin, kTriangleHeight)<<
QPoint(width() - 1, kTriangleHeight)
<< QPoint(width() -1, height() -1)
<< QPoint(1, height() -1)
<< QPoint(1, kTriangleHeight) <<QPoint(kTriangleLeftMargin, kTriangleHeight);
QRectF text_rect = rect().adjusted(0, kTriangleHeight, -1, -1);
painter.fillRect(rect(), Qt::transparent);
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::white);
painter.drawPolygon(polygon_triangle);
painter.drawRoundedRect(text_rect, 6.0, 5.0);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(Qt::gray);
painter.setBrush(Qt::NoBrush);
painter.drawPolyline(polygon_triangle);
painter.restore();
QTextOption opt;
opt.setAlignment(Qt::AlignCenter);
painter.drawText(text_rect, text(), opt);
}
使用上面小窗口在Lineedit获得焦点时显示大写锁定已打开
#ifndef TIPLABELLINEEDIT_H
#define TIPLABELLINEEDIT_H
#include <QLineEdit>
class TipLabel;
class TipLabelLineedit : public QLineEdit
{
Q_OBJECT
public:
explicit TipLabelLineedit(QWidget *parent = nullptr);
void setTopWindow(QWidget* w);
void setTipVisible(bool v);
virtual QPoint tipPos();
protected:
void resizeEvent(QResizeEvent *event) override;
void focusInEvent(QFocusEvent* event) override;
void focusOutEvent(QFocusEvent* event) override;
void keyEvent(QKeyEvent* event) override;
private:
TipLabel* label;
bool tip_visible{false};
};
#endif
#include "tiplabel-lineedit.h"
#include "../IMLabel/tiplabel.h"
#include <QResizeEvent>
#include "gui-util.h"
using namespace IMUtils;
TipLabelLineedit::TipLabelLineedit(QWidget *parent)
: QLineEdit{parent}, label(new TipLabel("大写锁定已打开", this))
{
auto calback = [this]()->QPoint{
return tipPos();
};
label->setCallBack(calback);
}
void TipLabelLineedit::setTopWindow(QWidget *w)
{
label->setTopWindow(w);
}
void TipLabelLineedit::setTipVisible(bool v)
{
tip_visible = v;
}
QPoint TipLabelLineedit::tipPos()
{
auto pos = mapToGlobal(QPoint(10, size().height()/2));
return pos;
}
void TipLabelLineedit::resizeEvent(QResizeEvent *event)
{
auto pos = mapToGlobal(QPoint(6, event->size().height()/2));
label->updatePos(pos);
QLineEdit::resizeEvent(event);
}
void TipLabelLineedit::focusInEvent(QFocusEvent *event)
{
if(tip_visible && getCapsLockToggled()){
label->showNormal();
}
QLineEdit::focusInEvent(event);
}
void TipLabelLineedit::focusOutEvent(QFocusEvent *event)
{
label->hide();
QLineEdit::focusOutEvent(event);
}
void TipLabelLineedit::keyPressEvent(QKeyEvent *event)
{
if(tip_visible && getCapsLockToggled()){
label->showNormal();
}else {
label->hide();
}
QLineEdit::keyPressEvent(event);
}
参考链接