0

I am reading a sensor and want to display its output as a decimal number in a GUI using PyQt5. I have found a number of tutorials that point out the label.setText('myStr') function. This does not work for my setup, however, because I need to update the field based on the input from another function. I'm not very familiar with PyQt5 yet, and I would appreciate any insight into how this problem ought to be approached. Note: (I am using LCM to acquire data from a Raspberry Pi. I'm not sure that that is relevant to the problem, but it helps explain my code below.)

Here is what I am trying to do:

class Home_Win(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        loadUi("sensor_interface.ui", self)
        self.label_temp.setText('temperature') #Just to verify that I can change it from here

    def acquire_sensors(self):
        temp = 0  #Make variable available outside nested function
        def listen(channel, data):
            msg=sensor_data.decode(data)
            temp = msg.temperature

        lc = lcm.LCM()
        subscription = lc.subscribe("sensor_data_0", listen)

            while True:
                lc.handle()
                self.label_temp.setText(str(temp))

Any thoughts on how I can update the GUI to display the readings I am getting from my sensors? Thanks!

Barmar
  • 741,623
  • 53
  • 500
  • 612
Charles R
  • 49
  • 7

2 Answers2

0

You're almost there. All you need to do is to save the ui in an instance variable in __init__:

self.ui = loadUi("sensor_interface.ui", self) 

Then, assuming label_temp is the name of your QLabel widget, just do:

self.ui.label_temp.setText(str(temp))
Mario Camilleri
  • 1,457
  • 11
  • 24
  • Thanks for the tip! I ended up incorporating this into my code, although I also had to switch to a QLineEdit instead of QLabel and the repaint() before I could get the GUI to output live updates while reading the data stream. – Charles R Jun 30 '20 at 22:12
  • Glad that helped. However, you should not need to call the `repaint()` method - under normal circumstances that happens automatically in response to changing the widget's text. Which makes me think that there must be something in your code which is blocking paint events from being handled. – Mario Camilleri Jul 01 '20 at 13:47
  • Does it have to do with my infinite while loop? My goal for the user to click the button to start data acquisition and for it to continue reading data (possibly for hours or days). During this time, it should display the present temperature to the user. (This is for user convenience. The data will also be written to a .csv file for later analysis.) It seems like the GUI doesn't want to automatically update the widget until it exits the event loop. Using the repaint() function forces a refresh before finishing the event loop, or at least I think that is what is happening? – Charles R Jul 01 '20 at 16:45
  • Yes, your infinite polling loop must be blocking the Qt event loop. You can always call QApplication.processEvents each time through your loop, of course, but that's inelegant. The real root of the problem is that the application as written is poorly structured - you should have Qt running in the main thread, and create a separate thread (using QThread) for the background polling loop. The polling loop can emit a simple signal each time a data item is read from the sensor, which triggers a function in the main thread to update the text of your widget. That way the UI remains responsive. – Mario Camilleri Jul 02 '20 at 09:40
0

It turned out that I needed to add repaint(). I also switched to a QLineEdit as this seemed to work better for me. So inside the while loop I now have:

self.ui.lineEdit_temp.setText(str(temp))
self.ui.lineEdit_temp.repaint()

This now outputs live updates to the GUI while reading the data stream.

Charles R
  • 49
  • 7