Qt 带三角的提示框

1.鼠标放在控件或者提示框本身,提示框都显示

2.鼠标离开,延时500ms消失

3.鼠标移动到另一控件上,显示另一个带三角提示框,上一个提示框立即消失

4.扣掉三角两边的区域,鼠标移入提示框不显示

5.中间可以插入widget(qwidget包含qlabel,qframe等)

#ifndef TRIANGLEDIALOG_H
#define TRIANGLEDIALOG_H
#include<QEvent>
#include <QWidget>
#include <QHBoxLayout>
#include <QVector2D>
#include <QMouseEvent>
class TriangleDialog : public QWidget
{
    Q_OBJECT

public:
    //小三角显示的起始位置,三角左点距离左边长,三角宽高,矩形宽高,内嵌,响应控件rect,parent
    TriangleDialog(int startXtoleft,int Triawidth, int Triaheight,int Rectwidth, int Rectheight,QWidget* widget,QRect ,QWidget *parent = nullptr);
    ~TriangleDialog();

    // 设置小三角起始位置;
    void setStartXtoleft(int startXtoleft);

    // 设置小三角宽和高;
    void setTriangleInfo(int width, int height);
    void setRectInfo(int width, int height);

    // 设置中间区域widget;
    void setCenterWidget(QWidget* widget);
    void calculateGeometry(QRect parentRect);

protected:
    void paintEvent(QPaintEvent *);
//    void enterEvent(QEvent *even);
    void leaveEvent(QEvent *even);
    void mouseMoveEvent(QMouseEvent *event);
    bool pointInTriangle(QVector2D A, QVector2D B, QVector2D C, QVector2D P);
    bool pointInRect(QRect parent_Rect, QVector2D P);
signals:
    void signal_TriangleDlgshow(int );
private slots:
    void Hide();
    void onHide();
    void onHide(int);
    void Show();

private:
    // 小三角起始位置;
    int m_startX;
    int m_startY;

    int m_startXtoleft;

    // 小三角的宽度;
    int m_triangleWidth;
    int m_triangleHeight;

    int m_RectWidth;
    int m_RectHeight;

    QRect m_parentRect;
    QRect m_rect;
    QWidget *m_widget;
    QHBoxLayout* hMainLayout;

    QTimer *time;
    int waitTime;
    int margin_left;
    int margin_top;
    int margin_right;
    int margin_bottom;
};
#endif // WIDGET_H
#include "triangleDialog.h"
#include <QHBoxLayout>
#include <QPainter>
#include <QGraphicsDropShadowEffect>
#include <QTime>
#include <QTimer>
#define SHADOW_WIDTH 8                 // 窗口阴影宽度;
#define BORDER_RADIUS 2                 // 窗口边角的弧度;

//三角左点距离左边长,三角宽高,矩形宽高,内嵌,响应控件rect,parent
TriangleDialog::TriangleDialog(int startXtoleft,int Triawidth, int Triaheight,int Rectwidth, int Rectheight,QWidget* widget,QRect parentRect,QWidget *parent): QWidget(parent)
{
    setWindowFlags(Qt::Widget | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowStaysOnTopHint);
    setAttribute(Qt::WA_TranslucentBackground,true);
    waitTime=500;
    hMainLayout = new QHBoxLayout(this);

    margin_left=(Rectwidth-widget->geometry().width())/2;
    margin_top=(Rectheight-widget->geometry().height())/2+Triaheight-SHADOW_WIDTH/2;
    margin_right=Rectwidth-widget->geometry().width()-margin_left;
    margin_bottom=Rectheight-widget->geometry().height()-margin_top;
    hMainLayout->setContentsMargins(margin_left, margin_top,margin_right, margin_bottom);
    hMainLayout->setAlignment(this,Qt::AlignCenter);
    // 设置阴影边框;
    auto shadowEffect = new QGraphicsDropShadowEffect(this);
    shadowEffect->setOffset(0, 0);
    shadowEffect->setColor(Qt::gray);
    shadowEffect->setBlurRadius(SHADOW_WIDTH);
    this->setGraphicsEffect(shadowEffect);
    m_startX=startXtoleft+Triawidth/2;
    m_startY=0;
    setStartXtoleft(startXtoleft);
    setTriangleInfo(Triawidth, Triaheight);
    setRectInfo(Rectwidth, Rectheight);
    calculateGeometry(parentRect);
    m_parentRect=parentRect;
    setCenterWidget(widget);
    m_widget=widget;

        time= new QTimer();
        connect(time, SIGNAL(timeout()), this, SLOT(Hide()));
        setMouseTracking(true);
//        time->start(1000);
}

