colin moras
colin moras

Reputation: 33

Turning display with Tkinter GUI on and off on Raspberry Pi using python3

I need to turn the display on and off, while the display is on, I need it to display a welcome message created by using tkinter-python.

The sketch I have written,does turn the display on and off but displays the tkinter label only once I quit the program.

Could anyone explain to me why is tkinter label is not bieng displayed while the sketch is compiled?

import sys
import os
import time
from tkinter import *
import tkinter as tk
from tkinter.font import Font
import RPi.GPIO as GPIO

#pin description
sensor = 11

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(sensor,GPIO.IN)

print("Initializing PIR sensor....")
time.sleep(12)
print("PIR ready")
print("")

#initializing tkinter parameters
root = tk.Tk()
text = tk.Text(root)
font1 = Font(family = 'Helvetica', size = 30, weight = 'bold')
font2 = Font(family = 'Helvetica', size = 20, weight = 'bold')
font3 = Font(family = 'Helvetica', size = 15, weight = 'bold')

explanation = """WELCOME TO MY GUI"""
colin = tk.PhotoImage(file="background.gif")
#background=tk.Label(root,compound = tk.CENTER, text=explanation,font=font1, image=colin).pack()

def exitProgram():
    print("Exit button pressed")
    GPIO.cleanup()
    root.quit()
    exitButton =tk.Button(root, text = "Exit", font = font3, command = exitProgram, height = 1, width = 4, bd =1)
    exitButton.place(x= 350, y =435)


root.attributes("-fullscreen",True)

if sys.platform.startswith('linux'):
    os.system("xset dpms force off")
else:
    os.system("xset dpms force on")

try:
    while True:
        i = GPIO.input(sensor)
        if i==1:
            background=tk.Label(root,compound = tk.CENTER, text=explanation,font=font1, image=colin).pack()
            print("Human presence detected")
            if sys.platform.startswith('linux'):
                #background = tk.Label(root, compound = tk.CENTER, text=explanation, font = font1,image=colin).pack()
                os.system("xset dpms force on")
            time.sleep(30)
        else:
            print("no human around")
            if sys.platform.startswith('linux'):
                os.system("xset dpms force off")
            time.sleep(5)

except KeyboardInterrupt:
    GPIO.cleanup()

root.mainloop()

As you can I see, I am using a sensor to detect any movements. if movements are detected, the screen turns on and should display the welcome message.

You will also see that I have commented same lines of code at different places in the sketch, I tried placing the background label at different places, but still I get the same problem. The screen turns on and off but the tkinter label gets displayed only after I quit the program.

Upvotes: 3

Views: 1454

Answers (2)

scotty3785
scotty3785

Reputation: 7006

You've fallen in to the standard trap for tkinter applications. You have an infinite loop that doesn't allow the tkinter GUI to update. Never use an infinite loop with tkinter applications. Only use mainloop()

If you want to mix reading GPIOs with tkinter you need to take one of the following approaches

  1. Use the .after tkinter method to periodically schedule a function call. That function reads from the GPIO pins and updates the GUI based on the GPIO state. root.after(1000,do_function) will call a function named do_function after 1000 milli-seconds. If your do_function also contains a call to the .after method, the function will schedule it self to be called again after a specified period.

  2. Use GPIO callbacks. This is much easier if you use the gpiozero library rather than the RPi.GPIO module since you have the button.when_pressed = do_function syntax available.

With either method, the function that is called will be where you add any code to change the GUI based on the state of the GPIO pin(s).

Upvotes: 1

colin moras
colin moras

Reputation: 33

The Tkinter GUI was getting displayed after I interrupt the program since,root.mainloop() was placed at the end of the program.

Tkinter understanding mainloop This link helped me to understand the mainloop and to make necessary changes in the python sketch.

import sys
import os
import time
from tkinter import *
import tkinter as tk
from tkinter.font import Font
import RPi.GPIO as GPIO

#pin description
sensor = 11

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(sensor,GPIO.IN)

print("Initializing PIR sensor....")
time.sleep(12) #to warmup the sensor
print("PIR ready")
print("")

#initializing tkinter parameters
root = tk.Tk()
text = tk.Text(root)
font1 = Font(family = 'Helvetica', size = 30, weight = 'bold')
font2 = Font(family = 'Helvetica', size = 20, weight = 'bold')
font3 = Font(family = 'Helvetica', size = 15, weight = 'bold')

explanation = """WELCOME TO MY GUI"""
colin = tk.PhotoImage(file="background.gif")
background=tk.Label(root,compound = tk.CENTER, text=explanation,font=font1, image=colin).pack()

def exitProgram():
    print("Exit button pressed")
    GPIO.cleanup()
    root.quit()
exitButton =tk.Button(root, text = "Exit", font = font3, command = exitProgram, height = 1, width = 4, bd =1)
exitButton.place(x= 350, y =435)


root.attributes("-fullscreen",True)

os.system("xset dpms force off")
#keep the display turned off until any motion is detected

try:
    while True:
        i = GPIO.input(sensor)
        if i==1:#turn on the display when motion is detected
           print("Human presence detected")
           os.system("xset dpms force on")
           root.update()
           time.sleep(30)
       else:
           print("no human around")
           os.system("xset dpms force off")
           time.sleep(5)

except KeyboardInterrupt:
    GPIO.cleanup()

Upvotes: 0

Related Questions