Qt之QGraphicsEffect的简单使用(含源码+注释)

news2024/12/24 8:11:44

文章目录

  • 一、效果示例图
    • 1.效果演示图片
    • 3.弹窗演示图片
  • 二.问题描述
  • 三、源码
    • CFrame.h
    • CFrame.cpp
    • CMainWindow.h
    • CMainWindow.cpp
  • 总结

一、效果示例图

1.效果演示图片

在这里插入图片描述
在这里插入图片描述

3.弹窗演示图片

在这里插入图片描述

二.问题描述

(因为全是简单使用,毫无技巧,直接描述问题)

  1. 模糊效果:QGraphicsBlurEffect包含setBlurHints函数,其作用为设置模糊质量,但是更新它时我这边肉眼上是没有看出特别明显的效果,需考虑不同情况的状态。
  2. 阴影效果:使用QGraphicsDropShadowEffect时,当我作用到弹窗上,它不是作用在弹窗边缘之外,而是作用在弹窗边缘之内,所以需要为其预留部分空间显示阴影。
  3. 透明效果:文中是使用QLinearGradient设置其不透明蒙版,使用中我试图使用三种不同颜色操作蒙版但是失败;其次是我首次将其作用到弹窗中是有效的,但是二次过后就无效,这个我暂时没找到原因。

三、源码

CFrame.h

#ifndef CFRAME_H
#define CFRAME_H

#include <QObject>
#include <QFrame>
#include <QLabel>
#include <QHBoxLayout>

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

    /**
     * @brief setStyleSheet 重写样式设置
     * @param style 样式文本
     */
    void setStyleSheet(const QString &style);

    // QWidget interface
protected:
    /**
     * @brief keyReleaseEvent 键盘释放事件
     * @param event 事件对象
     */
    void keyReleaseEvent(QKeyEvent *event);

    /**
     * @brief mousePressEvent 鼠标按下事件
     * @param event 事件对象
     */
    void mousePressEvent(QMouseEvent *event);

    /**
     * @brief mouseMoveEvent 鼠标移动事件
     * @param event 事件对象
     */
    void mouseMoveEvent(QMouseEvent *event);

private:
    QPoint  m_globalMousePos; // 全局鼠标位置

    QPoint  m_globalWindowPos;  // 全局窗口位置

    QHBoxLayout  *m_layout; // 水平布局器对象

    QLabel  *m_label;       // 图片样式label

};

#endif // CFRAME_H

CFrame.cpp

#include "CFrame.h"

#include <QKeyEvent>

CFrame::CFrame(QWidget *parent) : QFrame(parent)
{
    this->setToolTip(u8"按任意键关闭窗口");
    this->setWindowFlag(Qt::FramelessWindowHint, true);

    // 创建水平布局器对象
    m_layout = new QHBoxLayout;
    m_layout->setMargin(10);
    // 创建图片显示label
    m_label = new QLabel;
    m_layout->addWidget(m_label);
    // 将布局器设置到当前类中
    this->setLayout(m_layout);
}

CFrame::~CFrame()
{
    delete m_layout;
    delete m_label;
}

void CFrame::setStyleSheet(const QString &style)
{
    // 样式设置到label上
    m_label->setStyleSheet(style);
}

void CFrame::keyReleaseEvent(QKeyEvent *event)
{
    // 任意键释放都关闭窗口
    this->close();
}

void CFrame::mousePressEvent(QMouseEvent *event)
{
    // 获取鼠标全局位置
    m_globalMousePos = event->globalPos();
    // 获取窗口左上角位置
    m_globalWindowPos = this->frameGeometry().topLeft();
}

void CFrame::mouseMoveEvent(QMouseEvent *event)
{
    //获得鼠标移动的距离
    QPoint distance = event->globalPos() - m_globalMousePos;
    //改变窗口的位置
    this->move(m_globalWindowPos + distance);
}

CMainWindow.h

#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H

#include "CFrame.h"

