分享

QToolButton 之续述

 勤奋不止 2019-06-29

有时候我们需要根据按钮的check状态来设置按钮的不同背景或者是实现不同的功能。关于Qt 中的四大按钮——QCheckBox, QPushButton, QRadioButton, QToolButton,这四个按钮都继承自QAbstractButton,所以他们Check状态的变化都由QAbstractButton来控制。要使用按钮的Check状态前提需要设置属性checkable为true。

通常每次点击按钮都会改变按钮的Check状态,看一下Qt如何实现的:

void QAbstractButton::nextCheckState()

This virtual handler is called when a button is clicked. The default implementation calls setChecked(!isChecked()) if the button isCheckable(). It allows subclasses to implement intermediate button states.

在按钮设置checkable为true时,当按钮被点击的时候nextCheckState方法被调用,而默认实现是调用setChecked(!isChecked())方法,也可以通过子类实现不同的按钮状态。

所以简单的来讲在每次点击按钮的时候其实就是调用了setChecked(!isChecked())方法。

这里我重写了QToolButton,并重写了mousePressEvent、mouseReleaseEvent、nextCheckState、checkStateSet方法,并对pressed、clicked、released信号绑定了不同的槽:

    connect(this, SIGNAL(pressed()), this, SLOT(onMousePress()));
    connect(this, SIGNAL(clicked()), this, SLOT(onMouseClicked()));
    connect(this, SIGNAL(released()), this, SLOT(onMouseRelease()));

点击按钮后输出:

this is mousePressEvent Fuction
this is onMousePress Fuction
this is mouseReleaseEvent Fuction
this is nextCheckState Fuction
this is onMouseRelease Fuction
this is onMouseClicked Fuction

根据上面的调用顺序我们可以在相应的地方去调用setChecked方法来设置按钮的Check状态。需要注意的是setChecked方法不是随便用的。如果我们想每次按钮点击的时候都将按钮的Check状态设置为true,在mousePressEvent或者onMousePress或者mouseReleaseEvent方法中去调用setChecked(true),那么在nextCheckState方法中会调用setChecked(!isChecked());这样的话每次点击按钮之后,按钮的Check状态都会设置为false。

关于checkStateSet方法的调用,看一下Qt中对这个方法的描述:

void QAbstractButton::checkStateSet()

This virtual handler is called when setChecked() is used, unless it is called from within nextCheckState(). It allows subclasses to reset their intermediate button states.

当调用setChecked方法时会自动调用checkStateSet方法,而在nextCheckState方法中调用setChecked方法时则不会调用。当然在checkStateSet方法内部调用setChecked方法的话也会自动调用本身,会导致进入到一个死循环中导致程序崩溃,所以不能在checkStateSet内部设置按钮Check状态。

重新设置QToolButton菜单按钮区域的新功能

我们在给QToolButton进行设置setPopupMode(QToolButton::MenuButtonPopup);(带弹出式菜单)时,再设置一个菜单变量setMenu(m_menu); 这样在我们点击QToolButton菜单区域部分会弹出自定义菜单,如下图:

这里写图片描述

但是这样我们点击QToolButton菜单区域部分只能弹出之前设置的菜单,没有可拓展性。所以我们可以获取QToolButton右边菜单的区域,在鼠标点击这块区域时我们可以有不同的实现。下面是在mousePressEvent中获取到QToolButton菜单区域,然后判断当前鼠标是否点击在该区域中。

void MyToolButton::mousePressEvent(QMouseEvent *event)
{
    QStyleOptionToolButton styleIOption;
    initStyleOption(&styleIOption);
    if (Qt::LeftButton == event->button() && MenuButtonPopup == popupMode())
    {
        // 获取QToolButton右边菜单按钮的区域;
        QRect popupButtonRect = style()->subControlRect(QStyle::CC_ToolButton, &styleIOption, QStyle::SC_ToolButtonMenu, this);
        if (popupButtonRect.isValid() && popupButtonRect.contains(event->pos()))
        {
            //在这里实现不同的功能,我这里是根据鼠标点击的位置显示菜单
            if (this->isChecked())
            {
                m_menu->exec(event->globalPos());
            }
            // 可以向外发出信号
            //emit signalToolMenuClicked();
        }
    }
    qDebug() << "this is mousePressEvent Fuction";
    QToolButton::mousePressEvent(event);
}

下图为根据鼠标点击的位置显示菜单:

根据鼠标点击的位置显示菜单

下图为点击菜单区域弹出窗口:

点击菜单区域弹出窗口

仔细看下图的菜单小箭头的颜色变化,不知道算不算上是QQ的一个bug。不过这只是一个小细节,纯属好玩发现的。(鼠标第一次点击小箭头变成黑色,再次点击变成灰色,后面连续点击任然是灰色,当鼠标离开这个控件区域后,再次点击变成黑色。也就是说在每次鼠标第一次进入到菜单按钮区域时点击小箭头会变黑色后面再次点击变灰色,可能个人想法不同,实现方案也不同。这里写图片描述

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多