简体   繁体   English

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

[英]Qt: Context menu / connect with parameters

I have a problem connecting context menu actions in Qt. 我在Qt中连接上下文菜单操作时遇到问题。 I know there are plenty of similar questions around, nevertheless I couldn't find a solution yet. 我知道周围有很多类似的问题,但是我还没有找到解决方案。

I have a series of plots built using QCustomplot. 我有一系列使用QCustomplot构建的图。

What I want to do is to create a context menu when right-clicking on the background of each plot listing all the signal present in the graph. 我想做的是在右键单击列出了图中所有信号的每个图的背景时创建一个上下文菜单。 By clicking an entry of this menu, the corresponding signal should be hidden (if currently visible) or made visible (if hidden). 通过单击此菜单的条目,相应的信号应隐藏(如果当前可见)或使其可见(如果隐藏)。

Now, I've defined a class called PlotHandler of which I paste the relevant parts here below: 现在,我定义了一个名为PlotHandler的类,将其相关部分粘贴在下面:

plotHandler.cpp 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 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();
}

The menu is correctly showed with the right entries and when I click on an action addRemoveGraph is called. 菜单正确显示了正确的条目,当我单击操作addRemoveGraph ,调用addRemoveGraph In debug it gives back the following message: 在调试中,它会返回以下消息:

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. 通过以下方式在线程0中停止:在0x5d6c2f9a处发生异常,代码:0xc0000005:在0x0处发生读取访问冲突,标志= 0x0。

trying to execute 试图执行

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

Could anyone point me towards the right direction? 有人能指出我正确的方向吗?

Thanks in advance 提前致谢

You use QObject::setProperty but QAction doesn't have a property named "graphIdx". 您使用QObject::setPropertyQAction没有名为“ graphIdx”的属性。 When you attempt to read the "graphIdx" property from QAction you will always get an invalid QVariant . 当您尝试从QAction读取“ graphIdx”属性时,您将始终得到一个无效的QVariant

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

You can use QAction::setData if you need to store only one property. 如果只需要存储一个属性,则可以使用QAction::setData Otherwise, use QObject::setProperty to set a custom property on any QObject . 否则,使用QObject::setProperty在任何QObject上设置自定义属性。 QAction is a QObject . QAction是一个QObject

Here below the solution that solved the issue. 在此下方解决问题的解决方案。

plotHandler.cpp 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 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();
}

Thanks everyone for your help. 感谢大家的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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