What kind of signals can be emitted in GUI applications before event loop starts
-
There are various kind of signals that can be emitted from different classes which we use while creating GUI application. Some of these classes are derived from QWidgets , some are not.
There are some classes like QItemSelectionModel class which are not derived form QWidget. From my experiments it seems currentChanged is called once for QItemSelectionModel (while using QTreeView) when the view is setup initially before any user click/selection happens.Signals like I described above are these guaranteed to be emitted only after event loops starts? For some signals to me they seem obvious that they will only be triggered when user clicks on something so they will be triggered only from event loop because that's where all keyboard/mouse etc events are handled. But for some signals (like currentChangedI described above), it seems it is not that clear. Like are there such scenarios where such signals can be emitted right after the "show()" call even before event loop is started
How can I be sure that a particular kind of signal will only be emitted by Qt classes after event loop starts
-
See https://doc.qt.io/qt-6/signalsandslots.html - signals connected to slots in the same thread and not the connection is not created with Qt::QueuedConnection are directly executed. This is the case for most of the signals from QWidgets.
-
@Christian-Ehrlicher Thanks you for replying. From my understanding of your reply, you are referring to when slot is executed once signal has been emitted. My question was more along the lines when is the signal really emitted in such scenarios. Will it be emitted before event loop in cases that I described above.
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
My question was more along the lines when is the signal really emitted in such scenarios. Will it be emitted before event loop in cases that I described above.
When the connection is not made across different threads, it's a
Qt::DirectConnection
very similar to a regular function call...
The "call" is transferred from the signal "call" to the connected slot.
Theemit
keyword is just there for you (or any other human), to differentiate between Qt Signal calls and plain C++ functions.
emit mySignal()
is the same asmySignal()
and is also treated like that (i.e. like "blank space").So to answer your question:
When is the signal emitted?
- The signal is emitted when called in the implementation of a certainQWidget
/QObject
.
When this happens exactly depends on your actions.And the corresponding slot(s)/function(s) are called immediately (when no multi-threading involved)
-
@Pl45m4 I thought atleast for GUI related classes, their corresponding signals will not be generated before event loop starts. Is this assumption wrong? Though so far I am not able to find any explicit mention of order of signal genration wrt to event loop for such classes (classes derived from QWidget and some other classes like QItemSelectionModel).
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
. Is this assumption wrong
Yes and we already told you why. Signals with directly connected slots don't go through the event loop. Therefore 'DirectConnection'.
-
@Christian-Ehrlicher Okay. Actually I thought that for such classes, signals themselves were emitted only as a result of event processing and hence needed event loop before they can actually be emitted by such Qt classes. It seems you are saying that is wrong assumption.
Is this atleast a valid assumption that signals will not be generated before the "show" call for top level widget or Qt provides no such gurantee and we should not make such assumption?
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
Is this assumption wrong?
Yes, it's wrong, however I guess I know why you thought so:
Most signals are emitted as reaction on a certain EVENT. So e.g.
QPushButton
's::clicked()
signal...
... and as you can tell from the name, Qt Events are not propagated without a running Qt Event Loop.
But this has nothing to do with Qt Signals or how theywork.int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow w; qDebug() << "Nothing to see here"; w.show(); qDebug() << "Now starting Event Loop"; return app.exec(); }
When changing the WindowTitle directly in
MainWindow
c'tor:
(as per implementationwindowTitleChanged
is not related to anyQEvent
)MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { connect(this, &MainWindow::windowTitleChanged, this, [=](const QString &title){ qDebug() << title; }); setWindowTitle("Foo42"); }
The output is:
"Foo42"
Nothing to see here
Now starting Event Loop@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
Is this atleast a valid assumption that signals will not be generated before the "show" call for top level widget or Qt provides no such gurantee and we should not make such assumption?
Also wrong.
As you can see,show()
results in aQShowEvent
... and you can use signals with lambdas for example in the c'tor already... way before the widget is shown...
Actually you don't need to show it at all. You can construct a widget and send signals to theQObject
instance without the widget ever becoming visible.Edit:
Added debug output beforeshow()
call.Edit_2:
All you need is a valid
QApplication
instance (orQCoreApplication
forQObject
s with no GUI involved --> NoQWidget
derived classes)
SeeQTimer
(aQObject
) and its signals, for example :)
Works just fine without drawing anything on screen -
@Pl45m4 Thank you for explaining with example like this.
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
There are some classes like QItemSelectionModel class which are not derived form QWidget. From my experiments it seems currentChanged is called once for QItemSelectionModel (while using QTreeView) when the view is setup initially before any user click/selection happens.
For above example of QItemSelectionModel currentChanged signal. It seems that this signal is emitted initially also before user clicks anywhere.
I will review my code for what would be a reliable point to add connect such that I dont miss the signal but also all other members have been initialized which might be accessed by corresponding slot -
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
I will review my code for what would be a reliable point to add connect such that I dont miss the signal
If you subclass it and write your own model, connect signals in the constructor.
If you just useQItemSelectionModel
connect as soon as possible (when sender and receiver are available and "ready" for whatever you're trying to do next)You could also check the Qt source code to see where and when the signals are fired.
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
For above example of QItemSelectionModel currentChanged signal. It seems that this signal is emitted initially also before user clicks anywhere.
Because it's currentChanged() and not clicked() or whatever. The current index changes as soon as there is data in the view. I don't see what's the problem here tbh.
-
@Christian-Ehrlicher I understand that it is being triggered before any click as part of just initial display. I was just trying to understand what is the point at which this signal is emitted . My initial understanding was that it will be emitted after show() call but after discussion today I am not going to make any such assumption.
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
My initial understanding was that it will be emitted after show() call but after discussion today I am not going to make any such assumption.
What
show()
call in the context ofQItemSelectionModel
are you talking about? :DI was just trying to understand what is the point at which this signal is emitted
As I've said before, go check it!
Here:
There you can see each occurrence of
emit currentChanged()
-
@Pl45m4 said in What kind of signals can be emitted in GUI applications before event loop starts:
What show() call in the context of QItemSelectionModel are you talking about? :
Sorry for missing context.
I am using QStandardItemModel for a tree like model and displaying it using QTreeView. There are some other items also in my window. QItemSelectionItemModel that i was referring to was one that I got from QTreeView. And the show call was referring to show call on the window that contained everything@Pl45m4 said in What kind of signals can be emitted in GUI applications before event loop starts:
As I've said before, go check it!
Yes, I will check the code. But I don't want to rely on something on the basis of current Qt implementation unless it is also mentioned/guaranteed explicitly in the doc because I don't want something to break if Qt version changes by relying on the current implementation
Thank you everyone for your help on this.
-
@abhic said in What kind of signals can be emitted in GUI applications before event loop starts:
I will review my code for what would be a reliable point to add connect such that I dont miss the signal but also all other members have been initialized which might be accessed by corresponding slot
I guess you are overthinking a little bit. Just use signal/slot connections where you need them without thinking about when app.exec() is called. I don't think I ever had a problem with slot not being called because the signal was emitted before the main event loop. (But you are right that you have to make sure that members are already initialized.)
-
@abhic
As @SimonSchroeder says, not sure why it should be an issue. But if it really bothers you, don't forget you could delay calling theconnect()
s/attaching your views to models etc. till the event loop has started by doing them in a function on aQTimer::singleShot(0)
which you set off just before theapp.exec()
.