[QT]自定义的QtabWidget

news2024/11/18 5:29:15

需求

最近有一个需求就是一个QTabWidget要求有四个tab页在左侧用于显示主页面,在右侧有一个关于按钮,点击后用于弹出窗口显示一些程序相关信息。主要是怎么实现右侧按钮

相关代码

#ifndef MYTABWIDGET_H
#define MYTABWIDGET_H

#include <QWidget>
#include <QTabWidget>
#include <QPaintEvent>
#include <QStyleOptionButton>
#include <QPushButton>
#include <QRect>
#include <QPainter>
#include <QStyle>
#include <QMouseEvent>

class MyTabWidget : public QTabWidget
{
    Q_OBJECT
public:
    explicit MyTabWidget(QWidget *parent = nullptr);
    ~MyTabWidget();
signals:
    void clickHelp();
protected:
    //重绘
    void paintEvent(QPaintEvent *event);
    //hover状态控制
    void mouseMoveEvent(QMouseEvent *event);
    //hover状态控制
    void leaveEvent(QEvent *event);
    //点击状态控制
    void mousePressEvent(QMouseEvent *event);
    //点击状态控制
    void mouseReleaseEvent(QMouseEvent *event);
private:
    QPushButton *m_pushButton = nullptr;//用于辅助绘制按钮将会使用此按钮的样式表
    QStyleOptionButton m_optionButton;//绘制按钮用于控制按钮状态按钮位置等
    bool m_isPressed = false;//按下标志位
    bool m_isReleased = false;//松开标志位
};

#endif // MYTABWIDGET_H

#include "MyTabWidget.h"
#include <QDebug>

MyTabWidget::MyTabWidget(QWidget *parent) : QTabWidget(parent)
{
    setAttribute(Qt::WA_StyledBackground);
    setMouseTracking(true);
    //不要给按钮指定父亲,指定父亲后此按钮会默认显示在父对象上。在析构函数中将它给delete掉,防止内存泄漏
    m_pushButton = new QPushButton;
    m_optionButton.text = QStringLiteral("帮助");
    m_optionButton.state |= QStyle::State_Enabled;
    //使用样式表来控制按钮的外观更加方便
    m_pushButton->setStyleSheet("QPushButton{border:1px solid #adadad;background-color:#e1e1e1} QPushButton:hover{border:1px solid #0078d7;background-color:#e5f1fb}"
                                "QPushButton::pressed{border:1px solid #00559b; background-color:#cde4f7}");
}

MyTabWidget::~MyTabWidget()
{
    delete m_pushButton;
    m_pushButton = nullptr;
}

void MyTabWidget::paintEvent(QPaintEvent *event)
{
    QTabWidget::paintEvent(event);
    QPainter painter(this);
    m_optionButton.rect = QRect(event->rect().topRight().x() - 41, event->rect().topRight().y() + 2, 40, 17);
    //m_pushButton->style()使用按钮的style()接口来绘制是非常重要的
    m_pushButton->style()->drawControl(QStyle::CE_PushButton, &m_optionButton, &painter, m_pushButton);
}

void MyTabWidget::mouseMoveEvent(QMouseEvent *event)
{
    QTabWidget::mouseMoveEvent(event);
    QRect rect = QRect(this->rect().topRight().x() - 41, this->rect().topRight().y() + 2, 40, 17);
    if(rect.contains(event->pos())){
        m_optionButton.state |= QStyle::State_MouseOver;
        this->repaint();
    }else{
        m_optionButton.state &= ~QStyle::State_MouseOver;
        this->repaint();
    }
}

void MyTabWidget::leaveEvent(QEvent *event)
{
    QTabWidget::leaveEvent(event);
    m_optionButton.state &= ~QStyle::State_MouseOver;
    this->repaint();
}

void MyTabWidget::mousePressEvent(QMouseEvent *event)
{
    QTabWidget::mousePressEvent(event);
    QRect rect = QRect(this->rect().topRight().x() - 41, this->rect().topRight().y() + 2, 40, 17);
    if(rect.contains(event->pos())){
        //QStyle::State_Sunken 也就是按钮按下的状态
        m_optionButton.state |= QStyle::State_Sunken;
        this->repaint();
        m_isPressed = true;
    }
}

