Menu

how to expose enums?

Help
2013-11-26
2013-11-30
  • iestyn bleasdale-shepherd

    Hi!

    I love PythonQt, it has helped me create the most amazing rapid prototyping framework (Python + Qt + OpenGL = awesome!). It really has changed my life for the better recently :)

    I've been able to figure out most things on my own, but I'm currently stuck on enums... I can't figure out how to expose my enums to Python!

    How do you expose an enum?

    Things I have tried:
    - copying the syntax of the built-in Qt classes (using the Q_ENUMS macro) ...no dice, Python doesn't see my classname in the global namespace (nor under Qt nor under PythonQt - I checked by spewing 'globals()' and it's not there)
    - moving my class into the Qt namespace... nope, still Python can't see it
    - making my class a subclass of a built-time Qt class that already has an exposed enum... nope!
    - note that I can instantiate my classes in Python fine (I have registered them with PythonQt::self()->registerClass) and can call their SLOT functions... everything works perfectly, except the enums! It's odd that my classes don't show up in the global namespace, despite Python being able to handle instances of these classes just fine...

    Thanks!

    iestyn

     
  • Florian Link

    Florian Link - 2013-11-26

    Enums are detected via QMetaObject, which means that PythonQt will know about all enums that are registered via Q_ENUMS. Make sure that the moc runs on you class (don't forget the Q_OBJECT macro).

    The enums appear on the class itself, not in the global namespace. The Qt namespace/enums are special and can not be extended in the current implementation.

    If you class is called MyClass and has an enum MyEnum with values MyValue1 and MyValue2, you should be able to access the enum value via:

    MyClass.MyValue1
    MyClass.MyValue2

    or

    instanceOfMyClass.MyValue1
    instanceOfMyClass.MyValue2

    The enum class itself is not exposed, as far as I remember (or is may be exposed on the class as MyClass.MyEnum, but I can't remember right now).

    The enums are derived from int and will be treated as ints, except for overload decisions when calling a slot with int and enum overloads.

     
  • Florian Link

    Florian Link - 2013-11-26

    By the way, is your framework available anywhere? It would be interesting to have a look at it.

     
  • iestyn bleasdale-shepherd

    Thanks very much for the response! PythonQt has already given me plenty of joy, so I really appreciate your taking the time to help me out, in addition to already providing this fantastic framework for free! :)

    So, the problem I am having here is that 'MyClass' (in my case 'QRealtimeEvent') does not appear to be visible in Python, so I can't get at the contained enum (or anything else at the class level).

    Here is my object declaration, in my MOC'd header file:

    class QRealtimeEvent : public QObject
    {
        Q_OBJECT
        Q_ENUMS(Type)
    public:
        enum Type
        {
            GamepadButtonPress   = QEvent::User + 0,
            GamepadButtonRelease = QEvent::User + 1
        };
        QRealtimeEvent( Type type ) : t( type ) {}
    public Q_SLOTS:
        QEvent::Type type() const { return QEvent::Type( t ); }
    public:
        Type t;
    };
    

    Here is my Python code:

    print QRealtimeEvent
    print QRealtimeEvent.Type
    print QRealtimeEvent.GamepadButtonPress
    

    Here is the error message (it occurs the same on any/all of the above lines, if active):

    NameError: name 'QRealtimeEvent' is not defined
    

    As I say, my Python code is successfully accessing instances of several other classes from my C++ header - but in no case do I actually access the 'class object'. If I try to do so, I get the same error (so I guess this post is mis-named; this really isn't about enums at all!).

    These other objects are instantiated by C++ code and I am accessing these instances in Python by exposing them as global variables with the PythonQtObjectPtr::addObject method, so I never have to access their respective class objects. I simply access their instances, calling methods, accessing properties and so on. Here is how I registered my classes with PythonQt:

    PythonQt::self()->registerClass( &RealtimeApp::staticMetaObject );
    PythonQt::self()->registerClass( &Window::staticMetaObject );
    PythonQt::self()->registerClass( &GLWidget::staticMetaObject );
    PythonQt::self()->registerClass( &ScriptInstance::staticMetaObject );
    PythonQt::self()->registerClass( &QRealtimeEvent::staticMetaObject );
    PythonQt::self()->registerClass( &QGamepadEvent::staticMetaObject );
    

    Any ideas what I might have missed? Thanks again!

    [ Btw, I'll take a look at the licenses of the various modules I'm using and see if I can put my project on SourceForge... it would be good to figure out distribution at some point! But in the short term, if you're just interested in taking a look at how I'm using PythonQt, I can also zip up my source tree/LIBs/DLLs and send it to you personally ]

     
  • Florian Link

    Florian Link - 2013-11-30

    You can pass an additional module name when calling registerClass(). PythonQt will create that module and put the class object into that module (as sub module of PythonQt).

    By default, your class will be located in PythonQt.private, so you should see it at:

    from PythonQt import private

    print private.QRealtimeEvent

    Alternatively you can use the second parameter of registerClass() and pass a package name, e.g. "MyApp".

    Then you can access your class via

    from PythonQt import MyApp

    print MyApp.QRealtimeEvent

     
  • iestyn bleasdale-shepherd

    Aha, brilliant - this works exactly as advertised! I can see my classes and their enums now. Thankyou so much :)

    I apologise if this was already covered in the documentation, I just didn't see it.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.