У меня есть пользовательская структура, экземпляры которой связаны с QAction экземпляров. Я хотел бы, чтобы слот выполнялся с соответствующим экземпляром моей структуры при выполнении действия.
Мне удалось заставить это работать, используя QSignalMapper по подклассам QObject инкапсулировать экземпляр моей структуры. Однако все значения моей структуры неверны, когда они поступают в слот — они кажутся неинициализированными.
Если я отправлю примитивный тип, такой как ИНТ вместо структуры, или даже что-то вроде QAction, все работает ок.
Можно ли сделать то, что я пытаюсь сделать? Если так, что я пропускаю?
Спасибо,
Алан
Изменить: Добавлен пример кода
Вот как я подключаю QSignalMapper. Примечание: STRUCT_WRAPPER является производным от QObject.
/* Connect signal mapper to selected slot */
connect(signalMapper, SIGNAL(mapped(QObject *)), this,
SLOT(on_selected(QObject *)));
/* For all structures */
for(x = 0; x < structureCount; x++)
{
/* Create action */
QAction * action = ui.menu->addAction("Name");
/* Get current structure */
MY_STRUCT myStruct = structList[x];
/* Create wrapper */
STRUCT_WRAPPER * structWrapper = new STRUCT_WRAPPER(this, myStruct);
/* Map struct to action */
signalMapper->setMapping(action, structWrapper);
}
И вот слот, где я получаю неинициализированные значения:
void on_selected(QObject * object)
{
/* Get structure wrapper */
STRUCT_WRAPPER * structWrapper = (STRUCT_WRAPPER *)object;
/* Get structure */
MY_STRUCT myStruct = structWrapper->GetStruct();
/* ID is always uninitialised */
int id = myStruct.ID;
}
Вместо использования QSignalMapper, который вынуждает вас создавать собственный STRUCT_WRAPPER, попробуйте использовать QAction :: УстановитьДанные метод, который принимает любой QVariant
Также не забудьте зарегистрировать вашу структуру в системе метатипов Qt, используя Q_DECLARE_METATYPE
Затем просто подключите все ваши QAction к одному и тому же слоту и используйте http://qt-project.org/doc/qt-4.8/qobject.html#sender чтобы получить QAction, который испустил сигнал:
void MyWindow::on_selected() {
QAction *action = qobject_cast<QAction *>(sender());
Q_ASSERT(action);
MY_STRUCT myStruct = action->data().value<MY_STRUCT>();
}
Кроме того, избегайте использования бросков в стиле C. Если вы не используете QObjects, используйте вместо этого qobject_cast (он опирается на информацию MetaObject и не нуждается в дополнительной функции RTTI):
STRUCT_WRAPPER * structWrapper = qobject_cast<STRUCT_WRAPPER *>(object;)
почему вы не просто используете пользовательский класс для работы? производя его от qobject и с некоторыми слотами / сигналами, он будет делать то, что вы хотите.
я понятия не имею, почему ваша структура получает недопустимые значения, поэтому было бы хорошо, чтобы получить код в качестве примера 🙂
су долго зайборг
void on_selected(QObject * structWrapper)
{
/* Get structure */
MY_STRUCT myStruct = structWrapper->GetStruct();
/* ID is always uninitialised */
int id = myStruct.ID;
}
я думаю, что проблема в том, что QObject * не знает, что должен делать GetStruct () … он должен выдавать ошибку при компиляции oO
может быть попробовать
MY_STRUCT myStruct = <dynamic_cast>(STRUCT_WRAPPER*)->GetStruct();
Спасибо за все полезные ссылки.
В конце концов, я понял, что единственной информацией, которую мне нужно было отобразить, был индекс в массиве структур. Сделав массив глобальным, я смог получить к нему доступ из своего слота, используя переданный индекс.
Я не хотел использовать Q_DECLARE_METATYPE в этом случае, потому что я бы предпочел не иметь зависимости QT от моей библиотеки API. В противном случае предложение восьмерика тоже сработало бы.