Ronnie Kisor
Ronnie Kisor

Reputation: 121

Is multithreading the only way to track passing time in a pysimplegui script?

So, I'm working on a script that needs to check elapsed time and do something at certain intervals. It seems like the pysimplegui main_loop structure is entirely event driven, so I can't just add an elapsed time check to the while loop. I've done multithreading once before, but I don't understand it well and I want to keep this as simple as possible.

#!/usr/bin/python3

import PySimpleGUI as sg
import os.path
from datetime import datetime
import csv

csvName = ''
currentTime = datetime.now()
fileStartTime = datetime.now()
workingVideoFile = ''
recordingFlag = False

def mainLoop():
    global recordingFlag
    global csvName
    global currentTime
    global fileStartTime
    global workingVideoFile

    while True:
        event, values = window.read()
        if event == "Exit" or event == sg.WIN_CLOSED:
            break
        
        if event == "-FOLDER-":
            folder = values["-FOLDER-"]
            try:
                csvSetup(str(folder))
                window.FindElement("Start Recording").Update(disabled=False)
                window.FindElement("Submit Log with Time Stamp").Update(disabled=False)
            except:
                print ('Trying to set destination folder')
                print (Exception)
        
        if event == "Start Recording":
            try:
                window.FindElement("Start Recording").Update(disabled=True)
                window.FindElement("Stop Recording").Update(disabled=False)
                fileStartTime = datetime.now()
                # Sent Bash command or whatever
                recordingFlag = True
            except:
                print ('Trying to start recording')
                print (Exception)

        if event == "Stop Recording":
            try:
                window.FindElement("Start Recording").Update(disabled=False)
                window.FindElement("Stop Recording").Update(disabled=True)
                # Send bash command or whatever
                recordingFlag = False
            except:
                print ('Trying to stop recording')
                print (Exception)
        
        if event == "Submit Log with Time Stamp":

            log = values["logText"].replace('\n', ' ')
            now = datetime.now().strftime("%m/%d/%Y %H:%M:%S")
            currentVideoName = "video 50:relative time" # get this
            logEntry = [now,currentVideoName, log]

            try:
                with open(csvName, "a") as logFile:
                    logWriter = csv.writer(logFile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
                    logWriter.writerow(logEntry)

                window.FindElement("logText").Update('')
            except:
                print ('Trying to write CSV')
                print (Exception)

        if recordingFlag:
            print (datetime.now()-fileStartTime)

        if recordingFlag and (datetime.now() - fileStartTime).total_seconds() >= 5:
            print ('it has been an hour')

    window.close()

def windowSetup():

    global window
    global layout

    sg.theme('DarkBlue')

    firstColumn = [
        [
            sg.Text("Select Location to Save Video File:"),
            sg.In(size=(40, 1), enable_events=True, key="-FOLDER-"),
            sg.FolderBrowse(),
        ],
        [
            sg.Text("                         ")
        ],
        [
            sg.Multiline(size=(200, 50), key='logText')
        ],
        [
            sg.Text ("                                                                                      "),
            sg.Button("Submit Log with Time Stamp", disabled=True),
        ],
    ]

    secondColumn = [
        [
            sg.Button("Start Recording", disabled=True),
        ],
        [
            sg.Text("               ")
        ],
        [
            sg.Text("               ")
        ],
        [
            sg.Button("Stop Recording", disabled=True),
        ],
    ]

    layout = [
        [
            sg.Column(firstColumn),
            sg.Column(secondColumn)
        
        ]
    ]

def csvSetup(dirr):
    global csvName

    now = datetime.now().strftime("%m-%d-%Y")
    csvName = dirr + "/" + now + ".csv"
    
    if  not os.path.exists(csvName):
        try:
            with open(csvName, "w") as logFile:
                logWriter = csv.writer(logFile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
                logWriter.writerow(['TIMESTAMP', 'VIDEO TIMESTAMP', 'LOG'])
        except:
            print('In csvSetup Function')
            print(Exception)
    
windowSetup()
window = sg.Window("Video Recorder", layout)
mainLoop()

Upvotes: 1

Views: 285

Answers (2)

Mike from PSG
Mike from PSG

Reputation: 5764

If you want to track actual time spent and get an accurate clock tick, then you need to measure against the Python reported time. Otherwise, your code will drift over time.

If a button click happens, for example, then your window.read() will return immediately and the time you had for the timeout won't have elapsed.

If it's critical I know the exact timing, I use code similar to this to compute it.

import PySimpleGUI as sg
from time import time


def main():

    layout = [  [sg.Text('My Window')],
                [sg.Input(key='-IN-')],
                [sg.Text(size=(12,1), key='-OUT-')],
                [sg.Button('Go'), sg.Button('Exit')]  ]

    window = sg.Window('Window Title', layout)

    start_time = last_time = time()

    while True:
        event, values = window.read(timeout=1000)
        if event in (sg.WIN_CLOSED, 'Exit'):
            break

        delta_from_last = time() - last_time
        elapsed_time = time()- start_time
        print(delta_from_last, elapsed_time)
        last_time = time()

    window.close()

if __name__ == '__main__':
    main()

Upvotes: 0

Ronnie Kisor
Ronnie Kisor

Reputation: 121

I went with adding a timeout to my

event, values = window.read()

file as

event, values = window.read(timeout=500)

to force the loop to run every half second, so I can just add the elapsed time check to the end of the loop

Upvotes: 1

Related Questions