How to Create a Custom Context Menu For QTableView
-
wrote on 27 Aug 2013, 12:39 last edited by
Can anyone please post a simple example for creating a custom context menu for a QTableView ? I'm new to Qt. I searched in Google. But couldn't find any examples out there.
-
wrote on 27 Aug 2013, 13:08 last edited by VRonin
Try the following:
main.cpp
#include <QtGui/QApplication> #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QtGui/QWidget> class QTableView; class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); public slots: void customMenuRequested(QPoint pos); private: QTableView *table; }; #endif // WIDGET_H
widget.cpp
#include <QtGui> #include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { QVBoxLayout *l=new QVBoxLayout(this); table=new QTableView(this); table->setContextMenuPolicy(Qt::CustomContextMenu); connect(table, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); l->addWidget(table); } Widget::~Widget(){} void Widget::customMenuRequested(QPoint pos){ QModelIndex index=table->indexAt(pos); QMenu *menu=new QMenu(this); menu->addAction(new QAction("Action 1", this)); menu->addAction(new QAction("Action 2", this)); menu->addAction(new QAction("Action 3", this)); menu->popup(table->viewport()->mapToGlobal(pos)); }
Basically, we tell our QTableView that we want to use a custom context menu by calling the setContextMenuPolicy() method with the arguments Qt::CustomContextMenu. We then create a slot customMenuRequested() and connect it to the customContextMenuRequested() signal. This signal has a QPoint as its argument which is the position at which the request was made relative to the table. This position is useful because we can use it to discover which table cell was clicked on (if any) using the indexAt() method and also to position our menu correctly relative to the mouse.
Hope this helps ;o)
[edit: updated coding tags SGaist]
-
wrote on 2 Sept 2013, 12:25 last edited by
Thank you Jazzycamel for your post. That was really hepful.
But as per your code, The customcontextmenu pops up for the Table View cells. But I want to create a customContextMenu for the TableView Header. (not for the QTableView Cells). Please Help...
-
wrote on 2 Sept 2013, 12:40 last edited by
Look into QHeaderView and repeat the steps to build a custom context menu for that. Then use your own QHeaderView for your QTableView. (i.e. QTableView::setHorizontalHeader() or something along these lines).
-
wrote on 2 Sept 2013, 12:47 last edited by
What have you tried so far? Did you tried using QHeaderView ?
-
wrote on 2 Sept 2013, 12:55 last edited by SGaist
Use the same JazzyCamel's example. In Widget.cpp
Instead of,
table->setContextMenuPolicy(Qt::CustomContextMenu); connect(table, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint)));
Change it to
table->horizontalHeader-> setContextMenuPolicy(Qt::CustomContextMenu); connect(table->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint)));
Hope you get it..
[edit: updated coding tags SGaist]
-
wrote on 2 Sept 2013, 13:01 last edited by SGaist
Rochi got there just as I was finishing the following and is exactly right, as both QTableView and QHeaderView inherit QAbstractItemView the method is the same:
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QtGui/QWidget> class QStandardItemModel; class QTableView; class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = 0); ~Widget(); public slots: void customMenuRequested(QPoint pos); void customHeaderMenuRequested(QPoint pos); private: QStandardItemModel *model; QTableView *table; }; #endif // WIDGET_H
widget.cpp
#include <QtGui> #include "widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) { model=new QStandardItemModel(10,10,this); QVBoxLayout *l=new QVBoxLayout(this); table=new QTableView(this); table->setModel(model); table->setContextMenuPolicy(Qt::CustomContextMenu); connect(table, SIGNAL(customContextMenuRequested(QPoint)), SLOT(customMenuRequested(QPoint))); table->horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu); connect(table->horizontalHeader(), SIGNAL(customContextMenuRequested(QPoint)), SLOT(customHeaderMenuRequested(QPoint))); l->addWidget(table); } Widget::~Widget() { } void Widget::customMenuRequested(QPoint pos){ QModelIndex index=table->indexAt(pos); QMenu *menu=new QMenu(this); menu->addAction(new QAction("Action 1", this)); menu->addAction(new QAction("Action 2", this)); menu->addAction(new QAction("Action 3", this)); menu->popup(table->viewport()->mapToGlobal(pos)); } void Widget::customHeaderMenuRequested(QPoint pos){ int column=table->horizontalHeader()->logicalIndexAt(pos); QMenu *menu=new QMenu(this); menu->addAction(new QAction("Header Action 1", this)); menu->addAction(new QAction("Header Action 2", this)); menu->addAction(new QAction("Header Action 3", this)); menu->popup(table->horizontalHeader()->viewport()->mapToGlobal(pos)); }
Hope this answers your question ;o)
[edit: updated coding tags SGaist]
-
wrote on 28 May 2020, 14:51 last edited by
Jus a side note, creating a nemu on the heap every time the user right clicks is going to eat up a lot of memory in the long term. It's much more efficient to create it once and call popup on it when needed