#include <QGraphicsBlurEffect>
#include <QGraphicsColorizeEffect>
#include <QGraphicsDropShadowEffect>
#include <QGraphicsOpacityEffect>
#include <QMainWindow>
#include <QLinearGradient>

QT_BEGIN_NAMESPACE
namespace Ui { class CMainWindow; }
QT_END_NAMESPACE

class CMainWindow : public QMainWindow
{
    Q_OBJECT

public:
    CMainWindow(QWidget *parent = nullptr);
    ~CMainWindow();

private:
    void connectSigSlot();

    /**
     * @brief getCurTypeEffect 获取效果对象
     * @param id 效果id
     * @return 效果对象指针
     */
    QGraphicsEffect *getCurTypeEffect(int id);

private slots:
    /**
     * @brief on_buttonGroup_buttonClicked 单选按钮组点击槽函数
     * @param id 点击按钮id
     */
    void on_buttonGroup_buttonClicked(int id);

    /**
     * @brief on_doubleSpinValueChanged 浮点微调框槽函数
     * @param arg1 调整值
     */
    void on_doubleSpinValueChanged(double arg1);

    /**
     * @brief on_spinValueChanged 整型微调框槽函数
     * @param arg1 调整值
     */
    void on_spinValueChanged(int arg1);

    /**
     * @brief on_btnClicked 按钮点击槽函数
     */
    void on_btnClicked();

    /**
     * @brief on_btnSelImg_clicked 图片选择槽函数
     */
    void on_btnSelImg_clicked();

    /**
     * @brief on_btnBecomeDlg_clicked 弹窗按钮槽函数
     */
    void on_btnBecomeDlg_clicked();

    // QWidget interface
protected:
    /**
     * @brief closeEvent 关闭事件
     * @param event 时间对象
     */
    void closeEvent(QCloseEvent *event);

private:
    Ui::CMainWindow             *ui;

    QLinearGradient             m_linearGradient;   // 透明效果的颜色梯度

    CFrame                      *m_dlgFrame;        // 弹窗对象
};
#endif // CMAINWINDOW_H

CMainWindow.cpp

#include "CMainWindow.h"
#include "ui_CMainWindow.h"

#include <QDebug>
#include <QKeyEvent>
#include <QFileDialog>
#include <QColorDialog>

CMainWindow::CMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::CMainWindow)
{
    ui->setupUi(this);

    // 创建弹窗对象
    m_dlgFrame = new CFrame;

    // 设置单选按钮id值
    ui->buttonGroup->setId(ui->checkBoxNoEffect, 0);
    ui->buttonGroup->setId(ui->checkBoxBlurEffect, 1);
    ui->buttonGroup->setId(ui->checkBoxColorEffect, 2);
    ui->buttonGroup->setId(ui->checkBoxShadowEffect, 3);
    ui->buttonGroup->setId(ui->checkBoxOpacityEffect, 4);

    // 线性渐变对象颜色位置赋值
    m_linearGradient.setColorAt(0, Qt::transparent);
    m_linearGradient.setColorAt(0.5, Qt::black);
    m_linearGradient.setColorAt(1, Qt::transparent);
    connectSigSlot();
}

CMainWindow::~CMainWindow()
{
    delete m_dlgFrame;
    delete ui;
}

void CMainWindow::connectSigSlot()
{
    // 链接浮点型数值框信号槽
    connect(ui->doubleSpinColorStrength, SIGNAL(valueChanged(double)), this, SLOT(on_doubleSpinValueChanged(double)));
    connect(ui->doubleSpinBoxOpacity, SIGNAL(valueChanged(double)), this, SLOT(on_doubleSpinValueChanged(double)));

    // 链接整型数值框信号槽
    connect(ui->spinBoxBulrRadius, SIGNAL(valueChanged(int)), this, SLOT(on_spinValueChanged(int)));
    connect(ui->spinBoxHorOffset, SIGNAL(valueChanged(int)), this, SLOT(on_spinValueChanged(int)));
    connect(ui->spinBoxVerOffset, SIGNAL(valueChanged(int)), this, SLOT(on_spinValueChanged(int)));
    connect(ui->spinBoxShadowBlurRadius, SIGNAL(valueChanged(int)), this, SLOT(on_spinValueChanged(int)));

    // 链接按钮信号槽
    connect(ui->btnColorSel, &QPushButton::clicked, this, &CMainWindow::on_btnClicked);
    connect(ui->btnShadowColorSel, &QPushButton::clicked, this, &CMainWindow::on_btnClicked);
}

