Qt实现可关闭页签

记录

最近在工作中遇到了用Qt实现类似于浏览器可关闭页签的功能,在网上没有找到相关资料,只能自己动手,丰衣足食了。

实现的效果

这里写图片描述

实现思路

自绘QPushButton,分开处理按钮区域和非按钮区域。

核心代码


CloseableButton::CloseableButton(const QString &text, QWidget *parent)
    : QPushButton{text, parent}
{
    // 页签有两种状态,普通状态和按下状态,因此设置checkable为true
    setCheckable(true);

    // 为了在没有鼠标按下的时候响应MouseMove事件,设置MouseTracking为true
    setMouseTracking(true);
}

void CloseableButton::paintEvent(QPaintEvent *)
{
    QPainter painter(this);  // 创建Painter

    QPoint curPos = getCursorPos();  // 当前鼠标位置

    // 背景
    if (isChecked())  // 选中状态
    {
        painter.fillRect(rect(), QColor(244,248,255));
    }
    else  // 非选中状态
    {
        if (rect().contains(curPos))  // 鼠标在按钮区域
        {
            painter.fillRect(rect(), QColor(222,231,245));
        }
        else  // 鼠标不在按钮区域
        {
            painter.fillRect(rect(), QColor(213,225,242));
        }
    }

    // 关闭按钮
    QRect closeButtonRect = getCloseButtonRect();  // 获取关闭按钮坐标
    if (closeButtonRect.contains(curPos))  // 鼠标在关闭按钮区域
    {
        if (m_pressedOnCloseButton)  // 鼠标在关闭按钮区域按下
        {
            painter.drawImage(closeButtonRect.topLeft(), QImage(":/skin/closeTabPressed.png"));
        }
        else  // 鼠标悬停在关闭按钮区域
        {
            painter.drawImage(closeButtonRect.topLeft(), QImage(":/skin/closeTabHot.png"));
        }
    }
    else  // 鼠标不在按钮区域
    {
        painter.drawImage(closeButtonRect.topLeft(), QImage(":/skin/closeTabNormal.png"));
    }

    // 文本
    QRect textRect;
    textRect.setTop(9);
    textRect.setLeft(8);
    textRect.setBottom(25);
    if (isChecked())  // 选中状态
    {
        textRect.setRight(rect().right() - 23);
        painter.setFont(QFont(painter.font().family(), -1, QFont::Bold));  // 选中状态文字设置为粗体
    }
    else  // 非选中状态
    {
        textRect.setRight(rect().right() - 28);
    }
    QFontMetrics fontMetrics(painter.font());
    QString textDraw = fontMetrics.elidedText(text(), Qt::ElideRight, textRect.width());  // 如果文字超出显示区域,则末尾截断,加省略号
    painter.drawText(textRect, Qt::TextSingleLine, textDraw);
}

void CloseableButton::mouseMoveEvent(QMouseEvent *e)
{
    QPushButton::mouseMoveEvent(e);
    update();
}

void CloseableButton::mousePressEvent(QMouseEvent *e)
{
    // 记录按下位置
    auto curPos = getCursorPos();
    if (getCloseButtonRect().contains(curPos))
    {
        m_pressedOnCloseButton = true;
    }
    else
    {
        m_pressedOnCloseButton = false;
        if (rect().contains(curPos))
        {
            m_pressedOnButton = true;
            QPushButton::mousePressEvent(e);
        }
        else
        {
            m_pressedOnButton = false;
        }
    }
    update();
}

void CloseableButton::mouseReleaseEvent(QMouseEvent *e)
{
    // 根据不同的鼠标按下状态发射不同的信号
    auto curPos = getCursorPos();
    if (m_pressedOnCloseButton && getCloseButtonRect().contains(curPos))  // 在关闭按钮区域按下并释放鼠标左键
    {
        resetPressState();
        update();
        emit closeButtonClicked(this);  // 发射自定义信号
    }
    else
    {
        if (m_pressedOnButton && rect().contains(curPos))  // 在页签区域按下并释放鼠标左键
        {
            resetPressState();
            update();
            QPushButton::mouseReleaseEvent(e);  // 调用父类方法发射clicked信号
        }
        else
        {
            resetPressState();
            update();
        }
    }
}

工程下载

工程编译器为 qt-mingw530-5.7.1。已上传至github,欢迎大家下载。下载地址:
https://github.com/comaxy/tabbuttondemo.git
如果有错误或可以改善的地方,请不吝赐教。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值