0

I am writing a domotic control program in Python using Tkinter library. There's a button which start a function located in a other script (which I include at the beginning).

The button works fine but it still pressed during the execution of my function, which takes some time to execute... I would put a "waiting screen" instead of just having the button pressed and the program non-responding. I join an extract of my code.

I searched everywhere but I didn't find a clear solution.

Hope you can help me !

Main script :

import backend
from tkinter import *

window = Tk()
frameMain  = Frame(window)
buttonConnection = Button(frameMain, text="Connect devices", command=backend.configDevices)
frameMain.pack()

backend.py script :

pathConfip = 'assets/confip.txt'
...
def configDevices():
    with open(pathConfip, 'r', encoding='utf-8') as fileConfip:
        # ips are in a text file, separated by "###" each time
        ip = fileConfip.read().split('###')
    global bulb1, bulb2, bulb3, stripeBulb, lgtv, cast
    bulb1 = Bulb(ip[0])
    bulb2 = Bulb(ip[1])
    bulb3 = Bulb(ip[2])
    stripeBulb = Bulb(ip[3])
    lgtv = WebOsClient(ip[4])
    cast = Chromecast(ip[5])
luigittgl
  • 5
  • 1
  • Tkinter is single threaded. If the function takes a long time to run, you'll need to run it in a separate thread because tkinter can't refresh the window while your function runs in the main thread. – Bryan Oakley Aug 12 '20 at 21:31
  • Thank you ! How could I do to create a seperate thread ? I'm a beginner and I just looked how to do it but I dont' understand. Can you advise a good tutorial to learn how to do it ? – luigittgl Aug 12 '20 at 21:36
  • You could bind your method to a `MouseRelease` event on the button. You could also do something hacky like: `command=lambda:(buttonConnection['state']='normal', backend.configDevices())`. I'm not saying these are ideal solutions. – OneMadGypsy Aug 12 '20 at 22:36
  • Why not just type in threading tkinter. There are alot of not soo hard video. – Delrius Euphoria Aug 12 '20 at 23:06
  • For the moment I'll use the Eric Roy's method as I don't need something very "proper", but thank you very much ! – luigittgl Aug 13 '20 at 11:10

1 Answers1

0

As Bryan stated on the comments, the best way to handle this is by using threads. Maybe the easiest way (without getting too much into that) is by running another python script by command.

import os
os.system("python file.py &")

Note that this will work on Linux. To run commands on background on windows you will need to use pythonw.exe instead of python.exe (see here). Pythonw will also work on Linux as well.

Last thing, how to know when the command has ended? Again, the easiest (but also ugly) way to do it is by modifying a file (json or txt) located in the same folder. Then, every second or so, the tkinter app can look at the file, if it has changed, so it knows when to stop showing the loading screen.

Eric Roy
  • 334
  • 5
  • 15