У меня есть 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. Это работает нормально, если я создаю отдельный преобразователь сигнала для каждого подменю. Но я надеялся, что должен использоваться один картограф, и я делаю что-то здесь неправильно. Еще несколько подробностей в комментариях к ответу.
После добавления 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*
,
Других решений пока нет …