Как передать QString в слот Qt из QMenu через QSignalMapper или иным образом

У меня есть QMenu со многими подменю. Они создаются динамически, то есть меню имен поступают из БД и создаются в цикле. Теперь я хотел запустить тот же слот triggered () или аналогичный при щелчке меню, но мне нужно было передать имя меню QString в слот, чтобы я мог выполнять определенные для меню действия. я пытался этот то есть передача QAction * к инициированному событию и использование setData, но я получаю ошибку времени выполнения.

object :: connect: нет такого сигнала QAction :: triggered (QAction *)

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
QAction *subMenuAct = subMenu->addAction(tr(c_name)); // c_name the menu name
subMenuAct->setData(ch_name);
connect(subMenuAct, SIGNAL(triggered(QAction *)), this, SLOT(playChannel(QAction *))); // playChannel is the slot
}

void <ClassName>::playChannel(QAction *channelAction)
{
QString str = channelAction->data().toString();
qDebug() << "Selected - " << str;
}

Кроме того, я также попытался QSignalMapper, где signalMapper является членом данных, инициализированных в конструкторе

signalMapper = new QSignalMapper(this);

а также

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
QAction *subMenuAct = subMenu->addAction(tr(c_name));

connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
signalMapper->setMapping(subMenu, ch_name);
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString)));
}

Во втором случае я не получаю никакой ошибки, однако функция слота playChannel не вызывается. Был бы очень признателен, если бы кто-то мог помочь решить это.

Обновление 1: Единственное отличие, которое я вижу из других примеров, которые я видел, состоит в том, что обычно люди подключение сигналов от нескольких виджетов к одному слоту (скажем разные кнопки). В моем случае я подключаюсь несколько подменю (с разными именами) в одном слоте. Должно ли это иметь какое-то значение?

Обновление 2: Сработало после исправления, предложенного в решении ниже для QSignalMapper. Также тот факт, что я использовал SubMenu в качестве аргумента для setMapping, где вместо этого должен был использоваться элемент MenuAction. Но теперь я получаю событие несколько раз, то есть столько раз, сколько есть записей в главном меню для выбранной категории подменю. Если тип канала английский (главное меню) с четырьмя записями), HBO, звездные фильмы и т. Д. (Подменю), и я выбираю HBO, то событие запускается четыре раза со строкой HBO. Это работает нормально, если я создаю отдельный преобразователь сигнала для каждого подменю. Но я надеялся, что должен использоваться один картограф, и я делаю что-то здесь неправильно. Еще несколько подробностей в комментариях к ответу.

6

Решение

После добавления QAction в меню, вам нужно только подключиться QMenu в слот. Вы не подключаете каждое действие отдельно к слоту:

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
ch_name = <name from the database for the channel j>;
QAction *subMenuAct = subMenu->addAction(tr(ch_name));
subMenuAct->setData(ch_name);
}

connect(subMenu, SIGNAL(triggered(QAction *)),
this, SLOT(playChannel(QAction *)), Qt::UniqueConnection);

Как я не знаю, как вы, если вы удалите subMenu каждый раз, когда динамическое меню заполняется, Qt::UniqueConnection убедитесь, что слот не будет повторно подключен несколько раз.


Для версии преобразователя сигналов следует подключать действия только к преобразователю в цикле. Подключение от картографа к слоту должно быть выполнено только один раз.

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){
ch_name = <name from the database for the channel j>;
QAction *subMenuAct = subMenu->addAction(tr(ch_name));
connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map()));
signalMapper->setMapping(subMenuAct, ch_name);
}
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString)));

И для этого случая, слот playChannel должен принять QString вместо QAction*,

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]