qt 自定义ToolTip,实现气泡+图片+文字显示效果

说明

QT自带的tooltip显示效果不好看,不能显示类型气泡或者其他不规则形状的边框,在网上也没有找到自己想要的效果的代码,只能自己自定义了一个tooltip的显示效果(见实现效果里的GIF)。

文中有描述的不对的地方,敬请指正!!

工程文件源码地址

待上传

实现效果

在这里插入图片描述

实现思路

  1. 新建一个myWidget类并继承widget,在myWidget里添加两个label控件,其中一个用于显示图片,一个显示需要提示的文字内容;
  2. 使用myWidgetpaintEvent函数,在里面绘制自己想要的外框形状,我这里绘制的气泡形状;
  3. QT中的控件添加自定义tooltip都是基于上面构造的myWidget类进行实现,以label控件为例,需要新建一个myLable类并继承QLabel,在构造函数中new一个myWidget成员m_widget,并安装一个事件过滤器this->installEventFilter(this);
  4. myLable的事件过滤器中获取QEvent::ToolTip事件,同时获取鼠标位置,并在该位置将m_widget进行显示;
  5. myLable的事件过滤器中获取QEvent::Leave事件,此时将m_widget给隐藏掉;
  6. 最后,若某一个Label控件在需要使用自定义ToolTip的时候,只需要将该控件提升myLable即可。

存在的问题

若需要显示的tooltip超出了widget的父窗口则会造成工具提示显示不全。

暂时解决方案

  1. myLable中新建一个QDialog对话框m_dialog,指定m_widget的父对象为m_dialog
  2. 修改myLable的事件过滤器中函数bool myLabel::eventFilter(QObject *obj, QEvent *event),在获取QEvent::ToolTip事件时,在鼠标位置将m_dialog进行显示,在获取QEvent::Leave事件时,此时将m_dialog给关闭掉即可。

其他问题

通过QDialog的方法可以解决之前 ToolTip显示不全的问题,但是当控件较多时,启动应用程序时还会有点小bug(这个需自行感受),而且弹出自定义的 ToolTip后,原窗口会变为非激活态。

暂时还没有找到比较好的方法实现自定义的ToolTip

实现代码

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <QPainter>
#include <QLabel>
#include <QPainterPath>
#include <QFont>

class myWidget : public QWidget
{
    Q_OBJECT
public:
    explicit myWidget(QWidget *parent = nullptr);
    ~myWidget();

    void setLabelText(QString str);
    double getLabelTextLength(void);

private:
    QLabel *m_TextLabel = nullptr;
    QLabel *m_ImgLabel = nullptr;
    
protected:
    void paintEvent(QPaintEvent *);
};

#endif // MYWIDGET_H

mywidget.cpp

#include "mywidget.h"


#define BORDER_RADIUS   15      // 窗口边角的弧度;

#pragma execution_character_set("utf-8")

myWidget::myWidget(QWidget *parent) : QWidget(parent)
{
    setAttribute(Qt::WA_TranslucentBackground);
    m_ImgLabel = new QLabel(this);
    m_TextLabel = new QLabel(this);

    //提示图标
    m_ImgLabel->setGeometry(5,8,32,32);
    QPixmap  *pixmap = new QPixmap("warning_128px.ico");
    pixmap->scaled(m_ImgLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    m_ImgLabel->setScaledContents(true);
    m_ImgLabel->setPixmap(*pixmap);
    m_ImgLabel->setAlignment(Qt::AlignCenter);

    //文本label
    QFont lbl_font;
    lbl_font.setPixelSize(20);      //设置默认字体大小
    m_TextLabel->setFont(lbl_font);
    m_TextLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
    m_TextLabel->setGeometry(40,14,100,20);
    m_TextLabel->setMinimumHeight(20);
}

void myWidget::setLabelText(QString str)
{
    m_TextLabel->setText(str);
    m_TextLabel->adjustSize();
}

double myWidget::getLabelTextLength(void)
{
    return m_TextLabel->width();
}

myWidget::~myWidget()
{
}

void myWidget::paintEvent(QPaintEvent *)
{
    QPainter Painter(this);
    Painter.setRenderHint(QPainter::Antialiasing, true);
    Painter.setPen(Qt::SolidLine); //SolidLine
    Painter.setBrush(QColor(218, 250, 250, 255));
    QPainterPath PainterPath;
    PainterPath.moveTo(10,65);  //起点
    PainterPath.lineTo(25,48);
    PainterPath.lineTo(width()-BORDER_RADIUS,48);
    PainterPath.arcTo(width()-BORDER_RADIUS,48-BORDER_RADIUS,BORDER_RADIUS,BORDER_RADIUS,270,90);
    PainterPath.lineTo(width(),BORDER_RADIUS);
    PainterPath.arcTo(width()-BORDER_RADIUS,0,BORDER_RADIUS,BORDER_RADIUS,0,90);
    PainterPath.lineTo(BORDER_RADIUS,0);
    PainterPath.arcTo(0,0,BORDER_RADIUS,BORDER_RADIUS,90,90);
    PainterPath.lineTo(0,48-BORDER_RADIUS);
    PainterPath.arcTo(0,48-BORDER_RADIUS,BORDER_RADIUS,BORDER_RADIUS,180,90);
    PainterPath.lineTo(10,65);
    Painter.drawPath(PainterPath);
}

mylabel.h

#ifndef MYLABEL_H
#define MYLABEL_H

#include <QObject>
#include <QWidget>
#include <QDialog>
#include <QDebug>
#include <QMouseEvent>
#include <QLabel>
#include <QString>
#include "mywidget.h"
class myLabel  : public QLabel
{
    Q_OBJECT
public:
    myLabel(QWidget *parent=0);
    ~myLabel();

private:
    myWidget *m_widget;
    QDialog *dialog ;
protected:
    bool eventFilter(QObject *obj, QEvent *event);
};

#endif // MYLABEL_H

mylabel.cpp

#include "mylabel.h"

myLabel::myLabel(QWidget *parent):
    QLabel(parent)
{
    dialog = new QDialog();
    dialog->close();
    dialog->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    dialog->setWindowModality(Qt::WindowModal);
    dialog->setGeometry(0,0,200,65);
    dialog->setAttribute(Qt::WA_TranslucentBackground, true);

    m_widget = new myWidget(dialog);
    m_widget->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
    m_widget->setWindowModality(Qt::WindowModal);
    m_widget->setGeometry(0,0,200,65);
    m_widget->setAutoFillBackground(true);
    m_widget->show();
    m_widget->setVisible(true);
    m_widget->setWindowFlags(Qt::WindowStaysOnTopHint);
    m_widget->raise();
    this->installEventFilter(this);
}

myLabel::~myLabel()
{
}

bool myLabel::eventFilter(QObject *obj, QEvent *event)
{
    static uint8_t flag=0;
    if(obj == this)
    {
        if(event->type() == QEvent::ToolTip)
        {
            if(!flag)
            {
                flag = 1;
                if(this->toolTip().isEmpty())
                    m_widget->setLabelText(this->text());
                else
                    m_widget->setLabelText(this->toolTip());
                m_widget->resize(m_widget->getLabelTextLength()+50,m_widget->height());
                dialog->move(QCursor::pos().x()-10,QCursor::pos().y()-65);
                dialog->adjustSize();
                dialog->show();
            }
            return true;
        }
        else if(event->type() == QEvent::Leave)
        {
            if(flag)
            {
                flag = 0;
                dialog->close();
            }
            return true;
        }
    }
    return QWidget::eventFilter(obj,event);
}

  • 10
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MengJunlei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值