简体   繁体   中英

How to create a context menu for right click in QGraphicsView

I created a graphics view using the designer in Qt creator.

The hierarchy is the following:

在此处输入图像描述

When I do a right click in the area of my graphics view nothing happens (which is the default behavior afaik). Since I'm trying to show a drop down menu on right click but I can't get it to work I added a connect and custom slot.

Here is my code:


MainWindow::MainWindow(QWidget *parent) :
   QMainWindow(parent),
   ui(new Ui::MainWindow)
{
   ui->setupUi(this);
   MainWindow:: makePlot();
=
   ui->graphView->setContextMenuPolicy(Qt::CustomContextMenu);
   
   QObject::connect(ui->graphView ,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(on_graphView_customContextMenuRequested(const QPoint &)));
   scene = new QGraphicsScene();
   ui->graphView->setScene(scene);
...
}

And the slot function that is called to handle the menu:

`

void MainWindow::on_graphView_customContextMenuRequested(const QPoint &pos)
{

    qDebug() << " custom menuu!!!!!!!!!"<<  "##"<< pos.x() << "  ;  "<< pos.y();
//    QMenu menu(this);
//        menu.addAction("...1");
//        menu.addAction("...2");
//        menu.exec(pos);
}

`

The problem (s):

  1. the qdebug string is printed twice on my console on each single right click, why does that happen? It is supposed to appear only once...

  2. I'm drawing Qgraphicsitems on my scene, the on_graphView_customContextMenuRequested seems to be triggered even when I right click a drawn item and not only a blank space in the scene, how do I get it to trigger only for graphview, in areas with nothing on top (no overlay of item on scene).

  3. the coordinates in pos are relative the graphview dimensions, therefore when I uncomment the menu.exec in the above code, the menu is shown in a wrong location. How do I convert my pos to global coordinates relative to the entire Windows and not only the graphicsview.

Explanation:

  1. It gets 2 impressions because the on_graphView_customContextMenuRequested slot is invoked 2 times since there are 2 connections. The first connection is the one made by using QtDesigner that uses the uic tool to generate C++ code using the.ui, this connection is automatic if the name of the slot complies with the void on_<object name>_<signal name>(<signal parameters>); rule (See this ), and the second connection is the one you show in the code. There are several options:

    1.1 Change the name of the slot.

    1.2 Remove the connection that you show.

  2. The customContextMenuRequested signal is emitted whether or not there is an item, the solution in that case is to filter if there is an item or not.

  3. The exec() method must use the global position but the customContextMenuRequested signal passes the position with respect to the widget that emits the signal, so you must convert it to global position.

MWE:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->graphView->setContextMenuPolicy(Qt::CustomContextMenu);
    scene = new QGraphicsScene();
    ui->graphView->setScene(scene);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_graphView_customContextMenuRequested(const QPoint &pos)
{
    if(ui->graphView->itemAt(pos))
        return;
    QMenu menu(this);
    menu.addAction("...1");
    menu.addAction("...2");
    menu.exec(ui->graphView->mapToGlobal(pos));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM