单击 QT C++ 上下文菜单中的 "more items..." 选项
Click for "more items..." option on context menu in QT C++
我使用 C++
在 QT
中实施了一个 context menu
项目。我希望上下文菜单中最多显示 5 个元素。但它总共有 15 个元素,我希望用户单击“更多项目...”或某种“向下”箭头按钮,以便扩展上下文菜单以显示超过 5 个元素。可能吗?如果是,我将不胜感激一些指向正确方向的指示。谢谢。
请注意,我尝试实现它的方式是,单击“更多项目”时上下文菜单会消失...所以这不是我想要的。
//代码
void myWidget::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction(new QAction("Action 1", this));
menu.addAction(new QAction("Action 2", this));
menu.addAction(new QAction("Action 3", this));
menu.addAction(new QAction("Action 4", this));
menu.addAction(new QAction("Action 5", this));
QAction *moreItems = new QAction("More items...", this);
QObject::connect(moreItems , SIGNAL(clicked()), this, SLOT(moreItemsClicked()));
menu.addAction(moreItems);
menu.exec(event->globalPos());
}
void myWidget::moreItemsClicked()
{
//Now what! Need help!
}
首先,我建议您不要使用宏 SIGNAL
和 SLOT
,或者如果您想使用它们 - 请始终检查连接结果。您的意图是连接到 QAction
的 clicked
信号,但是有 no such signal。
如果您将使用函数指针而不是 SIGNAL
- 您将得到编译错误,这总是比运行时断言更好。
关于问题本身,请考虑简单的多级菜单:
但如果你真的想要,你可以这样扩展菜单:
void contextMenuEvent(QContextMenuEvent* event)
{
auto menu = new QMenu(this);
menu->addAction(new QAction("Action 1", this));
menu->addAction(new QAction("Action 2", this));
menu->addAction(new QAction("Action 3", this));
menu->addAction(new QAction("Action 4", this));
menu->addAction(new QAction("Action 5", this));
QAction* moreItems = new QAction("More items...", this);
const auto connection_result = connect(moreItems, &QAction::triggered, [=]()
{
menu->removeAction(moreItems);
menu->addAction(new QAction("Action 6", this));
menu->addAction(new QAction("Action 7", this));
menu->exec(event->globalPos());
});
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
menu->addAction(moreItems);
menu->exec(event->globalPos());
}
您将被迫重新打开菜单,因为它会在点击后隐藏。
此外,必须在堆上创建菜单才能在 lambda 中使用。这迫使我们注意内存泄漏。为此,您可以添加此连接:
connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
但在那种情况下,我们需要依赖连接顺序,因为我们希望在执行 lambda 时菜单仍然存在,这不是最好的。或者从每个动作中调用 QMenu::deleteLater
,这也不好。
所以我会像这样重新创建扩展菜单:
QMenu* CreateContextMenu(bool is_extended, QAction* extra_action, QWidget* parent)
{
auto menu = new QMenu(parent);
const auto connection_result = connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
menu->addAction(new QAction("Action 1", this));
menu->addAction(new QAction("Action 2", this));
menu->addAction(new QAction("Action 3", this));
menu->addAction(new QAction("Action 4", this));
menu->addAction(new QAction("Action 5", this));
if (is_extended)
{
menu->addAction(new QAction("Action 6", this));
menu->addAction(new QAction("Action 7", this));
} else {
menu->addAction(extra_action);
}
return menu;
}
void contextMenuEvent(QContextMenuEvent* event)
{
QAction* moreItems = new QAction("More items...", this);
const auto connection_result = connect(moreItems, &QAction::triggered, [=]() {
auto extended_menu = CreateContextMenu(true, nullptr, this);
extended_menu->exec(event->globalPos());
});
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
auto menu = CreateContextMenu(false, moreItems, this);
menu->exec(event->globalPos());
}
您还可以改进 CreateContextMenu 的界面,因为第一个和第二个参数不能同时存在,可能使用 std::variant
。但我决定这将是题外话。
我使用 C++
在 QT
中实施了一个 context menu
项目。我希望上下文菜单中最多显示 5 个元素。但它总共有 15 个元素,我希望用户单击“更多项目...”或某种“向下”箭头按钮,以便扩展上下文菜单以显示超过 5 个元素。可能吗?如果是,我将不胜感激一些指向正确方向的指示。谢谢。
请注意,我尝试实现它的方式是,单击“更多项目”时上下文菜单会消失...所以这不是我想要的。
//代码
void myWidget::contextMenuEvent(QContextMenuEvent *event)
{
QMenu menu(this);
menu.addAction(new QAction("Action 1", this));
menu.addAction(new QAction("Action 2", this));
menu.addAction(new QAction("Action 3", this));
menu.addAction(new QAction("Action 4", this));
menu.addAction(new QAction("Action 5", this));
QAction *moreItems = new QAction("More items...", this);
QObject::connect(moreItems , SIGNAL(clicked()), this, SLOT(moreItemsClicked()));
menu.addAction(moreItems);
menu.exec(event->globalPos());
}
void myWidget::moreItemsClicked()
{
//Now what! Need help!
}
首先,我建议您不要使用宏 SIGNAL
和 SLOT
,或者如果您想使用它们 - 请始终检查连接结果。您的意图是连接到 QAction
的 clicked
信号,但是有 no such signal。
如果您将使用函数指针而不是 SIGNAL
- 您将得到编译错误,这总是比运行时断言更好。
关于问题本身,请考虑简单的多级菜单:
但如果你真的想要,你可以这样扩展菜单:
void contextMenuEvent(QContextMenuEvent* event)
{
auto menu = new QMenu(this);
menu->addAction(new QAction("Action 1", this));
menu->addAction(new QAction("Action 2", this));
menu->addAction(new QAction("Action 3", this));
menu->addAction(new QAction("Action 4", this));
menu->addAction(new QAction("Action 5", this));
QAction* moreItems = new QAction("More items...", this);
const auto connection_result = connect(moreItems, &QAction::triggered, [=]()
{
menu->removeAction(moreItems);
menu->addAction(new QAction("Action 6", this));
menu->addAction(new QAction("Action 7", this));
menu->exec(event->globalPos());
});
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
menu->addAction(moreItems);
menu->exec(event->globalPos());
}
您将被迫重新打开菜单,因为它会在点击后隐藏。
此外,必须在堆上创建菜单才能在 lambda 中使用。这迫使我们注意内存泄漏。为此,您可以添加此连接:
connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
但在那种情况下,我们需要依赖连接顺序,因为我们希望在执行 lambda 时菜单仍然存在,这不是最好的。或者从每个动作中调用 QMenu::deleteLater
,这也不好。
所以我会像这样重新创建扩展菜单:
QMenu* CreateContextMenu(bool is_extended, QAction* extra_action, QWidget* parent)
{
auto menu = new QMenu(parent);
const auto connection_result = connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
menu->addAction(new QAction("Action 1", this));
menu->addAction(new QAction("Action 2", this));
menu->addAction(new QAction("Action 3", this));
menu->addAction(new QAction("Action 4", this));
menu->addAction(new QAction("Action 5", this));
if (is_extended)
{
menu->addAction(new QAction("Action 6", this));
menu->addAction(new QAction("Action 7", this));
} else {
menu->addAction(extra_action);
}
return menu;
}
void contextMenuEvent(QContextMenuEvent* event)
{
QAction* moreItems = new QAction("More items...", this);
const auto connection_result = connect(moreItems, &QAction::triggered, [=]() {
auto extended_menu = CreateContextMenu(true, nullptr, this);
extended_menu->exec(event->globalPos());
});
Q_ASSERT(connection_result);
Q_UNUSED(connection_result);
auto menu = CreateContextMenu(false, moreItems, this);
menu->exec(event->globalPos());
}
您还可以改进 CreateContextMenu 的界面,因为第一个和第二个参数不能同时存在,可能使用 std::variant
。但我决定这将是题外话。