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

[PySide2] How come this code is not getting executed in a line by line order?



  • Hello,

    I am using a code to connect my Raspberry Pi to the WiFi and it works.
    But changing the text on the labels, that doesn't work in t he correct order.

    For example, this is the code to view a list of WiFi networks and add them to a combobox:

            self.label_connectionStatus2.setText("Refreshing...")
            
            out = subprocess.Popen('sudo rfkill unblock 0', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            out = subprocess.Popen('ifconfig wlan0 up', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            out = subprocess.Popen('sudo /sbin/iwlist wlan0 scan | grep ESSID', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            stdout = out.communicate()[0]
            stdout = stdout.decode("utf-8")
            wifilist = stdout.split('"')[1::2]
            self.comboBox_WiFiName.clear()
            self.comboBox_WiFiName.addItems(wifilist)
            
    

    The code works but the part where I use 'setText("Refreshing...")' on the label, that part is executed at the end, it shows up after the code below it has been executed.

    I even tried adding a 'time.sleep(10)' after the 'self.label_connectionStatus2.setText("Refreshing...")' line, but nothing changed.

    Why is this happening?



  • Hey

    Some GUI's are only drawn after code blocks are executed or if you call a function for drawing.
    In Qt you could try running this to signal Qt to process pending events, or emit a signal for change.

    self.label_connectionStatus2.setText("Refreshing...")
    app.processEvents()
    

    https://doc.qt.io/qt-5/qcoreapplication.html#processEvents



  • Hey

    Some GUI's are only drawn after code blocks are executed or if you call a function for drawing.
    In Qt you could try running this to signal Qt to process pending events, or emit a signal for change.

    self.label_connectionStatus2.setText("Refreshing...")
    app.processEvents()
    

    https://doc.qt.io/qt-5/qcoreapplication.html#processEvents



  • @MEMekaniske Thank you! Works perfectly!



  • @lolcocks very good :)

    No problem!


  • Banned

    @lolcocks to more properly answer this question let us actually look at what exactly was happening and what is happening now

    first you are in a method (I assume since its not an MRE) as such you are in an Event cycle or code block

    self.label_connectionStatus2.setText("Refreshing...")
    This sends a message to the Main Event Queue then continues with the rest of the current Event cycle once this current Event cycle has completed it passes control back to the Main Event Handler which then executes the next statement within the the Main Event Queue which may or may not be that message you sent earlier

    app.processEvents()
    This inserted after the above line -- tells the system to process all the events in the Main Event Queue then return when done whereupon it then finishes executing the remaining statements within the current Event cycle

    These concepts are very important to understand when dealing with Event Queues because doing this can sometimes be very harmful if you are not implementing your code appropriately when it comes to interacting with the Main Event Handler in this way as you might execute something in Queue that you were not ready to execute

    I hope this helps you to understand what it is doing and how to use it safely



  • @Denni-0 Thank you so much good sir, this does clarify how it works internally. Thank you for sharing and improving my knowledge. :)



  • @lolcocks said in [PySide2] How come this code is not getting executed in a line by line order?:

    @Denni-0 Thank you so much good sir, this does clarify how it works internally. Thank you for sharing and improving my knowledge. :)

    You would have learned what dennis said + a lot more from following the link I gave to the documentation.. :)



  • I will throw in: personally, I would have tried

    self.label_connectionStatus2.repaint()
    

    https://doc.qt.io/qt-5/qwidget.html#repaint, first, unless a Qt expert says otherwise. (Not update() here, that requires a processEvents().) Provided it works, no need to spin a processEvents() with unknown consequences if all you want to achieve is making text immediately visible to user. If it does not work, or if you see any unacceptable "flicker" (which I doubt you will here), then I would have gone for processEvents().

    Of course, really the subprocess should be run in a separate thread, or asynchronously, and this whole matter of UI updates being blocked would not be an issue. If the OP chose to use Qt's QProcess to do the commands it would all be asynchronous with signals/slots and there would be no issue. This is a better choice than Python subprocess in a Qt GUI application, but that is a matter of preference. (Incidentally, your code for running the 3 sub-processes is subject to race conditions: it runs them in parallel not in series.)



  • @JonB guess this process uses less resources and time when executed too compared to processEvents :)



  • @MEMekaniske
    I'm just a purist :) repaint() has no side-effects and is self-contained. If you do a processEvents() you do not know that only that label will be updated, there could be other pending events/signals which could do potentially other things.


Log in to reply