Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to Create a Custom Context Menu For QTableView
QtWS25 Last Chance

How to Create a Custom Context Menu For QTableView

Scheduled Pinned Locked Moved General and Desktop
8 Posts 5 Posters 80.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    JoyRider
    wrote on last edited by
    #1

    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.

    1 Reply Last reply
    0
    • jazzycamelJ Offline
      jazzycamelJ Offline
      jazzycamel
      wrote on last edited by VRonin
      #2

      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]

      For the avoidance of doubt:

      1. All my code samples (C++ or Python) are tested before posting
      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
      1 Reply Last reply
      1
      • J Offline
        J Offline
        JoyRider
        wrote on last edited by
        #3

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

        1 Reply Last reply
        0
        • T Offline
          T Offline
          thEClaw
          wrote on last edited by
          #4

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

          1 Reply Last reply
          0
          • M Offline
            M Offline
            Macro
            wrote on last edited by
            #5

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

            1 Reply Last reply
            0
            • M Offline
              M Offline
              Macro
              wrote on last edited by SGaist
              #6

              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]

              1 Reply Last reply
              0
              • jazzycamelJ Offline
                jazzycamelJ Offline
                jazzycamel
                wrote on last edited by SGaist
                #7

                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]

                For the avoidance of doubt:

                1. All my code samples (C++ or Python) are tested before posting
                2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
                1 Reply Last reply
                2
                • VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #8

                  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

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  1 Reply Last reply
                  5

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved