6

多くのサブメニューを持つ 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;
}

または、signalMapper がコンストラクターで初期化されたデータ メンバーである QSignalMapper も試しました。

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)));
}

2 番目のケースでは、エラーは発生しませんが、スロット関数 playChannel は呼び出されていません。誰かがそれを解決するのを助けることができれば本当に感謝しています.

更新 1:私が見た他の例との唯一の違いは、通常、人々は複数のウィジェットから単一のスロット(異なるボタンなど) に信号を接続していることです。私の場合、複数のサブメニュー (異なる名前) を単一のスロットに接続しています。これは違いを生むべきですか?

更新 2:以下の QSignalMapperのソリューションで提案されている修正後に機能しました。また、 SubMenu を setMapping の引数として使用していたという事実もあり、代わりに MenuAction アイテムを使用する必要がありました。しかし今、私はイベントを複数回発生させています。つまり、選択したサブメニューカテゴリのメインメニューにエントリがある回数だけです。チャネル タイプが英語 (メイン メニュー) で 4 つのエントリ)、HBO、スター映画など (サブ メニュー) で、HBO を選択した場合、イベントは文字列 HBO で 4 回発生します。サブメニューごとに個別のシグナルマッパーを作成すると、うまく機能します。しかし、私は単一のマッパーを使用することを望んでいましたが、ここで間違ったことをしています。回答へのコメントの詳細。

4

1 に答える 1

5

をメニューに追加した後は、スロット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受け入れる必要があります。QStringQAction*

于 2013-01-04T12:47:04.680 に答える