2016-02-25 2 views
0

Используя Qt5, скажем, у меня есть элемент управления, реализующий его собственное контекстное меню. И предположим, что при некоторых условиях я хочу добавить некоторые элементы в стандартное контекстное меню. Итак, чтобы сделать это, я создаю временный QMenu, добавлю некоторые вещи к нему и добавлю стандартное меню. Что-то вроде:Qt & Prepending один QMenu другому QMenu

// MyControl is derived from QPlainTextEdit 
void MyControl::showContextMenu(const QPoint& pos) 
{ 
    // This is QPlainTextEdit::createStandardContextMenu() 
    QMenu* contextMenu = createStandardContextMenu(); 

    if (someCondition) 
    { 
     QMenu* tempMenu = new QMenu(this); 
     /* add several actions to tempMenu */ 

     tempMenu->addSeperator(); 

     for (auto a : contextMenu->actions) 
     { 
      tempMenu->addAction(a); 
     } 

     // Feel like I should delete the original QMenu here but doing this 
     // will delete the QActions it created 
     // delete contextMenu; 
     contextMenu = tempMenu; 
    } 

    contextMenu->exec(mapToGlobal(pos)); 
    delete contextMenu; 
} 

Вопрос в том, не является ли это источником утечки памяти? И если да, то каков правильный способ этого? Я не могу delete contextMenu, прежде чем я сделаю contextMenu = newMenu;, потому что это, очевидно, удаляет действия, которые я хочу.

EDIT:

В конце концов, что я хочу сделать, это использовать createStandardContextMenu() который возвращает выделенную QMenu, а затем добавить некоторые QActions к верхней меню, и убедитесь, что утечки ничего.

+0

Кажется, что newMenu и tempMenu одинаковы? Но тогда код неверен. Да, tempMenu утечки там, если не исправлены. Теперь похоже, что contextMenu также протекает. Не знаю, зачем вы это делаете. – AlexanderVX

+0

Да, они были одинаковыми. Извините, я исправил это. – Addy

+1

@Addy, чтобы избежать утечки памяти, вы можете использовать ['QSharedPointer'] (https://doc.qt.io/qt-5/qsharedpointer.html#operator-eq) вместо обычного указателя –

ответ

-1

Контекстного меню должно быть модальным, поэтому не использовать динамическое выделение, и передать «этот», чтобы застройщик, и меню построить в зависимости от прошедшего контекста

(condition) 
{ 
    context.add(...); 
} 

CustomMenu menu(this,context); 
menu.exec(mapToGlobal(point)); 

нет повторений, чтобы добавить комментарий, так

QMenu* tempMenu = new QMenu(this); 

Нет, это не утечка, поскольку вы передаете указатель родительского объекта.

+0

Я не верю, что этот ответ предлагает мне решение о том, как условно добавлять элементы к уже существующему 'QMenu' без утечек. Кроме того, 'createStandardContextMenu()' возвращает динамически выделенный 'QMenu', у меня нет выбора, кроме как его использовать. – Addy

+0

передать контекст createStandardContextMenu(), добавить конструктор в CustomMenu, обрабатывать данные, иначе переименовать CustomMenu в DummyMenu, потому что он ничего не делает. – jonezq

+0

'createStandardContextMenu' - это функция Qt, которая может принимать только QPoint. – Addy

1

QWidget::addAction(QAction*) не принимает на себя ответственность за действие. Удаление contextMenu приведет к удалению действий, зависит от того, как реализована реализация createStandardContextMenu (например, QMenu::addAction(QString) принимает на себя ответственность за созданное им действие).

Так действия, которые принадлежат к исходному меню должны быть повторно основателями:

for (auto a : contextMenu->actions) 
    { 
     tempMenu->addAction(a); 
     if (a->parent() == contextMenu){ 
      a->setParent(tempMenu); 
     } 
    } 
delete contextMenu; 
contextMenu = tempMenu; 
1

Использование insertAction на QMenu для вставки пользовательских действий до первого стандартного действия, например:

QMenu* contextMenu = createStandardContextMenu(); 
QAction* first = contextMenu->actions().at(0); 
QAction* customAction = /* Create some custom action */ 
contextMenu->insertAction(first, customAction); 

EDIT: вы можете использовать insertSeparator, чтобы отделить свои пользовательские действия от первого стандартного действия.

Смежные вопросы