在我的菜单中,我正在为菜单操作设置数据。如何在插槽中提取这些数据?或者更好的是,除了连接插槽,我还可以连接能够提取操作数据的成员函数(如在第一个连接中)吗?操作数据旨在标识每个操作。作为侧节点,我不确定我是否可以仅在一个openNote
-action 上使用多个菜单操作条目。
void Traymenu::createMainContextMenu() {
QAction *actionNewNote = m_mainContextMenu.addAction("Neue Notiz");
actionNewNote->setIcon(QIcon("C:\new.ico"));
actionNewNote->setIconVisibleInMenu(true);
QObject::connect(actionNewNote,&QAction::triggered,this,&Traymenu::newNote);
QString menuEntryName;
QAction *openNote;
QVariant noteID;
for (int i = 0; i<m_noteList.count(); i++) {
std::string noteTitle = m_noteList[i].data()->getTitle();
menuEntryName = QString::fromStdString(noteTitle);
openNote = m_mainContextMenu.addAction(menuEntryName);
connect(openNote,SIGNAL(triggered()),this,SLOT(s_showNote()));
noteID.setValue(m_noteList[i].data()->getID());
openNote->setData(noteID);
}
m_mainIcon.setContextMenu(&m_mainContextMenu);
}
和插槽:
void Traymenu::s_showNote() {
QObject* obj = sender();
//int noteID = data.toInt();
//Search all notes in noteList for that ID and show it
}
使用 QObject::sender()
可以使用QObject::sender()
获取信号的发送方,然后使用 qobject_cast
将发送方指针转换为正确的类型。
void Traymenu::s_showNote()
{
QAction* act = qobject_cast<QAction *>(sender());
if (act != 0)
{
QVariant data = act->data();
int noteID = data.toInt();
showNote(noteID); // isolate showNote logic from "get my ID" stuff
}
}
void Traymenu::showNote(int noteID)
{
// Do the real work here, now that you have the ID ...
}
正如Qt文档所警告的那样,"这个函数违反了面向对象的模块化原则。 不过,这仍然是一种相当安全和标准的做法——只是有一些缺点。特别要注意的是,你承诺拥有一个 s_showNote
方法,该方法仅在作为槽访问时才有效(否则 sender 为 0)。
使用 QSignalMapper
或者,可以使用 QSignalMapper
类返回指向项的指针,或将唯一标识符(int 或 QString)与每个项相关联。
像这样:
void Traymenu::createMainContextMenu()
{
signalMapper = new QSignalMapper(this); // (or initialize elsewhere)
// ... (create your newNote here same as before) ...
QString menuEntryName;
QAction *openNote;
int noteID;
for (int i = 0; i<m_noteList.count(); i++) {
std::string noteTitle = m_noteList[i].data()->getTitle();
menuEntryName = QString::fromStdString(noteTitle);
openNote = m_mainContextMenu.addAction(menuEntryName);
noteID = m_noteList[i].data()->getID();
openNote->setData(QVariant(noteID)); // (if you still need data in the QActions)
signalMapper->setMapping(openNote, noteID);
}
connect(signalMapper, SIGNAL(mapped(int)),
this, SLOT(showNote(int)));
m_mainIcon.setContextMenu(&m_mainContextMenu);
}
void Traymenu::showNote(int noteID) {
// Now you have the ID ...
}
这种模式的好处是将所有丑陋的"等等,我如何获取我的标识符?"的东西隔离在一个地方,而不是让初始化代码和插槽函数都有用于关联操作和 ID 的代码。
我会这样写:
void Traymenu::s_showNote() {
QObject* obj = sender();
QAction *action = qobject_cast<QAction *>(obj);
int id = action->data().toInt();
for (int i = 0; i < m_noteList.count(); i++) {
if (m_noteList[i].data()->getID() == id) {
[..]
}
}
}