c++ - How are Qt signals/slots actually coupled to the elements in a .ui file? -
i'm working on qt project , confused signals , slots mechanism. feel have understanding between differences between qobject , user interface form.
a user interface form (described .ui file) fed user interface compiler(uic) , produces associated header file. header file doesn't contain interface information, instead contains implementation details on qobject should formatted. qobject on other hand base class in lot of qt framework built upon. signals , slot systems based on qobject.
when extending qobject class (or derived class), defining object in can produce signals , slots. format object user interface designed in qt designer, create instance of ui class (via ui header generated uic). call setup method on class , feed new qobject you're creating.
this seems make sense.
however, doesn't make sense when start defining signals. qt designer, have option right click , select 'signal'. when select signal (whether mouse click on button or change in progress bar), ends adding qobjects signals section. question is: why , how? how actions in qt designer (a program generates xml uic) getting coupled qobject in qt creator? more specifically, how know qobject add slot to?
this question may unclear, i'll throw example here.
say example want create new interactive display of kind. let's call 'myscreen'. in order create interface, have 3 files: 'myscreen.h', 'myscreen.cpp', , 'myscreen.ui'. 'myscreen.h' responsible declaring qobjects properties , methods signals , slots. 'myscreen.cpp' responsible defining methods, signals, , slots. 'myscreen.ui' repsonible creating user interface layout used format instance of myscreen.
but due had stated saying ui used generating header, why coupled 'myscreen.cpp'? is, can right click on .ui layout, create new signal type, , signal type added myscreen.h , myscreen.cpp. how happen? how coupled? qt operate such there should 3 files (xxx.h, xxx.cpp, xxx.ui) should exist?
so gives context in i'm confused about. there doesn't seem written document (that i've found @ least), thoroughly describes underlying relationship between these items.
tldr - how signal/slot .h , .cpp link elements defined in .ui file?
my question is: why , how? how actions in qt designer (a program generates xml uic) getting coupled qobject in qt creator? more specifically, how know qobject add slot to?
the short answer is: magic.
the real answer is, has nothing actions in designer, @ least not directly. it's not ui-specific thing, it's designer makes use of it. happens this:
first of all, time compile file makes use of q_object
macro, triggers qt's moc
tool run during compilation ("triggers" isn't accurate description: more precisely, when qmake
run generate makefiles, adds build rules run moc
when q_object
detected in header, that's beside point). details bit outside scope of answer long story short generates moc_*.cpp
files you'll see after compilation, contain whole bunch of compiled meta info. important part of generates run-time accessible information various signals , slots have declared. you'll see how that's important here below.
the other important thing qobject
s have a name. name accessible @ runtime. the name give widgets in designer set widget's object name. reason important become clear below.
and final important thing qobject
s have hierarchical structure; when create qobject
can set parent. of widgets on form have form (e.g. qmainwindow
-derived class) parent.
ok, so...
you'll notice in source code qt generates windows have ui->setupui(this)
call in constructor. implementation of function generated qt's uic
tool during compilation, in e.g. ui_mainwindow.h
. function properties set in designer, stored in .ui file, set, including widgets' object names. now, last line of generated setupui()
implementation key:
void setupui(qmainwindow *mainwindow) { ... // object properties, including names, set here. // generated .ui file. example: pushbutton = new qpushbutton(centralwidget); pushbutton->setobjectname(qstring::fromutf8("pushbutton")); pushbutton->setgeometry(qrect(110, 70, 75, 23)); ... // important part signal/slot binding: qmetaobject::connectslotsbyname(mainwindow); }
that function, connectslotsbyname
, magic happens widget signals.
basically function following:
- iterate through declared slot names, can because packed runtime-accessible strings
moc
in meta object info. - when finds slot name matches pattern
on_<objectname>_<signalname>
, recursively searches object hierarchy object name <objectname>, e.g. 1 of named widgets, or whatever other named objects may have created. connects objects signal, <signalname> slot found (it automates callsqobject::connect(...)
).
and that's it.
so means is, nothing special happens in designer when go slot there. all happens designer inserts slot named on_widgetname_signalname, appropriate parameters, header , generates empty function body it. (thuga has added a great explanation of this). enough qmetaobject::connectslotsbyname
find @ run time , set connection.
the implications here convenient:
- you can remove widget's signal handler without doing special in designer. remove slot , definition source file, it's self contained.
- you can add widget signal handlers hand without having go through designer interface, can save tedium sometimes. have create slot in window named e.g.
on_lineedit1_returnpressed()
, voila, works. have careful, hyde reminds in comment: if make mistake here won't compile-time error, run-time warning printed stderr , connection won't created; it's important pay attention console output if make changes here.
the other implication here functionality isn't limited ui components. moc
runs qobject
s, , connectslotsbyname
available. object hierarchy create, if name objects, declare slots appropriate names, can call connectslotsbyname
automatically set connections; happens uic
sticks call @ end of setupui
, because that's convenient place put it. magic isn't ui-specific, , doesn't rely on uic
, on meta info. it's available mechanism. it's pretty neat.
as aside: stuck quick example of qmetaobject::connectslotsbyname
on github.
Comments
Post a Comment