像 QToolButton 一样的办公室

Office like QToolButton

我目前正在尝试使 QToolButton 看起来与 Office 中的等效。

它应该是这样的:

我知道我可以使用 QToolButton::menu-button 访问菜单按钮,但是 QToolButton::menu-button:hover 与 QToolButton:hover 相同,所以我不能区分两者,我可以' 为 QToolButton::menu 按钮设置边框。有什么想法吗?

您可以创建类似拆分按钮的东西。

class SplitButton : public QPushButton
{
    Q_OBJECT
public:
    explicit SplitButton(QWidget *parent = 0);
    void setMenu(QMenu* menu);

protected:
    void resizeEvent ( QResizeEvent * );
    void mousePressEvent ( QMouseEvent * );
private:
    QFrame* line;
};

增加了通过setMenu() 方法插入菜单的机会。 QFrame 需要分离按钮和弹出菜单。

在构造函数中只初始化基class:

#include <QFrame>
#include <QMenu>
#include <QResizeEvent>

SplitButton::SplitButton(QWidget *parent):
    QPushButton(parent)
{

}

弹出菜单将添加如下:

void SplitButton::setMenu( QMenu* menu )
{
    if (menu) {
        line = new QFrame(this);
        line->setFrameShape(QFrame::VLine);
        line->setFrameShadow(QFrame::Sunken);

        QPushButton::setMenu(menu);
        connect(menu, &QMenu::triggered, [=](QAction *act) {
           setText(act->text());
        });
    }
}

如您所见,我们使用了 QPushButton::setMenu() method and connect menu triggered signal to slot, realized with labda, so you need include c++11 compatibility

在我们需要覆盖resize、mousePress 和keyPressed 事件之后。作为最小的例子,我做了第二个。

void SplitButton::resizeEvent ( QResizeEvent * event )
{
    if (menu()) {
        int width  = event->size().width();
        int height = event->size().height();
        line->setGeometry(QRect(width - 18, 4, 3, height - 8));
    }
}

如果菜单可用,在调整大小事件中,我们为伪按钮添加偏移量的帧。

void SplitButton::mousePressEvent( QMouseEvent * event )
{
    if (menu()) {
        if ( width()-event->x() <= 15 )
            showMenu();
        else
            setDown(true);
    } else {
        QPushButton::mousePressEvent(event);
    }
}

对于 mousePress 事件,我们只是 select 我们想要做的事情:显示菜单或按钮。

用法:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent), m_file(QString())
{
    setupUi(this);  

    SplitButton *split = new SplitButton;
    split->setText("B");
    QMenu *menu = new QMenu;
    menu->addAction("Y");
    menu->addAction("B");
    menu->addAction("U");

    split->setMenu(menu);
    split->setCheckable(true);
    Ui::MainWindow::mainToolBar->addWidget(split);
}

并且您可以为类似 Office 的效果设置按钮 chechable

这只是其中一种可能的实现方式,希望对您有所帮助。

我在屏幕上的样子:

当然,这不是最终结果,您需要根据需要重新绘制或使用 styles 进行平面样式。