Qt6之带三角形的提示框——仿ToDesk(3)

news2024/11/14 23:08:01

声明:本文仅用于用qt学习todesk界面设计;

如下左图有一排扩展功能的菜单,鼠标滑块会显示带三角形的提示框,本文将用qt实现如右图:

 

 1、布局按钮

直接拖拽出QPushButton,7个,分别设置默认样式和划过样式,如下样式表:

 2、实现带三角形的提示框

显然这种带箭头的提示窗口,不是常规窗口,需要用户自己来绘制三角形,这里以QWidget作为基类实现:

 triangleDialog.h

#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(QEnterEvent *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

triangleDialog.cpp

#include "triangleDialog.h"
#include "triangleDialog.h"
#include <QHBoxLayout>
#include <QPainter>
#include <QGraphicsDropShadowEffect>
#include <QTime>
#include <QTimer>
#include <QPainterPath>
#include <QStylePainter>
#include <QStyleOption>
#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();
    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 *)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);


    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);
}

3、调用带三角的提示框及在提示框内加入widget

mainwindow.h 需要两部分,三角形提示框和重写事件处理部分

 mainwindow.cpp 需要两部分:

一部分处理窗口及样式;

另一部分重写事件处理eventFilter;


ui->pushButton_7->installEventFilter(this);       //安装事件过滤器
    qwidgetOther = new QWidget(this);
    qwidgetOther->setObjectName("qwidgetOther");
    qwidgetOther->setWindowFlags (Qt::FramelessWindowHint| Qt::Popup);
    qwidgetOther->resize(404,531);

    DialogOther=new TriangleDialog(16,16,8,404,531,qwidgetOther,
                                      QRect(ui->pushButton_7->geometry().x()+ui->frame->geometry().x(),ui->pushButton_7->geometry().y()+ui->frame->geometry().y(),ui->pushButton_7->geometry().width(),ui->pushButton_7->geometry().height()),
                                      this);
    DialogOther->setStyleSheet("QWidget#qwidgetOther{background-image:url(:/resource/otherContent.png);border:0;}"\
                                "QWidget{border-radius:5px;}");
    DialogOther->hide();

 4、运行演示

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/907561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始,IntelliJ IDEA快速创建 SpringBoot 项目

准备 Java JDK8 下载 https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 开发工具 IntelliJ IDEA 下载 https://www.jetbrains.com/idea/ 接口调试工具 Postman 下载 https://www.postman.com/downloads/ 创建项目 用IDEA创建SpringBoot项目 打…

OLED透明屏案例:揭示技术创新的无限可能性

OLED透明屏作为一项创新性技术&#xff0c;在各个领域展现出了令人惊叹的应用潜力。 那么&#xff0c;尼伽便通过介绍一些具体的OLED透明屏案例&#xff0c;探索其在智能家居、汽车行业、商业展示、航空航天、教育与培训以及医疗健康等领域的成功应用。 这些案例将展示OLED透明…

JAMstack架构:快速构建安全、高性能的现代应用

随着Web应用的快速发展&#xff0c;开发者们在寻找更加高效、安全和可维护的应用架构。JAMstack架构应运而生&#xff0c;它通过将前端、后端和部署过程分离&#xff0c;提供了一种现代化的方式来构建Web应用。在本文中&#xff0c;我们将深入探讨JAMstack架构的特点、优势以及…

人事变动?前沃尔沃汽车大中华区总裁钦培吉将加盟吉利

根据消息&#xff0c;吉利控股集团高级副总裁杨学良在今天上午通过微博宣布&#xff0c;前沃尔沃汽车大中华区总裁钦培吉将加盟吉利。钦培吉将担任吉利汽车集团销售公司副总经理&#xff0c;并负责集团渠道发展委员会的主任一职&#xff0c;向吉利汽车集团的高级副总裁林杰报告…

什么是链表,前端如何理解链表

一、什么是链表 多个元素存储的列表链表中的元素在内存中不是顺序存储的&#xff0c;而是通过“next”指针联系在一起的。 JS中的原型链 原理就是 链表结构 链表结构 {key: "A",next: {key: "B",next: {key: "C",next: null}} } //原型链 //对…

“智荟·数字未来 2023-得帆数字化高管峰会”成功举办

规模空前&#xff0c;业内最大规模AIGC低代码数字化高管峰会 近日&#xff0c;根据IDC最新数据报告&#xff0c;得帆获得2022年独立低代码厂商市场份额第一&#xff0c;这是客户对得帆最大的认可&#xff0c;也是得帆优秀产品的体现&#xff0c;除了市场份额第一之外&#xff…

React通过docx-preview预览Word文档