QGraphicsEffect *CMainWindow::getCurTypeEffect(int id)
{
    QGraphicsEffect *effectTmp = Q_NULLPTR;
    //! 根据ID创建效果对象,并将对应的效果之更新到对象中
    switch (id) {
    case 1:
    {
        QGraphicsBlurEffect *blurEffect = new QGraphicsBlurEffect; // 模糊效果
        // 设置颜模糊半径
        blurEffect->setBlurRadius(ui->spinBoxBulrRadius->value());
        effectTmp = blurEffect;
        break;
    }
    case 2:
    {
        QGraphicsColorizeEffect *colorEffect = new QGraphicsColorizeEffect; // 颜色效果
        // 设置颜色强度
        colorEffect->setStrength(ui->doubleSpinColorStrength->value());
        // 设置颜色
        colorEffect->setColor(ui->btnColorSel->palette().color(QPalette::Button));

        effectTmp = colorEffect;
        break;
    }
    case 3:
    {
        QGraphicsDropShadowEffect *shadowEffect = new QGraphicsDropShadowEffect; // 阴影效果
        shadowEffect->setColor(ui->btnShadowColorSel->palette().color(QPalette::Button)); // 阴影颜色
        shadowEffect->setOffset(ui->spinBoxHorOffset->value(), ui->spinBoxVerOffset->value()); // 阴影偏移度
        shadowEffect->setBlurRadius(ui->spinBoxBulrRadius->value()); // 模糊半径
        effectTmp = shadowEffect;
        break;
    }
    case 4:
    {
        QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
        opacityEffect->setOpacity(ui->doubleSpinBoxOpacity->value()); // 透明度

        m_linearGradient.setStart(ui->label->geometry().topLeft()); //起始位置
        m_linearGradient.setFinalStop(ui->label->geometry().bottomLeft()); // 结束位置

        opacityEffect->setOpacityMask(m_linearGradient);
        effectTmp = opacityEffect;
        break;
    }
    default:
    {
        break;
    }
    }
    return effectTmp;
}

void CMainWindow::on_buttonGroup_buttonClicked(int id)
{
    // 更新栈窗口
    ui->stackedWidget->setCurrentIndex(id);

    // 更新控件效果
    ui->label->setGraphicsEffect(getCurTypeEffect(id));
}

void CMainWindow::on_doubleSpinValueChanged(double arg)
{
    //! 获取发送者类型属性值
    //! 不同值做不同操作
    switch (sender()->property("Type").toInt())
    {
    case 2:
    {
        // 设置颜色强度
        dynamic_cast<QGraphicsColorizeEffect*>(ui->label->graphicsEffect())->setStrength(arg);
        break;
    }
    case 4:
    {
        // 设置透明度
        dynamic_cast<QGraphicsOpacityEffect*>(ui->label->graphicsEffect())->setOpacity(arg);
        break;
    }
    default:
        break;
    }
}

