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)
-
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.
-
Hi and welcome to devnet,
Do you have a singleton instance of your state machine ?
-
@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.