Qt: подключение сигналов и слотов из текста
Как бы я подключил сигнал и слот из 2 объектов, когда имена объектов, сигналы и слоты все указаны в текстовом файле?
Получение правильных имен объектов не является проблемой, так как я могу легко перебрать массив и сравнить имена с местом в файле, но должен быть какой-то способ, которым я могу вернуть сигнал и слот из файла и использовать его в функции подключения, например:
connect(rtnObj1(line),SIGNAL(rtnSignal(line)),rtnObj2(line),SLOT(rtnSlot(line)));
где функции rtn возвращают имя объекта / сигнал / слот, а "строка" - это текущая строка QString из файла.
Единственный известный мне способ - это буквально кодировать каждую комбинацию и сравнивать QStrings с операторами if, но это было бы невероятно утомительно, так как количество комбинаций было бы невероятно высоким.
Примечание. Вот упрощенный пример, демонстрирующий, как существует эта проблема.
Кадр 1: 4 QComboBoxes. Первый и третий содержат имена объектов, второй содержит сигналы, четвертый содержит слоты. Каждый элемент, конечно, является QString в этих списках. Нажатие на кнопку добавляет новую строку в файл, записывая текст, выбранный из каждого поля.
Кадр 2: уже содержит необходимые объекты. Считывая файл, он сопоставляет объекты, определенные в списке, с уже созданными и соединяет их, как описано в файле.
Достаточно легко создать объект на основе данных, которые хранятся в файле, но как создать / извлечь сигнал и слот из файла?
Редактировать: Разве можно подключиться так?
connect(objectA, "", objectB, "");
Потому что я только что узнал, что мой код будет скомпилирован таким образом, однако всякий раз, когда я пытаюсь вставить имена слотов или сигналов, я просто получаю сообщение об ошибке:
QObject:: connect: используйте макрос SIGNAL для привязки Tile::clicked
1 ответ
Ваша проблема легко решается с помощью одного из следующих статических методов QObject::connect():
QMetaObject::Connection QObject::connect(
const QObject *sender, const QMetaMethod &signal,
const QObject *receiver, const QMetaMethod &method,
Qt::ConnectionType type = Qt::AutoConnection)
Прежде всего, вам нужны указатели на объекты отправителя и получателя. Существует несколько способов хранения пула объектов. Я бы предложил сохранить все объекты в QHash:
QHash<QString, QObject *> m_objects; // I use QObject as a generic example
Теперь можно найти указатель на любой объект для эффективного подключения.
Следующим шагом будет получение объектов QMetaMethod для сигнала отправителя и слота получателя из соответствующих объектов QMetaObject. Используйте QObject::metaObject() QMetaObject
экземпляров.
Вот полный код функции, которая соединяет два объекта, используя только строковые параметры:
void dynamicConnect(const QString &senderName, const QString &signalName,
const QString &receiverName, const QString &slotName)
{
QObject *emitter = m_objects.value(senderName);
int index = emitter->metaObject()
->indexOfSignal(QMetaObject::normalizedSignature(qPrintable(signalName)));
if (index == -1) {
qWarning("Wrong signal name!");
return;
}
QMetaMethod signal = emitter->metaObject()->method(index);
QObject *receiver = m_objects.value(receiverName);
index = receiver->metaObject()
->indexOfSlot(QMetaObject::normalizedSignature(qPrintable(slotName)));
if (index == -1) {
qWarning("Wrong slot name!");
return;
}
QMetaMethod slot = receiver->metaObject()->method(index);
QObject::connect(emitter, signal, receiver, slot);
}