void CMainWindow::on_spinValueChanged(int arg)
{
    //! 获取发送者类型属性值
    //! 不同值做不同操作
    switch (sender()->property("Type").toInt())
    {
    case 1:
    {
        // 设置颜模糊半径
        dynamic_cast<QGraphicsBlurEffect*>(ui->label->graphicsEffect())->setBlurRadius(arg);
        break;
    }
    case 3:
    {
        int flag = sender()->property("WhatThis").toInt();
        if(0 == flag)
        {
            // 设置颜模糊半径
            dynamic_cast<QGraphicsDropShadowEffect*>(ui->label->graphicsEffect())->setBlurRadius(arg);
        }
        else if(1 == flag)
        {
            // 设置垂直偏移
            dynamic_cast<QGraphicsDropShadowEffect*>(ui->label->graphicsEffect())->setYOffset(arg);
        }
        else
        {
            // 设置水平偏移
            dynamic_cast<QGraphicsDropShadowEffect*>(ui->label->graphicsEffect())->setXOffset(arg);
        }
        break;
    }
    default:
        break;
    }
}

void CMainWindow::on_btnClicked()
{
    QPushButton *btn = dynamic_cast<QPushButton *>(sender());
    // 获取按钮进入的palette对象
    QPalette palette(btn->palette());

    // 颜色对象先赋值为当前按钮颜色(防止重新获取颜色时拿到失效颜色)
    QColor color =  palette.color(QPalette::Button);
    // 然后重新获取颜色
    color =  QColorDialog::getColor();
    if(!color.isValid())
    {
        return;
    }

    //! 获取发送者类型属性值
    //! 不同值做不同操作
    switch (btn->property("Type").toInt())
    {
    case 2:
    {
        // 设置颜色
        dynamic_cast<QGraphicsColorizeEffect*>(ui->label->graphicsEffect())->setColor(color);
        break;
    }
    case 3:
    {
        // 设置阴影颜色
        dynamic_cast<QGraphicsDropShadowEffect*>(ui->label->graphicsEffect())->setColor(color);
        break;
    }
    default:
        break;
    }

    // 更新调色板对象按钮颜色
    palette.setColor(QPalette::Button, color);
    btn->setPalette(palette);
    btn->setFlat(true); // 设置按钮扁平化
    btn->setAutoFillBackground(true); // 设置自动填充背景
}

void CMainWindow::on_btnSelImg_clicked()
{
    // 获取图片
    QString fileName = QFileDialog::getOpenFileName(this, u8"选择图片", "./", "*.png *.jpg *.svg");
    // 为空返回
    if(fileName.isEmpty())
    {
        return;
    }
    // 通过样式设置图片
    ui->label->setStyleSheet(QString("border-image:url(%1)").arg(fileName));
}

void CMainWindow::on_btnBecomeDlg_clicked()
{
    // 设置大小为本类的label(图片显示控件)大小
    m_dlgFrame->setFixedSize(ui->label->size());
    // 当前样式图片更新到弹窗label中
    m_dlgFrame->setStyleSheet(ui->label->styleSheet());
    // 获取当前属性效果并设置
    m_dlgFrame->setGraphicsEffect(getCurTypeEffect(ui->buttonGroup->checkedId()));
    // 显示弹窗
    m_dlgFrame->show();
}

void CMainWindow::closeEvent(QCloseEvent *event)
{
    // 当弹窗未关闭时进入关闭
    if(m_dlgFrame->isVisible())
    {
        m_dlgFrame->close();
    }
}

总结

效果使用较为简单,因此暂无强调;文中存在一些问题,后期有解决会更新(要是有大佬指点更好啦)。

友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 o/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

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

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

相关文章

计算机视觉的深度学习 Lecture3:Linear Classifiers 笔记 EECS 498.008

注意到每一行完成一类的分类 事先思考一下loss的可能值有助于debug。如果W随机为高斯分布&#xff0c;μ为0.001&#xff0c;那么下面sj-syi就会很小&#xff0c;Li的值接近C-1&#xff0c;C为分类数 正则化表达式&#xff1a; 如果score都是随机很小的数&#xff0c;近似意…

博客管理系统--博客详情页、登录页

登录页实现强制登录 URL解决后&#xff1b;现在到查看全文按钮。我们点击这个查看全文我们就跳转到博客详情页。 我们希望就是在这个页面&#xff1b;把这些写死的数据换成从后端获取的。 1&#xff1a;约定前后端交互接口 请求&#xff1a;GET /blog?blogId1 (这样子写和博…

