说明
QT自带的tooltip显示效果不好看,不能显示类型气泡或者其他不规则形状的边框,在网上也没有找到自己想要的效果的代码,只能自己自定义了一个tooltip的显示效果(见实现效果里的GIF)。
文中有描述的不对的地方,敬请指正!!
工程文件源码地址
待上传
实现效果
实现思路
- 新建一个
myWidget
类并继承widget
,在myWidget
里添加两个label
控件,其中一个用于显示图片,一个显示需要提示的文字内容; - 使用
myWidget
的paintEvent
函数,在里面绘制自己想要的外框形状,我这里绘制的气泡形状; - QT中的控件添加自定义
tooltip
都是基于上面构造的myWidget
类进行实现,以label
控件为例,需要新建一个myLable
类并继承QLabel
,在构造函数中new
一个myWidget
成员m_widget
,并安装一个事件过滤器this->installEventFilter(this);
- 在
myLable
的事件过滤器中获取QEvent::ToolTip
事件,同时获取鼠标位置,并在该位置将m_widget
进行显示; - 在
myLable
的事件过滤器中获取QEvent::Leave
事件,此时将m_widget
给隐藏掉; - 最后,若某一个
Label
控件在需要使用自定义ToolTip
的时候,只需要将该控件提升为myLable
即可。
存在的问题
若需要显示的
tooltip
超出了widget
的父窗口则会造成工具提示显示不全。
暂时解决方案
- 在
myLable
中新建一个QDialog
对话框m_dialog
,指定m_widget
的父对象为m_dialog
;- 修改
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);
}