TriangleDialog::~TriangleDialog()
{

}

// 小三角相对左边位置
void TriangleDialog::setStartXtoleft(int startXtoleft)
{
    m_startXtoleft = startXtoleft;
}
// 设置小三角宽高
void TriangleDialog::setTriangleInfo(int width, int height)
{
    m_triangleWidth = width;
    m_triangleHeight = height;
}

// 设置矩形宽高
void TriangleDialog::setRectInfo(int width, int height)
{
    m_RectWidth = width;
    m_RectHeight = height;
}
//计算整个widget的Geometry
void TriangleDialog::calculateGeometry(QRect parentRect)
{
    int x = parentRect.x()+parentRect.width()/2-m_startXtoleft-m_triangleWidth/2+6;
    int y=parentRect.y()+parentRect.height()+12;
    int width = m_RectWidth;
    int height = m_RectHeight+m_triangleHeight;

    this->move(x,y);
    this->resize(width, height);
}
//加widget
void TriangleDialog::setCenterWidget(QWidget* widget)
{
    hMainLayout->addWidget(widget);
}

bool TriangleDialog::pointInTriangle(QVector2D A, QVector2D B, QVector2D C, QVector2D P)
{
    QVector2D v0 = C - A;
    QVector2D v1 = B - A;
    QVector2D v2 = P - A;

    float dot00 = QVector2D::dotProduct(v0, v0);
    float dot01 = QVector2D::dotProduct(v0, v1);
    float dot02 = QVector2D::dotProduct(v0, v2);
    float dot11 = QVector2D::dotProduct(v1, v1);
    float dot12 = QVector2D::dotProduct(v1, v2);

    float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01);

    float u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
    if (u < 0 || u > 1) // if u out of range, return directly
    {
        return false;
    }

    float v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
    if (v < 0 || v > 1) // if v out of range, return directly
    {
        return false;
    }
    return u + v <= 1;
}

bool TriangleDialog::pointInRect(QRect parent_Rect,  QVector2D P)
{
    if(P.x()>parent_Rect.x()
            &&P.y()>parent_Rect.y()
            &&P.x()<parent_Rect.x()+parent_Rect.width()
            &&P.y()<parent_Rect.y()+parent_Rect.height())
    {
        return true;
    }
    else
    {
        return false;
    }
}

void TriangleDialog::Hide()
{
    hide();
}

void TriangleDialog::onHide()
{
    time->start(waitTime);
}
void TriangleDialog::onHide(int close_time)
{
    time->start(close_time);
}

void TriangleDialog::Show()
{
    time->stop();
    show();
    emit signal_TriangleDlgshow(0);
}

void TriangleDialog::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(255, 255, 255));

    // 小三角区域;
    QPolygon trianglePolygon;
    trianglePolygon << QPoint(m_startX , m_startY );
    trianglePolygon << QPoint(m_startX + m_triangleWidth / 2, m_startY + m_triangleHeight );
    trianglePolygon << QPoint(m_startX - m_triangleWidth / 2, m_startY + m_triangleHeight );

    //矩形
    QPainterPath drawPath;
    drawPath.addRoundedRect(QRect(m_startX - m_startXtoleft-m_triangleWidth / 2, m_startY + m_triangleHeight,\
                                  m_RectWidth, m_RectHeight),\
                            BORDER_RADIUS, BORDER_RADIUS);
    // Rect + Triangle;
    drawPath.addPolygon(trianglePolygon);
    painter.drawPath(drawPath);
}


void TriangleDialog::mouseMoveEvent(QMouseEvent *event)
{
    float P_X = event->x();
    float P_Y = event->y();
    m_rect=QRect(0,m_triangleHeight,m_RectWidth,m_RectHeight);
    if(pointInTriangle(QVector2D(m_startX , m_startY),\
                       QVector2D(m_startX + m_triangleWidth / 2, m_startY + m_triangleHeight),QVector2D(m_startX - m_triangleWidth / 2, m_startY + m_triangleHeight),QVector2D(P_X,P_Y))
            ||pointInRect(m_rect, QVector2D(event->x(),event->y()))  //
            ||m_widget->geometry().contains(QPoint(P_X,P_Y)))
    {
            time->stop();
            this->show();
    }
    else
    {
        time->start(waitTime);
    }
}

