2015-09-28 4 views
1

У меня есть QMenu, для которого я создал виджет действия QColorModel (это фактически просто QStandardItemModel). Мое желаемое поведение заключается в том, что когда пользователь нажимает один из цветов в модели, действие должно запускаться, а меню закрывается. Однако, похоже, это не так, даже когда я запускаю действие вручную.Как вы закрываете QMenu при срабатывании QWidgetAction?

Я пробовал вручную скрывать меню, но это kludge, потому что он не скроет родительские меню, к которым может быть привязано меню.

Вот соответствующий раздел кода:

// 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); 

EDIT

Я также попытался добавить что-то к эффекту:

QMenu* menu = m_colorMenu; 
do 
{ 
    menu->close(); 
    menu = dynamic_cast<QMenu*>(menu->parent()); 
} while (menu); 

, но он также является хрупким/kludgey, потому что он предполагает, что: а) все виджеты должным образом определены, и б) что все родители на самом деле должны быть меню. В моем случае это не так.

ответ

2

Если содержащиеся меню не находятся в дереве родительских элементов, а меню, которое вы хотите закрыть, не является меню верхнего уровня, нет простого способа сделать это. Тем не менее, есть:

ЯДЕРНОЕ ВАРИАНТ

Добавление этого к концу лямбда-функции

auto topLevelWidgets = qApp->topLevelWidgets(); 
for (auto widget : topLevelWidgets) 
{ 
    QMenu* menu = dynamic_cast<QMenu*>(widget); 
    if (menu) 
    { 
     menu->close(); 
    } 
} 

приведет ВСЕ меню верхнего уровня, чтобы закрыть после того, как действие вызывается. Это относительно нормально способ сделать то, что вы хотите, потому что:

  1. один из меню верхнего уровня будет содержать меню в вопросе и
  2. никогда не говори никогда, но я не могу вспомнить ни одного случая где вы могли бы (или хотеть) открыть более одного меню за раз, поэтому, скорее всего, единственное открытое дерево меню, которое вы закроете, является предполагаемым.