5 ms·
I've been fighting c++ recently with qt. Something as simple as iterating over widgets on a page isn't possible without casting to every kind of child widget an
by devwastaken 8y ago
I've been fighting c++ recently with qt. Something as simple as iterating over widgets on a page isn't possible without casting to every kind of child widget and checking it. I get why, it's because if static typing, but I wonder if it'd ever be possible to 'type hint' and make it possible to implicitly downcast. For example qt will let you iterate over QWidget * type, but you gotta cast it to the real type of QLineEdit and such to get the widgets values.
Of course the 'c++' way is doing event listeners and recording data when it's changed.
- llukas 8y agoThere is another way: https://sourcemaking.com/design_patterns/visitor https://sourcemaking.com/design_patterns/visitor
- ahartmetz 8y agoA tangent on ways to do it with Qt, because I don't like seeing Qt presented in a bad light due to unfamiliarity. With Qt you can chain QObject::metaType(), QMetaObject::className(), int QMetaType::type(const char *typeName) to get an integer you can use to switch () on type. It is, I believe, possible but obscure on purpose because it is not meant to be used willy-nilly. You can also access Q_PROPERTYs by name using QObject::property(), and Qt's own classes have the same names for the same properties where it makes sense - such as text() in QLineEdit and QAbstractSpinBox etc. It depends on your requirements if using that approach actually makes sense. I haven't seen it used yet... If you want to serialize GUI state, a more intrusive design where, say, you keep some helper data on the side to allow "dumber" code in the actual de/serialization might be better. Or just wire up the widgets to a model (QAbstractItemModel and / or QObjects exposing Q_PROPERTYs - that's how you do it with QML if you do it right) and use the model as the main source of truth and, of course, for serialization. The "high level debugger for Qt" GammaRay is a nice showcase of what you can do with Qt's introspection capabilities. Qt had ~3 extension points added for GammaRay to observe object lifecycles, most everything else is based on pre-existing functionality.
- devwastaken 8y agoHow do you use QMetaType::type without having to do the same as I said, which is explicit casting? afaik there's no way to get the 'real' type that you can shove into qobject_cast or dynamic_cast to turn QWidget into a QLineEdit. The only way is to write in the type and try each cast, you can't store types in some map and go 'get' the type at runtime to have casted.
- ahartmetz 8y agoYes you will have to cast eventually, and no you won't have to try casts.
- devwastaken 8y agoYou'd have to point out specific code for that. Afaik that's not possible in c++ at runtime. Compiler has to know the type even in dynamic casting.
- ahartmetz 8y agoI actually think I've given you all the info you need. You switch on type ID and cast to the then known type.
- gumby 8y agoThat is the point of virtual base classes. Not using them in this situation is simply fetishism on the part of your library.
- jcelerier 8y agocurious, I've written hundred of thousands LOC of Qt code and never had I encountered a case where I would need to iterate over all child widgets, it's generally only a well known subset. what do you need to do ?
- devwastaken 8y agoIts a config menu that's in part generated from a config file, and part pre-made in a .UI file. I don't control the config, and it can add or remove options. I premake widgets for known options, but still generate widgets for any options that aren't covered by pre made ones. To keep things far simpler, the .UI file is meant to be the one that defines the premade widgets, and have properties on them. How UI seems to be usually done in QT is uic generates a header and the object names become members that can be used directly. Then all those members are used directly, and become hard coded. In this circumstance though, I don't want to hard code in every widget, that way if new options are added, they can be updated in the .ui file and not require recompilation and more hard coding of widgets. Problem is, you can't do qwidget->find, get the head widget, then get a list of the widgets actual child type. What I've read and have asked others on, you gotta qobject_cast until it sticks. C++ can't get types at runtime and then cast them, it has to know what to do at compile time. Hence having to write out every type and cast it.