前言 在基于React的Web应用中&#xff0c;我们经常遇到需要预览和展示Word文档的需求。而docx-preview是一个优秀的React组件库&#xff0c;可以帮助我们实现在Web页面上预览Word文档的功能。本文将介绍如何使用docx-preview组件来实现Word文档的预览&#xff0c;并提供一个案例…

Project ‘app‘ not found in root project ‘xxx‘

使用rn进行下载依赖时报了这个错误&#xff1a; 在android下的settings.gradle下查看是否有这段话&#xff1a;

CentOS 8.5修改安装包镜像源

1 备份原配置 cd /etc/yum.repos.d mkdir backup mv *.repo backup/2 下载镜像源 2.1 使用wget下载 wget http://mirrors.aliyun.com/repo/Centos-8.repo2.2 使用curl下载 我是安装的最小版本的系统&#xff0c;默认只有curl curl使用方法&#xff1a;https://www.ruanyife…

高效多用的群集-Haproxy搭建Web集群

Haproxy搭建 Web 群集 一、Haproxy前言 HAProxy是一个使用c语言编写的自由及开放源代码软件&#xff0c;其提供高可用性、负载均衡&#xff0c;以及基于TcP和HrrP的应用程序代理。HAProxy特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或七层处理。…

1.82亿南沙区“数字城市”城市运营中心建设项目采购需求

1. 总体技术需求 项目整体框架 遵循“一个中枢、两大中台、基础底座”的总体架构&#xff0c;构建全区城市治理中枢&#xff0c;实现连通上下、衔接左右、分拨处置和协同指挥等作用。 本项目系统的总体架构分为一个中枢、两大中台、基础底座共五部分&#xff0c;在政务云平台…

字符串经典问题

1. 验证回文串 验证回文串 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s&#xff0c;如果它是 回文串 &#xff0c;返回 t…

基于Jenkins构建生产CICD环境(上篇)

目录 环境概述 Jenkins简介 持续集成 持续集成的效益 持续集成的作用 持续集成的特点 持续交付 持续部署 Maven 介绍 安装配置Jenkins Jenkins配置 1、修改jenkins初始密码 2、安装 Jenkins 必要插件 环境概述 随着软件开发需求及复杂度的不断提高&#xff0c;团队…

【vue】更改角色权限后,实现页面不刷新更改其可展示的导航菜单

登入的角色本身属于领导级别&#xff08;集团权限&#xff09;&#xff0c;没有下级的不同权限&#xff1a; 切换不同身份&#xff08;公司&#xff09;&#xff0c;以获得相应部门的不同导航菜单及权限 这里实现&#xff1a;更改角色权限后&#xff0c;实现页面 不刷新 更改…

Bigemap如何添加最新地图?

工具 Bigemap gis office地图软件 BIGEMAP GIS Office-全能版 Bigemap APP_卫星地图APP_高清卫星地图APP 打开软件&#xff0c;要提示需要授权和添加地图&#xff0c;需要授权可以联系客服处理&#xff0c;然后点击选择地图这个按钮&#xff0c;列表中有个添加按钮点进去选择…

这款Linux不收费,却赢得了江湖!

Linux也好&#xff0c;开源也好&#xff0c;近些年犹如翻涌的漩涡&#xff0c;狂热非常&#xff0c;争论不断。从去年高人气开源 npm 包“colors”与“faker”被作者恶意引进错误内容&#xff0c;再到近期的红帽修改公共版的RHEL源代码的发布规则&#xff0c;都在业内引起了不小…

SpringBoot整合Mybatis Plus——条件构造器Wrapper

Mybatis Plus为我们提供了如下的一些条件构造器&#xff0c;我们可以利用它们实现查询条件、删除条件、更新条件的构造。 条件构造器 | MyBatis-Plus (baomidou.com) 一、通过maven坐标引入依赖&#xff08;注意版本&#xff01;&#xff01;&#xff09; <dependency>…

Vulnhub: ICMP: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.208 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.208 80端口的cms为Monitorr 1.7.6m 搜索发现该版本的cms存在远程代码执行 searchsploit monitorr 漏洞利用 nc本地监听&…

GEE-PIE遥感大数据处理与典型案例教程

详情点击链接&#xff1a;GEE-PIE遥感大数据处理与典型案例教程 一&#xff1a;GEE和PIE遥感云平台 1.GEE和PIE平台及典型应用案例 2.JavaScript基础&#xff0c;包括变量&#xff0c;运算符&#xff0c;数组&#xff0c;判断及循环语句等 3.遥感云重要概念与典型数据分析流程…

水电站数字孪生三维可视化展示开发

一、智慧污水处理厂数字孪生系统 智慧污水处理厂结合视频识别、机器人、BIM、互联网、物联网、云计算及大数据等技术&#xff0c;在前期进行精细化设计&#xff0c;实现水质达标&#xff0c;安全生产、高效节能等生产、运营和管理目标&#xff0c;从而达到提升城市生活污水处理…