Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Custom QEvent for QStateMachine : type recognition won't work



  • Hello everyone,
    I have a problem I've been struggling with for a few hours now. I have a QStateMachine controlling a GUI and its screens, and I wanna link this SM to the socket for a TCP/IP communication my software needs.

    Therefore, my aim is to post a custom event (ConnectionEvent) to the state machine (GUIStateMachine) in order to process a custom transition (ConnectionTransition). I followed the example of the documentation (https://doc.qt.io/qtforpython/overviews/statemachine-api.html#events-transitions-and-guards)

    The problem is, once I post the event from my connection-related class, the eventTest method from ConnectionTransition is unable to get the type of my custom event (defined to QEvent.User + 2). It returns PySide2.QtCore.QEvent.Type.None_.

    If you have any advice, would be very appreciated ! Thank you

    Here are my custom types :

    class ConnectionEvent(QEvent):
    
        def __init__(self, connected):
            print("ConnectionEvent")
            super(ConnectionEvent, self).__init__(QEvent.Type(QEvent.User + 2))
            self.setAccepted(connected)
    
    
    class ConnectTransition(QAbstractTransition):
    
        def __init__(self, connected):
            super(ConnectTransition, self).__init__()
            self.state = connected
    
        def eventTest(self, event) -> bool:
            if event.type() != QEvent.Type(QEvent.User + 2):
                print("Unrecognized type")
                print(event.type()) #there I get PySide2.QtCore.QEvent.Type.None_
                return False
            else:
                print("Recognized type")
                return self.state == event.isAccepted()
    
    

    The code defining my transitions in GUIStateMachine:

     t1 = ConnectTransition(True)
     t1.setTargetState(self.states["CONNECTED"])
    self.states["WAITING"].addTransition(t1)
    
    t2 = ConnectTransition(False)
    t2.setTargetState(self.states["CONNECTION"])
    self.states["CONNECTED"].addTransition(t2)
    

    And finally the code posting the event :

    def setConnected(self, value):
            # some code
        
            print("posting event")
            event = sm.ConnectionEvent(value)
            sm.GUIStateMachine.getInstance().postEvent(event)

  • Banned

    Okay let me see if I understand what you are trying to do -- you want to tie your GUI (View) to your Socket (data source / model) directly. If that is correct then you should read up on MVC Methodology as that is not a good way to go.

    Instead you connect to this socket using pure python by creating a stand alone Data Source Class that handles all communication to and from this socket

    Then this Data Source Class is set up to do whatever you need it to do via API Senders and Receivers

    Once that is set up the Router (or Controller) takes over -- routing the messages to and from this Data Source Class

    The GUI (View) in turn is step up similarly with various API Senders and Receivers

    Sometimes all the Router does is act as a pass through function but other times it manipulates the information so that the receiver can process the sent information more efficiently.

    Once this is done your GUI (View) never worries about the Data Source as it has no knowledge of where the data is coming from (outside the Router) and the Data Source (your socket) does not care nor does it know what the the data it is providing is used for or being routed to



  • @Denni-0 said in Custom QEvent for QStateMachine : type recognition won't work:

    View

    Thank you for your answer.
    I see your point : I'll have to implement an intermediary controller class between my socket (pure python) and my QStateMachine. To be fair, I'm still at the step of creating/conceiving the code, and I was planning on doing this next.

    However, the thing that worries me is that I'm not able to retrieve the data I want from my custom QEvent. It's supposed to be working in C++ but I don't know if there is a specificity about Python that I'm missing, concerning "abstract classes method parameters" (here, event from eventTest method which is QEvent) and "inherited classes method arguments" (here, my ConnectionEvent that I post to the SM). It's hard to be clear but I hope you (or someone maybe?) get my point.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Do you have a singleton instance of your state machine ?


  • Banned

    @tomviow what I do and I teach my students to do is create a MUC (Minimal Usable Code) that reflects just the specific thing you are trying to understand -- aka reduce this to its most minimalistic aspect and muck around with that until you get it working how you want it to work. I am going to be guessing you are trying to eat that whole cake all at once.

    This being said in the MUC you would have -- no socket -- just some way to simulate that socket as it will be done in your new MVC Methodology -- which btw the MVC structure helps with this greatly as every piece is autonomous so you can focus in on what you are striving to do. Next I am not sure why you are running this custom QStateMachine and perhaps there is a better way to handle this than the method you are currently attempting to put into place

    Basically K.I.S.S. it -- Keep It Simple and Smart -- says that maybe you might be over thinking this and using something much more complex than necessary -- however I would have to better understand the reasons for why you are attempting to do what you are doing to better gauge if there is a simpler method to employ that does the same or basically the same thing.



  • @SGaist I do have a singleton instance of my state machine.

    @Denni-0 I completely agree with you. I'll work around a controller which will be the intermediary layer between my components.


    Eventually, I found out how to link my socket to my GUI: I just created a "smart boolean" class (QObject), from which I emit signals when the value changes from false to true, or from true to false. With these signals, I can proceed to the transitions and actions I want.


Log in to reply