总结848

学习目标&#xff1a; 月目标&#xff1a;5月&#xff08;张宇强化前10讲&#xff0c;背诵15篇短文&#xff0c;熟词僻义300词基础词&#xff09; 周目标&#xff1a;张宇强化前3讲并完成相应的习题并记录&#xff0c;英语背3篇文章并回诵 每日必复习&#xff08;5分钟&#…

【连续介质力学】向量

向量的代数操作 加法 a ⃗ \vec a a , b ⃗ \vec b b 为任意向量 c ⃗ a ⃗ b ⃗ b ⃗ a ⃗ \vec c \vec a \vec b \vec b \vec a c a b b a 减法 d ⃗ a ⃗ − b ⃗ \vec d \vec a- \vec b d a −b 标量乘法 λ a ⃗ \lambda \vec a λa , 与 a ⃗ \vec a a 相同…

ubuntu18 使用matplotlib画图

一、安装virtualenvwrapper 1.确认virtualenvwrapper是否已安装&#xff1a; 打开Termianl终端&#xff0c;执行指令&#xff1a;which virtualenvwrapper.sh查询virtualenvwrapper.sh的路径&#xff0c;如果没有提示&#xff0c;则表明virtualenvwrapper.sh没有安装。 2.安…

Codeforces Round 871 (Div. 4) G 记忆化搜索+二分 你没见过的解法!

