signals from worker object never reach controller object?
-
i have an
AudioWorker
(optionally on a background thread), and i connected it to theAudioTest
controller running on the main thread, like this:connect( this, &AudioWorker::updateControl, audioTestP, &AudioTest::updateControl, Qt::QueuedConnection);
yet if i attempt this from the worker object:
emit updateControl(kControl_VOLUME_SLIDER, logVolume);
the
AudioTest
slot in the controller object never gets called. which means the button names in the UI never updateHere is a minimum compileable example:
http://kjams.com/downloads/audiotest.zipnote in the example, i commented out this line:
m_audioWorkerP->moveToThread(&m_workerThread);
to see if it would help, and strangely the signals STILL don't reach the slots?
what am i missing here?The top button toggles between push and pull, and the bottom button toggles pause/resume. they work, but the text never gets updated due to the signals from the worker object never reaching the slots in the controller object
-
@davecotter Hello, I have took a quick look to your code and I think I found what the problem is.
Have you check the connect statement did work?
I don't think so, because your signal is using an enum as parameter (ControlType).
You have to register first this enum, so Qt can serialized the data. If you don't do that, you cannot useQueuedConnection
:qRegisterMetaType<ControlType>("ControlType");
After that, it will work as expected.
==> take a look at documentation: https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1
-
Hi, you'll get the button texts updated if you do a vanilla connect() instead of a Qt::QueuedConnection on line 345 in audiooutput.cpp, i.e. in AudioWorkers constructor:
AudioWorker::AudioWorker(AudioTest *audioTestP) : m_pushTimer(new QTimer(this)) { m_curVolume = LogToLinVol(50); connect( this, &AudioWorker::updateControl, audioTestP, &AudioTest::updateControl); // Qt::QueuedConnection); }
If you comment out the Qt::QueuedConnection the connect will work.
-
@davecotter Hello, I have took a quick look to your code and I think I found what the problem is.
Have you check the connect statement did work?
I don't think so, because your signal is using an enum as parameter (ControlType).
You have to register first this enum, so Qt can serialized the data. If you don't do that, you cannot useQueuedConnection
:qRegisterMetaType<ControlType>("ControlType");
After that, it will work as expected.
==> take a look at documentation: https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1
-
@hskoglund i probably should have mentioned i had already attempted a "plain vanilla" connect, to no avail. it does seem more correct to have it be queued, since it may be on another thread anyway.
@KroMignon yes, the return value of the
connect()
call does read astrue
when cast tobool
. Separately, i have tried to callqRegisterMetaType()
, but that doesn't cause the signals to make it to the slots.Have either of you (or anyone?) tried actually running the code provided? It's quite simple and will compile and run quite easily.
-dave
-
@davecotter said in signals from worker object never reach controller object?:
Have either of you (or anyone?) tried actually running the code provided? It's quite simple and will compile and run quite easily.
Yes, I did it in the way I say it to you:
int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setApplicationName("Audio Output Test"); qRegisterMetaType<ControlType>("ControlType"); AudioTest audio; audio.show(); return app.exec(); }
Without
qRegisterMetaType<>()
:
And with
qRegisterMetaType<>()
:
-
@KroMignon
I did test it and I got the reason/error printed in my outputjust as @KroMignon said, you need to register the enum with the meta system
what I did:
AudioWorker::AudioWorker(AudioTest *audioTestP) : m_pushTimer(new QTimer(this)) { qRegisterMetaType<ControlType>("ControlType"); m_curVolume = LogToLinVol(50); connect( this, &AudioWorker::updateControl, audioTestP, &AudioTest::updateControl, Qt::QueuedConnection); }
and more important:
typedef enum { kControl_PUSH_PULL_BUTTON, kControl_SUSPEND_RESUME_BUTTON, kControl_OUT_DEVICE_MENU, kControl_VOLUME_SLIDER } ControlType; //---------------------------------------------------------------------------------- class AudioTest; class AudioWorker : public QObject { Q_OBJECT Q_ENUM(ControlType)////<-------
The Q_ENUM macro is vital as wellsee posts below -
-
You're right juts tested it without it. I though it was vital and I always write it 😇
But it seem to work here just as fine without it
-
@J-Hilk said in signals from worker object never reach controller object?:
I though it was vital and I always write it
For a global enum, you should not. A global enum you declare with
Q_DECLARE_METATYPE
and register as @KroMignon mentioned. If it's aliased the aliased name is required, if not the usual call without a string argument is appropriate. -
my apologies for the extra goose-chasing.
the suggestion by @KroMignon was in fact correct, i had mistyped it in a way that did compile but was incorrect, so my conclusion was wrong.
thanks everyone for your great help!!!