0

Currently I'm working on a project of mine involving sensors, and showing that sensory data on a display via TKinter. Everythings written in Python 3.7.3.

The issue im currently handling, is to update the label in the window, while the mainloop is running. What i mean by this, is that if i execute the script, first the window options get defined, then the update function gets defined with a while true loop. Then its supposed to start the window. Now because of the while true loop it does not reach the window.mainloop() point (obviously, the while loop doesn't break...). My interest was peaked and i tried to put the window.mainloop() function inside the while loop of the update (please don't blame me, i know my script is a spaghetti mess.) I figured out that i could run the whole thing in threads, and so i decided to thread the whole window process, and add queues for the sensor data. Now the while loop was still in the way and didnt work properly, and after a bit of googling i found a code snippet that might help me. After trying to implement it in my script, i got an exception "function init expects 3 arguments, but 4 were given.." (code below) and I'm kinda running out of ideas on this.

Bear in mind that im not raelly a developer, i just need a script that can handle sensor data, dispaly it in a window, and export the current data to a database. So go easy on the blame please.

Current Script:

import time
import board
import adafruit_dht
import threading
import queue
from tkinter import *

dhtDevice = adafruit_dht.DHT22(board.D4, use_pulseio=False)

tempQ = queue.Queue(maxsize=0)
humQ = queue.Queue(maxsize=0)
    
    
class windowMain:


    def __init__(self):
        

        self.tempC_label = Label(fenster, text="Placeholder TempC")

        self.humidity_label = Label(fenster, text="Placeholder Humidity")

        self.tempC_label.pack()
        self.humidity_label.pack()
        
        self.tempC_label.after(2000, self.labelUpdate)
        self.humidity_label.after(2000, self.labelUpdate)
    
        
    def labelUpdate(self, tempQ, humQ):
        self.tempC_label.configure(text= tempQ.get() + "°C")
        #this is just to confirm if the function called or not, to see if the label updated or not.
        #if the label didnt update, and the function called, there is something wrong with the       function
        #if the label didnt update, and the function didnt call, there is a problem somwhere else
        print("Current Temp: " +tempQ.get() + "°C")
        self.label.after(2000, self.labelUpdate)

if __name__ == "__main__":
    windowName = Tk()
    windowName.title = ("Climatemonitor")
    windowMain(windowName)
    windowName.mainloop()
    

try:
    windowThread = threading.Thread(target=windowMain, args=(tempQ, humQ, ))
    windowThread.start()
except:
    print("Unable to start thread")



while True:
    
    try:
        temperature_c= dhtDevice.temperature
        tempText= temperature_c
        tempText= str(tempText)
        tempQ.put(tempText)
        humidity = dhtDevice.humidity
        humidityP = str(humidity)
        
        #this one is just to check if the sensor reads data
        print(
              "Temp: {:.1f} C     Humidity: {}% ".format(
            temperature_c, humidity
            )
              )
        
        time.sleep(2.0)
    except RuntimeError as error:
        print(error.args[0])
        time.sleep(2.0)
        continue
    except Exception as error:
        
        dhtDevice.exit()
        raise error
    
    time.sleep(2.0)

The ultimate goal is to display my sensor data, with a 2 second refresh (the HZ rate of the Sensor), while the sensor continues to read every 2 seconds. I'd also like to add that this is my first time using Python, since im, again, not really a developer yet. Thanks a bunch in advance for every critique and help

  • 1
    most simple way of doing this would be using a button to execute a function and then including your while loop in that function. – Prathamesh Apr 22 '21 at 14:25

1 Answers1

0

most simple way of doing this would be using a button to execute a function and then including your while loop in that function,

Using an button gives you an point where you can start running while instead of directly starting it as soon as you run your program

Sample code should be something like this,

import tkinter as t

def execute():
    print('hello')
    
window = t.Tk()
window.title("system")
window.geometry("550x250")
b1 = t.Button(window, text="Start", width=15, command=execute)
b1.grid(row=1, sticky="W", padx=4)
window.mainloop()

As there will be no user interaction, a button can invoked using button.invoke method such as following,

import tkinter as t

def execute():
    print('hello')
    
window = t.Tk()
window.title("system")
window.geometry("550x250")
b1 = t.Button(window, text="Start", width=0, command=execute)
#b1.grid(row=1, sticky="W", padx=4)
b1.invoke()
window.mainloop()

here removing .grid() will cause the button to disapper but can affect your GUI while updating the label value later , also have a look at this ->

Is there a way to press a button without touching it on tkinter / python?

Python tkinter button.invoke method trouble

Prathamesh
  • 1,064
  • 1
  • 6
  • 16
  • The thing is, the end product isnt supposed to have user interaction. With a button that would be way easier, i agree, but it all runs on a Raspberry Pi that will run on its own in some semi dusty corner of a museum, so that wouldnt really work, since it defeats the purpose of the project. – RE_Numbr Apr 23 '21 at 06:09
  • There is an 'invoke' method for button in tkinter which you can call to autoclick or automatically invoke the method. I have updated the answer for it. – Prathamesh Apr 23 '21 at 06:25
  • I tried to implement that solution, sadly im getting the issue, that i cant point to a tkinter label between functions. When i try to point at it in the function execute() (in your example) it gives me the exception, that the first function which i used (__init__ in my script as seen above) doesnt have an attribute with the name of my label... – RE_Numbr Apr 26 '21 at 14:14