qtc++11qt5qmenuqaction

QMenu (and submenu) opens up in a different monitor location


I built an application that uses QMenu and its related submenu. The Qmenu is triggered to open via QAction.

The problem I have is that as soon as I call the QAction and I chose the QAction that carries the "Options", it should open the QMenu, but instead the QMenu open in another location of the application looking totally detached.

Below is the wrong behavior, where it is possible to see the QMenu opening in another location of the Desktop.

worng

Here is the expected behavior where the QMenu opens up after selecting "Oprions":

correct

I am not sure of why this is happening. Below the snippet of code related:

rostreewidget.h

    class ROSTreeWidget : public QTreeWidget
    {
        Q_OBJECT

    public:
        enum ROSType {
            NULLPTR,
            TABLE,
            BASE,
            MENU
        };

        ROSTreeWidget(QWidget *parent = nullptr);
        ROSType rostype(ROSTreeItem *rosItem) const;
        ROSType rostype() const {
            return rostype(currentItem());
        }

    signals:
        void selectFrom();
        void editLaserTable();

    private:
        QAction *mActionSELECT_FROM;
        QAction *mActionEditLaserTable;
        QAction *mAddMenuOptions;

        QMenu *submenuLaserScanA;
        QAction *submenuActionA, *submenuActionB, *submenuActionC;
        QMenu *submenuLaserScanB;
        QAction *submenuActionAA, *submenuActionBB, *submenuActionCC;
        QMenu *submenuLaserScanC;
        QAction *submenuActionAAA, *submenuActionBBB, *submenuActionCCC;

    };

rostreewidget.cpp

ROSTreeWidget::ROSTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
    mActionSELECT_FROM = new QAction(QIcon(":"), "SELECT * FROM", this);
    mActionEditLaserTable = new QAction(QIcon(":"), "Edit LaserScan Table");
    mAddMenuOptions = new QAction(QIcon(":"), "Options", this);

    addActions({ mActionSELECT_FROM,
                 mActionEditLaserTable,
                 mAddMenuOptions});

    connect(mActionSELECT_FROM, &QAction::triggered, [&]() {
        emit selectFrom();
    });

    connect(mActionEditLaserTable, &QAction::triggered, [&]() {
        emit editLaserTable();
    });

    connect(mAddMenuOptions, &QAction::triggered, [&]() {
        mMenu = new QMenu();

        submenuLaserScanA = mMenu->addMenu( "Menu A" );
        mMenu->addSeparator();

        submenuLaserScanB = mMenu->addMenu( "Menu B" );
        mMenu->addSeparator();

        submenuLaserScanC = mMenu->addMenu( "Menu C" );
        submenuActionAAA = submenuLaserScanC->addAction("Setup C" );
        submenuActionBBB = submenuLaserScanC->addAction( "Setup C" );

        mMenu->show();
    });
}

What I have done so far:

  1. After following this source I was able to prepare the menu and the submenu to be inserted in the QAction and in fact all the related settings about it are as I need them to be.

  2. I thought that linking the QAction inside the lambda function, exactly as I did for the other choices, would have worked, but instead what I am obtaining as soon as I launch the application is a QMenu that opens in another location of the Desktop without being linked to the main choice as shown below.

  3. According to the documentation QMenu::addMenu parameters set are correct, so what is going on?

Thanks for pointing to the right direction for solving this issue.


Solution

  • Use this as a general pattern:

    {
        QMenu menu;
        
        menu.addAction(...);
        menu.addAction(...);
        
        menu.exec(QCursor::pos()); // exec returns a triggered QAction
        // process action
    }
    

    QMenu::exec() is modal. You don't need a QMenu instance outside the function.