More demo programs updates 🤦♂️ wow.....I thought for sure these were checked in....
This commit is contained in:
parent
cfe2c96a1f
commit
430d1bc77f
|
@ -85,7 +85,8 @@ def main(location):
|
|||
margins=(1,1),
|
||||
element_padding=(0,0),
|
||||
border_depth=0,
|
||||
location=location)
|
||||
location=location,
|
||||
right_click_menu=[[''], ['Edit Me', 'Exit',]])
|
||||
|
||||
|
||||
graphs = []
|
||||
|
@ -95,12 +96,15 @@ def main(location):
|
|||
window[('-TXT-', (rows, cols))],
|
||||
0, colors[(rows*NUM_COLS+cols)%len(colors)])]
|
||||
|
||||
|
||||
# ---------------- main loop ----------------
|
||||
while True :
|
||||
# --------- Read and update window once every Polling Frequency --------
|
||||
event, values = window.read(timeout=POLL_FREQUENCY)
|
||||
if event in (sg.WIN_CLOSED, 'Exit'): # Be nice and give an exit
|
||||
break
|
||||
elif event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
# read CPU for each core
|
||||
stats = psutil.cpu_percent(percpu=True)
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class Gauge():
|
|||
: Return
|
||||
Addition result for number1 and number2.
|
||||
"""
|
||||
return number1 + number1
|
||||
return number1 + number2
|
||||
|
||||
def limit(number):
|
||||
"""
|
||||
|
@ -274,7 +274,7 @@ def main(location):
|
|||
[sg.T(size=(5, 1), font='Any 20', justification='c', background_color='black', k='-gauge VALUE-')]]
|
||||
|
||||
|
||||
window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
|
||||
window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
|
||||
|
||||
gauge = Gauge(pointer_color=sg.theme_text_color(), clock_color=sg.theme_text_color(), major_tick_color=sg.theme_text_color(),
|
||||
minor_tick_color=sg.theme_input_background_color(), pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45,
|
||||
|
@ -293,7 +293,8 @@ def main(location):
|
|||
# ----------- update the graphics and text in the window ------------
|
||||
# update the window, wait for a while, then check for exit
|
||||
event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
|
||||
if event == sg.WIN_CLOSED or event == 'Exit':
|
||||
if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
|
||||
sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting
|
||||
break
|
||||
if event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
|
@ -306,5 +307,5 @@ if __name__ == '__main__':
|
|||
location = sys.argv[1].split(',')
|
||||
location = (int(location[0]), int(location[1]))
|
||||
else:
|
||||
location = (None, None)
|
||||
location = sg.user_settings_get_entry('-location-', (None, None))
|
||||
main(location)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
import PySimpleGUI as sg
|
||||
import sys
|
||||
import psutil
|
||||
import math
|
||||
|
||||
"""
|
||||
Desktop floating widget - CPU Cores as Gauges
|
||||
|
@ -17,20 +18,17 @@ import psutil
|
|||
Copyright 2020 PySimpleGUI
|
||||
"""
|
||||
|
||||
GRAPH_WIDTH = 120 # each individual graph size in pixels
|
||||
GRAPH_HEIGHT = 40
|
||||
# gsize = (120, 75)
|
||||
# gsize = (85, 40)
|
||||
gsize = (55, 30)
|
||||
|
||||
TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window
|
||||
NUM_COLS = 4
|
||||
POLL_FREQUENCY = 2000 # how often to update graphs in milliseconds
|
||||
POLL_FREQUENCY = 1500 # how often to update graphs in milliseconds
|
||||
|
||||
colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
|
||||
|
||||
|
||||
|
||||
import math
|
||||
import random
|
||||
|
||||
|
||||
class Gauge():
|
||||
def mapping(func, sequence, *argc):
|
||||
"""
|
||||
|
@ -56,7 +54,7 @@ class Gauge():
|
|||
: Return
|
||||
Addition result for number1 and number2.
|
||||
"""
|
||||
return number1 + number1
|
||||
return number1 + number2
|
||||
|
||||
def limit(number):
|
||||
"""
|
||||
|
@ -67,7 +65,6 @@ class Gauge():
|
|||
angel degree in 0 ~ 360, return 0 if number < 0, 360 if number > 360.
|
||||
"""
|
||||
return max(min(360, number), 0)
|
||||
|
||||
class Clock():
|
||||
"""
|
||||
Draw background circle or arc
|
||||
|
@ -134,7 +131,7 @@ class Gauge():
|
|||
self.figure = []
|
||||
self.stop_angle = angle
|
||||
self.graph_elem = graph_elem
|
||||
self.new(degree=angle)
|
||||
self.new(degree=angle, color=pointer_color)
|
||||
|
||||
def new(self, degree=0, color=None):
|
||||
"""
|
||||
|
@ -224,10 +221,10 @@ class Gauge():
|
|||
All angles defined as count clockwise from negative x-axis.
|
||||
Should create instance of clock, pointer, minor tick and major tick first.
|
||||
"""
|
||||
def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None):
|
||||
def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, minor_tick_step=5, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None):
|
||||
|
||||
self.clock = Gauge.Clock(start_angle=start_angle, stop_angle=stop_angle, fill_color=clock_color, radius=clock_radius, graph_elem=graph_elem)
|
||||
self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem)
|
||||
self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem, step=minor_tick_step)
|
||||
self.major_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=major_tick_width, start_radius=major_tick_start_radius, stop_radius=major_tick_stop_radius, step=major_tick_step, line_color=major_tick_color, graph_elem=graph_elem)
|
||||
self.pointer = Gauge.Pointer(angle=pointer_angle, inner_radius=pointer_inner_radius, outer_radius=pointer_outer_radius, pointer_color=pointer_color, outer_color=pointer_outer_color, origin_color=pointer_origin_color, line_width=pointer_line_width, graph_elem=graph_elem)
|
||||
|
||||
|
@ -250,7 +247,7 @@ class Gauge():
|
|||
if self.pointer:
|
||||
self.pointer.move(delta_x, delta_y)
|
||||
|
||||
def change(self, degree=None, step=1):
|
||||
def change(self, degree=None, step=1, pointer_color=None):
|
||||
"""
|
||||
Rotation of pointer
|
||||
call it with degree and step to set initial options for rotation.
|
||||
|
@ -266,17 +263,17 @@ class Gauge():
|
|||
new_degree = now + step
|
||||
if ((step > 0 and new_degree < self.pointer.stop_degree) or
|
||||
(step < 0 and new_degree > self.pointer.stop_degree)):
|
||||
self.pointer.new(degree=new_degree, color='red' if new_degree > 90 else None)
|
||||
self.pointer.new(degree=new_degree, color=pointer_color)
|
||||
return False
|
||||
else:
|
||||
self.pointer.new(degree=self.pointer.stop_degree, color='red' if self.pointer.stop_degree > 90 else None)
|
||||
self.pointer.new(degree=self.pointer.stop_degree, color=pointer_color)
|
||||
return True
|
||||
|
||||
|
||||
# ------------------------------ BEGINNING OF CPU WIDGET GUI CODE ------------------------------
|
||||
|
||||
# DashGraph does the drawing of each graph
|
||||
class DashGraph(object):
|
||||
def __init__(self, graph_elem, text_elem, starting_count, color):
|
||||
def __init__(self, gsize, graph_elem, text_elem, starting_count, color):
|
||||
self.graph_current_item = 0
|
||||
self.graph_elem = graph_elem # type: sg.Graph
|
||||
self.text_elem = text_elem
|
||||
|
@ -285,26 +282,36 @@ class DashGraph(object):
|
|||
self.color = color
|
||||
self.line_list = [] # list of currently visible lines. Used to delete oild figures
|
||||
|
||||
self.gauge = Gauge(pointer_color=color, clock_color=color, major_tick_color=color,
|
||||
minor_tick_color=color, pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45,
|
||||
minor_tick_start_radius=45, minor_tick_stop_radius=50, major_tick_stop_radius=50, major_tick_step=30, clock_radius=50, pointer_line_width=3,
|
||||
pointer_inner_radius=10, pointer_outer_radius=50, graph_elem=graph_elem)
|
||||
self.gauge = Gauge(pointer_color=color,
|
||||
clock_color=color,
|
||||
major_tick_color=color,
|
||||
minor_tick_color=color,
|
||||
pointer_outer_color=color,
|
||||
major_tick_start_radius=gsize[1] - 10,
|
||||
minor_tick_start_radius=gsize[1] - 10,
|
||||
minor_tick_stop_radius=gsize[1] - 5,
|
||||
major_tick_stop_radius=gsize[1] - 5,
|
||||
clock_radius=gsize[1] - 5,
|
||||
pointer_outer_radius=gsize[1] - 5,
|
||||
major_tick_step=30,
|
||||
minor_tick_step=15,
|
||||
pointer_line_width=3,
|
||||
pointer_inner_radius=10,
|
||||
graph_elem=graph_elem)
|
||||
|
||||
|
||||
self.gauge.change(degree=0)
|
||||
|
||||
def graph_percentage_abs(self, value):
|
||||
if self.gauge.change():
|
||||
if self.gauge.change(pointer_color='red' if value > 50 else None):
|
||||
new_angle = value*180/100
|
||||
self.gauge.change(degree=new_angle, step=new_angle)
|
||||
self.gauge.change()
|
||||
self.gauge.change(degree=new_angle, step=100, pointer_color='red' if value > 50 else None)
|
||||
self.gauge.change(pointer_color='red' if value > 50 else None)
|
||||
|
||||
def text_display(self, text):
|
||||
self.text_elem.update(text)
|
||||
|
||||
def main(location):
|
||||
gsize = (100, 55)
|
||||
|
||||
|
||||
# A couple of "User defined elements" that combine several elements and enable bulk edits
|
||||
def Txt(text, **kwargs):
|
||||
return(sg.Text(text, font=('Helvetica 8'), **kwargs))
|
||||
|
@ -312,7 +319,7 @@ def main(location):
|
|||
def GraphColumn(name, key):
|
||||
layout = [
|
||||
[sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key=key+'-GRAPH-')],
|
||||
[sg.T(size=(5, 1), justification='c', font='Courier 14', k=key+'-GAUGE VALUE-')]]
|
||||
[sg.T(size=(5, 1), justification='c', font='Courier 10', k=key+'-GAUGE VALUE-')]]
|
||||
return sg.Column(layout, pad=(2, 2), element_justification='c')
|
||||
|
||||
num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU
|
||||
|
@ -320,9 +327,7 @@ def main(location):
|
|||
sg.theme('black')
|
||||
sg.set_options(element_padding=(0,0), margins=(1,1), border_width=0)
|
||||
|
||||
# the clever Red X graphic
|
||||
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
|
||||
layout = [[ sg.Button(image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'),
|
||||
layout = [[ sg.Button(image_data=sg.red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'),
|
||||
sg.Text(' CPU Core Usage')] ]
|
||||
|
||||
# add on the graphs
|
||||
|
@ -342,10 +347,12 @@ def main(location):
|
|||
use_default_focus=False,
|
||||
finalize=True,
|
||||
location=location,
|
||||
right_click_menu=[[''], 'Exit'])
|
||||
right_click_menu=[[''], 'Exit'],
|
||||
# transparent_color='black',
|
||||
)
|
||||
|
||||
# setup graphs & initial values
|
||||
graphs = [DashGraph(window['-CPU-'+str(i)+'-GRAPH-'],
|
||||
graphs = [DashGraph(gsize, window['-CPU-'+str(i)+'-GRAPH-'],
|
||||
window['-CPU-'+str(i) + '-GAUGE VALUE-'],
|
||||
0, colors[i%6]) for i in range(num_cores) ]
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import sys
|
|||
|
||||
"""
|
||||
Another simple Desktop Widget using PySimpleGUI
|
||||
This time a RAM indicator. The Widget is square.
|
||||
This time a CPU Usage indicator. The Widget is square.
|
||||
The bottom section will be shaded to
|
||||
represent the total amount CPU currently in use.
|
||||
Uses the theme's button color for colors.
|
||||
|
@ -18,16 +18,12 @@ GSIZE = (160, 160)
|
|||
UPDATE_FREQUENCY_MILLISECONDS = 2 * 1000
|
||||
|
||||
|
||||
def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')):
|
||||
""" Returns a human readable string reprentation of bytes"""
|
||||
return str(bytes) + ' ' + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:])
|
||||
|
||||
|
||||
def main(location):
|
||||
graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-', enable_events=True)
|
||||
graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-')
|
||||
|
||||
layout = [[graph]]
|
||||
|
||||
window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
|
||||
window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
|
||||
|
||||
text_id2 = graph.draw_text(f'CPU', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0])
|
||||
|
||||
|
@ -45,7 +41,8 @@ def main(location):
|
|||
|
||||
# update the window, wait for a while, then check for exit
|
||||
event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
|
||||
if event == sg.WIN_CLOSED or event == 'Exit':
|
||||
if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
|
||||
sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting
|
||||
break
|
||||
if event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
|
@ -62,5 +59,5 @@ if __name__ == '__main__':
|
|||
location = sys.argv[1].split(',')
|
||||
location = (int(location[0]), int(location[1]))
|
||||
else:
|
||||
location = (None, None)
|
||||
location = sg.user_settings_get_entry('-location-', (None, None))
|
||||
main(location)
|
||||
|
|
|
@ -24,7 +24,6 @@ g_cpu_percent = 0
|
|||
g_procs = None
|
||||
g_exit = False
|
||||
|
||||
|
||||
def CPU_thread(args):
|
||||
global g_interval, g_cpu_percent, g_procs, g_exit
|
||||
|
||||
|
@ -53,7 +52,7 @@ def main(location):
|
|||
]
|
||||
|
||||
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)
|
||||
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
|
||||
thread = Thread(target=CPU_thread, args=(None,))
|
||||
|
@ -67,9 +66,10 @@ def main(location):
|
|||
# --------- Do Button Operations --------
|
||||
if event in (sg.WIN_CLOSED, 'Exit'):
|
||||
break
|
||||
|
||||
elif event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
timeout_value = int(values['spin']) * 1000 # for now on, use spinner for timeout
|
||||
|
||||
g_interval = int(values['spin'])
|
||||
cpu_percent = g_cpu_percent
|
||||
display_string = ''
|
||||
if g_procs:
|
||||
|
|
|
@ -50,7 +50,7 @@ class Gauge():
|
|||
: Return
|
||||
Addition result for number1 and number2.
|
||||
"""
|
||||
return number1 + number1
|
||||
return number1 + number2
|
||||
|
||||
def limit(number):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
import PySimpleGUI as sg
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
"""
|
||||
Desktop Widget - Display the date
|
||||
Simple display of the date in the format of:
|
||||
Day of week Day Month Year
|
||||
|
||||
You can change the format by modifying the function get_date_string
|
||||
|
||||
Copyright 2021 PySimpleGUI
|
||||
"""
|
||||
|
||||
ALPHA = 0.9 # Initial alpha until user changes
|
||||
THEME = 'Dark green 3' # Initial theme until user changes
|
||||
refresh_font = title_font = 'Courier 8'
|
||||
main_info_font = sg.user_settings_get_entry('-main info font-', 'Courier 60')
|
||||
|
||||
main_info_size = (12, 1)
|
||||
UPDATE_FREQUENCY_MILLISECONDS = 1000 * 60 * 60 # update every hour by default until set by user
|
||||
|
||||
|
||||
def choose_theme(location, size):
|
||||
"""
|
||||
A window to allow new themes to be tried out.
|
||||
Changes the theme to the newly chosen one and returns theme's name
|
||||
Automaticallyi switches to new theme and saves the setting in user settings file
|
||||
|
||||
:param location: (x,y) location of the Widget's window
|
||||
:type location: Tuple[int, int]
|
||||
:param size: Size in pixels of the Widget's window
|
||||
:type size: Tuple[int, int]
|
||||
:return: The name of the newly selected theme
|
||||
:rtype: None | str
|
||||
"""
|
||||
layout = [[sg.Text('Try a theme')],
|
||||
[sg.Listbox(values=sg.theme_list(), size=(20, 20), key='-LIST-', enable_events=True)],
|
||||
[sg.OK(), sg.Cancel()]]
|
||||
|
||||
window = sg.Window('Look and Feel Browser', layout, location=location)
|
||||
old_theme = sg.theme()
|
||||
while True: # Event Loop
|
||||
event, values = window.read()
|
||||
if event in (sg.WIN_CLOSED, 'Exit', 'OK', 'Cancel'):
|
||||
break
|
||||
sg.theme(values['-LIST-'][0])
|
||||
window.hide()
|
||||
# make at test window to the left of the current one
|
||||
test_window = make_window(location=((location[0] - size[0] * 1.2, location[1])), test_window=True)
|
||||
test_window.read(close=True)
|
||||
window.un_hide()
|
||||
window.close()
|
||||
|
||||
# after choice made, save theme or restore the old one
|
||||
if event == 'OK' and values['-LIST-']:
|
||||
sg.theme(values['-LIST-'][0])
|
||||
sg.user_settings_set_entry('-theme-', values['-LIST-'][0])
|
||||
return values['-LIST-'][0]
|
||||
else:
|
||||
sg.theme(old_theme)
|
||||
return None
|
||||
|
||||
|
||||
def make_window(location, test_window=False):
|
||||
"""
|
||||
Defines the layout and creates the window for the main window
|
||||
If the parm test_window is True, then a simplified, and EASY to close version is shown
|
||||
|
||||
:param location: (x,y) location to create the window
|
||||
:type location: Tuple[int, int]
|
||||
:param test_window: If True, then this is a test window & will close by clicking on it
|
||||
:type test_window: bool
|
||||
:return: newly created window
|
||||
:rtype: sg.Window
|
||||
"""
|
||||
title = sg.user_settings_get_entry('-title-', '')
|
||||
if not test_window:
|
||||
theme = sg.user_settings_get_entry('-theme-', THEME)
|
||||
sg.theme(theme)
|
||||
main_info_font = sg.user_settings_get_entry('-main info font-', 'Courier 60')
|
||||
|
||||
# ------------------- Window Layout -------------------
|
||||
initial_text = get_date_string()
|
||||
if test_window:
|
||||
title_element = sg.Text('Click to close', font=title_font, enable_events=True)
|
||||
right_click_menu = [[''], ['Exit', ]]
|
||||
else:
|
||||
title_element = sg.pin(sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-'))
|
||||
right_click_menu = [[''],
|
||||
['Choose Title', 'Edit Me', 'New Theme', 'Save Location', 'Font', 'Refresh', 'Set Refresh Rate', 'Show Refresh Info', 'Hide Refresh Info',
|
||||
'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
|
||||
|
||||
|
||||
layout = [[title_element],
|
||||
[sg.Text(initial_text, size=(len(initial_text)+2, 1), font=main_info_font, k='-MAIN INFO-', justification='c', enable_events=test_window)],
|
||||
[sg.pin(
|
||||
sg.Text(size=(15, 2), font=refresh_font, k='-REFRESHED-', justification='c', visible=sg.user_settings_get_entry('-show refresh-', True)))]]
|
||||
|
||||
# ------------------- Window Creation -------------------
|
||||
try:
|
||||
window = sg.Window('Desktop Widget Template', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_justification='c', element_padding=(0, 0), alpha_channel=sg.user_settings_get_entry('-alpha-', ALPHA), finalize=True, right_click_menu=right_click_menu, right_click_menu_tearoff=False)
|
||||
except Exception as e:
|
||||
if sg.popup_yes_no('Error creating the window', e, 'Do you want to delete your settings file to fix?') == 'Yes':
|
||||
sg.user_settings_delete_filename()
|
||||
sg.popup('Settings file deleted. Please restart your program.')
|
||||
exit()
|
||||
return window
|
||||
|
||||
def get_date_string():
|
||||
dtime_here = datetime.utcnow() + timedelta(hours=-5)
|
||||
return dtime_here.strftime('%a %d %b %Y')
|
||||
|
||||
|
||||
def main(location):
|
||||
"""
|
||||
Where execution begins
|
||||
The Event Loop lives here, but the window creation is done in another function
|
||||
This is an important design pattern
|
||||
|
||||
:param location: Location to create the main window if one is not found in the user settings
|
||||
:type location: Tuple[int, int]
|
||||
"""
|
||||
|
||||
window = make_window(sg.user_settings_get_entry('-location-', location))
|
||||
|
||||
refresh_frequency = sg.user_settings_get_entry('-fresh frequency-', UPDATE_FREQUENCY_MILLISECONDS)
|
||||
|
||||
while True: # Event Loop
|
||||
# Normally a window.read goes here, but first we're updating the values in the window, then reading it
|
||||
# First update the status information
|
||||
window['-MAIN INFO-'].update(get_date_string())
|
||||
# for debugging show the last update date time
|
||||
if sg.user_settings_get_entry('-title-', 'None') in ('None', 'Hide'):
|
||||
window['-TITLE-'].update(visible=False)
|
||||
else:
|
||||
window['-TITLE-'].update(sg.user_settings_get_entry('-title-', 'None'),visible=True)
|
||||
window['-REFRESHED-'].update(datetime.now().strftime("%m/%d/%Y\n%I:%M:%S %p"))
|
||||
|
||||
# -------------- Start of normal event loop --------------
|
||||
event, values = window.read(timeout=refresh_frequency)
|
||||
print(event, values)
|
||||
if event in (sg.WIN_CLOSED, 'Exit'): # standard exit test... ALWAYS do this
|
||||
break
|
||||
if event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
elif event == 'Choose Title':
|
||||
new_title = sg.popup_get_text('Choose a title for your Widget\nEnter None if you do not want anything displayed', location=window.current_location())
|
||||
if new_title is not None:
|
||||
if new_title in ('None', 'Hide'):
|
||||
window['-TITLE-'].update(visible=False)
|
||||
else:
|
||||
window['-TITLE-'].update(new_title, visible=True)
|
||||
sg.user_settings_set_entry('-title-', new_title)
|
||||
elif event == 'Show Refresh Info':
|
||||
window['-REFRESHED-'].update(visible=True)
|
||||
sg.user_settings_set_entry('-show refresh-', True)
|
||||
elif event == 'Save Location':
|
||||
sg.user_settings_set_entry('-location-', window.current_location())
|
||||
sg.popup_notify(f'Saved your current window location:', window.current_location(), title='Saved Location')
|
||||
elif event == 'Hide Refresh Info':
|
||||
window['-REFRESHED-'].update(visible=False)
|
||||
sg.user_settings_set_entry('-show refresh-', False)
|
||||
elif event in [str(x) for x in range(1, 11)]: # if Alpha Channel was chosen
|
||||
window.set_alpha(int(event) / 10)
|
||||
sg.user_settings_set_entry('-alpha-', int(event) / 10)
|
||||
elif event == 'Set Refresh Rate':
|
||||
choice = sg.popup_get_text('How frequently to update window in seconds? (can be a float)',
|
||||
default_text=sg.user_settings_get_entry('-fresh frequency-', UPDATE_FREQUENCY_MILLISECONDS) / 1000,
|
||||
location=window.current_location())
|
||||
if choice is not None:
|
||||
try:
|
||||
refresh_frequency = float(choice) * 1000 # convert to milliseconds
|
||||
sg.user_settings_set_entry('-fresh frequency-', float(refresh_frequency))
|
||||
except Exception as e:
|
||||
sg.popup_error(f'You entered an incorrect number of seconds: {choice}', f'Error: {e}', location=window.current_location())
|
||||
elif event == 'New Theme':
|
||||
loc = window.current_location()
|
||||
if choose_theme(window.current_location(), window.size) is not None:
|
||||
window.close() # out with the old...
|
||||
window = make_window(loc) # in with the new
|
||||
elif event == 'Font':
|
||||
font = sg.popup_get_text('Enter font string using PySimpleGUI font format (e.g. courier 70 or courier 70 bold)', default_text=sg.user_settings_get_entry('-main info font-'), keep_on_top=True)
|
||||
if font:
|
||||
sg.user_settings_set_entry('-main info font-', font)
|
||||
loc = window.current_location()
|
||||
_, window = window.close(), make_window(loc)
|
||||
window.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# To start the window at a specific location, get this location on the command line
|
||||
# The location should be in form x,y with no spaces
|
||||
location = (None, None) # assume no location provided
|
||||
if len(sys.argv) > 1:
|
||||
location = sys.argv[1].split(',')
|
||||
location = (int(location[0]), int(location[1]))
|
||||
main(location)
|
|
@ -19,6 +19,7 @@ import datetime
|
|||
|
||||
ALPHA = 0.9 # Initial alpha until user changes
|
||||
THEME = 'Dark green 3' # Initial theme until user changes
|
||||
sg.user_settings_filename(filename='DaysUntil.json')
|
||||
refresh_font = sg.user_settings_get_entry('-refresh font-', 'Courier 8')
|
||||
title_font = sg.user_settings_get_entry('-title font-', 'Courier 8')
|
||||
main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70')
|
||||
|
|
|
@ -0,0 +1,359 @@
|
|||
#!/usr/bin/env python
|
||||
import PySimpleGUI as sg
|
||||
import psutil
|
||||
import sys
|
||||
import math
|
||||
|
||||
"""
|
||||
Desktop "Rainmeter" style widget - Drive usage
|
||||
Requires: psutil
|
||||
Uses a "Gauge" to display drive usage
|
||||
"""
|
||||
|
||||
ALPHA = 0.7
|
||||
THEME = 'black'
|
||||
UPDATE_FREQUENCY_MILLISECONDS = 20 * 1000
|
||||
|
||||
BAR_COLORS = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
|
||||
gsize = (50, 30)
|
||||
|
||||
class Gauge():
|
||||
def mapping(func, sequence, *argc):
|
||||
"""
|
||||
Map function with extra argument, not for tuple.
|
||||
: Parameters
|
||||
func - function to call.
|
||||
sequence - list for iteration.
|
||||
argc - more arguments for func.
|
||||
: Return
|
||||
list of func(element of sequence, *argc)
|
||||
"""
|
||||
if isinstance(sequence, list):
|
||||
return list(map(lambda i: func(i, *argc), sequence))
|
||||
else:
|
||||
return func(sequence, *argc)
|
||||
|
||||
def add(number1, number2):
|
||||
"""
|
||||
Add two number
|
||||
: Parameter
|
||||
number1 - number to add.
|
||||
numeer2 - number to add.
|
||||
: Return
|
||||
Addition result for number1 and number2.
|
||||
"""
|
||||
return number1 + number1
|
||||
|
||||
def limit(number):
|
||||
"""
|
||||
Limit angle in range 0 ~ 360
|
||||
: Parameter
|
||||
number: angle degree.
|
||||
: Return
|
||||
angel degree in 0 ~ 360, return 0 if number < 0, 360 if number > 360.
|
||||
"""
|
||||
return max(min(360, number), 0)
|
||||
class Clock():
|
||||
"""
|
||||
Draw background circle or arc
|
||||
All angles defined as clockwise from negative x-axis.
|
||||
"""
|
||||
|
||||
def __init__(self, center_x=0, center_y=0, radius=100, start_angle=0,
|
||||
stop_angle=360, fill_color='white', line_color='black', line_width=2, graph_elem=None):
|
||||
|
||||
instance = Gauge.mapping(isinstance, [center_x, center_y, radius, start_angle,
|
||||
stop_angle, line_width], (int, float)) + Gauge.mapping(isinstance,
|
||||
[fill_color, line_color], str)
|
||||
if False in instance:
|
||||
raise ValueError
|
||||
start_angle, stop_angle = Gauge.limit(start_angle), Gauge.limit(stop_angle)
|
||||
self.all = [center_x, center_y, radius, start_angle, stop_angle,
|
||||
fill_color, line_color, line_width]
|
||||
self.figure = []
|
||||
self.graph_elem = graph_elem
|
||||
self.new()
|
||||
|
||||
def new(self):
|
||||
"""
|
||||
Draw Arc or circle
|
||||
"""
|
||||
x, y, r, start, stop, fill, line, width = self.all
|
||||
start, stop = (180 - start, 180 - stop) if stop < start else (180 - stop, 180 - start)
|
||||
if start == stop % 360:
|
||||
self.figure.append(self.graph_elem.DrawCircle((x, y), r, fill_color=fill,
|
||||
line_color=line, line_width=width))
|
||||
else:
|
||||
self.figure.append(self.graph_elem.DrawArc((x - r, y + r), (x + r, y - r), stop - start,
|
||||
start, style='arc', arc_color=fill))
|
||||
|
||||
def move(self, delta_x, delta_y):
|
||||
"""
|
||||
Move circle or arc in clock by delta x, delta y
|
||||
"""
|
||||
if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)):
|
||||
raise ValueError
|
||||
self.all[0] += delta_x
|
||||
self.all[1] += delta_y
|
||||
for figure in self.figure:
|
||||
self.graph_elem.MoveFigure(figure, delta_x, delta_y)
|
||||
|
||||
class Pointer():
|
||||
"""
|
||||
Draw pointer of clock
|
||||
All angles defined as clockwise from negative x-axis.
|
||||
"""
|
||||
|
||||
def __init__(self, center_x=0, center_y=0, angle=0, inner_radius=20,
|
||||
outer_radius=80, outer_color='white', pointer_color='blue',
|
||||
origin_color='black', line_width=2, graph_elem=None):
|
||||
|
||||
instance = Gauge.mapping(isinstance, [center_x, center_y, angle, inner_radius,
|
||||
outer_radius, line_width], (int, float)) + Gauge.mapping(isinstance,
|
||||
[outer_color, pointer_color, origin_color], str)
|
||||
if False in instance:
|
||||
raise ValueError
|
||||
|
||||
self.all = [center_x, center_y, angle, inner_radius, outer_radius,
|
||||
outer_color, pointer_color, origin_color, line_width]
|
||||
self.figure = []
|
||||
self.stop_angle = angle
|
||||
self.graph_elem = graph_elem
|
||||
self.new(degree=angle, color=pointer_color)
|
||||
|
||||
def new(self, degree=0, color=None):
|
||||
"""
|
||||
Draw new pointer by angle, erase old pointer if exist
|
||||
degree defined as clockwise from negative x-axis.
|
||||
"""
|
||||
(center_x, center_y, angle, inner_radius, outer_radius,
|
||||
outer_color, pointer_color, origin_color, line_width) = self.all
|
||||
pointer_color = color or pointer_color
|
||||
if self.figure != []:
|
||||
for figure in self.figure:
|
||||
self.graph_elem.DeleteFigure(figure)
|
||||
self.figure = []
|
||||
d = degree - 90
|
||||
self.all[2] = degree
|
||||
dx1 = int(2 * inner_radius * math.sin(d / 180 * math.pi))
|
||||
dy1 = int(2 * inner_radius * math.cos(d / 180 * math.pi))
|
||||
dx2 = int(outer_radius * math.sin(d / 180 * math.pi))
|
||||
dy2 = int(outer_radius * math.cos(d / 180 * math.pi))
|
||||
self.figure.append(self.graph_elem.DrawLine((center_x - dx1, center_y - dy1),
|
||||
(center_x + dx2, center_y + dy2),
|
||||
color=pointer_color, width=line_width))
|
||||
self.figure.append(self.graph_elem.DrawCircle((center_x, center_y), inner_radius,
|
||||
fill_color=origin_color, line_color=outer_color, line_width=line_width))
|
||||
|
||||
def move(self, delta_x, delta_y):
|
||||
"""
|
||||
Move pointer with delta x and delta y
|
||||
"""
|
||||
if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)):
|
||||
raise ValueError
|
||||
self.all[:2] = [self.all[0] + delta_x, self.all[1] + delta_y]
|
||||
for figure in self.figure:
|
||||
self.graph_elem.MoveFigure(figure, delta_x, delta_y)
|
||||
|
||||
class Tick():
|
||||
"""
|
||||
Create tick on click for minor tick, also for major tick
|
||||
All angles defined as clockwise from negative x-axis.
|
||||
"""
|
||||
|
||||
def __init__(self, center_x=0, center_y=0, start_radius=90, stop_radius=100,
|
||||
start_angle=0, stop_angle=360, step=6, line_color='black', line_width=2, graph_elem=None):
|
||||
|
||||
instance = Gauge.mapping(isinstance, [center_x, center_y, start_radius,
|
||||
stop_radius, start_angle, stop_angle, step, line_width],
|
||||
(int, float)) + [Gauge.mapping(isinstance, line_color, (list, str))]
|
||||
if False in instance:
|
||||
raise ValueError
|
||||
start_angle, stop_angle = Gauge.limit(start_angle), Gauge.limit(stop_angle)
|
||||
self.all = [center_x, center_y, start_radius, stop_radius,
|
||||
start_angle, stop_angle, step, line_color, line_width]
|
||||
self.figure = []
|
||||
self.graph_elem = graph_elem
|
||||
|
||||
self.new()
|
||||
|
||||
def new(self):
|
||||
"""
|
||||
Draw ticks on clock
|
||||
"""
|
||||
(x, y, start_radius, stop_radius, start_angle, stop_angle, step,
|
||||
line_color, line_width) = self.all
|
||||
start_angle, stop_angle = (180 - start_angle, 180 - stop_angle
|
||||
) if stop_angle < start_angle else (180 - stop_angle, 180 - start_angle)
|
||||
for i in range(start_angle, stop_angle + 1, step):
|
||||
start_x = x + start_radius * math.cos(i / 180 * math.pi)
|
||||
start_y = y + start_radius * math.sin(i / 180 * math.pi)
|
||||
stop_x = x + stop_radius * math.cos(i / 180 * math.pi)
|
||||
stop_y = y + stop_radius * math.sin(i / 180 * math.pi)
|
||||
self.figure.append(self.graph_elem.DrawLine((start_x, start_y),
|
||||
(stop_x, stop_y), color=line_color, width=line_width))
|
||||
|
||||
def move(self, delta_x, delta_y):
|
||||
"""
|
||||
Move ticks by delta x and delta y
|
||||
"""
|
||||
if False in Gauge.mapping(isinstance, [delta_x, delta_y], (int, float)):
|
||||
raise ValueError
|
||||
self.all[0] += delta_x
|
||||
self.all[1] += delta_y
|
||||
for figure in self.figure:
|
||||
self.graph_elem.MoveFigure(figure, delta_x, delta_y)
|
||||
|
||||
"""
|
||||
Create Gauge
|
||||
All angles defined as count clockwise from negative x-axis.
|
||||
Should create instance of clock, pointer, minor tick and major tick first.
|
||||
"""
|
||||
def __init__(self, center=(0, 0), start_angle=0, stop_angle=180, major_tick_width=5, minor_tick_width=2,major_tick_start_radius=90, major_tick_stop_radius=100, minor_tick_step=5, major_tick_step=30, clock_radius=100, pointer_line_width=5, pointer_inner_radius=10, pointer_outer_radius=75, pointer_color='white', pointer_origin_color='black', pointer_outer_color='white', pointer_angle=0, degree=0, clock_color='white', major_tick_color='black', minor_tick_color='black', minor_tick_start_radius=90, minor_tick_stop_radius=100, graph_elem=None):
|
||||
|
||||
self.clock = Gauge.Clock(start_angle=start_angle, stop_angle=stop_angle, fill_color=clock_color, radius=clock_radius, graph_elem=graph_elem)
|
||||
self.minor_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=minor_tick_width, line_color=minor_tick_color, start_radius=minor_tick_start_radius, stop_radius=minor_tick_stop_radius, graph_elem=graph_elem, step=minor_tick_step)
|
||||
self.major_tick = Gauge.Tick(start_angle=start_angle, stop_angle=stop_angle, line_width=major_tick_width, start_radius=major_tick_start_radius, stop_radius=major_tick_stop_radius, step=major_tick_step, line_color=major_tick_color, graph_elem=graph_elem)
|
||||
self.pointer = Gauge.Pointer(angle=pointer_angle, inner_radius=pointer_inner_radius, outer_radius=pointer_outer_radius, pointer_color=pointer_color, outer_color=pointer_outer_color, origin_color=pointer_origin_color, line_width=pointer_line_width, graph_elem=graph_elem)
|
||||
|
||||
self.center_x, self.center_y = self.center = center
|
||||
self.degree = degree
|
||||
self.dx = self.dy = 1
|
||||
|
||||
def move(self, delta_x, delta_y):
|
||||
"""
|
||||
Move gauge to move all componenets in gauge.
|
||||
"""
|
||||
self.center_x, self.center_y =self.center = (
|
||||
self.center_x+delta_x, self.center_y+delta_y)
|
||||
if self.clock:
|
||||
self.clock.move(delta_x, delta_y)
|
||||
if self.minor_tick:
|
||||
self.minor_tick.move(delta_x, delta_y)
|
||||
if self.major_tick:
|
||||
self.major_tick.move(delta_x, delta_y)
|
||||
if self.pointer:
|
||||
self.pointer.move(delta_x, delta_y)
|
||||
|
||||
def change(self, degree=None, step=1, pointer_color=None):
|
||||
"""
|
||||
Rotation of pointer
|
||||
call it with degree and step to set initial options for rotation.
|
||||
Without any option to start rotation.
|
||||
"""
|
||||
if self.pointer:
|
||||
if degree != None:
|
||||
self.pointer.stop_degree = degree
|
||||
self.pointer.step = step if self.pointer.all[2] < degree else -step
|
||||
return True
|
||||
now = self.pointer.all[2]
|
||||
step = self.pointer.step
|
||||
new_degree = now + step
|
||||
if ((step > 0 and new_degree < self.pointer.stop_degree) or
|
||||
(step < 0 and new_degree > self.pointer.stop_degree)):
|
||||
self.pointer.new(degree=new_degree, color=pointer_color)
|
||||
return False
|
||||
else:
|
||||
self.pointer.new(degree=self.pointer.stop_degree, color=pointer_color)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')):
|
||||
""" Returns a human readable string reprentation of bytes"""
|
||||
return str(bytes) + ' ' + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:])
|
||||
|
||||
|
||||
def update_window(window):
|
||||
particians = psutil.disk_partitions()
|
||||
for count, part in enumerate(particians):
|
||||
mount = part[0]
|
||||
try:
|
||||
usage = psutil.disk_usage(mount)
|
||||
window[('-NAME-', mount)].update(mount)
|
||||
# window[('-PROG-', mount)].update_bar(int(usage.percent))
|
||||
window[('-%-', mount)].update(f'{usage.percent}%')
|
||||
window[('-STATS-', mount)].update(f'{human_size(usage.used)} / {human_size(usage.total)} = {human_size(usage.free)} free')
|
||||
gauge = Gauge(pointer_color=window[('-GRAPH-', mount)].metadata,
|
||||
clock_color=window[('-GRAPH-', mount)].metadata,
|
||||
major_tick_color=sg.theme_input_background_color(),
|
||||
minor_tick_color=sg.theme_input_text_color(),
|
||||
pointer_outer_color=sg.theme_input_background_color(),
|
||||
major_tick_start_radius=gsize[1] - 10,
|
||||
minor_tick_start_radius=gsize[1] - 10,
|
||||
minor_tick_stop_radius=gsize[1] - 5,
|
||||
major_tick_stop_radius=gsize[1] - 5,
|
||||
clock_radius=gsize[1] - 5,
|
||||
pointer_outer_radius=gsize[1] - 5,
|
||||
major_tick_step=30,
|
||||
minor_tick_step=15,
|
||||
pointer_line_width=3,
|
||||
pointer_inner_radius=10,
|
||||
graph_elem=window[('-GRAPH-', mount)])
|
||||
gauge.change(degree=0)
|
||||
gauge.change(degree=180 * usage.percent / 100, step=180)
|
||||
gauge.change()
|
||||
except KeyError as e: # A key error means a new drive was added
|
||||
print('Got a key error, so a new drive was added. Window will restart')
|
||||
return False
|
||||
except BaseException as e:
|
||||
print(e)
|
||||
|
||||
|
||||
|
||||
return True
|
||||
|
||||
def create_window(location):
|
||||
layout = [[sg.Text('Drive Status', font='Any 16')]]
|
||||
|
||||
# Add a row for every partician that has a bar graph and text stats
|
||||
particians = psutil.disk_partitions()
|
||||
for count, part in enumerate(particians):
|
||||
mount = part[0]
|
||||
try:
|
||||
bar_color = sg.theme_progress_bar_color()
|
||||
this_color = BAR_COLORS[count % len(BAR_COLORS)]
|
||||
usage = psutil.disk_usage(mount)
|
||||
stats_info = f'{human_size(usage.used)} / {human_size(usage.total)} = {human_size(usage.free)} free'
|
||||
layout += [[sg.Text(mount, size=(3, 1), key=('-NAME-', mount)),
|
||||
sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key=('-GRAPH-', mount), metadata=this_color),
|
||||
# sg.ProgressBar(100, 'h', size=(10, 15), key=('-PROG-', mount), bar_color=(this_color, bar_color[1])),
|
||||
sg.Text(f'{usage.percent}%', size=(6, 1), key=('-%-', mount)), sg.T(stats_info, size=(30, 1), key=('-STATS-', mount)),
|
||||
]]
|
||||
except:
|
||||
pass
|
||||
layout += [[sg.Text('Refresh', font='Any 8', key='-REFRESH-', enable_events=True), sg.Text('❎', enable_events=True, key='Exit Text')]]
|
||||
|
||||
# ---------------- Create Window ----------------
|
||||
window = sg.Window('Drive Status Widget', layout, location=location, keep_on_top=True, grab_anywhere=True, no_titlebar=True, alpha_channel=ALPHA, use_default_focus=False,
|
||||
finalize=True)
|
||||
return window
|
||||
|
||||
def main(location):
|
||||
# Turn off the popups because key errors are normal in this program.
|
||||
# Will get a key error is a new drive is added. Want to get the key error as an exception.
|
||||
sg.set_options(suppress_error_popups=True, suppress_raise_key_errors=False, suppress_key_guessing=True)
|
||||
sg.theme(THEME)
|
||||
|
||||
window = create_window(location)
|
||||
|
||||
update_window(window) # sets the progress bars
|
||||
|
||||
# ---------------- Event Loop ----------------
|
||||
while True:
|
||||
event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
|
||||
if event == sg.WIN_CLOSED or event.startswith('Exit'):
|
||||
break
|
||||
if not update_window(window):
|
||||
window.close()
|
||||
window = create_window(location)
|
||||
update_window(window)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 1:
|
||||
location = sys.argv[1].split(',')
|
||||
location = (int(location[0]), int(location[1]))
|
||||
else:
|
||||
location = (None, None)
|
||||
main(location)
|
||||
|
|
@ -150,6 +150,8 @@ def main():
|
|||
while True:
|
||||
event, values = window.read(timeout=1000*60*60) # wake every hour
|
||||
if event == sg.WIN_CLOSED or event == 'Exit':
|
||||
if event == 'Exit':
|
||||
sg.user_settings_set_entry('-location-', window.current_location())
|
||||
break
|
||||
if event == 'Add Package':
|
||||
window.metadata += 1
|
||||
|
|
|
@ -121,7 +121,7 @@ def main():
|
|||
if new_count is not None:
|
||||
counter = int(new_count)
|
||||
elif event == 'Choose Title':
|
||||
new_title = sg.popup_get_text('Choose a title for your counter', default_text=sg.user_settings_get_entry('-title-', ''), location=window.current_location(), keep_on_top=True)
|
||||
new_title = sg.popup_get_text('Choose a title for your counter', default_text=sg.user_settings_get_entry('-title-', ''), location=window.current_location(), )
|
||||
if new_title is not None:
|
||||
window['-TITLE-'].update(new_title)
|
||||
sg.user_settings_set_entry('-title-', new_title)
|
||||
|
@ -134,7 +134,7 @@ def main():
|
|||
# this is result of hacking code down to 99 lines in total. Not tried it before. Interesting test.
|
||||
_, window = window.close(), make_window(loc)
|
||||
elif event == 'Set Main Font':
|
||||
font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-main number font-'), keep_on_top=True, location=window.current_location())
|
||||
font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-main number font-'), keep_on_top=False, location=window.current_location())
|
||||
if font:
|
||||
sg.user_settings_set_entry('-main number font-', font)
|
||||
_, window = window.close(), make_window(loc)
|
||||
|
@ -164,7 +164,7 @@ def main():
|
|||
if sound_file is not None:
|
||||
sg.user_settings_set_entry('-sound file-', sound_file)
|
||||
elif event =='Show Settings':
|
||||
sg.Print(sg.UserSettings._default_for_function_interface)
|
||||
sg.popup_scrolled(sg.UserSettings._default_for_function_interface, location=window.current_location())
|
||||
|
||||
sg.user_settings_set_entry('-counter-', counter)
|
||||
|
||||
|
@ -172,4 +172,5 @@ def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sg.set_options(keep_on_top=True)
|
||||
main()
|
|
@ -51,7 +51,7 @@ class Gauge():
|
|||
: Return
|
||||
Addition result for number1 and number2.
|
||||
"""
|
||||
return number1 + number1
|
||||
return number1 + number2
|
||||
|
||||
def limit(number):
|
||||
"""
|
||||
|
|
|
@ -30,7 +30,7 @@ def main(location):
|
|||
graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-', enable_events=True)
|
||||
layout = [[graph]]
|
||||
|
||||
window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
|
||||
window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
|
||||
|
||||
|
||||
while True: # Event Loop
|
||||
|
@ -43,7 +43,9 @@ def main(location):
|
|||
text_id2 = graph.draw_text(f'{human_size(ram.used)} used', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0])
|
||||
|
||||
event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
|
||||
if event == sg.WIN_CLOSED or event == 'Exit':
|
||||
if event in (sg.WIN_CLOSED, 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT):
|
||||
if event != sg.WIN_CLOSED:
|
||||
sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting
|
||||
break
|
||||
elif event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
|
@ -59,5 +61,5 @@ if __name__ == '__main__':
|
|||
location = sys.argv[1].split(',')
|
||||
location = (int(location[0]), int(location[1]))
|
||||
else:
|
||||
location = (None, None)
|
||||
location = sg.user_settings_get_entry('-location-', (None, None))
|
||||
main(location)
|
||||
|
|
|
@ -208,11 +208,12 @@ def create_window(win_location):
|
|||
|
||||
layout = [[top_col],
|
||||
[lf_col, rt_col],
|
||||
[bot_col]]
|
||||
[bot_col],
|
||||
[sg.Text(f'{sg.ver} {sg.framework_version} {sys.version}', font=('Arial', 8), background_color=BG_COLOR, text_color=TXT_COLOR, pad=(0,0))]]
|
||||
|
||||
window = sg.Window(layout=layout, title='Weather Widget', margins=(0, 0), finalize=True, location=win_location,
|
||||
element_justification='center', keep_on_top=True, no_titlebar=True, grab_anywhere=True, alpha_channel=ALPHA,
|
||||
right_click_menu=[[''], 'Exit'])
|
||||
right_click_menu=[[''], ['Edit Me', 'Versions', 'Exit',]], enable_close_attempted_event=True)
|
||||
|
||||
for col in ['COL1', 'COL2', 'TopCOL', 'BotCOL', '-QUIT-']:
|
||||
window[col].expand(expand_y=True, expand_x=True)
|
||||
|
@ -261,14 +262,19 @@ def main(refresh_rate, win_location):
|
|||
|
||||
while True: # Event Loop
|
||||
event, values = window.read(timeout=refresh_in_milliseconds)
|
||||
if event in (None, '-QUIT-', 'Exit'):
|
||||
if event in (None, '-QUIT-', 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT):
|
||||
sg.user_settings_set_entry('-win location-', window.current_location()) # The line of code to save the position before exiting
|
||||
break
|
||||
if event == '-CHANGE-':
|
||||
x, y = window.current_location()
|
||||
settings = change_settings(settings, (x + 200, y+50))
|
||||
elif event == '-REFRESH-':
|
||||
sg.popup_quick_message('Refreshing...', keep_on_top=True, background_color='red', text_color='white',
|
||||
auto_close_duration=3, non_blocking=False, location=(win_location[0]+170, win_location[1]+150))
|
||||
auto_close_duration=3, non_blocking=False, location=(window.current_location()[0]+window.size[0]//2-30, window.current_location()[1]+window.size[1]//2-10))
|
||||
elif event == 'Edit Me':
|
||||
sg.execute_editor(__file__)
|
||||
elif event == 'Versions':
|
||||
sg.main_get_debug_data()
|
||||
elif event != sg.TIMEOUT_KEY:
|
||||
sg.Print('Unknown event received\nEvent & values:\n', event, values, location=win_location)
|
||||
|
||||
|
@ -282,5 +288,6 @@ if __name__ == '__main__':
|
|||
win_location = sys.argv[1].split(',')
|
||||
win_location = (int(win_location[0]), int(win_location[1]))
|
||||
else:
|
||||
win_location = (None, None)
|
||||
win_location = sg.user_settings_get_entry('-win location-', (None, None))
|
||||
|
||||
main(refresh_rate=1, win_location=win_location)
|
|
@ -25,34 +25,38 @@ import PySimpleGUI as sg
|
|||
"""
|
||||
|
||||
# ------------------- The Old Way -------------------
|
||||
import PySimpleGUI as sg
|
||||
|
||||
layout = [[sg.Text('My Window')],
|
||||
[sg.InputText(size=(50, 1), key='-FILENAME-'), sg.FileBrowse()],
|
||||
[sg.Button('Go'), sg.Button('Exit')]]
|
||||
|
||||
event1, values1 = sg.Window('Window Title', layout).read(close=True)
|
||||
event1, values1 = sg.Window('Normal Filename', layout).read(close=True)
|
||||
|
||||
# ------------------- The New Way with history -------------------
|
||||
import PySimpleGUI as sg
|
||||
|
||||
layout = [[sg.Text('My Window')],
|
||||
[sg.Combo(sg.user_settings_get_entry('-filenames-', []), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'),
|
||||
sg.FileBrowse()],
|
||||
[sg.Button('Go'), sg.Button('Exit')]]
|
||||
|
||||
event, values = sg.Window('Window Title', layout).read(close=True)
|
||||
event, values = sg.Window('Filename with History', layout).read(close=True)
|
||||
|
||||
if event == 'Go':
|
||||
sg.user_settings_set_entry('-filenames-', list(set(sg.user_settings_get_entry('-filenames-', []) + [values['-FILENAME-'], ])))
|
||||
sg.user_settings_set_entry('-last filename-', values['-FILENAME-'])
|
||||
|
||||
|
||||
# ------------------- The New Way with history and clear -------------------
|
||||
import PySimpleGUI as sg
|
||||
|
||||
layout = [[sg.Text('My Window')],
|
||||
[sg.Combo(sg.user_settings_get_entry('-filenames-', []), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'),
|
||||
sg.FileBrowse()],
|
||||
[sg.Button('Go'), sg.B('Clear'), sg.Button('Exit')]]
|
||||
|
||||
window = sg.Window('Window Title', layout)
|
||||
window = sg.Window('Filename History Clearable', layout)
|
||||
|
||||
while True:
|
||||
event, values = window.read()
|
||||
|
|
Loading…
Reference in New Issue