0
点赞
收藏
分享

微信扫一扫

自定义QTabWidget实现右侧增加按钮

需求

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

  1. 直接new一个QPushButton,然后以QTabWidget作为父对象,然后将按钮移动到正确位置上。在每次QTabWidget大小发生变化时修改QPushButton的位置即可。
  2. 使用QStyle QStyleOptionButton 直接绘制按钮实现相关功能 考虑到用尽费退选择第二种方法实现

关键代码

CustomTableWidget

#include "CustomTableWidget.h"
#include <QPaintEvent>
#include <QMouseEvent>
#include <QPainter>
#include <QTabBar>
#include <QDebug>
#include <QEvent>

CustomTableWidget::CustomTableWidget(QWidget *parent) : QTabWidget(parent)
{
    setMouseTracking(true);
    m_aboutBtn = new QPushButton;
    m_aboutBtn->setStyleSheet("QPushButton{border: 1px solid red; color: white}"
                              "QPushButton:hover{color: #e9bbc0}");
    m_aboutBtnOption.state |= QStyle::State_Enabled;
    m_aboutBtnOption.text = QStringLiteral("关于");
}

CustomTableWidget::~CustomTableWidget()
{
    delete m_aboutBtn;
    m_aboutBtn = nullptr;
}

void CustomTableWidget::paintEvent(QPaintEvent *event)
{
    QTabWidget::paintEvent(event);
    QPainter painter(this);
    QRect tabWidgetRect = event->rect();
    if(this->tabBar()){
        if(tabWidgetRect == this->tabBar()->rect() || tabWidgetRect == this->tabBar()->tabRect(0) || tabWidgetRect == this->tabBar()->tabRect(1)){
            return;
        }
    }
    m_aboutBtnRect = QRect(tabWidgetRect.topRight().x() - 60, tabWidgetRect.topRight().y(), 60, 37);
    m_aboutBtnOption.rect = m_aboutBtnRect;
    m_aboutBtn->style()->drawControl(QStyle::CE_PushButton, &m_aboutBtnOption, &painter, m_aboutBtn);
}

void CustomTableWidget::mouseMoveEvent(QMouseEvent *event)
{
    QTabWidget::mouseMoveEvent(event);
    if(m_aboutBtnRect.contains(event->pos())){
        if(!m_aboutBtnOption.state.testFlag(QStyle::State_MouseOver)){
            m_aboutBtnOption.state |= QStyle::State_MouseOver;
            this->repaint();
        }
    }else{
        if(m_aboutBtnOption.state.testFlag(QStyle::State_MouseOver)){
            m_aboutBtnOption.state = m_aboutBtnOption.state & (~QStyle::State_MouseOver);
            this->repaint();
        }
    }
}

void CustomTableWidget::leaveEvent(QEvent *event)
{
    QTabWidget::leaveEvent(event);
    if(m_aboutBtnOption.state.testFlag(QStyle::State_MouseOver)){
        m_aboutBtnOption.state = m_aboutBtnOption.state & (~QStyle::State_MouseOver);
        this->repaint();
    }
}

main.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QTabBar>
#include <QPushButton>
#include <QDebug>

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

    ui->tabWidget->setAttribute(Qt::WA_StyledBackground);

    m_widget1 = new QWidget;
    m_widget1->setMouseTracking(true);
    m_widget2 = new QWidget;
    m_widget2->setMouseTracking(true);

    ui->tabWidget->addTab(m_widget1, QStringLiteral("页面一"));
    ui->tabWidget->addTab(m_widget2, QStringLiteral("页面二"));
    m_widget1->parentWidget()->setMouseTracking(true);
}

Widget::~Widget()
{
    delete ui;
}

解析

m_widget1->setMouseTracking(true);
m_widget2->setMouseTracking(true);

子控件遮挡父控件导致父控件接受不到 鼠标移动 事件。虽然

void QWidget::mouseMoveEvent(QMouseEvent *event)
{
    event->ignore();
}

QWidget的鼠标移动默认行为就是没有行为而且会向上传递。但是我们必须 setMouseTracking(true)否则它根本不会由notify发送给event。所以我们要设置m_widget1 m_widget2 为true。 QTabWidget的结构如下 在这里插入图片描述

m_widget1->parentWidget()->setMouseTracking(true);

所以还要设置这个,因为 m_widget1 还套了一个 QStackedWidget

    if(this->tabBar()){
        if(tabWidgetRect == this->tabBar()->rect() || tabWidgetRect == this->tabBar()->tabRect(0) || tabWidgetRect == this->tabBar()->tabRect(1)){
            return;
        }
    }

如上图所示,当我们点击tabBar相关区域时也会触发 tabWidgetpaintEvent 函数。此时QRect tabWidgetRect = event->rect(); tabWidgetRect 是 这个tabBar的 rect或者是某一个 tab 页的宽度,需要被排除在外。

效果图

最后在看看效果吧,家人们 在这里插入图片描述

举报

相关推荐

0 条评论