0

Hi I am trying to write a simple program that while working in the background looks for how long a specific executable is working. This bit works in the shell of the IDE however I don't know how to connect the shells output to the GUI so that it refreshes and shows the time in seconds that a program is working for.

[I have tried StringVar but it failed]

If someone would help it would be lovely

Below is the code which as stated works only partially:

import time
from tkinter import * # Another GUI-Framework is PYQT5
import wmi
import sys

c = wmi.WMI()
Task_List = []


class AppButtons:
    # A variable and a List for the gatering of currently running processes

    def __init__(self, master):
        main_frame = Frame(master)
        main_frame.pack()

        '''
        #Program title
        self.Label = Label(main_frame, text='The time monitoring app')
        self.Label.config(font=("Courier", 30), anchor=CENTER)
        self.Label.grid(row=0, column=0)
        '''


        # Program start
        self.strat_timer = Button(main_frame, text='Beggin the app running time monitoring!!!', command=self.main_timer)
        self.strat_timer.config(font=("Courier", 12))
        self.strat_timer.grid(row=1, column=0,pady=10, sticky=E+W) # pady and padx add space btw the widgets in the x and y directions corespondingly

        # Program termination
        self.end_timer = Button(main_frame, text='Terminate the app timmer', command=self.timer_kill)
        self.end_timer.config(font=("Courier", 12))
        self.end_timer.grid(row=1, column=1,pady=10, sticky=E+W)

        # Output description
        self.time_overwatch_label1 = Label(main_frame, bg='red' ,width=60, height=1 , text='Program: WorldOfTanks.exe | Running time:')
        self.time_overwatch_label1.grid(row=2, column=0,)

        self.time_overwatch_label2 = Label(main_frame, bg='Yellow',width=60, height=1 , text='Program: chrome.exe | Running time:')
        self.time_overwatch_label2.grid(row=3, column=0)

        self.time_overwatch_label3 = Label(main_frame, bg='red',width=60, height=1 , text='Program: pycharm64.exe | Running time:')
        self.time_overwatch_label3.grid(row=4, column=0)


        # Output part
        self.output1 = Label(main_frame, bg='red' ,width=60, height=1, text=self.main_timer)
        self.output1.grid(row=2, column=1)

        self.output2 = Text(main_frame, bg='Yellow', width=60, height=1)
        self.output2.grid(row=3, column=1)

        self.output3 = Text(main_frame, bg='red', width=60, height=1)
        self.output3.grid(row=4, column=1)

    # gives the list of currently running processes using the WMI library
    def running_tasks(self):
        Task_List.clear()
        for process in c.Win32_Process():
            Task_List.append(process.Name)
        return Task_List

    def program_search(self):
        self.running_tasks()
        if any('WorldOfTanks.exe' in s for s in Task_List):
            return True
        else:
            return False

    # Main fuction which is responsible for the output of the timmer (in this example of WorldOfTanks.exe)
    # This fuction cosists of "running_tasks" and "task_search". It should be called from the GUI window
    def main_timer(self):
        start_time = time.time()
        while True:
            if self.program_search() is True:
                print('WoT is Running for', "--- %s seconds ---" % (time.time() - start_time))
                continue
            if time.time() - start_time < 21:
                print("World of Tanks wasn't running")
                break
            if self.program_search() is False:
                print('WorldOfTanks.exe was running for', "--- %s seconds ---" % (time.time() - start_time))
                break


    def timer_kill(self):
        sys.exit()


root = Tk()

# Title of the window is displayed on the uppermost bar
root.title("The Time Monitoring App")

# Initializes the class
b = AppButtons(root)

root.mainloop()

1 Answer 1

1

The most sensible approach would be to create three StringVar() for the three running times and linking them to the labels. At each iteration of the loop (which might be less demanding if you included a time.sleep(.5) to wait for half a second before running it again), update all of the string variables.

Creating and linking the string variables:

    self.t1 = StringVar()
    self.t1.set("No time recorded for WoT") ## Set to no output before the button is pressed

    self.output1 = Label(main_frame, bg='red' ,width=60, height=1, textvariable=self.t1)
    self.output1.grid(row=2, column=1)

Updating their values:

def main_timer(self):
    start_time = time.time()
    while True:
        time.sleep(0.5)
        if self.program_search() is True:
            self.t1.set('WoT is Running for', "--- %s seconds ---" % (time.time() - start_time))
            continue
        if time.time() - start_time < 21:
            self.t1.set("World of Tanks wasn't running")
            break
        if self.program_search() is False:
            self.t1.set('WorldOfTanks.exe was running for', "--- %s seconds ---" % (time.time() - start_time))
            break

Whenever you change the value of self.t1 in the method .main_timer(), the label will be updated as it is directly linked to this StringVar. Important: The text of the label has to be set using textvariable, not text, if you want it to change automatically.

Sign up to request clarification or add additional context in comments.

4 Comments

Are you aware that a StringVar isn't necessary? You can use it, but you can also directly change the text of a label without it. In this case the StringVar adds overhead without adding any additional benefit.
OK now I see how this is supposed to be done, thanks to both of You. Now I understand the StringVar method (though I don't know how should I do it without it as Bryan Oakley suggested,, but i guess I don't need it)
@Brian: No, I was actually unaware of that. I thought, the .set() method was required to update all widgets that use this textvariable. But if it's not necessary, I have quite a lot of code cleaning to do :)
@MartinWettstein I don't only have code cleaning to do but also quite some learning. I have implemnted what You have written, but somehow for some unknown reasen the code works but it dosn't update this value in the GUI [BUT IN A DEBUGGER IT IS OBVIOUS THAT THE VALUE T1 GETS UPDATED !!!] do You have any idea why ? (I have read that it might be somehow bugged because of the loop). I will put the code in a separate anwser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.