void MyTabWidget::mouseReleaseEvent(QMouseEvent *event)
{
    QTabWidget::mouseReleaseEvent(event);
    QRect rect = QRect(this->rect().topRight().x() - 41, this->rect().topRight().y() + 2, 40, 17);
    if(rect.contains(event->pos()) && m_isPressed){
        m_isReleased = true;
        emit clickHelp();
        m_isPressed = false;
        m_isReleased = false;
        m_optionButton.state &= ~QStyle::State_Sunken;
        this->repaint();
    }else{
        m_isPressed = false;
        m_optionButton.state &= ~QStyle::State_Sunken;
        this->repaint();
    }
}

效果展示

在这里插入图片描述

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

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

相关文章

UDP通信发送和接收 || UDP实现全双工通信

recvfrom ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); 功能: 从套接字中接收数据 参数: sockfd:套接字文件描述符 buf:存放数据空间首地址 …

康奈尔开源近10万份审稿意见,未来论文发表或将由AI定夺

大语言模型&#xff08;LLMs&#xff09;的进步为自动化论文评审开辟了新途径&#xff0c;这些模型在学术反馈领域展现出巨大潜力。自动化评审的核心优势在于其能够精准指出论文草稿的不足之处&#xff0c;助力作者优化研究。尽管已有丰富的同行评审数据&#xff0c;但现有自动…

利用websocket +定时器简易的实现一个网络聊天室

其实原理非常简单,就是客户端用户通过websoket来连接websocket服务端。然后服务端,收集每个用户发出的消息, 进而将每条用户的消息通过广播的形式推送到每个连接到服务端的客户端。从而实现用户的实时聊天。 // TODO : 我主要是讲一下实现思路。并未完善其功能。 1.后端 依赖 …

云原生(一)、linux快速上手

Linux是一种开源的Unix-like操作系统内核。它是由Linus Torvalds于1991年首次发布&#xff0c;其后经过全球的自由软件社区的持续开发和改进。Linux内核是操作系统的核心部分&#xff0c;但通常与GNU项目合作&#xff0c;以形成完整的操作系统&#xff0c;被称为Linux发行版&am…

每日OJ题_牛客WY28 跳石板(动态规划)

目录 牛客WY28 跳石板 解析代码 牛客WY28 跳石板 跳石板_牛客题霸_牛客网 解析代码 #include <iostream> #include <vector> #include <climits> #include <cmath> using namespace std;void get_div_num(int n, vector<int>& arr) {for…

基于java+springboot+vue实现的农产品智慧物流系统(文末源码+Lw)23-239

课题意义 现如今&#xff0c;信息种类变得越来越多&#xff0c;信息的容量也变得越来越大&#xff0c;这就是信息时代的标志。近些年&#xff0c;计算机科学发展得也越来越快&#xff0c;而且软件开发技术也越来越成熟&#xff0c;因此&#xff0c;在生活中的各个领域&#x…

WEBUI中的完美像素模式(Pixel Perfect)到底是什么意思

在webui的controlnet中&#xff0c;有个选项&#xff0c;叫做“完美像素模式”&#xff0c;英文为“pixel perfect mode”&#xff0c;有很多朋友在使用的时候不知道这个神奇的选项是否应该勾选上&#xff0c;所以有时候排查问题的时候&#xff0c;会反复的选择和去掉勾选&…

机器学习的基础学习笔记

黑马的学习视频 大家常说的人工智能、机器学习、深度学习其实是包含关系&#xff0c;深度学习是机器学习的一种特殊方法&#xff0c;而机器学习又是人工智能的一个子领域。 其中机器学习是使计算机系统能够通过学习经验和数据来改进性能。机器学习算法能够从数据中发现模式&am…

Igraph入门指南 5

2、graph_from系列&#xff0c;将其他R数据结构转换成图 2-1 邻接矩阵转图&#xff1a;graph_from_adjacency_matrix 可以接受Matrix包创建的稀疏矩阵作为参数 邻接矩阵中行的顺序被保留&#xff0c;并作为图中顶点的顺序。 本函数几个重要的参数&#xff1a; weighted&am…