//void TriangleDialog::enterEvent(QEvent *even)
//{
//    time->stop();
//    this->show();
//}

void TriangleDialog::leaveEvent(QEvent *even)
{
    time->start(waitTime);
}

 

使用:

Q_SIGNALS:
    void sigSetFileShowtriangleDlg();
    void sigSetFileHidetriangleDlg( );

    void sigQQShowtriangleDlg();
    void sigQQHidetriangleDlg();

private slots:
    bool eventFilter(QObject *obj, QEvent *event);

private:
    Ui::UpLoad *ui;
    TriangleDialog *setfileDialog;
    TriangleDialog *qqDialog;
    QQWidget *qqwidget;
    int waitTime;

    bool mouse_is_press;     //鼠标是否按下
    QPoint  mouse_move_len;  //鼠标移动事件中,移动的距离

    QPoint mouseStartPoint;
    QLabel *setfilelabel;
void UpLoad::InitTitleBar()
{
    ui->setfileButton->installEventFilter(this);       //安装事件过滤器
    ui->qqButton->installEventFilter(this);       //安装事件过滤器

    setfilelabel=new QLabel("111");
    setfilelabel->setWordWrap(true);
    setfilelabel->setObjectName("setfilelabel");
    setfilelabel->setFixedSize(115,44);

    //三角左点距离左边长,三角宽高,矩形宽高,内嵌,响应控件rect,parent
    setfileDialog=new TriangleDialog(16,16,8,147,60,setfilelabel,
                                     QRect(ui->setfileButton->geometry().x(),ui->setfileButton->geometry().y(),ui->setfileButton->geometry().width(),ui->setfileButton->geometry().height()),
                                     this);
    connect(this, SIGNAL(sigSetFileShowtriangleDlg()), setfileDialog, SLOT(Show()));
    connect(this, SIGNAL(sigSetFileHidetriangleDlg()), setfileDialog, SLOT(onHide()));

    setfileDialog->hide();


    qqwidget = new QQWidget();
    qqwidget->setObjectName("QQWidget");
    qqwidget->setStyleSheet("QQWidget#QQWidget{background-color:#FFFFFF;border:1px solid #DADADA;}");
    qqwidget->setWindowFlags (Qt::FramelessWindowHint| Qt::Popup);//

    qqDialog=new TriangleDialog(16,16,8,198,266,qqwidget,
                                QRect(ui->qqButton->geometry().x(),ui->qqButton->geometry().y(),ui->qqButton->geometry().width(),ui->qqButton->geometry().height()),
                                this);
    connect(this, SIGNAL(sigQQShowtriangleDlg()), qqDialog, SLOT(Show()));
    connect(this, SIGNAL(sigQQHidetriangleDlg()), qqDialog, SLOT(onHide()));

    connect(qqDialog, SIGNAL(signal_TriangleDlgshow(int )), setfileDialog, SLOT(onHide(int )));
    connect(setfileDialog, SIGNAL(signal_TriangleDlgshow(int )), qqDialog, SLOT(onHide(int )));
    qqDialog->hide();

}
bool UpLoad::eventFilter(QObject *obj, QEvent *event)
{
    if(obj == ui->setfileButton) {
        if(event->type() == QEvent::Enter) {//QEvent::HoverEnter,QEvent::HoverLeave
            emit sigSetFileShowtriangleDlg();
            return true;
        }
        if(event->type() == QEvent::Leave)
        {
            emit sigSetFileHidetriangleDlg();
            return true;
        }
        return QWidget::eventFilter(obj,event);
    }
    if(obj == ui->qqButton) {
        if(event->type() == QEvent::Enter) {//QEvent::HoverEnter,QEvent::HoverLeave
            emit sigQQShowtriangleDlg();
            return true;
        }
        if(event->type() == QEvent::Leave)
        {
            emit sigQQHidetriangleDlg();
            return true;
        }
        return QWidget::eventFilter(obj,event);
    }
}

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值