Сброс QMenu для принятия нового набора QActions

Я хочу сбросить / воссоздать пользовательское контекстное меню. Я использую QMenu и QAction(переменные-члены) для достижения этой цели.

 QMenu* m_menu;
 QAction* m_actionTitle;

У меня слот подключен вот так:

connect(m_ui->actionLoad_Definition_File, &QAction::triggered, m_Item.get(),
        &Item::loadDefinitionFilesFromMenu);

Рабочая часть:

В моем конструкторе я настроил что-то вроде этого:

 Item::Item(QWidget* parent)
 {
     // Connect context menu
     this->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
        this,   SLOT(showContextMenu(const QPoint&)));  
 }


/* virtual */ void Item::showContextMenu(const QPoint& pos)
{
    // Obtain global position
    QPoint globalPos = mapToGlobal(pos);

   // Change the first menu entry to show the range
   m_actionTitle->setText(QString::number(m_from) + " - " +
                       QString::number(m_to));  //Access Violation error

   QAction* action = m_menu->exec(globalPos); 
   if (action != NULL)
   {
      if (action->text() == "something")
   {
        // Remove the item
        m_view->removeItem(this);
   }
   else
   {
        // Display the text
        setText(action->text());
        setColor(action->text());
        setToolTip(action->text());
        m_edit.setText(action->text());
        m_view->arrange();
   }
 }
}

Что я хочу:

Я хочу сбросить m_menu всех его действий и подтолкнуть новые действия в него. Поэтому всякий раз, когда я щелкаю правой кнопкой мыши, должно появляться новое контекстное меню.

Эта проблема:

После создания QToolButton, если я щелкну на нем правой кнопкой мыши, я получу "Ошибка нарушения доступа". Отладка, и m_menu, и m_actionTitle выходят из области видимости или просто уничтожаются. Не уверен, почему это происходит.

Что я сделал до сих пор:

void Item::loadDefinitionFilesFromMenu()
{
    //Clear the vector of existing values
    m_defaults.clear();
    //Clear the menu of actions
    m_menu->clear();

    QString file = QFileDialog::getOpenFileName(nullptr, "Choose a definition file", QString(),
                                            QString("(*.ad)"));

    if (!file.isNull())
    {
        MLParser ml;

        std::map<std::string, std::string> base = ml.readDefinitions(file.toStdString());

        for (auto const& gestureValues : base)
        {
            m_defaults.push_back(gestureValues.first);  // string (key)
        }

        m_menu = new QMenu(this);
        m_actionTitle = new QAction("Note", m_menu);
        m_actionTitle->setEnabled(false);
        m_menu->addAction(m_actionTitle);
        m_menu->addSeparator();

        for (std::vector<std::string>::iterator it = m_defaults.begin();
         it != m_defaults.end();
         ++it)
        {
            m_menu->addAction(QString::fromStdString(*it)); //works ok
        }

        m_menu->addSeparator();
    }
}

Я хотел бы использовать повторно m_menu на протяжении всей моей программы, но я не могу сбросить его и принять новый набор действий. Я что-то здесь упускаю?

РЕДАКТИРОВАТЬ 1:

Удалены QMenu а также QAction в конструкторе. Только внутри loadDefinitionFilesFromMenu,

1 ответ

Решение

Сделать меню общим для всех Item экземпляров.

В заголовке класса Item:

private:
    static QMenu* m_menu;
    static QAction * m_actionTitle;
    static std::vector<std::string> m_defaults;

В классе Item cpp после определений и перед определениями методов:

QMenu* Item::m_menu = 0;
QAction * Item::m_actionTitle = 0;
std::vector<std::string> Item::m_defaults;

Меню создается только один раз, в Item конструктор:

if(m_menu == 0)
{
    m_menu = new QMenu();
    // load defaults here
}

Нет необходимости создавать экземпляр меню снова: удалите эту строку из loadDefinitionFilesFromMenu:

m_menu = new QMenu(this);

О тебе m_actionTitle указатель: не назначать новый QAction чтобы он держал возвращаемое значение addAction метод:

    m_actionTitle = m_menu->addAction("Note");
    m_actionTitle->setEnabled(false);
    m_menu->addSeparator();

Наконец, есть статический метод для удаления (единственного и единственного) экземпляра меню. В заголовочном файле:

static void dismissMenu();

В cpp:

void Item::dismissMenu()
{
  delete m_menu;
}

Вы можете вызвать этот метод перед выходом, после QApplication::exec возвращает:

Item::dismissMenu();
Другие вопросы по тегам