当 QWidgetAction 被触发时,如何关闭 QMenu?
How do you close a QMenu when its QWidgetAction is triggered?
我有一个 QMenu
,我为其创建了一个 QColorModel
动作小部件(它实际上只是一个 QStandardItemModel
)。我想要的行为是,当用户单击模型中的一种颜色时,应该触发该操作,然后关闭菜单。然而,它似乎并没有这样做,即使我手动触发了这个动作。
我试过手动隐藏菜单,但这是一个错误,因为它不会隐藏菜单可能附加到的父菜单。
这是代码的相关部分:
// color menu
m_colorMenu = new QMenu("color", this);
m_colorView = new QColorView(m_colorMenu);
m_colorViewAction = new QWidgetAction(m_colorMenu);
m_colorViewAction->setDefaultWidget(m_colorView);
m_colorView->setModel(new QStandardColorModel);
connect(m_colorView, &QColorView::clicked, [&](QModelIndex index)
{
QColor color = qvariant_cast<QColor>(index.data(Qt::DecorationRole));
if (m_pen.color() != color)
{
m_pen.setColor(color);
drawIcon();
drawColorIcon();
update();
}
//this->hide(); // kludge, didn't close all parent menus
m_colorViewAction->trigger(); // doesn't seem to cause menu closure
});
m_colorMenu->addAction(m_colorViewAction);
编辑
我也试过添加一些东西来达到以下效果:
QMenu* menu = m_colorMenu;
do
{
menu->close();
menu = dynamic_cast<QMenu*>(menu->parent());
} while (menu);
但它也是 fragile/kludgey,因为它假定 a) 所有小部件都有适当的父级,并且 b) 所有父级实际上都应该是菜单。就我而言,它们不是。
如果包含的菜单不在父级树中,并且您要关闭的菜单不是顶级菜单,则没有简单的方法可以执行此操作。也就是说,有:
核选项
将其添加到 lambda 函数的末尾
auto topLevelWidgets = qApp->topLevelWidgets();
for (auto widget : topLevelWidgets)
{
QMenu* menu = dynamic_cast<QMenu*>(widget);
if (menu)
{
menu->close();
}
}
将在触发操作后关闭所有顶级菜单。这是一个相对不错的方法来完成你想要的,因为:
- 顶级菜单之一将包含相关菜单,并且
- 永不言败,但我想不出在任何情况下您会(或想要)一次打开多个菜单,因此很可能您要关闭的唯一打开的菜单树是预期的一.
我有一个 QMenu
,我为其创建了一个 QColorModel
动作小部件(它实际上只是一个 QStandardItemModel
)。我想要的行为是,当用户单击模型中的一种颜色时,应该触发该操作,然后关闭菜单。然而,它似乎并没有这样做,即使我手动触发了这个动作。
我试过手动隐藏菜单,但这是一个错误,因为它不会隐藏菜单可能附加到的父菜单。
这是代码的相关部分:
// color menu
m_colorMenu = new QMenu("color", this);
m_colorView = new QColorView(m_colorMenu);
m_colorViewAction = new QWidgetAction(m_colorMenu);
m_colorViewAction->setDefaultWidget(m_colorView);
m_colorView->setModel(new QStandardColorModel);
connect(m_colorView, &QColorView::clicked, [&](QModelIndex index)
{
QColor color = qvariant_cast<QColor>(index.data(Qt::DecorationRole));
if (m_pen.color() != color)
{
m_pen.setColor(color);
drawIcon();
drawColorIcon();
update();
}
//this->hide(); // kludge, didn't close all parent menus
m_colorViewAction->trigger(); // doesn't seem to cause menu closure
});
m_colorMenu->addAction(m_colorViewAction);
编辑
我也试过添加一些东西来达到以下效果:
QMenu* menu = m_colorMenu;
do
{
menu->close();
menu = dynamic_cast<QMenu*>(menu->parent());
} while (menu);
但它也是 fragile/kludgey,因为它假定 a) 所有小部件都有适当的父级,并且 b) 所有父级实际上都应该是菜单。就我而言,它们不是。
如果包含的菜单不在父级树中,并且您要关闭的菜单不是顶级菜单,则没有简单的方法可以执行此操作。也就是说,有:
核选项
将其添加到 lambda 函数的末尾
auto topLevelWidgets = qApp->topLevelWidgets();
for (auto widget : topLevelWidgets)
{
QMenu* menu = dynamic_cast<QMenu*>(widget);
if (menu)
{
menu->close();
}
}
将在触发操作后关闭所有顶级菜单。这是一个相对不错的方法来完成你想要的,因为:
- 顶级菜单之一将包含相关菜单,并且
- 永不言败,但我想不出在任何情况下您会(或想要)一次打开多个菜单,因此很可能您要关闭的唯一打开的菜单树是预期的一.