Qt:上下文菜单/连接参数

Qt: Context menu / connect with parameters

我在 Qt 中连接上下文菜单操作时遇到问题。我知道周围有很多类似的问题,但是我还没有找到解决方案。

我有一系列使用 QCustomplot 构建的绘图。

我想要做的是在每个图的背景上单击鼠标右键时创建一个上下文菜单,列出图中存在的所有信号。通过单击此菜单的条目,相应的信号应隐藏(如果当前可见)或可见(如果隐藏)。

现在,我已经定义了一个名为 PlotHandler 的 class,我将其相关部分粘贴在下面:

plotHandler.cpp

#include "plothandler.h"

PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
    QWidget(parent), scrolling(false), refreshing(true)
{
    pPlot = new QCustomPlot(this);
    pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}

void PlotHandler::contextMenuRequest(QPoint pos)
{
    int i;
    QMenu *menu = new QMenu(this);
    for(i=0; i<pGroup->getDataLength(); i++)
        {
            QAction *menuEntry;
            menuEntry = new QAction(pPlot->graph(i)->name(), this);
            menuEntry->setProperty("graphIdx", i);
            menu->addAction(menuEntry);
            connect(menuEntry, SIGNAL(triggered()), this, SLOT(addRemoveGraph()));
        }
        menu->popup(pPlot->mapToGlobal(pos));    
}

void PlotHandler::addRemoveGraph()
{
    QAction *selectedSignal = qobject_cast<QAction *>(sender());
    int tmp = selectedSignal->property("graphIdx").toInt();

    if (pPlot->graph(tmp)->visible())
    {
        pPlot->graph(tmp)->setVisible(false);
    }
    else
    {
        pPlot->graph(tmp)->setVisible(true);
    }
}

plotHandler.h

class PlotHandler : public QWidget
{
    Q_OBJECT
public:
    explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
    QString groupRequested();

private:
    QCustomPlot *pPlot;

public slots:
   void contextMenuRequest(QPoint pos);
   void addRemoveGraph();
}

菜单正确显示并带有正确的条目,当我单击某个操作时 addRemoveGraph 被调用。在调试中,它返回以下消息:

The inferior stopped because it triggered an exception. Stopped in thread 0 by: Exception at 0x5d6c2f9a, code: 0xc0000005: read access violation at: 0x0, flags=0x0.

正在尝试执行

int tmp = selectedSignal->property("graphIdx").toInt();

谁能指出我正确的方向?

提前致谢

您使用 QObject::setProperty,但 QAction 没有名为 "graphIdx" 的 属性。当您尝试从 QAction 读取 "graphIdx" 属性 时,您将始终得到无效的 QVariant.

int tmp = selectedSignal->property("graphIdx").toInt();
// tmp always is 0;

如果您只需要存储一个属性,您可以使用QAction::setData。否则,使用 QObject::setProperty 在任何 QObject 上设置自定义 属性。 QAction 是一个 QObject.

下面是解决问题的方法。

plotHandler.cpp

#include "plothandler.h"

PlotHandler::PlotHandler(QStringList groupNames, int startIdx, QWidget *parent) :
    QWidget(parent), scrolling(false), refreshing(true)
{
    pPlot = new QCustomPlot(this);
    pPlot->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(pPlot, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
}

void PlotHandler::contextMenuRequest(QPoint pos)
{
    int i;
    QMenu *menu = new QMenu(this);
    for(i=0; i<pGroup->getDataLength(); i++)
        {
            QAction *menuEntry;
            menuEntry = new QAction(pPlot->graph(i)->name(), this);
            menuEntry->setData(i);
            menu->addAction(menuEntry);
        }

    connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(addRemoveGraph(QAction*)));    
    menu->popup(pPlot->mapToGlobal(pos));    
}

void PlotHandler::addRemoveGraph(QAction *selectedSignal)
{

    int tmp = selectedSignal->property("graphIdx").toInt();

    if (pPlot->graph(tmp)->visible())
    {
        pPlot->graph(tmp)->setVisible(false);
    }
    else
    {
        pPlot->graph(tmp)->setVisible(true);
    }
    pPlot->replot();
}

plotHandler.h

class PlotHandler : public QWidget
{
    Q_OBJECT
public:
    explicit PlotHandler(QStringList groupNames, int startIdx, QWidget *parent = 0);
    QString groupRequested();

private:
    QCustomPlot *pPlot;

public slots:
   void contextMenuRequest(QPoint pos);
   void addRemoveGraph();
}

感谢大家的帮助。