Я пытался воспроизвести проблему ОП. В отсутствие MCVE я сделал свой собственный testQDockWidgetMenu.cc
:
#include <QtWidgets>
int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
// setup UI
QMainWindow qWinMain;
QLabel qLbl("Choose a menu item");
qWinMain.setCentralWidget(&qLbl);
QDockWidget qDock;
qDock.setWindowTitle("Dockable Menu");
QMenu qMenu("Menu");
#define ADD_ITEM(I) \
qMenu.addAction( \
"Menu Item "#I, [&]() { qLbl.setText("Menu item "#I" chosen."); })
ADD_ITEM(1);
ADD_ITEM(2);
ADD_ITEM(3);
#undef ADD_ITEM
qDock.setWidget(&qMenu);
qWinMain.addDockWidget(Qt::TopDockWidgetArea, &qDock);
qWinMain.show();
// runtime loop
return app.exec();
}
Минимальный проект Qt testQDockWidgetMenu.pro
:
SOURCES = testQDockWidgetMenu.cc
QT += widgets
Скомпилировано и запущено в cygwin64 в Windows 10:
$ qmake-qt5 testQDockWidgetMenu.pro
$ make && ./testQDockWidgetMenu
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQDockWidgetMenu.o testQDockWidgetMenu.cc
g++ -o testQDockWidgetMenu.exe testQDockWidgetMenu.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
Qt Version: 5.9.4

После того, как я щелкнул в пустое пространство справа, я получил это (как описано в OP):

Oops! (Я этого не ожидал.)
Я полагаю, что это поведение встроено в меню: поскольку они предназначены для всплывающих меню, происходит автоматическое закрытие при обнаружении внешнего щелчка.
Я немного пролистал документ. QMenu
есть ли что-то, чтобы подавить это поведение по умолчанию. Вместо этого я нашел:
Этот сигнал испускается непосредственно перед тем, как меню скрыто от пользователя.
Эта функция была введена в Qt 4.2.
Это, по крайней мере, хорошо для обходного пути: если автоматическое закрытие собирается скрыть меню, просто покажите его снова. Чтобы проверить это, я добавил обработчик сигнала:
// install signal handlers
QObject::connect(&qMenu, &QMenu::aboutToHide,
[&]{
QWidget *const pQParent = dynamic_cast<QWidget*>(qMenu.parent());
if (pQParent && pQParent->isVisible()) {
qMenu.show();
qDebug() << "Prevent hiding qMenu";
}
});
(вставлено чуть выше return app.exec();
)
Скомпилировано и запущено снова: Et voilà. Больше нет автоматического закрытия.

Вывод отладки в консоли показывает, что обработчик сигнала делает то, для чего он предназначен:
Qt Version: 5.9.4
Prevent hiding qMenu
Prevent hiding qMenu
Prevent hiding qMenu
Prevent hiding qMenu
Prevent hiding qMenu
Prevent hiding qMenu
Prevent hiding qMenu
Примечание:
Проверка на if (pQParent && pQParent->isVisible())
может показаться немного параноидальной и может быть ненужной.
Я пробовал без, и это сработало. Хотя я заметил, что сообщение отладки появилось также, например, когда я закрыл весь док. Не то чтобы это изменило внешний вид & ndash; если родительский виджет невидим, то и дети тоже.
Итак, я пришел к выводу, что параноидальная проверка не повредит.