创建带下拉菜单的工具条按钮

如何构造一个带图标和下拉菜单的工具条按钮, Qt的例子DiagramScene给出了很好的例子.

提供了三个函数, 并在MainWindow的构造函数中依次调用:

  • createActions()
  • createToolBox()
  • createMenus()

重要的代码在createToolBox()中, 创建的:

下面是创建了按钮fontColorButton, 就是上图中被展开下拉菜单的按钮.

  • 首先要创建QToolButton,
  • 然后要调用它的setPopupMode()函数, 将其设置为QToolButton::MenuButtonPopup. 这样, 就会有下拉的标志和菜单动作.
  • 然后要调用它的setMenu()函数为它设置菜单. 在这里, 我们通过函数createColorMenu()来创建并返回创建的菜单的指针.
  • 这个按钮对应的QActiontextAction, 注意, 当为下来菜单的时候, 我们指定QAction的方式.
  • 另外, 一个要注意的是对setAutoFillBackground()的调用.
1
2
3
4
5
6
7
fontColorToolButton = new QToolButton;
fontColorToolButton->setPopupMode(QToolButton::MenuButtonPopup);
fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()), Qt::black));
textAction = fontColorToolButton->menu()->defaultAction();
fontColorToolButton->setIcon(createColorToolButtonIcon(":/images/textpointer.png", Qt::black));
fontColorToolButton->setAutoFillBackground(true);
connect(fontColorToolButton, &QAbstractButton::clicked, this, &MainWindow::textButtonTriggered);

再看createColorMenu()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
{
QList<QColor> colors;
colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow;
QStringList names;
names << tr("black") << tr("white") << tr("red") << tr("blue")
<< tr("yellow");

QMenu *colorMenu = new QMenu(this);
for (int i = 0; i < colors.count(); ++i) {
QAction *action = new QAction(names.at(i), this);
action->setData(colors.at(i));
action->setIcon(createColorIcon(colors.at(i)));
connect(action, SIGNAL(triggered()), this, slot);
colorMenu->addAction(action);
if (colors.at(i) == defaultColor)
colorMenu->setDefaultAction(action);
}
return colorMenu;
}

QIcon MainWindow::createColorIcon(QColor color)
{
QPixmap pixmap(20, 20);
QPainter painter(&pixmap);
painter.setPen(Qt::NoPen);
painter.fillRect(QRect(0, 0, 20, 20), color);

return QIcon(pixmap);
}

在这个程序里面是动态生成的图标, 这个当然不一定要这样, 我们也可以使用其他的方式来指定图标等.

createColorMenu()中, 是用const char *来传递slot函数的:
调用者利用SLOT(textColorChanged())来将slot函数传递进去.

1
fontColorToolButton->setMenu(createColorMenu(SLOT(textColorChanged()), Qt::black));

而使用者:

1
2
3
4
5
6
QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
{
...
connect(action, SIGNAL(triggered()), this, slot);
...
}

当然, 进入C++17之后, 上述可以进行简化. 我们先不管.

我们可以接下来看textAction这个QAction, 这个代码很有意思的是, 它其实并没有使用textAction作为常规的signal-slot关联使用, 而是仅仅是用它来作为一个数据存储的单元