G. Hits Different 记dp数组为答案数组 首先 dp[2] 2 2 2^2 22 1 2 1^2 12 dp[3] 3 2 3^2 32 1 2 1^2 12 dp[5] 2 2 2^2 22 3 2 3^2 32 1 2 1^2 12 不难发现dp[5]dp[2]dp[3]-dp[1] 同理dp[25]dp[18]dp[19]-dp[13] 接下来就是愉快的找公式时间 观察到题目中给的每一层塔的级数 (…

Notion AI 进阶【help me write】

对于Notion Ai来说,尽管一直在不断发展&#xff0c;但似乎人们还沉浸在Chat Gpt带来的狂欢&#xff0c;但如果你是国内用户&#xff0c;Notion AI所能提供的是远远大于限制过多的GPT&#xff0c;本篇讲一讲在Notion AI中help me write的使用 在这周我把Notion ai接入到Discord…

PostgresML - PostgreSQL的生成式AI扩展

PostgresML 是 PostgreSQL 的机器学习扩展&#xff0c;支持生成式AI&#xff0c;使你能够使用 SQL 查询对文本和表格数据执行训练和推理。 借助 PostgresML&#xff0c;你可以将机器学习模型无缝集成到你的 PostgreSQL 数据库中&#xff0c;并利用尖端算法的强大功能来高效地处…

【Python数据类型-集合】------- PYTHON基础14

内容目录 一、 集合1. 集合创建1.1. 创建集合1.2. 创建空集合 2. 集合基本操作2.1. add()添加新的元素 set1.add(element)2.2.remove()删除元素 set1.remove(element)2.3.discard()删除元素 set1.discard(element)2.4.clear()清空集合里的所有元素 set1.clear() 3. 集合与列表、…

介绍10款ChatGPT替代产品

ChatGPT 引领着聊天 AI 的世界&#xff0c;许多人已经开始在日常生活中使用它。OpenAI 的 GPT-3 语言模型是聊天机器人的基础&#xff0c;它使得用户能够通过回答问题与 AI 进行交互。 GPT-4 的引入为机器人提供了更强大的功能。然而&#xff0c;它也有一个明显的缺点&#xff…

09-HTML-表格标签(合并单元格)

标签描述<table>定义表格<caption>定义表格标题。<th>定义表格中的表头单元格。<tr>定义表格中的行。<td>定义表格中的单元。<thead>定义表格中的表头内容。<tbody>定义表格中的主体内容。<tfoot>定义表格中的表注内容&#x…

API数据接口可以从几个不同的角度来看待;

一.API数据接口可以从几个不同的角度来看待&#xff1a; 1. 技术角度&#xff1a;API数据接口是一种技术实现&#xff0c;通常是以HTTP协议或其他网络协议为基础&#xff0c;并采用特定的数据格式&#xff08;如JSON或XML&#xff09;来传递数据。 2. 业务角度&#xff1a;API数…

Ubuntu22.04安装PyTorch1.12.1 GPU版本

目录 一、电脑相关信息 1. 电脑显卡环境&#xff1a; 二、安装Pytorch1.12.1/cu116&#xff08;GPU版本&#xff09; 1. 准备&#xff1a;新建虚拟环境 2. 方式一&#xff1a;用pip在线安装torch1.12.1cu116、torchvision0.13.1cu116&#xff1a;&#xff08;在pytorch官网…

堆的实现,以及画图和代码分析,建堆,堆排序,时间复杂度的分析

堆的实现 堆的概念及结构堆的实现初始化销毁返回堆顶元素判空有效数据个数 堆的插入&#xff08;向上调整算法&#xff09;删除堆顶元素&#xff0c;仍然保持堆的形态&#xff08;向下调整算法&#xff09;堆的创建向上调整法建堆向下调整建堆两种建堆方法时间复杂度向下调整法…

shell脚本之数值,冒泡排序算法

目录 一、数组 1.定义数组 2. 数组中数据类型 2.1数值类型 2.2字符类型 二、数组的用法 1. 输出数组中的值 2. 统计数组参数个数 ​编辑 3.查看数组下标列表 4.分割字符串 5.替换数组中的字符 6.删除数组 三、数组追加元素 1.方法1示例 2.方法2示例 3.方法3示例 …

Notion Ai中文指令使用技巧

Notion AI 是一种智能技术&#xff0c;可以自动处理大量数据&#xff0c;并从中提取有用的信息。它能够 智能搜索&#xff1a;通过搜索文本和查询结果进行快速访问 自动归档&#xff1a;可以根据关键字和日期自动将内容归档 内容分类&#xff1a;可以根据内容的标签和内容的…

【嵌入式Linux】MBR分区表 和 GPT分区表

文章目录 GUID以及分区表MBR分区方案GPT 分区方案GPT分区表结构 GPT分区表LBALBA0LBA1LBA 2-33python生成GPT分区表gpt分区表实例 gpt分区表查看查看百问网T113-s3固件查看友善之臂nanopi-m1-plus官方固件查看荣品RV1126固件查看f1c200s固件查看V3s的SD启动卡 原文&#xff1a;…

session和Filter

session 介绍 jsp利用servlet提供的HttpSession接口识别一个用户&#xff0c;存储这个用户的所有访问信息。默认情况下&#xff0c;jsp允许会话跟踪&#xff0c;一个新的HttpSession对象将会自动地为新的客户端实例化。禁止会话跟踪需要关掉它&#xff0c;通过将page指令中ses…

多模态:BLIP-2论文讲解

多模态&#xff1a;BLIP-2论文讲解 IntroductionMethod第一阶段第二阶段 实验 Introduction 多模态学习在近两年我们已经见证了他的快速发展&#xff0c;由于它是视觉-语言的交叉领域&#xff0c;我们自然地期待可以借助目前风头正盛的LLM来辅助完成多模态任务。 在这篇论文中…

【SAP Abap】X-DOC:SNRO - ABAP流水号应用

【SAP Abap】X-DOC&#xff1a;SNRO - ABAP流水号应用 1、定义表&#xff08;字段域&#xff09;2、定义流水号3、使用流水号4、测试程序 1、定义表&#xff08;字段域&#xff09; 2、定义流水号 Tcode: SNRO/SNUM&#xff0c; 根据以上创建的字段域 YDSNRO&#xff0c;创建对…