Может ли Qt-сигналы вернуть значение?

Boost.Signals позволяет использовать различные страtagsи использования возвращаемых значений слотов для формирования возвращаемого значения сигнала. Например, добавив их, сформировав из них vector или вернув последний.

Общая мудрость (выраженная в документации Qt [EDIT: а также некоторые ответы на этот вопрос ] ) заключается в том, что с Qt-сигналами такой возможности не существует.

Однако, когда я запускаю moc в следующем определении classа:

 class Object : public QObject { Q_OBJECT public: explicit Object( QObject * parent=0 ) : QObject( parent ) {} public Q_SLOTS: void voidSlot(); int intSlot(); Q_SIGNALS: void voidSignal(); int intSignal(); }; 

Мало того, что moc не жалуется на сигнал с невообразимым возвращаемым типом, он, как представляется, активно реализует его таким образом, чтобы разрешить возвращаемое значение:

 // SIGNAL 1 int Object::intSignal() { int _t0; void *_a[] = { const_cast(reinterpret_cast(&_t0)) }; QMetaObject::activate(this, &staticMetaObject, 1, _a); return _t0; } 

Итак: согласно документам, эта вещь невозможна. Тогда что делает moc здесь?

Слоты могут иметь возвращаемые значения , поэтому можем ли мы подключить слот с возвращаемым значением к сигналу с возвратным значением сейчас? Может быть, это возможно, в конце концов? Если это так, полезно ли это?

EDIT: Я не прошу обходных решений, поэтому, пожалуйста, не предоставляйте никаких.

EDIT: Очевидно, что это не полезно в режиме Qt::QueuedConnection (ни API-интерфейс QPrintPreviewWidget , ни все же он существует и полезен). Но как насчет Qt::DirectConnection и Qt::BlockingQueuedConnection (или Qt::AutoConnection , когда он разрешает Qt::DirectConnection ).

ОК. Итак, я немного поработал. Кажется, это возможно. Я смог испустить сигнал и получить значение из слота, к которому был подключен сигнал. Но проблема заключалась в том, что он возвращал только последнее возвращаемое значение из нескольких подключенных слотов:

Вот простое определение classа ( main.cpp ):

 #include  #include  class TestClass : public QObject { Q_OBJECT public: TestClass(); Q_SIGNALS: QString testSignal(); public Q_SLOTS: QString testSlot1() { return QLatin1String("testSlot1"); } QString testSlot2() { return QLatin1String("testSlot2"); } }; TestClass::TestClass() { connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1())); connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2())); QString a = emit testSignal(); qDebug() << a; } int main() { TestClass a; } #include "main.moc" 

При основных запусках он создает один из тестовых classов. Конструктор соединяет два слота с сигналом testSignal, а затем испускает сигнал. Он фиксирует возвращаемое значение из выведенного слота (ов).

К сожалению, вы получите только последнее возвращаемое значение. Если вы оцениваете приведенный выше код, вы получите: «testSlot2», последнее возвращаемое значение из подключенных слотов сигнала.

Вот почему. Qt Signals - это синтаксический сахаризованный интерфейс для шаблона сигнализации. Слоты являются получателями сигнала. В прямом соединении с сигналом-слотом вы можете думать о нем аналогично (псевдокоду):

 foreach slot in connectedSlotsForSignal(signal): value = invoke slot with parameters from signal return value 

Очевидно, что moc делает немного больше, чтобы помочь в этом процессе (рудиментарная проверка типов и т. Д.), Но это помогает нарисовать картину.

Нет, они не могут.

Boost::signals сильно отличаются от Boost::signals в Qt. Первые предоставляют расширенный механизм обратного вызова, тогда как последний реализует сигнальную идиому. В контексте многопоточности сигналы Qt (cross-threaded) зависят от очередей сообщений, поэтому они называются асинхронно на некотором (неизвестном для streamа эмиттера) момент времени.

Функция Qt qt_metacall возвращает целочисленный код состояния. Из-за этого я считаю, что это делает невозможным фактическое возвращаемое значение (если только вы не обманываете себя с помощью системы метаобъектов и файлов moc после предварительной компиляции).

Однако у вас есть обычные функциональные параметры. Должна быть возможность изменить свой код таким образом, чтобы использовать параметры «out», которые действуют как ваш «возврат».

 void ClassObj::method(return_type * return_) { ... if(return_) *return_ = ...; } // somewhere else in the code... return_type ret; emit this->method(&ret); 

Вы можете получить возвращаемое значение из Qt signal с помощью следующего кода:

В моем примере показано, как использовать Qt signal для чтения текста QLineEdit . Я просто расширяю то, что предложил @jordan:

Должна быть возможность изменить свой код таким образом, чтобы использовать параметры «out», которые действуют как ваш «возврат».

 #include  #include  class SignalsRet : public QObject { Q_OBJECT public: SignalsRet() { connect(this, SIGNAL(Get(QString*)), SLOT(GetCurrentThread(QString*)), Qt::DirectConnection); connect(this, SIGNAL(GetFromAnotherThread(QString*)), SLOT(ReadObject(QString*)), Qt::BlockingQueuedConnection); edit.setText("This is a test"); } public slots: QString call() { QString text; emit Get(&text); return text; } signals: void Get(QString *value); void GetFromAnotherThread(QString *value); private slots: void GetCurrentThread(QString *value) { QThread *thread = QThread::currentThread(); QThread *mainthread = this->thread(); if(thread == mainthread) //Signal called from the same thread that SignalsRet class was living ReadObject(value); else //Signal called from another thread emit GetFromAnotherThread(value); } void ReadObject(QString *value) { QString text = edit.text(); *value = text; } private: QLineEdit edit; }; 

Чтобы использовать это, просто запросите call(); ,

Вы можете попытаться решить эту проблему следующим образом:

  1. Все подключенные слоты должны сохранять свои результаты в некотором месте (контейнере), доступном из объекта сигнализации
  2. Последний подключенный слот должен каким-то образом (выбрать максимальное или последнее значение) обрабатывать собранные значения и выставлять только один
  3. Испускающий объект может попытаться получить доступ к этому результату

Как идея.

  • Неблокирующий рабочий - копия файла прерывания
  • Как установить значок панели задач приложения в Windows 7
  • Как использовать Qt, чтобы сделать метод QObject streamобезопасным?
  • Когда следует использовать Q_OBJECT?
  • Как безопасно уничтожить QThread?
  • Qt - обновление основного windows со вторым streamом
  • Масштабирование изображения (KeepAspectRatioByExpanding) через OpenGL
  • Как создать Qt 4.8 / 5.2 статически в VS2012, используя статическую среду выполнения MSVC, с поддержкой Windows XP?
  • Получить индекс QPushButton на 2D-массиве QPushButton
  • Рисование прямоугольного наложения на QWidget при щелчке
  • Как сохранить пропорции виджетов в Qt?
  • Давайте будем гением компьютера.