Merge pull request #5257 from PySimpleGUI/Dev-latest

Reworked to use the newer PySimpleGUI constructs - save window positi…
This commit is contained in:
PySimpleGUI 2022-03-08 10:03:49 -05:00 committed by GitHub
commit 5ba5b949b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 45 additions and 70 deletions

View File

@ -2,104 +2,79 @@
import PySimpleGUI as sg import PySimpleGUI as sg
import psutil import psutil
import time import time
from threading import Thread
import operator import operator
import sys import sys
""" """
PSUTIL Desktop Widget PSUTIL "Top" CPU Processes - Desktop Widget
Creates a floating CPU utilization window that is always on top of other windows
You move it by grabbing anywhere on the window Creates a floating CPU utilization window running something similar to a "top" command.
Good example of how to do a non-blocking, polling program using PySimpleGUI
Use the spinner to adjust the number of seconds between readings of the CPU utilizaiton
NOTE - you will get a warning message printed when you exit using exit button. Use the spinner to adjust the number of seconds between readings of the CPU utilizaiton
It will look something like: Rather than calling the threading module this program uses the PySimpleGUI perform_long_operation method.
invalid command name "1616802625480StopMove" The result is similar. The function is run as a thread... the call is simply wrapped.
Copyright 2022 PySimpleGUI
""" """
# globale used to communicate with thread.. yea yea... it's working fine # global used to communicate with thread.
g_interval = 1 g_interval = 1 # how often to poll for CPU usage
g_cpu_percent = 0
g_procs = None
g_exit = False
def CPU_thread(args): def CPU_thread(window:sg.Window):
global g_interval, g_cpu_percent, g_procs, g_exit
while not g_exit: while True:
try: cpu_percent = psutil.cpu_percent(interval=g_interval)
g_cpu_percent = psutil.cpu_percent(interval=g_interval) procs = psutil.process_iter()
g_procs = psutil.process_iter() window.write_event_value('-CPU UPDATE-', (cpu_percent, procs))
except:
pass
def main(location): def main():
global g_interval, g_procs, g_exit global g_interval
location = sg.user_settings_get_entry('-location-', (None, None))
# ---------------- Create Form ---------------- # ---------------- Create Form ----------------
sg.theme('Black') sg.theme('Black')
layout = [ layout = [[sg.Text('', size=(8, 1), font=('Helvetica', 20),
[sg.Text('', size=(8, 1), font=('Helvetica', 20), text_color=sg.YELLOWS[0], justification='center', key='text'), sg.Push(), sg.Text('', enable_events=True, key='Exit')],
text_color=sg.YELLOWS[0], justification='center', key='text')], [sg.Text('', size=(30, 8), font=('Courier New', 12),
[sg.Text('', size=(30, 8), font=('Courier New', 12),
text_color='white', justification='left', key='processes')], text_color='white', justification='left', key='processes')],
[sg.Text('Update every '), [sg.Text('Update every '), sg.Spin([x+1 for x in range(10)], 3, key='spin'), sg.T('seconds ')]]
sg.Spin([x+1 for x in range(10)], 3, key='spin'), sg.T('seconds '),
sg.Text('', enable_events=True, key='Exit')
]
]
window = sg.Window('Top CPU Processes', layout, window = sg.Window('Top CPU Processes', layout, no_titlebar=True, keep_on_top=True,location=location, use_default_focus=False, alpha_channel=.8, grab_anywhere=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
no_titlebar=True, keep_on_top=True,location=location, use_default_focus=False, alpha_channel=.8, grab_anywhere=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
# start cpu measurement thread # start cpu measurement thread
thread = Thread(target=CPU_thread, args=(None,)) # using the PySimpleGUI call to start and manage the thread
thread.start() window.perform_long_operation(lambda: CPU_thread(window), '-THREAD FINISHED-')
timeout_value = 1 # make first read really quick
g_interval = 1 g_interval = 1
# ---------------- main loop ---------------- # ---------------- main loop ----------------
while True: while True:
# --------- Read and update window -------- # --------- Read and update window --------
event, values = window.read(timeout_value) event, values = window.read()
# --------- Do Button Operations -------- # --------- Do Button Operations --------
if event in (sg.WIN_CLOSED, 'Exit'): if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting
break break
elif event == 'Edit Me': elif event == 'Edit Me':
sg.execute_editor(__file__) sg.execute_editor(__file__)
timeout_value = int(values['spin']) * 1000 # for now on, use spinner for timeout elif event == '-CPU UPDATE-': # indicates data from the thread has arrived
cpu_percent, procs = values[event] # the thread sends a tuple
if procs:
# --------- Create dictionary of top % CPU processes. Format is name:cpu_percent --------
top = {proc.name(): proc.cpu_percent() for proc in procs}
top_sorted = sorted(top.items(), key=operator.itemgetter(1), reverse=True) # reverse sort to get highest CPU usage on top
if top_sorted:
top_sorted.pop(0) # remove the idle process
display_string = '\n'.join([f'{cpu/10:2.2f} {proc}' for proc, cpu in top_sorted])
# --------- Display timer and proceses in window --------
window['text'].update(f'CPU {cpu_percent}')
window['processes'].update(display_string)
# get the timeout from the spinner
g_interval = int(values['spin']) g_interval = int(values['spin'])
cpu_percent = g_cpu_percent
display_string = ''
if g_procs:
# --------- Create list of top % CPU porocesses --------
try:
top = {proc.name(): proc.cpu_percent() for proc in g_procs}
except:
pass
top_sorted = sorted(
top.items(), key=operator.itemgetter(1), reverse=True)
if top_sorted:
top_sorted.pop(0)
display_string = ''
for proc, cpu in top_sorted:
display_string += '{:2.2f} {}\n'.format(cpu/10, proc)
# --------- Display timer and proceses in window --------
window['text'].update('CPU ' + str(cpu_percent))
window['processes'].update(display_string)
g_exit = True
thread.join()
window.close() window.close()
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) > 1: main()
location = sys.argv[1].split(',')
location = (int(location[0]), int(location[1]))
else:
location = (None, None)
main(location)