How to Create a Custom Context Menu For QTableView



  • 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.



  • 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&#40;&#41;;
    

    }
    @

    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]



  • 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...



  • 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).



  • What have you tried so far? Did you tried using QHeaderView ?



  • 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]



  • 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]


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.