美团 Java 开发笔试热经

Voiceover&#xff1a; 见者有缘&#xff0c;缘来好运。欢迎大家来到我的博客【CS_GUIDER】&#xff1a;&#xff08;建议收藏至浏览器书签&#xff09; https://wlei224.gitee.io &#xff08;建议访问这个&#xff0c;速度极快&#xff09; https://wl2o2o.github.io &#x…

Kafka 面试题及答案整理,最新面试题

Kafka中的Producer API是如何工作的&#xff1f; Kafka中的Producer API允许应用程序发布一流的数据到一个或多个Kafka主题。它的工作原理包括&#xff1a; 1、创建Producer实例&#xff1a; 通过配置Producer的各种属性&#xff08;如服务器地址、序列化方式等&#xff09;来…

数据结构/C++:AVL树

数据结构/C&#xff1a;AVL树 概念实现插入左单旋右单旋左右双旋右左双旋 总代码展示 概念 AVL树是一种自平衡二叉搜索树&#xff08;BST&#xff09;&#xff0c;被命名为Adelson-Velskii和Landis树&#xff0c;以它们的发明者们的名字命名。AVL树通过在插入和删除操作后进行…

嘉立创画PCB板子入门喔

PCB层叠结构 单层板&#xff0c;双层板&#xff08;就是在单层板的基础上过孔到背面&#xff09;&#xff0c;四层板&#xff0c;六层板&#xff08;四层&#xff0c;六层就是在双层板子基础上通过通孔&#xff0c;盲孔&#xff0c;埋空完成&#xff09;一般以偶数去打板。 为什…

2024年掌握人工智能的顶级课程

[AI 课程推荐] 谷歌、微软、哈佛大学, DeepLearning.AI都发布了免费的人工智能和ChatGPT的课程。 以下是 2024 年掌握人工智能的顶级课程: GOOGLE - 生成式人工智能学习路径微软- 为每个人提供生成式人工智能微软 - 人工智能初学者入门哈佛 - CS50 的 Python 人工智能简介Deep…

MATLAB报错:尝试将 SCRIPT imread 作为函数执行

报错&#xff1a; 在执行matlab脚本的时候出现报错。 >> imread 尝试将 SCRIPT imread 作为函数执行: S:\temp_file\matlab\DigitalImageProcessing\imread.m出错 imread (line 2) I imread(S:\temp_file\matlab\DigitalImageProcessing\blueman.png);分析以及解决方…

Java并发编程总结(一)

一、进程与线程 1、进程与线程 1.1、进程 程序一般认为是静态存储的&#xff0c;而进程则是活动的&#xff0c;真正执行的、动态加载到内存的&#xff0c;被CPU执行的。 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加…

解决 JavaScript heap out of memory 报错

前台运行项目时候提示内存溢出 解决 先执行&#xff1a; export NODE_OPTIONS"--max-old-space-size4096" 再运行&#xff1b; nom run serve

算法---双指针练习-4(盛水最多的容器)

题目 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;盛水最多的容器 2. 讲解算法原理 算法的主要思路是使用双指针的方法&#xff0c;通过不断调整指针的位置来计算面积&#xff0c;并更新最大面积。具体步骤如下&#xff1a; 初始化左指针x为数组…

Chrome浏览器好用的几个扩展程序

Chrome好用的扩展程序 背景目的介绍JsonHandle例子未完待续。。。。。。 背景 偶然在往上看到Chrome有很多好用的扩展程序&#xff0c;比较好用&#xff0c;因此记录下比较实用的扩展程序。 目的 记录Chrome浏览器好用的插件。 介绍 JsonHandle下载以及无法扩展插件的解决…

C#实现线性查找算法

C#实现线性查找算法 以下是使用 C# 实现线性查找算法的示例代码&#xff1a; using System;class Program {static int LinearSearch(int[] array, int target){for (int i 0; i < array.Length; i){if (array[i] target){return i; // 如果找到目标&#xff0c;返回其索…