一. 缺陷信息
缺陷:当QMenu使用QMenu::addMenu(QMenu *menu)添加一个子菜单后。想隐藏子菜单时,调用hide()或者setVisible()时,子菜单依然会显示
二.根因分析
Qt在加入子菜单的时候,在菜单中只加了子菜单的action
QAction *QMenu::addMenu(QMenu *menu)
{
QAction *action = menu->menuAction();
addAction(action);
return action;
}
void QWidget::addAction(QAction *action)
{
insertAction(nullptr, action);
}
void QWidget::insertAction(QAction *before, QAction *action)
{
if (Q_UNLIKELY(!action)) {
qWarning("QWidget::insertAction: Attempt to insert null action");
return;
}
Q_D(QWidget);
if (d->actions.contains(action))
removeAction(action);
int pos = d->actions.indexOf(before);
if (pos < 0) {
before = nullptr;
pos = d->actions.size();
}
d->actions.insert(pos, action);
QActionPrivate *apriv = action->d_func();
apriv->associatedObjects.append(this);
QActionEvent e(QEvent::ActionAdded, action, before);
QCoreApplication::sendEvent(this, &e);
}
并且在QMenu的hideEvent中并没有进行隐藏action的操作
void QMenu::hideEvent(QHideEvent *)
{
Q_D(QMenu);
emit aboutToHide();
if (d->eventLoop)
d->eventLoop->exit();
d->setCurrentAction(nullptr);
#ifndef QT_NO_ACCESSIBILITY
QAccessibleEvent event(this, QAccessible::PopupMenuEnd);
QAccessible::updateAccessibility(&event);
#endif
#if QT_CONFIG(menubar)
if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget))
mb->d_func()->setCurrentAction(nullptr);
#endif
if (QMenuPrivate::mouseDown == this)
QMenuPrivate::mouseDown = nullptr;
d->hasHadMouse = false;
if (d->activeMenu)
d->hideMenu(d->activeMenu);
d->causedPopup.widget = nullptr;
d->causedPopup.action = nullptr;
if (d->scroll)
d->scroll->scrollTimer.stop(); //make sure the timer stops
}
所以我们调用QMenu的hide()或者setVisible()是没有用的
三.修复方案
隐藏时需要调用子菜单的QMenu::menuAction()->setVisible(false);

929

被折叠的 条评论
为什么被折叠?



