Right-click context menus with Qt

— richardwb on Thursday, July 23, 2009 @ 20:47

Getting right-clicks to popup a context menu is pretty straightforward in Qt. There are just a couple of things to watch out for...

First, there are several ways to tell Qt you want a context menu. One approach is to subclass the widget and override the QWidget::contextMenuEvent() event handler. However, I think the easiest approach is to call setContextMenuPolicy(Qt::CustomContextMenu) on the widget you want, and then connect the customContextMenuRequested() signal to the appropriate slot:

// myWidget is any QWidget-derived class
connect(myWidget, SIGNAL(customContextMenuRequested(const QPoint&)),
    this, SLOT(ShowContextMenu(const QPoint&)));

Next, note that the const QPoint& pos parameter in the customContextMenuRequested() signal is normally in widget coordinates. However, also note that classes which inherit from QAbstractScrollArea1 instead use the coordinates of their viewport(). Either way, you will need to map these coordinates to global coordinates using mapToGlobal().

Finally, simply either popup() or exec() your QMenu. Remember that popup() is non-blocking, so if you wish to use that, make sure your QMenu is created on the heap (or some other way of guaranteeing that the QMenu's lifetime outlasts the scope of the function)!

void MyClass::ShowContextMenu(const QPoint& pos) // this is a slot
    // for most widgets
    QPoint globalPos = myWidget->mapToGlobal(pos);
    // for QAbstractScrollArea and derived classes you would use:
    // QPoint globalPos = myWidget->viewport()->mapToGlobal(pos);

    QMenu myMenu;
    myMenu.addAction("Menu Item 1");
    // ...

    QAction* selectedItem = myMenu.exec(globalPos);
    if (selectedItem)
        // something was chosen, do stuff
        // nothing was chosen

  1. Examples include QTreeWidget, QTreeView, QListWidget, QListView, QTableWidget, QTableView, QTextEdit, QPlainTextEdit, and QMdiArea

comments powered by Disqus