diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 3ba13e0ce..000000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1 +0,0 @@
-blank_issues_enabled: false
diff --git a/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md b/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md
index d8e2f7446..65b5bfb5c 100644
--- a/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md
+++ b/.github/ISSUE_TEMPLATE/issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md
@@ -1,100 +1,35 @@
---
-name: Issue Form - **Must fill in this form**
+name: Issue Form - Must fill in this form with every new issue submitted
about: This form contains the information needed to help you solve your problem
-title: "[ Enhancement/Bug/Question] "
+title: "[ Enhancement/Bug/Question] My problem is..."
labels: ''
assignees: ''
---
-### Type of Issue (Enhancement, Error, Bug, Question)
+### Type of Issues (Enhancement, Error, Bug, Question)
+### Operating System
-----------------------------------------
+### Python version
-#### Operating System
+### PySimpleGUI Port and Version
+### Your Experience Levels In Months or Years
+_________ Python programming experience
+_________ Programming experience overall
+_________ Have used another Python GUI Framework (tkiner, Qt, etc) previously (yes/no is fine)?
-#### PySimpleGUI Port (tkinter, Qt, Wx, Web)
+### You have completed these steps:
-
-
-----------------------------------------
-
-## Versions
-
-### NOTE - PSG4 is no longer supported
-
-Please try **Version 6** if you're running **Version 4**.
-
-
-Version information can be obtained by calling `sg.main_get_debug_data()`
-Or you can print each version shown in ()
-
-
-#### Python version (`sg.sys.version`)
-
-
-
-#### PySimpleGUI Version (`sg.__version__`)
-
-
-#### GUI Version (tkinter (`sg.tclversion_detailed`), PySide2, WxPython, Remi)
-
-
-
----------------------
-
-#### Your Experience In Months or Years (optional)
-
-Years Python programming experience
-
-Years Programming experience overall
-
-Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)
-
-Anything else you think would be helpful?
-
-
----------------------
-
-#### Troubleshooting
-
-These items may solve your problem. Please check those you've done by changing - [ ] to - [X]
-
-- [ ] Searched main docs for your problem [PySimpleGUI Documenation](https://docs.PySimpleGUI.com)
-- [ ] Looked for Demo Programs that are similar to your goal. It is recommend you use the Demo Browser! [Demo Programs](Demos.PySimpleGUI.com)
-- [ ] None of your GUI code was generated by an AI algorithm like GPT
-- [ ] If not tkinter - looked for Demo Programs for specific port
-- [ ] For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)
+- [ ] Read instructions on how to file an Issue
+- [ ] Searched through main docs http://www.PySimpleGUI.org for your problem
+- [ ] Searched through the readme for your specific port if not PySimpleGUI (Qt, WX, Remi)
+- [ ] Looked for Demo Programs that are similar to your goal http://www.PySimpleGUI.com
+- [ ] Note that there are also Demo Programs under each port on GitHub
- [ ] Run your program outside of your debugger (from a command line)
-- [ ] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.com
-- [ ] Upgraded to the latest release of PySimpleGUI on PyPI (Version 6)
-
-
-#### Detailed Description
-
-
-
-
-#### Code To Duplicate
-
-A **short** program that isolates and demonstrates the problem (Do not paste your massive program, but instead 10-20 lines that clearly show the problem)
-
-This pre-formatted code block is all set for you to paste in your bit of code:
-
-```python
-
-# Paste your code here
-
-
-```
-
-#### Screenshot, Sketch, or Drawing
-
----------------------
+- [ ] Searched through Issues (open and closed) to see if already reported
-### Watcha Makin?
-If you care to share something about your project, it would be awesome to hear what you're building.
+### Code or partial code causing the problem
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
index d7deb2407..20f25f0ce 100644
--- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
@@ -1,3 +1,16 @@
## Pull Request Instructions
-**Pull requests are not currently accepted for the project including the core PySimpleGUI code, the Demo Programs and documentation **
+**Pull requests are not currently accepted for for core code which are these files:**
+
+* PySimpleGUI.py
+* PySimpleGUIQt.py
+* PySimpleGUIWx.py
+* PySimpleGUIWeb.py
+
+The bandwidth required to review and merge these changes simply isn't there. Because PySimpleGUI core files are a single file,
+ALL submitted pull requests required a manual merge of the code.
+
+If you have code that you believe will fix a problem in the core code, post it in the Issue that discusses the problem.
+This has worked well in the past as it enables the community to see the proposed changes.
+
+Pull Requests for the Demo Files are being accepted and are welcomed.
diff --git a/.github/workflows/close_prs.yml b/.github/workflows/close_prs.yml
deleted file mode 100644
index 73f50c1f4..000000000
--- a/.github/workflows/close_prs.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-name: Auto Close Pull Requests
-
-on:
- pull_request:
- types:
- - opened
- - reopened
-
-jobs:
- close-pr:
- runs-on: ubuntu-latest
-
- steps:
- - name: Check Out Repository
- uses: actions/checkout@v2
-
- - name: Close Pull Request
- run: |
- gh pr close ${{ github.event.pull_request.number }} --comment "Hi there!
- Thank you for your interest in contributing to PySimpleGUI. However, we do not accept pull requests at this time.
- (Refer to CONTRIBUTING.md)
-
- Please open an issue instead and we'll be happy to discuss it with you. :D"
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
- # - name: Error out
- # run:
- # exit 1
- # with this commented, when a pr is closed it has a checkmark. if you'd prefer it to have an X, uncomment the code above ^^^
-
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 0d20b6487..000000000
--- a/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/images/ButtonGraphics/Exit.png b/ButtonGraphics/Exit.png
similarity index 100%
rename from images/ButtonGraphics/Exit.png
rename to ButtonGraphics/Exit.png
diff --git a/images/ButtonGraphics/Loop.png b/ButtonGraphics/Loop.png
similarity index 100%
rename from images/ButtonGraphics/Loop.png
rename to ButtonGraphics/Loop.png
diff --git a/images/ButtonGraphics/Next.png b/ButtonGraphics/Next.png
similarity index 100%
rename from images/ButtonGraphics/Next.png
rename to ButtonGraphics/Next.png
diff --git a/images/ButtonGraphics/Pause.png b/ButtonGraphics/Pause.png
similarity index 100%
rename from images/ButtonGraphics/Pause.png
rename to ButtonGraphics/Pause.png
diff --git a/images/ButtonGraphics/Play.png b/ButtonGraphics/Play.png
similarity index 100%
rename from images/ButtonGraphics/Play.png
rename to ButtonGraphics/Play.png
diff --git a/images/ButtonGraphics/Restart.png b/ButtonGraphics/Restart.png
similarity index 100%
rename from images/ButtonGraphics/Restart.png
rename to ButtonGraphics/Restart.png
diff --git a/images/ButtonGraphics/Rewind.png b/ButtonGraphics/Rewind.png
similarity index 100%
rename from images/ButtonGraphics/Rewind.png
rename to ButtonGraphics/Rewind.png
diff --git a/images/ButtonGraphics/RobotBack.png b/ButtonGraphics/RobotBack.png
similarity index 100%
rename from images/ButtonGraphics/RobotBack.png
rename to ButtonGraphics/RobotBack.png
diff --git a/images/ButtonGraphics/RobotForward.png b/ButtonGraphics/RobotForward.png
similarity index 100%
rename from images/ButtonGraphics/RobotForward.png
rename to ButtonGraphics/RobotForward.png
diff --git a/images/ButtonGraphics/RobotLeft.png b/ButtonGraphics/RobotLeft.png
similarity index 100%
rename from images/ButtonGraphics/RobotLeft.png
rename to ButtonGraphics/RobotLeft.png
diff --git a/images/ButtonGraphics/RobotRight.png b/ButtonGraphics/RobotRight.png
similarity index 100%
rename from images/ButtonGraphics/RobotRight.png
rename to ButtonGraphics/RobotRight.png
diff --git a/images/ButtonGraphics/Stop.png b/ButtonGraphics/Stop.png
similarity index 100%
rename from images/ButtonGraphics/Stop.png
rename to ButtonGraphics/Stop.png
diff --git a/images/ButtonGraphics/green.png b/ButtonGraphics/green.png
similarity index 100%
rename from images/ButtonGraphics/green.png
rename to ButtonGraphics/green.png
diff --git a/images/ButtonGraphics/green30.png b/ButtonGraphics/green30.png
similarity index 100%
rename from images/ButtonGraphics/green30.png
rename to ButtonGraphics/green30.png
diff --git a/images/ButtonGraphics/orange.png b/ButtonGraphics/orange.png
similarity index 100%
rename from images/ButtonGraphics/orange.png
rename to ButtonGraphics/orange.png
diff --git a/images/ButtonGraphics/orange30.png b/ButtonGraphics/orange30.png
similarity index 100%
rename from images/ButtonGraphics/orange30.png
rename to ButtonGraphics/orange30.png
diff --git a/images/ButtonGraphics/red.png b/ButtonGraphics/red.png
similarity index 100%
rename from images/ButtonGraphics/red.png
rename to ButtonGraphics/red.png
diff --git a/images/ButtonGraphics/red30.png b/ButtonGraphics/red30.png
similarity index 100%
rename from images/ButtonGraphics/red30.png
rename to ButtonGraphics/red30.png
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index cc30e198a..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## Contributing to PySimpleGUI
-
-We are happy to receive issues describing bug reports and feature requests! If your bug report relates to a security vulnerability, please do not file a public issue, and please instead reach out to us at issues@PySimpleGUI.com.
-
-We do not accept (and do not wish to receive) contributions of user-created or third-party code, including patches, pull requests, or code snippets incorporated into submitted issues. Please do not send us any such code! Bug reports and feature requests should not include any source code.
-
-If you nonetheless submit any user-created or third-party code to us, (1) you assign to us all rights and title in or relating to the code; and (2) to the extent any such assignment is not fully effective, you hereby grant to us a royalty-free, perpetual, irrevocable, worldwide, unlimited, sublicensable, transferrable license under all intellectual property rights embodied therein or relating thereto, to exploit the code in any manner we choose, including to incorporate the code into PySimpleGUI and to redistribute it under any terms at our discretion.
diff --git a/Chess/ChessPiecesArray.png b/Chess/ChessPiecesArray.png
new file mode 100644
index 000000000..101c0c9d6
Binary files /dev/null and b/Chess/ChessPiecesArray.png differ
diff --git a/Chess/Demo_Chess_AGAINST_AI.py b/Chess/Demo_Chess_AGAINST_AI.py
new file mode 100644
index 000000000..cf6cbc995
--- /dev/null
+++ b/Chess/Demo_Chess_AGAINST_AI.py
@@ -0,0 +1,233 @@
+import PySimpleGUI as sg
+import os
+import sys
+import chess
+import chess.pgn
+import copy
+import chess.uci
+
+CHESS_PATH = '.' # path to the chess pieces
+
+BLANK = 0 # piece names
+PAWNB = 1
+KNIGHTB = 2
+BISHOPB = 3
+ROOKB = 4
+KINGB = 5
+QUEENB = 6
+PAWNW = 7
+KNIGHTW = 8
+BISHOPW = 9
+ROOKW = 10
+KINGW = 11
+QUEENW = 12
+
+initial_board = [[ROOKB, KNIGHTB, BISHOPB, QUEENB, KINGB, BISHOPB, KNIGHTB, ROOKB],
+ [PAWNB, ] * 8,
+ [BLANK, ] * 8,
+ [BLANK, ] * 8,
+ [BLANK, ] * 8,
+ [BLANK, ] * 8,
+ [PAWNW, ] * 8,
+ [ROOKW, KNIGHTW, BISHOPW, QUEENW, KINGW, BISHOPW, KNIGHTW, ROOKW]]
+
+blank = os.path.join(CHESS_PATH, 'blank.png')
+bishopB = os.path.join(CHESS_PATH, 'nbishopb.png')
+bishopW = os.path.join(CHESS_PATH, 'nbishopw.png')
+pawnB = os.path.join(CHESS_PATH, 'npawnb.png')
+pawnW = os.path.join(CHESS_PATH, 'npawnw.png')
+knightB = os.path.join(CHESS_PATH, 'nknightb.png')
+knightW = os.path.join(CHESS_PATH, 'nknightw.png')
+rookB = os.path.join(CHESS_PATH, 'nrookb.png')
+rookW = os.path.join(CHESS_PATH, 'nrookw.png')
+queenB = os.path.join(CHESS_PATH, 'nqueenb.png')
+queenW = os.path.join(CHESS_PATH, 'nqueenw.png')
+kingB = os.path.join(CHESS_PATH, 'nkingb.png')
+kingW = os.path.join(CHESS_PATH, 'nkingw.png')
+
+images = {BISHOPB: bishopB, BISHOPW: bishopW, PAWNB: pawnB, PAWNW: pawnW, KNIGHTB: knightB, KNIGHTW: knightW,
+ ROOKB: rookB, ROOKW: rookW, KINGB: kingB, KINGW: kingW, QUEENB: queenB, QUEENW: queenW, BLANK: blank}
+
+
+def open_pgn_file(filename):
+ pgn = open(filename)
+ first_game = chess.pgn.read_game(pgn)
+ moves = [move for move in first_game.main_line()]
+ return moves
+
+
+def render_square(image, key, location):
+ if (location[0] + location[1]) % 2:
+ color = '#B58863'
+ else:
+ color = '#F0D9B5'
+ return sg.RButton('', image_filename=image, size=(1, 1), button_color=('white', color), pad=(0, 0), key=key)
+
+
+def redraw_board(window, board):
+ for i in range(8):
+ for j in range(8):
+ color = '#B58863' if (i + j) % 2 else '#F0D9B5'
+ piece_image = images[board[i][j]]
+ elem = window.FindElement(key=(i, j))
+ elem.Update(button_color=('white', color),
+ image_filename=piece_image, )
+
+
+def PlayGame():
+ menu_def = [['&File', ['&Open PGN File', 'E&xit']],
+ ['&Help', '&About...'], ]
+
+ # sg.SetOptions(margins=(0,0))
+ sg.ChangeLookAndFeel('GreenTan')
+ # create initial board setup
+ psg_board = copy.deepcopy(initial_board)
+ # the main board display layout
+ board_layout = [[sg.T(' ')] + [sg.T('{}'.format(a), pad=((23, 27), 0), font='Any 13') for a in 'abcdefgh']]
+ # loop though board and create buttons with images
+ for i in range(8):
+ row = [sg.T(str(8 - i) + ' ', font='Any 13')]
+ for j in range(8):
+ piece_image = images[psg_board[i][j]]
+ row.append(render_square(piece_image, key=(i, j), location=(i, j)))
+ row.append(sg.T(str(8 - i) + ' ', font='Any 13'))
+ board_layout.append(row)
+ # add the labels across bottom of board
+ board_layout.append([sg.T(' ')] + [sg.T('{}'.format(a), pad=((23, 27), 0), font='Any 13') for a in 'abcdefgh'])
+
+ # setup the controls on the right side of screen
+ openings = (
+ 'Any', 'Defense', 'Attack', 'Trap', 'Gambit', 'Counter', 'Sicillian', 'English', 'French', 'Queen\'s openings',
+ 'King\'s Openings', 'Indian Openings')
+
+ board_controls = [[sg.RButton('New Game', key='New Game'), sg.RButton('Draw')],
+ [sg.RButton('Resign Game'), sg.RButton('Set FEN')],
+ [sg.RButton('Player Odds'), sg.RButton('Training')],
+ [sg.Drop(openings), sg.Text('Opening/Style')],
+ [sg.CBox('Play As White', key='_white_')],
+ [sg.Drop([2, 3, 4, 5, 6, 7, 8, 9, 10], size=(3, 1), key='_level_'), sg.Text('Difficulty Level')],
+ [sg.Text('Move List')],
+ [sg.Multiline([], do_not_clear=True, autoscroll=True, size=(15, 10), key='_movelist_')],
+ ]
+
+ # layouts for the tabs
+ controls_layout = [[sg.Text('Performance Parameters', font='_ 20')],
+ [sg.T('Put stuff like AI engine tuning parms on this tab')]]
+
+ statistics_layout = [[sg.Text('Statistics', font=('_ 20'))],
+ [sg.T('Game statistics go here?')]]
+
+ board_tab = [[sg.Column(board_layout)]]
+
+ # the main window layout
+ layout = [[sg.Menu(menu_def, tearoff=False)],
+ [sg.TabGroup([[sg.Tab('Board', board_tab),
+ sg.Tab('Controls', controls_layout),
+ sg.Tab('Statistics', statistics_layout)]], title_color='red'),
+ sg.Column(board_controls)],
+ [sg.Text('Click anywhere on board for next move', font='_ 14')]]
+
+ window = sg.Window('Chess',
+ default_button_element_size=(12, 1),
+ auto_size_buttons=False,
+ icon='kingb.ico').Layout(layout)
+
+ filename = sg.PopupGetFile('\n'.join(('To begin, set location of AI EXE file',
+ 'If you have not done so already, download the engine',
+ 'Download the StockFish Chess engine at: https://stockfishchess.org/download/')),
+ file_types=(('Chess AI Engine EXE File', '*.exe'),))
+ if filename is None:
+ sys.exit()
+ engine = chess.uci.popen_engine(filename)
+ engine.uci()
+ info_handler = chess.uci.InfoHandler()
+ engine.info_handlers.append(info_handler)
+
+ board = chess.Board()
+ move_count = 1
+ move_state = move_from = move_to = 0
+ # ---===--- Loop taking in user input --- #
+ while not board.is_game_over():
+
+ if board.turn == chess.WHITE:
+ engine.position(board)
+
+ # human_player(board)
+ move_state = 0
+ while True:
+ button, value = window.Read()
+ if button in (None, 'Exit'):
+ exit()
+ if button == 'New Game':
+ sg.Popup('You have to restart the program to start a new game... sorry....')
+ break
+ psg_board = copy.deepcopy(initial_board)
+ redraw_board(window, psg_board)
+ move_state = 0
+ break
+ level = value['_level_']
+ if type(button) is tuple:
+ if move_state == 0:
+ move_from = button
+ row, col = move_from
+ piece = psg_board[row][col] # get the move-from piece
+ button_square = window.FindElement(key=(row, col))
+ button_square.Update(button_color=('white', 'red'))
+ move_state = 1
+ elif move_state == 1:
+ move_to = button
+ row, col = move_to
+ if move_to == move_from: # cancelled move
+ color = '#B58863' if (row + col) % 2 else '#F0D9B5'
+ button_square.Update(button_color=('white', color))
+ move_state = 0
+ continue
+
+ picked_move = '{}{}{}{}'.format('abcdefgh'[move_from[1]], 8 - move_from[0],
+ 'abcdefgh'[move_to[1]], 8 - move_to[0])
+
+ if picked_move in [str(move) for move in board.legal_moves]:
+ board.push(chess.Move.from_uci(picked_move))
+ else:
+ print('Illegal move')
+ move_state = 0
+ color = '#B58863' if (move_from[0] + move_from[1]) % 2 else '#F0D9B5'
+ button_square.Update(button_color=('white', color))
+ continue
+
+ psg_board[move_from[0]][move_from[1]] = BLANK # place blank where piece was
+ psg_board[row][col] = piece # place piece in the move-to square
+ redraw_board(window, psg_board)
+ move_count += 1
+
+ window.FindElement('_movelist_').Update(picked_move + '\n', append=True)
+
+ break
+ else:
+ engine.position(board)
+ best_move = engine.go(searchmoves=board.legal_moves, depth=level, movetime=(level * 100)).bestmove
+ move_str = str(best_move)
+ from_col = ord(move_str[0]) - ord('a')
+ from_row = 8 - int(move_str[1])
+ to_col = ord(move_str[2]) - ord('a')
+ to_row = 8 - int(move_str[3])
+
+ window.FindElement('_movelist_').Update(move_str + '\n', append=True)
+
+ piece = psg_board[from_row][from_col]
+ psg_board[from_row][from_col] = BLANK
+ psg_board[to_row][to_col] = piece
+ redraw_board(window, psg_board)
+
+ board.push(best_move)
+ move_count += 1
+ sg.Popup('Game over!', 'Thank you for playing')
+
+
+# Download the StockFish Chess engine at: https://stockfishchess.org/download/
+# engine = chess.uci.popen_engine(r'E:\DownloadsE\stockfish-9-win\Windows\stockfish_9_x64.exe')
+# engine.uci()
+# info_handler = chess.uci.InfoHandler()
+# engine.info_handlers.append(info_handler)
+# level = 2
+PlayGame()
diff --git a/Chess/Demo_Chess_Board.py b/Chess/Demo_Chess_Board.py
new file mode 100644
index 000000000..279e0ce1a
--- /dev/null
+++ b/Chess/Demo_Chess_Board.py
@@ -0,0 +1,160 @@
+import PySimpleGUI as sg
+import os
+import chess
+import chess.pgn
+import copy
+import time
+
+button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer')
+
+CHESS_PATH = '.' # path to the chess pieces
+
+BLANK = 0 # piece names
+PAWNB = 1
+KNIGHTB = 2
+BISHOPB = 3
+ROOKB = 4
+KINGB = 5
+QUEENB = 6
+PAWNW = 7
+KNIGHTW = 8
+BISHOPW = 9
+ROOKW = 10
+KINGW = 11
+QUEENW = 12
+
+initial_board = [[ROOKB, KNIGHTB, BISHOPB, KINGB, QUEENB, BISHOPB, KNIGHTB, ROOKB ],
+ [PAWNB,]*8,
+ [BLANK,]*8,
+ [BLANK,]*8,
+ [BLANK,]*8,
+ [BLANK,]*8,
+ [PAWNW,]*8,
+ [ROOKW, KNIGHTW, BISHOPW, KINGW, QUEENW, BISHOPW, KNIGHTW, ROOKW]]
+
+blank = os.path.join(CHESS_PATH, 'blank.png')
+bishopB = os.path.join(CHESS_PATH, 'nbishopb.png')
+bishopW = os.path.join(CHESS_PATH, 'nbishopw.png')
+pawnB = os.path.join(CHESS_PATH, 'npawnb.png')
+pawnW = os.path.join(CHESS_PATH, 'npawnw.png')
+knightB = os.path.join(CHESS_PATH, 'nknightb.png')
+knightW = os.path.join(CHESS_PATH, 'nknightw.png')
+rookB = os.path.join(CHESS_PATH, 'nrookb.png')
+rookW = os.path.join(CHESS_PATH, 'nrookw.png')
+queenB = os.path.join(CHESS_PATH, 'nqueenB.png')
+queenW = os.path.join(CHESS_PATH, 'nqueenW.png')
+kingB = os.path.join(CHESS_PATH, 'nkingb.png')
+kingW = os.path.join(CHESS_PATH, 'nkingw.png')
+
+images = {BISHOPB: bishopB, BISHOPW: bishopW, PAWNB: pawnB, PAWNW: pawnW, KNIGHTB: knightB, KNIGHTW: knightW,
+ ROOKB: rookB, ROOKW: rookW, KINGB: kingB, KINGW: kingW, QUEENB: queenB, QUEENW: queenW, BLANK: blank}
+
+def open_pgn_file(filename):
+ pgn = open(filename)
+ first_game = chess.pgn.read_game(pgn)
+ moves = [move for move in first_game.main_line()]
+ return moves
+
+def render_square(image, key, location):
+ if (location[0] + location[1]) % 2:
+ color = '#B58863'
+ else:
+ color = '#F0D9B5'
+ return sg.RButton('', image_filename=image, size=(1, 1), button_color=('white', color), pad=(0, 0), key=key)
+
+def redraw_board(window, board):
+ for i in range(8):
+ for j in range(8):
+ color = '#B58863' if (i+j) % 2 else '#F0D9B5'
+ piece_image = images[board[i][j]]
+ elem = window.FindElement(key=(i,j))
+ elem.Update(button_color = ('white', color),
+ image_filename=piece_image,)
+
+def PlayGame():
+
+ menu_def = [['&File', ['&Open PGN File', 'E&xit' ]],
+ ['&Help', '&About...'],]
+
+ # sg.SetOptions(margins=(0,0))
+ sg.ChangeLookAndFeel('GreenTan')
+ # create initial board setup
+ board = copy.deepcopy(initial_board)
+ # the main board display layout
+ board_layout = [[sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh']]
+ # loop though board and create buttons with images
+ for i in range(8):
+ row = [sg.T(str(8-i)+' ', font='Any 13')]
+ for j in range(8):
+ piece_image = images[board[i][j]]
+ row.append(render_square(piece_image, key=(i,j), location=(i,j)))
+ row.append(sg.T(str(8-i)+' ', font='Any 13'))
+ board_layout.append(row)
+ # add the labels across bottom of board
+ board_layout.append([sg.T(' ')] + [sg.T('{}'.format(a), pad=((23,27),0), font='Any 13') for a in 'abcdefgh'])
+
+ # setup the controls on the right side of screen
+ openings = ('Any', 'Defense', 'Attack', 'Trap', 'Gambit','Counter', 'Sicillian', 'English','French', 'Queen\'s openings', 'King\'s Openings','Indian Openings')
+
+ board_controls = [[sg.RButton('New Game', key='Open PGN File'), sg.RButton('Draw')],
+ [sg.RButton('Resign Game'), sg.RButton('Set FEN')],
+ [sg.RButton('Player Odds'),sg.RButton('Training') ],
+ [sg.Drop(openings),sg.Text('Opening/Style')],
+ [sg.CBox('Play a White', key='_white_')],
+ [sg.Text('Move List')],
+ [sg.Multiline([], do_not_clear=True, autoscroll=True, size=(15,10),key='_movelist_')],]
+
+ # layouts for the tabs
+ controls_layout = [[sg.Text('Performance Parameters', font='_ 20')],
+ [sg.T('Put stuff like AI engine tuning parms on this tab')]]
+
+ statistics_layout = [[sg.Text('Statistics', font=('_ 20'))],
+ [sg.T('Game statistics go here?')]]
+
+ board_tab = [[sg.Column(board_layout)]]
+
+ # the main window layout
+ layout = [[sg.Menu(menu_def, tearoff=False)],
+ [sg.TabGroup([[sg.Tab('Board',board_tab),
+ sg.Tab('Controls', controls_layout),
+ sg.Tab('Statistics', statistics_layout)]], title_color='red'),
+ sg.Column(board_controls)],
+ [sg.Text('Click anywhere on board for next move', font='_ 14')]]
+
+ window = sg.Window('Chess', default_button_element_size=(12,1), auto_size_buttons=False, icon='kingb.ico').Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ i = 0
+ moves = None
+ while True:
+ button, value = window.Read()
+ if button in (None, 'Exit'):
+ break
+ if button == 'Open PGN File':
+ filename = sg.PopupGetFile('', no_window=True)
+ if filename is not None:
+ moves = open_pgn_file(filename)
+ i = 0
+ board = copy.deepcopy(initial_board)
+ window.FindElement('_movelist_').Update(value='')
+ if button == 'About...':
+ sg.Popup('Powerd by Engine Kibitz Chess Engine')
+ if type(button) is tuple and moves is not None and i < len(moves):
+ move = moves[i] # get the current move
+ window.FindElement('_movelist_').Update(value='{} {}\n'.format(i+1, str(move)), append=True)
+ move_from = move.from_square # parse the move-from and move-to squares
+ move_to = move.to_square
+ row, col = move_from // 8, move_from % 8
+ piece = board[row][col] # get the move-from piece
+ button = window.FindElement(key=(row,col))
+ for x in range(3):
+ button.Update(button_color = ('white' , 'red' if x % 2 else 'white'))
+ window.Refresh()
+ time.sleep(.05)
+ board[row][col] = BLANK # place blank where piece was
+ row, col = move_to // 8, move_to % 8 # compute move-to square
+ board[row][col] = piece # place piece in the move-to square
+ redraw_board(window, board)
+ i += 1
+
+PlayGame()
\ No newline at end of file
diff --git a/Chess/bishopb.png b/Chess/bishopb.png
new file mode 100644
index 000000000..453cb3235
Binary files /dev/null and b/Chess/bishopb.png differ
diff --git a/Chess/bishopw.png b/Chess/bishopw.png
new file mode 100644
index 000000000..26dae01cf
Binary files /dev/null and b/Chess/bishopw.png differ
diff --git a/Chess/blank.png b/Chess/blank.png
new file mode 100644
index 000000000..09ffa6d69
Binary files /dev/null and b/Chess/blank.png differ
diff --git a/Chess/game.pgn b/Chess/game.pgn
new file mode 100644
index 000000000..1dda9fbd5
--- /dev/null
+++ b/Chess/game.pgn
@@ -0,0 +1,36 @@
+[Event "Wch U12"]
+[Site "Duisburg"]
+[Date "1992.??.??"]
+[Round "1"]
+[White "Malakhov, Vladimir"]
+[Black "Ab Rahman, M."]
+[Result "1-0"]
+[WhiteElo ""]
+[BlackElo ""]
+[ECO "A05"]
+
+1.Nf3 Nf6 2.b3 g6 3.Bb2 Bg7 4.g3 d6 5.Bg2 O-O 6.O-O c6 7.d3 e5 8.c4 Ne8 9.Nbd2 f5
+10.Qc2 Na6 11.c5 Nxc5 12.Nxe5 Qe7 13.d4 Na6 14.Qc4+ Kh8 15.Nef3 Be6 16.Qc3 f4
+17.gxf4 Rxf4 18.Qe3 Rf8 19.Ng5 Nec7 20.Nc4 Rae8 21.Nxe6 Qxe6 22.Qxe6 Rxe6
+23.e3 d5 24.Ne5 g5 25.Ba3 Rff6 26.Bh3 Re8 27.Bd7 Rd8 28.Be7 Rxd7 29.Bxf6 1-0
+
+
+[Event "Wch U12"]
+[Site "Duisburg"]
+[Date "1992.??.??"]
+[Round "2"]
+[White "Malakhov, Vladimir"]
+[Black "Berescu, Alin"]
+[Result "1-0"]
+[WhiteElo ""]
+[BlackElo ""]
+[ECO "D05"]
+
+1.d4 Nf6 2.Nd2 d5 3.Ngf3 e6 4.e3 c5 5.c3 Nbd7 6.Bd3 Bd6 7.O-O O-O 8.Re1 b6
+9.e4 dxe4 10.Nxe4 Be7 11.Ne5 Bb7 12.Ng5 g6 13.Qe2 Nxe5 14.dxe5 Nh5 15.Ne4 Qd5
+16.f4 Rfd8 17.Bc2 Qc6 18.Be3 Rd7 19.Rad1 Rad8 20.Rxd7 Rxd7 21.Nd2 Ng7 22.Be4 Qc8
+23.g4 Qd8 24.Bxb7 Rxb7 25.Ne4 Rd7 26.c4 h5 27.h3 h4 28.Kh2 Ne8 29.f5 Qc7
+30.Bf4 Rd4 31.Qf2 Rxc4 32.f6 Qb7 33.Ng5 Bf8 34.b3 Rc3 35.Qd2 Rf3 36.Nxf3 Qxf3
+37.Qe3 Qd5 38.Qe4 Qd7 39.Qf3 Nc7 40.Rd1 Nd5 41.Bg5 Qc7 42.Re1 b5 43.Qd1 c4
+44.Qc1 Bb4 45.Bd2 Bxd2 46.Qxd2 Nxf6 47.bxc4 bxc4 48.Qd6 Qa5 49.Rf1 Nd5 50.Qd7 Qd2+
+51.Kh1 f5 52.exf6 1-0
diff --git a/Chess/kingb.ico b/Chess/kingb.ico
new file mode 100644
index 000000000..6e6030b33
Binary files /dev/null and b/Chess/kingb.ico differ
diff --git a/Chess/kingb.png b/Chess/kingb.png
new file mode 100644
index 000000000..0d94a1c29
Binary files /dev/null and b/Chess/kingb.png differ
diff --git a/Chess/kingw.png b/Chess/kingw.png
new file mode 100644
index 000000000..a4fe68c80
Binary files /dev/null and b/Chess/kingw.png differ
diff --git a/Chess/knightb.png b/Chess/knightb.png
new file mode 100644
index 000000000..8e3d04e6f
Binary files /dev/null and b/Chess/knightb.png differ
diff --git a/Chess/knightw.png b/Chess/knightw.png
new file mode 100644
index 000000000..2d716b15b
Binary files /dev/null and b/Chess/knightw.png differ
diff --git a/Chess/nbishopb.png b/Chess/nbishopb.png
new file mode 100644
index 000000000..c52b6779b
Binary files /dev/null and b/Chess/nbishopb.png differ
diff --git a/Chess/nbishopw.png b/Chess/nbishopw.png
new file mode 100644
index 000000000..ab73bae61
Binary files /dev/null and b/Chess/nbishopw.png differ
diff --git a/Chess/nkingb.png b/Chess/nkingb.png
new file mode 100644
index 000000000..945a4898a
Binary files /dev/null and b/Chess/nkingb.png differ
diff --git a/Chess/nkingw.png b/Chess/nkingw.png
new file mode 100644
index 000000000..6662f3233
Binary files /dev/null and b/Chess/nkingw.png differ
diff --git a/Chess/nknightb.png b/Chess/nknightb.png
new file mode 100644
index 000000000..e28cbb170
Binary files /dev/null and b/Chess/nknightb.png differ
diff --git a/Chess/nknightw.png b/Chess/nknightw.png
new file mode 100644
index 000000000..34da37f91
Binary files /dev/null and b/Chess/nknightw.png differ
diff --git a/Chess/npawnb.png b/Chess/npawnb.png
new file mode 100644
index 000000000..a47983505
Binary files /dev/null and b/Chess/npawnb.png differ
diff --git a/Chess/npawnw.png b/Chess/npawnw.png
new file mode 100644
index 000000000..a05034abb
Binary files /dev/null and b/Chess/npawnw.png differ
diff --git a/Chess/nqueenb.png b/Chess/nqueenb.png
new file mode 100644
index 000000000..54231369c
Binary files /dev/null and b/Chess/nqueenb.png differ
diff --git a/Chess/nqueenw.png b/Chess/nqueenw.png
new file mode 100644
index 000000000..afaab4859
Binary files /dev/null and b/Chess/nqueenw.png differ
diff --git a/Chess/nrookb.png b/Chess/nrookb.png
new file mode 100644
index 000000000..8b18a6f57
Binary files /dev/null and b/Chess/nrookb.png differ
diff --git a/Chess/nrookw.png b/Chess/nrookw.png
new file mode 100644
index 000000000..31522a369
Binary files /dev/null and b/Chess/nrookw.png differ
diff --git a/Chess/pawnb.png b/Chess/pawnb.png
new file mode 100644
index 000000000..c432d38ae
Binary files /dev/null and b/Chess/pawnb.png differ
diff --git a/Chess/pawnw.png b/Chess/pawnw.png
new file mode 100644
index 000000000..e98fae2bd
Binary files /dev/null and b/Chess/pawnw.png differ
diff --git a/Chess/queenb.png b/Chess/queenb.png
new file mode 100644
index 000000000..225f869e9
Binary files /dev/null and b/Chess/queenb.png differ
diff --git a/Chess/queenw.png b/Chess/queenw.png
new file mode 100644
index 000000000..d7341649b
Binary files /dev/null and b/Chess/queenw.png differ
diff --git a/Chess/readme.md b/Chess/readme.md
new file mode 100644
index 000000000..037f51006
--- /dev/null
+++ b/Chess/readme.md
@@ -0,0 +1,16 @@
+# PySimpleGUI-Chess A Chess Game Playback Program
+
+
+
+
+## Introduction
+This is the start of a front-end GUI for an AI engine that plays chess. It simply reads moves the a PGN file and steps through it showing each of the moves on the board.
+
+To play against the AI run the program
+Demo_Chess_AGAINST_AI.py
+
+Locate where the pacakge was installed and run the programs from that folder. You need to run from the installed folder so that the images of the chess pieces are located.
+
+## Home Page (GitHub)
+
+[www.PySimpleGUI.com](www.PySimpleGUI.com)
diff --git a/Chess/requirements.txt b/Chess/requirements.txt
new file mode 100644
index 000000000..5003cd5ff
--- /dev/null
+++ b/Chess/requirements.txt
@@ -0,0 +1,2 @@
+PySimpleGUI==3.9.1
+python-chess==0.23.9
diff --git a/Chess/rookb.png b/Chess/rookb.png
new file mode 100644
index 000000000..b9748e87f
Binary files /dev/null and b/Chess/rookb.png differ
diff --git a/Chess/rookw.png b/Chess/rookw.png
new file mode 100644
index 000000000..a805de496
Binary files /dev/null and b/Chess/rookw.png differ
diff --git a/DemoPrograms old/ButtonClick.wav b/DemoPrograms old/ButtonClick.wav
new file mode 100644
index 000000000..f774f70e4
Binary files /dev/null and b/DemoPrograms old/ButtonClick.wav differ
diff --git a/DemoPrograms old/Color-Guide.png b/DemoPrograms old/Color-Guide.png
new file mode 100644
index 000000000..bd9edbe4a
Binary files /dev/null and b/DemoPrograms old/Color-Guide.png differ
diff --git a/DemoPrograms old/Color-names.png b/DemoPrograms old/Color-names.png
new file mode 100644
index 000000000..f81654f70
Binary files /dev/null and b/DemoPrograms old/Color-names.png differ
diff --git a/DemoPrograms old/Demo_All_Widgets.py b/DemoPrograms old/Demo_All_Widgets.py
new file mode 100644
index 000000000..51d702374
--- /dev/null
+++ b/DemoPrograms old/Demo_All_Widgets.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+sg.ChangeLookAndFeel('GreenTan')
+
+# ------ Menu Definition ------ #
+menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
+ ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
+ ['&Help', '&About...'], ]
+
+# ------ Column Definition ------ #
+column1 = [[sg.Text('Column 1', background_color='lightblue', justification='center', size=(10, 1))],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]
+
+layout = [
+ [sg.Menu(menu_def, tearoff=True)],
+ [sg.Text('(Almost) All widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
+ [sg.Text('Here is some text.... and a place to enter text')],
+ [sg.InputText('This is my text')],
+ [sg.Frame(layout=[
+ [sg.Checkbox('Checkbox', size=(10,1)), sg.Checkbox('My second checkbox!', default=True)],
+ [sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10,1)), sg.Radio('My second Radio!', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
+ [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
+ sg.Multiline(default_text='A second multi-line', size=(35, 3))],
+ [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)),
+ sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
+ [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
+ [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
+ sg.Frame('Labelled Group',[[
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=25),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),
+ sg.Column(column1, background_color='lightblue')]])],
+ [sg.Text('_' * 80)],
+ [sg.Text('Choose A Folder', size=(35, 1))],
+ [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'),
+ sg.InputText('Default Folder'), sg.FolderBrowse()],
+ [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]]
+
+window = sg.Window('Everything bagel', default_element_size=(40, 1), grab_anywhere=False).Layout(layout)
+event, values = window.Read()
+
+sg.Popup('Title',
+ 'The results of the window.',
+ 'The button clicked was "{}"'.format(event),
+ 'The values are', values)
+
+
diff --git a/DemoPrograms old/Demo_Animated_GIFs.py b/DemoPrograms old/Demo_Animated_GIFs.py
new file mode 100644
index 000000000..e6f02868e
--- /dev/null
+++ b/DemoPrograms old/Demo_Animated_GIFs.py
@@ -0,0 +1,65 @@
+import PySimpleGUI as sg
+
+"""
+ Demo_Animated_GIFs.py
+
+ Shows how to:
+ * Use PopupAnimated
+ * Use animated GIF in a custom window layout
+ * Store your GIFs in base64 format inside this source file (copy and paste into your source file)
+
+ The first image that uses PopupAnimated will stop after a few seconds on its own.
+ The remaining images are shown 1 at a time. To move on to the next image, click the current image.
+ If you want to exit before reaching the final image, right click the image and choose 'exit'
+"""
+
+# ---------------------------- Base 64 GIFs ----------------------------
+
+line_boxes = b'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'
+
+
+line_bubbles = b'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'
+
+ring_black_dots = b'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'
+
+ring_gray_segments = b'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'
+
+
+ring_lines = b'R0lGODlh2ADYAKIHAPj4+ODg4MnJyaysrIuLi2NjYzk5Of///yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0NFQTZFMUU5QzBDMTFFMkFFNDdDRTVDRTJCRUM3RTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0NFQTZFMUY5QzBDMTFFMkFFNDdDRTVDRTJCRUM3RTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQ0VBNkUxQzlDMEMxMUUyQUU0N0NFNUNFMkJFQzdFMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQ0VBNkUxRDlDMEMxMUUyQUU0N0NFNUNFMkJFQzdFMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDP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'
+
+
+red_dots_ring = b'R0lGODlhkAHIALMPAM0/QMQfIdRcXtpxc9+EhOahofbf3/vv7+KTlOy4ucIYGv/+/vHNze/Dw8MbHf///yH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjMzOEMxNzM2RTAzMTFFNjg4Mzk5NzdDMkE1QzlDRjIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjMzOEMxNzQ2RTAzMTFFNjg4Mzk5NzdDMkE1QzlDRjIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MzM4QzE3MTZFMDMxMUU2ODgzOTk3N0MyQTVDOUNGMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MzM4QzE3MjZFMDMxMUU2ODgzOTk3N0MyQTVDOUNGMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t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'
+
+blue_dots = b'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'
+
+ring_blue = b'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HGieCTBLWavP5OjocYKR////HI/jXLPc////PJTMVG6EdLTsRJrMBEF1rNb4VK33////+vz8////NFp8NpjaVF5oVJ7EJE9mBHDIdLLE////////OH60O2FxPJLcFCAnHFqBeb/5PKboJEBMHILU////4O/8VLTuDI70lJyh////////RKrkPHKM////////DEJopKq0////rLrMvMjQbK7EfKbMVIiYfKTEVIKMfJKsv8LEhNDlxNLgpMLcpNL8VHaU////PHaXXGZs////lLXR////////PEJM////JDI6vNLkFFaMfIeRHDhGfHp8vNvxNIzJpKKkXI60KYDAi9/5PFhgPGd4lM78j5OUVFhYZK7MVI68XJWmfH+H1ODwXJ7U1NLUaLrc////HE5wHG6oT2Z8dLrRdK7gVJjYBE6E////aLrsb3qE8vb4////V67gLH6sFEJk////GmKYaJq0ebrsPI68////////KEhk////LHKo////////LGKQTKbUOKb4PGKEBFaYrLK8XLrkfLLcVLr4lKKspLLEXIKkfI6cHD5MDIjqDEp0FGaglMjwbLLIbMnxTGqENFhkLI7ZDDxcrMbc1NfcHFR9DFycHIfWbMLp////THyMXKbkLDhIVJOsPE5cHDE6HEhkJGiWXGp0fLTkTJe/XJ+8LFFiDHHBHCAkLEBI////zNHUrM7sXHKE/v7+CP4A/wkcSLCgwYFztrjh4qyBw4cxuAzbMuegxYsYMXrp5KaBM2rfRIka8q3kt0RDEn2j0yAMh05eMsqcKXBXAmcEQn4j0KBOgJ9Af2qb8kZaonRv1rjZRbNpwV0dJ4ia0DOAz6A/c2QNoDXHlF5FeoUYxtTpTC+lGkglcBVrUK1c4+bomiMGkSchusU0e3HOR1EE3GLtKpcr3blz17zKsqYiX4OMGgyZ0BZrnRh0YJxMxJlIrmYx0CFGPKK0Am+hUDwe6MWNM1ENBNchUGQIjDxhprx4oe3FlDBvnhQh0kx06TIjypSJg8pTrb1md3GhNqTyzwYwEkmbMoVDgk5zdv558aJiTqdu7OKgU0AElRXl8Mvgs1fPVtmm0jVbr5OuSJ4pWFRAUwVYxOEJKqigA98DZTxQTw8k3CeTF1zAMIFbeSTyXykS0rRLNxp44k09+DxgoonEQAhdRrnQ8c1b2qSTzhTDrMjXLvTgMwYFGpz4gAvEyGDETIw4kwhQWk2hYRgCrlYQK6EQQ0EoLvz4ozvJLJJRBQ0k4hNcSsbQTIdO1lSPBhT4UqULVbrTBBQXefFGETHINUURLtlYJmtGyMIjm2xyQ0gaegrUDRfSwJWDNnhysGdGfarSBKDQPJKEJAftoqQ2hgXwSh7skPkoQV6kkowqLkCjKjSEBKOCQf7DSJPHXFwp8EoIoo5K0C7JyCADNBcAG4wehTx1J10vFBFHk7pilMI5hshzwbQX6NHGqwO5QUUMo1GRxTDNzlRIMIZMe8sAbSRhAmtrFDHaFLTEkWu4uwazjjwDnDsABszs1UkYT4z2hBXd0DuTJG1goO8AM7ShiEBYQBDCXCPEEe+8Bg+0SyZ6zDDAxwOogYRA4hBx3AhWZFFLxjMJswEpWsSshRoz/DOHJ83Eh0oozLJ8UQrbYDBACVqUsAETUKCgwHvKjWBGHD7PZI4asZRgNROxAELPE3HAF8oYrUQt0zUbbGC11fcgYYs3JTLYAzGYio2RCUyYXYITJfjQiP4ngjBoYg+hYCI3RpiMM8rdd98DRigU+GiPLI4NfhAPJYziBN5OwBHP1ye6QAE+GMutghPh3H35L+No0IOVD1BwQKGS/+NFCQt0cLkT2XSAjztWuiDMObBL7oUTC9yOwCZOaOAOoC6ockDoYo9evBMIINBBB8oz704wcMZuECtO6EN99ZvAkQaqbEIjQxOCe19QIJlXX70Sx6SyfKqVXup+QdU4gUP1RzgCPGYxCBkEY1XyeAQo9kcQfyhBCQFEwBGUoIlFPEIewLoAtILBwIFkAx4nkGAEozGHYDyCWrdYxwpS0EF+IAAeAYzhEVjxjySs4xYXOJc8SCGMDkYBAf4nCKAFAggHgQhDDyvQ1wowkAnoGcwLSgjhEYY4RF0IRBEzwBfISGGOuHnPDkcIogXGGEAHCMQLzBDax7RgDi46sVm7gAcb2DBFMioBOiZghjlkNrNYHMJ7mgjjGIMwRguYgiAqWAHMilYCJqihDywcXDmOQMdBEvII2BrIITZQtbOR4R4zeGOZdtGOI4jAAkEg5BitWBAVmCMcfThbCcLxi0YEb1ReEIMF2EDIVF4ykwQxARmqhrlx+KADGYjaBwqJSl8GwQ4W8cIz7jGO2znBmMi85Wq8oAsqOjOVlQgeD35xD8RdrgPFu4IoZ7ILMfTSlwAIAgAsUI6MWAOd1v68nD7oV89RuaIdqkxlPAFA0GrMJAPZyMb4EHA5HGwCAdhYp0F2sQpUNpOgGA3CB2jiBXBsogPyk58S/peNakj0H7uwwwlSiUqMurQA2tzVLD4KwJCCEAFKiAI/aMKPD+QjoC516Tti+pRZKAEeIpQhEIMowHnYARE8UMF4VMADRNgBEitVZVCDCtPHeOGHSkgqFQM4RzrW8Z3OtORWXfoBol7ED0BEwFgLWccp2pWZal2rSw36KB744AgSxGsvm9lMZ+o1qEvoJy5VKkSLsvSb8pTnYTNqCrc6RQWrkOsUIRvZyQaVE91jmQpMAQ9mClSyngVAPgQQWrF5ARG6gCRHPDs72Xx8ABGWpRcU/KALMbQjHxYgqAVE0I4CcOITPHhUQAAAIfkECQkA/wAsAAAAAEAAQACHBBEdFIzkBFCNjI6UTE5UVI2fCm66Bi9MXLLUJE5klMr0////JDE5RKPcVKLEdMnnNIq8DD5gBB8zzNTYRHB8BH/hJF6EBFmfbLjUbKLMb3V8JHS43Ov3jLLUFCAmNJXcBHDIbIykBDBWRH+cbL7c////BEBxrK+3HFqBJEBKOmBqKZfpLHqs////BBYkBGSyBCI8bLPqTK/nRJrMzODw9PX4FC9CZKrBlL/h////HE9xZL/p////////XG58FIHRJILEOUFJJIzY////NG+MbK3AbJe4HG6pxMzURoyxHEFXFicrPJvXB3bLFBocFDZMZLXZJGiSVIWW////////////////ZKC0gtHqTHefdIGP6/T5FjpU////JEZUfLXnKZLfjKK0OGqQBChG////Gne6SHeIfIyYBTZb////JFd3FSo2XLrpDCY0pLLEfMDUWK7cPGd3DBggHDA7pMLcTKj0GYbZJIbRPHakfK3UwNvvRJ3W////VGFs////JDhAvMbOpKSkrMzoRGZ0VHqcPH2fjJqskrjZ////vNbslKe3XJ7U3NrcfKbITIKsNldi+vz8hMrkJ2KR7O7vdKrYfJevLHapPJLE////////////ZJqsVGp8VIKofL70HEZk////LFZkXKbE1NrkBF6nbKa8TIac////NIKsdLr0TJ7E1Ob0LIbENEZUPHaURJK4////3Ob0fIaUxOL8qNL0WLXoLHKoNI3JbMLpGVyP////////////////VJbU////OJ7qBDllVKr0DIbkbHqEJ3q3RKrsWKbMDDZMrLbEfLrvfJKkpLrQVIq0DBIULFBeTKTXXKG/fMjfFEBeDB8pTHJ8dLnNlK7EPJbUdIqcTICS////NHykdLPp////1N7pHILNLIC8LI3XPG+KHDdF////fICGLEhRlKCpDCg+LFhxLITMXHiQTFZcZLrcZKa4LF54xMbIlJqcDF6cTJKs5ObnHIrcPIu31NbUDIHeDFqcdKDELHa05O75dMDY/v7+CP4A/wkcSLCgwYH9aCkT9gGMkIdCxH1Y1E1Qv4MYM2rUCGlWtxXAZLiTJs0fBgQIoGCwdnIGq3WU9EDaSLOmwC0KVhjbgQUBMDD5KjQR2qQJCBBNwEFQVUQUhHCHtticWnCLpxW1sNQCU6GrUKJFkR4da6DMq3evNuSRSrUmpJw8jXntOrSoXaNjQRgA8YLvi3DRkmw4NLNtRg4hscid+7Wu3bxHXxh4QZkyKRabuKGKZfggrRUPdgxj/DUfGGhwoHSzxrKIg1cQyvStbJlUoQJH6HQeCCkVMCzASFf40QDDGwQzxIH70aRM83WX6N24kkT2C1LYL1w4IiXKvsJtIf7VqfUgwOjRXYUgkAZNCLhFChJxqAEJUg0OiXAsKlPm3iZ6lmBHinYX6DMCEc2AZxMkxrCByzDodWVHLf4wYUc3NNhEAyVHWEIPPVEQeIEAF7hChCMKbiSeg6Q1IM0eQihQg2E14HCELQWMoB2JAghAxIkpZhRDLbhUEGE+O0BhhzIz7vZPDXnMM0IBufRopRiSGFETLcA8EGEF9jwAjTirOFnQKrZE0Z2VApgwDgrMbLTKClgEMFcA0nwATZNmElRDM7loI0mbPZpAgQ5lYgTJbytEaI80YHQTZJ//QGJELmZY0KYJPcYhxqT/KCBDLXPl488HMVCqkREomKHDpv4mqKHGNQdtQeeXUEADDaiqVtqJBRRwasKwKujAFkHK1NKAV03sAYU4fPZ6UA2SwBPHsMN+okYlVa0gDbN2PABOotJmRIMAg+gwbDDBPPLJJAR5oixdTdQyQzfl0lSJDiqYwG4wESQQBm8ffFuXPdbYEW2+0+oATwL/BvNMAoXNwgSpdcGBjQIM03TNJ4+wi4YISkyDhEAxuCMEUfm8AQ6vHQtUgw6hfILGzWicE4JAYETi2B6qpBrzRiF88owISIvgxTP/9AMGHI9BcUeGQ2s0QQSPJC0CF0/EQgs0TNiVjzXgVE3TJ+dMg/QYyJDjxhcI2IOXONEsYvZGhHihxP4YIowxhhJnQPPGYzNgg8PdGinCRQp9+/0HJx9YIxYIDrCiB+IZAYLMOX77Tc4z4mCQ1w1lcIA5RrGMkULnY8zBxR035FVEGceeTtAWY3DuNww22ACOKGO9UIQBMN8NierpjAEDDGukA84xevU1fPFmH/+H8hJIsEYbQIgyGV+lGLCw7f9sAcMfy8OgfTrrvDPbC9EcYTr5BDEyBvrqS7AEObfEXhk9xUgE/QgCiHQwIHvZ88A5fPGOyVAmCag4xAAHgo50zCF7LpCAB/qQB1UcoTIsSIIvJigQHyxhCRLIoAs8kA1B3CMclTnCJo5Awn+QY3sYlIAcTtCPDSThOv4Dws0oJogEGKDQBUikhgvq8Q/MCMg2eMjABLXQhiWo0AXU+INAMkCPI1xgQPMoQBTGd7ca2GAJSkSiC+RADIHowRKFGJB2TBEFCZIPHdSwYgqRKId4CAQSliiAiKKgjVxQr1w1mIMH0ugCAMiBAeDpQCFCNCIBjCAKjbCdLFxgRSQCwAXOWMbtuFNJAQRKAN/AHD40mEYAOFIO8CJII1wRBTaNYxySIGO+apACD3jgk650pTkMsoVcmIJNAqCABTpxSCdBog9y8EAjg+kMD8SyIIcQQy0JpYNDaWloGlihJ4MJAHkoCg9mQIGwTICCdBmhmVSBBDFWSA1yAsAZrf7gVSxQQAFCDQsFKviENnS5mxr0YYVysKcjGbERZqDgWtgyAb8cNoFe4eMP0UyoQgNREyPAQxIRNcE0HhGKCFSCoDWpgSx06AGN2lMDC8qCCiyALXaZ4BmPmMYnFIFSjNQAHXOIpjQV6gwCwBMSWVCHOiIWDDRw4Rnn4MI0slHRmkxAC1b0pUvtGYSeGqQGWUhAKPyFs5Ep4RzneMIBlMAOdAAiFpOoTw0YAQh0+GAOWNTqNBVKAK8eBBJFe0QERDCypI3hCSlIwR/IcYA2LA+B2aNGHvW615f6NSNumMYzlGDYxvntCTZgwB/+wIA5mPaES1ikGhV6T2eYk1LfiInDWUfGN9alT335w6AaV6vQPzC0VzVQxCcSiwzbpg+BV0wuUV17WapMYhlcIEcKnqC8x0JWjSkEJjmd4UhzXLNjkzCEFyx4wzEgN4efbGQjncFdBgzgu1WDBBK04IU2rOG+qW2DHKixXzn4t73EiEdz81UPN8iiD+cgRxskS401BKEPWjgBZ/oUEAAh+QQJCQD/ACwAAAAAQABAAIcEER0UjOQEUI2MjpRMTlRUjZ8KbroGL0xUtOgsT1mUyvT///8kMTlEo9xUosQMPmR0yecEHzM0irxEb3zM1NgEf+EkXoRsuNQEWZ5woMRsdXwkeLTc6/eMstQUICYEcMgEMFY0lNpEf5xsjqxsvtRUoeIEQHGsr7ckP0g0XmwUXJD///8seqwEFyQkl+kEZLIUL0JMr+cEIjzM4PBss+n09fj///88lsQUeMgcUHJkv+k8pegUgdFsrb8kgsSMwvQ0PkxUmrw0b4xcqsxccHwWJytRgakUOEwcbqnEzNQHdss8m9cUGhwkjdhktdgcQVckaJIWOVT///////////8bZZ////9UlKxkn7GC0epGjLH////r8/krR1CMorQsV2partc4apAEKEZ8tOj///8VKjYad7pEdowFNltUhZZ8wdf///9EndYpkt5UYWxcuumkucx8jZy8xc48aHgMGCAcMDtMqPQbhtt8q9T///88dqTB2+////8MEhT///8kOECkpKSkwtyszOhEaHRUepx8oLw8fZ+MmqyTuNn///+81uyUp7fc2tz///98gYY2V2L6/PyEyuQnYpHs7u////98lqxUqvQsdqlapsj///////////9Uanx8vvQcRmR8psz///9IdoTU2uQEXqdsprxMhpw0gqzU5vRwuvQkWn////80RlQ8dpRMhrT////c5vREkrjE4vyo0vQscqg0jclswukkQlj///////9UltT///83nekEOWYMhuRveoQsfrREquwMNkystsRkprh8hpT///9MpNdcob8UQF58yOAMIClMcnx0uc2UrsRMgJJ0ipxcoNgcXIw0fKT////U3ul0s+ccgs2Uwec8b4ocN0Qsjdf///9clKeUoKkMKD3////ExshceJBMVlxkutx8uulMnsQsXniUmpwMXpx0pswsWnjk5ugcitxctug8i7fU1tQMgd4MWpwseLjk7vk8ltR0wNj///88YWpEmswcesREpeQshMI8QkhclsRkq8f+/v4I/gD/CRxIsKDBgfNkjSkRQpsPa9Z87KOVq1qgeQczaty4EdKeam3aGANTj9kFf0MwYfLX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qqz///8Eedbc3eBMlLQ0UFx3v9f///8YXIwUMEH///83NzkHDxT///8caJ6E1+0LHylso88sZpQcj+MUSWwJMEtcrdF8yOHc6PRkmqxxe4T///88oPT///88lMx4s+ZMl78EQXWs1vhUtOxUnsR0ssT///////98v/b///8kQFBUXmgkT2YEcMj///////9UboQ4frQ7YXEUICZEquT6/Pw0Wnz////g7/x8e38MjvSUnKH///////////+kqrQMQmj///8slOI8pulUgoxUrdwEgORclaasusy8ytRsrsR8psxUiJh8pMT///+/wsSE0OXE0uA8coykwtyk0vz///88dpdcZmyUtc7///88QkwwcJr///8kMjcUVowcN0a82vFUuvdcntQ0jMmkoqRcjrQpgMCL3/n///88WGA8Z3hUmryUzvx8ipePk5RUWFhUjrzU4PBUq/fU0tRoutz///9kuuQcbqgcTnD///90utBPZnx0ruQEToT////y9vkcWoQsfqz///8UQmT///8aYppxgpH///9cuuQ8jrz///////8oSGT///////////8sYpQscqhMptQpjtk3mtxcxvw4pvg8YoRUpswEVpissrx8stx8goyUoqykssRcgqS80uQcPkxsuvxUmNAMiOwMSXQUZqCUyPBssshsyfM0WGQMPFysxtzU19wch9cMXJxswuccVX0sOEj///9MfIxUk6w8TlwcMTokaJYcSGTk6vBctOBcn7wsQEgsUWIMccFcanQcICRMretcruwMftzM0dSszuz+/v4I/gD/CRxIsKDBgXD8Xdm2yZMGDfcepkE1aBGcgxgzatTYBtOVZcuwQAMHLgkXLO3a/fnTzoYjI0osJGqzsaZNgbfA6GEGwQc0K+buORjqoIVRo97gOeKjCBmyQrduSi2YE4aTJ04+jCjDtQzRoUdbRLtANoYSDGrSFZI39WabbzDmPdnDb4SOrVwdeC3agm+0vxdqDRicTk0HWJBots0IhYo+RGx0SL5bBi/RvkcBkxU8OEsWWGqIPUu1+CAjGIiAcdPhR7Jdrvc2BcNCz4LtP4RcwjtX68LgAZ5PnCBjb5e10gPbaNtzpIGf56zt8iMBARyXYLk0HNh+IGmypeyU/sQAngWP8BPjenDIoLjtLVWZEMl53trPCHNOZClwyOUbtgq3tNEGC1BgA8kfQADhBgaipJPFeU00cQID2aAR1VS36ONCOAHQ15oK88gCFC2Y3JSCBemkI4oaTEAYYTbZzHKhTW2oMkE4fnRInwJPWPHBNzNKdQsksIBGxgkRItkEB+/M0t5G2mTCYYcdqsAKBCr4EORitxQyjj09jBNhEwg0EUQQvtjECBtHBODmc0s8wcYypCFXUAo0xGOPmGQigMAlCNyxERwNfCLHmwHEyYwyW9qJExq7MMBBn36+g8AOGbXhTHOHdrgEInps8KSjBLWRAQcMUIoEAkG4M+pA/qRk0oybHXKDyAwbkLpRBk2kigASwAJbzUG3FNqpm+iwocqrupaKRhAy+BnsGkGwVRAYE+hDqx9soKNHo81SRcwlQQQbLDVUGUurHEcsUUG4NZXz569IUEABEmuwQFACzThzbLJgwGtTKQi8U+/BFJiSnLpuorYEuAJTdYnB9RJxbyWKVeDMBMe64Mw3EdtUDRJB3EuBxRQcIpA2za3bLsQhlxrEGvWebK8IAhVKawD67KNNzDZJgcAa9hJhcSX/wLHxseHo8S7QG/WDLxIWG01EKlpkkonLy0Bt08wnW00EDmCE0wCtVLiyj9c14QOs2ERIoY+hb27BBshsazTH/r1wj+HMJzu7MEOJeWd0CN9GAwDAEA20+eYTS1xUOEapEEF14kSs0cCUHSKiAsyFs2C51YpTsPmbfiDCDbOT/9NG0UQorvjpOabOD+uTt1F17LJvXnvqn7d+EAv2AsA7AKYjoqMfT6ggufAE7VC17ADkQ8URtevgih6EQz/QIRZTD0AlqihPXx8KJOA9QaaQLnsBZS9B3wxOrL2+QI8kTn0cjOizB3Tm8IE57ieQEpxMfJyAwwyAQR8dCPBp3utH+MSHqQY8oTWSUYYCrnA/KehPdvkQyBXQIT/JBPB23rvFGj6oOJz9AxN7UAYGRwCBTeBNeHNwn+xU5jo9XPAu/iNYhiDMAbqQsaAELKxee77RB2aM4IllEMQmpiE8ahABBOIDgAAIwoIl+OA1I/CEIO4BQbatImxZtNZArtDEynAFC1zwRBGbdQt1THB/BrnFB1iBF65YYBOowF2z2jCG6VGPCGokyDcUoICuOEADFtBAErwmgqJlUWEHaYMVhqiXoXjCAq9IgiCR0wYpwO54i8NdBT4wxq/kIgqvQMUcMVRIS4qvHBtBwSa4sBejaCAKk0hGCsJVDnXULImcsAktgsGDy7TgFbk5B1QcdYtS1ItoOgSAC2vSBixgIRiYMco5bEAIePQCErOkSjUMRrOwobIAoyTILUjAA3CGJRrw/mAHBoBgiSjg0ib98EW51mDAUxoPAK5qSxu2kYZ2+IUs0VACO9BAg26k4xrVCAQUAtSGW+wgENVAgxj8VIIStNOdvINnadqQhGS0wxt/GQtncCEKtNAAFuYZ05jO9I6enhSlxhNBPDWyCCMQwhFjCQxnPAOLDohDHKHogT0YwIB6iEEGlqLXMd1JgWHpCgppmAQhetGb3wQHQieYVISkRS97Fa1okvjnICFhBEVgABedOauSxuSnvgLLZG69lynSORUWFAIIZ6EBcNAqIb5qtWZ/RYIvEhmyW1QDHrhQg2HMs1dK0etX9AqCKSgLtTYkIgo0YAJx7GEPYmSDA5fgJMCZzgQsGUjhAUONmTwAEQU0uCEe45gUB8RADHxQwxpQ0FVAAAAh+QQJCQD/ACwAAAAAQABAAIcEBQgEhOqMiowMRGg8rvRMVFwPY6REgpwEIz4knO+EzuRsr8YkQ1QEZLFEm8wkJiTIztQkhswEMlRkx/cETIYqerIEEhpku+EQdMRkm6nc7flEbXk0YnwMkPZ8hIwkUmwUIywki9ZZwPwppvwENFysxtwEVpQYGBx0vdJUsur///8UhNiUqrwUUnxMouwEdM9sbmwscpwEGiTE4vx00/wcRFs0mtyE3Pc0ksw8TlwcMjn09fU0U1wUV4cEKkQkSlxMeIccLDMUa680grR0yuhpp7x0uvRUuOwEetQEDBMEivVEZmx0tsxUpswWPlxUkagcO06MmqQKSnocbqREhqQEFSZkwew0boQ0ldcEWKCsqqw0eqTc3txMtPD///8UUoQ0fqwcjuc8p+r///8citlEpuT///80ovFUfoQMiuxUhJIpovpsr+YEbcFcmqwkOD/U1NgEUpQofcEcdLTr9fv///+s2vz///+M4/w0XXAEK07///8MDg9UlrCkpKgMg+GsusyQvNz///+80OD///88PkT////AwMQ0MjT///8kWITE2uwkluyk0PCUttTU5PSUlpyUprSUy/c8doz6/PwcSnDs7uz///9Usvx0tuxUirRUpux8enz///////85irxUosS83vxkorhEtvxQWmQkisxswuT///94ipxMlrzM5vw4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i7GELEQcihDKF1rQA4pYBCOjCggAIfkECQkA/wAsAAAAAEAAQACHBAkO////BEiAjIqM////TFBUTIac////CSc7jMr8RKDXJCYoK0hR////xMbMJJ71bLTJ////ZMf5KonK0eb5ZqCyJHe3BBYjBFiabImc////DDNLB3bLNFdfbLXsKI3YNGqEFBka////bHB0SJLI////pMrsBDxpFCcvzNrk7vDxBHnXFFmMF0lqBBktKFh+ZMDvJJfqKXapJDhD////dNL8////UpSyNJ/nrKqs3N3gZKrESHqMNzc5FIffUKzc////dMnpHDM6VKfsBw8UVLTnhNjyBG/EdMDXOJPK4efpBF2mZJmnKmiUcXuEFCw/FHjCd7Pm////NFp8NJjc////R2Z3rNb4////BCA3JEFOPKL3XLrkVIeXWZ+8JE9nfLLcNIa8dKbUVG6ETJbAHC40////BX7b4O/8HGaXBC5MDB4kFCAnHCgx+vz8F094////HJDk////////FHC0JG6kfHt/lJuf////////OH60DBgdMmByPJLcSq7upKq0rLrMvMrUNHigVH6M////VF5ofL/4v8LEhNHmxNLgpMLcpNL8////LH60PHCIlLXOGWCZPEJMbKLQbKrcJDI4XJanvNrxXI60////pKKk////VJjQFILUNHGYlM78fIqXj5OUVFdZVI/BXKvOBHLN1ODw1NLU////ZLrn////GX7MWKbMF26s////HDpKBDZgDF6cKJLiDEJo8vb5////PKbp////TIKcit75////cYKR////dLrMPH6c////RIqwKEhk////////////////////XJ7U////BIHm////LGKUXIKk////DI70LI7Mb3Z8ebrpOGKArLK8fIKMlKKspLLEvNLkbLr5HDNFDEh4lMjwTKDQLJ/2bMjwDFmUFDNFPGZ0TKr0rMbcDDxf1NfcHFaEbMLnLJbkLDhIfNTy////bKu8HIfZPE5cfMjhXKbkXLLcDG64HHe6PJrYDCEuLEJMLFFhPIi0fKXHXGp0HCAkLHCkPHaUzNHUrM7s/v7+CP4A/wkcSLCgwYFKAGUYNAXYuA0bvrlqZ+WTNCUHM2rcuNFNogzKWnyx16EdAwZaZrhSSekJijUznDhww7GmTYEq8IEoBw7ciy+yXr1SQ5RoFgRZjqJAwQbmABU3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LCcwLHxWmdCAwmhNe1oZkEMYwpiCNxJhUkxJohbVmIEuDuALaDhgD80Qww+w4QNYeEAYZ/CGNzzAB9jySgO2yMMPdHGPLdRjC0c4wjGwUQ1BmO5JAQEAIfkECQkA/wAsAAAAAEAAQACHBAkO////jIqMBEiA////TFBQDGisRIuvBCdEhM7lK0hRRJ/XJCYsBGi4xMbMKJ72arLIZMj8BzZb////0eb5JHe3CxcbBFCPLFdsZKCybIacRG55BHbMbLPpJIzaFBkaFCczcXR3NGeCUJSy////BDllpMrsRKbkBHnX7vDyJlh9zNrkJJjqHFJsdNL4BB40BFyiZMHz////FJL0JDdE////THyMLHWprKqs////NJ7mFDZJ3N3g////FEhsdMHZ////Z6vC////////hNPq////BxAU4efpCx8pHGCSFD9ZWbPgVK7cN5PMOGFxdLTs////VKfsODg8////JFBpGHK0dLbMbJKsVGyA////rNb4BX7cPGKEOZnZVJrBdsns////O4e0fKXHOJLYBj9r+vz8KGCA////4O/8V730lJyjVF5oVJ68////OH60////HHe3////////XJWkBGGu////////////bLrWKZLfpKq0er/5PHSP////GU5x////rLrMvMjQVIugVIKMfJKsv8LEJDE6////pMLc////////bKPPdK7clMjwXGZsKH60////lLXOvNLkFFaMfIaRfHp8vNvxNIrHpKKk////VFdXPFhgFEJkj5OUPEJEbKrc1ODwNDI01NLUZLrkFFqERJrM////hNr3////VGZ8VKbMGX7ICE6EDC5ETKbY////////b3qETK7s8vb4////DGKkPKbs////fM7kerrqdLrMaJq0JG6kPI68////jMr8KEhk////GVWCTJPPFInl////FGKk////////BEF1LGKQTGJ8////////DI70LI7MNqb2////rLK8lKKsXJ7UXJqspLLEPHqcXIKklM78fI6cbLr4VJjQDEd0FGehDCg5TKDMbMfuNFpsTGqELI7cHCkxPGd3rMbcTKrv1Nfc////fNX0DFyYbMLoHJPoLDhINHOcPE5c////HDdFHElkfMDUjNXmHDE6HD5RXKvPfLLkXKrkLFBgfLLcXGp0/v7+CP4A/wkcSLCgwYFHcMTSJAXJBwAAjHyQoikW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aYlTtOQUVDhDAuJRjGfY057P4AMtzqYRawYhHsqop0SV8YxiHOEF+tDHLhIhCgzgwDE4wIAoErELfZzhBUcohjXOIFGJ8iEI8OwKJ6iQCnKMo6US7UY8pmHMbiSACBL9AhGS0I0gHGEaR3gGUHFKhCOkggrjNIgjEoANdLT0CxIlAiL4cNRpePWr0yBHB15w03piFasBeAE2EuBLFmGgG+goBiIC8IW61pWuZ+3DOBKQgHEs4ayAvesXEuAFdHTjlE/iRCISUAsvzNWukLWrBjQQ2com4Ai1WIY4OWUGNCyjFvZAx18jS1nJfqG0de0DAeyRWTSkEVhmmFQEKQgwA3vYABFLKC1lJ2vXPpjABjPwAgGWMYnX1osTLkADKRABXB7YwxgPqEUtHmAMe/BgBrclBRpEEdUxmYEOaAgCIhBhgvKaYLlBQAMdECuggAAAIfkECQkA/wAsAAAAAEAAQACHBAkOBIfvjIqMBEZ8////TFBQR42xBGasBCZDhMvfRJ7UJCYsKkhS////xMbMZ7PQKZ/1////ZMb4KInK0eb5Z6GxJHe3BBYjRG16bIecBFicJFZ0bLPpFCcxBnbLJI3cbHV8JGaMSJLERKTkFBkZkazBpMrsBDll7vDxzNrkKVd/BHjX////dNL8ZMHyF0lqRHuRKXapFJL0////ZKzE////BCpMBBktrKqsJDhCNJ7kGzA43N3gVbPjTJK0dMfhBw8Ub7/cGzhIGYfZh9ToVKzc////4efp////JGeUVKfsVIiYBl6jdLTsdIKR////rNb4F4LUNzc5VLv0CXC6PJbMLIC4VGyATJi+Bj9rPGKENJjcFD5UBEyHfLLcfKXHNFZcPJLc+vz8////KV+ABn/bBCA3NKH3////////4O/8TGJ8FGagDDBEV6HBKVBjPIasFHbEJ5LhFCAmGU5wGY7olJyhHCkxfHp8pKq0er/5VICQZK7M////////////rLrMvMjQPGZxfJKsOHic////v8LE////M3GYpMLclMjw////////PHCIbKPPVFhalLXROWBxJDE8vNLkfIaRWI6wvNrxXGZs////pKKkSazuHGGSPEJEFHK0VJjQFEJkj5OUjMr8VI68XJSk1ODwdK7c1NLURHKCZLrkZ5qx////dLrIGG6q////F37KfL7UbLrY////DB4kcHqE8vb4TIKc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2uTu8PEEXKQ5WWEkl+kEHjQcUmz///900vhkwfP///8UlPQkN0QUNkksdan///////9Eeoysqqzc3eD///90wdlnq8L///8UP1n///+E0+p0x+cFftwcYJIHDxQUSGzh5ukLHypZs+AkUGlUrtw3k8xkmqwmWH1xe4Ss1vj///84ODz///8YcrR0tsx4s+ZcrOg5mdkUgdccaJ40hrxUboR8pcc4ktj///8GP2v///9UmsD////////g7/xXvfRUXmhUnsAEcMcsfrT///8cd7cUICZclaRMrun6/Pz///80XHQkQUz///8pYIJ8e3+Um59sutYqkt8cKTGkqrR8v/Y8dZGsusy8xsxUi6BUgoz///////84frS/wsQkMTf///+kwtz///////90rtxcZmyUtc680NwUVoxso8y82vE0isekoqT///9UWFgUQmR8ipePk5Q8QkRsqtzU4PDU0tREdoxkuuQXWoREmsz///8ajuKE2vcZTnFPZnxUpsz///80MjQIToQMLkRMptz////////y9vk8Xmz///88puz///////9xgpF0usz///8kbqQ8jrz///84YniUzvz///8nSWT///9EcIgZVYJMk88UieX///////////////8EQXX///8YesgMjvAsjsw2pvaEzuSssrxcntRcmqxQrvh8goyUoqykssQ8epxcgqRsuvxUmNAMRnQUZ6EMKDlMoMxsx+4sjtw8Z3esxtxUqO7U19wMXJz///981fNswugckuQsOEgcN0U0c5w8Tlz///9MfIx8wNQcMTocPlGM1OZ8yOQcSGQsUGBcq898stwkaJg8h7JcanQMcMAcICQsQkz+/v4I/gD/CRxIsKDBgUnEfRlmqEIuN24qsAGjDUuJMwczaty4UQ4kSfnysdMBpySJk2p+/IBwT1QzcFgmyeFIs6ZAFV9E3Ak26E8uLiuCrmhAlOiaZU5Q3QKlZU8CWDajFsRpilcwEaEuaL0gNGjRBmvCht3SBF6WPX5USLUp51E9DeGgDJi7lSvXoUOLiuXAAQUKLUSWtOg1c61GHrx+xXqRLNncAXW74tUblq9fFEW0PDsxC6Nhg9Yw2WMiZkTjx5AjcRkpCI60DRvUkNFFaVnly0VyLyHSQsrngXIyBGmHKYJpMadX3dHRkx0Xbgaic7PCRhcZCBC8bVnjN3fuFudm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pdaq1OQMTmyhHeAzFg3ekUD2pbB7lTWrwg5wL80qwRnD0mgGNHo6lUtAQot6xCtlxaba1f5KCSRYRgLSdQmrXWIADGCB7/4QuuYGTmocS2sTBlsCTFw0VpMAxDAq4bskouG7aKCbHYxQCSMYIV/TAAJt+zUPOUACDrdgwDk2JgMjLMMTc1jHPDYVEAAh+QQJCQD/ACwAAAAAQABAAIcEER0MiuQEToSMjpRMTlRMiqQEb8NMsuwGL0wkTmQnb5yUyvQkMThMn8xstM4MP2EEHzMEXqQEf+HM1NgyjckkXoBsorREcYFsxuwkgMBvdXwsmuSMstRsjKTf7PgEMFdywNlUoeIUICb///////9EgpwEQHGsr7c0UF4kQEwEFyQsdagcYJA8YGpss+osjdlMkrxhtNgUL0Jcqs8bgMkEcszM4PAEIjyUv+H09fg5QUk0fqw8m9lcu+pamK4sV2psq7tsl7gXOlQUOEwcTm/EzNRcorwcQFdcbnwYKCsUGhwMZqQHN1n///////////////8qSFP///8ahtj///98yN50gY8aeLr///84dqQ0aoh8tec8pOckl+qMorQ0cZE8jLgkZozr9Pn///8EeNZcipx8usxEepR8jJgEWJw0WGQkerQZZ6AWgNcEKEYaWIAWKTf///8MEhVsutYkhsykssR8wdQESH+8xc4MGB86Z3lctegcMD2kwtx0qtjB2+9UYWykpKQijdqszOhEanRUepx8pshcpOBclsSMmqySuNm81uyUp7f////c2txUgpT///9cntRJeIp90Otcrtz6/PwkOEAsYpTs7u88nuxklqR8l698vvRUg6xUkqT///9Mptz///////9EkrwcRmAMdsRMptQMJjTU2uRMhpx0uvTU5vQ0RlRkprzc5vR8hpTE4vwkkuSo0vRUanz///8kUG8EYa3///8kdbf///9UltT///8nWHb///////9QqvQkSGAUecf///8MhuRseoQMNkystsR8uu98kqSkutD///88XnwMcbxUoMZ0tcQMHygsX3h0x+QsgsiUrsR0ipxMgZf///90s+lkrszU3uk8gKREnNJkvOb///9knrR8gIZEptyUoKc8coxEirD///8Md8xMd58MWpQ8WmQMJzwMSXfExsh8rdRceJBMVlxckqQ0mtw8apQserB0uswshsKUmpzk5ugMT4FUjqJUs+osT18UP2AMYKAMgdzU1tT+/v4I/gD/CRxIsKDBgR4GXQtB4YWgh4Ji8QihSpaYgxgzatRY6Y8fehS2zZgHYl6Mk3NAVKnC7QC8DapgVdpIs6ZAMYqk0TPioAGFDOVqCCVDlGg/QZn2VMHAZQOOizajEhTDDtcoCzBoGNhqQKjXokQlSCAjQVC+ST26cIIqlWYlRbjGedthwFZdrluH1gBLVqxfLlV6bFgws21GV9p2aNphy67ju3i97gU71q8ELpMOZPJg+GAfNvjGNR7duC4zaaOatXIwr7WDGKbgTQlrWcKwfNE2yOo8sJIFBfgUpEkTgTQzbUaAwABDj0awUsGC0aDAYwYIEJRm15bQZRIXVYXb/lbq9KXaueER0keI623clSuRcCzyIKZSJTEe/uA4NIUOODtzwNOXbRIEgEE+v4RnUw4liHPGcBCmwc8478iDCxA22GTDNW3Ak1IX2/XQQ4JRjfeFOGkIEOEK72ShwFOGVbLAFDxUQYllw0ggIok1BQGNOHcIIKSK1VTDDztsdVbJFm3EEI0gtfWQjws1JfPGBUOqeE4hCqyQDW8GrSLINlXAUxtTu2mUzZXqBCnklmHgkwOYB+XwywtV8IBjNF1whlEl8ehBxB2E3nGPOSwEoSCdBFXigiBlWtZFNJksOtA0vPByhwmFXlBBEIxu5AKeUPp1wC8LHCQGES08YAKn/nfocUknlobaaAg8gNCGZXwmKdAm+hDx6qu86BHGnLZqlMMLe1BCFlkbxMBJQZiog86wJqijhzqoJEvTKv2AIKBfGMSSpBfAkMIEEyYwwUstm3hb0zHwgNBPWBtQMq1AldSixrrtmtACEbXKW1AONDjAQ1hkRBNLYUXsA8wHTHxgwg9ETGNwTQu8AEJREoDDAywCdRBFMRSvi446yG6sbMICEjUFN1T+A0wUH+TMBCnAdOByTdeIBNYcsfxjzxAp5JyzPg9M8DNNNrRhRj+TmfKCGHUMMYQbSqNAxNM1BeMABZO9AI4saFiCANduCAFMO2DTdEgDDQzVTwxbzJKC/ht8fzDEEeHEvREOFGAj2Tyg6GMJ33wfMQQegmv0R8J51RADBUJYcgPjKRTjSOQZecCMM6XU0NUML8jAx+Z8790y6AWJYQAQV3RlQDN0pCPDDbzfsHfBoFcyu1ZdNUDDKXD07sbiwEdeiS20c2U8HHBAAAHvi78O+0BiLAEEM3c1kIEl1VsPweKfb1+QB94z41gz0kSRhPkQyHAK5OoTtAgu3jxmBAWASIIKzAeHUwQufwNRxBr65xgj6OIbp4CACgaIPCQgcCCI0IZoGsMMH/jhBHl4xgAHyIchXFAgbPCBPEZzBTAMwh4qEOEIC1iEC2aDH5pgw2i0sQbOWEIE/hOc4ClEYIULGmIFBSBOY3ywBoFoQIYThAD1tOc8fqQiC8QpjicsIJB15CEPQVSBCE6RiPwpggVliAB6VrCCP/CLAXkAgArkCAER8IGKYMsBC86AIggVYAXhGUAcwyiCZ6Bhe4ZgwSPOMxw2aIMDBMHEFwFAyQmKAAL+AB0qBCCJL6hIRWdgg6++EcdKxlAEKcCjwXJwCS1IYkhpOMcZDGEQTIiglJVUwjMA0bxQjecNkniDmzgpyoPUg5LItKQKiAG2IKjjAppy0yUUUIc/6UAOyKwkEInRSyUhQx2EgEahBHCPM2QBeI7IAzazmQcgAkKVvMlBIdTRAmi8qlDx/njDlzQSDgCsM5m3TEEmbYUKXrDqB8Mi1DJYkIyaaCCbAAUjGuBZkxxsggm1QIewsMWLT9mkEgT4JztvyYdwUBQjOWAEEYTwAxQ8gF3sMgERoGGObg4kBwSAKECBCAcr1LAmE6DGPoYADBSoa10wrQUvatoWnPpTpwBoZyFVwAckhAMPjsiBfXLgCDwwoh1HQMAQohCFzqUMqbWoRSFO+qeHQjWIIkhCEp7xDPpdj28ykIElUpCCISBAaTq7GCk6YNOMBEIOIs0mXOEgVz44lg+WYABkZbA2xgF2H/rYRzVD5Q9LIBaqcoziACFQ1+ttjnV941oxgHGEZezTVjmoccdnIRpG0Zqvd7xjnBuKcYQUHIERhZUKJjSghNlWMrRBtN5oTbs5BFjCEkNABibAholXMMCf65xjbZd7PThMFhiJmK7z1qGB634xhCGs4xCpR70bAIMYRQiuwexxAisAQgdwmGo6+BAFQFDjBPYIVUAAACH5BAkJAP8ALAAAAABAAEAAhwQJDgSH74yKjARIgESy/ExRVP///0yGnAknO4zK/ESf1StIUSQmLP///8TGzCSe9Gy0yf///2TH+SqJyiR3t9Hm+WagsgQWIwRYmmyKnP///wwzSjRXXwd2y2yz6SiN2DRqhBQZG////290d////0mSyaTK7AQ8aRQnL8za5O7w8f///xdJav///yhYfmTA7yl2qQQZLSSX6////yQ4QXTS/P///1KUsjSe5qyqrNzd4BSH32SqxEh6jITY8lCs3P///3TI6DqTyihplFSn7Dc3OQcPFARvxHPA1wRdpv///xwzPv///zRafOTo6HSz6XGCkf///6zW+DeZ2f///////1Sz6BR4wv///xaC1AQgN0dmd1SHl1mfvCRPZzSGvHylx1RuhP////r8/BRPeP///yRBTiRupFy65JScoxxmlwQuTHyy3Dh+tAweJBQgJ0SazBwuNASA5Hm/+RyQ5P///////xRwtODv/P///wwYHjJgcjyS3KSqtBwpMRRgnKy6zLzI0Dx2kFR+jHySrFReaL/CxITR5sTS4HSu3KTC3KTS/P///2qkzFSX1Cx+tDxwiJS1zjxCTCQyPLzS5HyHkXx6fFyWp7za8VyOtP///6SipP///zRxmJTO/I+TlFRYWFSOvFyrzgRyzXx/h9Tg8NTS1P///2S63P///2iatBh+zFimzBdurDx+nP///xw6SgQ2YAxenGa66ieS4v///296hAxCaPL2+P///zym6f///0yCnIre9////3m67P///3S6zP///0SKsChIZP///////////////1ye1ChikP///////zR6pFyCpP///wyO9CyOzDhigDym/KyyvJSirKSyxHyOnAxIeJTI8Eyi1Cyf9WzI8AxZlBQzRTxmdEyq9KzG3Aw8X9TX3GzC5////yw4SHzT8Tyg5ByI3GyrvDxOXHzJ5Fym5AxuuHy05Fyy3Bx3uAwhLixRYTyItFxqdBxRfCxCTCxxoRwgJEyWwAx+3BxhlMzR1KzO7P7+/gj+AP8JHEiwoMGBeKTMIbINx4OHD7ZNszJnEZ6DGDNq1DgG0y8ZOKxI8OHjUBBu3GqQ9FEDzbRtczCN2UizpkBcc6agI3doli4ZO+QEGEo0ALQHBCT0qkFgWwJcNqMWxPWOFjx2P2jJ2cpVaACvRYc+eNFLwoM5UKXWHJPtww8kcPZ1nbv1a9ii0Kb5kLDN00y1GfHwgQO3gxzDiOnOvTsUWgACPlxeBGzQxCoIrDpo3rx53xRt8IKwO0T63AsruugwNoqmxrZFlAeOSTQBwoQjo3J3GNVhHzok7ODpmkJnR5YAO+jg0DXr0DkrDxg/8EFg1l+1uByV4HHniPfco9L+iUKibUKWdtkw4cE1ZgwuPJiywaNDy4rJbXehtQSXNiouffp04d2AR1zBCgR8rJJIBTZV4AE06LDDzjZgDfWCBPxFNYYjw+iThDvuJOEdPRAIsYoi/fnnCR3oHIKGY0Wh8QI4123UCD03iCjiEe500cUd76QIGE47vMCOVnYF8AIas9SkCAyXfChlK13Q80gpsRlUAS26HIKDUF5xMw1sGlVwxiWyJKFmEndY8IgjQmZ5ExG0HIIOV1+dI8NkB43RBhdnrJlEK5dQ0EiNchI0xhO0sPMlVzIEgQ6iA0XSiSsYYLDmJWc0kuhGHtSpFVfggJPNQSqowUWmrB7QTCj+lH6qKBERysUVOzLECYYgQwyQ6QD48HJGnLJO9QE8qBy2FQ7w/FKQCvz04Kuv3XDxB4PFblTKPkhMoWwH5NCSIhggKDPAtLyCkW1NvwiBRGL1nSrQGMqEce653fTAD7HrTpUFBOgkhsQHfyHiwh73DgCJMpH0W1M2E7y7GTpTYCKQKnuQcS8ZPdjDr8ME4XKZEJtlgYoHArmwxS23DHCLCy6oAnJNTwghim6jeBDNP06wMM8AJ5wwwDdkpDAzTRVcEcxuvCkQDR6AeMFC0Cfc8o09R9e0ijq34TYBHP4QMs8tVLPggjNZ05QMgAN2IMo7PXAQy9wneOFFNWlvlM3+I6wQyIMjTawz99xSB5K3RpjEo86OSfAQDQsLrBGL5OucoMPhgbmjTojeOfIILMSsIfka84ijAuYYqZCEBXdwfkM8G5ghuuiCx4r6GKu3ouMwsMMy+xqR24457hbo/iE98XgDCwJraAH8Gh8fjksSlxifxDBnwEJD86LLjiXqBjkhC5prDkPBOks4r4UWsHhjOPgFUfJHJpqqmUkbW9CwvvPeeIM3/ASJxBAOwCoMHCAUlUABAva3hjiEAYAEyUQnBFHAA4CBGgiQx/4QMAlYQHAg0eoVBgaghmYowgnyQEEM9hcHBPTjgynoxiC64SsMDIEfF6GBClcYAxSgAAr+H1SFMiCRsB7gQyC2eIMWYsBELcTBG9Gb2RjIAAmE1RASMvuHA2LgBiYyEQXySAMAI2EPSGDjXi5QBiLmNYk3XOACXkTBEqLYL1zYYw9NaNm5FnadT+jhjYB8gxsqAT5C2GNlQBsAC/agroGowA16MMIFjBCDCyjRFJhLwS324IWgAU0aZDgdQaAgyVJewA0hMAcdP4ULF3iBA1Q7ATZcQIjw5SOSpoRkIYQnqzEMQhwcEEcsOWAPURYkDaU0gjIv8EdbZC0DG1gHCwYXCxZ4oWF9koQRAKDMZf5xBLyMzRgysIZ1mGFyg+NAE4Q3jkhys5tG+GMhVumfMGzgHrL+m10sFnCLy2lkE9wEgEC7GUlzvFBW4yCGN+7hu9+xABbWqMkIBErRgUbyAqSgJ0ZwcQ0ELIEG3mDe7GABiwzYZAwFqGhAlRlJP6RBowPBRTVo4NHtaWGBzVNeGMIZspSqdKDxNMIbbHFQmvQDCmD0xiRQsD6cakF5W4DpP3Dh059uE55+qMcnDKED9oxBBTowRBrqsYQYyMMPfmDq/vbXv6hSZgwT/SlQg7rMbgISjnp4AwreoEE4rnB/S0AAFHiqEWTKtaIEjaceFhuCELjhDX8EpBeZmMI19AGhRTgsRa8KT1NK8q6VXCEY1+HPXn5im5pVKWft+tk3PhYF1SBJrFpUYInUInal8HyjHh4LBWOCTAUCyIdtN5vbSE7iE77N2hgMUQ8GaPaq7zTCJEbgANk6TAc5GEEBihAC1ObVHKCAQh9Km6WAAAA7MGJrRXo5Y2lXNnVmU0JEVzFsWjk4YnBTejVFT1Mvbm5iRHBCSDJBNE5ONjFRSXU2QzdKNElOS3RHaFgwemlKbg=='
+
+
+
+bar_striped = b'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'
+
+# list of all of the base64 GIFs
+gifs = [ring_blue, red_dots_ring, ring_black_dots, ring_gray_segments, ring_lines, blue_dots, red_dots_ring, bar_striped, line_boxes, line_bubbles]
+
+# first show how to use PopupAnimated using built-in GIF image
+for i in range(100000):
+ sg.PopupAnimated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', time_between_frames=100)
+sg.PopupAnimated(None) # close all Animated Popups
+
+# Next demo is to show how to create custom windows with animations
+layout = [[sg.Image(data=gifs[0], enable_events=True, background_color='white', key='_IMAGE_', right_click_menu=['UNUSED', 'Exit'])],]
+
+window = sg.Window('My new window', no_titlebar=True, grab_anywhere=True, keep_on_top=True, background_color='white', alpha_channel=.8, margins=(0,0)).Layout(layout)
+
+offset = 0
+gif = gifs[0]
+while True: # Event Loop
+ event, values = window.Read(timeout=10) # loop every 10 ms to show that the 100 ms value below is used for animation
+ if event in (None, 'Exit', 'Cancel'):
+ break
+
+ elif event == '_IMAGE_': # if clicked on the image
+ offset += (offset < len(gifs)-1) # add 1 until the last one
+ gif = gifs[offset] # get a new gif image
+ # update the animation in the window
+ window.Element('_IMAGE_').UpdateAnimation(gif, time_between_frames=100)
diff --git a/DemoPrograms old/Demo_Bar_Chart.py b/DemoPrograms old/Demo_Bar_Chart.py
new file mode 100644
index 000000000..276e44715
--- /dev/null
+++ b/DemoPrograms old/Demo_Bar_Chart.py
@@ -0,0 +1,29 @@
+import PySimpleGUI as sg
+import random
+
+BAR_WIDTH = 50
+BAR_SPACING = 75
+EDGE_OFFSET = 3
+GRAPH_SIZE = (500,500)
+DATA_SIZE = (500,500)
+
+graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
+
+layout = [[sg.Text('Bar graphs using PySimpleGUI')],
+ [graph],
+ [sg.Button('OK')]]
+
+window = sg.Window('Window Title', layout)
+
+while True:
+ event, values = window.Read()
+ graph.Erase()
+ if event is None:
+ break
+
+ for i in range(7):
+ graph_value = random.randint(0, 400)
+ graph.DrawRectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
+ bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue')
+ graph.DrawText(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
+window.Close()
diff --git a/DemoPrograms old/Demo_Base64_Image_Encoder.py b/DemoPrograms old/Demo_Base64_Image_Encoder.py
new file mode 100644
index 000000000..bf7a6b446
--- /dev/null
+++ b/DemoPrograms old/Demo_Base64_Image_Encoder.py
@@ -0,0 +1,40 @@
+import PySimpleGUI as sg
+import os
+import base64
+
+'''
+ Base64 Encoder - encodes a folder of PNG files and creates a .py file with definitions
+'''
+
+OUTPUT_FILENAME = 'output.py'
+
+def main():
+ # folder = r'C:\Python\PycharmProjects\GooeyGUI\Uno Cards'
+ folder=''
+ folder = sg.PopupGetFolder('Source folder for images\nImages will be encoded and results saved to %s'%OUTPUT_FILENAME,
+ title='Base64 Encoder',
+ default_path=folder, initial_folder=folder )
+
+ if folder is None or folder == '':
+ sg.PopupCancel('Cancelled - No valid folder entered')
+ return
+ try:
+ namesonly = [f for f in os.listdir(folder) if f.endswith('.png') or f.endswith('.ico') or f.endswith('.gif')]
+ except:
+ sg.PopupCancel('Cancelled - No valid folder entered')
+ return
+
+ outfile = open(os.path.join(folder, OUTPUT_FILENAME), 'w')
+
+ for i, file in enumerate(namesonly):
+ contents = open(os.path.join(folder, file), 'rb').read()
+ encoded = base64.b64encode(contents)
+ outfile.write('\n{} = {}\n\n'.format(file[:file.index(".")], encoded))
+ sg.OneLineProgressMeter('Base64 Encoding', i+1, len(namesonly),key='_METER_')
+
+ outfile.close()
+ sg.Popup('Completed!', 'Encoded %s files'%(i+1))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Borderless_Window.py b/DemoPrograms old/Demo_Borderless_Window.py
new file mode 100644
index 000000000..38a4a287f
--- /dev/null
+++ b/DemoPrograms old/Demo_Borderless_Window.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+Turn off padding in order to get a really tight looking layout.
+"""
+
+sg.ChangeLookAndFeel('Dark')
+sg.SetOptions(element_padding=(0, 0))
+
+layout = [[sg.T('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)),
+ sg.T('0', size=(8, 1))],
+ [sg.T('Customer:', pad=((3, 0), 0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20, 1)),
+ sg.T('1', size=(8, 1))],
+ [sg.T('Notes:', pad=((3, 0), 0)), sg.In(size=(44, 1), background_color='white', text_color='black')],
+ [sg.Button('Start', button_color=('white', 'black')),
+ sg.Button('Stop', button_color=('gray50', 'black')),
+ sg.Button('Reset', button_color=('white', '#9B0023')),
+ sg.Button('Submit', button_color=('gray60', 'springgreen4')),
+ sg.Button('Exit', button_color=('white', '#00406B'))]]
+
+window = sg.Window("Borderless Window",
+ default_element_size=(12, 1),
+ text_justification='r',
+ auto_size_text=False,
+ auto_size_buttons=False,
+ no_titlebar=True,
+ grab_anywhere=True,
+ default_button_element_size=(12, 1))
+
+window.Layout(layout)
+
+while True:
+ event, values = window.Read()
+ if event is None or event == 'Exit':
+ break
+
+
diff --git a/DemoPrograms old/Demo_Button_Click.py b/DemoPrograms old/Demo_Button_Click.py
new file mode 100644
index 000000000..84f163762
--- /dev/null
+++ b/DemoPrograms old/Demo_Button_Click.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+if not sys.platform.startswith('win'):
+ sg.PopupError('Sorry, you gotta be on Windows')
+ sys.exit()
+import winsound
+
+
+# sg.ChangeLookAndFeel('Dark')
+# sg.SetOptions(element_padding=(0,0))
+
+layout = [
+ [sg.Button('Start', button_color=('white', 'black'), key='start'),
+ sg.Button('Stop', button_color=('white', 'black'), key='stop'),
+ sg.Button('Reset', button_color=('white', 'firebrick3'), key='reset'),
+ sg.Button('Submit', button_color=('white', 'springgreen4'), key='submit')]
+ ]
+
+window = sg.Window("Button Click", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, default_button_element_size=(12,1), use_default_focus=False).Layout(layout).Finalize()
+
+window.FindElement('submit').Update(disabled=True)
+
+recording = have_data = False
+while True:
+ event, values = window.Read(timeout=100)
+ if event is None:
+ sys.exit(69)
+ winsound.PlaySound("ButtonClick.wav", 1) if event != sg.TIMEOUT_KEY else None
diff --git a/DemoPrograms old/Demo_Button_Func_Calls.py b/DemoPrograms old/Demo_Button_Func_Calls.py
new file mode 100644
index 000000000..c4d62a71a
--- /dev/null
+++ b/DemoPrograms old/Demo_Button_Func_Calls.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+
+"""
+Demo Button Function Calls
+Typically GUI packages in Python (tkinter, Qt, WxPython, etc) will call a user's function
+when a button is clicked. This "Callback" model versus "Message Passing" model is a fundamental
+difference between PySimpleGUI and all other GUI.
+
+There are NO BUTTON CALLBACKS in the PySimpleGUI Architecture
+
+It is quite easy to simulate these callbacks however. The way to do this is to add the calls
+to your Event Loop
+"""
+
+def callback_function1():
+ sg.Popup('In Callback Function 1')
+ print('In the callback function 1')
+
+def callback_function2():
+ sg.Popup('In Callback Function 2')
+ print('In the callback function 2')
+
+layout = [ [sg.Text('Demo of Button Callbacks')],
+ [sg.Button('Button 1'), sg.Button('Button 2')] ]
+
+window = sg.Window('Button Callback Simulation').Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None:
+ break
+ elif event == 'Button 1':
+ callback_function1() # call the "Callback" function
+ elif event == 'Button 2':
+ callback_function2() # call the "Callback" function
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Button_States.py b/DemoPrograms old/Demo_Button_States.py
new file mode 100644
index 000000000..0b4426991
--- /dev/null
+++ b/DemoPrograms old/Demo_Button_States.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+"""
+Demonstrates using a "tight" layout with a Dark theme.
+Shows how button states can be controlled by a user application. The program manages the disabled/enabled
+states for buttons and changes the text color to show greyed-out (disabled) buttons
+"""
+
+sg.ChangeLookAndFeel('Dark')
+sg.SetOptions(element_padding=(0,0))
+
+layout = [[sg.T('User:', pad=((3,0),0)), sg.OptionMenu(values = ('User 1', 'User 2'), size=(20,1)), sg.T('0', size=(8,1))],
+ [sg.T('Customer:', pad=((3,0),0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20,1)), sg.T('1', size=(8,1))],
+ [sg.T('Notes:', pad=((3,0),0)), sg.In(size=(44,1), background_color='white', text_color='black')],
+ [sg.Button('Start', button_color=('white', 'black'), key='_Start_'),
+ sg.Button('Stop', button_color=('white', 'black'), key='_Stop_'),
+ sg.Button('Reset', button_color=('white', 'firebrick3'), key='_Reset_'),
+ sg.Button('Submit', button_color=('white', 'springgreen4'), key='_Submit_')]]
+
+window = sg.Window("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False,
+ default_button_element_size=(12,1)).Layout(layout).Finalize()
+
+
+for key, state in {'_Start_': False, '_Stop_': True, '_Reset_': True, '_Submit_': True}.items():
+ window.FindElement(key).Update(disabled=state)
+
+recording = have_data = False
+while True:
+ event, values = window.Read()
+ print(event)
+ if event is None:
+ sys.exit(69)
+ if event == '_Start_':
+ for key, state in {'_Start_':True, '_Stop_':False, '_Reset_':False, '_Submit_':True}.items():
+ window.FindElement(key).Update(disabled=state)
+ recording = True
+ elif event == '_Stop_' and recording:
+ [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':False, '_Submit_':False}.items()]
+ recording = False
+ have_data = True
+ elif event == '_Reset_':
+ [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':True}.items()]
+ recording = False
+ have_data = False
+ elif event == '_Submit_' and have_data:
+ [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':False}.items()]
+ recording = False
diff --git a/DemoPrograms old/Demo_Button_Toggle.py b/DemoPrograms old/Demo_Button_Toggle.py
new file mode 100644
index 000000000..0d923be68
--- /dev/null
+++ b/DemoPrograms old/Demo_Button_Toggle.py
@@ -0,0 +1,39 @@
+import PySimpleGUI as sg
+
+"""
+ Toggle Button Demo
+ The background color of the button toggles between on and off
+ Two versions are present... a simple button that changes text and a graphical one
+ A HUGE thank you to the PySimpleGUI community memeber that donated his time and skill in creating the buttons!
+ The text of the button toggles between Off and On
+"""
+def main():
+ layout = [[sg.Text('A toggle button example')],
+ [sg.T('A graphical version'), sg.B('', image_data=toggle_btn_off, key='_TOGGLE_GRAPHIC_', button_color=sg.COLOR_SYSTEM_DEFAULT,border_width=0),],
+ [sg.Button('On', size=(3,1), button_color=('white', 'green'), key='_B_'), sg.Button('Exit')]]
+
+ window = sg.Window('Toggle Button Example', layout)
+
+ down = True
+ graphic_off = True
+ while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event in (None, 'Exit'):
+ break
+ elif event == '_B_': # if the normal button that changes color and text
+ down = not down
+ window.Element('_B_').Update(('Off','On')[down], button_color=(('white', ('red', 'green')[down])))
+ elif event == '_TOGGLE_GRAPHIC_': # if the graphical button that changes images
+ graphic_off = not graphic_off
+ window.Element('_TOGGLE_GRAPHIC_').Update(image_data=(toggle_btn_on, toggle_btn_off)[graphic_off])
+
+ window.Close()
+
+
+toggle_btn_off = b'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'
+
+
+toggle_btn_on = b'iVBORw0KGgoAAAANSUhEUgAAAGQAAAAoCAYAAAAIeF9DAAARfUlEQVRoge1bCZRVxZn+qure+/q91zuNNNKAtKC0LYhs3R1iZHSI64iQObNkMjJk1KiJyXjc0cQzZkRwGTPOmaAmxlGcmUQnbjEGUVGC2tggGDZFBTEN3ey9vvXeWzXnr7u893oBkjOBKKlDcW9X1a137//Vv9ZfbNmyZTjSwhiDEAKGYVSYpnmOZVkzTdM8zTTNU4UQxYyxMhpzHJYupVSvUmqr67pbbNteadv2a7Ztd2SzWTiOA9d1oZQ6LGWOCJAACMuyzisqKroqGo1eYFlWxDRN3c4512OCejwWInZQpZQEQMa27WXZbHZJKpVank6nFYFzOGAOCwgR2zTNplgs9m/FxcXTioqKEABxvBL/SAsRngCwbXtNOp3+zpSLJzf3ffS5Jc8X/G0cam7DMIqKioruLy4uvjoej7NIJBICcbDnIN78cBXW71qH7d3bsTvZjoRMwpE2wIirjg0RjlbRi1wBBjcR5zFUx4ajtrQWZ46YjC+Mm4Gq0ipNJ8MwiGbTTNN8a+PyTUsSicT1jXMa0oO95oAc4k80MhqNvlBWVjYpHo9rrqD2dZ+sw9I1j6Nl/2qoGCCiDMzgYBYD49BghGh8XlEJRA5d6Z8EVFZBORJuSgEJhYahTfj7afMweczkvMcUcct7iUTikvr6+ta+0xIWAwJimmZdLBZ7uby8fGQsFtMo7zq4C/e+cg9aupphlBngcQ5OIFAVXvXA6DPZ5wkUIr4rAenfEyDBvfTulaMgHQWVVHC6HTSUN+GGP78JNUNqvCmUIiXfmkwmz6urq3s/f/oBARFC1MTj8eaKigq6ajCW/eZXuKd5EbKlGRjlBngRAzO5xxG8z0v7AAyKw2cNH180wQEmV07B2dUzcWbVFIwqHY2ySJnu68p04dOuHVi/Zx3eaF2BtXvXQkFCOYDb48LqieDGxptxwaQLw2kdx9mZSCSa6urqdgZt/QDhnBfFYjECY1JxcbEWU4+8/jAe+/DHME8wYZSIkCMKgOgLwueFKRTAJMPsmjm4YvxVGFUyyvs2LbF8iRCIL7+dLjs6d+DhdUvw7LZnoBiJMQnnoIP5p1yOK//sG+H0JL56e3ub6uvrtU4hLEKlTvrBNM37iouLJwWc8ejKH+Oxjx+FVW1BlAgtosDzCJ4PxEAgfJa5RAEnWiNw39QHcPqQCfqltdXkSCSSCWTSaUgyYcn4IZegqAiaboJjVNloLDxnMf667qu47pVvY5e7E2aVicc+ehScMVw+80r9E4ZhEK3vA/At+BiEHGIYRmNJScnblZWVjPTGyxuW4Z9Xf0+DYZQKMLM/GP2AGOy+X+cfdyElPbVsKu6f/gNURCr0uyaTSXR2duqrOsTXEO3Ky8v1lQZ1JA/i2hevwbsH10K5gL3fxh1Nd+L8My7wcFdKJZPJGePGjWt+9dVXPcHDGGOWZT1YXFysTdu2g21Y3Hy3FlPEGQVgMNYfDNa35hpyDiM+E5Wo3VTRhIdm/AjlVrn2I3bv3o329nakUin9LZyR/mQFzjCtfMY50qkU2ne362dcx0V5tAI/mfMEmqq+qEkiKgwsfvtu7DqwCwHtI5HIA3RvWZYHiBDiy0VFRdrpIz/jnlcWwy7Nap1RIKYCwvJBwAhByBG/P1h/xBXA6Oho3DvtARgQsG0HbW3tSCZT4AQAzweDhyBQG3iwSD2Akqkk2tva4WQdGNzAgxf9O0Zbo8EFQzaWweLli0KuEkI0bNu2bRbRn/viisIhWom/t2N9aNqyPjpjUK5AHhfwvHb+2QKEKYbvT1iIGI/BcST27dsL13U8MBgPweB5HOFd6W+h+7kPEFXHdbBn7x44rouoGcXds+4FyzDwIo6Wjmas274u4BKi/TWEAeecVViWdWEkYsEwBJauecLzM6LeD/VV4H3VwoT4GVgw7nZsvPgDr17k1VtOuh315gQoV/lWCXDr2O9i44Uf6HrL6Nshs7k+Kj9r+LnuWzFzFWRKes8eraKAi4ddgtPK66GURGdXpw8GL6gBR/S9Emhhf95VShddHR06vjVh+ARcMma29llEXODJtY+HksQwBGFQwTkX51qWZZmmhY7eTryzvxk8xrWfEZq2g+iM2SfMxf+c8xS+Ov5r/aj2d/Vfw09nPY1LSudoR8nXYGH/nHFzUS8nQNoyN2fQTcrvgANlq6PHIS4wr3a+Jlw6nUY2kwFjwhNPeaAInzOED4B3ZXmgsQI9Q5yTzmaQTmf03P/YcCVUGtp1WL2nGQd7OnwJwwmDc7kQ4ktBsPDNraugogCPHMKCYjnOuKvh7sMu34VnL0K9mgDpFOCBmBXD9WfeCJlU2qop4EByetN57X/oCoZJpZNRUzQSUklPeXMGoQEQ+toXGOYT3yO8yOMUkQcU1zpDcKHnpLlHVYzE5KopmkukCaza+uvwswkLAuR00u4EyLq2dV5symT9uaMAGIYrx14VNm1u3YQrHr8ctYtH4eT7R+PKn16Bzbs2hf3fGH81ZMItEE9UGsY0YHblXMBWA0ZcjlalldJU+QVNMOlKuFLqlU2rmAt/pecTXARXGuMBE4BGY3QANtyW8MAjn4XmllLhi6PO0iEWbgJrW9eGlhphwTnnY4P9jO0d27yQiBjEys5rbhjeqK879u3AxUsvxBvdr8EabsIaYWEVW4mvvHYpNrdv1mOaxjRB9voxIL88t/ZZfXP9jBvg9rr6BY9ZkcDpJRM0sRzb8QnsrWweXj1OITA05wTcQhwkhC/GvH4CQfgACh8w4iLbsbXYmnjiRB1WodXwScf2vEXITua0yxdsMu1Ot4MZrD8gff6cEJ+ImBnT98RyIs5hVAkYFYY2CMiRNCoNvHdgvR4Ti8QwMXpGASBL1z+BfT37MLRkKG4bf4dW4seqkCitiY7UxCIuITHFfTACEcR9YueLKw2CyOkW4hjBcyB4QOXaaH7y9kdVjgZ8g6U92Z7zZTgvJ0BKg4akm/ydHeruTDd4lOtKYAY6hpsMWxKbw3G1JWMLAGECeHrTU/p+7sSvoJ5P7CfSjlqRCnEjpsGAvykXiqVAmefpDtGnzauij0Um+t0TaQiUkkiJJxGUQoponuOQUp7vbarfgyKlRaXa9xho97C+4vTwftuBjwq1Omd48KMHsK93n+ag6yffqEMLx6SQESHJiJDeShV9iRuII5EHggg5RlejcHzQJ/KAIVGmuZA4Rfr7KAqFHr9SqjvYC46J2BGt0o29G5C0PWTPn3CBP3nhg/RDM6pn6PtkJon1nev7+TLEUQ+sv1/fk4IfUznmGCHihdClv2C0qBKFYGjlzVjhqmf9uSGnW3JmsAZSeFYSgd6Z6PJ+VAExEQ3fgbDgfsaEbhgeG6FZqZ9DNgBIq3d628NDS4fi2Yt/gdkVcz02lApfKpuJn037X4wuPUmP2di60RNnffZOiLNe6HwOm/d6oo1M4WNSGNCa+K1nBSnlE1uEK531UeqBWat1hfBM2wAAFoq6PCNAr36hudBVEjv2f+J9pVSojg7PTw7p5FLKj4NMiNqyWij7EB5y0MyARz58KGyuP7EeC2cuwqa/2Ko97f9oWoLThtSH/YtXLNKbWgX6KdhGEMB/fbT02AARFM6wqWOj9tBdx4Eg38E3ebnvhwiWrz9EKNY8P0XkiTkRWmnM7w84xXFtSFdhQ+t7Hi2kwpiK2vA1lFLbSGRtIkBIrk0bNU3vCWsPWYajCkS/R0iFjakNWLDilsN+681P3YgNqfUQxQIQhX3eljTDCx3PoaX1nf59R6lSWX2wWfsfru8vhA5eYLaKfEXPwvAJ83WDNnEDMISvX4QIn9W6Qy98ibe2v6mlA+WDTB05NeQQKeVm4pBfU74QPXDWqWeBpQCZUWFWRSEQuS1NmvC5jmfxV8/8JZ58p/8KX7rqCcx9ZA5+3vY0jAqh9+ALOSRHbZrrX7fQPs0xQoQpbOrdgJ09rZoOyXRa6wvB8j10plc744Gz6HEN90MnIvTchecMEucwFoou7alLhU/3/xbv7f6N53DbDGefdnb4yVLKlez111+vKCkp2V1VVWXRtu21//1NtDirYZ5ggFs8t6oHimfBQ1mlXLgJ6QUEHS/+pL3cGIco5uAxoc1g6nO6XDhdju43hxge5zAvOYD2n50OFzIrdTv1kzn9By86VCMxK/ZlXFd/k/60srIyUDg897GqMN4WEkLljcj/P9eazqTR1ekp8oW//Be8tONFzTXTKxvx0PyHPQtXqWxvb281iSxKd3wpk8lodp3f+HVNMEmiS+ZFYwfJtiP3nxPxqgxY1SYiNRYiIyzttZtDDW/r1/T0Byl2USpgDaM+s4DYBBCNNYeZ+nkCQ4f/j0bx3+2VjuXYevB9zSVdXV36Gsas8i0nFlhcOasrNy4/5sW8uTq9ubbs2oKXPvylTpuSWRfzm+aH7oLruoRBh6aIbdsPEUvZto3JtVPQVDlDp7BQrlGQ5hJi0kd0wVfMRDweF7rS6qbwMnGYDuHniTwCh/pELC9Eo/JA0Vwl9J6BflbhqFT9LiZwz/t3I5FN6D2MvXv3Qfoh+HxdEYixcKcw3BPxrClPZHGd00tz0DWZSeDOl+4AIl4q0PQTGjH91Aafrjpf64eEAfdl1/JMJkPpjhrJW8+/DVZXBE6P6+1ZBKD4Cl7JAYBRuT9C8SyPDjH/XyotCJOhTe3CXevvhO1k4Dg2drfv0fvoHkegQKfkgocMHPkhFYZUKqm3cWmOrGvju8/fhtZUq168RXYRFlx0e5gFKqVsqampeYWkFPcRUplM5ju9vb10RU1VDRacdTvsvbYX+LMLQQktr4FACcaE4AT16Orp36eS+YsIx7r0u7ij5XtIZpOwaddvzx60tbUhlUoXcgXru63LtPJub2vTz5AKIKd4wTM3oWVPi97WIF1188xbcVL1SQF3UBL2dXRPtBfz5s0LOnYqpYYahjGd9kfqauqgeoCWT1v0ytHZibxvdiILdV2/GNihPP6jpBp+5xJs5XKgLdWGVTtWYnxxHYZEh2ix09Pdg67uLmRtG45taxFPFiqB0NXdjb1796K7u0uPpbK1/QPc9PwN+KDrfe2HkfX69UlX4LKZ8zR30EKl7PgRI0Y8TOMvu+yyXF6W33ljT0/PDMoXIna8etY1Or71oy0PDZwo5yt6FQDTxwIbFJRjGGk/XNGvbnBQFIkSyP9pzbdwbsUs/E3d32J46QhIx0F3VxfCXCDi/mBF6sWp0Na1E0+2PImXt70MFkHIGQTGtRd8W4MBL3uR8nxvCF6JMGArVqwoeEXDMMJUUjKDKWHuxXd/gbtWfR92Wdbbbz8OUkmVn6erUtIz6RMSddHTMH1YI+qH1uPE0hEoiRRrEHqyPWjrbMPm3ZvQ/Onb2LhvE5ihNI3IUo3YEdwycwFmN1yaD8ZOylqsra0NU0kJi36AwE+2jsfjOtk6yGJs3d+KRS8vRPOBt3LJ1hGWE2efx2RrnVztRS5kxvOzdE1LL9ud+tzCkJK3SJneoyfTtnFYE26+cAHGVI/RRkCQbJ1IJM6rra0tSLYeFJDgOEIsFguPI9A2L7Wv+XgN/vOdn6B591tAnB0fxxECYBy/ZqUHhJsLo8Pf3yBHGRmgYUQT/qFxPhrHN2ogkFMLJKYuHTt27Kd9f4awGPDAjm8XE4pNUsr7HccJD+xMPXkqpo2dhgM9B7Dy/TfwbutabOvchvYD7eh1e+HS3uTn+cCO9I+vSe+ew0CxiKM6Xo3ailpMrpmiwyHDKqpDp88/SUXW1JLe3t7rx48fP/iBnYE4JL8QupZl0ZG2H8Tj8emUs/qnI21HVvKOtLUkk8nrxo0b9/ahHhyUQ/ILOYqZTKbZcZyGTCYzK5lMfjMajZ4fiUT0oU8vIir+dOgz79CnHz3P2rb9q0wm88NTTjll+ZHOc1gOKRjsn8Y1TZOORVOC3dmWZdUbhqGPRXPOS49TQHqUUj1SSjoWvdlxnJXZbPa1bDbbQb4K1SM6Fg3g/wC58vyvEBd3YwAAAABJRU5ErkJggg=='
+
+main()
diff --git a/DemoPrograms old/Demo_Buttons_Mac.py b/DemoPrograms old/Demo_Buttons_Mac.py
new file mode 100644
index 000000000..b605923bf
--- /dev/null
+++ b/DemoPrograms old/Demo_Buttons_Mac.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+import sys
+import time
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+def show_win():
+ sg.SetOptions(border_width=0, margins=(0,0), element_padding=(5,3))
+
+
+ frame_layout = [ [sg.Button('', image_data=mac_red, button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='_exit_'),
+ sg.Button('', image_data=mac_orange, button_color=('white', sg.COLOR_SYSTEM_DEFAULT)),
+ sg.Button('', image_data=mac_green, button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='_minimize_'),
+ sg.Text(' '*40)],]
+
+ layout = [[sg.Frame('',frame_layout)],
+ [sg.T('')],
+ [ sg.Text(' My Mac-alike window', size=(25,2)) ],]
+
+ window = sg.Window('My new window',
+ no_titlebar=True,
+ grab_anywhere=True,
+ alpha_channel=0,
+ ).Layout(layout).Finalize()
+
+ for i in range(100):
+ window.SetAlpha(i/100)
+ time.sleep(.01)
+
+ while True: # Event Loop
+ event, values = window.Read()
+ if event is None or event == '_exit_':
+ break
+ if event == '_minimize_':
+ # window.Minimize() # cannot minimize a window with no titlebar
+ pass
+ print(event, values)
+
+
+
+mac_red = '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'
+
+mac_green = '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'
+
+mac_orange = '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'
+
+
+show_win()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Buttons_Nice_Graphics.py b/DemoPrograms old/Demo_Buttons_Nice_Graphics.py
new file mode 100644
index 000000000..2a53a9197
--- /dev/null
+++ b/DemoPrograms old/Demo_Buttons_Nice_Graphics.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import io
+from PIL import Image
+import base64
+
+"""
+Shows some fancy button graphics with the help of PIL
+
+Usually when you create Base64 buttons to embed in your PySimpleGUI code, you make the exactly the correct size. Resizing isn't an option when
+ using the tkinter version of PySimpleGUI (except for crude "Scaling")
+
+The PIL code resizes the button images prior to creating the sg.Button
+"""
+
+
+DEF_BUTTON_COLOR =('white', 'black')
+
+def resize_base64_image(image64, size):
+ '''
+ May not be the original purpose, but this code is being used to resize an image for use with PySimpleGUI (tkinter) button graphics
+ :param image64: (str) The Base64 image
+ :param size: Tuple[int, int] Size to make the image in pixels (width, height)
+ :return: (str) A new Base64 image
+ '''
+ image_file = io.BytesIO(base64.b64decode(image64))
+ img = Image.open(image_file)
+ img.thumbnail(size, Image.ANTIALIAS)
+ bio = io.BytesIO()
+ img.save(bio, format='PNG')
+ imgbytes = bio.getvalue()
+ return imgbytes
+
+
+def GraphicButton(text, key, image_data, color=DEF_BUTTON_COLOR, size=(100,50)):
+ '''
+ A user defined element. Use this function inside of your layouts as if it were a Button element (it IS a Button Element)
+ Only 3 parameters are required.
+
+ :param text: (str) Text you want to display on the button
+ :param key: (Any) The key for the button
+ :param image_data: (str) The Base64 image to use on the button
+ :param color: Tuple[str, str] Button color
+ :param size: Tuple[int, int] Size of the button to display in pixels (width, height)
+ :return: (PySimpleGUI.Button) A button with a resized Base64 image applied to it
+ '''
+ return sg.Button(text, image_data=resize_base64_image(image_data, size), button_color=color, font='Any 15', pad=(0, 0), key=key, border_width=0)
+
+def ShowMeTheButtons():
+
+ sg.ChangeLookAndFeel('Black')
+
+ frame_layout = [ [sg.Text('Who says Windows have to be ugly when using tkinter?', size=(45,3))],
+ [sg.Text('All of these buttons are part of the code itself', size=(45,2))],
+ [GraphicButton('Next', '-NEXT-', button64),
+ GraphicButton('Submit', '-SUBMIT-', red_pill64),
+ GraphicButton('OK', '-OK-', green_pill64),
+ GraphicButton('Exit', '-EXIT-', orange64)],]
+
+ layout = [[sg.Frame('Nice Buttons', frame_layout, font=('any 18'), background_color='black')]]
+
+ window = sg.Window('Demo of Nice Looking Buttons', layout,
+ grab_anywhere=True,
+ keep_on_top=True,
+ no_titlebar=True,
+ use_default_focus=False,
+ font='any 15',
+ background_color='black')
+
+ # ---===--- The event loop --- #
+ while True:
+ event, values = window.Read()
+ print(event)
+ if event in ('-EXIT-', None): # Exit button or X
+ break
+
+if __name__ == '__main__':
+
+ # To convert your images, use the PySimpleGUI program - Demo_Base64_Image_Encoder.py located on the GitHub (http://www.PySimpleGUI.com)
+
+ orange64 = 'iVBORw0KGgoAAAANSUhEUgAAAiIAAADLCAMAAABkvgh7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANtvJ99sId5tIt5uI91tJNxuJNxuJttvKN90NN91Ntt3PN52ONx3Otx3PNt4Pdp4Ptx4PepfD+pfEOtgD+piD+tkD+ttD+dnFOdoE+doFOVoFuNqG+JrHOFrHuFsHuRpGORpGuRqGORqGupgEOpiEOpkEOlmEOhnEupoEOpoEupqFettEetsF+tuFOxqFetrGOtsGetvHOxrGOxsGOxtGuxuG+xuHexxFutwH+xxGOxyGOxyGuxxHuBsIOJvJ+NvKORvKONwKeNwKuJxLONyLeJyLuRwKeRwKuRxLOtxIexyIexzJOx0JOx1Ju11KOx2KOx2Kux5Iux4Kux5Le1/LeFyMOFzMuB0NOB1Nux7MOx8MOx8Mu19NO1+NO1+Ntd7RdV8RtN+S9J/TdF/TtV9SNR9Stl5QNl6Qdh6Qth7RK+Tfa+Tfq6Ufr+JZb+JZr+KZ7uMbr6KaL6LaryMbLyNb7yOb7WPdLuNcLqOcLmOcrmPdLOQd7SQdrKReLKRerGSerCTfLCTfrmQde2AN+2AOO2BOu2COu6DPO6EPe6EPsWDV8OFXcOFXsOGXcOGXsaDWMSEWsqCVs+AUM2AUs6CU82CVMqDWMmEWtCAT9CAUMKHYMCIYsCIZMCKZu6FQO6GQe6GQu6HRO6IRe6JRu6KR+6KSO+LSu+MS++MTO+OTe+OTu+OUO+RUu+TVfCNTvCOTvCPUPCQUfCQUvCSU/CRVPCSVPCSVvCUV/CUWPCVWvGWWvGXXPGYXvCWYPGaYfGcYvGcZPKdZvKeZ/GdavKeaPKebfKebvKgavKhbPKibfGibvKjcPGkcfKmdPKiePOod/OpePSpePSqevSrfPSsfPSsfvSqg/SugfWwgvWwhPWyhfWyhvWxi/Wyj/W0ifW2jfa4j/a1kPW2kva2lfW2lvW4kPa6kfa7kva5lvW7lPa8lPW8lve+l/a4mva5nPa6nPa7nva+mPa+mva/nPa8oPa9ovbAm/bAnfXAnvbCofbEo/XGp/bGqPbIqQAAAC/NnaUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAAJXElEQVR4Xu3de3zVdR3H8Xb9/sJh60LlOTtubdIZEyckSdedMzkdZyRGIePmZdqki8s0KllJmtGCTAXRlUAyrireUeZga2JRkooYRWR0JbXMLsIqZ5fT7/L5nRvj9/md0/fhw/Px/fyHP+D33fb4vPj+LvsxXpMA8IREgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgJF7Ih1Xf3bVsuu/AYXu+mUrL+u8iqbqIcdErvhme0V8SjQCIpwWe+0nli+k2R5NTolc0jYzqpQBcigV+UDltZ57SQ6JfLqyRRXRyiCIis7u7qAhj8B3Ip1tLdg/pFLR0Z+hOR/JbyIrWxGIZCp289E2Ep+J3HzEFqLKy0qhUJUfeUkZnf8lGnYWX4l0tDfTOg5VEqoJNNTXh6EgmaMLBKuaymmcJFLRSfPO5CuRtgitYisPBehDQUFrqC3O2EtUxRdo4Bn8JHJhlNawlNZh85Aj2JQeiRp9JY08nY9Euk+nFUwq1ECLgww1ZTRaS+R8mnk6PpEF8dTDkNIgLQxiHFdNw7U0d9PU07CJdLw+tRUVpy5Cxo19+bz9lYI+n5cNfdhcjWGZf2jsCTTJcDiUmnBR/HKaewqbSHfqQqSJrkLGvuuctZu3jOgBD1u99B7Fg6a+Vwrrk8kNfRX+0XE2+qg527adsc38M723d01yK3lbqhH1SZp7CpfIolnJw4udQk44ddPOn/3q6b+M6K8+/c2vF+jXVw29X/ALI7N+Z3jome+f/QZ7pOG6VCMtl9Dkk7hElifvd0uPs1cb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'
+
+ green_pill64 = 'iVBORw0KGgoAAAANSUhEUgAAAYEAAACCCAYAAACgunQ+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAl2cEFnAAABgQAAAIIAb/yLCQAAGGZJREFUeNrt3XuUXWV9N/Dvb+99bnPOZK7JTBIIF3MBAgElEiIBjEWwVl/f6iIKWhRae9GFlxaKttQQQWyL0db61sWqS1kWqw2vdlWrVqzINZogQtKQGHIDcs/cMnOu++y9n1//mImNM3ufOWdu5yT5ftaKK5x9e05c6/me57KfR1QVRER0ZrLqXQAiIqofhgAR0RmMIUBEdAZz6l2AevrIbkkM+sggQBo2kvUuDxHNrMBBIeYg99C5GFScmQOkcroODP/pAUkN5LDQsrAQgoWqWAjFYgg6IGiBQSsEAgCOJBKOxOP1LjMRzSzX5PMKY0b+swQgD8UggIMAdquF3ZZitwmwO17Ayw9erl69yzzVTpsQeP+vpMOxcI0BVoniGgCLIZCk1dxc77IR0amtZLJZKDwItgB4SgVPB0Vs/Poyzde7bJN1yoaAQOTW3bhGDK43wHUCXMhf9EQ0E0ZCwUDwSwgesw2++09LdGu9yzURp1wIfHCnLAuANQq8SwTz+UufiOqtZLJZVeywBBvUxoavvkb317tM1TolQmDNdok3O7hdgdsBtLPiJ6JGVQqyQ7DwM6P4znmL8ZW1UDP5u06fhg6B23bLbBj8CRQfBNDCyp+IThUjXUb7AXwxl8HXN5ylxXqXKUxDhsBt2+Rs4+CjorglbqfbLVj2RO+lBnCH9H//DCqCssL4gPGAwBv5u1/vb01EM812ACsGWDGBHQMsB7ATgmSrIDFr+E88IxieRzgxJZPNAuiH4stw8eDXLtPj9f7eJ2uoELhlq6SdGD6pij9J2s3tE7lHOavIHTHIHVWU+g1Kxxvn+xHRqSnVLmjqtJDutpCZK3AStaeCa/J5o2ZAgfuKF+ErG6BBvb8X0CAhIBB5/3bcCOBeAHNr6fZRAwztN8gfMxjYG8CcdrN4iajRJFoEzfMsNM+3kOmyamoplEw2qwbbRHDnQ0v1mXp/l7qHwG0vykVG8WUIXlt15a9A7qjB4MsGg/tZ8RNR/TgpQes5FlrOtZFqrz4NSiY7BMW3RfAXX1uqR+pV/rqFwDqItXc7PgaDv6y268d4wLH/9tH/UjAl4+0igq6WBYg5ccTtBGJOAnEngbiTxKQ6AYmoQSn8wEPZd+EFLsq+i7JfwmChDwU3O+m7J1oEHUtstJ5vQ6pcma1ksgcE+PBDS/W79fgXqUsI3PqidBuDByFYXc2vf6+g6N9pMLAnmNAAbiKWwrmzL8S5sy9Ea7oTbenZaE13Ip1sYVVPRACAwATozR7G8XwPBvI9ONi/Bwf79qJn6CAUtdWTTkrQsdhC20IbVmz880smm1Xga6UsPrFh5czOIprxELjlRbkBBl9OWpnzxjvX+EDPtgD9uwxq+f8gFU/jorOuwDmdS7CgcwlamiY0xkxEBGMCvNq3C4cHXsaLBzbhUP++qkNBbKDjAgudF47fMiiZXA7ADsvg1ocu1Rdn6vvNWAgIRG7Zgs+q4MNJK5OpdK4aoH+XQe+O6n/5d7WcjQvnL8fC7mXoajkb7M4houngegX86tAvsffoNuw49AtUU4c6KUHXMguzzh6/j6gU5IYg+KOvL9NvzcT3mZEQWLNd4kkP/wjg3eMFQP6o4uiWAOXc+OVKxFK4aP7rccmCq9DdsmAm/r2IiH6tUM7ixf2bsHX/M+jLjj+229Qp6LrURqKl8o9UN8hlVbDu65fq+un+DtMeAu/bJLOsBL6hwBsrBYDxgSPPB8geHH/EN51owdVL3oYL5i+HVDv6QkQ0jV4+th1bXn0Ge49tG/fcttdYmHOxXbHDomRyOQG+UtqFOzbcOH3vFExrCPz+8zKvrPg2BBdXCoDSgOLwcwG8QuWytKe7sPz8N2FR92Ws/ImoIfVmD+HZvf+FvUe3VRw7SLULui+3EUtFJ8FIEHw/ZXDbg5drYTrKO20h8P7N0hE4eCppZS6MPEmBgb0Gfb8KKu7pk4w1YdWSt+M1c5ZB2NVPRKeA/twxPLb9EfRmD0WeY8WArmU2MnOjf9SOBMHmtll46xcXqjvV5ZyWEHj/ZukIbPzIkcQljsRC1/fXADj0nI9ib/TzLbFw4fwr8Lpz34i4nZjychIRTScFsPfYNmze8ygK5ej3EFoWWJh9cfQSaSWTy4niR02Cm6Z6d7MpD4F3PCPN6Ti+H7MSK6ICICgDh5/z4Q5GP7sjMxfXLX03krH0lJaPiGimGfXx/CtPYtuBn0Wek+m2MGdZ9FTSksnlFNiwZDk+OJXLU09pCKz5maTiDr6jglVRYwBefvz+/wvmLcdlC66BJRNePJSIqOEcHNiDn+/+IVw//H2wVLug+7VO5AtmJwaLH16uH5+qMk1ZCAhEbn4Wj0BxQ9IODwB3SHH4F37k3P+Ek8IVr7ke3S3nTtX3IyJqKMVyDpv2/Cd6sgdDjztJwfwVNuyIlUpLQS4nwL0PX6F/OxXlmbIQuHmTfAzAvVEBUM4pDj/nRy721pxswxsW/Q6a4tw3hohOb6qKLa8+iX2920OPx9KCecsrtAiC3JBl4Z0Pv15/MtmyTEkI3LxJVsHge0kn0xp23C8qDv/SRxAxrt2e7sLrz3szYg4Hf4nozLHr6AvYefi50GOJWYKu1zqRW2qV/NwrloVVD6/QA5Mpw6RD4OZN0qUGTyftzMKw44GrOPJ8AL8U/pzO5vm4/JzVnPdPRGekQwN7sPVA+LYCyVbBnGVO5GCxa3I/9WfhLRsu0vJEn+9MpvBrHhHbmo8NKTuzMOydCDXAsa0BAldD5/d3ZuZh2dmrEGiABtlkh4hoRs1pWYCl6mP7oU1jjrmDit4Xfcy+OLyqVoPXO4O4D8CfT/T5k2oJ3LRRPqKKz0SNA/TtDFDoCZ/J1JLqxLKzVsGa+PbBRESnjQP9u7CnZ2vosdZzbTSfFd4cKPm5rNh4yzdX6saJPHfCIXDTk3I2bDybsDJdYcdzRwyO7w0PgKZ480gATKohQkR0Wnm1bwcODOwee0CA2UttJGZFzBgyuefnDGHlF3+79jeKJ1wLq2B9QtJdYSFSzikGXzahiyPZloNFXZfBwMCYCXdjERGddua2no+sexyDxd4xx/p3BZhzScQmNQaLj2bwZwDur/WZE2oJrHlS/o8F/EvCTo95nVcNcHRrEDkT6LzOi9HaNHv6/zWJiE5BgfHwq8PPohxSicabBbMviugWMvn+QHHl/79Gd9XyvJpbAjc8Kum2BL6UsNPpsMHgoVcNTBmRA8HNyVYE3BmeiCjSOZ0XYM+xrWNWIfVyikKPoqlzbAWblHS7q/l/APCWWp5Vcwi0JPAhBdrD2g9eXpHv0dBuoJidQGfzPPgTn8lERHRGiDkJtGe60Zc/PObY0AGDRKuNsCFVVaxa84S8ecO1+uNqn1VTCKx5XDIC3B7aClBg6BWNXOp5dvN8BOrXtFcwEdGZqi09G0OlXvijek40ALIHDFrOGdstlLDS6ZLJfwLA9IQAFH+oQHvYMEKhR+GVwlsBTfFmJGKpMV+GiIiitaW70JMb+0JwsV+R6lDE0iEVrsGKNY/Jmza8SR+r5hlVh8Atj0pabXwk6YxtBWgA5I+ayFZAS6oDAWcCERHVJBlLIeEkUQ5KY47lDinaFo6tdBNWOu2a/CcBTG0IFGz8gQCdoa2APh1e3TokBJJOE1QUHscCiIhq1pRoRrk4NgS8osIdUsSbx1a8arByzY/l2g1v1ifGu39VIbBunVi4Ch8OGwtQAxT7TOSGyYl4E2cDERFNkG3HYNsOgpA1+As9ingmvDVQ0vyHAExNCGy9Etdainlhg7ql/uFWQFhXkGPFIALOCCIimoSEk0TRy4353C8pyjlFPHxs4Pp3PipzvnO9Hqt076pCQATvi1vptIbMCCoORLcCbNvhYDAR0SSJZUXWs8U+RawppDVgN7WUgsK7AfxDpXuPGwLv+K40Owm8PawVUM4qNIgsG6AKnwPCRESTZosFE7K1sF9UBGXAHrOchIgo3ovJhoATx7ugaAobEHazGpkAAoGvHt8LICKaAirRx9whg1T72PcGVHHx7/5ALvu3t+oLUddW0x30nrA1gow/nEAS3QyAgnsEEBFNlaj61sspUu1jP0/Y6bQr+fcAeCHqnhVD4IZHJd1ksEJD1isq57RCPxAREc0UEwBeQeGkxlbKxuC3Kl1bMQSaPawKBLGwLh0vzxAgImoUXl7hJMdWymJwwZofSPeGt+qRsOsqhoAPrE5aTenRy01rMNwdJMIUICJqBL4LhG0NELebMsWg8EYA3wq7rmIIiGJ1WCvAd8FWABFRA1EDGA+hq4taBqtRawis+aHMhmJpWAgYt9KAMBER1UPgAqHbtiveGHVNZAi4Hq5IWMlU2NRQ3wNbAkREDcYvhw8OK3DW2/9D5n/vbXpw9LFK3UFLBJYVtmIoAmYAEVGj0TJC381KWE1NRa+wBEANIWCwJOzlhMAHE4CIqAEphqeLSsi0fhEsQcjy0pEhoIrFYYmiATgeQETUoCLraIPFYedHtwQUi8PGA9Tw/QAiokZlAkBCBodVsSTs/NAQeOe/yRwArWHHojaPISKi+lOjiKikF4V9GBoCgcH8uJ0KnRmkyu4gIqJGpWa4nh7zuWLuunVirV37m0uRhoaAH6A5ZlWo6hkCRESNK3z1Ztm0EBkAQyd/GBoCImiOWgKarQAiosYlQHgIKGDH0YxqQsAEyIStHIrIriYiImoEKuHdQXGrqalgCpnRn9fWEuB4ABFR44voybECNI/+LDQE1FRoCRARUUPTiLraANW1BKBIRFb4bAkQETW2iPrbNkiM/iw0BCyEr0sNcA8BIqJGF1V/Gx0bD07EiYXQJBGwJUBE1OhM+MeWojj6s6gxgSzs8JuwIUBE1NiievPVQnb0Z+HdQYKsRswOqrwXGRER1ZVGDQyrqldlCGiALMJmB4EtASKiRqa//p/fVA5KpaDalkBgI6ecHUREdOrRyLWDEC8hN/rz8BDwcLxsFYtxO5UKu5FEtBKIiKi+VIGIvWDK3/tDLYz+PDQEbAevqA8NfWHMMASIiBpW1Cqign1hp4eGwI9+T/Nv+aocgI7diYb7CRARNS4NNLQlIAYvhZ0fOdfHKHZqaAgoXxgjImpQJghvCRhgZ9j5lbaXfCksTUwAtgSIiBqUCRD+okCtLQFV7AwdXPA4TZSIqBFpgNC3hV2/WJxIS2BHySsWE85vzhBSBYwPWLF6f10iIjpZ4EW8KGag8UyNIeDH8QunjCKAMdNEAw+w4/X+ukREdLKgHLWRAJ7/wXt1KOxQZAj89ANauu5B2aiKt40+5ruKeIZ9QkREjcR3w1sCgcFPo66puBKQpXgcISEQuCN/YQ4QETWEwBsZExjF9YtFW/B41HUVQ0CBx1y/WIrbyeToA4ErcFJMASKiRhAUNXwfAQO31cXGqOsqvvu76ii2iGIAJ15DPulPOc+9JomIGkU5bxBWVwP4+YaPazHquootgbVr1Vz3j/JDKG4bfczLK9DBJSSIiOrNLylMeeznqsYo8P1K1467O4AafMPV0s1hXULlvCIxi11CRET1VM5p6IBw2SvnPeBfK107bghc04fHn2rHflhYNOYBQ4pkC0OAiKheVIFyVqO2E/vRk7drT6Xrxw2BtWvVrP6SfMNR3DP6mFdU+K7CSTIIiIjqwR3U4aUiRikHpRIM/nm866vaLNJSPFz2SnfFneSYF8eKvYrmsxkCREQzToFin4laK6iv8zj+c7xbiGp1s3xW/708GneSbw471na+xdYAEdEMKx1XZA+Z0GOeX3rgsY/qn493j6q3jRdgfdkvXT1mgBhAoUcxawFDgIhoxihQ6AlvBbhBaUgsfLGa21TdEgCA1X8nT8fs5FVhxzoW23CSVd+KiIgmoTigGNof3gpw/dKXnvi43l7NfapuCQCAGNxfNqVvx52xrYHsQYO2hXxpgIhoumkA5A6HtwLKfinrKD5X7b1qagkIRK5dj2fiTnJl2PGWBRZSHewWIiKaTkP7DQq94XV3OSh9+fE/1Q9Ve6+aWgIK1dUi97te6ZGw1sDQQYNEqw2rprsSEVG1vLwi3xMeAK5fKgjwQC33q6klcMK1n5P/iNvJ3wk7luoQtJ7PbiEioimnQO92A68wtt4u+6USBOufuEPvruWWE/rN7is+ql7pDXEn2Tb6WKFXkWpXJNvYLURENJWGDprIxTsN8HLrLNxf6z0n1BIAgKv/Vu4SxT1h3UKWA8y+hLOFiIimintc0bsjfDZQ2S+V1MLvPnWnjvty2GgT7r2fW8QXDifxHlW9bPSxwAP6dwaYs8zhKqNERJMUuIq+XUHoInFe4LoKfGciAQBMoiUAANd8Vq6C4CcxO5EIO57uttC+yK7TPxsR0alPFTi2xR9eJC6EF7hHEoILfnyXDk7k/pMKAQC4+rNyNwR3RwVB+yIbzXPZHCAimoieHcHwm8EhPM8twcaap+7S7030/pOezHldGff/OIYrjZjftsQaU9v3vxTAsoF0F4OAiKgWA3sCFI5FBMBwN9AXnp5EAADjbC9ZjbVr1ZQ8fCAIvH2hW5sp0LcjQLGP21ESEVVr8BWDoVcjtowc/vN0zMOnJvucSXcHnbDyXllhC/4r5iQyoQ+ygO7LHE4dJSIax9ABg76dQeRxz3dfLftYsfkePTLZZ01ZCADA1Z+RG1Xxz1HjA5YNzFnmINXJICAiCjP4ikH/S9EBUA7cbEzxW4//lT47Fc+b0hAAgDfcK3cIcF9UEIgAnUttzJrPMQIiol9ToHdngMFXTOQpnu/m1MKNG++e2HTQMFMeAgBw1Tq5D4I7ooIAGJ41xFVHiYgANcCxLQFyRyoEQOAWBbj16U/pv9Zw63FNSwgIRK5chy+J4vdjTnQQNM+z0HWpzRfKiOiMZXzg4GYfpYHoutjzXVcVt/9snf7TVD9/WkIAGA6CFffgIUvx7kpBEG8WdL/ORmIWxwmI6MySP6o4+oKPoBx9jue7LoCPblynD05HGaYtBICRFsFa3CuKOyoFgdjA7KU2Ws9jk4CITn9qgN7tAQb2mIrneb6bBfDHGz+t/zJdZZnWEDhh5afkjxVYH3cSTZXOy3QL5i53uB8BEZ22/BJw8Oc+Sscr172e7/aI4KaN6/Qn01meGQkBALhyrbwDBg/FnURrpfMsB+hYYqNtkcWxAiI6bQTl4V//x/eFbwt5Mi9wXzbA/930ad0y3eWasRAAgBV3y3IRfFdgdTp2LFbp3HhG0HWpjUw3xwqI6BSmwPGXDY5tCyr2/QNA2XddAfYZ4PrN9+n+mSjejIYAAFz9SWkrC/4fBO+MVxgnOCHdJei8wEbTHIYBEZ1CdHgv4N4dBu7Q+PWs57tFCNb7Pfj0Lx5Ub6aKOeMhcMLKv5Q/MMADMTveWs35qQ4LnReMvGTGPCCiBqUBMLAvQN/OAOVcFZV/UC4DOAKDWzd9Vh+b6fLWLQQA4HV3ybyYjX8HsCxmx+PVXJOYJWhbaKPtfBtWrJoriIimn19S9O0I0L8rgAmqu2YkAB6VBN7787U6VI9y1zUEAGD1OnHyRXwQgrWOFZsjIlX9zhcBMnMttJ5rYdbZNmcUEdGM80uKwVcMBvbVtlLySOW/D4o7N//15JaCnqy6h8AJ1/yFzC4G+LQl+IBjx2vbnXgkEJrnWkh3WUi1C7uMiGjKqQEKPQa5Iwb5I4r8MVPT9UaDIAiCrACfa0ph/U/v0VK9v1PDhMAJr7tDznEsPATBG6rtIhrzpezhJSlSHRYSrYLELEGiRTjllIiqpgFQGlC4Qwp30CB/TFE4ajDRKtMLyi4Uj4iDj226X/vq/f1OaLgQOOHKT8iqwOBOADfE7Pi4s4iqEc8Mh4EdA6yYwIoBtjPyd3YnEZ1xAg8wnsL4v/n3Yr/CL05N3ej55ZwC3xQL65/9G91Z7+88WsOGwAlX3inLAsUdELwrZsebJn9HIqLpFRjfN8YMieCr5QB/98Ln9WC9yxSl4UPghOUfkwXq4H0iuBXAgol2FRERTRcvKLuq2CTAN+MGGzZ+XvvrXabxnDIhcLLL75DLBbhJFDeqoJuBQET1MjLT5yUFvmkbfGvz53VvvctUi1MyBE624k5Z6StWW4prVbASQIKhQETTZaTSHxLgSVU8oRYef+4B3Vrvck3UKR8CJ1u9TpxCHitNgBsUOA/AJSJYpIDFYCCiWnlBuQyFr4IXBdgOxS8tG08++wC26GlSeZ5WIRD6BdeJdXke56mPRSK4WIBWBWYBaIYgA6AZQFoUtb2bQESnPCMoWIKcKnJQZC0gbwTHLeCgJ3hJA+za8gUcOl0q/DCnfQgQEVE0vj5FRHQGYwgQEZ3BGAJERGcwhgAR0RnsfwCReA5ROFftiwAAADt0RVh0Y29tbWVudABFZGl0ZWQgYnkgUGF1bCBTaGVybWFuIGZvciBXUENsaXBhcnQsIFB1YmxpYyBEb21haW40zfqqAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDA4LTEwLTE0VDE2OjQwOjIxLTA0OjAwPdgB9gAAACV0RVh0bW9kaWZ5LWRhdGUAMjAwOC0xMC0xNFQxNjo0MDoyMS0wNDowMGJpd8IAAAAASUVORK5CYII='
+
+ red_pill64 = 'iVBORw0KGgoAAAANSUhEUgAAAYEAAACCCAYAAACgunQ+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAl2cEFnAAABgQAAAIIAb/yLCQAAF7hJREFUeNrt3XmUXGd55/Hvc++trat6UXdrX7CNFtsysh072MaKsEmwgZBZwjiEIcmBTMgk4TjAxB5D4sEWJmYmYLIME47P5GQ4k7AEH5IzJIRgwDGObSy8ypElZEmWhXa1WktXVXct977P/NFqjum+t7p6rWrp+ZzTx3K9de99q/54f/Uu972iqhhjjLkwea2ugDHGmNaxEDDGmAuYhYAxxlzAglZXoJX2rpNMOEIhGibv+2RbXR9jzPwKHMOBo3TRGc5ygU6Qyvn6uQ+tllypzlpPWSuwVmGtKutF6BPodkqPgABIJpORVDrd6jobY+aXGy6Xcc6d+98KUFY4CxwG9nqwV2FvBHuH1/DqNc9ovdV1nm3nTQj8cJX0eXW24NiswhZgvYB4hc7OVtfNGLOwuVKxqEpdhO0I/yIhj4+keHLTMS23um4ztXBDQET2LmOLi7gF5ecQLrNf9MaY+eBKxaKCE3hO4BEnfH3DcX2x1fWajgUXAruXyiaUX0J5lwgr7Ze+MabVzvUUdonHV/2Qr75+UA+2uk7NWhAhsHOjpIOT3A7cjtJrDb8xpl1FpeKQB99X5W/Xn+QvUHUzP+vcaesQ2LtcFruQ31bhA0C3Nf7GmIXClYpFFQ7i+LPCSf7vKtWRVtcpTluGwI4+WR14fEiFX/M78r14nj/dczlgKFKG3Ojf2UipqRIq1IH6uX+H7fc1GGPmWCCQEkiJkJLRNfMZEXp8ocsTunyh4MnoMsJpcqViEeGUKp+v1nnwqtN6ptWf+7XaKgReXCb5lONjqvy239nZO51zFJ1yLHQcD5VTznEmap/PZ4xZmHp9od/3WBZ4LA+EjEw9FtxwuazOnUb55OWjw0RRqz8XtEsIiMjOXm7D4z5g+VSGfRxwsO44ETleqUfU2+DjGGPOb92esCLwWBl4LA28KfUUXKlYdMoO8blz43F9otWfpeUh8NJyuVxDPi9wdbONvwLHQ8erdcfB0Bp+Y0zr5ER4XcrjopRPr998HLhScUiFrwn8/sYTeqxV9W9dCIh4O/v5sFP+oNmhn7rCv1ZDXq5FzMZ0u4jQvWoNQTqNn8kQ/PgvCzMaBTTGtCclqtcJq1WiWpWwWiWsVBg+PUi1WJzx2bs9YUPa55K03/TGbK5UPAR8cOOAfr0V30hLQuClJbLMOR4U4eZmfv0PO2V3zbGvHk1rAjeVy7F4w2Us3nAZ+b5+8v2Lyff1k+3unvfPboxpTy6KKB47SvnkAOWBAU7t38fg/lcYOnoYpthO5kRYn/FYm/JJNfF70pWKRZT/UxzkozfM8yqieQ+Bl5bKrU75vJcvXDzZe0OFHdWIPTXHVGqZzudZdc0b6V+/gf51G+hYNK05ZmOMwUURg/v2cPrAqxx6ehunDuxvOhR84NKMx2WZyXsGrlwqAbucz/uvPKovzdfnm78QEJHti/mUwAe9fKHQ8MsA9tQcu6rN//LvXrWalVdfy7IrNtG9ajVMY/beGGMmUx8Z5sgLz3F85w6OPPdMU5uP5kTYlPVYnZp8kCgql4bE4z9vOqZfmY/PMy8hsHOjpOsD/Dnw7skC4HiobK9GlNzk9Urlcqz8qZ9mzfU30r1qzXx8X8YY82O1UpGDz2zj4FNPUDw++dxuvy9cmfXp9hr/SI3KpaIoW68c0Afm+jPMeQhs65OujMcXgZsaBUCo8Hw14nA4+ZRvpqubDW9/Jyuvvhbx7Lk4xpjWO/HDnfzoqSc4sXPHpO99fcrjiozfcPnJueGhv9hzkjtum8N7CuY0BJ5fLCtU+ZoIVzQKgNOR8mw1YniSX//5xUu55Ka3sGzTVYhY42+MaT/Fo0d45dHvcHznjoZzB72+cE3WJ9dg6PpcEHzDpfj1a47o8FzUd85C4Add0hek+RevULgs6T0KvFJz/LAWNZz4TeU62PCOX2DJFZts4aYxZkEoDZxg5989RPHokcT3pAQ2ZXyWB8k/as8FwQ+6enjH2j1ane16zkkI/KBL+vwM35J05g2SSsXu7x8Bz46EnGywrYN4HiuveSMXbbkJP52Z9XoaY8xcO7FzB/u++zC1UvJ9CGvODQ8lceVSSYVvyRreM9tPN5v1EHhisXSm4RteOnNdUgDUdDQAzjYY/iksXc7G//BuUh35Wa2fMcbMN41CDjzxGIe2fT/xPcsCj03Z5KWkrlwqoXz12kE+MJvbU89qCHx/teSCCn8rsDlpDqDslGcrjcf/V1x9LWtu3IL409481Bhj2s7p/fvY++1vEo7E3w/W6wtXZ4PEG8zGJouvHdCPzFadZi8EROTpPh5S4VY/IQCGnPJMJUxc+x/kcrz+LbfQveai2fp8xhjTVmrlEvu+808UjxyOLc+KcF3OT9ypNBrtEdz3xpP6R7NRn1kLgW198mGE+5ICoOSUZ6th4mZv2Z5FrLv150nbc2OMMec5dcqPnnyMkz/cGVue94RrM8k9gqhcGvLgF3/6pH53pnWZlRDY1iubncffB/lCT1z5iCrPVUKqCZfKL1nKxTe/lSBjk7/GmAvH8X99gaPPPxtb1uUJV2cCkjYmDculA56y+bpBPTSTOsw4BLYtlaUu4nE/X1gbV15V5flKRCXhOp3LV/K6LTfbTV/GmAvS6f37OPRU/GMFenxhUyZoNFn8z11LedvlL2ltutefUQg8JOKv7OURv1DYEltB4LlKmDgJXFi2gtVv+hkLAGPMBe3Mq69w5JltsWW9vnBFJogti8qlkiifv2FQ/+t0rz2jEHhyifyuOv4waR5gdzViIIpfyZTr62fV9ZvxbAWQMcZwat8eBl56MbbsopTPqoTN58Jyqegrb7thUJ+cznWnHQKPrZTVfo2nvY7C0rjyY6HjlVp8AKQLnax602Y8P8AYY8yowZd3cXrf3gmvC7Ax69OVsPGcK5eeH1rEDW+fxh3F026FpcYD0pFfqjEbPpSc8mrdxe7m7AUBS6+8CpzDuWkPYxljzHmn5+JLqJ49w8jgyQlle2oRb8jEP6TGCesLp/k94P6pXnNaPYHHFsm/wedLfkd+wu28DnixGiWuBOq//Ao6+hbP/bdpjDELkAvrHH3uaaLqxB/1nZ5weTp+WMiVy6c05PotZ3XPVK435RB4WCSf6WOX35FfHVd+oO44kbAfUGH5CrovumR+vkljjFmg6qUiJ3a8GLsL6cUpj/6EdaNuuPytLSf1bVO51pSHgzL9/A5K7PMay04ZiDR2p08/k6Fz+Qq0ZkNAxhjTSJDOUFiyjPLxoxPKDoWOHs8niGloFTZ/r0/e+uZB/XbT15pKxR4VKdDH7X5HPj8+nxQ4EGriVs+dy1eiYTilZwUbY8yFKr94MZVTJ3H1n9w0NNLRIHhdzGohryOfd8PljwJzEwLaz2+i9MY15AOhUnHxIZAudJLK5nC1Wd0B1Rhjzmv5xUspHZl4Q/CpSOnzlXzMaiEH1z3SL295y0l9pJlrNB0CDy+TvK/8bhDTC4iA45FL7AXkevtwdRsGMsaYqUjlcgSZLFG1MqHsSKisTU9sdc/1Bj4GzG4I+HV+A6E/rhcwGCkOYpeEBh0dCIpaCBhjzJRlujoZOTkxBEZUGXJKZ3xv4IZvL5Y3v3VAvzfZ+ZsKga0i3o29fNDP5fPjJ6sdMBgm9wLSuQ5caMNAxhgzHX6Qwg8CXBhOKBsIlULMjQNeLp/Xcvl3gNkJget7eLPCirhewKmxXkBMmRekELAVQcYYMwNBJks9LE14vaJKySXODdzy8DJZcssxPdHw3M1UQDx+xUtYEXS6wVyAHwQTZraNMcZMjed5ie3sYKR0xISA39HRHVWG3w38z0bnnjQEvr5YOjPKL8T1AopOiRocqyjOegHGGDNj4nmom7gf24gqNWXidhIiosp7mWkIpJV3qdCRFAJJ6YQIWq/bfQHGGDMLpEHZkHP0+hPvG1C44h8XyVXvOK0vJB07+XCQ8stxewSFCiONQkAVoghjjDGzI6m9LTmlN2ZXfr8jn5eR8i8DLySds2EIPCySd4u4Lm67opIq0iiajDHGzIsIGFYlF9MoO+VnGx3bMATqvWwWJRW3x1y5US/AGGPMvCo7JevFhsCl/7hElr3jhB6LO67xcJBys9fRkR//zICI0eEgsRgwxpi2UHWg3sRf7H5HRyEaHr4J+ErccQ1DQIWb4yZ2q4o1/8YY00YcUFdidxd1ws1MNQS+2SmLNc3G+BCwoSBjjGk3VQU/fovpm5KOSQyBeoo3eplsLi4E6s56AsYY025qquTiW+dV/9AvK995Ug+PL/ASzyZswPM8ZfTO4LG/UMEWfhpjTPup6U+212N/Xq6jox6yIe6YxJ6Agw1xeRKCLQ01xpg2FRH/614CNhCzvXRiCKhjfdzS0MgmhY0xpm1FLv6HuotYH/f+5BAQ1sfNBzhsUtgYY9pVBMTcPIzKFIaD/q5TlpCiJ67MWU/AGGPalkOJbaWVdXHvjw0BF7DSz+ZiVwYlnN4YY0wbcBC7cacKy7eKePeo/sRWpLEhEEGnJ8nTvxYCxhjTphQ0vpGWtb0UgKHXvhgbAiJ0Jm0BbQFgjDHtLWkUJy100kwIRI6Cl3ASWx5qjDHtS4gPAS/X0eGKw4XxrwcJJ+mMWx5q8wHGGNP+NGEoJ/LoHP9a/MSwJvcEjDHGtLfEtlporiegQsbmBIwxZmFKar+dIzP+tfibxbzRh8THsWcIGGNMe0tqv1UmFsT3BJThuFMI1hMwxph25xJeV4+R8a8FCSco+gknsRAwxpiFyVOK41+LXx2kFJPWmQaWAsYY07aUhNVBqlpPNxkCERS9hJkFu0/AGGPaW+wO0JVKxQubDAHfp2Srg4wxZuEZe5BM3OuVTkrjX48NgXqNM54bGfGzuVzciZIfR2aMMaaVVONDIFJqv3lEh8e/HtueB3kOuHM9ivF/zu4YM8aYtjW2i+j4P4H9ce+P7Qn86jEt/2WPHFImPonGYUNCxhjTrqKEuwQcvBz3/uQniym740NA7YYxY4xpU1HCcBDC7riXk0PA4+XYcSVshZAxxrSriPgQcDLVnkDE7rhlRnUFsZlhY4xpO5HGz9uGlZERdKo9gYBd9crISDBuhZACoULKegPGGNNW6glDQQ60EEwxBNLdPFM7xQgwYZloXSFtIWCMMW2llvAgAU95/r2DOhRXlhgC79uvlQe75UmFd44vq6pSsMlhY4xpK9XknsA/Jx0TNDgf6vFofAiM/tdiwBhj2kNdRyeFxwsrIyMiPJp0XMMQAB4JKyMVP5vNvvZFBaoq5GyZkDHGtIUR1dg7BBxUq508mXRcwxA4fobtS3o4rbB8fFlZlZxnIWCMMe2grC7piWJPfeSgjiQd1zAE7lF1f94j31Tl1ydcMFL6fNtHyBhjWq2iSi3mSTLqnEP5RqNjJxsOwsEXtVL5j3FDQmWndFlvwBhjWqoUxW8VUa/Xyjj+ptGxk4bA4Fke7e3ioAfrxpcNRUq3hYAxxrSMAkWX8FRhx7duL+pAo+MnDYF7VN3nuuWLCveOLxtRpapK1iaIjTGmJc46jV0VFFUqFQd/Ndnxk4YAgAp/Xa9W7goy2Qk3jp2MlNX2zEljjJl3CgxGLmmvoMEzq/inyc7RVAjcfkb3/WmPPA68dXxZyVlvwBhjWuGsU+rJz3j50j0vaW2yczQVAgAoD4SVys+MnyAGGIiUNbaZkDHGzBsFBhJ6AVGlMuQF/Fkz5xHV5h8V9ifd8rifyd4YV7Y+45O1HDDGmHlxOlIO1l1sWVitfO4jZ/X2Zs7TfE8AcHC/q1S+FsT0Bg7XHWvTdteAMcbMtQg4Gsb3AsJqpagen2n2XFNqtf/LEN9U4fm451cWnTIY2QOIjTFmrh2pO2oa/yxh4K9/77QeaPZcU+oJoKrSJffXK5WHYnsDoaPH87HFQsYYMzfKThlI+MEdVivDCJ+eyvmmNCcw5jNd8g9+NvvzcWV9vnBJyoaFjDFmtimws+oYjmm3w0qlIsIDd5zVu6dyzqn1BMYq4vGheqXypiCbXTS+7GSk9PrKIruT2BhjZtXh0FFO/uH+alee+6d6zmn1BAD+qEvuUrg3blgoEHiDrRYyxphZcyZSdtUSVgNVKhVP+Pd3ntVJbw4bb9ohsFUkne1im5/OXBVXnveETdnAdhk1xpgZqqqyvRLG3hgWVatVlK/dVdT3Tufc0w4BgE91yY0C3/UzmUxc+bLAY13ab9HXZowxC58C2yshRRffVkfV6jEJuPSuU3p2OuefUQgAfKpT7hbh7qQgWJf2WR5Yf8AYY6ZjVzViIIofBqpXqxUffumuIf376Z5/WhPDr1UrcX+qi+vFubeL501o7V+uRfjAUgsCY4yZkn31iBMJARBVq1Xgj2cSADALDwa7R9XVlfdFYX1/3I0LCuyqRXYjmTHGTMGBuuNHdUdSu6rC4/UiH5/pdWY8HDTmvg65TlJ8J0hnCnHlHnBVNrClo8YYM4lDoWN3LUosD2vVH4UR191b0mMzvdashQDAH/bIber4q6T5AV9gUyag37cgMMaYOAfqjpcbBEBUqxYVfva/ndWnZ+N6sxoCAPd1yR0on0wKAgE2ZnxW2l3FxhjzYwrsrkYcSNgZFCCsVUuecNvd07gfIMmshwDA1k75pMAdSUEAo6uGbNdRY4wBB2yvRBwLkwMgqlZH8Hn/x8/o3zR/5snNSQggIlsLfE7hPwUNgmBF4HFl1rcbyowxF6xQ4QeVkNMNFs+E1WpVhdu3Dun/nu3rz00IAIjIvXm+oMK7GwVBpyf8VNanyyaMjTEXmOOh8kI1pNagGQ5Hl4J+aGtRH5yLOsxdCACIyD0F7lO4o1EQ+IzOE1xs8wTGmAuAA3ZWI/Y1GP8HCGvVIo7f+kRJvzRXdZnbEDjn453yW8ADQSbT0eh9ywLh2kxgzyMwxpy3KgpPjYSccY3b3rBaHRDlPVtL+t25rM+8hADAPV3yb53yhSCT6Wn0vkBgQ8pnXdqzuQJjzHmjprCzFrG/Hv9YyNeKatVX8fl3nzit2+e6XvMWAgB398i1EvF1xOv3U6lUo/cWPOHKrM8y6xYYYxYwBV6tOXZUo4Zj/3Bu/F/YT8QtnxzWg/NRv3kNAYCP9cgiCflfAr/YaJ5gzNJAuDTts8TCwBizgChwsO7YVXUMucnb2bBaHRHhgYESn3hQtT5f9Zz3EBjzB13yGyif9tPpnmbe3+d7XJrxWRl4WBwYY9pVBOyvReyuRZSaaPyjWq0GHHPw/k8V9ZH5rm/LQgDgrrys8H3+H8omP51ON3NMlyesTftckvJJWRoYY9pERZVd1Yg99Yhm98uMarUawsOZFO+9Z1CHWlHvloYAwFaRYKTABwTu8VKpJSLSVNMuwPLA46KUx+rAtxVFxph5V1HlQN2xvz61nZLPNf77Fe787zPcCnqmWh4CY36/UxZH8AmB9/npdHYqx44FwvLAY6nv0euLDRkZY2adAwYix7HQcSzUxL3+k2gURVEUFYHP5Pp54N79Wmn1Z2qbEBhzR05e5wV8QeBNzQ4RjeczuiVFn+/R4wldvtDtiS05NcY0LQJOR8qQU846x4lIOR5Ovrwz8Xy1WlWFhwL48P1DOtjqzzem7UJgzEe7ZLNT7kS51U+nJ11F1IyCNxoGKYGUjP43EEghNpxkzAWorlBHCfXcv3X036ciZWSW2sawXisBX/aEB/7HkO5u9Wcer21DYMydBdmkcIfAu/x0umPmZzTGmLnlwjB0zg0J/GXk+JPPDuvhVtcpSduHwJgP52RN4PEr4vF+lDXTHSoyxpi5EtVqVYVtKF92AV/97Fk91eo6TWbBhMBr3ZGXa/B5jzpuE1hmgWCMaZVz6/xfRvmyi/jKZyv6SqvrNBULMgRe684uuUEjblaPNwvcgJKxUDDGzJVzjf4QwmMK3/OURz9d0hdbXa/pWvAh8FpbRYJyJzdEyq0oFwNvEFgHeBYMxpipimq1mkIo8BKwU4XnfOWxT5fZrudJ43lehUCcrSJeOcPFYcA6gSsQenB0IXSKUAA6ceRVmNK9CcaYhU9gWKCkQkmVIkJZ4AzCYanzciTs+eMRjpwvDX7sd3AefzZjjDGTsPunjDHmAmYhYIwxFzALAWOMuYBZCBhjzAXs/wOhrcv9WD6DSAAAADt0RVh0Y29tbWVudABFZGl0ZWQgYnkgUGF1bCBTaGVybWFuIGZvciBXUENsaXBhcnQsIFB1YmxpYyBEb21haW40zfqqAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDA4LTEwLTE0VDE2OjQwOjIwLTA0OjAwm68KQgAAACV0RVh0bW9kaWZ5LWRhdGUAMjAwOC0xMC0xNFQxNjo0MDoyMC0wNDowMMQefHYAAAAASUVORK5CYII='
+
+ button64 = 'iVBORw0KGgoAAAANSUhEUgAAAoAAAAFACAMAAAAbEz04AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAMAUExURUdwTACK0gtEiwJMiP7///j5+v///wf//wCLzwCe3guh4wCL0QRXgQCMzwNUgQRaiACR2gBytf///wCW4Ax4rQCW3gCa6ACY4wJWhACJzgRUhgVRgApeigCY4QCV4QNbigNdiwJZhwCb5wCW4ACT3ANbigNZhQCU3QCGygRejK3R4wCN0gJOfQCa5gCM0ACY4wCP0QCS2QBEegCV4Ljb5keNsit3nQCc6fb7/qrP4wAAJn2wyQCIzACKzq/S5Pr//9vu+Pz//9bt+dXo8uHv9L/d6Zq9zzaPvwCN0gJ0rQJupAGBwACLzwCM0QJsoQGFxgGGxwCGyAJ1rwJ2sAF/vgGAvwCM0AF6twGCwgJ3sgF8uQF7twF9ugJzqwJ4sgF+vAF6tgJwpwJyqgJvpQGCwQGDwwJ3sQF5tQGDxAF5tAF8uAF+uwJtowF9uwJyqQJwqAF/vQJxqAJ1rgJzrAJ4swJtogJvpgGExQGFxQCHyQCIywCKzQCKzgCIygCJzACHynGguGyctm6et1GOrWGWsXSiuVuTsFaRrmaYs0SIqnmlvGmatGSYslSPrl6VsTmDqEGGqoauw1mSr3ajuk2MrE+MrUaJq36ovouxxYOswY6zx5a5ynynvTF/pzuDqUqKq5O3yYGqwJC1yKC/zy5+pjOApzaBqD6FqYivxJu8zSt9pavG1Sl8pZ6+zq7I1iZ7pZi6yyJ4pKPB0abD0rPM2SN5pKjE0x93pBx2o7DK17XO2rrR3Bl1o7/U37fP273T3sLW4BRzoxd0oxFxosXY4sfZ48rb5A9xogxvos3d5tXi6tDf59Lh6AluogZuodrm7Njk6+Dq793o7eLr8Ofv8+Xt8ezy9enw9O/09/////L2+PT3+QCQ1vf5+wNXggJnmgNqnwJikgJklgVZhANdiwNfjgRbiAJpnQFroACa5gBRfgBGdgCT2wCX4RBgiQxsni90mApijyBqkA1olkmFpEKAoYivwzx9ns7j7uP0/TV4m4270eDq8K7S47fX54myxnvpTJMAAABIdFJOUwDvAQME+1UB/hAD/Pz9/e3YCP2+HIg5dtf9OibGSiZ1Sl5TzeuMrfbvoErL863ks66ZkKgrhvSo7cMSv7lakM7DrJLw993z55DmvZgAAA1sSURBVHja7N1XbFNZGsDxIxsGEVm2YuUhciIBD0FKxBOC0RRp+z7srsTDFm3vvffd1xR6L0MNMCwBBgiEFgZIGUKHEAgJIYmDuI5973VGvlIabYaZXe25thNMGiHx4T7w//kFI5G8/PnO/W5sRwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8VK5prmkZU/DKysjIkA040l48PP4Lwm5hyhS362Vm6MqYMi3xhynz5hUUvIZXVEFBwbystzKTGbozXC8xvukFr33h8599Y+q9IF5pHV/88ptvz58VeCteh9utNEKXO37q5hR85nNvJL+//95UvLL894J+2YA/+HF5UW7erBy7DnUNutz2lw/Mf/NLdnn3pnZId+/ewyuto6O9Q5Yoi/j4k9dz5wbsEaUkwXh+gflvfyS/1dT21nbZHpDQ0dHaOlUOwo+Ko9lzAyoStPPLmZFbbtfXKusDnnW3XU4l2WD5MSt7RlaaE7R37Jy5r/9X1tfW2g6MorXtrt9f0WvNyctJVJOe2zzyCwXmvv6/oL+1pRUYU0t70F/da3nz05agPHwDs/VPgv6WO23Ac91pCwZ3aVY0PxCPZ/L5ZeVbS1r8d263AONyuyXYssTSzPysySboyhCuGXPuV/nbm+4A49bUHqzutkzfDLeYzM9H7Iu/XOtBm7+p6TbwApqa/K0PLK0vNxDPaKLHb2ZeLLbV39bYBLygxrbgI8syjLzMCR7DLrfIyY3ptcHmxmbghTU2B2u7LY+ZmzOhm4Lyn8zyWf3Nd+sbgQmp72jqtzxR36wJHMPy+M0PW7132hpuARPU0NLyxPLoZv4LH8P28WtaD1s/vV4PTNj1T+Uq4k0cwy/WX8BnWg/aG683AJNw/VZHiaV7DF/gRQp0i5k+w3rcWn/tOjAp1+pbH8oCo76Z4y/QLWYZUau3qf7yNWCSLtff7pUF6sas8RZo96db/fX1ly4Dk3ap/la/pXu18RYo+wt7YvqlWxcvAWlwsf6yHtO93vC4CpTXf4bHa5U1110E0qKu+YSl6V6PMY7rQLn/GrrHWtF0tg5Ik7NNxZaueXXjubuwW+T4ZH+9jXW1QPo0PokX6HvO/UC3yMqOygvA2kvVZ4G0qb54MRqTBUazs8Yq0OV25xoezdrfUFUNpFFVwzZL0zSPkTvW+4bdIs/06NaThqoPgLSqarAPYc1j5o0+AuUCbHo8sVh5XWUVkFaVtRWxmD0DzVFXYXkB6NO9urX62plKIM3OXFtoj0C5iIxyGZi4ANRj3bWVZ4C0q6ztjunxy8CMES8D3WKG6dF0a9HF8gog7crrltsjUBY4Y6QR6HLl+HRNDsAPKsoBBSqq4yNQ0305I7xl3S1mG/YAXFp7/H1AgRNni5IjcPbwERjfgOUA1CvKTwBKlFcmRuAIm7DLlZkd9coBuLi67DigRFl1fBG2fyCSOeQQTmwgmhY78P7hMkCNE2Xxe4FyBA7ZQ9yuLLmByAHYW3ngMKDIgcre+AjUNF+Wyz18AOpWccXRA4AiRysKEwEOGYEu13Sf7rVXkMMHSo8CipQeKNPja4hX901PuQocHICPK3aVAsrsqng4wgiUK7A9AGWAhcd37wKU2X18USJAOQKfLsIDK7AW21a6bTegzLbS3Vp8D04dgS6X274HKC8B+8u2AUqV9ccSIzCaPfAL5jJEwO5PnsAPyx5tARR6dPhB8kaMNxqQ6SVO4PzkCVxUum4/oNC60uLEESzP4PzEGewS032JJmPrtqwDlNqyP3kRqOm+6fGPDbQ/iSMxAPUt67YCau1OvCDBflFM4pMSEq/DsneQ7i3/AdTavKt/MMD4q7IGT2A7wM2AWtt3P04GmDyD3WJmfAe2A1y3HVBr+ZaNyTVY7sH2ywLj7wVOBrh1OaDWhq0Lk0tI8j3CrmnZgxNw8wZArUXbiwYC9Eaz7V+EmTUneSLLABcBii0vHAhQ0+ZkyS14ZuImjB3g8kJAsQ2LBgO0PzBQDFwCxgMsBhQrLBwcgPZFoEjeBYwHuKEIUKy4UBvcQozZQmQmdxA7wMIVgGJFxXrKFpIpcuYk78pose7ipYBqRYMBavqcHDEzqg1uwUUrAcWWrtC1gZmnRWfar0TQE7TuFQsBxVbaASbZr0fISwlw6WpAsYUroykB5onZpieaoHWvXAyotlAGmEzOY84WuaYeTTy07oXrAcUWr5atJZPTzVyRbQ7kqHevXgKottgYKE4GmC2yB5/qfYtXAYotWR99GqCRLXzGwLNo3/oSQLFVS6JPGT4Z4AC9b9VGQLGSEtndIJ94+iTat+odQLGSd1P6MwxhpARY8i6g1qaSNaMFaPS9swlQa1nJQd1MDdAcJANcBqi1dmN/1EyRGqC5adlaQK1NfcYoAZrGmrXvAUqtXfNMfzLA8MAjbBxbtmYnoNCaZceMsJnyEOGnjPtr1wBKrb1vhlOlBhg29+zcByi0c8ez/Q0J8MLOvYBC7/WMFWA4vGPvDkCZvTvC4aEBRlIe5oV9ewBl9l0IPxNcJCwiqcLhQ3sOAorsORSODPFsgJHw/R2HADWO7Lj/vAAjkZqDRwAlDtYM6294gJFjR04CChw5FhlOhIaIhI4cAxQ4IuMaRkRCzz5CkZ6Tp4C0O9kztDX7IYY3Gek5dRpIs1M9I8y/0EgBhkI9p0/XAGl0+nRPKDTuAEM9NTXngbSpqRmlv5DoGkmo89z5c0CanD/XGeoamRjl77uunrsApMW5q12jEp2j6Lp55cIVYNIuXLnZ1TVaZp2jBijduApM2o3OrjEiGyvAzs6bN4BJublgzMI6xYdjW3ATmLAFHz6PWAA4SPwTcJD4A+Ag8VXAQQQIZwP8OeAg8S/AQeKngIPEnwEHib8CDhJ/AhwkfgY4SPwQcJD4O+Ag8RXAQQQIZwP8G+Ag8XXAQeIbgIPErwAHie8CDhI/Ahwk/gE4SPwWcJD4NeAg8RPAQeLbgIPE9wEHid8BDhLfAxwkfgA4SPwRcJD4PeAg8WPAQeIvgIPENwEHiW8BDhJfAxxEgHA2wF8ADhLfARwkfgk4SPwGcJD49//buZvdRpEoDMNn8AIbhAQigLywF4BkS1b+lEVvuvdeDEqyybVMfnrmRrkBpKp7mMKOO07GSTuJoUbK+2yya0vk0/lOlekAFslfgEVyCVgkV4BFcnkNWHMp85+3gCV3c5nfXf8DWHHdBvDh6idgxdXDXMKb6zvAiusqlEV9+zdgxW29kO/1+B6wYlx/l3M1fgBsuB+rc8nU+E/AirHK5AcBhL0A/pA0qG4AK6ogldG8HlaABcN6PhJ3oYIlYEGgFq7IhfZ5FLDB1xcikjUEEHYC2GQmgKka8ihgw1ClJoCjsiaBsJG/uhyJeBKzBMLOChib+HksgbC3AnoykJQKhp0KTk38HIlCbgLRv0CFkYmfGYIJHQwbDZyY8LUB5CIGNhpYpasAOg4dDDsN7JgGpoNhtYHbAE5nFSWMfgu4mk0fA2h+nHIXjZ4HoD7d5M/8nLAEou8VcPIrgOYcwtdx6HkAxusTyGYEEkD0G8CtASjiDhaKBKK//KnFwH3Kn8lizghEnwMw3x6AZgn0uIxGjyeQ0NtaAddbIJfR6G0ANs82wHUCzyhh9FXAZy/zJ547nS2HPBt0b7icTd2XAVy9GT3m4aB749Wb0C85Hi/FoKcTSOQ5/wng+hxyw/NBt252nEA2CUw4h6D7E0iyO3+mhD2+Ekbn+Yu9XQW8HoFHZc0aiC4XwLo8emUAsgbC4gL4aw1s/IrnhG5UT+/h7+Z63hlfyaGzBbA58zxX3kqgE3EQQXcHkMh5M39tCY8KzTci6MBYF6M3C3hzFA4VCcTh86fCo9/nb/W/NEtej8bB+1eV033yt0pgyB6IQ+9/4Z75W7VwobmNweFUvi6O9s3f6iQScyONg7nxm3i0f/5EBhJdND7fyuEgAr+5iEyo3sGENdE1iyAOsf7VOpH3zL/1jbTkJYsgDrH+lbn87v5592E4bgJqGJ+r36CJp+8df5sEDpJG+UMeIj5q6KsmGXwsfyaBjkzCZskmiI9uf8smnIjzwfy170hLlM00PYyPta+eZZG89v7zvqfh6bHpYSKId9+9qOZ4KuLJp7TjMy+0CihivKd8A6WLXD43/h6HoCdeXjT6nuMI9j163OumyL02O4fQ/it5rPWSJsY+3bvUOs7l0+37vIdlcjpr1NAPuJvGq6rAH6pmdjqRg7Tv8ysZmSahalTl08XY3bx+ZQISJlP5xNXLW7ugeGkS1lrX5qMCUoin7AVmLLXJCJPUk0PtfrsiaDKYxWXdaFWbUej74yAIhviizC9/3KagqpVu6jLOUk86i9/jX+9of4zS7FtRmsAbSqkaX5T55a9CUJfFtywdraeUI51yNp8wSvPs/DguwpOTP/AlnZyERXx8nuXr7D1lo2uutzVlo2iELyqKtvYzz5U+Oe7AfGZPicf/ltOmYODay4HjOC6+KMdhAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFjwL+5facBUK2JbAAAAAElFTkSuQmCC'
+
+ ShowMeTheButtons()
+
diff --git a/DemoPrograms old/Demo_Calendar.py b/DemoPrograms old/Demo_Calendar.py
new file mode 100644
index 000000000..79a5533c8
--- /dev/null
+++ b/DemoPrograms old/Demo_Calendar.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[sg.T('Calendar Test')],
+ [sg.In('', size=(20,1), key='input')],
+ [sg.CalendarButton('Choose Date', target='input', key='date')],
+ [sg.Ok(key=1)]]
+
+window = sg.Window('Calendar', grab_anywhere=False).Layout(layout)
+event,values = window.Read()
+sg.Popup(values['input'])
diff --git a/DemoPrograms old/Demo_Canvas.py b/DemoPrograms old/Demo_Canvas.py
new file mode 100644
index 000000000..60773758f
--- /dev/null
+++ b/DemoPrograms old/Demo_Canvas.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [
+ [sg.Canvas(size=(150, 150), background_color='red', key='canvas')],
+ [sg.T('Change circle color to:'), sg.Button('Red'), sg.Button('Blue')]
+ ]
+
+window = sg.Window('Canvas test').Layout(layout).Finalize()
+
+cir = window.FindElement('canvas').TKCanvas.create_oval(50, 50, 100, 100)
+
+while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ if event in ('Blue', 'Red'):
+ window.FindElement('canvas').TKCanvas.itemconfig(cir, fill=event)
diff --git a/DemoPrograms old/Demo_Change_Look_And_Feel_Browser.py b/DemoPrograms old/Demo_Change_Look_And_Feel_Browser.py
new file mode 100644
index 000000000..823e66f54
--- /dev/null
+++ b/DemoPrograms old/Demo_Change_Look_And_Feel_Browser.py
@@ -0,0 +1,25 @@
+import PySimpleGUI as sg
+
+"""
+ Allows you to "browse" through the look and feel settings. Click on one and you'll see a
+ Popup window using the color scheme you chose. It's a simply little program that demonstrates
+ how snappy a GUI can feel if you enable an element's events rather than waiting on a button click.
+ In this program, as soon as a listbox entry is clicked, the read returns.
+"""
+
+sg.ChangeLookAndFeel('GreenTan')
+
+layout = [ [sg.Text('Look and Feel Browser')],
+ [sg.Text('Click a look and feel color to see demo window')],
+ [sg.Listbox(values=sg.list_of_look_and_feel_values(), size=(20,12), key='-LIST-', enable_events=True)],
+ [sg.Button('Show Window'), sg.Button('Exit')] ]
+
+window = sg.Window('Look and Feel Browser', layout)
+
+while True: # Event Loop
+ event, values = window.read()
+ if event in (None, 'Exit'):
+ break
+ sg.change_look_and_feel(values['-LIST-'][0])
+ sg.popup_get_text('This is {}'.format(values['-LIST-'][0]))
+window.close()
diff --git a/DemoPrograms old/Demo_Change_Submits_InputText.py b/DemoPrograms old/Demo_Change_Submits_InputText.py
new file mode 100644
index 000000000..215b46b2d
--- /dev/null
+++ b/DemoPrograms old/Demo_Change_Submits_InputText.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+ Demonstrates the new change_submits parameter for inputtext elements
+ It ONLY submits when a button changes the field, not normal user input
+ Be careful on persistent forms to not clear the input
+"""
+layout = [[ sg.Text('Test of reading input field') ],
+ [sg.T('This input is normal'), sg.In()],
+ [sg.T('This input change submits'), sg.In(change_submits=True)],
+ [sg.T('This multiline input change submits'), sg.Multiline(change_submits=True, do_not_clear=True)],
+ [sg.T('This input is normal'), sg.In(), sg.FileBrowse()],
+ [sg.T('File Browse submits'), sg.In(change_submits=True,
+ do_not_clear=True,
+ key='_in1_'), sg.FileBrowse()],
+ [sg.T('Color Chooser submits'), sg.In(change_submits=True,
+ do_not_clear=True,
+ key='_in2_'), sg.ColorChooserButton('Color...', target=(sg.ThisRow, -1))],
+ [sg.T('Folder Browse submits'), sg.In(change_submits=True,
+ do_not_clear=True,
+ key='_in3_'), sg.FolderBrowse()],
+ [sg.T('Calendar Chooser submits'), sg.In(change_submits=True,
+ do_not_clear=True,
+ key='_in4_'), sg.CalendarButton('Date...', target=(sg.ThisRow, -1))],
+ [sg.T('Disabled input submits'), sg.In(change_submits=True,
+ do_not_clear=True,
+ disabled=True,
+ key='_in5'), sg.FileBrowse()],
+ [sg.T('This input clears after submit'),sg.In(change_submits=True,
+ key='_in6_'), sg.FileBrowse()],
+ [ sg.Button('Read')]]
+
+window = sg.Window('Demonstration of InputText with change_submits',
+ auto_size_text=False,
+ default_element_size=(22,1),
+ text_justification='right',
+ ).Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event is None:
+ break
diff --git a/DemoPrograms old/Demo_Chat.py b/DemoPrograms old/Demo_Chat.py
new file mode 100644
index 000000000..c4ab0dd31
--- /dev/null
+++ b/DemoPrograms old/Demo_Chat.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+'''
+A chat window. Add call to your send-routine, print the response and you're done
+
+To see this program RUN on the web go here:
+https://repl.it/@PySimpleGUI/Chat-Application-Demo
+
+Note that the size of the display on repl.it is smaller than most, so the sizes of the
+Multiline and Output text areas were reduced in the online version. Nothing else was changed
+'''
+
+sg.ChangeLookAndFeel('GreenTan') # give our window a spiffy set of colors
+
+layout = [ [sg.Text('Your output will go here', size=(40, 1))],
+ [sg.Output(size=(127, 30), font=('Helvetica 10'))],
+ [sg.Multiline(size=(85, 5), enter_submits=True, key='query'),
+ sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
+ sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
+
+window = sg.Window('Chat window',
+ default_element_size=(30, 2),
+ font=('Helvetica',' 13'),
+ default_button_element_size=(8,2)).Layout(layout)
+
+# ---===--- Loop taking in user input and using it --- #
+while True:
+ event, value = window.Read()
+ if event == 'SEND':
+ query = value['query'].rstrip()
+ # EXECUTE YOUR COMMAND HERE
+ print('The command you entered was {}'.format(query))
+ elif event in (None, 'EXIT'): # quit if exit button or X
+ break
+sys.exit(69)
+
diff --git a/DemoPrograms old/Demo_Chat_With_History.py b/DemoPrograms old/Demo_Chat_With_History.py
new file mode 100644
index 000000000..1330caa11
--- /dev/null
+++ b/DemoPrograms old/Demo_Chat_With_History.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+'''
+A chatbot with history
+Scroll up and down through prior commands using the arrow keys
+Special keyboard keys:
+ Up arrow - scroll up in commands
+ Down arrow - scroll down in commands
+ Escape - clear current command
+ Control C - exit form
+'''
+
+def ChatBotWithHistory():
+ # ------- Make a new Window ------- #
+ sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors
+
+ layout = [[sg.Text('Your output will go here', size=(40, 1))],
+ [sg.Output(size=(127, 30), font=('Helvetica 10'))],
+ [sg.T('Command History'), sg.T('', size=(20,3), key='history')],
+ [sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
+ sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
+ sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
+
+ window = sg.Window('Chat window with history', default_element_size=(30, 2), font=('Helvetica',' 13'), default_button_element_size=(8,2), return_keyboard_events=True).Layout(layout)
+
+ # ---===--- Loop taking in user input and using it --- #
+ command_history = []
+ history_offset = 0
+ while True:
+ (event, value) = window.Read()
+ if event == 'SEND':
+ query = value['query'].rstrip()
+ # EXECUTE YOUR COMMAND HERE
+ print('The command you entered was {}'.format(query))
+ command_history.append(query)
+ history_offset = len(command_history)-1
+ window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear
+ window.FindElement('history').Update('\n'.join(command_history[-3:]))
+ elif event in (None, 'EXIT'): # quit if exit event or X
+ break
+ elif 'Up' in event and len(command_history):
+ command = command_history[history_offset]
+ history_offset -= 1 * (history_offset > 0) # decrement is not zero
+ window.FindElement('query').Update(command)
+ elif 'Down' in event and len(command_history):
+ history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list
+ command = command_history[history_offset]
+ window.FindElement('query').Update(command)
+ elif 'Escape' in event:
+ window.FindElement('query').Update('')
+
+ sys.exit(69)
+
+
+ChatBotWithHistory()
diff --git a/DemoPrograms old/Demo_Chatterbot.py b/DemoPrograms old/Demo_Chatterbot.py
new file mode 100644
index 000000000..a80d08c3a
--- /dev/null
+++ b/DemoPrograms old/Demo_Chatterbot.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+from chatterbot import ChatBot
+import chatterbot.utils
+
+
+'''
+Demo_Chatterbot.py
+A GUI wrapped arouind the Chatterbot package.
+The GUI is used to show progress bars during the training process and
+to collect user input that is sent to the chatbot. The reply is displayed in the GUI window
+'''
+
+# Create the 'Trainer GUI'
+# The Trainer GUI consists of a lot of progress bars stacked on top of each other
+sg.ChangeLookAndFeel('GreenTan')
+# sg.DebugWin()
+MAX_PROG_BARS = 20 # number of training sessions
+bars = []
+texts = []
+training_layout = [[sg.T('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))], ]
+for i in range(MAX_PROG_BARS):
+ bars.append(sg.ProgressBar(100, size=(30, 4)))
+ texts.append(sg.T(' ' * 20, size=(20, 1), justification='right'))
+ training_layout += [[texts[i], bars[i]],] # add a single row
+
+training_window = sg.Window('Training').Layout(training_layout)
+current_bar = 0
+
+# callback function for training runs
+def print_progress_bar(description, iteration_counter, total_items, progress_bar_length=20):
+ global current_bar
+ global bars
+ global texts
+ global training_window
+ # update the window and the bars
+ button, values = training_window.Read(timeout=0)
+ if button is None: # if user closed the window on us, exit
+ sys.exit(69)
+ if bars[current_bar].UpdateBar(iteration_counter, max=total_items) is False:
+ sys.exit(69)
+ texts[current_bar].Update(description) # show the training dataset name
+ if iteration_counter == total_items:
+ current_bar += 1
+
+# redefine the chatbot text based progress bar with a graphical one
+chatterbot.utils.print_progress_bar = print_progress_bar
+
+chatbot = ChatBot('Ron Obvious', trainer='chatterbot.trainers.ChatterBotCorpusTrainer')
+
+# Train based on the english corpus
+chatbot.train("chatterbot.corpus.english")
+
+################# GUI #################
+
+layout = [[sg.Output(size=(80, 20))],
+ [sg.Multiline(size=(70, 5), enter_submits=True),
+ sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
+
+window = sg.Window('Chat Window', auto_size_text=True, default_element_size=(30, 2)).Layout(layout)
+
+# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
+while True:
+ event, (value,) = window.Read()
+ if event != 'SEND':
+ break
+ string = value.rstrip()
+ print(' '+string)
+ # send the user input to chatbot to get a response
+ response = chatbot.get_response(value.rstrip())
+ print(response)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Chatterbot_With_TTS.py b/DemoPrograms old/Demo_Chatterbot_With_TTS.py
new file mode 100644
index 000000000..565c89c12
--- /dev/null
+++ b/DemoPrograms old/Demo_Chatterbot_With_TTS.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+from chatterbot import ChatBot
+import chatterbot.utils
+
+from gtts import gTTS
+from pygame import mixer
+import time
+import os
+
+'''
+Demo_Chatterbot.py
+A GUI wrapped arouind the Chatterbot package.
+The GUI is used to show progress bars during the training process and
+to collect user input that is sent to the chatbot. The reply is displayed in the GUI window
+'''
+
+# Create the 'Trainer GUI'
+# The Trainer GUI consists of a lot of progress bars stacked on top of each other
+sg.ChangeLookAndFeel('NeutralBlue')
+# sg.DebugWin()
+MAX_PROG_BARS = 20 # number of training sessions
+bars = []
+texts = []
+training_layout = [[sg.T('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))], ]
+for i in range(MAX_PROG_BARS):
+ bars.append(sg.ProgressBar(100, size=(30, 4)))
+ texts.append(sg.T(' ' * 20, size=(20, 1), justification='right'))
+ training_layout += [[texts[i], bars[i]],] # add a single row
+
+training_window = sg.Window('Training').Layout(training_layout)
+current_bar = 0
+
+# callback function for training runs
+def print_progress_bar(description, iteration_counter, total_items, progress_bar_length=20):
+ global current_bar
+ global bars
+ global texts
+ global training_window
+ # update the window and the bars
+ button, values = training_window.Read(timeout=0)
+ if button is None: # if user closed the window on us, exit
+ sys.exit(69)
+ if bars[current_bar].UpdateBar(iteration_counter, max=total_items) is False:
+ sys.exit(69)
+ texts[current_bar].Update(description) # show the training dataset name
+ if iteration_counter == total_items:
+ current_bar += 1
+
+def speak(text):
+ global i
+ tts = gTTS(text=text, lang='en',slow=False)
+ tts.save('speech{}.mp3'.format(i%2))
+ # playback the speech
+ mixer.music.load('speech{}.mp3'.format(i%2))
+ mixer.music.play()
+ # wait for playback to end
+ while mixer.music.get_busy():
+ time.sleep(.1)
+ mixer.stop()
+ i += 1
+
+i = 0
+mixer.init()
+
+# redefine the chatbot text based progress bar with a graphical one
+chatterbot.utils.print_progress_bar = print_progress_bar
+
+chatbot = ChatBot('Ron Obvious', trainer='chatterbot.trainers.ChatterBotCorpusTrainer')
+
+# Train based on the english corpus
+chatbot.train("chatterbot.corpus.english")
+
+################# GUI #################
+
+layout = [[sg.Output(size=(80, 20))],
+ [sg.Multiline(size=(70, 5), enter_submits=True),
+ sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
+
+window = sg.Window('Chat Window', auto_size_text=True, default_element_size=(30, 2)).Layout(layout)
+
+# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
+while True:
+ event, (value,) = window.Read()
+ if event != 'SEND':
+ break
+ string = value.rstrip()
+ print(' '+string)
+ # send the user input to chatbot to get a response
+ response = chatbot.get_response(value.rstrip())
+ print(response)
+ speak(str(response))
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Color.py b/DemoPrograms old/Demo_Color.py
new file mode 100644
index 000000000..ead1245fc
--- /dev/null
+++ b/DemoPrograms old/Demo_Color.py
@@ -0,0 +1,1728 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+MY_WINDOW_ICON = 'E:\\TheRealMyDocs\\Icons\\The Planets\\jupiter.ico'
+reverse = {}
+colorhex = {}
+
+colors = {
+ "abbey" : ( 76, 79, 86),
+ "acadia" : ( 27, 20, 4),
+ "acapulco" : (124, 176, 161),
+ "aero blue" : (201, 255, 229),
+ "affair" : (113, 70, 147),
+ "akaroa" : (212, 196, 168),
+ "alabaster" : (250, 250, 250),
+ "albescent white" : (245, 233, 211),
+ "algae green" : (147, 223, 184),
+ "alice blue" : (240, 248, 255),
+ "alizarin crimson" : (227, 38, 54),
+ "allports" : ( 0, 118, 163),
+ "almond" : (238, 217, 196),
+ "almond frost" : (144, 123, 113),
+ "alpine" : (175, 143, 44),
+ "alto" : (219, 219, 219),
+ "aluminium" : (169, 172, 182),
+ "amaranth" : (229, 43, 80),
+ "amazon" : ( 59, 122, 87),
+ "amber" : (255, 191, 0),
+ "americano" : (135, 117, 110),
+ "amethyst" : (153, 102, 204),
+ "amethyst smoke" : (163, 151, 180),
+ "amour" : (249, 234, 243),
+ "amulet" : (123, 159, 128),
+ "anakiwa" : (157, 229, 255),
+ "antique brass" : (200, 138, 101),
+ "antique bronze" : (112, 74, 7),
+ "anzac" : (224, 182, 70),
+ "apache" : (223, 190, 111),
+ "apple" : ( 79, 168, 61),
+ "apple blossom" : (175, 77, 67),
+ "apple green" : (226, 243, 236),
+ "apricot" : (235, 147, 115),
+ "apricot peach" : (251, 206, 177),
+ "apricot white" : (255, 254, 236),
+ "aqua deep" : ( 1, 75, 67),
+ "aqua forest" : ( 95, 167, 119),
+ "aqua haze" : (237, 245, 245),
+ "aqua island" : (161, 218, 215),
+ "aqua spring" : (234, 249, 245),
+ "aqua squeeze" : (232, 245, 242),
+ "aquamarine" : (127, 255, 212),
+ "aquamarine blue" : (113, 217, 226),
+ "arapawa" : ( 17, 12, 108),
+ "armadillo" : ( 67, 62, 55),
+ "arrowtown" : (148, 135, 113),
+ "ash" : (198, 195, 181),
+ "asparagus" : (123, 160, 91),
+ "asphalt" : ( 19, 10, 6),
+ "astra" : (250, 234, 185),
+ "astral" : ( 50, 125, 160),
+ "astronaut" : ( 40, 58, 119),
+ "astronaut blue" : ( 1, 62, 98),
+ "athens gray" : (238, 240, 243),
+ "aths special" : (236, 235, 206),
+ "atlantis" : (151, 205, 45),
+ "atoll" : ( 10, 111, 117),
+ "atomic tangerine" : (255, 153, 102),
+ "au chico" : (151, 96, 93),
+ "aubergine" : ( 59, 9, 16),
+ "australian mint" : (245, 255, 190),
+ "avocado" : (136, 141, 101),
+ "axolotl" : ( 78, 102, 73),
+ "azalea" : (247, 200, 218),
+ "aztec" : ( 13, 28, 25),
+ "azure" : ( 49, 91, 161),
+ "azure radiance" : ( 0, 127, 255),
+ "baby blue" : (224, 255, 255),
+ "bahama blue" : ( 2, 99, 149),
+ "bahia" : (165, 203, 12),
+ "baja white" : (255, 248, 209),
+ "bali hai" : (133, 159, 175),
+ "baltic sea" : ( 42, 38, 48),
+ "bamboo" : (218, 99, 4),
+ "banana mania" : (251, 231, 178),
+ "bandicoot" : (133, 132, 112),
+ "barberry" : (222, 215, 23),
+ "barley corn" : (166, 139, 91),
+ "barley white" : (255, 244, 206),
+ "barossa" : ( 68, 1, 45),
+ "bastille" : ( 41, 33, 48),
+ "battleship gray" : (130, 143, 114),
+ "bay leaf" : (125, 169, 141),
+ "bay of many" : ( 39, 58, 129),
+ "bazaar" : (152, 119, 123),
+ "bean " : ( 61, 12, 2),
+ "beauty bush" : (238, 193, 190),
+ "beaver" : (146, 111, 91),
+ "beeswax" : (254, 242, 199),
+ "beige" : (245, 245, 220),
+ "bermuda" : (125, 216, 198),
+ "bermuda gray" : (107, 139, 162),
+ "beryl green" : (222, 229, 192),
+ "bianca" : (252, 251, 243),
+ "big stone" : ( 22, 42, 64),
+ "bilbao" : ( 50, 124, 20),
+ "biloba flower" : (178, 161, 234),
+ "birch" : ( 55, 48, 33),
+ "bird flower" : (212, 205, 22),
+ "biscay" : ( 27, 49, 98),
+ "bismark" : ( 73, 113, 131),
+ "bison hide" : (193, 183, 164),
+ "bistre" : ( 61, 43, 31),
+ "bitter" : (134, 137, 116),
+ "bitter lemon" : (202, 224, 13),
+ "bittersweet" : (254, 111, 94),
+ "bizarre" : (238, 222, 218),
+ "black" : ( 0, 0, 0),
+ "black bean" : ( 8, 25, 16),
+ "black forest" : ( 11, 19, 4),
+ "black haze" : (246, 247, 247),
+ "black marlin" : ( 62, 44, 28),
+ "black olive" : ( 36, 46, 22),
+ "black pearl" : ( 4, 19, 34),
+ "black rock" : ( 13, 3, 50),
+ "black rose" : (103, 3, 45),
+ "black russian" : ( 10, 0, 28),
+ "black squeeze" : (242, 250, 250),
+ "black white" : (255, 254, 246),
+ "blackberry" : ( 77, 1, 53),
+ "blackcurrant" : ( 50, 41, 58),
+ "blaze orange" : (255, 102, 0),
+ "bleach white" : (254, 243, 216),
+ "bleached cedar" : ( 44, 33, 51),
+ "blizzard blue" : (163, 227, 237),
+ "blossom" : (220, 180, 188),
+ "blue" : ( 0, 0, 255),
+ "blue bayoux" : ( 73, 102, 121),
+ "blue bell" : (153, 153, 204),
+ "blue chalk" : (241, 233, 255),
+ "blue charcoal" : ( 1, 13, 26),
+ "blue chill" : ( 12, 137, 144),
+ "blue diamond" : ( 56, 4, 116),
+ "blue dianne" : ( 32, 72, 82),
+ "blue gem" : ( 44, 14, 140),
+ "blue haze" : (191, 190, 216),
+ "blue lagoon" : ( 1, 121, 135),
+ "blue marguerite" : (118, 102, 198),
+ "blue ribbon" : ( 0, 102, 255),
+ "blue romance" : (210, 246, 222),
+ "blue smoke" : (116, 136, 129),
+ "blue stone" : ( 1, 97, 98),
+ "blue violet" : (100, 86, 183),
+ "blue whale" : ( 4, 46, 76),
+ "blue zodiac" : ( 19, 38, 77),
+ "blumine" : ( 24, 88, 122),
+ "blush" : (180, 70, 104),
+ "blush pink" : (255, 111, 255),
+ "bombay" : (175, 177, 184),
+ "bon jour" : (229, 224, 225),
+ "bondi blue" : ( 0, 149, 182),
+ "bone" : (228, 209, 192),
+ "bordeaux" : ( 92, 1, 32),
+ "bossanova" : ( 78, 42, 90),
+ "boston blue" : ( 59, 145, 180),
+ "botticelli" : (199, 221, 229),
+ "bottle green" : ( 9, 54, 36),
+ "boulder" : (122, 122, 122),
+ "bouquet" : (174, 128, 158),
+ "bourbon" : (186, 111, 30),
+ "bracken" : ( 74, 42, 4),
+ "brandy" : (222, 193, 150),
+ "brandy punch" : (205, 132, 41),
+ "brandy rose" : (187, 137, 131),
+ "breaker bay" : ( 93, 161, 159),
+ "brick red" : (198, 45, 66),
+ "bridal heath" : (255, 250, 244),
+ "bridesmaid" : (254, 240, 236),
+ "bright gray" : ( 60, 65, 81),
+ "bright green" : (102, 255, 0),
+ "bright red" : (177, 0, 0),
+ "bright sun" : (254, 211, 60),
+ "bright turquoise" : ( 8, 232, 222),
+ "brilliant rose" : (246, 83, 166),
+ "brink pink" : (251, 96, 127),
+ "bronco" : (171, 161, 150),
+ "bronze" : ( 63, 33, 9),
+ "bronze olive" : ( 78, 66, 12),
+ "bronzetone" : ( 77, 64, 15),
+ "broom" : (255, 236, 19),
+ "brown" : (150, 75, 0),
+ "brown bramble" : ( 89, 40, 4),
+ "brown derby" : ( 73, 38, 21),
+ "brown pod" : ( 64, 24, 1),
+ "brown rust" : (175, 89, 62),
+ "brown tumbleweed" : ( 55, 41, 14),
+ "bubbles" : (231, 254, 255),
+ "buccaneer" : ( 98, 47, 48),
+ "bud" : (168, 174, 156),
+ "buddha gold" : (193, 160, 4),
+ "buff" : (240, 220, 130),
+ "bulgarian rose" : ( 72, 6, 7),
+ "bull shot" : (134, 77, 30),
+ "bunker" : ( 13, 17, 23),
+ "bunting" : ( 21, 31, 76),
+ "burgundy" : (144, 0, 32),
+ "burnham" : ( 0, 46, 32),
+ "burning orange" : (255, 112, 52),
+ "burning sand" : (217, 147, 118),
+ "burnt maroon" : ( 66, 3, 3),
+ "burnt orange" : (204, 85, 0),
+ "burnt sienna" : (233, 116, 81),
+ "burnt umber" : (138, 51, 36),
+ "bush" : ( 13, 46, 28),
+ "buttercup" : (243, 173, 22),
+ "buttered rum" : (161, 117, 13),
+ "butterfly bush" : ( 98, 78, 154),
+ "buttermilk" : (255, 241, 181),
+ "buttery white" : (255, 252, 234),
+ "cab sav" : ( 77, 10, 24),
+ "cabaret" : (217, 73, 114),
+ "cabbage pont" : ( 63, 76, 58),
+ "cactus" : ( 88, 113, 86),
+ "cadet blue" : (169, 178, 195),
+ "cadillac" : (176, 76, 106),
+ "cafe royale" : (111, 68, 12),
+ "calico" : (224, 192, 149),
+ "california" : (254, 157, 4),
+ "calypso" : ( 49, 114, 141),
+ "camarone" : ( 0, 88, 26),
+ "camelot" : (137, 52, 86),
+ "cameo" : (217, 185, 155),
+ "camouflage" : ( 60, 57, 16),
+ "camouflage green" : (120, 134, 107),
+ "can can" : (213, 145, 164),
+ "canary" : (243, 251, 98),
+ "candlelight" : (252, 217, 23),
+ "candy corn" : (251, 236, 93),
+ "cannon black" : ( 37, 23, 6),
+ "cannon pink" : (137, 67, 103),
+ "cape cod" : ( 60, 68, 67),
+ "cape honey" : (254, 229, 172),
+ "cape palliser" : (162, 102, 69),
+ "caper" : (220, 237, 180),
+ "caramel" : (255, 221, 175),
+ "cararra" : (238, 238, 232),
+ "cardin green" : ( 1, 54, 28),
+ "cardinal" : (196, 30, 58),
+ "cardinal pink" : (140, 5, 94),
+ "careys pink" : (210, 158, 170),
+ "caribbean green" : ( 0, 204, 153),
+ "carissma" : (234, 136, 168),
+ "carla" : (243, 255, 216),
+ "carmine" : (150, 0, 24),
+ "carnaby tan" : ( 92, 46, 1),
+ "carnation" : (249, 90, 97),
+ "carnation pink" : (255, 166, 201),
+ "carousel pink" : (249, 224, 237),
+ "carrot orange" : (237, 145, 33),
+ "casablanca" : (248, 184, 83),
+ "casal" : ( 47, 97, 104),
+ "cascade" : (139, 169, 165),
+ "cashmere" : (230, 190, 165),
+ "casper" : (173, 190, 209),
+ "castro" : ( 82, 0, 31),
+ "catalina blue" : ( 6, 42, 120),
+ "catskill white" : (238, 246, 247),
+ "cavern pink" : (227, 190, 190),
+ "cedar" : ( 62, 28, 20),
+ "cedar wood finish" : (113, 26, 0),
+ "celadon" : (172, 225, 175),
+ "celery" : (184, 194, 93),
+ "celeste" : (209, 210, 202),
+ "cello" : ( 30, 56, 91),
+ "celtic" : ( 22, 50, 34),
+ "cement" : (141, 118, 98),
+ "ceramic" : (252, 255, 249),
+ "cerise" : (218, 50, 135),
+ "cerise red" : (222, 49, 99),
+ "cerulean" : ( 2, 164, 211),
+ "cerulean blue" : ( 42, 82, 190),
+ "chablis" : (255, 244, 243),
+ "chalet green" : ( 81, 110, 61),
+ "chalky" : (238, 215, 148),
+ "chambray" : ( 53, 78, 140),
+ "chamois" : (237, 220, 177),
+ "champagne" : (250, 236, 204),
+ "chantilly" : (248, 195, 223),
+ "charade" : ( 41, 41, 55),
+ "chardon" : (255, 243, 241),
+ "chardonnay" : (255, 205, 140),
+ "charlotte" : (186, 238, 249),
+ "charm" : (212, 116, 148),
+ "chartreuse" : (127, 255, 0),
+ "chartreuse yellow" : (223, 255, 0),
+ "chateau green" : ( 64, 168, 96),
+ "chatelle" : (189, 179, 199),
+ "chathams blue" : ( 23, 85, 121),
+ "chelsea cucumber" : (131, 170, 93),
+ "chelsea gem" : (158, 83, 2),
+ "chenin" : (223, 205, 111),
+ "cherokee" : (252, 218, 152),
+ "cherry pie" : ( 42, 3, 89),
+ "cherrywood" : (101, 26, 20),
+ "cherub" : (248, 217, 233),
+ "chestnut" : (185, 78, 72),
+ "chestnut rose" : (205, 92, 92),
+ "chetwode blue" : (133, 129, 217),
+ "chicago" : ( 93, 92, 88),
+ "chiffon" : (241, 255, 200),
+ "chilean fire" : (247, 119, 3),
+ "chilean heath" : (255, 253, 230),
+ "china ivory" : (252, 255, 231),
+ "chino" : (206, 199, 167),
+ "chinook" : (168, 227, 189),
+ "chocolate" : ( 55, 2, 2),
+ "christalle" : ( 51, 3, 107),
+ "christi" : (103, 167, 18),
+ "christine" : (231, 115, 10),
+ "chrome white" : (232, 241, 212),
+ "cinder" : ( 14, 14, 24),
+ "cinderella" : (253, 225, 220),
+ "cinnabar" : (227, 66, 52),
+ "cinnamon" : (123, 63, 0),
+ "cioccolato" : ( 85, 40, 12),
+ "citrine white" : (250, 247, 214),
+ "citron" : (158, 169, 31),
+ "citrus" : (161, 197, 10),
+ "clairvoyant" : ( 72, 6, 86),
+ "clam shell" : (212, 182, 175),
+ "claret" : (127, 23, 52),
+ "classic rose" : (251, 204, 231),
+ "clay ash" : (189, 200, 179),
+ "clay creek" : (138, 131, 96),
+ "clear day" : (233, 255, 253),
+ "clementine" : (233, 110, 0),
+ "clinker" : ( 55, 29, 9),
+ "cloud" : (199, 196, 191),
+ "cloud burst" : ( 32, 46, 84),
+ "cloudy" : (172, 165, 159),
+ "clover" : ( 56, 73, 16),
+ "cobalt" : ( 0, 71, 171),
+ "cocoa bean" : ( 72, 28, 28),
+ "cocoa brown" : ( 48, 31, 30),
+ "coconut cream" : (248, 247, 220),
+ "cod gray" : ( 11, 11, 11),
+ "coffee" : (112, 101, 85),
+ "coffee bean" : ( 42, 20, 14),
+ "cognac" : (159, 56, 29),
+ "cola" : ( 63, 37, 0),
+ "cold purple" : (171, 160, 217),
+ "cold turkey" : (206, 186, 186),
+ "colonial white" : (255, 237, 188),
+ "comet" : ( 92, 93, 117),
+ "como" : ( 81, 124, 102),
+ "conch" : (201, 217, 210),
+ "concord" : (124, 123, 122),
+ "concrete" : (242, 242, 242),
+ "confetti" : (233, 215, 90),
+ "congo brown" : ( 89, 55, 55),
+ "congress blue" : ( 2, 71, 142),
+ "conifer" : (172, 221, 77),
+ "contessa" : (198, 114, 107),
+ "copper" : (184, 115, 51),
+ "copper canyon" : (126, 58, 21),
+ "copper rose" : (153, 102, 102),
+ "copper rust" : (148, 71, 71),
+ "copperfield" : (218, 138, 103),
+ "coral" : (255, 127, 80),
+ "coral red" : (255, 64, 64),
+ "coral reef" : (199, 188, 162),
+ "coral tree" : (168, 107, 107),
+ "corduroy" : ( 96, 110, 104),
+ "coriander" : (196, 208, 176),
+ "cork" : ( 64, 41, 29),
+ "corn" : (231, 191, 5),
+ "corn field" : (248, 250, 205),
+ "corn harvest" : (139, 107, 11),
+ "cornflower" : (147, 204, 234),
+ "cornflower blue" : (100, 149, 237),
+ "cornflower lilac" : (255, 176, 172),
+ "corvette" : (250, 211, 162),
+ "cosmic" : (118, 57, 93),
+ "cosmos" : (255, 216, 217),
+ "costa del sol" : ( 97, 93, 48),
+ "cotton candy" : (255, 183, 213),
+ "cotton seed" : (194, 189, 182),
+ "county green" : ( 1, 55, 26),
+ "cowboy" : ( 77, 40, 45),
+ "crail" : (185, 81, 64),
+ "cranberry" : (219, 80, 121),
+ "crater brown" : ( 70, 36, 37),
+ "cream" : (255, 253, 208),
+ "cream brulee" : (255, 229, 160),
+ "cream can" : (245, 200, 92),
+ "creole" : ( 30, 15, 4),
+ "crete" : (115, 120, 41),
+ "crimson" : (220, 20, 60),
+ "crocodile" : (115, 109, 88),
+ "crown of thorns" : (119, 31, 31),
+ "crowshead" : ( 28, 18, 8),
+ "cruise" : (181, 236, 223),
+ "crusoe" : ( 0, 72, 22),
+ "crusta" : (253, 123, 51),
+ "cumin" : (146, 67, 33),
+ "cumulus" : (253, 255, 213),
+ "cupid" : (251, 190, 218),
+ "curious blue" : ( 37, 150, 209),
+ "cutty sark" : ( 80, 118, 114),
+ "cyan / aqua" : ( 0, 255, 255),
+ "cyprus" : ( 0, 62, 64),
+ "daintree" : ( 1, 39, 49),
+ "dairy cream" : (249, 228, 188),
+ "daisy bush" : ( 79, 35, 152),
+ "dallas" : (110, 75, 38),
+ "dandelion" : (254, 216, 93),
+ "danube" : ( 96, 147, 209),
+ "dark blue" : ( 0, 0, 200),
+ "dark burgundy" : (119, 15, 5),
+ "dark ebony" : ( 60, 32, 5),
+ "dark fern" : ( 10, 72, 13),
+ "dark tan" : (102, 16, 16),
+ "dawn" : (166, 162, 154),
+ "dawn pink" : (243, 233, 229),
+ "de york" : (122, 196, 136),
+ "deco" : (210, 218, 151),
+ "deep blue" : ( 34, 8, 120),
+ "deep blush" : (228, 118, 152),
+ "deep bronze" : ( 74, 48, 4),
+ "deep cerulean" : ( 0, 123, 167),
+ "deep cove" : ( 5, 16, 64),
+ "deep fir" : ( 0, 41, 0),
+ "deep forest green" : ( 24, 45, 9),
+ "deep koamaru" : ( 27, 18, 123),
+ "deep oak" : ( 65, 32, 16),
+ "deep sapphire" : ( 8, 37, 103),
+ "deep sea" : ( 1, 130, 107),
+ "deep sea green" : ( 9, 88, 89),
+ "deep teal" : ( 0, 53, 50),
+ "del rio" : (176, 154, 149),
+ "dell" : ( 57, 100, 19),
+ "delta" : (164, 164, 157),
+ "deluge" : (117, 99, 168),
+ "denim" : ( 21, 96, 189),
+ "derby" : (255, 238, 216),
+ "desert" : (174, 96, 32),
+ "desert sand" : (237, 201, 175),
+ "desert storm" : (248, 248, 247),
+ "dew" : (234, 255, 254),
+ "di serria" : (219, 153, 94),
+ "diesel" : ( 19, 0, 0),
+ "dingley" : ( 93, 119, 71),
+ "disco" : (135, 21, 80),
+ "dixie" : (226, 148, 24),
+ "dodger blue" : ( 30, 144, 255),
+ "dolly" : (249, 255, 139),
+ "dolphin" : (100, 96, 119),
+ "domino" : (142, 119, 94),
+ "don juan" : ( 93, 76, 81),
+ "donkey brown" : (166, 146, 121),
+ "dorado" : (107, 87, 85),
+ "double colonial white" : (238, 227, 173),
+ "double pearl lusta" : (252, 244, 208),
+ "double spanish white" : (230, 215, 185),
+ "dove gray" : (109, 108, 108),
+ "downriver" : ( 9, 34, 86),
+ "downy" : (111, 208, 197),
+ "driftwood" : (175, 135, 81),
+ "drover" : (253, 247, 173),
+ "dull lavender" : (168, 153, 230),
+ "dune" : ( 56, 53, 51),
+ "dust storm" : (229, 204, 201),
+ "dusty gray" : (168, 152, 155),
+ "eagle" : (182, 186, 164),
+ "earls green" : (201, 185, 59),
+ "early dawn" : (255, 249, 230),
+ "east bay" : ( 65, 76, 125),
+ "east side" : (172, 145, 206),
+ "eastern blue" : ( 30, 154, 176),
+ "ebb" : (233, 227, 227),
+ "ebony" : ( 12, 11, 29),
+ "ebony clay" : ( 38, 40, 59),
+ "eclipse" : ( 49, 28, 23),
+ "ecru white" : (245, 243, 229),
+ "ecstasy" : (250, 120, 20),
+ "eden" : ( 16, 88, 82),
+ "edgewater" : (200, 227, 215),
+ "edward" : (162, 174, 171),
+ "egg sour" : (255, 244, 221),
+ "egg white" : (255, 239, 193),
+ "eggplant" : ( 97, 64, 81),
+ "el paso" : ( 30, 23, 8),
+ "el salva" : (143, 62, 51),
+ "electric lime" : (204, 255, 0),
+ "electric violet" : (139, 0, 255),
+ "elephant" : ( 18, 52, 71),
+ "elf green" : ( 8, 131, 112),
+ "elm" : ( 28, 124, 125),
+ "emerald" : ( 80, 200, 120),
+ "eminence" : (108, 48, 130),
+ "emperor" : ( 81, 70, 73),
+ "empress" : (129, 115, 119),
+ "endeavour" : ( 0, 86, 167),
+ "energy yellow" : (248, 221, 92),
+ "english holly" : ( 2, 45, 21),
+ "english walnut" : ( 62, 43, 35),
+ "envy" : (139, 166, 144),
+ "equator" : (225, 188, 100),
+ "espresso" : ( 97, 39, 24),
+ "eternity" : ( 33, 26, 14),
+ "eucalyptus" : ( 39, 138, 91),
+ "eunry" : (207, 163, 157),
+ "evening sea" : ( 2, 78, 70),
+ "everglade" : ( 28, 64, 46),
+ "faded jade" : ( 66, 121, 119),
+ "fair pink" : (255, 239, 236),
+ "falcon" : (127, 98, 109),
+ "fall green" : (236, 235, 189),
+ "falu red" : (128, 24, 24),
+ "fantasy" : (250, 243, 240),
+ "fedora" : (121, 106, 120),
+ "feijoa" : (159, 221, 140),
+ "fern" : ( 99, 183, 108),
+ "fern frond" : (101, 114, 32),
+ "fern green" : ( 79, 121, 66),
+ "ferra" : (112, 79, 80),
+ "festival" : (251, 233, 108),
+ "feta" : (240, 252, 234),
+ "fiery orange" : (179, 82, 19),
+ "finch" : ( 98, 102, 73),
+ "finlandia" : ( 85, 109, 86),
+ "finn" : (105, 45, 84),
+ "fiord" : ( 64, 81, 105),
+ "fire" : (170, 66, 3),
+ "fire bush" : (232, 153, 40),
+ "firefly" : ( 14, 42, 48),
+ "flame pea" : (218, 91, 56),
+ "flamenco" : (255, 125, 7),
+ "flamingo" : (242, 85, 42),
+ "flax" : (238, 220, 130),
+ "flax smoke" : (123, 130, 101),
+ "flesh" : (255, 203, 164),
+ "flint" : (111, 106, 97),
+ "flirt" : (162, 0, 109),
+ "flush mahogany" : (202, 52, 53),
+ "flush orange" : (255, 127, 0),
+ "foam" : (216, 252, 250),
+ "fog" : (215, 208, 255),
+ "foggy gray" : (203, 202, 182),
+ "forest green" : ( 34, 139, 34),
+ "forget me not" : (255, 241, 238),
+ "fountain blue" : ( 86, 180, 190),
+ "frangipani" : (255, 222, 179),
+ "french gray" : (189, 189, 198),
+ "french lilac" : (236, 199, 238),
+ "french pass" : (189, 237, 253),
+ "french rose" : (246, 74, 138),
+ "fresh eggplant" : (153, 0, 102),
+ "friar gray" : (128, 126, 121),
+ "fringy flower" : (177, 226, 193),
+ "froly" : (245, 117, 132),
+ "frost" : (237, 245, 221),
+ "frosted mint" : (219, 255, 248),
+ "frostee" : (228, 246, 231),
+ "fruit salad" : ( 79, 157, 93),
+ "fuchsia blue" : (122, 88, 193),
+ "fuchsia pink" : (193, 84, 193),
+ "fuego" : (190, 222, 13),
+ "fuel yellow" : (236, 169, 39),
+ "fun blue" : ( 25, 89, 168),
+ "fun green" : ( 1, 109, 57),
+ "fuscous gray" : ( 84, 83, 77),
+ "fuzzy wuzzy brown" : (196, 86, 85),
+ "gable green" : ( 22, 53, 49),
+ "gallery" : (239, 239, 239),
+ "galliano" : (220, 178, 12),
+ "gamboge" : (228, 155, 15),
+ "geebung" : (209, 143, 27),
+ "genoa" : ( 21, 115, 107),
+ "geraldine" : (251, 137, 137),
+ "geyser" : (212, 223, 226),
+ "ghost" : (199, 201, 213),
+ "gigas" : ( 82, 60, 148),
+ "gimblet" : (184, 181, 106),
+ "gin" : (232, 242, 235),
+ "gin fizz" : (255, 249, 226),
+ "givry" : (248, 228, 191),
+ "glacier" : (128, 179, 196),
+ "glade green" : ( 97, 132, 95),
+ "go ben" : (114, 109, 78),
+ "goblin" : ( 61, 125, 82),
+ "gold" : (255, 215, 0),
+ "gold drop" : (241, 130, 0),
+ "gold sand" : (230, 190, 138),
+ "gold tips" : (222, 186, 19),
+ "golden bell" : (226, 137, 19),
+ "golden dream" : (240, 213, 45),
+ "golden fizz" : (245, 251, 61),
+ "golden glow" : (253, 226, 149),
+ "golden grass" : (218, 165, 32),
+ "golden sand" : (240, 219, 125),
+ "golden tainoi" : (255, 204, 92),
+ "goldenrod" : (252, 214, 103),
+ "gondola" : ( 38, 20, 20),
+ "gordons green" : ( 11, 17, 7),
+ "gorse" : (255, 241, 79),
+ "gossamer" : ( 6, 155, 129),
+ "gossip" : (210, 248, 176),
+ "gothic" : (109, 146, 161),
+ "governor bay" : ( 47, 60, 179),
+ "grain brown" : (228, 213, 183),
+ "grandis" : (255, 211, 140),
+ "granite green" : (141, 137, 116),
+ "granny apple" : (213, 246, 227),
+ "granny smith" : (132, 160, 160),
+ "granny smith apple" : (157, 224, 147),
+ "grape" : ( 56, 26, 81),
+ "graphite" : ( 37, 22, 7),
+ "gravel" : ( 74, 68, 75),
+ "gray" : (128, 128, 128),
+ "gray asparagus" : ( 70, 89, 69),
+ "gray chateau" : (162, 170, 179),
+ "gray nickel" : (195, 195, 189),
+ "gray nurse" : (231, 236, 230),
+ "gray olive" : (169, 164, 145),
+ "gray suit" : (193, 190, 205),
+ "green" : ( 0, 255, 0),
+ "green haze" : ( 1, 163, 104),
+ "green house" : ( 36, 80, 15),
+ "green kelp" : ( 37, 49, 28),
+ "green leaf" : ( 67, 106, 13),
+ "green mist" : (203, 211, 176),
+ "green pea" : ( 29, 97, 66),
+ "green smoke" : (164, 175, 110),
+ "green spring" : (184, 193, 177),
+ "green vogue" : ( 3, 43, 82),
+ "green waterloo" : ( 16, 20, 5),
+ "green white" : (232, 235, 224),
+ "green yellow" : (173, 255, 47),
+ "grenadier" : (213, 70, 0),
+ "guardsman red" : (186, 1, 1),
+ "gulf blue" : ( 5, 22, 87),
+ "gulf stream" : (128, 179, 174),
+ "gull gray" : (157, 172, 183),
+ "gum leaf" : (182, 211, 191),
+ "gumbo" : (124, 161, 166),
+ "gun powder" : ( 65, 66, 87),
+ "gunsmoke" : (130, 134, 133),
+ "gurkha" : (154, 149, 119),
+ "hacienda" : (152, 129, 27),
+ "hairy heath" : (107, 42, 20),
+ "haiti" : ( 27, 16, 53),
+ "half baked" : (133, 196, 204),
+ "half colonial white" : (253, 246, 211),
+ "half dutch white" : (254, 247, 222),
+ "half spanish white" : (254, 244, 219),
+ "half and half" : (255, 254, 225),
+ "hampton" : (229, 216, 175),
+ "harlequin" : ( 63, 255, 0),
+ "harp" : (230, 242, 234),
+ "harvest gold" : (224, 185, 116),
+ "havelock blue" : ( 85, 144, 217),
+ "hawaiian tan" : (157, 86, 22),
+ "hawkes blue" : (212, 226, 252),
+ "heath" : ( 84, 16, 18),
+ "heather" : (183, 195, 208),
+ "heathered gray" : (182, 176, 149),
+ "heavy metal" : ( 43, 50, 40),
+ "heliotrope" : (223, 115, 255),
+ "hemlock" : ( 94, 93, 59),
+ "hemp" : (144, 120, 116),
+ "hibiscus" : (182, 49, 108),
+ "highland" : (111, 142, 99),
+ "hillary" : (172, 165, 134),
+ "himalaya" : (106, 93, 27),
+ "hint of green" : (230, 255, 233),
+ "hint of red" : (251, 249, 249),
+ "hint of yellow" : (250, 253, 228),
+ "hippie blue" : ( 88, 154, 175),
+ "hippie green" : ( 83, 130, 75),
+ "hippie pink" : (174, 69, 96),
+ "hit gray" : (161, 173, 181),
+ "hit pink" : (255, 171, 129),
+ "hokey pokey" : (200, 165, 40),
+ "hoki" : (101, 134, 159),
+ "holly" : ( 1, 29, 19),
+ "hollywood cerise" : (244, 0, 161),
+ "honey flower" : ( 79, 28, 112),
+ "honeysuckle" : (237, 252, 132),
+ "hopbush" : (208, 109, 161),
+ "horizon" : ( 90, 135, 160),
+ "horses neck" : ( 96, 73, 19),
+ "hot cinnamon" : (210, 105, 30),
+ "hot pink" : (255, 105, 180),
+ "hot toddy" : (179, 128, 7),
+ "humming bird" : (207, 249, 243),
+ "hunter green" : ( 22, 29, 16),
+ "hurricane" : (135, 124, 123),
+ "husk" : (183, 164, 88),
+ "ice cold" : (177, 244, 231),
+ "iceberg" : (218, 244, 240),
+ "illusion" : (246, 164, 201),
+ "inch worm" : (176, 227, 19),
+ "indian khaki" : (195, 176, 145),
+ "indian tan" : ( 77, 30, 1),
+ "indigo" : ( 79, 105, 198),
+ "indochine" : (194, 107, 3),
+ "international klein blue" : ( 0, 47, 167),
+ "international orange" : (255, 79, 0),
+ "irish coffee" : ( 95, 61, 38),
+ "iroko" : ( 67, 49, 32),
+ "iron" : (212, 215, 217),
+ "ironside gray" : (103, 102, 98),
+ "ironstone" : (134, 72, 60),
+ "island spice" : (255, 252, 238),
+ "ivory" : (255, 255, 240),
+ "jacaranda" : ( 46, 3, 41),
+ "jacarta" : ( 58, 42, 106),
+ "jacko bean" : ( 46, 25, 5),
+ "jacksons purple" : ( 32, 32, 141),
+ "jade" : ( 0, 168, 107),
+ "jaffa" : (239, 134, 63),
+ "jagged ice" : (194, 232, 229),
+ "jagger" : ( 53, 14, 87),
+ "jaguar" : ( 8, 1, 16),
+ "jambalaya" : ( 91, 48, 19),
+ "janna" : (244, 235, 211),
+ "japanese laurel" : ( 10, 105, 6),
+ "japanese maple" : (120, 1, 9),
+ "japonica" : (216, 124, 99),
+ "java" : ( 31, 194, 194),
+ "jazzberry jam" : (165, 11, 94),
+ "jelly bean" : ( 41, 123, 154),
+ "jet stream" : (181, 210, 206),
+ "jewel" : ( 18, 107, 64),
+ "jon" : ( 59, 31, 31),
+ "jonquil" : (238, 255, 154),
+ "jordy blue" : (138, 185, 241),
+ "judge gray" : ( 84, 67, 51),
+ "jumbo" : (124, 123, 130),
+ "jungle green" : ( 41, 171, 135),
+ "jungle mist" : (180, 207, 211),
+ "juniper" : (109, 146, 146),
+ "just right" : (236, 205, 185),
+ "kabul" : ( 94, 72, 62),
+ "kaitoke green" : ( 0, 70, 32),
+ "kangaroo" : (198, 200, 189),
+ "karaka" : ( 30, 22, 9),
+ "karry" : (255, 234, 212),
+ "kashmir blue" : ( 80, 112, 150),
+ "kelp" : ( 69, 73, 54),
+ "kenyan copper" : (124, 28, 5),
+ "keppel" : ( 58, 176, 158),
+ "key lime pie" : (191, 201, 33),
+ "khaki" : (240, 230, 140),
+ "kidnapper" : (225, 234, 212),
+ "kilamanjaro" : ( 36, 12, 2),
+ "killarney" : ( 58, 106, 71),
+ "kimberly" : (115, 108, 159),
+ "kingfisher daisy" : ( 62, 4, 128),
+ "kobi" : (231, 159, 196),
+ "kokoda" : (110, 109, 87),
+ "korma" : (143, 75, 14),
+ "koromiko" : (255, 189, 95),
+ "kournikova" : (255, 231, 114),
+ "kumera" : (136, 98, 33),
+ "la palma" : ( 54, 135, 22),
+ "la rioja" : (179, 193, 16),
+ "las palmas" : (198, 230, 16),
+ "laser" : (200, 181, 104),
+ "laser lemon" : (255, 255, 102),
+ "laurel" : (116, 147, 120),
+ "lavender" : (181, 126, 220),
+ "lavender gray" : (189, 187, 215),
+ "lavender magenta" : (238, 130, 238),
+ "lavender pink" : (251, 174, 210),
+ "lavender purple" : (150, 123, 182),
+ "lavender rose" : (251, 160, 227),
+ "lavender blush" : (255, 240, 245),
+ "leather" : (150, 112, 89),
+ "lemon" : (253, 233, 16),
+ "lemon chiffon" : (255, 250, 205),
+ "lemon ginger" : (172, 158, 34),
+ "lemon grass" : (155, 158, 143),
+ "light apricot" : (253, 213, 177),
+ "light orchid" : (226, 156, 210),
+ "light wisteria" : (201, 160, 220),
+ "lightning yellow" : (252, 192, 30),
+ "lilac" : (200, 162, 200),
+ "lilac bush" : (152, 116, 211),
+ "lily" : (200, 170, 191),
+ "lily white" : (231, 248, 255),
+ "lima" : (118, 189, 23),
+ "lime" : (191, 255, 0),
+ "limeade" : (111, 157, 2),
+ "limed ash" : (116, 125, 99),
+ "limed oak" : (172, 138, 86),
+ "limed spruce" : ( 57, 72, 81),
+ "linen" : (250, 240, 230),
+ "link water" : (217, 228, 245),
+ "lipstick" : (171, 5, 99),
+ "lisbon brown" : ( 66, 57, 33),
+ "livid brown" : ( 77, 40, 46),
+ "loafer" : (238, 244, 222),
+ "loblolly" : (189, 201, 206),
+ "lochinvar" : ( 44, 140, 132),
+ "lochmara" : ( 0, 126, 199),
+ "locust" : (168, 175, 142),
+ "log cabin" : ( 36, 42, 29),
+ "logan" : (170, 169, 205),
+ "lola" : (223, 207, 219),
+ "london hue" : (190, 166, 195),
+ "lonestar" : (109, 1, 1),
+ "lotus" : (134, 60, 60),
+ "loulou" : ( 70, 11, 65),
+ "lucky" : (175, 159, 28),
+ "lucky point" : ( 26, 26, 104),
+ "lunar green" : ( 60, 73, 58),
+ "luxor gold" : (167, 136, 44),
+ "lynch" : (105, 126, 154),
+ "mabel" : (217, 247, 255),
+ "macaroni and cheese" : (255, 185, 123),
+ "madang" : (183, 240, 190),
+ "madison" : ( 9, 37, 93),
+ "madras" : ( 63, 48, 2),
+ "magenta / fuchsia" : (255, 0, 255),
+ "magic mint" : (170, 240, 209),
+ "magnolia" : (248, 244, 255),
+ "mahogany" : ( 78, 6, 6),
+ "mai tai" : (176, 102, 8),
+ "maize" : (245, 213, 160),
+ "makara" : (137, 125, 109),
+ "mako" : ( 68, 73, 84),
+ "malachite" : ( 11, 218, 81),
+ "malibu" : (125, 200, 247),
+ "mallard" : ( 35, 52, 24),
+ "malta" : (189, 178, 161),
+ "mamba" : (142, 129, 144),
+ "manatee" : (141, 144, 161),
+ "mandalay" : (173, 120, 27),
+ "mandy" : (226, 84, 101),
+ "mandys pink" : (242, 195, 178),
+ "mango tango" : (231, 114, 0),
+ "manhattan" : (245, 201, 153),
+ "mantis" : (116, 195, 101),
+ "mantle" : (139, 156, 144),
+ "manz" : (238, 239, 120),
+ "mardi gras" : ( 53, 0, 54),
+ "marigold" : (185, 141, 40),
+ "marigold yellow" : (251, 232, 112),
+ "mariner" : ( 40, 106, 205),
+ "maroon" : (128, 0, 0),
+ "maroon flush" : (195, 33, 72),
+ "maroon oak" : ( 82, 12, 23),
+ "marshland" : ( 11, 15, 8),
+ "martini" : (175, 160, 158),
+ "martinique" : ( 54, 48, 80),
+ "marzipan" : (248, 219, 157),
+ "masala" : ( 64, 59, 56),
+ "matisse" : ( 27, 101, 157),
+ "matrix" : (176, 93, 84),
+ "matterhorn" : ( 78, 59, 65),
+ "mauve" : (224, 176, 255),
+ "mauvelous" : (240, 145, 169),
+ "maverick" : (216, 194, 213),
+ "medium carmine" : (175, 64, 53),
+ "medium purple" : (147, 112, 219),
+ "medium red violet" : (187, 51, 133),
+ "melanie" : (228, 194, 213),
+ "melanzane" : ( 48, 5, 41),
+ "melon" : (254, 186, 173),
+ "melrose" : (199, 193, 255),
+ "mercury" : (229, 229, 229),
+ "merino" : (246, 240, 230),
+ "merlin" : ( 65, 60, 55),
+ "merlot" : (131, 25, 35),
+ "metallic bronze" : ( 73, 55, 27),
+ "metallic copper" : (113, 41, 29),
+ "meteor" : (208, 125, 18),
+ "meteorite" : ( 60, 31, 118),
+ "mexican red" : (167, 37, 37),
+ "mid gray" : ( 95, 95, 110),
+ "midnight" : ( 1, 22, 53),
+ "midnight blue" : ( 0, 51, 102),
+ "midnight moss" : ( 4, 16, 4),
+ "mikado" : ( 45, 37, 16),
+ "milan" : (250, 255, 164),
+ "milano red" : (184, 17, 4),
+ "milk punch" : (255, 246, 212),
+ "millbrook" : ( 89, 68, 51),
+ "mimosa" : (248, 253, 211),
+ "mindaro" : (227, 249, 136),
+ "mine shaft" : ( 50, 50, 50),
+ "mineral green" : ( 63, 93, 83),
+ "ming" : ( 54, 116, 125),
+ "minsk" : ( 63, 48, 127),
+ "mint green" : (152, 255, 152),
+ "mint julep" : (241, 238, 193),
+ "mint tulip" : (196, 244, 235),
+ "mirage" : ( 22, 25, 40),
+ "mischka" : (209, 210, 221),
+ "mist gray" : (196, 196, 188),
+ "mobster" : (127, 117, 137),
+ "moccaccino" : (110, 29, 20),
+ "mocha" : (120, 45, 25),
+ "mojo" : (192, 71, 55),
+ "mona lisa" : (255, 161, 148),
+ "monarch" : (139, 7, 35),
+ "mondo" : ( 74, 60, 48),
+ "mongoose" : (181, 162, 127),
+ "monsoon" : (138, 131, 137),
+ "monte carlo" : (131, 208, 198),
+ "monza" : (199, 3, 30),
+ "moody blue" : (127, 118, 211),
+ "moon glow" : (252, 254, 218),
+ "moon mist" : (220, 221, 204),
+ "moon raker" : (214, 206, 246),
+ "morning glory" : (158, 222, 224),
+ "morocco brown" : ( 68, 29, 0),
+ "mortar" : ( 80, 67, 81),
+ "mosque" : ( 3, 106, 110),
+ "moss green" : (173, 223, 173),
+ "mountain meadow" : ( 26, 179, 133),
+ "mountain mist" : (149, 147, 150),
+ "mountbatten pink" : (153, 122, 141),
+ "muddy waters" : (183, 142, 92),
+ "muesli" : (170, 139, 91),
+ "mulberry" : (197, 75, 140),
+ "mulberry wood" : ( 92, 5, 54),
+ "mule fawn" : (140, 71, 47),
+ "mulled wine" : ( 78, 69, 98),
+ "mustard" : (255, 219, 88),
+ "my pink" : (214, 145, 136),
+ "my sin" : (255, 179, 31),
+ "mystic" : (226, 235, 237),
+ "nandor" : ( 75, 93, 82),
+ "napa" : (172, 164, 148),
+ "narvik" : (237, 249, 241),
+ "natural gray" : (139, 134, 128),
+ "navajo white" : (255, 222, 173),
+ "navy blue" : ( 0, 0, 128),
+ "nebula" : (203, 219, 214),
+ "negroni" : (255, 226, 197),
+ "neon carrot" : (255, 153, 51),
+ "nepal" : (142, 171, 193),
+ "neptune" : (124, 183, 187),
+ "nero" : ( 20, 6, 0),
+ "nevada" : (100, 110, 117),
+ "new orleans" : (243, 214, 157),
+ "new york pink" : (215, 131, 127),
+ "niagara" : ( 6, 161, 137),
+ "night rider" : ( 31, 18, 15),
+ "night shadz" : (170, 55, 90),
+ "nile blue" : ( 25, 55, 81),
+ "nobel" : (183, 177, 177),
+ "nomad" : (186, 177, 162),
+ "norway" : (168, 189, 159),
+ "nugget" : (197, 153, 34),
+ "nutmeg" : (129, 66, 44),
+ "nutmeg wood finish" : (104, 54, 0),
+ "oasis" : (254, 239, 206),
+ "observatory" : ( 2, 134, 111),
+ "ocean green" : ( 65, 170, 120),
+ "ochre" : (204, 119, 34),
+ "off green" : (230, 248, 243),
+ "off yellow" : (254, 249, 227),
+ "oil" : ( 40, 30, 21),
+ "old brick" : (144, 30, 30),
+ "old copper" : (114, 74, 47),
+ "old gold" : (207, 181, 59),
+ "old lace" : (253, 245, 230),
+ "old lavender" : (121, 104, 120),
+ "old rose" : (192, 128, 129),
+ "olive" : (128, 128, 0),
+ "olive drab" : (107, 142, 35),
+ "olive green" : (181, 179, 92),
+ "olive haze" : (139, 132, 112),
+ "olivetone" : (113, 110, 16),
+ "olivine" : (154, 185, 115),
+ "onahau" : (205, 244, 255),
+ "onion" : ( 47, 39, 14),
+ "opal" : (169, 198, 194),
+ "opium" : (142, 111, 112),
+ "oracle" : ( 55, 116, 117),
+ "orange" : (255, 104, 31),
+ "orange peel" : (255, 160, 0),
+ "orange roughy" : (196, 87, 25),
+ "orange white" : (254, 252, 237),
+ "orchid" : (218, 112, 214),
+ "orchid white" : (255, 253, 243),
+ "oregon" : (155, 71, 3),
+ "orient" : ( 1, 94, 133),
+ "oriental pink" : (198, 145, 145),
+ "orinoco" : (243, 251, 212),
+ "oslo gray" : (135, 141, 145),
+ "ottoman" : (233, 248, 237),
+ "outer space" : ( 45, 56, 58),
+ "outrageous orange" : (255, 96, 55),
+ "oxford blue" : ( 56, 69, 85),
+ "oxley" : (119, 158, 134),
+ "oyster bay" : (218, 250, 255),
+ "oyster pink" : (233, 206, 205),
+ "paarl" : (166, 85, 41),
+ "pablo" : (119, 111, 97),
+ "pacific blue" : ( 0, 157, 196),
+ "pacifika" : (119, 129, 32),
+ "paco" : ( 65, 31, 16),
+ "padua" : (173, 230, 196),
+ "pale canary" : (255, 255, 153),
+ "pale leaf" : (192, 211, 185),
+ "pale oyster" : (152, 141, 119),
+ "pale prim" : (253, 254, 184),
+ "pale rose" : (255, 225, 242),
+ "pale sky" : (110, 119, 131),
+ "pale slate" : (195, 191, 193),
+ "palm green" : ( 9, 35, 15),
+ "palm leaf" : ( 25, 51, 14),
+ "pampas" : (244, 242, 238),
+ "panache" : (234, 246, 238),
+ "pancho" : (237, 205, 171),
+ "papaya whip" : (255, 239, 213),
+ "paprika" : (141, 2, 38),
+ "paradiso" : ( 49, 125, 130),
+ "parchment" : (241, 233, 210),
+ "paris daisy" : (255, 244, 110),
+ "paris m" : ( 38, 5, 106),
+ "paris white" : (202, 220, 212),
+ "parsley" : ( 19, 79, 25),
+ "pastel green" : (119, 221, 119),
+ "pastel pink" : (255, 209, 220),
+ "patina" : ( 99, 154, 143),
+ "pattens blue" : (222, 245, 255),
+ "paua" : ( 38, 3, 104),
+ "pavlova" : (215, 196, 152),
+ "peach" : (255, 229, 180),
+ "peach cream" : (255, 240, 219),
+ "peach orange" : (255, 204, 153),
+ "peach schnapps" : (255, 220, 214),
+ "peach yellow" : (250, 223, 173),
+ "peanut" : (120, 47, 22),
+ "pear" : (209, 226, 49),
+ "pearl bush" : (232, 224, 213),
+ "pearl lusta" : (252, 244, 220),
+ "peat" : (113, 107, 86),
+ "pelorous" : ( 62, 171, 191),
+ "peppermint" : (227, 245, 225),
+ "perano" : (169, 190, 242),
+ "perfume" : (208, 190, 248),
+ "periglacial blue" : (225, 230, 214),
+ "periwinkle" : (204, 204, 255),
+ "periwinkle gray" : (195, 205, 230),
+ "persian blue" : ( 28, 57, 187),
+ "persian green" : ( 0, 166, 147),
+ "persian indigo" : ( 50, 18, 122),
+ "persian pink" : (247, 127, 190),
+ "persian plum" : (112, 28, 28),
+ "persian red" : (204, 51, 51),
+ "persian rose" : (254, 40, 162),
+ "persimmon" : (255, 107, 83),
+ "peru tan" : (127, 58, 2),
+ "pesto" : (124, 118, 49),
+ "petite orchid" : (219, 150, 144),
+ "pewter" : (150, 168, 161),
+ "pharlap" : (163, 128, 123),
+ "picasso" : (255, 243, 157),
+ "pickled bean" : (110, 72, 38),
+ "pickled bluewood" : ( 49, 68, 89),
+ "picton blue" : ( 69, 177, 232),
+ "pig pink" : (253, 215, 228),
+ "pigeon post" : (175, 189, 217),
+ "pigment indigo" : ( 75, 0, 130),
+ "pine cone" : (109, 94, 84),
+ "pine glade" : (199, 205, 144),
+ "pine green" : ( 1, 121, 111),
+ "pine tree" : ( 23, 31, 4),
+ "pink" : (255, 192, 203),
+ "pink flamingo" : (255, 102, 255),
+ "pink flare" : (225, 192, 200),
+ "pink lace" : (255, 221, 244),
+ "pink lady" : (255, 241, 216),
+ "pink salmon" : (255, 145, 164),
+ "pink swan" : (190, 181, 183),
+ "piper" : (201, 99, 35),
+ "pipi" : (254, 244, 204),
+ "pippin" : (255, 225, 223),
+ "pirate gold" : (186, 127, 3),
+ "pistachio" : (157, 194, 9),
+ "pixie green" : (192, 216, 182),
+ "pizazz" : (255, 144, 0),
+ "pizza" : (201, 148, 21),
+ "plantation" : ( 39, 80, 75),
+ "plum" : (132, 49, 121),
+ "pohutukawa" : (143, 2, 28),
+ "polar" : (229, 249, 246),
+ "polo blue" : (141, 168, 204),
+ "pomegranate" : (243, 71, 35),
+ "pompadour" : (102, 0, 69),
+ "porcelain" : (239, 242, 243),
+ "porsche" : (234, 174, 105),
+ "port gore" : ( 37, 31, 79),
+ "portafino" : (255, 255, 180),
+ "portage" : (139, 159, 238),
+ "portica" : (249, 230, 99),
+ "pot pourri" : (245, 231, 226),
+ "potters clay" : (140, 87, 56),
+ "powder ash" : (188, 201, 194),
+ "powder blue" : (176, 224, 230),
+ "prairie sand" : (154, 56, 32),
+ "prelude" : (208, 192, 229),
+ "prim" : (240, 226, 236),
+ "primrose" : (237, 234, 153),
+ "provincial pink" : (254, 245, 241),
+ "prussian blue" : ( 0, 49, 83),
+ "puce" : (204, 136, 153),
+ "pueblo" : (125, 44, 20),
+ "puerto rico" : ( 63, 193, 170),
+ "pumice" : (194, 202, 196),
+ "pumpkin" : (255, 117, 24),
+ "pumpkin skin" : (177, 97, 11),
+ "punch" : (220, 67, 51),
+ "punga" : ( 77, 61, 20),
+ "purple" : (102, 0, 153),
+ "purple heart" : (101, 45, 193),
+ "purple mountain's majesty" : (150, 120, 182),
+ "purple pizzazz" : (255, 0, 204),
+ "putty" : (231, 205, 140),
+ "quarter pearl lusta" : (255, 253, 244),
+ "quarter spanish white" : (247, 242, 225),
+ "quicksand" : (189, 151, 142),
+ "quill gray" : (214, 214, 209),
+ "quincy" : ( 98, 63, 45),
+ "racing green" : ( 12, 25, 17),
+ "radical red" : (255, 53, 94),
+ "raffia" : (234, 218, 184),
+ "rainee" : (185, 200, 172),
+ "rajah" : (247, 182, 104),
+ "rangitoto" : ( 46, 50, 34),
+ "rangoon green" : ( 28, 30, 19),
+ "raven" : (114, 123, 137),
+ "raw sienna" : (210, 125, 70),
+ "raw umber" : (115, 74, 18),
+ "razzle dazzle rose" : (255, 51, 204),
+ "razzmatazz" : (227, 11, 92),
+ "rebel" : ( 60, 18, 6),
+ "red" : (255, 0, 0),
+ "red beech" : (123, 56, 1),
+ "red berry" : (142, 0, 0),
+ "red damask" : (218, 106, 65),
+ "red devil" : (134, 1, 17),
+ "red orange" : (255, 63, 52),
+ "red oxide" : (110, 9, 2),
+ "red ribbon" : (237, 10, 63),
+ "red robin" : (128, 52, 31),
+ "red stage" : (208, 95, 4),
+ "red violet" : (199, 21, 133),
+ "redwood" : ( 93, 30, 15),
+ "reef" : (201, 255, 162),
+ "reef gold" : (159, 130, 28),
+ "regal blue" : ( 1, 63, 106),
+ "regent gray" : (134, 148, 159),
+ "regent st blue" : (170, 214, 230),
+ "remy" : (254, 235, 243),
+ "reno sand" : (168, 101, 21),
+ "resolution blue" : ( 0, 35, 135),
+ "revolver" : ( 44, 22, 50),
+ "rhino" : ( 46, 63, 98),
+ "rice cake" : (255, 254, 240),
+ "rice flower" : (238, 255, 226),
+ "rich gold" : (168, 83, 7),
+ "rio grande" : (187, 208, 9),
+ "ripe lemon" : (244, 216, 28),
+ "ripe plum" : ( 65, 0, 86),
+ "riptide" : (139, 230, 216),
+ "river bed" : ( 67, 76, 89),
+ "rob roy" : (234, 198, 116),
+ "robin's egg blue" : ( 0, 204, 204),
+ "rock" : ( 77, 56, 51),
+ "rock blue" : (158, 177, 205),
+ "rock spray" : (186, 69, 12),
+ "rodeo dust" : (201, 178, 155),
+ "rolling stone" : (116, 125, 131),
+ "roman" : (222, 99, 96),
+ "roman coffee" : (121, 93, 76),
+ "romance" : (255, 254, 253),
+ "romantic" : (255, 210, 183),
+ "ronchi" : (236, 197, 78),
+ "roof terracotta" : (166, 47, 32),
+ "rope" : (142, 77, 30),
+ "rose" : (255, 0, 127),
+ "rose bud" : (251, 178, 163),
+ "rose bud cherry" : (128, 11, 71),
+ "rose fog" : (231, 188, 180),
+ "rose white" : (255, 246, 245),
+ "rose of sharon" : (191, 85, 0),
+ "rosewood" : (101, 0, 11),
+ "roti" : (198, 168, 75),
+ "rouge" : (162, 59, 108),
+ "royal blue" : ( 65, 105, 225),
+ "royal heath" : (171, 52, 114),
+ "royal purple" : (107, 63, 160),
+ "rum" : (121, 105, 137),
+ "rum swizzle" : (249, 248, 228),
+ "russet" : (128, 70, 27),
+ "russett" : (117, 90, 87),
+ "rust" : (183, 65, 14),
+ "rustic red" : ( 72, 4, 4),
+ "rusty nail" : (134, 86, 10),
+ "saddle" : ( 76, 48, 36),
+ "saddle brown" : ( 88, 52, 1),
+ "saffron" : (244, 196, 48),
+ "saffron mango" : (249, 191, 88),
+ "sage" : (158, 165, 135),
+ "sahara" : (183, 162, 20),
+ "sahara sand" : (241, 231, 136),
+ "sail" : (184, 224, 249),
+ "salem" : ( 9, 127, 75),
+ "salmon" : (255, 140, 105),
+ "salomie" : (254, 219, 141),
+ "salt box" : (104, 94, 110),
+ "saltpan" : (241, 247, 242),
+ "sambuca" : ( 58, 32, 16),
+ "san felix" : ( 11, 98, 7),
+ "san juan" : ( 48, 75, 106),
+ "san marino" : ( 69, 108, 172),
+ "sand dune" : (130, 111, 101),
+ "sandal" : (170, 141, 111),
+ "sandrift" : (171, 145, 122),
+ "sandstone" : (121, 109, 98),
+ "sandwisp" : (245, 231, 162),
+ "sandy beach" : (255, 234, 200),
+ "sandy brown" : (244, 164, 96),
+ "sangria" : (146, 0, 10),
+ "sanguine brown" : (141, 61, 56),
+ "santa fe" : (177, 109, 82),
+ "santas gray" : (159, 160, 177),
+ "sapling" : (222, 212, 164),
+ "sapphire" : ( 47, 81, 158),
+ "saratoga" : ( 85, 91, 16),
+ "satin linen" : (230, 228, 212),
+ "sauvignon" : (255, 245, 243),
+ "sazerac" : (255, 244, 224),
+ "scampi" : (103, 95, 166),
+ "scandal" : (207, 250, 244),
+ "scarlet" : (255, 36, 0),
+ "scarlet gum" : ( 67, 21, 96),
+ "scarlett" : (149, 0, 21),
+ "scarpa flow" : ( 88, 85, 98),
+ "schist" : (169, 180, 151),
+ "school bus yellow" : (255, 216, 0),
+ "schooner" : (139, 132, 126),
+ "science blue" : ( 0, 102, 204),
+ "scooter" : ( 46, 191, 212),
+ "scorpion" : (105, 95, 98),
+ "scotch mist" : (255, 251, 220),
+ "screamin' green" : (102, 255, 102),
+ "sea buckthorn" : (251, 161, 41),
+ "sea green" : ( 46, 139, 87),
+ "sea mist" : (197, 219, 202),
+ "sea nymph" : (120, 163, 156),
+ "sea pink" : (237, 152, 158),
+ "seagull" : (128, 204, 234),
+ "seance" : (115, 30, 143),
+ "seashell" : (241, 241, 241),
+ "seashell peach" : (255, 245, 238),
+ "seaweed" : ( 27, 47, 17),
+ "selago" : (240, 238, 253),
+ "selective yellow" : (255, 186, 0),
+ "sepia" : (112, 66, 20),
+ "sepia black" : ( 43, 2, 2),
+ "sepia skin" : (158, 91, 64),
+ "serenade" : (255, 244, 232),
+ "shadow" : (131, 112, 80),
+ "shadow green" : (154, 194, 184),
+ "shady lady" : (170, 165, 169),
+ "shakespeare" : ( 78, 171, 209),
+ "shalimar" : (251, 255, 186),
+ "shamrock" : ( 51, 204, 153),
+ "shark" : ( 37, 39, 44),
+ "sherpa blue" : ( 0, 73, 80),
+ "sherwood green" : ( 2, 64, 44),
+ "shilo" : (232, 185, 179),
+ "shingle fawn" : (107, 78, 49),
+ "ship cove" : (120, 139, 186),
+ "ship gray" : ( 62, 58, 68),
+ "shiraz" : (178, 9, 49),
+ "shocking" : (226, 146, 192),
+ "shocking pink" : (252, 15, 192),
+ "shuttle gray" : ( 95, 102, 114),
+ "siam" : (100, 106, 84),
+ "sidecar" : (243, 231, 187),
+ "silk" : (189, 177, 168),
+ "silver" : (192, 192, 192),
+ "silver chalice" : (172, 172, 172),
+ "silver rust" : (201, 192, 187),
+ "silver sand" : (191, 193, 194),
+ "silver tree" : (102, 181, 143),
+ "sinbad" : (159, 215, 211),
+ "siren" : (122, 1, 58),
+ "sirocco" : (113, 128, 128),
+ "sisal" : (211, 203, 186),
+ "skeptic" : (202, 230, 218),
+ "sky blue" : (118, 215, 234),
+ "slate gray" : (112, 128, 144),
+ "smalt" : ( 0, 51, 153),
+ "smalt blue" : ( 81, 128, 143),
+ "smoky" : ( 96, 91, 115),
+ "snow drift" : (247, 250, 247),
+ "snow flurry" : (228, 255, 209),
+ "snowy mint" : (214, 255, 219),
+ "snuff" : (226, 216, 237),
+ "soapstone" : (255, 251, 249),
+ "soft amber" : (209, 198, 180),
+ "soft peach" : (245, 237, 239),
+ "solid pink" : (137, 56, 67),
+ "solitaire" : (254, 248, 226),
+ "solitude" : (234, 246, 255),
+ "sorbus" : (253, 124, 7),
+ "sorrell brown" : (206, 185, 143),
+ "soya bean" : (106, 96, 81),
+ "spanish green" : (129, 152, 133),
+ "spectra" : ( 47, 90, 87),
+ "spice" : (106, 68, 46),
+ "spicy mix" : (136, 83, 66),
+ "spicy mustard" : (116, 100, 13),
+ "spicy pink" : (129, 110, 113),
+ "spindle" : (182, 209, 234),
+ "spray" : (121, 222, 236),
+ "spring green" : ( 0, 255, 127),
+ "spring leaves" : ( 87, 131, 99),
+ "spring rain" : (172, 203, 177),
+ "spring sun" : (246, 255, 220),
+ "spring wood" : (248, 246, 241),
+ "sprout" : (193, 215, 176),
+ "spun pearl" : (170, 171, 183),
+ "squirrel" : (143, 129, 118),
+ "st tropaz" : ( 45, 86, 155),
+ "stack" : (138, 143, 138),
+ "star dust" : (159, 159, 156),
+ "stark white" : (229, 215, 189),
+ "starship" : (236, 242, 69),
+ "steel blue" : ( 70, 130, 180),
+ "steel gray" : ( 38, 35, 53),
+ "stiletto" : (156, 51, 54),
+ "stonewall" : (146, 133, 115),
+ "storm dust" : (100, 100, 99),
+ "storm gray" : (113, 116, 134),
+ "stratos" : ( 0, 7, 65),
+ "straw" : (212, 191, 141),
+ "strikemaster" : (149, 99, 135),
+ "stromboli" : ( 50, 93, 82),
+ "studio" : (113, 74, 178),
+ "submarine" : (186, 199, 201),
+ "sugar cane" : (249, 255, 246),
+ "sulu" : (193, 240, 124),
+ "summer green" : (150, 187, 171),
+ "sun" : (251, 172, 19),
+ "sundance" : (201, 179, 91),
+ "sundown" : (255, 177, 179),
+ "sunflower" : (228, 212, 34),
+ "sunglo" : (225, 104, 101),
+ "sunglow" : (255, 204, 51),
+ "sunset orange" : (254, 76, 64),
+ "sunshade" : (255, 158, 44),
+ "supernova" : (255, 201, 1),
+ "surf" : (187, 215, 193),
+ "surf crest" : (207, 229, 210),
+ "surfie green" : ( 12, 122, 121),
+ "sushi" : (135, 171, 57),
+ "suva gray" : (136, 131, 135),
+ "swamp" : ( 0, 27, 28),
+ "swamp green" : (172, 183, 142),
+ "swans down" : (220, 240, 234),
+ "sweet corn" : (251, 234, 140),
+ "sweet pink" : (253, 159, 162),
+ "swirl" : (211, 205, 197),
+ "swiss coffee" : (221, 214, 213),
+ "sycamore" : (144, 141, 57),
+ "tabasco" : (160, 39, 18),
+ "tacao" : (237, 179, 129),
+ "tacha" : (214, 197, 98),
+ "tahiti gold" : (233, 124, 7),
+ "tahuna sands" : (238, 240, 200),
+ "tall poppy" : (179, 45, 41),
+ "tallow" : (168, 165, 137),
+ "tamarillo" : (153, 22, 19),
+ "tamarind" : ( 52, 21, 21),
+ "tan" : (210, 180, 140),
+ "tan hide" : (250, 157, 90),
+ "tana" : (217, 220, 193),
+ "tangaroa" : ( 3, 22, 60),
+ "tangerine" : (242, 133, 0),
+ "tango" : (237, 122, 28),
+ "tapa" : (123, 120, 116),
+ "tapestry" : (176, 94, 129),
+ "tara" : (225, 246, 232),
+ "tarawera" : ( 7, 58, 80),
+ "tasman" : (207, 220, 207),
+ "taupe" : ( 72, 60, 50),
+ "taupe gray" : (179, 175, 149),
+ "tawny port" : (105, 37, 69),
+ "te papa green" : ( 30, 67, 60),
+ "tea" : (193, 186, 176),
+ "tea green" : (208, 240, 192),
+ "teak" : (177, 148, 97),
+ "teal" : ( 0, 128, 128),
+ "teal blue" : ( 4, 66, 89),
+ "temptress" : ( 59, 0, 11),
+ "tenn" : (205, 87, 0),
+ "tequila" : (255, 230, 199),
+ "terracotta" : (226, 114, 91),
+ "texas" : (248, 249, 156),
+ "texas rose" : (255, 181, 85),
+ "thatch" : (182, 157, 152),
+ "thatch green" : ( 64, 61, 25),
+ "thistle" : (216, 191, 216),
+ "thistle green" : (204, 202, 168),
+ "thunder" : ( 51, 41, 47),
+ "thunderbird" : (192, 43, 24),
+ "tia maria" : (193, 68, 14),
+ "tiara" : (195, 209, 209),
+ "tiber" : ( 6, 53, 55),
+ "tickle me pink" : (252, 128, 165),
+ "tidal" : (241, 255, 173),
+ "tide" : (191, 184, 176),
+ "timber green" : ( 22, 50, 44),
+ "timberwolf" : (217, 214, 207),
+ "titan white" : (240, 238, 255),
+ "toast" : (154, 110, 97),
+ "tobacco brown" : (113, 93, 71),
+ "toledo" : ( 58, 0, 32),
+ "tolopea" : ( 27, 2, 69),
+ "tom thumb" : ( 63, 88, 59),
+ "tonys pink" : (231, 159, 140),
+ "topaz" : (124, 119, 138),
+ "torch red" : (253, 14, 53),
+ "torea bay" : ( 15, 45, 158),
+ "tory blue" : ( 20, 80, 170),
+ "tosca" : (141, 63, 63),
+ "totem pole" : (153, 27, 7),
+ "tower gray" : (169, 189, 191),
+ "tradewind" : ( 95, 179, 172),
+ "tranquil" : (230, 255, 255),
+ "travertine" : (255, 253, 232),
+ "tree poppy" : (252, 156, 29),
+ "treehouse" : ( 59, 40, 32),
+ "trendy green" : (124, 136, 26),
+ "trendy pink" : (140, 100, 149),
+ "trinidad" : (230, 78, 3),
+ "tropical blue" : (195, 221, 249),
+ "tropical rain forest" : ( 0, 117, 94),
+ "trout" : ( 74, 78, 90),
+ "true v" : (138, 115, 214),
+ "tuatara" : ( 54, 53, 52),
+ "tuft bush" : (255, 221, 205),
+ "tulip tree" : (234, 179, 59),
+ "tumbleweed" : (222, 166, 129),
+ "tuna" : ( 53, 53, 66),
+ "tundora" : ( 74, 66, 68),
+ "turbo" : (250, 230, 0),
+ "turkish rose" : (181, 114, 129),
+ "turmeric" : (202, 187, 72),
+ "turquoise" : ( 48, 213, 200),
+ "turquoise blue" : (108, 218, 231),
+ "turtle green" : ( 42, 56, 11),
+ "tuscany" : (189, 94, 46),
+ "tusk" : (238, 243, 195),
+ "tussock" : (197, 153, 75),
+ "tutu" : (255, 241, 249),
+ "twilight" : (228, 207, 222),
+ "twilight blue" : (238, 253, 255),
+ "twine" : (194, 149, 93),
+ "tyrian purple" : (102, 2, 60),
+ "ultramarine" : ( 18, 10, 143),
+ "valencia" : (216, 68, 55),
+ "valentino" : ( 53, 14, 66),
+ "valhalla" : ( 43, 25, 79),
+ "van cleef" : ( 73, 23, 12),
+ "vanilla" : (209, 190, 168),
+ "vanilla ice" : (243, 217, 223),
+ "varden" : (255, 246, 223),
+ "venetian red" : (114, 1, 15),
+ "venice blue" : ( 5, 89, 137),
+ "venus" : (146, 133, 144),
+ "verdigris" : ( 93, 94, 55),
+ "verdun green" : ( 73, 84, 0),
+ "vermilion" : (255, 77, 0),
+ "vesuvius" : (177, 74, 11),
+ "victoria" : ( 83, 68, 145),
+ "vida loca" : ( 84, 144, 25),
+ "viking" : (100, 204, 219),
+ "vin rouge" : (152, 61, 97),
+ "viola" : (203, 143, 169),
+ "violent violet" : ( 41, 12, 94),
+ "violet" : ( 36, 10, 64),
+ "violet eggplant" : (153, 17, 153),
+ "violet red" : (247, 70, 138),
+ "viridian" : ( 64, 130, 109),
+ "viridian green" : (103, 137, 117),
+ "vis vis" : (255, 239, 161),
+ "vista blue" : (143, 214, 180),
+ "vista white" : (252, 248, 247),
+ "vivid tangerine" : (255, 153, 128),
+ "vivid violet" : (128, 55, 144),
+ "voodoo" : ( 83, 52, 85),
+ "vulcan" : ( 16, 18, 29),
+ "wafer" : (222, 203, 198),
+ "waikawa gray" : ( 90, 110, 156),
+ "waiouru" : ( 54, 60, 13),
+ "walnut" : (119, 63, 26),
+ "wasabi" : (120, 138, 37),
+ "water leaf" : (161, 233, 222),
+ "watercourse" : ( 5, 111, 87),
+ "waterloo " : (123, 124, 148),
+ "wattle" : (220, 215, 71),
+ "watusi" : (255, 221, 207),
+ "wax flower" : (255, 192, 168),
+ "we peep" : (247, 219, 230),
+ "web orange" : (255, 165, 0),
+ "wedgewood" : ( 78, 127, 158),
+ "well read" : (180, 51, 50),
+ "west coast" : ( 98, 81, 25),
+ "west side" : (255, 145, 15),
+ "westar" : (220, 217, 210),
+ "wewak" : (241, 155, 171),
+ "wheat" : (245, 222, 179),
+ "wheatfield" : (243, 237, 207),
+ "whiskey" : (213, 154, 111),
+ "whisper" : (247, 245, 250),
+ "white" : (255, 255, 255),
+ "white ice" : (221, 249, 241),
+ "white lilac" : (248, 247, 252),
+ "white linen" : (248, 240, 232),
+ "white pointer" : (254, 248, 255),
+ "white rock" : (234, 232, 212),
+ "wild blue yonder" : (122, 137, 184),
+ "wild rice" : (236, 224, 144),
+ "wild sand" : (244, 244, 244),
+ "wild strawberry" : (255, 51, 153),
+ "wild watermelon" : (253, 91, 120),
+ "wild willow" : (185, 196, 106),
+ "william" : ( 58, 104, 108),
+ "willow brook" : (223, 236, 218),
+ "willow grove" : (101, 116, 93),
+ "windsor" : ( 60, 8, 120),
+ "wine berry" : ( 89, 29, 53),
+ "winter hazel" : (213, 209, 149),
+ "wisp pink" : (254, 244, 248),
+ "wisteria" : (151, 113, 181),
+ "wistful" : (164, 166, 211),
+ "witch haze" : (255, 252, 153),
+ "wood bark" : ( 38, 17, 5),
+ "woodland" : ( 77, 83, 40),
+ "woodrush" : ( 48, 42, 15),
+ "woodsmoke" : ( 12, 13, 15),
+ "woody brown" : ( 72, 49, 49),
+ "xanadu" : (115, 134, 120),
+ "yellow" : (255, 255, 0),
+ "yellow green" : (197, 225, 122),
+ "yellow metal" : (113, 99, 56),
+ "yellow orange" : (255, 174, 66),
+ "yellow sea" : (254, 169, 4),
+ "your pink" : (255, 195, 192),
+ "yukon gold" : (123, 102, 8),
+ "yuma" : (206, 194, 145),
+ "zambezi" : (104, 85, 88),
+ "zanah" : (218, 236, 214),
+ "zest" : (229, 132, 27),
+ "zeus" : ( 41, 35, 25),
+ "ziggurat" : (191, 219, 226),
+ "zinnwaldite" : (235, 194, 175),
+ "zircon" : (244, 248, 255),
+ "zombie" : (228, 214, 155),
+ "zorba" : (165, 155, 145),
+ "zuccini" : ( 4, 64, 34),
+ "zumthor" : (237, 246, 255)}
+
+def build_reverse_dict():
+ global reverse
+ global colorhex
+ global colors
+ for color in colors:
+ rgb = colors[color]
+ hex = '#%02X%02X%02X' % (rgb)
+ reverse[hex] = color
+ colorhex[color] = hex
+ return
+
+
+def get_complementary_hex(color):
+ # strip the # from the beginning
+ color = color[1:]
+ # convert the string into hex
+ color = int(color, 16)
+ # invert the three bytes
+ # as good as substracting each of RGB component by 255(FF)
+ comp_color = 0xFFFFFF ^ color
+ # convert the color back to hex by prefixing a #
+ comp_color = "#%06X" % comp_color
+ # return the result
+ return comp_color
+
+def get_complementary_rgb(red, green, blue):
+ color_string = '#%02X%02X%02X' % (red, green, blue)
+ # strip the # from the beginning
+ color = color_string[1:]
+ # convert the string into hex
+ color = int(color, 16)
+ # invert the three bytes
+ # as good as substracting each of RGB component by 255(FF)
+ comp_color = 0xFFFFFF ^ color
+ # convert the color back to hex by prefixing a #
+ comp_color = "#%06X" % comp_color
+ # return the result
+ return comp_color
+
+def get_name_from_hex(hex):
+ global reverse
+ global colorhex
+ global colors
+
+ hex = hex.upper()
+ try:
+ name = reverse[hex]
+ except:
+ name = 'No Hex For Name'
+ return name
+
+def get_hex_from_name(name):
+ global reverse
+ global colorhex
+ global colors
+
+ name = name.lower()
+ try:
+ hex = colorhex[name]
+ except:
+ hex = '#000000'
+ return hex
+
+def show_all_colors_on_buttons():
+ global reverse
+ global colorhex
+ global colors
+ window = sg.Window('Colors on Buttons Demo', default_element_size=(3, 1), location=(0, 0), icon=MY_WINDOW_ICON, font=("Helvetica", 7))
+ row = []
+ row_len = 20
+ for i, c in enumerate(colors):
+ hex = get_hex_from_name(c)
+ button1 = sg.CButton(button_text=c, button_color=(get_complementary_hex(hex), hex), size=(8, 1))
+ button2 = sg.CButton(button_text=c, button_color=(hex, get_complementary_hex(hex)), size=(8, 1))
+ row.append(button1)
+ row.append(button2)
+ if (i+1) % row_len == 0:
+ window.AddRow(*row)
+ row = []
+ if row != []:
+ window.AddRow(*row)
+ window.Show()
+
+
+GoodColors = [('#0e6251', sg.RGB(255, 246, 122)),
+ ('white', sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 210, 124), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 210, 87), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 164, 73), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 74, 60), sg.RGB(0, 74, 60)),
+ ]
+
+
+def main():
+ global colors
+ global reverse
+
+ build_reverse_dict()
+ list_of_colors = [c for c in colors]
+ printable = '\n'.join(map(str, list_of_colors))
+ # show_all_colors_on_buttons()
+ sg.SetOptions(element_padding=(0,0))
+ while True:
+ # ------- Form show ------- #
+ layout = [[sg.Text('Find color')],
+ [sg.Text('Demonstration of colors')],
+ [sg.Text('Enter a color name in text or hex #RRGGBB format')],
+ [sg.InputText(key='hex')],
+ [sg.Listbox(list_of_colors, size=(20, 30), bind_return_key=True, key='listbox'), sg.T('Or choose from list')],
+ [sg.Submit(), sg.Button('Many buttons', button_color=('white', '#0e6251'), key='Many buttons'), sg.ColorChooserButton( 'Chooser', target=(3,0), key='Chooser'), sg.Quit(),],
+ ]
+ # [g.Multiline(DefaultText=str(printable), Size=(30,20))]]
+ event, values = sg.Window('Color Demo', auto_size_buttons=False).Layout(layout).Read()
+
+ # ------- OUTPUT results portion ------- #
+ if event == 'Quit' or event is None:
+ exit(0)
+ elif event == 'Many buttons':
+ show_all_colors_on_buttons()
+
+ drop_down_value = values['listbox']
+ hex_input = values['hex']
+ if hex_input == '' and len(drop_down_value) == 0:
+ continue
+
+ if len(hex_input) != 0:
+ if hex_input[0] == '#':
+ color_hex = hex_input.upper()
+ color_name = get_name_from_hex(hex_input)
+ else:
+ color_name = hex_input
+ color_hex = get_hex_from_name(color_name)
+ elif drop_down_value is not None and len(drop_down_value) != 0:
+ color_name = drop_down_value[0]
+ color_hex = get_hex_from_name(color_name)
+
+ complementary_hex = get_complementary_hex(color_hex)
+ complementary_color = get_name_from_hex(complementary_hex)
+
+ layout = [[sg.Text('That color and it\'s compliment are shown on these buttons. This form auto-closes')],
+ [sg.CloseButton(button_text=color_name, button_color=(color_hex, complementary_hex))],
+ [sg.CloseButton(button_text=complementary_hex + ' ' + complementary_color, button_color=(complementary_hex , color_hex), size=(30, 1))],
+ ]
+ sg.Window('Color demo', default_element_size=(100, 1), auto_size_text=True, auto_close=True, auto_close_duration=5, icon=MY_WINDOW_ICON).Layout(layout).Read()
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Color_Names.py b/DemoPrograms old/Demo_Color_Names.py
new file mode 100644
index 000000000..aa080f307
--- /dev/null
+++ b/DemoPrograms old/Demo_Color_Names.py
@@ -0,0 +1,709 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+
+"""
+
+ Shows a big chart of colors... give it a few seconds to create it
+ Once large window is shown, you can click on any color and another window will popup
+ showing both white and black text on that color
+ Uses TOOLTIPS to show the hex values for the colors. Hover over a color and a tooltip will show you the RGB
+ You will find the list of tkinter colors here:
+ http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm
+
+"""
+
+color_map = {
+ 'alice blue': '#F0F8FF',
+ 'AliceBlue': '#F0F8FF',
+ 'antique white': '#FAEBD7',
+ 'AntiqueWhite': '#FAEBD7',
+ 'AntiqueWhite1': '#FFEFDB',
+ 'AntiqueWhite2': '#EEDFCC',
+ 'AntiqueWhite3': '#CDC0B0',
+ 'AntiqueWhite4': '#8B8378',
+ 'aquamarine': '#7FFFD4',
+ 'aquamarine1': '#7FFFD4',
+ 'aquamarine2': '#76EEC6',
+ 'aquamarine3': '#66CDAA',
+ 'aquamarine4': '#458B74',
+ 'azure': '#F0FFFF',
+ 'azure1': '#F0FFFF',
+ 'azure2': '#E0EEEE',
+ 'azure3': '#C1CDCD',
+ 'azure4': '#838B8B',
+ 'beige': '#F5F5DC',
+ 'bisque': '#FFE4C4',
+ 'bisque1': '#FFE4C4',
+ 'bisque2': '#EED5B7',
+ 'bisque3': '#CDB79E',
+ 'bisque4': '#8B7D6B',
+ 'black': '#000000',
+ 'blanched almond': '#FFEBCD',
+ 'BlanchedAlmond': '#FFEBCD',
+ 'blue': '#0000FF',
+ 'blue violet': '#8A2BE2',
+ 'blue1': '#0000FF',
+ 'blue2': '#0000EE',
+ 'blue3': '#0000CD',
+ 'blue4': '#00008B',
+ 'BlueViolet': '#8A2BE2',
+ 'brown': '#A52A2A',
+ 'brown1': '#FF4040',
+ 'brown2': '#EE3B3B',
+ 'brown3': '#CD3333',
+ 'brown4': '#8B2323',
+ 'burlywood': '#DEB887',
+ 'burlywood1': '#FFD39B',
+ 'burlywood2': '#EEC591',
+ 'burlywood3': '#CDAA7D',
+ 'burlywood4': '#8B7355',
+ 'cadet blue': '#5F9EA0',
+ 'CadetBlue': '#5F9EA0',
+ 'CadetBlue1': '#98F5FF',
+ 'CadetBlue2': '#8EE5EE',
+ 'CadetBlue3': '#7AC5CD',
+ 'CadetBlue4': '#53868B',
+ 'chartreuse': '#7FFF00',
+ 'chartreuse1': '#7FFF00',
+ 'chartreuse2': '#76EE00',
+ 'chartreuse3': '#66CD00',
+ 'chartreuse4': '#458B00',
+ 'chocolate': '#D2691E',
+ 'chocolate1': '#FF7F24',
+ 'chocolate2': '#EE7621',
+ 'chocolate3': '#CD661D',
+ 'chocolate4': '#8B4513',
+ 'coral': '#FF7F50',
+ 'coral1': '#FF7256',
+ 'coral2': '#EE6A50',
+ 'coral3': '#CD5B45',
+ 'coral4': '#8B3E2F',
+ 'cornflower blue': '#6495ED',
+ 'CornflowerBlue': '#6495ED',
+ 'cornsilk': '#FFF8DC',
+ 'cornsilk1': '#FFF8DC',
+ 'cornsilk2': '#EEE8CD',
+ 'cornsilk3': '#CDC8B1',
+ 'cornsilk4': '#8B8878',
+ 'cyan': '#00FFFF',
+ 'cyan1': '#00FFFF',
+ 'cyan2': '#00EEEE',
+ 'cyan3': '#00CDCD',
+ 'cyan4': '#008B8B',
+ 'dark blue': '#00008B',
+ 'dark cyan': '#008B8B',
+ 'dark goldenrod': '#B8860B',
+ 'dark gray': '#A9A9A9',
+ 'dark green': '#006400',
+ 'dark grey': '#A9A9A9',
+ 'dark khaki': '#BDB76B',
+ 'dark magenta': '#8B008B',
+ 'dark olive green': '#556B2F',
+ 'dark orange': '#FF8C00',
+ 'dark orchid': '#9932CC',
+ 'dark red': '#8B0000',
+ 'dark salmon': '#E9967A',
+ 'dark sea green': '#8FBC8F',
+ 'dark slate blue': '#483D8B',
+ 'dark slate gray': '#2F4F4F',
+ 'dark slate grey': '#2F4F4F',
+ 'dark turquoise': '#00CED1',
+ 'dark violet': '#9400D3',
+ 'DarkBlue': '#00008B',
+ 'DarkCyan': '#008B8B',
+ 'DarkGoldenrod': '#B8860B',
+ 'DarkGoldenrod1': '#FFB90F',
+ 'DarkGoldenrod2': '#EEAD0E',
+ 'DarkGoldenrod3': '#CD950C',
+ 'DarkGoldenrod4': '#8B6508',
+ 'DarkGray': '#A9A9A9',
+ 'DarkGreen': '#006400',
+ 'DarkGrey': '#A9A9A9',
+ 'DarkKhaki': '#BDB76B',
+ 'DarkMagenta': '#8B008B',
+ 'DarkOliveGreen': '#556B2F',
+ 'DarkOliveGreen1': '#CAFF70',
+ 'DarkOliveGreen2': '#BCEE68',
+ 'DarkOliveGreen3': '#A2CD5A',
+ 'DarkOliveGreen4': '#6E8B3D',
+ 'DarkOrange': '#FF8C00',
+ 'DarkOrange1': '#FF7F00',
+ 'DarkOrange2': '#EE7600',
+ 'DarkOrange3': '#CD6600',
+ 'DarkOrange4': '#8B4500',
+ 'DarkOrchid': '#9932CC',
+ 'DarkOrchid1': '#BF3EFF',
+ 'DarkOrchid2': '#B23AEE',
+ 'DarkOrchid3': '#9A32CD',
+ 'DarkOrchid4': '#68228B',
+ 'DarkRed': '#8B0000',
+ 'DarkSalmon': '#E9967A',
+ 'DarkSeaGreen': '#8FBC8F',
+ 'DarkSeaGreen1': '#C1FFC1',
+ 'DarkSeaGreen2': '#B4EEB4',
+ 'DarkSeaGreen3': '#9BCD9B',
+ 'DarkSeaGreen4': '#698B69',
+ 'DarkSlateBlue': '#483D8B',
+ 'DarkSlateGray': '#2F4F4F',
+ 'DarkSlateGray1': '#97FFFF',
+ 'DarkSlateGray2': '#8DEEEE',
+ 'DarkSlateGray3': '#79CDCD',
+ 'DarkSlateGray4': '#528B8B',
+ 'DarkSlateGrey': '#2F4F4F',
+ 'DarkTurquoise': '#00CED1',
+ 'DarkViolet': '#9400D3',
+ 'deep pink': '#FF1493',
+ 'deep sky blue': '#00BFFF',
+ 'DeepPink': '#FF1493',
+ 'DeepPink1': '#FF1493',
+ 'DeepPink2': '#EE1289',
+ 'DeepPink3': '#CD1076',
+ 'DeepPink4': '#8B0A50',
+ 'DeepSkyBlue': '#00BFFF',
+ 'DeepSkyBlue1': '#00BFFF',
+ 'DeepSkyBlue2': '#00B2EE',
+ 'DeepSkyBlue3': '#009ACD',
+ 'DeepSkyBlue4': '#00688B',
+ 'dim gray': '#696969',
+ 'dim grey': '#696969',
+ 'DimGray': '#696969',
+ 'DimGrey': '#696969',
+ 'dodger blue': '#1E90FF',
+ 'DodgerBlue': '#1E90FF',
+ 'DodgerBlue1': '#1E90FF',
+ 'DodgerBlue2': '#1C86EE',
+ 'DodgerBlue3': '#1874CD',
+ 'DodgerBlue4': '#104E8B',
+ 'firebrick': '#B22222',
+ 'firebrick1': '#FF3030',
+ 'firebrick2': '#EE2C2C',
+ 'firebrick3': '#CD2626',
+ 'firebrick4': '#8B1A1A',
+ 'floral white': '#FFFAF0',
+ 'FloralWhite': '#FFFAF0',
+ 'forest green': '#228B22',
+ 'ForestGreen': '#228B22',
+ 'gainsboro': '#DCDCDC',
+ 'ghost white': '#F8F8FF',
+ 'GhostWhite': '#F8F8FF',
+ 'gold': '#FFD700',
+ 'gold1': '#FFD700',
+ 'gold2': '#EEC900',
+ 'gold3': '#CDAD00',
+ 'gold4': '#8B7500',
+ 'goldenrod': '#DAA520',
+ 'goldenrod1': '#FFC125',
+ 'goldenrod2': '#EEB422',
+ 'goldenrod3': '#CD9B1D',
+ 'goldenrod4': '#8B6914',
+ 'green': '#00FF00',
+ 'green yellow': '#ADFF2F',
+ 'green1': '#00FF00',
+ 'green2': '#00EE00',
+ 'green3': '#00CD00',
+ 'green4': '#008B00',
+ 'GreenYellow': '#ADFF2F',
+ 'grey': '#BEBEBE',
+ 'grey0': '#000000',
+ 'grey1': '#030303',
+ 'grey2': '#050505',
+ 'grey3': '#080808',
+ 'grey4': '#0A0A0A',
+ 'grey5': '#0D0D0D',
+ 'grey6': '#0F0F0F',
+ 'grey7': '#121212',
+ 'grey8': '#141414',
+ 'grey9': '#171717',
+ 'grey10': '#1A1A1A',
+ 'grey11': '#1C1C1C',
+ 'grey12': '#1F1F1F',
+ 'grey13': '#212121',
+ 'grey14': '#242424',
+ 'grey15': '#262626',
+ 'grey16': '#292929',
+ 'grey17': '#2B2B2B',
+ 'grey18': '#2E2E2E',
+ 'grey19': '#303030',
+ 'grey20': '#333333',
+ 'grey21': '#363636',
+ 'grey22': '#383838',
+ 'grey23': '#3B3B3B',
+ 'grey24': '#3D3D3D',
+ 'grey25': '#404040',
+ 'grey26': '#424242',
+ 'grey27': '#454545',
+ 'grey28': '#474747',
+ 'grey29': '#4A4A4A',
+ 'grey30': '#4D4D4D',
+ 'grey31': '#4F4F4F',
+ 'grey32': '#525252',
+ 'grey33': '#545454',
+ 'grey34': '#575757',
+ 'grey35': '#595959',
+ 'grey36': '#5C5C5C',
+ 'grey37': '#5E5E5E',
+ 'grey38': '#616161',
+ 'grey39': '#636363',
+ 'grey40': '#666666',
+ 'grey41': '#696969',
+ 'grey42': '#6B6B6B',
+ 'grey43': '#6E6E6E',
+ 'grey44': '#707070',
+ 'grey45': '#737373',
+ 'grey46': '#757575',
+ 'grey47': '#787878',
+ 'grey48': '#7A7A7A',
+ 'grey49': '#7D7D7D',
+ 'grey50': '#7F7F7F',
+ 'grey51': '#828282',
+ 'grey52': '#858585',
+ 'grey53': '#878787',
+ 'grey54': '#8A8A8A',
+ 'grey55': '#8C8C8C',
+ 'grey56': '#8F8F8F',
+ 'grey57': '#919191',
+ 'grey58': '#949494',
+ 'grey59': '#969696',
+ 'grey60': '#999999',
+ 'grey61': '#9C9C9C',
+ 'grey62': '#9E9E9E',
+ 'grey63': '#A1A1A1',
+ 'grey64': '#A3A3A3',
+ 'grey65': '#A6A6A6',
+ 'grey66': '#A8A8A8',
+ 'grey67': '#ABABAB',
+ 'grey68': '#ADADAD',
+ 'grey69': '#B0B0B0',
+ 'grey70': '#B3B3B3',
+ 'grey71': '#B5B5B5',
+ 'grey72': '#B8B8B8',
+ 'grey73': '#BABABA',
+ 'grey74': '#BDBDBD',
+ 'grey75': '#BFBFBF',
+ 'grey76': '#C2C2C2',
+ 'grey77': '#C4C4C4',
+ 'grey78': '#C7C7C7',
+ 'grey79': '#C9C9C9',
+ 'grey80': '#CCCCCC',
+ 'grey81': '#CFCFCF',
+ 'grey82': '#D1D1D1',
+ 'grey83': '#D4D4D4',
+ 'grey84': '#D6D6D6',
+ 'grey85': '#D9D9D9',
+ 'grey86': '#DBDBDB',
+ 'grey87': '#DEDEDE',
+ 'grey88': '#E0E0E0',
+ 'grey89': '#E3E3E3',
+ 'grey90': '#E5E5E5',
+ 'grey91': '#E8E8E8',
+ 'grey92': '#EBEBEB',
+ 'grey93': '#EDEDED',
+ 'grey94': '#F0F0F0',
+ 'grey95': '#F2F2F2',
+ 'grey96': '#F5F5F5',
+ 'grey97': '#F7F7F7',
+ 'grey98': '#FAFAFA',
+ 'grey99': '#FCFCFC',
+ 'grey100': '#FFFFFF',
+ 'honeydew': '#F0FFF0',
+ 'honeydew1': '#F0FFF0',
+ 'honeydew2': '#E0EEE0',
+ 'honeydew3': '#C1CDC1',
+ 'honeydew4': '#838B83',
+ 'hot pink': '#FF69B4',
+ 'HotPink': '#FF69B4',
+ 'HotPink1': '#FF6EB4',
+ 'HotPink2': '#EE6AA7',
+ 'HotPink3': '#CD6090',
+ 'HotPink4': '#8B3A62',
+ 'indian red': '#CD5C5C',
+ 'IndianRed': '#CD5C5C',
+ 'IndianRed1': '#FF6A6A',
+ 'IndianRed2': '#EE6363',
+ 'IndianRed3': '#CD5555',
+ 'IndianRed4': '#8B3A3A',
+ 'ivory': '#FFFFF0',
+ 'ivory1': '#FFFFF0',
+ 'ivory2': '#EEEEE0',
+ 'ivory3': '#CDCDC1',
+ 'ivory4': '#8B8B83',
+ 'khaki': '#F0E68C',
+ 'khaki1': '#FFF68F',
+ 'khaki2': '#EEE685',
+ 'khaki3': '#CDC673',
+ 'khaki4': '#8B864E',
+ 'lavender': '#E6E6FA',
+ 'lavender blush': '#FFF0F5',
+ 'LavenderBlush': '#FFF0F5',
+ 'LavenderBlush1': '#FFF0F5',
+ 'LavenderBlush2': '#EEE0E5',
+ 'LavenderBlush3': '#CDC1C5',
+ 'LavenderBlush4': '#8B8386',
+ 'lawn green': '#7CFC00',
+ 'LawnGreen': '#7CFC00',
+ 'lemon chiffon': '#FFFACD',
+ 'LemonChiffon': '#FFFACD',
+ 'LemonChiffon1': '#FFFACD',
+ 'LemonChiffon2': '#EEE9BF',
+ 'LemonChiffon3': '#CDC9A5',
+ 'LemonChiffon4': '#8B8970',
+ 'light blue': '#ADD8E6',
+ 'light coral': '#F08080',
+ 'light cyan': '#E0FFFF',
+ 'light goldenrod': '#EEDD82',
+ 'light goldenrod yellow': '#FAFAD2',
+ 'light gray': '#D3D3D3',
+ 'light green': '#90EE90',
+ 'light grey': '#D3D3D3',
+ 'light pink': '#FFB6C1',
+ 'light salmon': '#FFA07A',
+ 'light sea green': '#20B2AA',
+ 'light sky blue': '#87CEFA',
+ 'light slate blue': '#8470FF',
+ 'light slate gray': '#778899',
+ 'light slate grey': '#778899',
+ 'light steel blue': '#B0C4DE',
+ 'light yellow': '#FFFFE0',
+ 'LightBlue': '#ADD8E6',
+ 'LightBlue1': '#BFEFFF',
+ 'LightBlue2': '#B2DFEE',
+ 'LightBlue3': '#9AC0CD',
+ 'LightBlue4': '#68838B',
+ 'LightCoral': '#F08080',
+ 'LightCyan': '#E0FFFF',
+ 'LightCyan1': '#E0FFFF',
+ 'LightCyan2': '#D1EEEE',
+ 'LightCyan3': '#B4CDCD',
+ 'LightCyan4': '#7A8B8B',
+ 'LightGoldenrod': '#EEDD82',
+ 'LightGoldenrod1': '#FFEC8B',
+ 'LightGoldenrod2': '#EEDC82',
+ 'LightGoldenrod3': '#CDBE70',
+ 'LightGoldenrod4': '#8B814C',
+ 'LightGoldenrodYellow': '#FAFAD2',
+ 'LightGray': '#D3D3D3',
+ 'LightGreen': '#90EE90',
+ 'LightGrey': '#D3D3D3',
+ 'LightPink': '#FFB6C1',
+ 'LightPink1': '#FFAEB9',
+ 'LightPink2': '#EEA2AD',
+ 'LightPink3': '#CD8C95',
+ 'LightPink4': '#8B5F65',
+ 'LightSalmon': '#FFA07A',
+ 'LightSalmon1': '#FFA07A',
+ 'LightSalmon2': '#EE9572',
+ 'LightSalmon3': '#CD8162',
+ 'LightSalmon4': '#8B5742',
+ 'LightSeaGreen': '#20B2AA',
+ 'LightSkyBlue': '#87CEFA',
+ 'LightSkyBlue1': '#B0E2FF',
+ 'LightSkyBlue2': '#A4D3EE',
+ 'LightSkyBlue3': '#8DB6CD',
+ 'LightSkyBlue4': '#607B8B',
+ 'LightSlateBlue': '#8470FF',
+ 'LightSlateGray': '#778899',
+ 'LightSlateGrey': '#778899',
+ 'LightSteelBlue': '#B0C4DE',
+ 'LightSteelBlue1': '#CAE1FF',
+ 'LightSteelBlue2': '#BCD2EE',
+ 'LightSteelBlue3': '#A2B5CD',
+ 'LightSteelBlue4': '#6E7B8B',
+ 'LightYellow': '#FFFFE0',
+ 'LightYellow1': '#FFFFE0',
+ 'LightYellow2': '#EEEED1',
+ 'LightYellow3': '#CDCDB4',
+ 'LightYellow4': '#8B8B7A',
+ 'lime green': '#32CD32',
+ 'LimeGreen': '#32CD32',
+ 'linen': '#FAF0E6',
+ 'magenta': '#FF00FF',
+ 'magenta1': '#FF00FF',
+ 'magenta2': '#EE00EE',
+ 'magenta3': '#CD00CD',
+ 'magenta4': '#8B008B',
+ 'maroon': '#B03060',
+ 'maroon1': '#FF34B3',
+ 'maroon2': '#EE30A7',
+ 'maroon3': '#CD2990',
+ 'maroon4': '#8B1C62',
+ 'medium aquamarine': '#66CDAA',
+ 'medium blue': '#0000CD',
+ 'medium orchid': '#BA55D3',
+ 'medium purple': '#9370DB',
+ 'medium sea green': '#3CB371',
+ 'medium slate blue': '#7B68EE',
+ 'medium spring green': '#00FA9A',
+ 'medium turquoise': '#48D1CC',
+ 'medium violet red': '#C71585',
+ 'MediumAquamarine': '#66CDAA',
+ 'MediumBlue': '#0000CD',
+ 'MediumOrchid': '#BA55D3',
+ 'MediumOrchid1': '#E066FF',
+ 'MediumOrchid2': '#D15FEE',
+ 'MediumOrchid3': '#B452CD',
+ 'MediumOrchid4': '#7A378B',
+ 'MediumPurple': '#9370DB',
+ 'MediumPurple1': '#AB82FF',
+ 'MediumPurple2': '#9F79EE',
+ 'MediumPurple3': '#8968CD',
+ 'MediumPurple4': '#5D478B',
+ 'MediumSeaGreen': '#3CB371',
+ 'MediumSlateBlue': '#7B68EE',
+ 'MediumSpringGreen': '#00FA9A',
+ 'MediumTurquoise': '#48D1CC',
+ 'MediumVioletRed': '#C71585',
+ 'midnight blue': '#191970',
+ 'MidnightBlue': '#191970',
+ 'mint cream': '#F5FFFA',
+ 'MintCream': '#F5FFFA',
+ 'misty rose': '#FFE4E1',
+ 'MistyRose': '#FFE4E1',
+ 'MistyRose1': '#FFE4E1',
+ 'MistyRose2': '#EED5D2',
+ 'MistyRose3': '#CDB7B5',
+ 'MistyRose4': '#8B7D7B',
+ 'moccasin': '#FFE4B5',
+ 'navajo white': '#FFDEAD',
+ 'NavajoWhite': '#FFDEAD',
+ 'NavajoWhite1': '#FFDEAD',
+ 'NavajoWhite2': '#EECFA1',
+ 'NavajoWhite3': '#CDB38B',
+ 'NavajoWhite4': '#8B795E',
+ 'navy': '#000080',
+ 'navy blue': '#000080',
+ 'NavyBlue': '#000080',
+ 'old lace': '#FDF5E6',
+ 'OldLace': '#FDF5E6',
+ 'olive drab': '#6B8E23',
+ 'OliveDrab': '#6B8E23',
+ 'OliveDrab1': '#C0FF3E',
+ 'OliveDrab2': '#B3EE3A',
+ 'OliveDrab3': '#9ACD32',
+ 'OliveDrab4': '#698B22',
+ 'orange': '#FFA500',
+ 'orange red': '#FF4500',
+ 'orange1': '#FFA500',
+ 'orange2': '#EE9A00',
+ 'orange3': '#CD8500',
+ 'orange4': '#8B5A00',
+ 'OrangeRed': '#FF4500',
+ 'OrangeRed1': '#FF4500',
+ 'OrangeRed2': '#EE4000',
+ 'OrangeRed3': '#CD3700',
+ 'OrangeRed4': '#8B2500',
+ 'orchid': '#DA70D6',
+ 'orchid1': '#FF83FA',
+ 'orchid2': '#EE7AE9',
+ 'orchid3': '#CD69C9',
+ 'orchid4': '#8B4789',
+ 'pale goldenrod': '#EEE8AA',
+ 'pale green': '#98FB98',
+ 'pale turquoise': '#AFEEEE',
+ 'pale violet red': '#DB7093',
+ 'PaleGoldenrod': '#EEE8AA',
+ 'PaleGreen': '#98FB98',
+ 'PaleGreen1': '#9AFF9A',
+ 'PaleGreen2': '#90EE90',
+ 'PaleGreen3': '#7CCD7C',
+ 'PaleGreen4': '#548B54',
+ 'PaleTurquoise': '#AFEEEE',
+ 'PaleTurquoise1': '#BBFFFF',
+ 'PaleTurquoise2': '#AEEEEE',
+ 'PaleTurquoise3': '#96CDCD',
+ 'PaleTurquoise4': '#668B8B',
+ 'PaleVioletRed': '#DB7093',
+ 'PaleVioletRed1': '#FF82AB',
+ 'PaleVioletRed2': '#EE799F',
+ 'PaleVioletRed3': '#CD687F',
+ 'PaleVioletRed4': '#8B475D',
+ 'papaya whip': '#FFEFD5',
+ 'PapayaWhip': '#FFEFD5',
+ 'peach puff': '#FFDAB9',
+ 'PeachPuff': '#FFDAB9',
+ 'PeachPuff1': '#FFDAB9',
+ 'PeachPuff2': '#EECBAD',
+ 'PeachPuff3': '#CDAF95',
+ 'PeachPuff4': '#8B7765',
+ 'peru': '#CD853F',
+ 'pink': '#FFC0CB',
+ 'pink1': '#FFB5C5',
+ 'pink2': '#EEA9B8',
+ 'pink3': '#CD919E',
+ 'pink4': '#8B636C',
+ 'plum': '#DDA0DD',
+ 'plum1': '#FFBBFF',
+ 'plum2': '#EEAEEE',
+ 'plum3': '#CD96CD',
+ 'plum4': '#8B668B',
+ 'powder blue': '#B0E0E6',
+ 'PowderBlue': '#B0E0E6',
+ 'purple': '#A020F0',
+ 'purple1': '#9B30FF',
+ 'purple2': '#912CEE',
+ 'purple3': '#7D26CD',
+ 'purple4': '#551A8B',
+ 'red': '#FF0000',
+ 'red1': '#FF0000',
+ 'red2': '#EE0000',
+ 'red3': '#CD0000',
+ 'red4': '#8B0000',
+ 'rosy brown': '#BC8F8F',
+ 'RosyBrown': '#BC8F8F',
+ 'RosyBrown1': '#FFC1C1',
+ 'RosyBrown2': '#EEB4B4',
+ 'RosyBrown3': '#CD9B9B',
+ 'RosyBrown4': '#8B6969',
+ 'royal blue': '#4169E1',
+ 'RoyalBlue': '#4169E1',
+ 'RoyalBlue1': '#4876FF',
+ 'RoyalBlue2': '#436EEE',
+ 'RoyalBlue3': '#3A5FCD',
+ 'RoyalBlue4': '#27408B',
+ 'saddle brown': '#8B4513',
+ 'SaddleBrown': '#8B4513',
+ 'salmon': '#FA8072',
+ 'salmon1': '#FF8C69',
+ 'salmon2': '#EE8262',
+ 'salmon3': '#CD7054',
+ 'salmon4': '#8B4C39',
+ 'sandy brown': '#F4A460',
+ 'SandyBrown': '#F4A460',
+ 'sea green': '#2E8B57',
+ 'SeaGreen': '#2E8B57',
+ 'SeaGreen1': '#54FF9F',
+ 'SeaGreen2': '#4EEE94',
+ 'SeaGreen3': '#43CD80',
+ 'SeaGreen4': '#2E8B57',
+ 'seashell': '#FFF5EE',
+ 'seashell1': '#FFF5EE',
+ 'seashell2': '#EEE5DE',
+ 'seashell3': '#CDC5BF',
+ 'seashell4': '#8B8682',
+ 'sienna': '#A0522D',
+ 'sienna1': '#FF8247',
+ 'sienna2': '#EE7942',
+ 'sienna3': '#CD6839',
+ 'sienna4': '#8B4726',
+ 'sky blue': '#87CEEB',
+ 'SkyBlue': '#87CEEB',
+ 'SkyBlue1': '#87CEFF',
+ 'SkyBlue2': '#7EC0EE',
+ 'SkyBlue3': '#6CA6CD',
+ 'SkyBlue4': '#4A708B',
+ 'slate blue': '#6A5ACD',
+ 'slate gray': '#708090',
+ 'slate grey': '#708090',
+ 'SlateBlue': '#6A5ACD',
+ 'SlateBlue1': '#836FFF',
+ 'SlateBlue2': '#7A67EE',
+ 'SlateBlue3': '#6959CD',
+ 'SlateBlue4': '#473C8B',
+ 'SlateGray': '#708090',
+ 'SlateGray1': '#C6E2FF',
+ 'SlateGray2': '#B9D3EE',
+ 'SlateGray3': '#9FB6CD',
+ 'SlateGray4': '#6C7B8B',
+ 'SlateGrey': '#708090',
+ 'snow': '#FFFAFA',
+ 'snow1': '#FFFAFA',
+ 'snow2': '#EEE9E9',
+ 'snow3': '#CDC9C9',
+ 'snow4': '#8B8989',
+ 'spring green': '#00FF7F',
+ 'SpringGreen': '#00FF7F',
+ 'SpringGreen1': '#00FF7F',
+ 'SpringGreen2': '#00EE76',
+ 'SpringGreen3': '#00CD66',
+ 'SpringGreen4': '#008B45',
+ 'steel blue': '#4682B4',
+ 'SteelBlue': '#4682B4',
+ 'SteelBlue1': '#63B8FF',
+ 'SteelBlue2': '#5CACEE',
+ 'SteelBlue3': '#4F94CD',
+ 'SteelBlue4': '#36648B',
+ 'tan': '#D2B48C',
+ 'tan1': '#FFA54F',
+ 'tan2': '#EE9A49',
+ 'tan3': '#CD853F',
+ 'tan4': '#8B5A2B',
+ 'thistle': '#D8BFD8',
+ 'thistle1': '#FFE1FF',
+ 'thistle2': '#EED2EE',
+ 'thistle3': '#CDB5CD',
+ 'thistle4': '#8B7B8B',
+ 'tomato': '#FF6347',
+ 'tomato1': '#FF6347',
+ 'tomato2': '#EE5C42',
+ 'tomato3': '#CD4F39',
+ 'tomato4': '#8B3626',
+ 'turquoise': '#40E0D0',
+ 'turquoise1': '#00F5FF',
+ 'turquoise2': '#00E5EE',
+ 'turquoise3': '#00C5CD',
+ 'turquoise4': '#00868B',
+ 'violet': '#EE82EE',
+ 'violet red': '#D02090',
+ 'VioletRed': '#D02090',
+ 'VioletRed1': '#FF3E96',
+ 'VioletRed2': '#EE3A8C',
+ 'VioletRed3': '#CD3278',
+ 'VioletRed4': '#8B2252',
+ 'wheat': '#F5DEB3',
+ 'wheat1': '#FFE7BA',
+ 'wheat2': '#EED8AE',
+ 'wheat3': '#CDBA96',
+ 'wheat4': '#8B7E66',
+ 'white': '#FFFFFF',
+ 'white smoke': '#F5F5F5',
+ 'WhiteSmoke': '#F5F5F5',
+ 'yellow': '#FFFF00',
+ 'yellow green': '#9ACD32',
+ 'yellow1': '#FFFF00',
+ 'yellow2': '#EEEE00',
+ 'yellow3': '#CDCD00',
+ 'yellow4': '#8B8B00',
+ 'YellowGreen': '#9ACD32',
+}
+
+
+sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=1, tooltip_time=100)
+
+#start layout with the tittle
+layout = [[sg.Text('Hover mouse to see RGB value, click for white & black text',
+ text_color='blue',
+ font='Any 15',
+ relief=sg.RELIEF_SUNKEN,
+ justification='center',
+ size=(100,1),
+ background_color='light green',
+ pad=(0,(0,20))),]]
+
+# -- Create primary color viewer window --
+color_list = [key for key in color_map]
+for rows in range(40):
+
+ row = []
+ for i in range(12):
+ try:
+ color = color_list[rows+40*i]
+ row.append(sg.Button(color, button_color=('black', color), key=color, tooltip=color_map[color]))
+ except:
+ pass
+ layout.append(row)
+
+
+window = sg.Window('Color Viewer', grab_anywhere=False, font=('any 9')).Layout(layout)
+
+# -- Event loop --
+while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ # -- Create a secondary window that shows white and black text on chosen color
+ layout2 =[[sg.DummyButton(event, button_color=('white', event), tooltip=color_map[event]), sg.DummyButton(event, button_color=('black', event), tooltip=color_map[event])] ]
+ sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read(timeout=0)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Color_Names_Smaller_List.py b/DemoPrograms old/Demo_Color_Names_Smaller_List.py
new file mode 100644
index 000000000..e6911dcd8
--- /dev/null
+++ b/DemoPrograms old/Demo_Color_Names_Smaller_List.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+ Color names courtesy of Big Daddy's Wiki-Python
+ http://www.wikipython.com/tkinter-ttk-tix/summary-information/colors/
+
+ Shows a big chart of colors... give it a few seconds to create it
+ Once large window is shown, you can click on any color and another window will popup
+ showing both white and black text on that color
+"""
+
+
+
+COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace',
+ 'linen', 'antique white', 'papaya whip', 'blanched almond', 'bisque', 'peach puff',
+ 'navajo white', 'lemon chiffon', 'mint cream', 'azure', 'alice blue', 'lavender',
+ 'lavender blush', 'misty rose', 'dark slate gray', 'dim gray', 'slate gray',
+ 'light slate gray', 'gray', 'light gray', 'midnight blue', 'navy', 'cornflower blue', 'dark slate blue',
+ 'slate blue', 'medium slate blue', 'light slate blue', 'medium blue', 'royal blue', 'blue',
+ 'dodger blue', 'deep sky blue', 'sky blue', 'light sky blue', 'steel blue', 'light steel blue',
+ 'light blue', 'powder blue', 'pale turquoise', 'dark turquoise', 'medium turquoise', 'turquoise',
+ 'cyan', 'light cyan', 'cadet blue', 'medium aquamarine', 'aquamarine', 'dark green', 'dark olive green',
+ 'dark sea green', 'sea green', 'medium sea green', 'light sea green', 'pale green', 'spring green',
+ 'lawn green', 'medium spring green', 'green yellow', 'lime green', 'yellow green',
+ 'forest green', 'olive drab', 'dark khaki', 'khaki', 'pale goldenrod', 'light goldenrod yellow',
+ 'light yellow', 'yellow', 'gold', 'light goldenrod', 'goldenrod', 'dark goldenrod', 'rosy brown',
+ 'indian red', 'saddle brown', 'sandy brown',
+ 'dark salmon', 'salmon', 'light salmon', 'orange', 'dark orange',
+ 'coral', 'light coral', 'tomato', 'orange red', 'red', 'hot pink', 'deep pink', 'pink', 'light pink',
+ 'pale violet red', 'maroon', 'medium violet red', 'violet red',
+ 'medium orchid', 'dark orchid', 'dark violet', 'blue violet', 'purple', 'medium purple',
+ 'thistle', 'snow2', 'snow3',
+ 'snow4', 'seashell2', 'seashell3', 'seashell4', 'AntiqueWhite1', 'AntiqueWhite2',
+ 'AntiqueWhite3', 'AntiqueWhite4', 'bisque2', 'bisque3', 'bisque4', 'PeachPuff2',
+ 'PeachPuff3', 'PeachPuff4', 'NavajoWhite2', 'NavajoWhite3', 'NavajoWhite4',
+ 'LemonChiffon2', 'LemonChiffon3', 'LemonChiffon4', 'cornsilk2', 'cornsilk3',
+ 'cornsilk4', 'ivory2', 'ivory3', 'ivory4', 'honeydew2', 'honeydew3', 'honeydew4',
+ 'LavenderBlush2', 'LavenderBlush3', 'LavenderBlush4', 'MistyRose2', 'MistyRose3',
+ 'MistyRose4', 'azure2', 'azure3', 'azure4', 'SlateBlue1', 'SlateBlue2', 'SlateBlue3',
+ 'SlateBlue4', 'RoyalBlue1', 'RoyalBlue2', 'RoyalBlue3', 'RoyalBlue4', 'blue2', 'blue4',
+ 'DodgerBlue2', 'DodgerBlue3', 'DodgerBlue4', 'SteelBlue1', 'SteelBlue2',
+ 'SteelBlue3', 'SteelBlue4', 'DeepSkyBlue2', 'DeepSkyBlue3', 'DeepSkyBlue4',
+ 'SkyBlue1', 'SkyBlue2', 'SkyBlue3', 'SkyBlue4', 'LightSkyBlue1', 'LightSkyBlue2',
+ 'LightSkyBlue3', 'LightSkyBlue4', 'Slategray1', 'Slategray2', 'Slategray3',
+ 'Slategray4', 'LightSteelBlue1', 'LightSteelBlue2', 'LightSteelBlue3',
+ 'LightSteelBlue4', 'LightBlue1', 'LightBlue2', 'LightBlue3', 'LightBlue4',
+ 'LightCyan2', 'LightCyan3', 'LightCyan4', 'PaleTurquoise1', 'PaleTurquoise2',
+ 'PaleTurquoise3', 'PaleTurquoise4', 'CadetBlue1', 'CadetBlue2', 'CadetBlue3',
+ 'CadetBlue4', 'turquoise1', 'turquoise2', 'turquoise3', 'turquoise4', 'cyan2', 'cyan3',
+ 'cyan4', 'DarkSlategray1', 'DarkSlategray2', 'DarkSlategray3', 'DarkSlategray4',
+ 'aquamarine2', 'aquamarine4', 'DarkSeaGreen1', 'DarkSeaGreen2', 'DarkSeaGreen3',
+ 'DarkSeaGreen4', 'SeaGreen1', 'SeaGreen2', 'SeaGreen3', 'PaleGreen1', 'PaleGreen2',
+ 'PaleGreen3', 'PaleGreen4', 'SpringGreen2', 'SpringGreen3', 'SpringGreen4',
+ 'green2', 'green3', 'green4', 'chartreuse2', 'chartreuse3', 'chartreuse4',
+ 'OliveDrab1', 'OliveDrab2', 'OliveDrab4', 'DarkOliveGreen1', 'DarkOliveGreen2',
+ 'DarkOliveGreen3', 'DarkOliveGreen4', 'khaki1', 'khaki2', 'khaki3', 'khaki4',
+ 'LightGoldenrod1', 'LightGoldenrod2', 'LightGoldenrod3', 'LightGoldenrod4',
+ 'LightYellow2', 'LightYellow3', 'LightYellow4', 'yellow2', 'yellow3', 'yellow4',
+ 'gold2', 'gold3', 'gold4', 'goldenrod1', 'goldenrod2', 'goldenrod3', 'goldenrod4',
+ 'DarkGoldenrod1', 'DarkGoldenrod2', 'DarkGoldenrod3', 'DarkGoldenrod4',
+ 'RosyBrown1', 'RosyBrown2', 'RosyBrown3', 'RosyBrown4', 'IndianRed1', 'IndianRed2',
+ 'IndianRed3', 'IndianRed4', 'sienna1', 'sienna2', 'sienna3', 'sienna4', 'burlywood1',
+ 'burlywood2', 'burlywood3', 'burlywood4', 'wheat1', 'wheat2', 'wheat3', 'wheat4', 'tan1',
+ 'tan2', 'tan4', 'chocolate1', 'chocolate2', 'chocolate3', 'firebrick1', 'firebrick2',
+ 'firebrick3', 'firebrick4', 'brown1', 'brown2', 'brown3', 'brown4', 'salmon1', 'salmon2',
+ 'salmon3', 'salmon4', 'LightSalmon2', 'LightSalmon3', 'LightSalmon4', 'orange2',
+ 'orange3', 'orange4', 'DarkOrange1', 'DarkOrange2', 'DarkOrange3', 'DarkOrange4',
+ 'coral1', 'coral2', 'coral3', 'coral4', 'tomato2', 'tomato3', 'tomato4', 'OrangeRed2',
+ 'OrangeRed3', 'OrangeRed4', 'red2', 'red3', 'red4', 'DeepPink2', 'DeepPink3', 'DeepPink4',
+ 'HotPink1', 'HotPink2', 'HotPink3', 'HotPink4', 'pink1', 'pink2', 'pink3', 'pink4',
+ 'LightPink1', 'LightPink2', 'LightPink3', 'LightPink4', 'PaleVioletRed1',
+ 'PaleVioletRed2', 'PaleVioletRed3', 'PaleVioletRed4', 'maroon1', 'maroon2',
+ 'maroon3', 'maroon4', 'VioletRed1', 'VioletRed2', 'VioletRed3', 'VioletRed4',
+ 'magenta2', 'magenta3', 'magenta4', 'orchid1', 'orchid2', 'orchid3', 'orchid4', 'plum1',
+ 'plum2', 'plum3', 'plum4', 'MediumOrchid1', 'MediumOrchid2', 'MediumOrchid3',
+ 'MediumOrchid4', 'DarkOrchid1', 'DarkOrchid2', 'DarkOrchid3', 'DarkOrchid4',
+ 'purple1', 'purple2', 'purple3', 'purple4', 'MediumPurple1', 'MediumPurple2',
+ 'MediumPurple3', 'MediumPurple4', 'thistle1', 'thistle2', 'thistle3', 'thistle4',
+ 'grey1', 'grey2', 'grey3', 'grey4', 'grey5', 'grey6', 'grey7', 'grey8', 'grey9', 'grey10',
+ 'grey11', 'grey12', 'grey13', 'grey14', 'grey15', 'grey16', 'grey17', 'grey18', 'grey19',
+ 'grey20', 'grey21', 'grey22', 'grey23', 'grey24', 'grey25', 'grey26', 'grey27', 'grey28',
+ 'grey29', 'grey30', 'grey31', 'grey32', 'grey33', 'grey34', 'grey35', 'grey36', 'grey37',
+ 'grey38', 'grey39', 'grey40', 'grey42', 'grey43', 'grey44', 'grey45', 'grey46', 'grey47',
+ 'grey48', 'grey49', 'grey50', 'grey51', 'grey52', 'grey53', 'grey54', 'grey55', 'grey56',
+ 'grey57', 'grey58', 'grey59', 'grey60', 'grey61', 'grey62', 'grey63', 'grey64', 'grey65',
+ 'grey66', 'grey67', 'grey68', 'grey69', 'grey70', 'grey71', 'grey72', 'grey73', 'grey74',
+ 'grey75', 'grey76', 'grey77', 'grey78', 'grey79', 'grey80', 'grey81', 'grey82', 'grey83',
+ 'grey84', 'grey85', 'grey86', 'grey87', 'grey88', 'grey89', 'grey90', 'grey91', 'grey92',
+ 'grey93', 'grey94', 'grey95', 'grey97', 'grey98', 'grey99']
+
+
+
+
+sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=0)
+
+layout = [[sg.Text('Click on a color square to see both white and black text on that color', text_color='blue', font='Any 15')]]
+row = []
+layout = []
+# -- Create primary color viewer window --
+for rows in range(40):
+
+ row = []
+ for i in range(12):
+ try:
+ color = COLORS[rows+40*i]
+ row.append(sg.Button(color, button_color=('black', color), key=color))
+ except:
+ pass
+ layout.append(row)
+
+
+# for i, color in enumerate(COLORS):
+# row.append(sg.Button(color, button_color=('black', color), key=color))
+# if (i+1) % 12 == 0:
+# layout.append(row)
+# row = []
+
+window = sg.Window('Color Viewer', grab_anywhere=False, font=('any 9')).Layout(layout)
+
+# -- Event loop --
+while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ # -- Create a secondary window that shows white and black text on chosen color
+ layout2 =[[sg.DummyButton(event, button_color=('white', event)), sg.DummyButton(event, button_color=('black', event))]]
+ sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read(timeout=0)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Column_And_Frames.py b/DemoPrograms old/Demo_Column_And_Frames.py
new file mode 100644
index 000000000..2c6f64ea8
--- /dev/null
+++ b/DemoPrograms old/Demo_Column_And_Frames.py
@@ -0,0 +1,48 @@
+import PySimpleGUI as sg
+# this one long import has the effect of making the code more compact as there is no 'sg.' prefix required for Elements
+from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu, Canvas, Column, Col, Combo, Frame, Graph, Image, InputText, Input, In, Listbox, LBox, Menu, Multiline, ML, MLine, OptionMenu, Output, Pane, ProgressBar, Radio, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, TreeData, VerticalSeparator, Window, Sizer
+
+"""
+ Demo Columns and Frames
+ Demonstrates using mixture of Column and Frame elements to create a nice window layout.
+ A couple of the concepts shown here include:
+ * Using Columns and Frames with specific sizes on them
+ * Importing all required classes so that "sg." is not required on any objects. This makes the code more compact and readable
+
+ There are 3 columns. Two are side by side at the top and the third is along the bottom
+"""
+
+sg.change_look_and_feel('GreenTan')
+
+col2 = Column([[Frame('Accounts:', [[Column([[Listbox(['Account '+str(i) for i in range(1,16)], key='-ACCT-LIST-', size=(15,20)),]],size=(150,400))]])]], pad=(0,0))
+
+col1 = Column([
+ # Categories frame
+ [Frame('Categories:', [[Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10, 1)),
+ Radio('Software', 'radio1',key='-SOFTWARE-', size=(10, 1))]],)],
+ # Information frame
+ [Frame('Information:', [[Column([[Text('Account:')],
+ [Input(key='-ACCOUNT-IN-', size=(19, 1))],
+ [Text('User Id:')],
+ [Input(key='-USERID-IN-', size=(19, 1)), Button('Copy', key='-USERID-')],
+ [Text('Password:')],
+ [Input(key='-PW-IN-', size=(19, 1)), Button('Copy', key='-PASS-')],
+ [Text('Location:')],
+ [Input(key='-LOC-IN-', size=(19, 1)), Button('Copy', key='-LOC')],
+ [Text('Notes:')],
+ [Multiline(key='-NOTES-', size=(25, 5))],
+ ], size=(235,350),pad=(0,0))]])],], pad=(0,0))
+
+col3 = Column([[Frame('Actions:', [[Column([[Button('Save'), Button('Clear'), Button('Delete'),]], size=(450,45), pad=(0,0))]])]], pad=(0,0))
+
+layout = [ [col1, col2],
+ [col3]]
+
+window = Window('Passwords', layout)
+
+while True:
+ event, values = window.read()
+ print(event, values)
+ if event is None:
+ break
+window.close()
diff --git a/DemoPrograms old/Demo_Columns.py b/DemoPrograms old/Demo_Columns.py
new file mode 100644
index 000000000..481751cb0
--- /dev/null
+++ b/DemoPrograms old/Demo_Columns.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+sg.ChangeLookAndFeel('BlueMono')
+
+# Column layout
+col = [[sg.Text('col Row 1', text_color='white', background_color='blue')],
+ [sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')],
+ [sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]]
+# Window layout
+layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'),
+ select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20, 3)),
+ sg.Column(col, background_color='blue')],
+ [sg.Input('Last input')],
+ [sg.OK()]]
+
+# Display the window and get values
+event, values = sg.Window('Compact 1-line form with column').Layout(layout).Read()
+
+sg.Popup(event, values, line_width=200)
+
diff --git a/DemoPrograms old/Demo_Compact_Layouts_Element_Renaming.py b/DemoPrograms old/Demo_Compact_Layouts_Element_Renaming.py
new file mode 100644
index 000000000..589375a3d
--- /dev/null
+++ b/DemoPrograms old/Demo_Compact_Layouts_Element_Renaming.py
@@ -0,0 +1,47 @@
+import PySimpleGUI as sg
+# Import the elements individually to save space
+from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu,BMenu, Canvas, Column, Col, Combo, DropDown, Drop, DD, Frame, Graph, Image, InputText, Input, In, I, Listbox, LBox, LB, Menu, Multiline, ML, MLine, OptionMenu, Output, Pane, ProgressBar, Prog, PBar, Radio, R, Rad, Sizer, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, TreeData, VerticalSeparator, Window, Print
+
+
+"""
+ Demo - Compact Layouts and Element Renaming
+
+ Some layouts contain many many elements such that space becomes a premium. For experienced PySimpleGUI
+ programmers, there is little additional knowledge to be gained by writing
+ sg.Text('My text')
+ rather than using one of the shortcuts such as
+ sg.T('My text')
+ However, even with shortcut usage, you continue to have the package prefix of
+ sg.
+ That's 3 characters per element that are added to your layout!
+ The very long import statement st the top can be copied into your code to give you the ability to write
+ T('My text')
+
+ If you don't want to use that very-long import or perhaps want to use your own shortcut names, you can easily
+ create your shortcut by simple assignment:
+ T = sg.Text
+ This enables you to use T just as if you imported the Class T from PySimpleGUI. You could develop your own
+ template that you copy and paste at the top of all of your PySimpleGUI programs. Or perhaps perform an import
+ of those assignments from a .py file you create.
+
+ Note that you may lose docstrings in PyCharm using these shortcuts. You can still see the parameters when pressing
+ Control+P, but the Control+Q doesn't bring up the full list of parms and their descriptions. Looking for a fix
+ for this.
+
+ PLEASE OH PLEASE OH PLEASE NEVER EVER EVER do this:
+ from PySimpleGUI import *
+ There is a bot scanning GitHub for this statement. If found in your code, a squad of assassins will be dispatched
+ from the PySimpleGUI headquarters and you will be hunted down and forced to change your code.
+"""
+
+# A user created shortcut....
+# Suppose this user's layout contains many Multiline Elements. It could be advantageous to have a single letter
+# shortcut version for Multiline
+M = sg.Multiline
+
+# This layout uses the user defined "M" element as well as the PySimpleGUI Button shortcut, B.
+layout = [[M(size=(30,3))],
+ [B('OK')]]
+
+event, values = Window('Shortcuts', layout).read()
+sg.popup_scrolled(event, values)
diff --git a/DemoPrograms old/Demo_Compare_Files.py b/DemoPrograms old/Demo_Compare_Files.py
new file mode 100644
index 000000000..77ab262db
--- /dev/null
+++ b/DemoPrograms old/Demo_Compare_Files.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+# sg.SetOptions(button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+def GetFilesToCompare():
+ form_rows = [[sg.Text('Enter 2 files to comare')],
+ [sg.Text('File 1', size=(15, 1)), sg.InputText(key='file1'), sg.FileBrowse()],
+ [sg.Text('File 2', size=(15, 1)), sg.InputText(key='file2'), sg.FileBrowse(target='file2')],
+ [sg.Submit(), sg.Cancel()]]
+
+ window = sg.Window('File Compare')
+ event, values = window.Layout(form_rows).Read()
+ return event, values
+
+def main():
+ button, values = GetFilesToCompare()
+ f1 = values['file1']
+ f2 = values['file2']
+
+ if any((button != 'Submit', f1 =='', f2 == '')):
+ sg.PopupError('Operation cancelled')
+ sys.exit(69)
+
+ # --- This portion of the code is not GUI related ---
+ with open(f1, 'rb') as file1:
+ with open(f2, 'rb') as file2:
+ a = file1.read()
+ b = file2.read()
+
+ for i, x in enumerate(a):
+ if x != b[i]:
+ sg.Popup('Compare results for files', f1, f2, '**** Mismatch at offset {} ****'.format(i))
+ break
+ else:
+ if len(a) == len(b):
+ sg.Popup('**** The files are IDENTICAL ****')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Conways_Game_of_Life.py b/DemoPrograms old/Demo_Conways_Game_of_Life.py
new file mode 100644
index 000000000..ece57f651
--- /dev/null
+++ b/DemoPrograms old/Demo_Conways_Game_of_Life.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+
+# John Conway's "Game of Life" using a GUI.
+# Copyright (C) 2018 PySimpleGUI.org
+# GUI provided by PySimpleGUI.
+# Core game engine provied by Christian Jacobs
+
+# An implementation of Conway's Game of Life in Python.
+
+# Copyright (C) 2013 Christian Jacobs.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import numpy
+import PySimpleGUI as sg # Take your pick! Tkinter
+# import PySimpleGUIWeb as sg # Or the Web! (Remi!)
+
+BOX_SIZE = 15
+
+class GameOfLife:
+
+ def __init__(self, N=20, T=200):
+ """ Set up Conway's Game of Life. """
+ # Here we create two grids to hold the old and new configurations.
+ # This assumes an N*N grid of points.
+ # Each point is either alive or dead, represented by integer values of 1 and 0, respectively.
+ self.N = N
+ self.old_grid = numpy.zeros(N * N, dtype='i').reshape(N, N)
+ self.new_grid = numpy.zeros(N * N, dtype='i').reshape(N, N)
+ self.T = T # The maximum number of generations
+
+ # Set up a random initial configuration for the grid.
+ for i in range(0, self.N):
+ for j in range(0, self.N):
+ self.old_grid[i][j] = 0
+ self.init_graphics()
+ self.manual_board_setup()
+
+ def live_neighbours(self, i, j):
+ """ Count the number of live neighbours around point (i, j). """
+ s = 0 # The total number of live neighbours.
+ # Loop over all the neighbours.
+ for x in [i - 1, i, i + 1]:
+ for y in [j - 1, j, j + 1]:
+ if (x == i and y == j):
+ continue # Skip the current point itself - we only want to count the neighbours!
+ if (x != self.N and y != self.N):
+ s += self.old_grid[x][y]
+ # The remaining branches handle the case where the neighbour is off the end of the grid.
+ # In this case, we loop back round such that the grid becomes a "toroidal array".
+ elif (x == self.N and y != self.N):
+ s += self.old_grid[0][y]
+ elif (x != self.N and y == self.N):
+ s += self.old_grid[x][0]
+ else:
+ s += self.old_grid[0][0]
+ return s
+
+ def play(self):
+ """ Play Conway's Game of Life. """
+
+ # Write the initial configuration to file.
+
+ self.t = 1 # Current time level
+ while self.t <= self.T: # Evolve!
+ # print( "At time level %d" % t)
+
+ # Loop over each cell of the grid and apply Conway's rules.
+ for i in range(self.N):
+ for j in range(self.N):
+ live = self.live_neighbours(i, j)
+ if (self.old_grid[i][j] == 1 and live < 2):
+ self.new_grid[i][j] = 0 # Dead from starvation.
+ elif (self.old_grid[i][j] == 1 and (live == 2 or live == 3)):
+ self.new_grid[i][j] = 1 # Continue living.
+ elif (self.old_grid[i][j] == 1 and live > 3):
+ self.new_grid[i][j] = 0 # Dead from overcrowding.
+ elif (self.old_grid[i][j] == 0 and live == 3):
+ self.new_grid[i][j] = 1 # Alive from reproduction.
+
+ # Output the new configuration.
+
+ # The new configuration becomes the old configuration for the next generation.
+ self.old_grid = self.new_grid.copy()
+ self.draw_board()
+ # Move on to the next time level
+ self.t += 1
+
+ def init_graphics(self):
+ self.graph = sg.Graph((600, 600), (0, 0), (450, 450), key='_GRAPH_', change_submits=True, drag_submits=False, background_color='lightblue')
+ layout = [
+ [sg.Text('Game of Life ', font='ANY 15'), sg.Text('', key='_OUTPUT_', size=(30,1), font='ANY 15')],
+ [self.graph],
+ [sg.Button('Go!', key='_DONE_'),
+ sg.Text(' Delay (ms)') , sg.Slider([0,800], orientation='h', key='_SLIDER_', enable_events=True, size=(15,15)), sg.T('', size=(3,1), key='_S1_OUT_'),
+ sg.Text(' Num Generations'), sg.Slider([0, 20000],default_value=4000, orientation='h',size=(15,15),enable_events=True, key='_SLIDER2_'), sg.T('', size=(3,1), key='_S2_OUT_')]
+ ]
+
+ self.window = sg.Window('Window Title', ).Layout(layout).Finalize()
+ event, values = self.window.Read(timeout=0)
+ self.delay = values['_SLIDER_']
+ self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
+ self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
+
+
+ def draw_board(self):
+ BOX_SIZE = 15
+ self.graph.Erase()
+ for i in range(self.N):
+ for j in range(self.N):
+ if self.old_grid[i][j]:
+ self.graph.DrawRectangle((i * BOX_SIZE, j * BOX_SIZE),
+ (i * BOX_SIZE + BOX_SIZE, j * (BOX_SIZE) + BOX_SIZE),
+ line_color='black', fill_color='yellow')
+ event, values = self.window.Read(timeout=self.delay)
+ if event in (None, '_DONE_'):
+ exit()
+ self.delay = values['_SLIDER_']
+ self.T = int(values['_SLIDER2_'])
+ self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
+ self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
+ self.window.Element('_OUTPUT_').Update('Generation {}'.format(self.t))
+
+
+ def manual_board_setup(self):
+ ids = []
+ for i in range(self.N):
+ ids.append([])
+ for j in range(self.N):
+ ids[i].append(0)
+ while True: # Event Loop
+ event, values = self.window.Read()
+ if event is None or event == '_DONE_':
+ break
+ self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
+ self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
+ mouse = values['_GRAPH_']
+
+ if event == '_GRAPH_':
+ if mouse == (None, None):
+ continue
+ box_x = mouse[0] // BOX_SIZE
+ box_y = mouse[1] // BOX_SIZE
+ if self.old_grid[box_x][box_y] == 1:
+ id = ids[box_x][box_y]
+ self.graph.DeleteFigure(id)
+ self.old_grid[box_x][box_y] = 0
+ else:
+ id = self.graph.DrawRectangle((box_x * BOX_SIZE, box_y * BOX_SIZE),
+ (box_x * BOX_SIZE + BOX_SIZE, box_y * (BOX_SIZE) + BOX_SIZE),
+ line_color='black', fill_color='yellow')
+ ids[box_x][box_y] = id
+ self.old_grid[box_x][box_y] = 1
+ self.window.Element('_DONE_').Update(text='Exit')
+
+if (__name__ == "__main__"):
+ game = GameOfLife(N=35, T=200)
+ game.play()
+ game.window.Close()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Crossword_Puzzle.py b/DemoPrograms old/Demo_Crossword_Puzzle.py
new file mode 100644
index 000000000..62dd7b4e1
--- /dev/null
+++ b/DemoPrograms old/Demo_Crossword_Puzzle.py
@@ -0,0 +1,54 @@
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+ # import PySimpleGUIWeb as sg # take your pick of ports. Runs on both
+else:
+ import PySimpleGUI27 as sg
+import random
+import string
+
+"""
+ Demo application to show how to draw rectangles and letters on a Graph Element
+ This demo mocks up a crossword puzzle board
+ It will place a letter where you click on the puzzle
+"""
+
+
+BOX_SIZE = 25
+
+layout = [
+ [sg.Text('Crossword Puzzle Using PySimpleGUI'), sg.Text('', key='_OUTPUT_')],
+ [sg.Graph((800,800), (0,450), (450,0), key='_GRAPH_', change_submits=True, drag_submits=False)],
+ [sg.Button('Show'), sg.Button('Exit')]
+ ]
+
+window = sg.Window('Window Title', ).Layout(layout).Finalize()
+
+g = window.FindElement('_GRAPH_')
+
+for row in range(16):
+ for col in range(16):
+ if random.randint(0,100) > 10:
+ g.DrawRectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black')
+ else:
+ g.DrawRectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black', fill_color='black')
+
+ g.DrawText('{}'.format(row * 6 + col + 1), (col * BOX_SIZE + 10, row * BOX_SIZE + 8))
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event is None or event == 'Exit':
+ break
+ mouse = values['_GRAPH_']
+
+ if event == '_GRAPH_':
+ if mouse == (None, None):
+ continue
+ box_x = mouse[0]//BOX_SIZE
+ box_y = mouse[1]//BOX_SIZE
+ letter_location = (box_x * BOX_SIZE + 18, box_y * BOX_SIZE + 17)
+ print(box_x, box_y)
+ g.DrawText('{}'.format(random.choice(string.ascii_uppercase)), letter_location, font='Courier 25')
+
+window.Close()
diff --git a/DemoPrograms old/Demo_DOC_Viewer_PIL.py b/DemoPrograms old/Demo_DOC_Viewer_PIL.py
new file mode 100644
index 000000000..50c6f0c8a
--- /dev/null
+++ b/DemoPrograms old/Demo_DOC_Viewer_PIL.py
@@ -0,0 +1,242 @@
+"""
+@created: 2018-08-19 18:00:00
+@author: (c) 2018 Jorj X. McKie
+Display a PyMuPDF Document using Tkinter
+-------------------------------------------------------------------------------
+Dependencies:
+-------------
+PyMuPDF, PySimpleGUI (requires Python 3), Tkinter, PIL
+License:
+--------
+GNU GPL V3+
+Description
+------------
+Get filename and start displaying page 1. Please note that all file types
+of MuPDF are supported (including EPUB e-books and HTML files for example).
+Pages can be directly jumped to, or buttons can be used for paging.
+
+This version contains enhancements:
+* Use of PIL improves response times by a factor 3 or more.
+* Zooming is now flexible: only one button serves as a toggle. Arrow keys can
+ be used for moving the window when zooming.
+
+We also interpret keyboard events (PageDown / PageUp) and mouse wheel actions
+to support paging as if a button was clicked. Similarly, we do not include
+a 'Quit' button. Instead, the ESCAPE key can be used, or cancelling the window.
+To improve paging performance, we are not directly creating pixmaps from
+pages, but instead from the fitz.DisplayList of the page. A display list
+will be stored in a list and looked up by page number. This way, zooming
+pixmaps and page re-visits will re-use a once-created display list.
+
+"""
+import sys
+import fitz
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import tkinter as tk
+from PIL import Image, ImageTk
+import time
+
+if len(sys.argv) == 1:
+ fname = sg.PopupGetFile('Document Browser', 'Document file to open', no_window=True,
+ file_types = (
+ ("PDF Files", "*.pdf"),
+ ("XPS Files", "*.*xps"),
+ ("Epub Files", "*.epub"),
+ ("Fiction Books", "*.fb2"),
+ ("Comic Books", "*.cbz"),
+ ("HTML", "*.htm*")
+ # add more document types here
+ )
+ )
+else:
+ fname = sys.argv[1]
+
+if not fname:
+ sg.Popup("Cancelling:", "No filename supplied")
+ raise SystemExit("Cancelled: no filename supplied")
+
+doc = fitz.open(fname)
+page_count = len(doc)
+
+# used for response time statistics only
+fitz_img_time = 0.0
+tk_img_time = 0.0
+img_count = 1
+
+# allocate storage for page display lists
+dlist_tab = [None] * page_count
+
+title = "PyMuPDF display of '%s', pages: %i" % (fname, page_count)
+
+def get_page(pno, zoom = False, max_size = None, first = False):
+ """Return a PNG image for a document page number.
+ """
+ dlist = dlist_tab[pno] # get display list of page number
+ if not dlist: # create if not yet there
+ dlist_tab[pno] = doc[pno].getDisplayList()
+ dlist = dlist_tab[pno]
+ r = dlist.rect # the page rectangle
+ clip = r
+ # ensure image fits screen:
+ # exploit, but do not exceed width or height
+ zoom_0 = 1
+ if max_size:
+ zoom_0 = min(1, max_size[0] / r.width, max_size[1] / r.height)
+ if zoom_0 == 1:
+ zoom_0 = min(max_size[0] / r.width, max_size[1] / r.height)
+ mat_0 = fitz.Matrix(zoom_0, zoom_0)
+
+ if not zoom: # show total page
+ pix = dlist.getPixmap(matrix = mat_0, alpha=False)
+ else:
+ mp = r.tl + (r.br - r.tl) * 0.5 # page rect center
+ w2 = r.width / 2
+ h2 = r.height / 2
+ clip = r * 0.5
+ tl = zoom[0] # old top-left
+ tl.x += zoom[1] * (w2 / 2)
+ tl.x = max(0, tl.x)
+ tl.x = min(w2, tl.x)
+ tl.y += zoom[2] * (h2 / 2)
+ tl.y = max(0, tl.y)
+ tl.y = min(h2, tl.y)
+ clip = fitz.Rect(tl, tl.x + w2, tl.y + h2)
+
+ mat = mat_0 * fitz.Matrix(2, 2) # zoom matrix
+ pix = dlist.getPixmap(alpha=False, matrix=mat, clip=clip)
+
+ if first: # first call: tkinter still inactive
+ img = pix.getPNGData() # so use fitz png output
+ else: # else take tk photo image
+ pilimg = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
+ img = ImageTk.PhotoImage(pilimg)
+
+ return img, clip.tl # return image, clip position
+
+
+root = tk.Tk()
+max_width = root.winfo_screenwidth() - 20
+max_height = root.winfo_screenheight() - 135
+max_size = (max_width, max_height)
+root.destroy()
+del root
+
+window = sg.Window(title, return_keyboard_events = True,
+ location = (0,0), use_default_focus = False, no_titlebar=False)
+
+cur_page = 0
+data, clip_pos = get_page(cur_page,
+ zoom = False,
+ max_size = max_size,
+ first = True)
+
+image_elem = sg.Image(data = data)
+
+goto = sg.InputText(str(cur_page + 1), size=(5, 1), do_not_clear=True,
+ key = "PageNumber")
+
+layout = [
+ [
+ sg.ReadButton('Next'),
+ sg.ReadButton('Prev'),
+ sg.Text('Page:'),
+ goto,
+ sg.Text('(%i)' % page_count),
+ sg.ReadButton('Zoom'),
+ sg.Text('(toggle on/off, use arrows to navigate while zooming)'),
+ ],
+ [image_elem],
+]
+
+window.Layout(layout)
+
+# now define the buttons / events we want to handle
+enter_buttons = [chr(13), "Return:13"]
+quit_buttons = ["Escape:27", chr(27)]
+next_buttons = ["Next", "Next:34", "MouseWheel:Down"]
+prev_buttons = ["Prev", "Prior:33", "MouseWheel:Up"]
+Up = "Up:38"
+Left = "Left:37"
+Right = "Right:39"
+Down = "Down:40"
+zoom_buttons = ["Zoom", Up, Down, Left, Right]
+
+# all the buttons we will handle
+my_keys = enter_buttons + next_buttons + prev_buttons + zoom_buttons
+
+# old page store and zoom toggle
+old_page = 0
+old_zoom = False
+
+while True:
+ event, value = window.Read()
+ if event is None and (value is None or value['PageNumber'] is None):
+ break
+ if event in quit_buttons:
+ break
+
+ zoom_pressed = False
+ zoom = False
+
+ if event in enter_buttons:
+ try:
+ cur_page = int(value['PageNumber']) - 1 # check if valid
+ while cur_page < 0:
+ cur_page += page_count
+ except:
+ cur_page = 0 # this guy's trying to fool me
+
+ elif event in next_buttons:
+ cur_page += 1
+ elif event in prev_buttons:
+ cur_page -= 1
+ elif event == Up:
+ zoom = (clip_pos, 0, -1)
+ elif event == Down:
+ zoom = (clip_pos, 0, 1)
+ elif event == Left:
+ zoom = (clip_pos, -1, 0)
+ elif event == Right:
+ zoom = (clip_pos, 1, 0)
+ elif event == "Zoom":
+ zoom_pressed = True
+ zoom = (clip_pos, 0, 0)
+
+ # sanitize page number
+ if cur_page >= page_count: # wrap around
+ cur_page = 0
+ while cur_page < 0: # pages > 0 look nicer
+ cur_page += page_count
+
+ if zoom_pressed and old_zoom:
+ zoom = zoom_pressed = old_zoom = False
+
+ t0 = time.perf_counter()
+ data, clip_pos = get_page(cur_page, zoom = zoom, max_size = max_size,
+ first = False)
+ t1 = time.perf_counter()
+ image_elem.Update(data = data)
+ t2 = time.perf_counter()
+ fitz_img_time += t1 - t0
+ tk_img_time += t2 - t1
+ img_count += 1
+ old_page = cur_page
+ old_zoom = zoom_pressed or zoom
+
+ # update page number field
+ if event in my_keys:
+ goto.Update(str(cur_page + 1))
+
+
+# print some response time statistics
+if img_count > 0:
+ print("response times for '%s'" % doc.name)
+ print("%.4f" % (fitz_img_time/img_count), "sec fitz avg. image time")
+ print("%.4f" % (tk_img_time/img_count), "sec tk avg. image time")
+ print("%.4f" % ((fitz_img_time + tk_img_time)/img_count), "sec avg. total time")
+ print(img_count, "images read")
+ print(page_count, "pages")
diff --git a/DemoPrograms old/Demo_Debugger_Built_Into_PSG.py b/DemoPrograms old/Demo_Debugger_Built_Into_PSG.py
new file mode 100644
index 000000000..22e4b9aeb
--- /dev/null
+++ b/DemoPrograms old/Demo_Debugger_Built_Into_PSG.py
@@ -0,0 +1,55 @@
+import PySimpleGUI as sg
+# import imwatchingyou # Not needed because using the one inside PySimpleGUI.py code itself
+
+"""
+ Demo program that shows you how to integrate the PySimpleGUI Debugger
+ into your program.
+ This particular program is a GUI based program simply to make it easier for you to interact and change
+ things.
+
+ In this example, the debugger is not started initiallly. You click the "Debug" button to launch it
+ There are THREE steps, and they are copy and pastes.
+ 1. At the top of your app to debug add
+ import imwatchingyou
+ 2. When you want to show a debug window, call one of two functions:
+ imwatchingyou.show_debug_window()
+ imwatchingyou.show_popout_window()
+ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
+ In this loop add this call:
+ imwatchingyou.refresh()
+"""
+
+layout = [
+ [sg.T('A typical PSG application')],
+ [sg.In(key='_IN_')],
+ [sg.T(' ', key='_OUT_', size=(45,1))],
+ [sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
+ [sg.Radio('a',1, key='_R1_'), sg.Radio('b',1, key='_R2_'), sg.Radio('c',1, key='_R3_')],
+ [sg.Combo(['c1', 'c2', 'c3'], size=(6,3), key='_COMBO_')],
+ [sg.Output(size=(50,6))],
+ [sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Button('Popout'), sg.Button('Debugger'), sg.Debug(key='Debug')],
+ ]
+
+window = sg.Window('This is your Application Window', layout, debugger_enabled=False)
+
+counter = 0
+timeout = 100
+
+# Note that you can launch the debugger windows right away, without waiting for user input
+sg.show_debugger_popout_window()
+
+while True: # Your Event Loop
+ event, values = window.Read(timeout=timeout)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Enable':
+ window.EnableDebugger()
+ elif event == 'Popout':
+ sg.show_debugger_popout_window() # replaces old popout with a new one, possibly with new variables`
+ elif event == 'Debugger':
+ sg.show_debugger_window()
+ counter += 1
+ # to prove window is operating, show the input in another area in the window.
+ window.Element('_OUT_').Update(values['_IN_'])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Debugger_Button.py b/DemoPrograms old/Demo_Debugger_Button.py
new file mode 100644
index 000000000..b2b482d65
--- /dev/null
+++ b/DemoPrograms old/Demo_Debugger_Button.py
@@ -0,0 +1,48 @@
+import PySimpleGUI as sg
+# import imwatchingyou # STEP 1
+
+"""
+ Demo program that shows you how to integrate the PySimpleGUI Debugger
+ into your program.
+ This particular program is a GUI based program simply to make it easier for you to interact and change
+ things.
+
+ In this example, the debugger is not started initiallly. You click the "Debug" button to launch it
+ There are THREE steps, and they are copy and pastes.
+ 1. At the top of your app to debug add
+ import imwatchingyou
+ 2. When you want to show a debug window, call one of two functions:
+ imwatchingyou.show_debug_window()
+ imwatchingyou.show_popout_window()
+ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
+ In this loop add this call:
+ imwatchingyou.refresh()
+"""
+
+layout = [
+ [sg.T('A typical PSG application')],
+ [sg.In(key='_IN_')],
+ [sg.T(' ', key='_OUT_', size=(45,1))],
+ [sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
+ [sg.Radio('a',1, key='_R1_'), sg.Radio('b',1, key='_R2_'), sg.Radio('c',1, key='_R3_')],
+ [sg.Combo(['c1', 'c2', 'c3'], size=(6,3), key='_COMBO_')],
+ [sg.Output(size=(50,6))],
+ [sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Debug(key='Debug')],
+ ]
+
+window = sg.Window('This is your Application Window', layout, debugger_enabled=False)
+
+counter = 0
+timeout = 100
+
+while True: # Your Event Loop
+ event, values = window.Read(timeout=timeout)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Enable':
+ window.EnableDebugger()
+ counter += 1
+ # to prove window is operating, show the input in another area in the window.
+ window.Element('_OUT_').Update(values['_IN_'])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Debugger_ImWatchingYou.py b/DemoPrograms old/Demo_Debugger_ImWatchingYou.py
new file mode 100644
index 000000000..12239a7e9
--- /dev/null
+++ b/DemoPrograms old/Demo_Debugger_ImWatchingYou.py
@@ -0,0 +1,54 @@
+import PySimpleGUI as sg
+import imwatchingyou # STEP 1
+
+"""
+ Demo program that shows you how to integrate the PySimpleGUI Debugger
+ into your program.
+ This particular program is a GUI based program simply to make it easier for you to interact and change
+ things.
+
+ In this example, the debugger is not started initiallly. You click the "Debug" button to launch it
+ There are THREE steps, and they are copy and pastes.
+ 1. At the top of your app to debug add
+ import imwatchingyou
+ 2. When you want to show a debug window, call one of two functions:
+ imwatchingyou.show_debug_window()
+ imwatchingyou.show_popout_window()
+ 3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
+ In this loop add this call:
+ imwatchingyou.refresh()
+"""
+
+layout = [
+ [sg.T('A typical PSG application')],
+ [sg.In(key='_IN_')],
+ [sg.T(' ', key='_OUT_', size=(30, 1))],
+ [sg.Radio('a', 1, key='_R1_'), sg.Radio('b', 1, key='_R2_'), sg.Radio('c', 1, key='_R3_')],
+ [sg.Combo(['c1', 'c2', 'c3'], size=(6, 3), key='_COMBO_')],
+ [sg.Output(size=(50, 6))],
+ [sg.Ok(), sg.Exit(), sg.Button('Debug'), sg.Button('Popout')],
+]
+
+window = sg.Window('This is your Application Window', layout)
+
+counter = 0
+timeout = 100
+
+while True: # Your Event Loop
+ event, values = window.Read(timeout=timeout)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Ok':
+ print('You clicked Ok.... this is where print output goes')
+ elif event == 'Debug':
+ imwatchingyou.show_debugger_window() # STEP 2
+ elif event == 'Popout':
+ imwatchingyou.show_debugger_popout_window() # STEP 2
+ counter += 1
+ # to prove window is operating, show the input in another area in the window.
+ window.Element('_OUT_').Update(values['_IN_'])
+
+ # don't worry about the "state" of things, just call this function "frequently"
+ imwatchingyou.refresh_debugger() # STEP 3 - refresh debugger
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows.py b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows.py
new file mode 100644
index 000000000..22b8cf552
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows.py
@@ -0,0 +1,59 @@
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+ Demo - Running 2 windows with both being active at the same time
+ Three important things to note about this design patter:
+ 1. The layout for window 2 is inside of the while loop, just before the call to window2=sg.Window
+ 2. The read calls have timeout values of 100 and 0. You can change the 100 to whatever interval you wish
+ but must keep the second window's timeout at 0
+ 3. There is a safeguard to stop from launching multiple copies of window2. Only 1 window2 is visible at a time
+"""
+
+# Window 1 layout
+layout = [
+ [sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='_OUTPUT_')],
+ [sg.Text('')],
+ [sg.Button('Launch 2nd Window'),sg.Button('Popup'), sg.Button('Exit')]
+ ]
+
+window = sg.Window('Window Title', location=(800,600)).Layout(layout)
+win2_active = False
+i=0
+while True: # Event Loop
+ event, values = window.Read(timeout=100)
+ if event != sg.TIMEOUT_KEY:
+ print(i, event, values)
+
+ if event is None or event == 'Exit':
+ break
+ elif event == 'Popup':
+ sg.Popup('This is a BLOCKING popup','all windows remain inactive while popup active')
+ i+=1
+ if event == 'Launch 2nd Window' and not win2_active: # only run if not already showing a window2
+ win2_active = True
+ # window 2 layout - note - must be "new" every time a window is created
+ layout2 = [
+ [sg.Text('The second window'), sg.Text('', key='_OUTPUT_')],
+ [sg.Input(do_not_clear=True, key='_IN_')],
+ [sg.Button('Show'), sg.Button('Exit')]
+ ]
+ window2 = sg.Window('Second Window').Layout(layout2)
+ # Read window 2's events. Must use timeout of 0
+ if win2_active:
+ # print("reading 2")
+ event, values = window2.Read(timeout=100)
+ # print("win2 ", event)
+ if event != sg.TIMEOUT_KEY:
+ print("win2 ", event)
+ if event == 'Exit' or event is None:
+ # print("Closing window 2", event)
+ win2_active = False
+ window2.Close()
+ if event == 'Show':
+ sg.Popup('You entered ', values['_IN_'])
+
+window.Close()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows1.py b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows1.py
new file mode 100644
index 000000000..f2328e33b
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows1.py
@@ -0,0 +1,35 @@
+"""
+ PySimpleGUI The Complete Course
+ Lesson 7 - Multiple Windows
+"""
+import PySimpleGUI as sg
+
+# Design pattern 1 - First window does not remain active
+
+layout = [[ sg.Text('Window 1'),],
+ [sg.Input(do_not_clear=True)],
+ [sg.Text('', size=(20,1), key='_OUTPUT_')],
+ [sg.Button('Launch 2')]]
+
+win1 = sg.Window('Window 1').Layout(layout)
+win2_active=False
+while True:
+ ev1, vals1 = win1.Read(timeout=100)
+ if ev1 is None:
+ break
+ win1.FindElement('_OUTPUT_').Update(vals1[0])
+
+ if ev1 == 'Launch 2' and not win2_active:
+ win2_active = True
+ win1.Hide()
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('Exit')]]
+
+ win2 = sg.Window('Window 2').Layout(layout2)
+ while True:
+ ev2, vals2 = win2.Read()
+ if ev2 is None or ev2 == 'Exit':
+ win2.Close()
+ win2_active = False
+ win1.UnHide()
+ break
diff --git a/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows2.py b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows2.py
new file mode 100644
index 000000000..41bdad76e
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows2.py
@@ -0,0 +1,34 @@
+"""
+ PySimpleGUI The Complete Course
+ Lesson 7 - Multiple Windows
+"""
+import PySimpleGUI as sg
+
+# Design pattern 2 - First window remains active
+
+layout = [[ sg.Text('Window 1'),],
+ [sg.Input(do_not_clear=True)],
+ [sg.Text('', size=(20,1), key='_OUTPUT_')],
+ [sg.Button('Launch 2'), sg.Button('Exit')]]
+
+win1 = sg.Window('Window 1').Layout(layout)
+
+win2_active = False
+while True:
+ ev1, vals1 = win1.Read(timeout=100)
+ win1.FindElement('_OUTPUT_').Update(vals1[0])
+ if ev1 is None or ev1 == 'Exit':
+ break
+
+ if not win2_active and ev1 == 'Launch 2':
+ win2_active = True
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('Exit')]]
+
+ win2 = sg.Window('Window 2').Layout(layout2)
+
+ if win2_active:
+ ev2, vals2 = win2.Read(timeout=100)
+ if ev2 is None or ev2 == 'Exit':
+ win2_active = False
+ win2.Close()
diff --git a/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows3.py b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows3.py
new file mode 100644
index 000000000..b5500cec9
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Pattern_Multiple_Windows3.py
@@ -0,0 +1,48 @@
+import PySimpleGUI as sg
+
+layout = [[sg.Text('Window 1'), ],
+ [sg.Input(do_not_clear=True)],
+ [sg.Text('',size=(20,1), key='_OUTPUT_')],
+ [sg.Button('Next >'), sg.Button('Exit')]]
+
+win1 = sg.Window('Window 1').Layout(layout)
+
+win3_active = win2_active = False
+while True:
+ if not win2_active:
+ ev1, vals1 = win1.Read()
+ if ev1 is None or ev1 == 'Exit':
+ break
+ win1.FindElement('_OUTPUT_').Update(vals1[0])
+
+ if not win2_active and ev1 == 'Next >':
+ win2_active = True
+ win1.Hide()
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('< Prev'), sg.Button('Next >')]]
+
+ win2 = sg.Window('Window 2').Layout(layout2)
+
+ if win2_active:
+ ev2, vals2 = win2.Read()
+ if ev2 in (None, 'Exit', '< Prev'):
+ win2_active = False
+ win2.Close()
+ win1.UnHide()
+ elif ev2 == 'Next >':
+ win3_active = True
+ win2_active = False
+ win2.Hide()
+ layout3 = [[sg.Text('Window 3')],
+ [sg.Button('< Prev'), sg.Button('Exit')]]
+ win3 = sg.Window('Window 3').Layout(layout3)
+
+ if win3_active:
+ ev3, vals3 = win3.Read()
+ if ev3 == '< Prev':
+ win3.Close()
+ win3_active = False
+ win2_active = True
+ win2.UnHide()
+ elif ev3 in (None, 'Exit'):
+ break
diff --git a/DemoPrograms old/Demo_Design_Pattern_Persistent_Window.py b/DemoPrograms old/Demo_Design_Pattern_Persistent_Window.py
new file mode 100644
index 000000000..7d1374588
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Pattern_Persistent_Window.py
@@ -0,0 +1,24 @@
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [
+ [sg.Text('Your typed chars appear here:'), sg.Text('', size=(20,1), key='-OUTPUT-')],
+ [sg.Input(do_not_clear=True, key='-IN-')],
+ [sg.Button('Show'), sg.Button('Exit')]
+ ]
+
+window = sg.Window('Window Title').Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event is None or event == 'Exit':
+ break
+ if event == 'Show':
+ # change the "output" element to be the value of "input" element
+ window.FindElement('-OUTPUT-').Update(values['-IN-'])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Design_Patterns.py b/DemoPrograms old/Demo_Design_Patterns.py
new file mode 100644
index 000000000..64b396610
--- /dev/null
+++ b/DemoPrograms old/Demo_Design_Patterns.py
@@ -0,0 +1,54 @@
+"""
+When creating a new PySimpleGUI program from scratch, start here.
+These are the accepted design patterns that cover the two primary use cases
+
+1. A "One Shot" window
+2. A persistent window that stays open after button clicks (uses an event loop)
+3. A persistent window that need to perform Update of an element before the window.read
+"""
+# ---------------------------------#
+# DESIGN PATTERN 1 - Simple Window #
+# ---------------------------------#
+import PySimpleGUI as sg
+
+layout = [[ sg.Text('My Oneshot') ],
+ [ sg.Button('OK') ]]
+
+window = sg.Window('My Oneshot', layout)
+event, values = window.read()
+window.close()
+
+
+# -------------------------------------#
+# DESIGN PATTERN 2 - Persistent Window #
+# -------------------------------------#
+import PySimpleGUI as sg
+
+layout = [[ sg.Text('My layout') ],
+ [ sg.Button('OK'), sg.Button('Cancel') ]]
+
+window = sg.Window('Design Pattern 2', layout)
+
+while True: # Event Loop
+ event, values = window.read()
+ if event in (None, 'Cancel'):
+ break
+window.close()
+
+# ------------------------------------------------------------------#
+# DESIGN PATTERN 3 - Persistent Window with "early update" required #
+# ------------------------------------------------------------------#
+import PySimpleGUI as sg
+
+layout = [[ sg.Text('My layout', key='-TEXT-KEY-') ],
+ [ sg.Button('OK'), sg.Button('Cancel') ]]
+
+window = sg.Window('Design Pattern 3', layout, finalize=True)
+
+window['-TEXT-KEY-'].Update('NEW Text') # Change the text field. Finalize allows us to do this
+
+while True: # Event Loop
+ event, values = window.read()
+ if event in (None, 'Cancel'):
+ break
+window.close()
diff --git a/DemoPrograms old/Demo_Desktop_Floating_Toolbar.py b/DemoPrograms old/Demo_Desktop_Floating_Toolbar.py
new file mode 100644
index 000000000..785ae428a
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Floating_Toolbar.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import subprocess
+import os
+
+
+"""
+ Demo_Toolbar - A floating toolbar with quick launcher
+
+ One cool PySimpleGUI demo. Shows borderless windows, grab_anywhere, tight button layout
+ You can setup a specific program to launch when a button is clicked, or use the
+ Combobox to select a .py file found in the root folder, and run that file.
+
+"""
+
+ROOT_PATH = './'
+
+def Launcher():
+
+ # def print(line):
+ # window.FindElement('output').Update(line)
+
+ sg.ChangeLookAndFeel('Dark')
+
+ namesonly = [f for f in os.listdir(ROOT_PATH) if f.endswith('.py') ]
+
+ if len(namesonly) == 0:
+ namesonly = ['test 1', 'test 2', 'test 3']
+
+ sg.SetOptions(element_padding=(0,0), button_element_size=(12,1), auto_size_buttons=False)
+
+ layout = [[sg.Combo(values=namesonly, size=(35,30), key='demofile'),
+ sg.Button('Run', button_color=('white', '#00168B')),
+ sg.Button('Program 1'),
+ sg.Button('Program 2'),
+ sg.Button('Program 3', button_color=('white', '#35008B')),
+ sg.Button('EXIT', button_color=('white','firebrick3'))],
+ [sg.T('', text_color='white', size=(50,1), key='output')]]
+
+ window = sg.Window('Floating Toolbar', no_titlebar=True, grab_anywhere=True, keep_on_top=True).Layout(layout)
+
+
+ # ---===--- Loop taking in user input and executing appropriate program --- #
+ while True:
+ (event, values) = window.Read()
+ if event == 'EXIT' or event is None:
+ break # exit button clicked
+ if event == 'Program 1':
+ print('Run your program 1 here!')
+ elif event == 'Program 2':
+ print('Run your program 2 here!')
+ elif event == 'Run':
+ file = values['demofile']
+ print('Launching %s'%file)
+ ExecuteCommandSubprocess('python', os.path.join(ROOT_PATH, file))
+ else:
+ print(event)
+
+def ExecuteCommandSubprocess(command, *args, wait=False):
+ try:
+ if sys.platform == 'linux':
+ arg_string = ''
+ arg_string = ' '.join([str(arg) for arg in args])
+ # for arg in args:
+ # arg_string += ' ' + str(arg)
+ print('python3 ' + arg_string)
+ sp = subprocess.Popen(['python3 ', arg_string ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ else:
+ arg_string = ' '.join([str(arg) for arg in args])
+ sp = subprocess.Popen([command, arg_string], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # sp = subprocess.Popen([command, list(args)], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ if wait:
+ out, err = sp.communicate()
+ if out:
+ print(out.decode("utf-8"))
+ if err:
+ print(err.decode("utf-8"))
+ except: pass
+
+
+
+if __name__ == '__main__':
+ Launcher()
+
diff --git a/DemoPrograms old/Demo_Desktop_Widget_CPU_Dashboard.py b/DemoPrograms old/Demo_Desktop_Widget_CPU_Dashboard.py
new file mode 100644
index 000000000..0512f4d64
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_CPU_Dashboard.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import psutil
+
+"""
+ Desktop floating widget - CPU Cores
+ Uses psutil to display:
+ CPU usage on each individual core
+ Information is updated once a second and is shown as an area graph that scrolls
+"""
+
+GRAPH_WIDTH = 120 # each individual graph size in pixels
+GRAPH_HEIGHT = 40
+TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window
+NUM_COLS = 4
+POLL_FREQUENCY = 500 # how often to update graphs in milliseconds
+
+colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
+
+# DashGraph does the drawing of each graph
+class DashGraph(object):
+ def __init__(self, graph_elem, text_elem, starting_count, color):
+ self.graph_current_item = 0
+ self.graph_elem = graph_elem
+ self.text_elem = text_elem
+ self.prev_value = starting_count
+ self.max_sent = 1
+ self.color = color
+
+ def graph_percentage_abs(self, value):
+ self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color)
+ if self.graph_current_item >= GRAPH_WIDTH:
+ self.graph_elem.Move(-1,0)
+ else:
+ self.graph_current_item += 1
+
+ def text_display(self, text):
+ self.text_elem.Update(text)
+
+def main():
+ # A couple of "Uber Elements" that combine several elements and enable bulk edits
+ def Txt(text, **kwargs):
+ return(sg.Text(text, font=('Helvetica 8'), **kwargs))
+
+ def GraphColumn(name, key):
+ col = sg.Column([[Txt(name, key=key+'_TXT_'), ],
+ [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black',
+ key=key+'_GRAPH_')]], pad=(2, 2))
+ return col
+
+
+ num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0), margins=(1,1), border_width=0)
+
+ # ---------------- Create Layout ----------------
+ layout = [[ sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'),
+ sg.Text(' CPU Core Usage')] ]
+
+ # add on the graphs
+ for rows in range(num_cores//NUM_COLS+1):
+ row = []
+ for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)):
+ row.append(GraphColumn('CPU '+str(rows*NUM_COLS+cols), '_CPU_'+str(rows*NUM_COLS+cols)))
+ layout.append(row)
+
+ # ---------------- Create Window ----------------
+ window = sg.Window('PSG System Dashboard',
+ keep_on_top=True,
+ auto_size_buttons=False,
+ grab_anywhere=True,
+ no_titlebar=True,
+ default_button_element_size=(12, 1),
+ return_keyboard_events=True,
+ alpha_channel=TRANSPARENCY,
+ use_default_focus=False,
+ ).Layout(layout).Finalize()
+
+ # setup graphs & initial values
+ graphs = []
+ for i in range(num_cores):
+ graphs.append(DashGraph(window.FindElement('_CPU_'+str(i)+'_GRAPH_'),
+ window.FindElement('_CPU_'+str(i) + '_TXT_'),
+ 0, colors[i%6]))
+
+ # ---------------- main loop ----------------
+ while (True):
+ # --------- Read and update window once every Polling Frequency --------
+ event, values = window.Read(timeout=POLL_FREQUENCY)
+ if event in (None, 'Exit'): # Be nice and give an exit
+ break
+ # read CPU for each core
+ stats = psutil.cpu_percent(percpu=True)
+ # Update each graph
+ for i in range(num_cores):
+ graphs[i].graph_percentage_abs(stats[i])
+ graphs[i].text_display('{} CPU {:2.0f}'.format(i, stats[i]))
+ window.Close()
+
+if __name__ == "__main__":
+ # the clever Red X graphic
+ red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+
+ main()
+ sys.exit(69)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Desktop_Widget_CPU_Graph.py b/DemoPrograms old/Demo_Desktop_Widget_CPU_Graph.py
new file mode 100644
index 000000000..801cd61e0
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_CPU_Graph.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import time
+import random
+import psutil
+from threading import Thread
+
+
+STEP_SIZE=3
+SAMPLES = 300
+SAMPLE_MAX = 500
+CANVAS_SIZE = (300,200)
+
+
+g_interval = .25
+g_cpu_percent = 0
+g_procs = None
+g_exit = False
+
+def CPU_thread(args):
+ global g_interval, g_cpu_percent, g_procs, g_exit
+
+ while not g_exit:
+ try:
+ g_cpu_percent = psutil.cpu_percent(interval=g_interval)
+ g_procs = psutil.process_iter()
+ except:
+ pass
+
+def main():
+ global g_exit, g_response_time
+ # start ping measurement thread
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0))
+
+ layout = [ [sg.Quit( button_color=('white','black')), sg.T('', pad=((100,0),0), font='Any 15', key='output')],
+ [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
+
+ window = sg.Window('CPU Graph', grab_anywhere=True, keep_on_top=True, background_color='black', no_titlebar=True, use_default_focus=False).Layout(layout)
+
+ graph = window.FindElement('graph')
+ output = window.FindElement('output')
+ # start cpu measurement thread
+ thread = Thread(target=CPU_thread,args=(None,))
+ thread.start()
+
+ last_cpu = i = 0
+ prev_x, prev_y = 0, 0
+ while True: # the Event Loop
+ time.sleep(.5)
+ event, values = window.Read(timeout=0)
+ if event == 'Quit' or event is None: # always give ths user a way out
+ break
+ # do CPU measurement and graph it
+ current_cpu = int(g_cpu_percent*10)
+ if current_cpu == last_cpu:
+ continue
+ output.Update(current_cpu/10) # show current cpu usage at top
+ if current_cpu > SAMPLE_MAX:
+ current_cpu = SAMPLE_MAX
+ new_x, new_y = i, current_cpu
+ if i >= SAMPLES:
+ graph.Move(-STEP_SIZE,0) # shift graph over if full of data
+ prev_x = prev_x - STEP_SIZE
+ graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
+ prev_x, prev_y = new_x, new_y
+ i += STEP_SIZE if i < SAMPLES else 0
+ last_cpu = current_cpu
+
+ g_exit = True
+ window.Close()
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization.py b/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization.py
new file mode 100644
index 000000000..39aefb5dc
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import psutil
+import time
+from threading import Thread
+import operator
+
+
+"""
+ PSUTIL 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
+ 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.
+ It will look something like:
+ invalid command name "1616802625480StopMove"
+"""
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_interval = 1
+g_cpu_percent = 0
+g_procs = None
+g_exit = False
+
+def CPU_thread(args):
+ global g_interval, g_cpu_percent, g_procs, g_exit
+
+ while not g_exit:
+ try:
+ g_cpu_percent = psutil.cpu_percent(interval=g_interval)
+ g_procs = psutil.process_iter()
+ except:
+ pass
+
+
+def main():
+ global g_interval, g_procs, g_exit
+
+ # ---------------- Create Form ----------------
+ sg.ChangeLookAndFeel('Black')
+ layout = [[sg.Text('', size=(8,1), font=('Helvetica', 20),text_color=sg.YELLOWS[0],
+ justification='center', key='text')],
+ [sg.Text('', size=(30, 8), font=('Courier New', 12),text_color='white', justification='left', key='processes')],
+ [sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0), size=(9,1)),
+ sg.Spin([x+1 for x in range(10)], 3, key='spin')],]
+
+ window = sg.Window('CPU Utilization',
+ no_titlebar=True,
+ keep_on_top=True,
+ alpha_channel=.8,
+ grab_anywhere=True).Layout(layout)
+
+ # start cpu measurement thread
+ thread = Thread(target=CPU_thread,args=(None,))
+ thread.start()
+ timeout_value = 1 # make first read really quick
+ g_interval = 1
+ # ---------------- main loop ----------------
+ while (True):
+ # --------- Read and update window --------
+ event, values = window.Read(timeout=timeout_value, timeout_key='Timeout')
+ # --------- Do Button Operations --------
+ if event is None or event == 'Exit':
+ break
+
+ timeout_value = int(values['spin']) * 1000
+
+ 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.FindElement('text').Update('CPU {}'.format(cpu_percent))
+ window.FindElement('processes').Update(display_string)
+
+ g_exit = True
+ thread.join()
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization_Simple.py b/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization_Simple.py
new file mode 100644
index 000000000..f5c61b322
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_CPU_Utilization_Simple.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import psutil
+
+# ---------------- Create Form ----------------
+sg.ChangeLookAndFeel('Black')
+
+layout = [[sg.Text('CPU Utilization')],
+ [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='_text_')],
+ [sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9,1)),
+ sg.Spin([x + 1 for x in range(10)], 3, key='_spin_')]]
+
+# Layout the rows of the Window
+window = sg.Window('CPU Meter',
+ no_titlebar=True,
+ keep_on_top=True,
+ grab_anywhere=True).Layout(layout).Finalize()
+
+# ---------------- main loop ----------------
+interval = 10 # For the first one, make it quick
+while (True):
+ # --------- Read and update window --------
+ event, values = window.Read(timeout=interval)
+ # --------- Do Button Operations --------
+ if event is None or event == 'Exit':
+ break
+
+ interval = int(values['_spin_'])*1000
+
+
+
+ cpu_percent = psutil.cpu_percent(interval=1)
+
+ # --------- Display timer in window --------
+
+ window.FindElement('_text_').Update(f'CPU {cpu_percent:02.0f}%')
+
+# Broke out of main loop. Close the window.
+window.CloseNonBlocking()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Desktop_Widget_Email_Notification.py b/DemoPrograms old/Demo_Desktop_Widget_Email_Notification.py
new file mode 100644
index 000000000..de4264d81
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_Email_Notification.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+import sys
+
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+ sg.PopupError('Sorry, at the moment this program only runs on Python 3')
+ sys.exit()
+
+import email
+import imaplib
+from datetime import datetime
+import calendar
+
+IMAP_SERVER_GMAIL = 'imap.gmail.com' # gmail server address
+IMAP_SERVER_HOTMAIL = 'imap-mail.outlook.com' # hotmail server address
+
+################# Change these to match your email setup ################
+LOGIN_EMAIL = 'you@mail.com'
+LOGIN_PASSWORD = 'your email password'
+IMAP_SERVER = IMAP_SERVER_GMAIL # change to match your email service
+
+MAX_EMAILS = 10
+
+
+def gui():
+ sg.ChangeLookAndFeel('Topanga')
+
+ sg.SetOptions(border_width=0, margins=(0, 0), element_padding=(4, 0))
+
+ layout = [[sg.T('Email New Mail Notification' + 48 * ' '),
+ sg.Button('', image_data=refresh, button_color=('#282923', '#282923'), key='_refresh_',
+ tooltip='Refreshes Email'),
+ sg.Button('', image_data=red_x, button_color=('#282923', '#282923'), key='_quit_',
+ tooltip='Closes window')],
+ [sg.T('', key='_status_', size=(25, 1))], ]
+
+ for i in range(MAX_EMAILS):
+ layout.append([sg.T('', size=(20, 1), key='{}date'.format(i), font='Sans 8'),
+ sg.T('', size=(45, 1), font='Sans 8', key='{}from'.format(i))])
+
+ window = sg.Window('',
+ no_titlebar=True,
+ grab_anywhere=True,
+ keep_on_top=True,
+ alpha_channel=0,
+ ).Layout(layout).Finalize()
+
+ # move the window to the upper right corner of the screen
+ w, h = window.GetScreenDimensions()
+ window.Move(w - 410, 0)
+ window.SetAlpha(.9)
+ window.Refresh()
+ status_elem = window.FindElement('_status_')
+ # The Event Loop
+ while True:
+ status_elem.Update('Reading...')
+ window.Refresh()
+ read_mail(window)
+ status_elem.Update('')
+ event, values = window.Read(timeout=30 * 1000) # return every 30 seconds
+ if event == '_quit_':
+ break
+
+
+def read_mail(window):
+ """
+ Reads late emails from IMAP server and displays them in the Window
+ :param window: window to display emails in
+ :return:
+ """
+ mail = imaplib.IMAP4_SSL(IMAP_SERVER)
+
+ (retcode, capabilities) = mail.login(LOGIN_EMAIL, LOGIN_PASSWORD)
+ mail.list()
+ typ, data = mail.select('Inbox')
+ n = 0
+ now = datetime.now()
+ # get messages from today
+ search_string = '(SENTON {}-{}-{})'.format(now.day, calendar.month_abbr[now.month], now.year)
+ (retcode, messages) = mail.search(None, search_string)
+ if retcode == 'OK':
+ msg_list = messages[0].split() # message numbers are separated by spaces, turn into list
+ msg_list.sort(reverse=True) # sort messages descending
+ for n, message in enumerate(msg_list):
+ if n >= MAX_EMAILS:
+ break
+ from_elem = window.FindElement('{}from'.format(n))
+ date_elem = window.FindElement('{}date'.format(n))
+ from_elem.Update('') # erase them so you know they're changing
+ date_elem.Update('')
+ window.Refresh()
+ typ, data = mail.fetch(message, '(RFC822)')
+ for response_part in data:
+ if isinstance(response_part, tuple):
+ original = email.message_from_bytes(response_part[1])
+ date_str = original['Date'][:22]
+ from_elem.Update(original['From'])
+ date_elem.Update(date_str)
+ window.Refresh() # make the window changes show up right away
+
+
+red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+
+refresh = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACb0lEQVR4XpVTXUiTbxT/vePdFuF0BTFW9ufVvMlu+iACka6CQY1gQVdtEmTMpSKzzJT/RTdCRHhT4F0Us8LGVqlo1lZaFslWQWBkN+tDkpSpbfNz797T8zy6DbUbf/Dbec7vfOycMwa0DBJjM7Ko72mBtz+KplCS6Ronf3NNxNZBt2qv4dJzL0uKwGRqU/6zHDqyd1dBk32/xMnfXOMxkVPXXYlVSLjykk4fKIb/4zgUSxEO7zRBKd4Bjm/jU9ys8f2fJoCFhRiWl6pw6+Qw0BymhlfT5Lg/xmycHA++ktL+nsRqrUOrdpBpH6hhKC7yhObti0CgKUTu0KTgcd8X4j4aB2bYvj7UPqkQrO/1cU25ESV3eJJO8LzLIQ11/CYXn5Grf4KqGF19E3Ts9iixe2QPm0dtt5PtP6NcHxF5ZVfDhIbeqMQ6E0hcI4ec327jah513T4YDM5TR/dh8vc0hkfHUxI2gwuPKyDLb2wV5cIdePuZZGwWmQxSSyqICFBVyKgJJkFaQW4Hna4THQ4X/gUiD2+QXEwjNZsASJvTgWgMqoY95WWw7raAJdjheeTEeniCTqgZu2IxswnSmGI3gEZjMiQpAMocTC2nJcm4hU9gRjp9E+6Ajb07wKFpHqRVOzKqedFUhOX4HyRnEwSjMQCB8/4IqnxU2DYiaGnsIe7n2UlK61MWe0dbW18Ijdfk/wuy7IXeEEvEvmM+kcRM4XYYSkohW62ChtIS/NKbWGwO8z9+Anp9TNSsQU2wEtVdEZy5o7Gfi7Z5ewj/vxbkPs51kYhVP4zAw3I3IN+ohSVFcfZeEs67Gid/c03E1uEv5QpTFzvZK5EAAAAASUVORK5CYII='
+
+gui()
diff --git a/DemoPrograms old/Demo_Desktop_Widget_Timer.py b/DemoPrograms old/Demo_Desktop_Widget_Timer.py
new file mode 100644
index 000000000..31b248752
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_Timer.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import time
+
+"""
+ Timer Desktop Widget Creates a floating timer that is always on top of other windows You move it by grabbing anywhere on the window Good example of how to do a non-blocking, polling program using PySimpleGUI
+ Something like this can be used to poll hardware when running on a Pi
+
+ While the timer ticks are being generated by PySimpleGUI's "timeout" mechanism, the actual value
+ of the timer that is displayed comes from the system timer, time.time(). This guarantees an
+ accurate time value is displayed regardless of the accuracy of the PySimpleGUI timer tick. If
+ this design were not used, then the time value displayed would slowly drift by the amount of time
+ it takes to execute the PySimpleGUI read and update calls (not good!)
+
+"""
+
+def time_as_int():
+ return int(round(time.time() * 100))
+
+# ---------------- Create Form ----------------
+sg.ChangeLookAndFeel('Black')
+
+layout = [[sg.Text('')],
+ [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
+ [sg.Button('Pause', key='-RUN-PAUSE-', button_color=('white', '#001480')),
+ sg.Button('Reset', button_color=('white', '#007339'), key='-RESET-'),
+ sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
+
+window = sg.Window('Running Timer', layout, no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True, element_padding=(0,0))
+
+# ---------------- main loop ----------------
+current_time, paused_time, paused = 0, 0, False
+start_time = time_as_int()
+while (True):
+ # --------- Read and update window --------
+ if not paused:
+ event, values = window.Read(timeout=10)
+ current_time = time_as_int() - start_time
+ else:
+ event, values = window.Read()
+ # --------- Do Button Operations --------
+ if event in (None, 'Exit'): # ALWAYS give a way out of program
+ break
+ if event == '-RESET-':
+ paused_time = start_time = time_as_int()
+ current_time = 0
+ elif event == '-RUN-PAUSE-':
+ paused = not paused
+ if paused:
+ paused_time = time_as_int()
+ else:
+ start_time = start_time + time_as_int() - paused_time
+ window['-RUN-PAUSE-'].Update('Run' if paused else 'Pause') # Change button's text
+
+ # --------- Display timer in window --------
+ window['text'].Update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
+ (current_time // 100) % 60,
+ current_time % 100))
+window.close()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Desktop_Widget_psutil_Dashboard.py b/DemoPrograms old/Demo_Desktop_Widget_psutil_Dashboard.py
new file mode 100644
index 000000000..3d1df6058
--- /dev/null
+++ b/DemoPrograms old/Demo_Desktop_Widget_psutil_Dashboard.py
@@ -0,0 +1,138 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import psutil
+
+"""
+ Desktop floating widget - System status dashboard
+ Uses psutil to display:
+ Network I/O
+ Disk I/O
+ CPU Used
+ Mem Used
+ Information is updated once a second and is shown as an area graph that scrolls
+"""
+
+GRAPH_WIDTH = 120 # each individual graph size in pixels
+GRAPH_HEIGHT = 40
+ALPHA = .7
+
+class DashGraph(object):
+ def __init__(self, graph_elem, starting_count, color):
+ self.graph_current_item = 0
+ self.graph_elem = graph_elem
+ self.prev_value = starting_count
+ self.max_sent = 1
+ self.color = color
+
+ def graph_value(self, current_value):
+ delta = current_value - self.prev_value
+ self.prev_value = current_value
+ self.max_sent = max(self.max_sent, delta)
+ percent_sent = 100 * delta / self.max_sent
+ self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, percent_sent), color=self.color)
+ if self.graph_current_item >= GRAPH_WIDTH:
+ self.graph_elem.Move(-1,0)
+ else:
+ self.graph_current_item += 1
+ return delta
+
+ def graph_percentage_abs(self, value):
+ self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color)
+ if self.graph_current_item >= GRAPH_WIDTH:
+ self.graph_elem.Move(-1,0)
+ else:
+ self.graph_current_item += 1
+
+
+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():
+ # Make the layout less cluttered and allow bulk-changes to text formatting
+ def Txt(text, **kwargs):
+ return(sg.Text(text, font=('Helvetica 8'), **kwargs))
+ # Update a Text Element
+ def Txt_Update(window, key, value):
+ window.FindElement(key).Update(value)
+
+ # ---------------- Create Window ----------------
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0), margins=(1,1), border_width=0)
+
+ def GraphColumn(name, key):
+ col = sg.Column([[Txt(name, key=key+'TXT_'), ],
+ [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black',
+ key=key+'GRAPH_')]], pad=(2, 2))
+ return col
+
+ layout = [[sg.Text('System Status Dashboard'+' '*18), sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window')],
+ [GraphColumn('Net Out', '_NET_OUT_'),
+ GraphColumn('Net In', '_NET_IN_')],
+ [GraphColumn('Disk Read', '_DISK_READ_'),
+ GraphColumn('Disk Write', '_DISK_WRITE_')],
+ [GraphColumn('CPU Usage', '_CPU_'),
+ GraphColumn('Memory Usage', '_MEM_')],]
+
+ window = sg.Window('PSG System Dashboard',
+ keep_on_top=True,
+ auto_size_buttons=False,
+ grab_anywhere=True,
+ no_titlebar=True,
+ default_button_element_size=(12, 1),
+ return_keyboard_events=True,
+ alpha_channel=ALPHA,
+ use_default_focus=False,
+ ).Layout(layout).Finalize()
+
+ # setup graphs & initial values
+ netio = psutil.net_io_counters()
+ net_graph_in = DashGraph(window.FindElement('_NET_IN_GRAPH_'), netio.bytes_recv, '#23a0a0')
+ net_graph_out = DashGraph(window.FindElement('_NET_OUT_GRAPH_'), netio.bytes_sent, '#56d856')
+
+
+ diskio = psutil.disk_io_counters()
+ disk_graph_write = DashGraph(window.FindElement('_DISK_WRITE_GRAPH_'), diskio.write_bytes, '#be45be')
+ disk_graph_read = DashGraph(window.FindElement('_DISK_READ_GRAPH_'), diskio.read_bytes, '#5681d8')
+
+ cpu_usage_graph = DashGraph(window.FindElement('_CPU_GRAPH_'), 0, '#d34545')
+ mem_usage_graph = DashGraph(window.FindElement('_MEM_GRAPH_'), 0, '#BE7C29')
+
+ print(psutil.cpu_percent(percpu=True))
+ # ---------------- main loop ----------------
+ while (True):
+ # --------- Read and update window once a second--------
+ event, values = window.Read(timeout=1000)
+ if event in (None, 'Exit'): # Be nice and give an exit, expecially since there is no titlebar
+ break
+ # ----- Network Graphs -----
+ netio = psutil.net_io_counters()
+ write_bytes = net_graph_out.graph_value(netio.bytes_sent)
+ read_bytes = net_graph_in.graph_value(netio.bytes_recv)
+ Txt_Update(window, '_NET_OUT_TXT_', 'Net out {}'.format(human_size(write_bytes)))
+ Txt_Update(window, '_NET_IN_TXT_', 'Net In {}'.format(human_size(read_bytes)))
+ # ----- Disk Graphs -----
+ diskio = psutil.disk_io_counters()
+ write_bytes = disk_graph_write.graph_value(diskio.write_bytes)
+ read_bytes = disk_graph_read.graph_value(diskio.read_bytes)
+ Txt_Update(window, '_DISK_WRITE_TXT_', 'Disk Write {}'.format(human_size(write_bytes)))
+ Txt_Update(window, '_DISK_READ_TXT_', 'Disk Read {}'.format(human_size(read_bytes)))
+ # ----- CPU Graph -----
+ cpu = psutil.cpu_percent(0)
+ cpu_usage_graph.graph_percentage_abs(cpu)
+ Txt_Update(window, '_CPU_TXT_', '{0:2.0f}% CPU Used'.format(cpu))
+ # ----- Memory Graph -----
+ mem_used = psutil.virtual_memory().percent
+ mem_usage_graph.graph_percentage_abs(mem_used)
+ Txt_Update(window, '_MEM_TXT_', '{}% Memory Used'.format(mem_used))
+
+if __name__ == "__main__":
+ # the clever Red X graphic
+ red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+
+ main()
+ sys.exit(69)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Disable_Elements.py b/DemoPrograms old/Demo_Disable_Elements.py
new file mode 100644
index 000000000..4f4f77780
--- /dev/null
+++ b/DemoPrograms old/Demo_Disable_Elements.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+sg.ChangeLookAndFeel('Dark')
+sg.SetOptions(element_padding=(0, 0))
+
+layout = [
+ [sg.T('Notes:', pad=((3, 0), 0)), sg.In(size=(44, 1), background_color='white', text_color='black', key='notes')],
+ [sg.T('Output:', pad=((3, 0), 0)), sg.T('', size=(44, 1), text_color='white', key='output')],
+ [sg.CBox('Checkbox:', default=True, pad=((3, 0), 0), disabled=True, key='cbox'), sg.Listbox((1,2,3,4),size=(8,3),disabled=True, key='listbox'),
+ sg.Radio('Radio 1', default=True, group_id='1', disabled=True, key='radio1'), sg.Radio('Radio 2', default=False, group_id='1', disabled=True, key='radio2')],
+ [sg.Spin((1,2,3,4),1,disabled=True, key='spin'), sg.OptionMenu((1,2,3,4),disabled=True, key='option'), sg.Combo(values=(1,2,3,4),disabled=True,key='combo')],
+ [sg.Multiline('Multiline', size=(20,3),disabled=True, key='multi')],
+ [sg.Slider((1,10), size=(20,20), orientation='h', disabled=True, key='slider')],
+ [sg.Button('Enable', button_color=('white', 'black')),
+ sg.Button('Disable', button_color=('white', 'black')),
+ sg.Button('Reset', button_color=('white', '#9B0023'), key='reset'),
+ sg.Button('Values', button_color=('white', 'springgreen4')),
+ sg.Button('Exit', disabled=True, button_color=('white', '#00406B'), key='exit')]]
+
+window = sg.Window("Disable Elements Demo", default_element_size=(12, 1), text_justification='r', auto_size_text=False,
+ auto_size_buttons=False, keep_on_top=True, grab_anywhere=False,
+ default_button_element_size=(12, 1)).Layout(layout).Finalize()
+
+key_list = 'cbox', 'listbox', 'radio1', 'radio2', 'spin', 'option', 'combo', 'reset', 'notes', 'multi', 'slider', 'exit'
+
+for key in key_list: window.FindElement(key).Update(disabled=True) # don't do this kind of for-loop
+
+while True:
+ event, values = window.Read()
+ if event in (None, 'exit'):
+ break
+ elif event == 'Disable':
+ for key in key_list: window.FindElement(key).Update(disabled=True)
+ elif event == 'Enable':
+ for key in key_list: window.FindElement(key).Update(disabled=False)
+ elif event == 'Values':
+ sg.Popup(values, keep_on_top=True)
+
+sys.exit(0)
diff --git a/DemoPrograms old/Demo_DuplicateFileFinder.py b/DemoPrograms old/Demo_DuplicateFileFinder.py
new file mode 100644
index 000000000..7e7045c69
--- /dev/null
+++ b/DemoPrograms old/Demo_DuplicateFileFinder.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import hashlib
+import os
+
+
+# ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== #
+# Function to de-duplicate the folder passed in #
+# --------------------------------------------------------------------------- #
+def FindDuplicatesFilesInFolder(path):
+ shatab = []
+ total = 0
+ small_count, dup_count, error_count = 0,0,0
+ pngdir = path
+ if not os.path.exists(path):
+ sg.Popup('Duplicate Finder', '** Folder doesn\'t exist***', path)
+ return
+ pngfiles = os.listdir(pngdir)
+ total_files = len(pngfiles)
+ for idx, f in enumerate(pngfiles):
+ if not sg.OneLineProgressMeter('Counting Duplicates', idx + 1, total_files, 'Counting Duplicate Files'):
+ break
+ total += 1
+ fname = os.path.join(pngdir, f)
+ if os.path.isdir(fname):
+ continue
+ x = open(fname, "rb").read()
+
+ m = hashlib.sha256()
+ m.update(x)
+ f_sha = m.digest()
+ if f_sha in shatab:
+ # uncomment next line to remove duplicate files
+ # os.remove(fname)
+ dup_count += 1
+ # sg.Print(f'Duplicate file - {f}') # cannot current use sg.Print with Progress Meter
+ continue
+ shatab.append(f_sha)
+
+ msg = '{} Files processed\n {} Duplicates found'.format(total_files, dup_count)
+ sg.Popup('Duplicate Finder Ended', msg)
+
+# ====____====____==== Pseudo-MAIN program ====____====____==== #
+# This is our main-alike piece of code #
+# + Starts up the GUI #
+# + Gets values from GUI #
+# + Runs DeDupe_folder based on GUI inputs #
+# ------------------------------------------------------------- #
+if __name__ == '__main__':
+
+ source_folder = None
+ source_folder = sg.PopupGetFolder('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in')
+ if source_folder is not None:
+ FindDuplicatesFilesInFolder(source_folder)
+ else:
+ sg.PopupCancel('Cancelling', '*** Cancelling ***')
+ exit(0)
diff --git a/DemoPrograms old/Demo_EXE_Maker.py b/DemoPrograms old/Demo_EXE_Maker.py
new file mode 100644
index 000000000..9d751c6f8
--- /dev/null
+++ b/DemoPrograms old/Demo_EXE_Maker.py
@@ -0,0 +1,75 @@
+import PySimpleGUI as sg
+import subprocess
+from shutil import copyfile
+import shutil
+import os
+
+def Launcher():
+ sg.ChangeLookAndFeel('LightGreen')
+
+ layout = [[sg.T('PyInstaller EXE Creator', font='Any 15')],
+ [sg.T('Source Python File'), sg.In(key='_sourcefile_', size=(45,1)), sg.FileBrowse(file_types=(("Python Files", "*.py"),))],
+ [sg.T('Icon File'), sg.In(key='_iconfile_', size=(45,1)), sg.FileBrowse(file_types=(("Icon Files", "*.ico"),))],
+ [sg.Frame('Output', font='Any 15',layout= [[sg.Output(size=(65, 15), font='Courier 10')]])],
+ [sg.ReadFormButton('Make EXE',bind_return_key=True),
+ sg.SimpleButton('Quit', button_color=('white','firebrick3')),]]
+
+ window = sg.Window('PySimpleGUI EXE Maker',
+ auto_size_text=False,
+ auto_size_buttons=False,
+ default_element_size=(20,1,),
+ text_justification='right')
+
+ window.Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ (button, values) = window.Read()
+ if button in ('Quit', None):
+ break # exit button clicked
+
+ source_file = values['_sourcefile_']
+ icon_file = values['_iconfile_']
+
+ icon_option = '-i "{}"'.format(icon_file) if icon_file else ''
+ source_path, source_filename = os.path.split(source_file)
+ workpath_option = '--workpath "{}"'.format(source_path)
+ dispath_option = '--distpath "{}"'.format(source_path)
+ specpath_option = '--specpath "{}"'.format(source_path)
+ folder_to_remove = os.path.join(source_path,source_filename[:-3])
+ file_to_remove = os.path.join(source_path, source_filename[:-3]+'.spec')
+ command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format(source_file, icon_option, workpath_option, dispath_option, specpath_option)
+
+ if button == 'Make EXE':
+ try:
+ print(command_line)
+ print('Making EXE... this will take a while.. the program has NOT locked up...')
+ window.Refresh()
+ # print('Running command {}'.format(command_line))
+ runCommand(command_line)
+ shutil.rmtree(folder_to_remove)
+ os.remove(file_to_remove)
+ print('**** DONE ****')
+ except:
+ sg.PopupError('Something went wrong')
+
+
+def runCommand(cmd, timeout=None):
+ """ run shell command
+
+ @param cmd: command to execute
+ @param timeout: timeout for command execution
+
+ @return: (return code from command, command output)
+ """
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ output = ''
+
+ out, err = p.communicate()
+ p.wait(timeout)
+
+ return (out, err)
+
+if __name__ == '__main__':
+ Launcher()
+
diff --git a/DemoPrograms old/Demo_Event_Callback_Simulation.py b/DemoPrograms old/Demo_Event_Callback_Simulation.py
new file mode 100644
index 000000000..d36423689
--- /dev/null
+++ b/DemoPrograms old/Demo_Event_Callback_Simulation.py
@@ -0,0 +1,53 @@
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+# import PySimpleGUIWx as sg
+
+'''
+ Event Callback Simulation
+
+ This design pattern simulates callbacks for events.
+ This is NOT the "normal" way things work in PySimpleGUI and is an architecture that is actively discouraged
+ Unlike tkinter, Qt, etc, PySimpleGUI does not utilize callback
+ functions as a mechanism for communicating when button presses or other events happen.
+ BUT, should you want to quickly convert some existing code that does use callback functions, then this
+ is one way to do a "quick and dirty" port to PySimpleGUI.
+'''
+
+# The callback functions
+# These callbacks all display a message in a non-blocking way and immediately return
+def button1(event, values):
+ sg.popup_quick_message('Button 1 callback', background_color='red', text_color='white')
+
+def button2(event, values):
+ sg.popup_quick_message('Button 2 callback', background_color='green', text_color='white')
+
+def catch_all(event, values):
+ sg.popup_quick_message(f'An unplanned event = "{event}" happend', background_color='blue', text_color='white', auto_close_duration=6)
+
+# Lookup dictionary that maps event to function to call. In this case, only 2 event have defined callbacks
+func_dict = {'1':button1, '2':button2}
+
+# Layout the design of the GUI
+layout = [[sg.Text('Please click a button')],
+ [sg.Button('1'), sg.Button('2'), sg.Button('Not defined', key='-MY-KEY-'), sg.Quit()]]
+
+# Show the Window to the user
+window = sg.Window('Button callback example', layout)
+
+# Event loop. Read buttons, make callbacks
+while True:
+ # Read the Window
+ event, values = window.read()
+ # Lookup event in function dictionary and call the function, passing in the event and values variables
+ try:
+ func_dict[event](event, values) # Call function with event and values
+ except:
+ catch_all(event, values)
+ # See if should close the window
+ if event in ('Quit', None): # normally this is done IMMEDIATELY after the read
+ break
+
+window.close()
+
+# All done!
+sg.popup_auto_close('Done... this window auto closes')
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Fill_Form.py b/DemoPrograms old/Demo_Fill_Form.py
new file mode 100644
index 000000000..08e249297
--- /dev/null
+++ b/DemoPrograms old/Demo_Fill_Form.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+def Everything():
+ sg.ChangeLookAndFeel('TanBlue')
+
+ column1 = [
+ [sg.Text('Column 1', background_color=sg.DEFAULT_BACKGROUND_COLOR, justification='center', size=(10, 1))],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1', key='spin1')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3', key='spin3')]]
+
+ layout = [
+ [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))],
+ [sg.Text('Here is some text.... and a place to enter text')],
+ [sg.InputText('This is my text', key='in1', do_not_clear=True)],
+ [sg.Checkbox('Checkbox', key='cb1'), sg.Checkbox('My second checkbox!', key='cb2', default=True)],
+ [sg.Radio('My first Radio! ', "RADIO1", key='rad1', default=True),
+ sg.Radio('My second Radio!', "RADIO1", key='rad2')],
+ [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3),
+ key='multi1', do_not_clear=True),
+ sg.Multiline(default_text='A second multi-line', size=(35, 3), key='multi2', do_not_clear=True)],
+ [sg.InputCombo(('Combobox 1', 'Combobox 2'), key='combo', size=(20, 1)),
+ sg.Slider(range=(1, 100), orientation='h', size=(34, 20), key='slide1', default_value=85)],
+ [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'), key='optionmenu')],
+ [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3), key='listbox'),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, key='slide2', ),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75, key='slide3', ),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10, key='slide4'),
+ sg.Column(column1, background_color='gray34')],
+ [sg.Text('_' * 80)],
+ [sg.Text('Choose A Folder', size=(35, 1))],
+ [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'),
+ sg.InputText('Default Folder', key='folder', do_not_clear=True), sg.FolderBrowse()],
+ [sg.Button('Exit'),
+ sg.Text(' ' * 40), sg.Button('SaveSettings'), sg.Button('LoadSettings')]
+ ]
+
+ window = sg.Window('Form Fill Demonstration', default_element_size=(40, 1), grab_anywhere=False)
+ # button, values = window.LayoutAndRead(layout, non_blocking=True)
+ window.Layout(layout)
+
+ while True:
+ event, values = window.Read()
+
+ if event == 'SaveSettings':
+ filename = sg.PopupGetFile('Save Settings', save_as=True, no_window=True)
+ window.SaveToDisk(filename)
+ # save(values)
+ elif event == 'LoadSettings':
+ filename = sg.PopupGetFile('Load Settings', no_window=True)
+ window.LoadFromDisk(filename)
+ # load(form)
+ elif event in ('Exit', None):
+ break
+
+ # window.CloseNonBlocking()
+
+
+if __name__ == '__main__':
+ Everything()
diff --git a/DemoPrograms old/Demo_Floating_Toolbar.py b/DemoPrograms old/Demo_Floating_Toolbar.py
new file mode 100644
index 000000000..14312f6a6
--- /dev/null
+++ b/DemoPrograms old/Demo_Floating_Toolbar.py
@@ -0,0 +1,44 @@
+import PySimpleGUI as sg
+import sys
+
+button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer')
+
+house64='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'
+
+cpu64='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'
+
+timer64='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'
+
+close64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEQ0lEQVR42r2XW2wbRRSG/1177TgkdkyoS4shaaWogVIKRAXUVn4BgRBEIRBSkSK1lAakPhTxABJSK6BEtAoXCUHEWwWi4oEXUAVvRUASSBuJliAh5QJp6hrspoGQi69r73LO7Npu6kvsBGek0ezOrvf79szsmbG0D2iwAN8DaMQaFA0YHQFaLwCX6TQuHQAuNtjR2PawD05LZeFzKeC7b/txPoLxU8Aj1BVkAf1wqw/uejeU9RsASaqYQGp+Dv8EAvjgdD9OAg9S14gQOPKED1XNWyv7+lT0VArxiVH0fCUEOqjr3JoKcImN/pYW2EOnQyUJTESBJkdpgGkV8Cj/owDDdx59A8Mf92FT+GpR+KSlBrt6ehE6+hL0pLp6AYbvfusE5FontFgUZ989UVAiDU+X0OsvQ0/EVy4g4MeOQ3a6Mn38wKHet3MkrofzZJMsFlzpeRVaeLF8ASPsb8Javy7nDXRVxdA7x7FpIZQXnrlP0yDJMoKvHVpZBKq23Qv3M8/nzQt6PIah93qhRxaLwvPNhbLmgGP7Drg694mHlVqKwcsWEBItD8DVvleM6WrhRQXUwBSsnpthvclDY++BZLdnflS9YxecrZ2QFGVZePDIYcq5yWuGK47k39NIzlCdDkHxNuYXiJzrz/xIrr4BFpdbfAFyTS1CSi1uf7IDrqeeheyoLihxubsD2sI8UuEFaItUKfen5mahRcLZl7nft7xAvjIQs+GFP2cLCmjRCL5p3oDN6nzR56xIYDl4ORJlCwyqDnT7Z5aFL5G4w4vN8dnVCwymatA9daVkeCkSJQv8qDtxcDKYF86AwKEuSDYbvB+doq/DlnMPJ6uvmzfmSJQk0E9D+OLVcEG4f38bwgNnxLmz9Wl4+z6HZLXm3JuYHMfE7i0ri8Ck3Y3Hx4L0lvYl8Et7H0Xk7NJ7Xe1d8H74GX2/2YyZmv8XY3euo4SUXJkAFyvtEbdc+CsDn2r3Ifrrz3nHvW7Pftzy/kmxdhSCly2Qlmj66Xf88dB2qP6LRme+jauuo67rIDyvHMN4i1esmvlK6QIUTrEISbKxDnDlPkk2BK6VIDhXXaddP6Vk0H6A9wSUn0WKFn2lCgiYbDEmFVXJYjWOuU1LcHudgAASSLS0FnD4dV4TksYxNEOqsMDwgAAxELToSFZFfGaiVWzGNV6MWM4Uyc5OE8wQCr2AqwmxIuoJowX3k5CjZSd6vvxhqcBj921Fc2g8C2Mwzf5sax7zNZZjSdkcCg6/EEgacAYzlLZvRk1kW7rm39iELwZHsgLPATN311rqb7trG+65dT2FXTEg4o1NoDinZKOYQ8ICFo4ADwMJpEwBDrnKIU+YMqZQ0pAbC4QwODwCf0Rd/BQ4IATagM46oI+CeiNPPVS40EDF6M/pJ78Ap+n0PL8Cp7sGs9asgQSFDLxBmKJ6STKBVSbcZsa10gKcJHi/Hv0PWqbBbaFH/AEAAAAASUVORK5CYII='
+
+
+def main():
+
+ toolbar_buttons = [[sg.Button('', image_data=close64,button_color=('white', 'black'), pad=(0,0), key='-CLOSE-'),
+ sg.Button('', image_data=timer64, button_color=('white', 'black'), pad=(0, 0), key='-TIMER-'),
+ sg.Button('', image_data=house64, button_color=('white', 'black'), pad=(0, 0), key='-HOUSE-'),
+ sg.Button('', image_data=cpu64, button_color=('white', 'black'), pad=(0,0), key='-CPU-'),]]
+
+ # layout = toolbar_buttons
+ layout = [[sg.Column( toolbar_buttons, background_color='black')]]
+
+ window = sg.Window('Toolbar', layout, no_titlebar=True, grab_anywhere=True, background_color='black', margins=(0,0))
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = window.read()
+ print(button)
+ if button == '-CLOSE-' or button is None:
+ break # exit button clicked
+ elif button == '-TIMER-':
+ print('Timer Button') # add your call to launch a timer program
+ elif button == '-CPU-':
+ print('CPU Button') # add your call to launch a CPU measuring utility
+ elif button == '-HOUSE-':
+ print('Home Button')
+
+ window.close()
+
+if __name__ == '__main__':
+ main()
+
diff --git a/DemoPrograms old/Demo_Font_Previewer.py b/DemoPrograms old/Demo_Font_Previewer.py
new file mode 100644
index 000000000..1c7eeb636
--- /dev/null
+++ b/DemoPrograms old/Demo_Font_Previewer.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+from tkinter import font
+import tkinter
+root = tkinter.Tk()
+fonts = list(font.families())
+fonts.sort()
+root.destroy()
+
+sg.ChangeLookAndFeel('Black')
+
+layout = [[ sg.Text('My Text Element',
+ size=(20,1),
+ auto_size_text=False,
+ click_submits=True,
+ relief=sg.RELIEF_GROOVE,
+ font = 'Courier` 25',
+ text_color='#FF0000',
+ background_color='white',
+ justification='center',
+ pad=(5,3),
+ key='_text_',
+ tooltip='This is a text element',
+ ) ],
+ [sg.Listbox(fonts, size=(30,20), change_submits=True, key='_list_')],
+ [sg.Input(key='_in_')],
+ [ sg.Button('Read', bind_return_key=True), sg.Exit()]]
+
+window = sg.Window('My new window',
+ # grab_anywhere=True,
+ # force_toplevel=True,
+ ).Layout(layout)
+
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None or event == 'Exit':
+ break
+ text_elem = window.FindElement('_text_')
+ print(event, values)
+ if values['_in_'] != '':
+ text_elem.Update(font=values['_in_'])
+ else:
+ text_elem.Update(font=(values['_list_'][0], 25))
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Font_Sizer.py b/DemoPrograms old/Demo_Font_Sizer.py
new file mode 100644
index 000000000..7050160ec
--- /dev/null
+++ b/DemoPrograms old/Demo_Font_Sizer.py
@@ -0,0 +1,30 @@
+
+# Testing async form, see if can have a slider
+# that adjusts the size of text displayed
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+fontSize = 12
+layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin'),
+ sg.Slider(range=(6,172), orientation='h', size=(10,20), change_submits=True, key='slider', font=('Helvetica 20')), sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
+sz = fontSize
+window = sg.Window("Font size selector", grab_anywhere=False)
+window.Layout(layout)
+while True:
+ event, values= window.Read()
+ if event is None or event == 'Quit':
+ break
+ sz_spin = int(values['spin'])
+ sz_slider = int(values['slider'])
+ sz = sz_spin if sz_spin != fontSize else sz_slider
+ if sz != fontSize:
+ fontSize = sz
+ font = "Helvetica " + str(fontSize)
+ window.FindElement('text').Update(font=font)
+ window.FindElement('slider').Update(sz)
+ window.FindElement('spin').Update(sz)
+
+print("Done.")
diff --git a/DemoPrograms old/Demo_Font_String.py b/DemoPrograms old/Demo_Font_String.py
new file mode 100644
index 000000000..b97c0f679
--- /dev/null
+++ b/DemoPrograms old/Demo_Font_String.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[sg.Text('This is my sample text',size=(20,1), key='_text_') ],
+ [sg.CB('Bold', key='_bold_', change_submits=True),
+ sg.CB('Italics', key='_italics_', change_submits=True),
+ sg.CB('Underline', key='_underline_', change_submits=True)],
+ [sg.Slider((6,50), default_value=12, size=(14,20), orientation='h', key='_slider_', change_submits=True),
+ sg.Text('Font size')],
+ [sg.Text('Font string = '), sg.Text('', size=(25,1), key='_fontstring_')],
+ [ sg.Button('Exit')]]
+
+window = sg.Window('Font string builder').Layout(layout)
+
+text_elem = window.FindElement('_text_')
+while True: # Event Loop
+ event, values = window.Read()
+ if event in (None, 'Exit'):
+ break
+ font_string = 'Helvitica '
+ font_string += str(values['_slider_'])
+ if values['_bold_']:
+ font_string += ' bold'
+ if values['_italics_']:
+ font_string += ' italic'
+ if values['_underline_']:
+ font_string += ' underline'
+ text_elem.Update(font=font_string)
+ window.FindElement('_fontstring_').Update('"'+font_string+'"')
+ print(event, values)
diff --git a/DemoPrograms old/Demo_GoodColors.py b/DemoPrograms old/Demo_GoodColors.py
new file mode 100644
index 000000000..8ea1ba9cc
--- /dev/null
+++ b/DemoPrograms old/Demo_GoodColors.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+def main():
+ # ------- Make a new Window ------- #
+ window = sg.Window('GoodColors', auto_size_text=True, default_element_size=(30,2))
+ window.AddRow(sg.Text('Having trouble picking good colors? Try one of the colors defined by PySimpleGUI'))
+ window.AddRow(sg.Text('Here come the good colors as defined by PySimpleGUI'))
+
+ #===== Show some nice BLUE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
+ text_color = sg.YELLOWS[0]
+ buttons = (sg.Button('BLUES[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.BLUES))
+ window.AddRow(sg.T('Button Colors Using PySimpleGUI.BLUES'))
+ window.AddRow(*buttons)
+ window.AddRow(sg.Text('_' * 100, size=(65, 1)))
+
+ #===== Show some nice PURPLE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
+ buttons = (sg.Button('PURPLES[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.PURPLES))
+ window.AddRow(sg.T('Button Colors Using PySimpleGUI.PURPLES'))
+ window.AddRow(*buttons)
+ window.AddRow(sg.Text('_' * 100, size=(65, 1)))
+
+ #===== Show some nice GREEN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
+ buttons = (sg.Button('GREENS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.GREENS))
+ window.AddRow(sg.T('Button Colors Using PySimpleGUI.GREENS'))
+ window.AddRow(*buttons)
+ window.AddRow(sg.Text('_' * 100, size=(65, 1)))
+
+ #===== Show some nice TAN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
+ text_color = sg.GREENS[0] # let's use GREEN text on the tan
+ buttons = (sg.Button('TANS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.TANS))
+ window.AddRow(sg.T('Button Colors Using PySimpleGUI.TANS'))
+ window.AddRow(*buttons)
+ window.AddRow(sg.Text('_' * 100, size=(65, 1)))
+
+ #===== Show some nice YELLOWS colors with black text ===== ===== ===== ===== ===== ===== =====#
+ text_color = 'black' # let's use black text on the tan
+ buttons = (sg.Button('YELLOWS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.YELLOWS))
+ window.AddRow(sg.T('Button Colors Using PySimpleGUI.YELLOWS'))
+ window.AddRow(*buttons)
+ window.AddRow(sg.Text('_' * 100, size=(65, 1)))
+
+
+ #===== Add a click me button for fun and SHOW the window ===== ===== ===== ===== ===== ===== =====#
+ window.AddRow(sg.Button('Click ME!'))
+ event, values = window.Read() # show it!
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Google_TTS.py b/DemoPrograms old/Demo_Google_TTS.py
new file mode 100644
index 000000000..ee8557bb1
--- /dev/null
+++ b/DemoPrograms old/Demo_Google_TTS.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+from gtts import gTTS
+from pygame import mixer
+import time
+import os
+
+'''
+ Simple demonstration of using Google Text to Speech
+ Get a multi-line string
+ Convert to speech
+ Play back the speech
+
+ Note that there are 2 temp files created. The program tries to delete them but will fail on one of them
+'''
+
+layout = [[sg.Text('What would you like me to say?')],
+ [sg.Multiline(size=(60,10), enter_submits=True)],
+ [sg.Button('Speak', bind_return_key=True), sg.Exit()]]
+
+window = sg.Window('Google Text to Speech').Layout(layout)
+
+i = 0
+mixer.init()
+while True:
+ event, values = window.Read()
+ if event is None or event == 'Exit':
+ break
+ # Get the text and convert to mp3 file
+ tts = gTTS(text=values[0], lang='en',slow=False)
+ tts.save('speech{}.mp3'.format(i%2))
+ # playback the speech
+ mixer.music.load('speech{}.mp3'.format(i%2))
+ mixer.music.play()
+ # wait for playback to end
+ while mixer.music.get_busy():
+ time.sleep(.1)
+ mixer.stop()
+ i += 1
+
+# try to remove the temp files. You'll likely be left with 1 to clean up
+try:
+ os.remove('speech0.mp3')
+except:
+ pass
+try:
+ os.remove('speech1.mp3')
+except:
+ pass
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Graph_Ball_Game.py b/DemoPrograms old/Demo_Graph_Ball_Game.py
new file mode 100644
index 000000000..e1c3c642e
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Ball_Game.py
@@ -0,0 +1,97 @@
+# import PySimpleGUIWeb as sg
+import PySimpleGUI as sg
+import pymunk
+import random
+import socket
+
+"""
+ Demo that shows integrating PySimpleGUI with the pymunk library. This combination
+ of PySimpleGUI and pymunk could be used to build games.
+ Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
+"""
+
+class Ball():
+ def __init__(self, x, y, r, graph_elem, *args, **kwargs):
+ mass = 10
+ self.body = pymunk.Body(mass,
+ pymunk.moment_for_circle(mass, 0, r, (0, 0))) # Create a Body with mass and moment
+ self.body.position = x, y
+ self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) # Create a box shape and attach to body
+ self.shape.elasticity = 0.99999
+ self.shape.friction = 0.8
+ self.gui_circle_figure = None
+ self.graph_elem = graph_elem
+
+ def move(self):
+ self.graph_elem.RelocateFigure(self.gui_circle_figure, self.body.position[0], ball.body.position[1])
+
+
+
+class Playfield():
+ def __init__(self, graph_elem):
+ self.space = pymunk.Space()
+ self.space.gravity = 0, 200
+ self.add_wall((0, 400), (600, 400)) # ground
+ self.add_wall((0, 0), (0, 600)) # Left side
+ self.add_wall((600, 0), (600, 400)) # right side
+ self.arena_balls = [] # type: [] Ball
+ self.graph_elem = graph_elem # type: sg.Graph
+
+
+ def add_wall(self, pt_from, pt_to):
+ body = pymunk.Body(body_type=pymunk.Body.STATIC)
+ ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0)
+ ground_shape.friction = 0.8
+ ground_shape.elasticity = .99
+ self.space.add(ground_shape)
+
+ def add_random_balls(self):
+ for i in range(1, 200):
+ x = random.randint(0, 600)
+ y = random.randint(0, 400)
+ r = random.randint(1, 10)
+ self.add_ball(x,y,r)
+
+ def add_ball(self, x, y, r, fill_color='black', line_color='red'):
+ ball = Ball(x, y, r, self.graph_elem)
+ self.arena_balls.append(ball)
+ area.space.add(ball.body, ball.shape)
+ ball.gui_circle_figure = self.graph_elem.DrawCircle((x, y), r, fill_color=fill_color, line_color=line_color)
+ return ball
+
+ def shoot_a_ball(self, x, y, r, vector=(-10, 0), fill_color='black', line_color='red'):
+ ball = self.add_ball(x,y,r, fill_color=fill_color, line_color=line_color )
+ # ball.shape.surface_velocity=10
+ ball.body.apply_impulse_at_local_point(100*pymunk.Vec2d(vector))
+
+# ------------------- Build and show the GUI Window -------------------
+graph_elem = sg.Graph((600, 400), (0, 400), (600, 0), enable_events=True, key='_GRAPH_', background_color='lightblue')
+
+layout = [[sg.Text('Ball Test'), sg.T('My IP {}'.format(socket.gethostbyname(socket.gethostname())))],
+ [graph_elem],
+ [sg.B('Kick'), sg.B('Player 1 Shoot', size=(15,2)),sg.B('Player 2 Shoot', size=(15,2)), sg.Button('Exit')]]
+
+window = sg.Window('Window Title', layout, disable_close=True)
+
+area = Playfield(graph_elem)
+# area.add_random_balls()
+
+# ------------------- GUI Event Loop -------------------
+while True: # Event Loop
+ event, values = window.Read(timeout=10)
+ # print(event, values)
+ if event in (None, 'Exit'):
+ break
+ area.space.step(0.01)
+
+ if event == 'Player 2 Shoot':
+ area.shoot_a_ball(555, 200, 5, (-10,0), fill_color='green', line_color='green')
+ elif event == 'Player 1 Shoot':
+ area.shoot_a_ball(10, 200, 5, (10,0))
+
+ for ball in area.arena_balls:
+ if event == 'Kick':
+ ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(1,200)
+ ball.move()
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Graph_Drag_Rectangle.py b/DemoPrograms old/Demo_Graph_Drag_Rectangle.py
new file mode 100644
index 000000000..b23a795ff
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Drag_Rectangle.py
@@ -0,0 +1,53 @@
+import PySimpleGUI as sg
+
+"""
+ Demo - Drag a rectangle to draw it
+
+ This demo shows how to use a Graph Element to (optionally) display an image and then use the
+ mouse to "drag a rectangle". This is sometimes called a rubber band and is an operation you
+ see in things like editors
+"""
+
+
+# image_file = r'Color-names.png'
+image_file = None # image is optional
+
+layout = [[sg.Graph(
+ canvas_size=(400, 400),
+ graph_bottom_left=(0, 400),
+ graph_top_right=(400, 0),
+ key="-GRAPH-",
+ change_submits=True, # mouse click events
+ drag_submits=True),],
+ [sg.Text("", key="info", size=(60, 1))]]
+
+window = sg.Window("draw rect on image", layout, finalize=True)
+# get the graph element for ease of use later
+graph = window["-GRAPH-"] # type: sg.Graph
+
+graph.DrawImage(image_file, location=(0,0)) if image_file else None
+dragging = False
+start_point = end_point = prior_rect = None
+
+while True:
+ event, values = window.Read()
+ if event is None:
+ break # exit
+ if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
+ x, y = values["-GRAPH-"]
+ if not dragging:
+ start_point = (x, y)
+ dragging = True
+ else:
+ end_point = (x, y)
+ if prior_rect:
+ graph.DeleteFigure(prior_rect)
+ if None not in (start_point, end_point):
+ prior_rect = graph.DrawRectangle(start_point, end_point, line_color='red')
+ elif event.endswith('+UP'): # The drawing has ended because mouse up
+ info = window.Element("info")
+ info.Update(value=f"grabbed rectangle from {start_point} to {end_point}")
+ start_point, end_point = None, None # enable grabbing a new rect
+ dragging = False
+ else:
+ print("unhandled event", event, values)
diff --git a/DemoPrograms old/Demo_Graph_Drawing.py b/DemoPrograms old/Demo_Graph_Drawing.py
new file mode 100644
index 000000000..8c11ced1a
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Drawing.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0,0), graph_top_right=(400, 400), background_color='red', key='graph')],
+ [sg.T('Change circle color to:'), sg.Button('Red'), sg.Button('Blue'), sg.Button('Move')]]
+
+window = sg.Window('Graph test').Layout(layout).Finalize()
+
+graph = window.FindElement('graph')
+circle =graph .DrawCircle((75,75), 25, fill_color='black',line_color='white')
+point = graph.DrawPoint((75,75), 10, color='green')
+oval = graph.DrawOval((25,300), (100,280), fill_color='purple', line_color='purple' )
+rectangle = graph.DrawRectangle((25,300), (100,280), line_color='purple' )
+line = graph.DrawLine((0,0), (100,100))
+arc = graph.DrawArc((0,0), (400,400), 160, 10, style='arc' ,arc_color='blue')
+while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ if event in ('Blue', 'Red'):
+ graph.TKCanvas.itemconfig(circle, fill=event)
+ elif event == 'Move':
+ graph.MoveFigure(point, 10,10)
+ graph.MoveFigure(circle, 10,10)
+ graph.MoveFigure(oval, 10,10)
+ graph.MoveFigure(rectangle, 10,10)
+ graph.MoveFigure(arc, 10,10)
diff --git a/DemoPrograms old/Demo_Graph_Element.py b/DemoPrograms old/Demo_Graph_Element.py
new file mode 100644
index 000000000..67f28ac55
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Element.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import ping
+from threading import Thread
+import time
+
+
+STEP_SIZE=1
+SAMPLES = 1000
+CANVAS_SIZE = (1000,500)
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
+def ping_thread(args):
+ global g_exit, g_response_time
+ while not g_exit:
+ g_response_time = ping.quiet_ping('google.com', timeout=1000)
+
+def main():
+ global g_exit, g_response_time
+
+ # start ping measurement thread
+ thread = Thread(target=ping_thread, args=(None,))
+ thread.start()
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0))
+
+ layout = [ [sg.T('Ping times to Google.com', font='Any 12'), sg.Quit(pad=((100,0), 0), button_color=('white', 'black'))],
+ [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,500),background_color='black', key='graph')],]
+
+ window = sg.Window('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False).Layout(layout)
+
+ graph = window.FindElement('graph')
+
+ prev_response_time = None
+ i=0
+ prev_x, prev_y = 0, 0
+ while True:
+ event, values = window.Read(timeout=200)
+ if event == 'Quit' or event is None:
+ break
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ new_x, new_y = i, g_response_time[0]
+ prev_response_time = g_response_time
+ if i >= SAMPLES:
+ graph.Move(-STEP_SIZE,0)
+ prev_x = prev_x - STEP_SIZE
+ graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
+ # window.FindElement('graph').DrawPoint((new_x, new_y), color='red')
+ prev_x, prev_y = new_x, new_y
+ i += STEP_SIZE if i < SAMPLES else 0
+
+ # tell thread we're done. wait for thread to exit
+ g_exit = True
+ thread.join()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Graph_Element_Bar_Chart.py b/DemoPrograms old/Demo_Graph_Element_Bar_Chart.py
new file mode 100644
index 000000000..276e44715
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Element_Bar_Chart.py
@@ -0,0 +1,29 @@
+import PySimpleGUI as sg
+import random
+
+BAR_WIDTH = 50
+BAR_SPACING = 75
+EDGE_OFFSET = 3
+GRAPH_SIZE = (500,500)
+DATA_SIZE = (500,500)
+
+graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
+
+layout = [[sg.Text('Bar graphs using PySimpleGUI')],
+ [graph],
+ [sg.Button('OK')]]
+
+window = sg.Window('Window Title', layout)
+
+while True:
+ event, values = window.Read()
+ graph.Erase()
+ if event is None:
+ break
+
+ for i in range(7):
+ graph_value = random.randint(0, 400)
+ graph.DrawRectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
+ bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue')
+ graph.DrawText(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
+window.Close()
diff --git a/DemoPrograms old/Demo_Graph_Element_Sine_Wave.py b/DemoPrograms old/Demo_Graph_Element_Sine_Wave.py
new file mode 100644
index 000000000..dc2b73051
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Element_Sine_Wave.py
@@ -0,0 +1,51 @@
+# import PySimpleGUIWeb as sg
+# import PySimpleGUIQt as sg
+import PySimpleGUI as sg
+import math
+
+SIZE_X = 200
+SIZE_Y = 100
+NUMBER_MARKER_FREQUENCY = 25
+
+def draw_axis():
+ graph.draw_line((-SIZE_X,0), (SIZE_X, 0)) # axis lines
+ graph.draw_line((0,-SIZE_Y), (0,SIZE_Y))
+
+ for x in range(-SIZE_X, SIZE_X+1, NUMBER_MARKER_FREQUENCY):
+ graph.draw_line((x,-3), (x,3)) # tick marks
+ if x != 0:
+ graph.draw_text( str(x), (x,-10), color='green', font='Algerian 15') # numeric labels
+
+ for y in range(-SIZE_Y, SIZE_Y+1, NUMBER_MARKER_FREQUENCY):
+ graph.draw_line((-3,y), (3,y))
+ if y != 0:
+ graph.draw_text( str(y), (-10,y), color='blue')
+
+# Create the graph that will be put into the window
+graph = sg.Graph(canvas_size=(400, 400),
+ graph_bottom_left=(-(SIZE_X+5), -(SIZE_Y+5)),
+ graph_top_right=(SIZE_X+5, SIZE_Y+5),
+ background_color='white',
+ key='graph')
+# Window layout
+layout = [[sg.Text('Example of Using Math with a Graph', justification='center', size=(50,1), relief=sg.RELIEF_SUNKEN)],
+ [graph],
+ [sg.Text('y = sin(x / x2 * x1)', font='Algerian 18')],
+ [sg.Text('x1'),sg.Slider((0,200), orientation='h', enable_events=True,key='_SLIDER_')],
+ [sg.Text('x2'),sg.Slider((1,200), orientation='h', enable_events=True,key='_SLIDER2_')]]
+
+window = sg.Window('Graph of Sine Function', layout)
+
+while True:
+ event, values = window.read()
+ if event is None:
+ break
+ graph.erase()
+ draw_axis()
+ prev_x = prev_y = None
+ for x in range(-SIZE_X,SIZE_X):
+ y = math.sin(x/int(values['_SLIDER2_']))*int(values['_SLIDER_'])
+ if prev_x is not None:
+ graph.draw_line((prev_x, prev_y), (x,y), color='red')
+ prev_x, prev_y = x, y
+
diff --git a/DemoPrograms old/Demo_Graph_Noise.py b/DemoPrograms old/Demo_Graph_Noise.py
new file mode 100644
index 000000000..c18935142
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_Noise.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import random
+import sys
+
+STEP_SIZE=1
+SAMPLES = 300
+SAMPLE_MAX = 300
+CANVAS_SIZE = (300,300)
+
+
+def main():
+ global g_exit, g_response_time
+
+ layout = [[sg.T('Enter width, height of graph')],
+ [sg.In(size=(6, 1)), sg.In(size=(6, 1))],
+ [sg.Ok(), sg.Cancel()]]
+
+ window = sg.Window('Enter graph size').Layout(layout)
+ b,v = window.Read()
+ if b is None or b == 'Cancel':
+ sys.exit(69)
+ w, h = int(v[0]), int(v[1])
+ CANVAS_SIZE = (w,h)
+
+ # start ping measurement thread
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0))
+
+ layout = [ [sg.Button('Quit', button_color=('white','black'))],
+ [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
+
+ window = sg.Window('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False).Layout(layout).Finalize()
+ graph = window.FindElement('graph')
+
+ prev_response_time = None
+ i=0
+ prev_x, prev_y = 0, 0
+ graph_value = 250
+ while True:
+ # time.sleep(.2)
+ event, values = window.Read(timeout=0)
+ if event == 'Quit' or event is None:
+ break
+ graph_offset = random.randint(-10, 10)
+ graph_value = graph_value + graph_offset
+ if graph_value > SAMPLE_MAX:
+ graph_value = SAMPLE_MAX
+ if graph_value < 0:
+ graph_value = 0
+ new_x, new_y = i, graph_value
+ prev_value = graph_value
+ if i >= SAMPLES:
+ graph.Move(-STEP_SIZE,0)
+ prev_x = prev_x - STEP_SIZE
+ graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
+ # window.FindElement('graph').DrawPoint((new_x, new_y), color='red')
+ prev_x, prev_y = new_x, new_y
+ i += STEP_SIZE if i < SAMPLES else 0
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Graph__Element.py b/DemoPrograms old/Demo_Graph__Element.py
new file mode 100644
index 000000000..174ce1fb2
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph__Element.py
@@ -0,0 +1,66 @@
+import ping
+from threading import Thread
+import time
+import PySimpleGUI as sg
+
+
+STEP_SIZE=1
+SAMPLES = 6000
+CANVAS_SIZE = (6000,500)
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
+def ping_thread(args):
+ global g_exit, g_response_time
+ while not g_exit:
+ g_response_time = ping.quiet_ping('google.com', timeout=1000)
+
+def main():
+ global g_exit, g_response_time
+
+ # start ping measurement thread
+ thread = Thread(target=ping_thread, args=(None,))
+ thread.start()
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(element_padding=(0,0))
+
+ layout = [ [sg.T('Ping times to Google.com', font='Any 12'), sg.Quit(pad=((100,0), 0), button_color=('white', 'black'))],
+ [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,500),background_color='black', key='graph')],]
+
+ form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False)
+ form.Layout(layout)
+
+ form.Finalize()
+ graph = form.FindElement('graph')
+
+ prev_response_time = None
+ i=0
+ prev_x, prev_y = 0, 0
+ while True:
+ time.sleep(.2)
+
+ button, values = form.ReadNonBlocking()
+ if button == 'Quit' or values is None:
+ break
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ new_x, new_y = i, g_response_time[0]
+ prev_response_time = g_response_time
+ if i >= SAMPLES:
+ graph.Move(-STEP_SIZE,0)
+ prev_x = prev_x - STEP_SIZE
+ graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
+ # form.FindElement('graph').DrawPoint((new_x, new_y), color='red')
+ prev_x, prev_y = new_x, new_y
+ i += STEP_SIZE if i < SAMPLES else 0
+
+ # tell thread we're done. wait for thread to exit
+ g_exit = True
+ thread.join()
+
+
+if __name__ == '__main__':
+ main()
+ exit(69)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Graph_pymunk_2D_Graphics.py b/DemoPrograms old/Demo_Graph_pymunk_2D_Graphics.py
new file mode 100644
index 000000000..9dcd8e9c4
--- /dev/null
+++ b/DemoPrograms old/Demo_Graph_pymunk_2D_Graphics.py
@@ -0,0 +1,77 @@
+import PySimpleGUIWeb as sg
+# import PySimpleGUI as sg
+import pymunk
+import random
+import socket
+
+"""
+ Demo that shows integrating PySimpleGUI with the pymunk library. This combination
+ of PySimpleGUI and pymunk could be used to build games.
+ Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
+"""
+
+class Ball():
+ def __init__(self, x, y, r, *args, **kwargs):
+ mass = 10
+ self.body = pymunk.Body(mass,
+ pymunk.moment_for_circle(mass, 0, r, (0, 0))) # Create a Body with mass and moment
+ self.body.position = x, y
+ self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) # Create a box shape and attach to body
+ self.shape.elasticity = 0.99999
+ self.shape.friction = 0.8
+ self.gui_circle_figure = None
+
+class Playfield():
+ def __init__(self):
+ self.space = pymunk.Space()
+ self.space.gravity = 0, 200
+ self.add_wall((0, 400), (600, 400)) # ground
+ self.add_wall((0, 0), (0, 600)) # Left side
+ self.add_wall((600, 0), (600, 400)) # right side
+
+ def add_wall(self, pt_from, pt_to):
+ body = pymunk.Body(body_type=pymunk.Body.STATIC)
+ ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0)
+ ground_shape.friction = 0.8
+ ground_shape.elasticity = .99
+ self.space.add(ground_shape)
+
+ def add_balls(self):
+ self.arena_balls = []
+ for i in range(1, 200):
+ x = random.randint(0, 600)
+ y = random.randint(0, 400)
+ r = random.randint(1, 10)
+ ball = Ball(x, y, r)
+ self.arena_balls.append(ball)
+ area.space.add(ball.body, ball.shape)
+ ball.gui_circle_figure = graph_elem.DrawCircle((x, y), r, fill_color='black', line_color='red')
+
+
+# ------------------- Build and show the GUI Window -------------------
+graph_elem = sg.Graph((600, 400), (0, 400), (600, 0), enable_events=True, key='_GRAPH_', background_color='lightblue')
+
+layout = [[sg.Text('Ball Test'), sg.T('My IP {}'.format(socket.gethostbyname(socket.gethostname())))],
+ [graph_elem],
+ # [sg.Up(), sg.Down()],
+ [sg.B('Kick'), sg.Button('Exit')]]
+
+window = sg.Window('Window Title', layout, ).Finalize()
+
+area = Playfield()
+area.add_balls()
+
+# ------------------- GUI Event Loop -------------------
+while True: # Event Loop
+ event, values = window.Read(timeout=0)
+ # print(event, values)
+ if event in (None, 'Exit'):
+ break
+ area.space.step(0.02)
+
+ for ball in area.arena_balls:
+ if event == 'Kick':
+ ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(1,200)
+ graph_elem.RelocateFigure(ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Hello_World.py b/DemoPrograms old/Demo_Hello_World.py
new file mode 100644
index 000000000..eb7ee429b
--- /dev/null
+++ b/DemoPrograms old/Demo_Hello_World.py
@@ -0,0 +1,15 @@
+import PySimpleGUI as sg
+
+"""
+ Oh yes, the classic "Hello World". The problem is that you
+ can do it so many ways using PySimpleGUI
+"""
+
+sg.PopupNoButtons('Hello World') # the single line
+
+sg.Window('Hello world', [[sg.Text('Hello World')]]).Read() # single line using a real window
+
+# This is a "Traditional" PySimpleGUI window code. First make a layout, then a window, the read it
+layout = [[sg.Text('Hello World')]]
+window = sg.Window('Hello world', layout)
+event, values = window.Read()
diff --git a/DemoPrograms old/Demo_HowDoI.py b/DemoPrograms old/Demo_HowDoI.py
new file mode 100644
index 000000000..38d73bc00
--- /dev/null
+++ b/DemoPrograms old/Demo_HowDoI.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUIQt as sg
+else:
+ import PySimpleGUI27 as sg
+import subprocess
+
+
+# Test this command in a dos window if you are having trouble.
+HOW_DO_I_COMMAND = 'python -m howdoi.howdoi'
+
+# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file
+DEFAULT_ICON = 'E:\\TheRealMyDocs\\Icons\\QuestionMark.ico'
+
+def HowDoI():
+ '''
+ Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle
+ Excellent example of 2 GUI concepts
+ 1. Output Element that will show text in a scrolled window
+ 2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form
+ :return: never returns
+ '''
+ # ------- Make a new Window ------- #
+ sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors
+
+ layout = [
+ [sg.Text('Ask and your answer will appear here....', size=(40, 1))],
+ [sg.Output(size=(120, 30), font=('Helvetica 10'))],
+ [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'),
+ sg.Text('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15'),
+ sg.T('Command History', font='Helvetica 15'), sg.T('', size=(40,3), text_color=sg.BLUES[0], key='history')],
+ [sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
+ sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
+ sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]
+ ]
+
+ window = sg.Window('How Do I ??', default_element_size=(30, 2), icon=DEFAULT_ICON, font=('Helvetica',' 13'), default_button_element_size=(8,2), return_keyboard_events=True, no_titlebar=True, grab_anywhere=True)
+ window.Layout(layout)
+ # ---===--- Loop taking in user input and using it to query HowDoI --- #
+ command_history = []
+ history_offset = 0
+ while True:
+ event, values = window.Read()
+ if event == 'SEND':
+ query = values['query'].rstrip()
+ # print(query)
+ QueryHowDoI(query, values['Num Answers'], values['full text']) # send the string to HowDoI
+ command_history.append(query)
+ history_offset = len(command_history)-1
+ window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear
+ window.FindElement('history').Update('\n'.join(command_history[-3:]))
+ elif event == None or event == 'EXIT': # if exit button or closed using X
+ break
+ elif 'Up' in event and len(command_history): # scroll back in history
+ command = command_history[history_offset]
+ history_offset -= 1 * (history_offset > 0) # decrement is not zero
+ window.FindElement('query').Update(command)
+ elif 'Down' in event and len(command_history): # scroll forward in history
+ history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list
+ command = command_history[history_offset]
+ window.FindElement('query').Update(command)
+ elif 'Escape' in event: # clear currently line
+ window.FindElement('query').Update('')
+
+
+def QueryHowDoI(Query, num_answers, full_text):
+ '''
+ Kicks off a subprocess to send the 'Query' to HowDoI
+ Prints the result, which in this program will route to a gooeyGUI window
+ :param Query: text english question to ask the HowDoI web engine
+ :return: nothing
+ '''
+ howdoi_command = HOW_DO_I_COMMAND
+ full_text_option = ' -a' if full_text else ''
+ t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE)
+ (output, err) = t.communicate()
+ print('{:^88}'.format(Query.rstrip()))
+ print('_'*60)
+ print(output.decode("utf-8") )
+ exit_code = t.wait()
+
+if __name__ == '__main__':
+ HowDoI()
+
diff --git a/DemoPrograms old/Demo_IP_Address_Entry.py b/DemoPrograms old/Demo_IP_Address_Entry.py
new file mode 100644
index 000000000..7b92fff8e
--- /dev/null
+++ b/DemoPrograms old/Demo_IP_Address_Entry.py
@@ -0,0 +1,43 @@
+import PySimpleGUI as sg
+
+'''
+ IP Address entry window with digit validation and auto advance
+ If not a digit or ., the ignored
+ . will advance the focus to the next entry
+ On the last input, once it's complete the focus moves to the OK button
+ Pressing spacebar with focus on OK generates an _OK_ event
+'''
+
+# create a short-cut element so don't have to type this in over and over
+InIp = lambda key: sg.Input(do_not_clear=True, size=(3, 1), key=key, pad=(0, 2))
+
+layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_')],
+ [InIp(0), sg.T('.'), InIp(1), sg.T('.'), InIp(2), sg.T('.'), InIp(3)],
+ [sg.Button('Ok', key='_OK_', bind_return_key=True), sg.Button('Exit')]]
+
+window = sg.Window('Window Title', return_keyboard_events=True).Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event)
+ if event is None or event == 'Exit':
+ break
+ elem = window.FindElementWithFocus()
+ if elem is not None:
+ key = elem.Key
+ value = values[key] # get value of input field that has focus
+ if event == '.' and key!= '_OK_': # if a ., then advance to next field
+ elem.Update(value[:-1])
+ value = value[:-1]
+ next_elem = window.Element(key+1)
+ next_elem.SetFocus()
+ elif event not in '0123456789':
+ elem.Update(value[:-1])
+ elif len(value) > 2 and key < 3: # if 2 digits typed in, move on to next input
+ next_elem = window.Element(key+1)
+ next_elem.SetFocus()
+ elif len(value)> 2 and key == 3:
+ window.Element('_OK_').SetFocus()
+ print('You entered IP Address {}.{}.{}.{}'.format(*values.values()))
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Img_Viewer.py b/DemoPrograms old/Demo_Img_Viewer.py
new file mode 100644
index 000000000..c4fa408c6
--- /dev/null
+++ b/DemoPrograms old/Demo_Img_Viewer.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import os
+from PIL import Image, ImageTk
+import io
+"""
+Simple Image Browser based on PySimpleGUI
+--------------------------------------------
+There are some improvements compared to the PNG browser of the repository:
+1. Paging is cyclic, i.e. automatically wraps around if file index is outside
+2. Supports all file types that are valid PIL images
+3. Limits the maximum form size to the physical screen
+4. When selecting an image from the listbox, subsequent paging uses its index
+5. Paging performance improved significantly because of using PIL
+
+Dependecies
+------------
+Python v3
+PIL
+"""
+# Get the folder containin:g the images from the user
+folder = sg.PopupGetFolder('Image folder to open', default_path='')
+if not folder:
+ sg.PopupCancel('Cancelling')
+ raise SystemExit()
+
+# PIL supported image types
+img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
+
+# get list of files in folder
+flist0 = os.listdir(folder)
+
+# create sub list of image files (no sub folders, no wrong file types)
+fnames = [f for f in flist0 if os.path.isfile(os.path.join(folder,f)) and f.lower().endswith(img_types)]
+
+num_files = len(fnames) # number of iamges found
+if num_files == 0:
+ sg.Popup('No files in folder')
+ raise SystemExit()
+
+del flist0 # no longer needed
+
+#------------------------------------------------------------------------------
+# use PIL to read data of one image
+#------------------------------------------------------------------------------
+def get_img_data(f, maxsize = (1200, 850), first = False):
+ """Generate image data using PIL
+ """
+ img = Image.open(f)
+ img.thumbnail(maxsize)
+ if first: # tkinter is inactive the first time
+ bio = io.BytesIO()
+ img.save(bio, format = "PNG")
+ del img
+ return bio.getvalue()
+ return ImageTk.PhotoImage(img)
+#------------------------------------------------------------------------------
+
+
+# create the form that also returns keyboard events
+window = sg.Window('Image Browser', return_keyboard_events=True,
+ location=(0, 0), use_default_focus=False)
+
+# make these 2 elements outside the layout as we want to "update" them later
+# initialize to the first file in the list
+filename = os.path.join(folder, fnames[0]) # name of first file in list
+image_elem = sg.Image(data = get_img_data(filename, first = True))
+filename_display_elem = sg.Text(filename, size=(80, 3))
+file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15,1))
+
+# define layout, show and read the form
+col = [[filename_display_elem],
+ [image_elem]]
+
+col_files = [[sg.Listbox(values = fnames, change_submits=True, size=(60, 30), key='listbox')],
+ [sg.Button('Next', size=(8,2)), sg.Button('Prev',
+ size=(8,2)), file_num_display_elem]]
+
+layout = [[sg.Column(col_files), sg.Column(col)]]
+
+window.Layout(layout) # Shows form on screen
+
+# loop reading the user input and displaying image, filename
+i=0
+while True:
+ # read the form
+ event, values = window.Read()
+ print(event, values)
+ # perform button and keyboard operations
+ if event is None:
+ break
+ elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'):
+ i += 1
+ if i >= num_files:
+ i -= num_files
+ filename = os.path.join(folder, fnames[i])
+ elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'):
+ i -= 1
+ if i < 0:
+ i = num_files + i
+ filename = os.path.join(folder, fnames[i])
+ elif event == 'listbox': # something from the listbox
+ f = values["listbox"][0] # selected filename
+ filename = os.path.join(folder, f) # read this file
+ i = fnames.index(f) # update running index
+ else:
+ filename = os.path.join(folder, fnames[i])
+
+ # update window with new image
+ image_elem.Update(data=get_img_data(filename))
+ # update window with filename
+ filename_display_elem.Update(filename)
+ # update page display
+ file_num_display_elem.Update('File {} of {}'.format(i+1, num_files))
+
+
diff --git a/DemoPrograms old/Demo_Input_Auto_Complete.py b/DemoPrograms old/Demo_Input_Auto_Complete.py
new file mode 100644
index 000000000..e963dad0b
--- /dev/null
+++ b/DemoPrograms old/Demo_Input_Auto_Complete.py
@@ -0,0 +1,90 @@
+import sys
+import re
+QT = True
+if QT:
+ import PySimpleGUIQt as sg
+else:
+ import PySimpleGUI as sg
+
+def autocomplete_popup_show(text_list ):
+ autocomplete_popup_layout = [[sg.Listbox(values=text_list,
+ size=(100,20*len(text_list)) if QT else (15, len(text_list)),
+ change_submits=True,
+ bind_return_key=True,
+ auto_size_text=True,
+ key='_FLOATING_LISTBOX_', enable_events=True)]]
+
+ autocomplete_popup = sg.Window("Borderless Window",
+ default_element_size=(12, 1),
+ auto_size_text=False,
+ auto_size_buttons=False,
+ no_titlebar=True,
+ grab_anywhere=True,
+ return_keyboard_events=True,
+ keep_on_top=True,
+ background_color='black',
+ location=(1320,622),
+ default_button_element_size=(12, 1))
+
+ window = autocomplete_popup.Layout(autocomplete_popup_layout).Finalize()
+ return window
+
+
+def predict_text(input, lista):
+ pattern = re.compile('.*' + input + '.*')
+ return [w for w in lista if re.match(pattern, w)]
+
+choices = ['ABC' + str(i) for i in range(30)] # dummy data
+
+layout = [ [sg.Text('Your typed chars appear here:')],
+ [sg.In(key='_INPUT_', size=(10,1), do_not_clear=True)],
+ [sg.Button('Show'), sg.Button('Exit')],]
+
+window = sg.Window('Window Title', return_keyboard_events=True).Layout(layout)
+
+sel_item = -1
+skip_event = False
+while True: # Event Loop
+ event, values = window.Read(timeout=500)
+ if event is None or event == 'Exit':
+ break
+ if event != sg.TIMEOUT_KEY:
+ # print(f'ev1 {event}')
+ in_val = values['_INPUT_']
+ prediction_list = predict_text(str(in_val), choices)
+ if prediction_list:
+ try:
+ fwindow.Close()
+ except: pass
+ fwindow = autocomplete_popup_show(prediction_list)
+ list_elem = fwindow.Element('_FLOATING_LISTBOX_')
+ if event == '_COMBO_':
+ sg.Popup('Chose', values['_COMBO_'])
+ if event.startswith('Down') or event.startswith('special 16777237'):
+ sel_item = sel_item + (sel_item0)
+ list_elem.Update(set_to_index=sel_item)
+ skip_event = True
+ if event == '\r' or event.startswith('special 16777220'):
+ chosen = vals2['_FLOATING_LISTBOX_']
+ window.Element('_INPUT_').Update(vals2['_FLOATING_LISTBOX_'][0], select=True)
+ fwindow.Close()
+ sel_item = -1
+ if event.startswith('Escape') or event.startswith('special 16777216'):
+ window.Element('_INPUT_').Update('')
+
+ try:
+ ev2, vals2 = fwindow.Read(timeout=10)
+ if ev2 == '_FLOATING_LISTBOX_' and skip_event and QT:
+ skip_event = False
+ elif ev2 != sg.TIMEOUT_KEY and ev2 is not None:
+ # print(f'ev2 {ev2}')
+ fwindow.Close()
+ window.Element('_INPUT_').Update(vals2['_FLOATING_LISTBOX_'][0], select=True)
+ sel_item = -1
+ fwindow = None
+ except: pass
+window.Close()
diff --git a/DemoPrograms old/Demo_Input_Validation.py b/DemoPrograms old/Demo_Input_Validation.py
new file mode 100644
index 000000000..0a963f0b9
--- /dev/null
+++ b/DemoPrograms old/Demo_Input_Validation.py
@@ -0,0 +1,25 @@
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+ Simple field validation
+ Input field should only accept digits.
+ If non-digit entered, it is deleted from the field
+"""
+
+layout = [[sg.Text('Enter digits:')],
+ [sg.Input(do_not_clear=True, enable_events=True, key='_INPUT_')],
+ [sg.Button('Ok', key='_OK_'),sg.Button('Exit')]]
+
+window = sg.Window('Window Title').Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event in (None, 'Exit'):
+ break
+ if len(values['_INPUT_']) and values['_INPUT_'][-1] not in ('0123456789'): # if last char entered not a digit
+ window.Element('_INPUT_').Update(values['_INPUT_'][:-1]) # delete last char from input
+window.Close()
diff --git a/DemoPrograms old/Demo_Invisible_Elements.py b/DemoPrograms old/Demo_Invisible_Elements.py
new file mode 100644
index 000000000..df98d4bd7
--- /dev/null
+++ b/DemoPrograms old/Demo_Invisible_Elements.py
@@ -0,0 +1,27 @@
+import PySimpleGUI as sg
+
+"""
+ Demonstrates that using a Column Element to make groups of Elements appear and disappear
+ will cause the layout of the elements in the column to remain as they were. If each individual element
+ were made invisible and then visible, then tkinter puts EACH ELEMENT on a separate row when it is made
+ visible again. This means a row of 6 elements will become a column of 6 elements if you make each of them
+ visible one at a time.
+
+"""
+
+layout = [[sg.Column([[sg.Text('My Window')],[sg.Input(key='_IN_'), sg.B('My button', key='_OUT_')]], key='_COL_')],
+ [sg.Button('Invisible'), sg.B('Visible'), sg.Button('Exit')]]
+
+window = sg.Window('Window Title', layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event in (None, 'Exit'):
+ break
+ if event == 'Invisible':
+ window.Elem('_COL_').Update(visible=False)
+ elif event == 'Visible':
+ window.Elem('_COL_').Update(visible=True)
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Keyboard.py b/DemoPrograms old/Demo_Keyboard.py
new file mode 100644
index 000000000..6fd21931a
--- /dev/null
+++ b/DemoPrograms old/Demo_Keyboard.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+# Recipe for getting keys, one at a time as they are released
+# If want to use the space bar, then be sure and disable the "default focus"
+
+layout = [[sg.Text("Press a key or scroll mouse")],
+ [sg.Text("", size=(18,1), key='text')],
+ [sg.Button("OK", key='OK')]]
+
+window = sg.Window("Keyboard Test", return_keyboard_events=True, use_default_focus=False).Layout(layout)
+
+# ---===--- Loop taking in user input --- #
+while True:
+ event, values = window.Read()
+ text_elem = window.FindElement('text')
+ if event in ("OK", None):
+ print(event, "exiting")
+ break
+ if len(event) == 1:
+ text_elem.Update(value='%s - %s' % (event, ord(event)))
+ if event is not None:
+ text_elem.Update(event)
+
+
diff --git a/DemoPrograms old/Demo_Keyboard_ENTER_Presses_Button.py b/DemoPrograms old/Demo_Keyboard_ENTER_Presses_Button.py
new file mode 100644
index 000000000..de2c2a6b3
--- /dev/null
+++ b/DemoPrograms old/Demo_Keyboard_ENTER_Presses_Button.py
@@ -0,0 +1,46 @@
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+
+"""
+ tkinter and Qt do not "activate" buttons by pressing the ENTER key with the button highlighted / in focus
+ This demo will enable the application to click on a button if the button has focus (is highlighted) and the
+ user presses the ENTER key.
+ NOTE that the SPACE BAR works correctly out of the box with both tkinter and Qt. If a button has focus and
+ you press the space bar, then tkinter and Qt will both consider that a button click. But not so with the ENTER
+ key.
+
+ The solution is for your program to read the keyboard presses and act upon those directly. It's trivial logic
+ in the end:
+ 1. Get a key press
+ 2. See if the key is the ENTER key
+ 3. Find the Element that currently has focus
+ 4. Click the Button if the Element with focus is a button
+
+"""
+
+QT_ENTER_KEY1 = 'special 16777220'
+QT_ENTER_KEY2 = 'special 16777221'
+
+layout = [ [sg.T('Test of Enter Key use')],
+ [sg.In(key='_IN_')],
+ [sg.Button('Button 1', key='_1_')],
+ [sg.Button('Button 2', key='_2_')],
+ [sg.Button('Button 3', key='_3_')], ]
+
+window = sg.Window('My new window', layout,
+ return_keyboard_events=True)
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None:
+ break
+ if event in ('\r', QT_ENTER_KEY1, QT_ENTER_KEY2): # Check for ENTER key
+ elem = window.FindElementWithFocus() # go find element with Focus
+ if elem is not None and elem.Type == sg.ELEM_TYPE_BUTTON: # if it's a button element, click it
+ elem.Click()
+ # check for buttons that have been clicked
+ elif event == '_1_':
+ print('Button 1 clicked')
+ elif event == '_2_':
+ print('Button 2 clicked')
+ elif event == '_3_':
+ print('Button 3 clicked')
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Keyboard_Realtime.py b/DemoPrograms old/Demo_Keyboard_Realtime.py
new file mode 100644
index 000000000..cc50054ea
--- /dev/null
+++ b/DemoPrograms old/Demo_Keyboard_Realtime.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[sg.Text("Hold down a key")],
+ [sg.Button("OK")]]
+
+window = sg.Window("Realtime Keyboard Test", return_keyboard_events=True, use_default_focus=False).Layout(layout)
+
+while True:
+ event, values = window.Read(timeout=0)
+
+ if event == "OK":
+ print(event, values, "exiting")
+ break
+ if event is not sg.TIMEOUT_KEY:
+ if len(event) == 1:
+ print('%s - %s' % (event, ord(event)))
+ else:
+ print(event)
+ elif event is None:
+ break
diff --git a/DemoPrograms old/Demo_Keypad.py b/DemoPrograms old/Demo_Keypad.py
new file mode 100644
index 000000000..31194fbc4
--- /dev/null
+++ b/DemoPrograms old/Demo_Keypad.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+# Demonstrates a number of PySimpleGUI features including:
+# Default element size
+# auto_size_buttons
+# Button
+# Dictionary return values
+# Update of elements in form (Text, Input)
+# do_not_clear of Input elements
+
+
+
+layout = [[sg.Text('Enter Your Passcode')],
+ [sg.Input(size=(10, 1), do_not_clear=True, key='input')],
+ [sg.Button('1'), sg.Button('2'), sg.Button('3')],
+ [sg.Button('4'), sg.Button('5'), sg.Button('6')],
+ [sg.Button('7'), sg.Button('8'), sg.Button('9')],
+ [sg.Button('Submit'), sg.Button('0'), sg.Button('Clear')],
+ [sg.Text('', size=(15, 1), font=('Helvetica', 18), text_color='red', key='out')],
+ ]
+
+window = sg.Window('Keypad', default_button_element_size=(5, 2), auto_size_buttons=False, grab_anywhere=False).Layout(layout)
+
+# Loop forever reading the form's values, updating the Input field
+keys_entered = ''
+while True:
+ event, values = window.Read() # read the form
+ if event is None: # if the X button clicked, just exit
+ break
+ if event == 'Clear': # clear keys if clear button
+ keys_entered = ''
+ elif event in '1234567890':
+ keys_entered = values['input'] # get what's been entered so far
+ keys_entered += event # add the new digit
+ elif event == 'Submit':
+ keys_entered = values['input']
+ window.FindElement('out').Update(keys_entered) # output the final string
+
+ window.FindElement('input').Update(keys_entered) # change the form to reflect current key string
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_LED_Clock_Weather.py b/DemoPrograms old/Demo_LED_Clock_Weather.py
new file mode 100644
index 000000000..cde7115ec
--- /dev/null
+++ b/DemoPrograms old/Demo_LED_Clock_Weather.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+ sg.PopupError('This program uses Base64 images which are not supported in Python 2.7')
+ sys.exit()
+import datetime
+import calendar
+import forecastio
+
+##### CHANGE these settings to match your location... check Google Maps #####
+MY_LOCATION_LAT = 35.000000
+MY_LOCATION_LON = -79.000000
+##### You need a free dark-sky key. You get 1000 calls a month for free #####
+DARKSKY_KEY = "INSERT YOUR DARKSKY KEY HERE!" # *** INSERT YOUR DARKSKY KEY HERE **
+
+NUM_COLS = 5 # Changes number of days in forecast
+
+
+class GUI():
+ def __init__(self):
+ self.api_key = DARKSKY_KEY
+ self.lat = MY_LOCATION_LAT
+ self.lng = MY_LOCATION_LON
+ self.blink_count = 0
+
+ sg.SetOptions(border_width=0, text_color='white', background_color='black', text_element_background_color='black')
+
+ # Create clock layout
+ clock = [
+ [sg.T('', pad=((120,0),0)),
+ sg.Image(data=ledblank[22:], key='_hour1_'),
+ sg.Image(data=ledblank[22:], key='_hour2_'),
+ sg.Image(data=ledblank[22:], key='_colon_'),
+ sg.Image(data=ledblank[22:], key='_min1_'),
+ sg.Image(data=ledblank[22:], key='_min2_')], ]
+
+ # Create the weather columns layout
+ weather_cols = []
+ for i in range(NUM_COLS):
+ weather_cols.append(
+ [[sg.T('', size=(4, 1), font='Any 20', justification='center', key='_DAY_' + str(i)), ],
+ [sg.Image(data=w1[22:], background_color='black', key='_icon_'+str(i), pad=((4, 0), 3)), ],
+ [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_high_' + str(i), pad=((10, 0), 3))],
+ [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_low_' + str(i), pad=((10, 0), 3))]])
+
+ # Create the overall layout
+ layout = [[sg.Column(clock, background_color='black')],
+ [sg.Column(weather_cols[x], background_color='black') for x in range(NUM_COLS)],
+
+ [sg.Button('Exit', button_color=('black', 'black'),
+ image_data=orangeround[22:], tooltip='close window', pad=((450,0),(10,0)))]]
+
+ # Create the window
+ self.window = sg.Window('My new window',
+ background_color='black',
+ grab_anywhere=True,
+ use_default_focus=False,
+ no_titlebar=True,
+ alpha_channel=.8, # set an alpha channel if want transparent
+ ).Layout(layout).Finalize()
+
+ self.colon_elem = self.window.FindElement('_colon_')
+ self.hour1 = self.window.FindElement('_hour1_')
+ self.hour2 = self.window.FindElement('_hour2_')
+ self.min1 = self.window.FindElement('_min1_')
+ self.min2 = self.window.FindElement('_min2_')
+
+
+ def update_clock(self):
+ # update the clock
+ now = datetime.datetime.now()
+ real_hour = now.hour - 12 if now.hour > 12 else now.hour
+ hour1_digit = led_digits[real_hour // 10]
+ self.hour1.Update(data=hour1_digit[22:])
+ self.hour2.Update(data=led_digits[real_hour % 10][22:])
+ self.min2.Update(data=led_digits[int(now.minute) % 10][22:])
+ self.min1.Update(data=led_digits[int(now.minute) // 10][22:])
+ # Blink the :
+ if self.blink_count % 2:
+ self.colon_elem.Update(data=ledcolon[22:])
+ else:
+ self.colon_elem.Update(data=ledblank[22:])
+ self.blink_count += 1
+
+ def update_weather(self):
+ forecast = forecastio.load_forecast(self.api_key, self.lat, self.lng)
+ daily = forecast.daily()
+ today_weekday = datetime.datetime.today().weekday()
+
+ max_temps = []
+ min_temps = []
+ daily_icons = []
+ for daily_data in daily.data:
+ daily_icons.append(daily_data.d['icon'])
+ max_temps.append(int(daily_data.d['temperatureMax']))
+ min_temps.append(int(daily_data.d['temperatureMin']))
+
+ for i in range(NUM_COLS):
+ day_element = self.window.FindElement('_DAY_' + str(i))
+ max_element = self.window.FindElement('_high_' + str(i))
+ min_element = self.window.FindElement('_low_' + str(i))
+ icon_element = self.window.FindElement('_icon_' + str(i))
+ day_element.Update(calendar.day_abbr[(today_weekday + i) % 7])
+ max_element.Update(max_temps[i])
+ min_element.Update(min_temps[i])
+ icon_element.Update(data=weather_icon_dict[daily_icons[i]][22:])
+
+
+def led_clock():
+
+ # Get the GUI object that is used to update the window
+ gui = GUI()
+
+ # ---------- EVENT LOOP ----------
+ last_update_time = 0
+ while True:
+ # Wake up once a second to update the clock and weather
+ event, values = gui.window.Read(timeout=1000)
+ if event in (None, 'Exit'):
+ break
+ # update clock
+ gui.update_clock()
+ # update weather once ever 6 hours
+ now = datetime.datetime.now()
+ if last_update_time == 0 or (now-last_update_time).seconds >= 60*60*6:
+ print('*** Updating Weather ***')
+ last_update_time = now
+ gui.update_weather()
+
+
+led0 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg=='
+
+led1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII='
+
+led2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII='
+
+led3 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII='
+
+led4 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII='
+
+led5 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC'
+
+led6 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC'
+
+led7 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII='
+
+led8 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII='
+
+led9 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC'
+
+ledcolon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII='
+
+ledblank = 'data:image/png;base64,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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII='
+
+w1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsSAAALEgHS3X78AAAUjklEQVR4nO2ceZhddXnHP+/vnHO3mTt7MknIQhYSAhgSaAuGLaDYggqiVlyKLQ8V96WWAlJNQ6ViK23R1gcLPlpRXEr1AQOUnTYoQVlCICEbIRCTTGYyy52Zu57l9/aPc2ZJyDJDJsE/eJ/nPHfOuef83t/ve979/d0RVeVNei2ZN3oCv6/0JjAHoDcSGEmO30ty30DeBzNuMoZ7jigdBYnR/UuF+g5qnf0/YxWNDgCKygHHnEB6A1RJY5619ZcTbj8juZYAlCy4tulCgm3nx9f2BU80Po4sHVlgtJpGo30Wliw+2PVW/M1/nFxzR8ABKk9fiR2YmZzJXp+23IYdaN9rrCNARwiYRCr8l9+q5dVXxteG3rzGdk1rBa2sPxNwQHwglgRbaaa2+QxVwuT+oefij/Jj1xINTk0Y/b4Do/v3ME5rhxQfuoqwayGYKF6k8eNHwpL4L51N1D0fRIl2ngqAv+k8DTvbIJoSDyJRDKoolWc/otVNy/COeS7mKXafOUwYTQAwKqg1gI68XVFQg9u2XTG7tfDjb8XXI6PBCxdBUI9GU4l6obb5NGznWVR/8b9obTK1zWeLLSNqBwA0WPduMBG23KoDP/973PZ1Cd9RHlUNiKLRhIFzuMAIiGrl6XcRds8ZebtDcu9UJD3vWSk9/nZKqy8HN5Lqw3dRW3UTdmA2CFr+7efwn7oBreWo3HcP1RcvAgfCnjZqD3xHar/+BoQNOnDPCvFfnSOpWasT1lH8GXkgVv1Nb1N/8znxNT3sF+6sWLHiMB6PRVyi/nZ6//NmMic8hqnvi+fbPQ8xGWzNpfzUewk7jsdrrkc7zsJ2naa271j8QRHjT8XVmZAC7T0Gv6sJVSVll6I9pyNpS9Cfk+KDn0RSHg3vuQYJm9FqFskOgLFU1lzM4L03SP15tyHpwkSYnsNE1kQQOWROXIXTuJ2O657Af/UPY2C2L6P0g1XQfRGmPsDfMZ/i3TcguGikkmo2kpsD2emKySpiBFNvyU5X6mYJbiaDYlG/lfLD1xIO5tTUdxO9dAWl29diu08GoPzbP6fn5rskd9pPMQ3bIHKZgMBQxp9dDxnaIcOnBsQS7FqgOz+3FpMbkMnXXopXl6J4x/1IGiIfKq8qmWmQbhdUQWvxEZXA+slwBkwGTBYkq4gnIFDbbfF7DbnpiqiCNdR/7GxKa99C323f1tTcTdK+/Ewk1T08HxCwJn55RweYmOewLTF2eDK9P/w7+m5fgTdtpzac95SYwgWo7yGewaTBVpVgl+DvgqiMqiB4YNzELChoAASxz3Hq0dQ0JDUVxANbA40iTEoJnHWUnnoLGjm0fvLj1C29NTb+YhMVjxInIK8nIBwPMAIopSfPx20skl64ehiQqPM4/PWXoVKl5/vX4vfWk2qChiWC8cAGUNkA1VdQ0og7BZxm1GQQceOhdQhyC0SoLSNRHxp2IkRoZg6Smw84oFUY3KBENSE9q5OWD60g3DWf7Bk3Ivk98XStS2n1RzF1vyO7+KFRkjTRwFgDxuJvX6KdN35P0nN/S/OHb8KbtgUNm3Xg289g+2YjuYigz6BWyc4wVLYgg8+C5CA9F5wGwIJGQCLlOiSFCjJkOB0YAi3qQ2tbEUK04Y+Q1Ay0tjNCPIPXaLH9jjgzV9NwxbmgSmX9BfT/7HpM6w4mffpSJF0ar+SMU5WSwWvbTmbHpx8F69Jw4Y9p+sBXCbdcTfWRzyPZCHEdxIXCY2jld0jmBEi1JqoQMlJxGAKEff4eOk8+xQNJQdAJ1U1o3fFI41vBVsHaEK265C5YDvUrtf8XN0npibeRXfIkU5afj6SL45WW1wEMxFbfCam9dDo7Pnc3Yddk3Kk7qV/STypzAph4hT3/A1ENcicBYWJghdgRjpVnApTa+BmTARQtvYCk2qD1bWADRUSoFDqpbW3QaCBLdsmvZcpXLsXU7xyW9HHSGIBJIlsRHWagQQrxMlr69SWy+4bvojUHEJrOBjcDXSvjxWTmgi3HC5yImHRI5UwWKhtRtwlpuwDCPhhcH3/pTe2m/W/fi9f+PEoFcf1YYjT2huKMyUuNV5WILb5RBu/8KeH2i7FlsJUUYHEajPY+CkE3kp0NYQkYFQgfNg2ha8HJQnkr5OZA0+kQDlhEDU5zBTSFd8L3qX/3x8C6YMJxczowMIk9CXa3a2XN2yV70rN4MzYkLjEi2rNIC//+f6htQlzFyQr9a5D+p+PJ2gpHvNxjPLS8DVrPhbq5ENUUrQmm8RVp/sxZSN0OQLCVFiprT9eoPyP5ZSuRtH+ooQ9S2kzejtM0KEHPdO268uuCCTR36iOSmfcCmcW/ktTiX1L9zUfBjajtcel7EjJtEBYmaOUHozhPFS+Pdq9CUu0gjqIquMetovT0H1Jd/yVqL59CdeNJpGZslNYrvhyDcmgPNTYbgyj+9hPZ/Q9f18Jd74oj07pI3KaAhsUZMtNVd98nUtmKZtvjuOWo1LkVHA8p7ULzpyKTzkKrO5DiRotWBVsSTH2F1ituovnD/4hJlxhxhwelsdmYYeMryuCq89h9438S9czAySl1CwWTg23fh7pWMN5Y+E4ciYGwDLUazP4LCHqh1mmJykazJz4uk/76ClLHbBmpFY/NQ42tSyAmjkujwhRM7VyazzJE3eDUK05K6FwFYQXESeKUo0gaxTFObRcMbIbmReC1CraKeLObCTZejNPwHZx8aSSHip882LAHAWaoAJVUz0RCTF2RqLedcOdUTD1EZYMG6MDWOA6zo6LZo0aCqkCk0L8ZaVwItiaIq/gbTiI1G5x8EbVunICKxgAdXNUPZnw19vmj/L6YCg2XXokzaQOD9/4LTlrx+0QqXTH+4ZBtOZqqJPELsQLlDjQoqjhpUB/q3/tZ6pbdivo5xCsnXlJAU3G2emADvB8bM+SmO46j/4F3am3LDKLByULUrjaoii05aotToLJEGpaIDryMbLsrDttzdZDKJoHY0SCNbUytDJUiGIG5l8aecXBdoHgv4qRdJFMSpAAu6rYYqTv95zRd9B0kLfFkXys9+5GYBEW3dQf1S+8Twot04NEztPzMIqntzCKpODTPzAQNEb8fohBcDyolME48waOBjYBGAVJNouvQR/0BJNMMtuhJ0H0ytgbGQdPzt0rd0pWSX/YomROeQDyIkd3/0GNw1wnT7kmUfnsmfT/5KsaeSGqKYlxh1yroeBLcHNgIXBfNZeO86IhKTqyyUi5DGIExEFZh5tth8ikQ+VZrHUa8OY/S/JGryBy3DvGCsY5+CK80nCcJbuseleAU8eoXIgaiiiBZiMI4x7NJQcUPISoh2XQ82SMBjgCRhaqP2sT7JnOQyI/jqKgm4jUDhbMJX7kQWbgGjVxE7Fi6mYcARhQxNu4xh65kFv4PtthC9YVLscVWUEVjVjEwQ9IVQbECKRe8JC2YCHyGpD6wUAtHXUrWaYf5xBMxTV2aXXKHZE58YKRPPrbA81DuOo5hxAnBCKn5T6CpPQw8u4TglbdSP08xKUHZp9cuMVAVH/UN4pnYIZgEHR3LBHVkHZrYrCgBxY4uaCU3KXH9y0khGirVbaLenJ3ScPwPcY9Zizjjas4dyl2DLTdSfWkhg6v+mMKD79bKC4slKgpOC2SmG03lh8X4tWojECgaRHGS7ShiSCR5aNGjMHqNg0yGjEwMih0Z9rW8FMRBvDo0KhrKLyP2uSVaWPks6XkbyJ91n+TPeYzMwmfw2ncfCpgDu2u/czKFey6hcN9lFJ9eStAtiAFTr5pqQxpPFrxGKO5GN6w8FJ+9F74XOLoPMMnbV1ArI5bgkAKm4KaREy6GTBPUetDyxkhsxWKrHhqB29Sn2YWbaH7/LdL8p7eDEWT/Sn5grxQV8wS7WtCoDshj/QCtpSk9dQ2VJy7GrQ+xgYsqun4lUukFxxu7sR214KFHJMFkzGAMryJx1Y3HIAsvjI2vuKhGBWl836fJnrQByZSQVCdabUK8Mm7rnoMxOLAqOfWDOPMHk1XEUqS1POVH26AKkXEwGfBcyLdjB3sSvT80MHtNZ9TtQwDpqO/GBrPEDduGaXEcZS2ob8UONuFv/hMa3vHjOG5RAekf04gHj2NGW1RRbLku9kZSR/cPvqL9D3yQ7DGWwR6j6+/fxyAeRVIF4yCL3g2ZrKXaYcgve1AmffyLiNOHZAqYbGXvhw7urg9RYhuq84qi1mDqipimDrp/uZSOH54mhTVIpUNonAL1k5EwRJDhKOGoHBgkjJCWmVDXAuWdIoMvwp47F9P90/cgmUFMroxaE2ebY9uRNcaabzyglp5fzLar/43Cg2cirkrdfKHxZHActNCJvvAQOEnr+KikBEOpjoNZ/A7INkEUQOl5qGxXtCaaP32DzLjxc+TPeHg8vaUxqJIoQWc7O26+il3/+kUVE5F7yybSM6qSkiU4GbC+g5fGbv4NumMzpLxYz4+0ZomAH2LmLEaOXQRBBUwKrB1AWu6ntm0W5XULCAtNOukjP5ZpVy8nfezWMQ19kGI4cRRbSLHjpmsJumbTdO7jZOevJTPnZQYfvoruW67D5CNMvYMBIp9ozSMw2Aeel/SDjgQ6GqcbtQBpm4ZZdE4c44iBcFCxZdGp131K8ufeQnXzCfg7ZzGweilYmPwXt5Gavv1Q0nNoVVLfIarkcBsHR100DDzyCSCHDdrYvuIawoJq8yKhWsE++yj4VXCPVK4kEERQ34hZch4YixRfAicfMv3L38Kk9iBuH/llt8VFqQQEW8mAgMlUD8lizH0ljZxhBpJUwVQ93fLJf5fO26/UdLulZYkRN4UO9hKt/RVUq0jKjSVndIT7ekgZ9nrqR0i+CXPyUiRbB0EVBl6ICPocWt//E+bdcjni1eKQWUi2whGnNoedK+1Dwx08lTgkNY6+/FfflV23fhRxrKQbwclEBCWR+ibjnLIMu+43aF8fpEySEb9O6RGSIM5CoMjkdpyTTotjqKBmcXKqXoPB77J0fe9DGLcmc79zJUqEiCLuRDbc9kejKu2vrvgaL13/JbLtgzr5w/8l7uA51DbOw8kr6gkSoRjs1o3oq1tjY+wJMjr+PxjroZhIQK3GgKRSyOy5mFkL4l44HkhoCfuM1i1dDU2P0/WDyylumcTMq74ls7/x+bjmOZR7HClgNDKIY3X7P31RXl7+T0y7/A6mf/6fSbd3s/2LD5GetUXDalZ23PYOUq2W5hMMxqCFHuy2zWh3V5wdG5LDjOQBw9l04oKtTZJTIOUg7dMwx85DGpogCGFgoyUcMEy9bDXG9BP2TWXmzcsIelvp/N6ndOe/fYwpH7tVZn/tb3gdwcN49scIGKX77g9p18/fJbOuuYm6E9cAEPXXY8tNeFN3sO4Dd9B154epnxvRvNDBWovnGsRF+3uwHTvQnh60XIIgGJny6PxIgFQaqatD2towU6bHgISBEllF1NC/PqLa4WjLBffLiXe9E3/nApyGDpx83Ab1O+bojm9cR+NZD0nrJT8bTwwzTmAADV2qr84jfcyrmEwlNmqJeokb0n3Phax73z1ghfzx/TTOyxL2pZA0VHviACyVR/0qlEtouYJWyxD4cdnCSAxINofkckgmB14aagUISpBqAfVRtzGg+LuCDG6YhCh6/I8+IG3vvROsGZY+cSxqDf7uVlLt3YgzLqkZX9dd3JDs3I2I58clT2MRJ0JMhAYuO2/9OFVfaHvfj3TWdV/S2quO5k7erKVCiZ41aKUQqV8FtSr5RjWTWjCzZmGOOx6z4HjM/IU4M2dg2logl1fVCA1qSqU3ovc5tNrfr+k5W6ht92TuN7/A5A/djl9BOv7jUxC5xPVEjYtS1oAV0tP2jBeU8QMDwBAgQ3tlonhbSO9j5+nulRfpzMv+ixN/8peSnraF9s8ul/a/eSfVvm5FoNphBBOJ9dFqj7D7aSi8ogSRpVoGP7D0vqTa+RzUCiIaxKa61mNQg5Q7y3LM9Rcy6S9vxGnYxILb/lxnfuEWuh5cxp5fXoIYHflRh7GIG42lWrc/eh07qkbTSOatvzn1GZrOXC0LvvkZQLBVF5MJ6H34XJ5/z71E5SyzPv8w4brz8Fq3aLE3TfdDx5JqVmleIHh5S1A09G5Uwj6hdVk3ubomxOvA+4OH2Pa1P0OiFCc/eAFNZ9+PBl68eCdi2/Vf1+67z5dTHj8Hp644XnuyPzq8DSxD2eruH13C5Et+Lgu++Rk0MonNie+pbJtHpZSl5U/uZ/YN7yN93H8zbflHJLvoXokAt22Xtrz/TsIeZfKV12tq5gYNgbo/+qFOW3EZ3pynmHXdJ2g5/zGqNSiuPT6Zeiy1Ghpm/921TLviDrrvvmBkXodJqnp4hw08LW+dq1E1FV+zJrnuqir64idu1QdQLT6/WFXRoDerquiWq1fovai+8MEfadg3WXd+/R9VFfviFbfpvai+dM1fqyrq7zlWVdHy5pPsI00lu/6jP4vHD51kDqI2MqpWtLq9XTWSw16T6gRseRI3IDtna6zPQzvGEy+ltTrtfeY05qxYTt1bnkMjB6ch3s3ktMbV1knvWYnT1MWUv/oKAM1vfwQAUxfPzW3egQYu2ePWybzlN1B48g8AJ7ZxmnTdkr/TMzpHWhGHRxOzF0xVEmOsw+cAxQ0LyLX9jmO/cDMAYkaMoclFmsoXaTpjdfJdXApvfceDZHIVJJWJB48M4kaowozP/gv5RWso/PrUpHg2SmWGgZoQmphf0co+hm743Pgy+8v/gNs4OOzeh4yiyA5pPudXpKdvRyMHcQPUGryWXprPfELR/NBm1jhxVQG3JvNuvJqoqvvlO4G/lTxCPy9OJphftG4kABzayZR85+TQSec9luTLe9fHJ196B1E5F5+ZUWOqkJ338sidE6M2+6Mj/LtrlaRcMGoB8d+19ElryWWKaWB4+1dyX9jwtgfU72hKxd9Fez+7vzEnng4zjnn9ZOM+t5j9NLxUQVHMG9V14A0EBvbuP76WDj9IOxx6I4H5vaY3/xvIAehNYA5AbwJzAHoTmAPQm8AcgN4E5gD0/1bxlgNoWAgGAAAAAElFTkSuQmCC'
+
+w2 = 'data:image/png;base64,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'
+
+w3 = 'data:image/png;base64,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'
+
+w4 = 'data:image/png;base64,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'
+
+w5 = 'data:image/png;base64,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'
+
+orangeround = 'data:image/png;base64,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'
+
+weather_icon_dict = {'clear-day': w1, 'clear-night': w1, 'rain': w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'fog': w3,
+ 'cloudy': w4, 'partly-cloudy-day': w5, 'partly-cloudy-night': w5}
+
+led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9]
+
+if __name__ == '__main__':
+ led_clock()
diff --git a/DemoPrograms old/Demo_LED_Indicators.py b/DemoPrograms old/Demo_LED_Indicators.py
new file mode 100644
index 000000000..790b3cb87
--- /dev/null
+++ b/DemoPrograms old/Demo_LED_Indicators.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+import sys
+
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import time
+import random
+
+"""
+ Demo program showing how to create your own "LED Indicators"
+ The LEDIndicator function acts like a new Element that is directly placed in a window's layout
+ After the Window is created, use the SetLED function to access the LED and set the color
+
+"""
+
+
+def LEDIndicator(key=None, radius=30):
+ return sg.Graph(canvas_size=(radius, radius),
+ graph_bottom_left=(-radius, -radius),
+ graph_top_right=(radius, radius),
+ pad=(0, 0), key=key)
+
+def SetLED(window, key, color):
+ graph = window.FindElement(key)
+ graph.Erase()
+ graph.DrawCircle((0, 0), 12, fill_color=color, line_color=color)
+
+
+layout = [[sg.Text('My LED Status Indicators', size=(20,1))],
+ [sg.Text('CPU Use'), LEDIndicator('_cpu_')],
+ [sg.Text('RAM'), LEDIndicator('_ram_')],
+ [sg.Text('Temperature'), LEDIndicator('_temp_')],
+ [sg.Text('Server 1'), LEDIndicator('_server1_')],
+ [sg.Button('Exit')]]
+
+window = sg.Window('My new window', default_element_size=(12, 1), auto_size_text=False).Layout(layout).Finalize()
+
+i = 0
+while True: # Event Loop
+ event, value = window.Read(timeout=400)
+ if event == 'Exit' or event is None:
+ break
+ if value is None:
+ break
+ i += 1
+ SetLED(window, '_cpu_', 'green' if random.randint(1, 10) > 5 else 'red')
+ SetLED(window, '_ram_', 'green' if random.randint(1, 10) > 5 else 'red')
+ SetLED(window, '_temp_', 'green' if random.randint(1, 10) > 5 else 'red')
+ SetLED(window, '_server1_', 'green' if random.randint(1, 10) > 5 else 'red')
diff --git a/DemoPrograms old/Demo_Layout_Generation.py b/DemoPrograms old/Demo_Layout_Generation.py
new file mode 100644
index 000000000..201a0ce0f
--- /dev/null
+++ b/DemoPrograms old/Demo_Layout_Generation.py
@@ -0,0 +1,289 @@
+import PySimpleGUI as sg
+
+"""
+ PySimpleGUI is designed & authored in Python to take full advantage the awesome Python constructs & capabilities.
+ Layouts are represented as lists to PySimpleGUI. Lists are fundamental in Python and have a number of powerful
+ capabilities that PySimpleGUI exploits.
+
+ Many times PySimpleGUI programs can benefit from using CODE to GENERATE your layouts. This Demo illustrates
+ a number of ways of "building" a layout. Some work on 3.5 and up. Some are basic and show concatenation of rows
+ to build up a layout. Some utilize generators.
+
+ These 8 "Constructs" or Design Patterns demonstrate numerous ways of "generating" or building your layouts
+ 0 - A simple list comprehension to build a row of buttons
+ 1 - A simple list comprehension to build a column of buttons
+ 2 - Concatenation of rows within a layout
+ 3 - Concatenation of 2 complete layouts [[ ]] + [[ ]] = [[ ]]
+ 4 - Concatenation of elements to form a single row [ [] + [] + [] ] = [[ ]]
+ 5 - Questionnaire - Using a double list comprehension to build both rows and columns in a single line of code
+ 6 - Questionnaire - Unwinding the comprehensions into 2 for loops instead
+ 7 - Using the * operator to unpack generated items onto a single row
+ 8 - Multiple Choice Test - a practical use showing list comprehension and concatenated layout
+"""
+
+"""
+ Construct #0 - List comprehension to generate a row of Buttons
+
+ Comprehensions are super-powers of Python. In this example we're using a comprehension to create 4 buttons that
+ are all on the same row.
+"""
+
+
+def layout0():
+ layout = [[sg.Button(i) for i in range(4)]] # A list of buttons is created
+
+ window = sg.Window('Generated Layouts', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+"""
+ Construct #1 - List comprehension to generate a Column of Buttons
+
+ More list super-power, this time used to build a series of buttons doing DOWN the window instead of across
+
+"""
+
+def layout1():
+ layout = [[sg.Button(i)] for i in range(4)] # a List of lists of buttons. Notice the ] after Button
+
+ window = sg.Window('Generated Layouts', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct #2 - List comprehension to generate a row of Buttons and concatenation of more lines of elements
+
+ Comprehensions are super-powers of Python. In this example we're using a comprehension to create 4 buttons that
+ are all on the same row, just like the previous example.
+ However, here, we want to not just have a row of buttons, we want have an OK button at the bottom.
+ To do this, you "add" the rest of the GUI layout onto the end of the generated part.
+
+ Note - you can't end the layout line after the +. If you wanted to put the OK button on the next line, you need
+ to add a \ at the end of the first line.
+ See next Construct on how to not use a \ that also results in a VISUALLY similar to a norma layout
+"""
+
+def layout2():
+ layout = [[sg.Button(i) for i in range(4)]] + [[sg.OK()]] # if want to split, can't add newline after + to do it
+
+ window = sg.Window('Generated Layouts', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct # 3 - Adding together what appears to be 2 layouts
+
+ Same as layout2, except that the OK button is put on another line without using a \ so that the layout appears to
+ look like a normal, multiline layout without a \ at the end
+
+ Also shown is the OLD tried and true way, using layout.append. You will see the append technique in many of the
+ Demo programs and probably elsewhere. Hoping to remove these and instead use this more explicit method of +=.
+
+ Using the + operator, as you've already seen, can be used in the middle of the layout. A call to append you cannot
+ use this way because it modifies the layout list directly.
+"""
+
+def layout3():
+ # in terms of formatting, the layout to the RIGHT of the = sign looks like a 2-line GUI (ignore the layout +=
+ layout = [[sg.Button(i) for i in range(4)]]
+ layout += [[sg.OK()]] # this row is better than, but is the same as
+ layout.append([sg.Cancel()]) # .. this row in that they both add a new ROW with a button on it
+
+ window = sg.Window('Generated Layouts', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct 4 - Using + to place Elements on the same row
+
+ If you want to put elements on the same row, you can simply add them together. All that is happening is that the
+ items in one list are added to the items in another. That's true for all these contructs using +
+"""
+
+def layout4():
+ layout = [[sg.Text('Enter some info')] + [sg.Input()] + [sg.Exit()]]
+
+ window = sg.Window('Generated Layouts', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct #5 - Simple "concatenation" of layouts
+ Layouts are lists of lists. Some of the examples and demo programs use a .append method to add rows to layouts.
+ These will soono be replaced with this new technique. It's so simple that I don't know why it took so long to
+ find it.
+ This layout uses list comprehensions heavily, and even uses 2 of them. So, if you find them confusing, skip down
+ to the next Construct and you'll see the same layout built except for loops are used rather than comprehensions
+
+ The next 3 examples all use this same window that is layed out like this:
+ Each row is:
+ Text1, Text2, Radio1, Radio2, Radio3, Radio4, Radio5
+ Text1, Text2, Radio1, Radio2, Radio3, Radio4, Radio5
+ ...
+
+ It shows, in particular, this handy bit of layout building, a += to add on additional rows.
+ layout = [[stuff on row 1], [stuff on row 2]]
+ layout += [[stuff on row 3]]
+
+ Works as long as the things you are adding together look like this [[ ]] (the famous double bracket layouts of PSG)
+"""
+
+def layout5():
+ questions = ('Managing your day-to-day life', 'Coping with problems in your life?', 'Concentrating?',
+ 'Get along with people in your family?', 'Get along with people outside your family?',
+ 'Get along well in social situations?', 'Feel close to another person',
+ 'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
+
+ layout = [[sg.T(qnum + 1, size=(2, 2)), sg.T(q, size=(30, 2))] + [sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, col)) for col in range(5)] for qnum, q in enumerate(questions)]
+ layout += [[sg.OK()]]
+
+ window = sg.Window('Computed Layout Questionnaire', layout)
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct #6 - Computed layout without using list comprehensions
+ This layout is identical to Contruct #5. The difference is that rather than use list comprehensions, this code
+ uses for loops. Perhaps if you're a beginner this version makes more sense?
+
+ In this example we start with a "blank layout" [[ ]] and add onto it.
+
+ Works as long as the things you are adding together look like this [[ ]] (the famous double bracket layouts of PSG)
+"""
+
+
+def layout6():
+ questions = ('Managing your day-to-day life', 'Coping with problems in your life?', 'Concentrating?',
+ 'Get along with people in your family?', 'Get along with people outside your family?',
+ 'Get along well in social situations?', 'Feel close to another person',
+ 'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
+
+ layout = [[]]
+ for qnum, question in enumerate(questions): # loop through questions
+ row_layout = [sg.T(qnum + 1, size=(2, 2)), sg.T(question, size=(30, 2))] # rows start with # and question
+ for radio_num in range(5): # loop through 5 radio buttons and add to row
+ row_layout += [sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, radio_num))]
+ layout += [row_layout] # after row is completed layout, tack it onto the end of final layout
+
+ layout += [[sg.OK()]] # and finally, add a row to the bottom that has an OK button
+
+ window = sg.Window('Computed Layout Questionnaire', layout)
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+
+"""
+ Construct #7 - * operator and list comprehensions
+ Using the * operator from inside the layout
+ List comprehension inside the layout
+ Addition of rows to layouts
+ All in a single variable assignment
+
+ NOTE - this particular code, using the * operator, will not work on Python 2 and think it was added in Python 3.5
+
+ This code shows a bunch of questions with Radio Button choices
+
+ There is a double-loop comprehension used. One that loops through the questions (rows) and the other loops through
+ the Radio Button choices.
+ Thus each row is:
+ Text1, Text2, Radio1, Radio2, Radio3, Radio4, Radio5
+ Text1, Text2, Radio1, Radio2, Radio3, Radio4, Radio5
+ Text1, Text2, Radio1, Radio2, Radio3, Radio4, Radio5
+
+ What the * operator is doing in these cases is expanding the list they are in front of into a SERIES of items
+ from the list... one after another, as if they are separated with comma. It's a way of "unpacking" from within
+ a statement.
+
+ The result is a beautifully compact way to make a layout, still using a layout variable, that consists of a
+ variable number of rows and a variable number of columns in each row.
+"""
+
+def layout7():
+ questions = ('Managing your day-to-day life', 'Coping with problems in your life?', 'Concentrating?',
+ 'Get along with people in your family?', 'Get along with people outside your family?',
+ 'Get along well in social situations?', 'Feel close to another person',
+ 'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
+
+ layout = [[*[sg.T(qnum + 1, size=(2, 2)), sg.T(q, size=(30, 2))], # These are the question # and the question text
+ *[sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, col)) for col in range(5)]] for qnum, q in enumerate(questions)] + [[sg.OK()]] # finally add an OK button at the very bottom by using the '+' operator
+
+ window = sg.Window('Questionnaire', layout)
+
+ event, values = window.Read()
+
+ print(event, values)
+ window.Close()
+
+
+"""
+ Construct #8 - Computed layout using list comprehension and concatenation
+ This layout shows one practical use, a multiple choice test. It's been left parse as to focus on the generation
+ part of the program. For example, default keys are used on the Radio elements. In reality you would likely
+ use a tuple of the question number and the answer number.
+
+ In this example we start with a "Header" Text element and build from there.
+"""
+
+def layout8():
+ # The questions and answers
+ q_and_a = [
+ ['1. What is the thing that makes light in our solar system', ['A. The Moon', 'B. Jupiter', 'C. I dunno']],
+ ['2. What is Pluto', ['A. The 9th planet', 'B. A dwarf-planet', 'C. The 8th planet', 'D. Goofies pet dog']],
+ ['3. When did man step foot on the moon', ['A. 1969', 'B. 1960', 'C. 1970', 'D. 1869']], ]
+
+ layout = [[sg.Text('Astronomy Quiz #1', font='ANY 15', size=(30, 2))]] # make Header larger
+
+ # "generate" the layout for the window based on the Question and Answer information
+ for qa in q_and_a:
+ q = qa[0]
+ a_list = qa[1]
+ layout += [[sg.Text(q)]] + [[sg.Radio(a, group_id=q)] for a in a_list] + [[sg.Text('_' * 50)]]
+
+ layout += [[sg.Button('Submit Answers', key='SUBMIT')]]
+
+ window = sg.Window('Multiple Choice Test', layout)
+
+ while True: # Event Loop
+ event, values = window.read()
+ if event in (None, 'SUBMIT'):
+ break
+ sg.popup('The answers submitted were', values)
+ window.close()
+
+
+# ------------------------- Call each of the Constructs -------------------------
+
+layout0()
+layout1()
+layout2()
+layout3()
+layout4()
+layout5()
+layout6()
+layout7()
+layout8()
diff --git a/DemoPrograms old/Demo_Listbox_Search_Filter.py b/DemoPrograms old/Demo_Listbox_Search_Filter.py
new file mode 100644
index 000000000..88f4ce45f
--- /dev/null
+++ b/DemoPrograms old/Demo_Listbox_Search_Filter.py
@@ -0,0 +1,27 @@
+import PySimpleGUI as sg
+
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+layout = [ [sg.Text('Listbox with search')],
+ [sg.Input(do_not_clear=True, size=(20,1),enable_events=True, key='_INPUT_')],
+ [sg.Listbox(names, size=(20,4), enable_events=True, key='_LIST_')],
+ [sg.Button('Chrome'), sg.Button('Exit')]]
+
+window = sg.Window('Listbox with Search').Layout(layout)
+# Event Loop
+while True:
+ event, values = window.Read()
+ if event is None or event == 'Exit': # always check for closed window
+ break
+ if values['_INPUT_'] != '': # if a keystroke entered in search field
+ search = values['_INPUT_']
+ new_values = [x for x in names if search in x] # do the filtering
+ window.Element('_LIST_').Update(new_values) # display in the listbox
+ else:
+ window.Element('_LIST_').Update(names) # display original unfiltered list
+ if event == '_LIST_' and len(values['_LIST_']): # if a list item is chosen
+ sg.Popup('Selected ', values['_LIST_'])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_MIDI_Player.py b/DemoPrograms old/Demo_MIDI_Player.py
new file mode 100644
index 000000000..11b4445cf
--- /dev/null
+++ b/DemoPrograms old/Demo_MIDI_Player.py
@@ -0,0 +1,227 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import os
+import mido
+import time
+import sys
+
+PLAYER_COMMAND_NONE = 0
+PLAYER_COMMAND_EXIT = 1
+PLAYER_COMMAND_PAUSE = 2
+PLAYER_COMMAND_NEXT = 3
+PLAYER_COMMAND_RESTART_SONG = 4
+
+# ---------------------------------------------------------------------- #
+# PlayerGUI CLASS #
+# ---------------------------------------------------------------------- #
+class PlayerGUI():
+ '''
+ Class implementing GUI for both initial screen but the player itself
+ '''
+
+ def __init__(self):
+ self.Window = None
+ self.TextElem = None
+ self.PortList = mido.get_output_names() # use to get the list of midi ports
+ self.PortList = self.PortList[::-1] # reverse the list so the last one is first
+
+ # ---------------------------------------------------------------------- #
+ # PlayerChooseSongGUI #
+ # Show a GUI get to the file to playback #
+ # ---------------------------------------------------------------------- #
+ def PlayerChooseSongGUI(self):
+
+ # ---------------------- DEFINION OF CHOOSE WHAT TO PLAY GUI ----------------------------
+
+ layout = [[sg.Text('MIDI File Player', font=("Helvetica", 15), size=(20, 1), text_color='green')],
+ [sg.Text('File Selection', font=("Helvetica", 15), size=(20, 1))],
+ [sg.Text('Single File Playback', justification='right'), sg.InputText(size=(65, 1), key='midifile'), sg.FileBrowse(size=(10, 1), file_types=(("MIDI files", "*.mid"),))],
+ [sg.Text('Or Batch Play From This Folder', auto_size_text=False, justification='right'), sg.InputText(size=(65, 1), key='folder'), sg.FolderBrowse(size=(10, 1))],
+ [sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
+ [sg.Text('Choose MIDI Output Device', size=(22, 1)),
+ sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), key='device')],
+ [sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
+ [sg.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=("Helvetica", 15), bind_return_key=True), sg.Text(' ' * 2, size=(4, 1)), sg.Cancel(size=(8, 2), font=("Helvetica", 15))]]
+
+ window = sg.Window('MIDI File Player', auto_size_text=False, default_element_size=(30, 1), font=("Helvetica", 12)).Layout(layout)
+ self.Window = window
+ return window.Read()
+
+
+ def PlayerPlaybackGUIStart(self, NumFiles=1):
+ # ------- Make a new FlexForm ------- #
+
+ image_pause = './ButtonGraphics/Pause.png'
+ image_restart = './ButtonGraphics/Restart.png'
+ image_next = './ButtonGraphics/Next.png'
+ image_exit = './ButtonGraphics/Exit.png'
+
+ self.TextElem = sg.T('Song loading....', size=(70, 5 + NumFiles), font=("Helvetica", 14), auto_size_text=False)
+ self.SliderElem = sg.Slider(range=(1, 100), size=(50, 8), orientation='h', text_color='#f0f0f0')
+ layout = [
+ [sg.T('MIDI File Player', size=(30, 1), font=("Helvetica", 25))],
+ [self.TextElem],
+ [self.SliderElem],
+ [sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
+ image_filename=image_pause, image_size=(50,50), image_subsample=2, border_width=0, key='PAUSE'), sg.T(' '),
+ sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
+ image_filename=image_next, image_size=(50,50), image_subsample=2, border_width=0, key='NEXT'), sg.T(' '),
+ sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
+ image_filename=image_restart, image_size=(50,50), image_subsample=2, border_width=0, key='Restart Song'), sg.T(' '),
+ sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
+ image_filename=image_exit, image_size=(50,50), image_subsample=2, border_width=0,key='EXIT')]
+ ]
+
+ window = sg.Window('MIDI File Player', default_element_size=(30, 1), font=("Helvetica", 25)).Layout(layout).Finalize()
+ self.Window = window
+
+
+
+ # ------------------------------------------------------------------------- #
+ # PlayerPlaybackGUIUpdate #
+ # Refresh the GUI for the main playback interface (must call periodically #
+ # ------------------------------------------------------------------------- #
+ def PlayerPlaybackGUIUpdate(self, DisplayString):
+ window = self.Window
+ if 'window' not in locals() or window is None: # if the widnow has been destoyed don't mess with it
+ return PLAYER_COMMAND_EXIT
+ self.TextElem.Update(DisplayString)
+ event, (values) = window.Read(timeout=0)
+ if event is None:
+ return PLAYER_COMMAND_EXIT
+ if event == 'PAUSE':
+ return PLAYER_COMMAND_PAUSE
+ elif event == 'EXIT':
+ return PLAYER_COMMAND_EXIT
+ elif event == 'NEXT':
+ return PLAYER_COMMAND_NEXT
+ elif event == 'Restart Song':
+ return PLAYER_COMMAND_RESTART_SONG
+ return PLAYER_COMMAND_NONE
+
+
+# ---------------------------------------------------------------------- #
+# MAIN - our main program... this is it #
+# Runs the GUI to get the file / path to play #
+# Decodes the MIDI-Video into a MID file #
+# Plays the decoded MIDI file #
+# ---------------------------------------------------------------------- #
+def main():
+ def GetCurrentTime():
+ '''
+ Get the current system time in milliseconds
+ :return: milliseconds
+ '''
+ return int(round(time.time() * 1000))
+
+
+ pback = PlayerGUI()
+
+ button, values = pback.PlayerChooseSongGUI()
+ if button != 'PLAY':
+ sg.PopupCancel('Cancelled...\nAutoclose in 2 sec...', auto_close=True, auto_close_duration=2)
+ sys.exit(69)
+ if values['device']:
+ midi_port = values['device'][0]
+ else:
+ sg.PopupCancel('No devices found\nAutoclose in 2 sec...', auto_close=True, auto_close_duration=2)
+
+ batch_folder = values['folder']
+ midi_filename = values['midifile']
+ # ------ Build list of files to play --------------------------------------------------------- #
+ if batch_folder:
+ filelist = os.listdir(batch_folder)
+ filelist = [batch_folder+'/'+f for f in filelist if f.endswith(('.mid', '.MID'))]
+ filetitles = [os.path.basename(f) for f in filelist]
+ elif midi_filename: # an individual filename
+ filelist = [midi_filename,]
+ filetitles = [os.path.basename(midi_filename),]
+ else:
+ sg.PopupError('*** Error - No MIDI files specified ***')
+ sys.exit(666)
+
+ # ------ LOOP THROUGH MULTIPLE FILES --------------------------------------------------------- #
+ pback.PlayerPlaybackGUIStart(NumFiles=len(filelist) if len(filelist) <=10 else 10)
+ port = None
+ # Loop through the files in the filelist
+ for now_playing_number, current_midi_filename in enumerate(filelist):
+ display_string = 'Playing Local File...\n{} of {}\n{}'.format(now_playing_number+1, len(filelist), current_midi_filename)
+ midi_title = filetitles[now_playing_number]
+ # --------------------------------- REFRESH THE GUI ----------------------------------------- #
+ pback.PlayerPlaybackGUIUpdate(display_string)
+
+ # ---===--- Output Filename is .MID --- #
+ midi_filename = current_midi_filename
+
+ # --------------------------------- MIDI - STARTS HERE ----------------------------------------- #
+ if not port: # if the midi output port not opened yet, then open it
+ port = mido.open_output(midi_port if midi_port else None)
+
+ try:
+ mid = mido.MidiFile(filename=midi_filename)
+ except:
+ print('****** Exception trying to play MidiFile filename = {}***************'.format(midi_filename))
+ sg.PopupError('Exception trying to play MIDI file:', midi_filename, 'Skipping file')
+ continue
+
+ # Build list of data contained in MIDI File using only track 0
+ midi_length_in_seconds = mid.length
+ display_file_list = '>> ' + '\n'.join([f for i, f in enumerate(filetitles[now_playing_number:]) if i < 10])
+ paused = cancelled = next_file = False
+ ######################### Loop through MIDI Messages ###########################
+ while(True):
+ start_playback_time = GetCurrentTime()
+ port.reset()
+
+ for midi_msg_number, msg in enumerate(mid.play()):
+ #################### GUI - read values ##################
+ if not midi_msg_number % 4: # update the GUI every 4 MIDI messages
+ t = (GetCurrentTime() - start_playback_time)//1000
+ display_midi_len = '{:02d}:{:02d}'.format(*divmod(int(midi_length_in_seconds),60))
+ display_string = 'Now Playing {} of {}\n{}\n {:02d}:{:02d} of {}\nPlaylist:'.\
+ format(now_playing_number+1, len(filelist), midi_title, *divmod(t, 60), display_midi_len)
+ # display list of next 10 files to be played.
+ pback.SliderElem.Update(t, range=(1,midi_length_in_seconds))
+ rc = pback.PlayerPlaybackGUIUpdate(display_string + '\n' + display_file_list)
+ else: # fake rest of code as if GUI did nothing
+ rc = PLAYER_COMMAND_NONE
+ if paused:
+ rc = PLAYER_COMMAND_NONE
+ while rc == PLAYER_COMMAND_NONE: # TIGHT-ASS loop waiting on a GUI command
+ rc = pback.PlayerPlaybackGUIUpdate(display_string)
+ time.sleep(.25)
+
+ ####################################### MIDI send data ##################################
+ port.send(msg)
+
+ # ------- Execute GUI Commands after sending MIDI data ------- #
+ if rc == PLAYER_COMMAND_EXIT:
+ cancelled = True
+ break
+ elif rc == PLAYER_COMMAND_PAUSE:
+ paused = not paused
+ port.reset()
+ elif rc == PLAYER_COMMAND_NEXT:
+ next_file = True
+ break
+ elif rc == PLAYER_COMMAND_RESTART_SONG:
+ break
+
+ if cancelled or next_file:
+ break
+ #------- DONE playing the song ------- #
+ port.reset() # reset the midi port when done with the song
+
+ if cancelled:
+ break
+
+# ---------------------------------------------------------------------- #
+# LAUNCH POINT -- program starts and ends here #
+# ---------------------------------------------------------------------- #
+if __name__ == '__main__':
+ main()
+
diff --git a/DemoPrograms old/Demo_Machine_Learning.py b/DemoPrograms old/Demo_Machine_Learning.py
new file mode 100644
index 000000000..0b5881f11
--- /dev/null
+++ b/DemoPrograms old/Demo_Machine_Learning.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+def MachineLearningGUI():
+ sg.SetOptions(text_justification='right')
+
+ flags = [[sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))],
+ [sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)],
+ [sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))],
+ [sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))],
+ [sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)],
+ [sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))],]
+
+ loss_functions = [[sg.Radio('Cross-Entropy', 'loss', size=(12, 1)), sg.Radio('Logistic', 'loss', default=True, size=(12, 1))],
+ [sg.Radio('Hinge', 'loss', size=(12, 1)), sg.Radio('Huber', 'loss', size=(12, 1))],
+ [sg.Radio('Kullerback', 'loss', size=(12, 1)), sg.Radio('MAE(L1)', 'loss', size=(12, 1))],
+ [sg.Radio('MSE(L2)', 'loss', size=(12, 1)), sg.Radio('MB(L0)', 'loss', size=(12, 1))],]
+
+ command_line_parms = [[sg.Text('Passes', size=(8, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)),
+ sg.Text('Steps', size=(8, 1), pad=((7,3))), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))],
+ [sg.Text('ooa', size=(8, 1)), sg.In(default_text='6', size=(8, 1)), sg.Text('nn', size=(8, 1)),
+ sg.In(default_text='10', size=(10, 1))],
+ [sg.Text('q', size=(8, 1)), sg.In(default_text='ff', size=(8, 1)), sg.Text('ngram', size=(8, 1)),
+ sg.In(default_text='5', size=(10, 1))],
+ [sg.Text('l', size=(8, 1)), sg.In(default_text='0.4', size=(8, 1)), sg.Text('Layers', size=(8, 1)),
+ sg.Drop(values=('BatchNorm', 'other'), auto_size_text=True)],]
+
+ layout = [[sg.Frame('Command Line Parameteres', command_line_parms, title_color='green', font='Any 12')],
+ [sg.Frame('Flags', flags, font='Any 12', title_color='blue')],
+ [sg.Frame('Loss Functions', loss_functions, font='Any 12', title_color='red')],
+ [sg.Submit(), sg.Cancel()]]
+
+ window = sg.Window('Machine Learning Front End', font=("Helvetica", 12)).Layout(layout)
+ button, values = window.Read()
+ sg.SetOptions(text_justification='left')
+
+ print(button, values)
+
+def CustomMeter():
+ # layout the form
+ layout = [[sg.Text('A custom progress meter')],
+ [sg.ProgressBar(1000, orientation='h', size=(20,20), key='progress')],
+ [sg.Cancel()]]
+
+ # create the form`
+ window = sg.Window('Custom Progress Meter').Layout(layout)
+ progress_bar = window.FindElement('progress')
+ # loop that would normally do something useful
+ for i in range(1000):
+ # check to see if the cancel button was clicked and exit loop if clicked
+ event, values = window.Read(timeout=0, timeout_key='timeout')
+ if event == 'Cancel' or event == None:
+ break
+ # update bar with loop value +1 so that bar eventually reaches the maximum
+ progress_bar.UpdateBar(i+1)
+ # done with loop... need to destroy the window as it's still open
+ window.CloseNonBlocking()
+
+if __name__ == '__main__':
+ CustomMeter()
+ MachineLearningGUI()
diff --git a/DemoPrograms old/Demo_Matplotlib.py b/DemoPrograms old/Demo_Matplotlib.py
new file mode 100644
index 000000000..63164465d
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+
+import matplotlib
+matplotlib.use('TkAgg')
+
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+
+ Based on information from: https://matplotlib.org/3.1.0/gallery/user_interfaces/embedding_in_tk_sgskip.html
+ (Thank you Em-Bo & dirck)
+"""
+
+
+#------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+from matplotlib.ticker import NullFormatter # useful for `logit` scale
+
+# Fixing random state for reproducibility
+np.random.seed(19680801)
+
+# make up some data in the interval ]0, 1[
+y = np.random.normal(loc=0.5, scale=0.4, size=1000)
+y = y[(y > 0) & (y < 1)]
+y.sort()
+x = np.arange(len(y))
+
+# plot with various axes scales
+plt.figure(1)
+
+# linear
+plt.subplot(221)
+plt.plot(x, y)
+plt.yscale('linear')
+plt.title('linear')
+plt.grid(True)
+
+
+# log
+plt.subplot(222)
+plt.plot(x, y)
+plt.yscale('log')
+plt.title('log')
+plt.grid(True)
+
+
+# symmetric log
+plt.subplot(223)
+plt.plot(x, y - y.mean())
+plt.yscale('symlog', linthreshy=0.01)
+plt.title('symlog')
+plt.grid(True)
+
+# logit
+plt.subplot(224)
+plt.plot(x, y)
+plt.yscale('logit')
+plt.title('logit')
+plt.grid(True)
+plt.gca().yaxis.set_minor_formatter(NullFormatter())
+plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
+ wspace=0.35)
+fig = plt.gcf() # if using Pyplot then get the figure from the plot
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
+
+#------------------------------- Beginning of Matplotlib helper code -----------------------
+
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+#------------------------------- Beginning of GUI CODE -------------------------------
+
+# define the window layout
+layout = [[sg.Text('Plot test', font='Any 18')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
+
+# add the plot to the window
+fig_canvas_agg = draw_figure(window['canvas'].TKCanvas, fig)
+
+event, values = window.read()
diff --git a/DemoPrograms old/Demo_Matplotlib_Animated.py b/DemoPrograms old/Demo_Matplotlib_Animated.py
new file mode 100644
index 000000000..da28c03c5
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Animated.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+
+from random import randint
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
+from matplotlib.figure import Figure
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+
+def main():
+
+ NUM_DATAPOINTS = 10000
+ # define the form layout
+ layout = [[sg.Text('Animated Matplotlib', size=(40, 1), justification='center', font='Helvetica 20')],
+ [sg.Canvas(size=(640, 480), key='-CANVAS-')],
+ [sg.Text('Progress through the data')],
+ [sg.Slider(range=(0, NUM_DATAPOINTS), size=(60, 10), orientation='h', key='-SLIDER-')],
+ [sg.Text('Number of data points to display on screen')],
+ [sg.Slider(range=(10, 500), default_value=40, size=(40, 10), orientation='h', key='-SLIDER-DATAPOINTS-')],
+ [sg.Button('Exit', size=(10, 1), pad=((280, 0), 3), font='Helvetica 14')]]
+
+ # create the form and show it without the plot
+ window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
+
+ canvas_elem = window.FindElement('-CANVAS-')
+ slider_elem = window.FindElement('-SLIDER-')
+ canvas = canvas_elem.TKCanvas
+
+ # draw the initial plot in the window
+ fig = Figure()
+ ax = fig.add_subplot(111)
+ ax.set_xlabel("X axis")
+ ax.set_ylabel("Y axis")
+ ax.grid()
+ fig_agg = draw_figure(canvas, fig)
+ # make a bunch of random data points
+ dpts = [randint(0, 10) for x in range(NUM_DATAPOINTS)]
+
+ for i in range(len(dpts)):
+ event, values = window.Read(timeout=10)
+ if event in ('Exit', None):
+ exit(69)
+ slider_elem.Update(i) # slider shows "progress" through the data points
+ ax.cla() # clear the subplot
+ ax.grid() # draw the grid
+ data_points = int(values['-SLIDER-DATAPOINTS-']) # draw this many data points (on next line)
+ ax.plot(range(data_points), dpts[i:i+data_points], color='purple')
+ fig_agg.draw()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Matplotlib_Animated_Scatter.py b/DemoPrograms old/Demo_Matplotlib_Animated_Scatter.py
new file mode 100644
index 000000000..21df8cdfd
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Animated_Scatter.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+
+import PySimpleGUI as sg
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+import matplotlib.pyplot as plt
+from numpy.random import rand
+
+def draw_figure(canvas, figure):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+
+
+
+
+def main():
+ # define the form layout
+ layout = [[sg.Text('Animated Matplotlib', size=(40, 1), justification='center', font='Helvetica 20')],
+ [sg.Canvas(size=(640, 480), key='-CANVAS-')],
+ [sg.Button('Exit', size=(10, 2), pad=((280, 0), 3), font='Helvetica 14')]]
+
+ # create the form and show it without the plot
+ window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
+
+ canvas_elem = window.FindElement('-CANVAS-')
+ canvas = canvas_elem.TKCanvas
+ # draw the intitial scatter plot
+ fig, ax = plt.subplots()
+ ax.grid(True)
+ fig_agg = draw_figure(canvas, fig)
+
+ while True:
+ event, values = window.Read(timeout=10)
+ if event in ('Exit', None):
+ exit(69)
+
+ ax.cla()
+ ax.grid(True)
+ for color in ['red', 'green', 'blue']:
+ n = 750
+ x, y = rand(2, n)
+ scale = 200.0 * rand(n)
+ ax.scatter(x, y, c=color, s=scale, label=color, alpha=0.3, edgecolors='none')
+ ax.legend()
+ fig_agg.draw()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Matplotlib_Browser.py b/DemoPrograms old/Demo_Matplotlib_Browser.py
new file mode 100644
index 000000000..a05242b02
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Browser.py
@@ -0,0 +1,878 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import matplotlib
+matplotlib.use('TkAgg')
+import inspect
+
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+
+Each plotting function, complete with imports, was copied directly from Matplot examples page
+"""
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+def PyplotSimple():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # evenly sampled time .2 intervals
+ t = np.arange(0., 5., 0.2) # go from 0 to 5 using .2 intervals
+
+ # red dashes, blue squares and green triangles
+ plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^')
+
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def PyplotHistogram():
+ """
+ =============================================================
+ Demo of the histogram (hist) function with multiple data sets
+ =============================================================
+
+ Plot histogram with multiple sample sets and demonstrate:
+
+ * Use of legend with multiple sample sets
+ * Stacked bars
+ * Step curve with no fill
+ * Data sets of different sample sizes
+
+ Selecting different bin counts and sizes can significantly affect the
+ shape of a histogram. The Astropy docs have a great section on how to
+ select these parameters:
+ http://docs.astropy.org/en/stable/visualization/histogram.html
+ """
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ np.random.seed(0)
+
+ n_bins = 10
+ x = np.random.randn(1000, 3)
+
+ fig, axes = plt.subplots(nrows=2, ncols=2)
+ ax0, ax1, ax2, ax3 = axes.flatten()
+
+ colors = ['red', 'tan', 'lime']
+ ax0.hist(x, n_bins, normed=1, histtype='bar', color=colors, label=colors)
+ ax0.legend(prop={'size': 10})
+ ax0.set_title('bars with legend')
+
+ ax1.hist(x, n_bins, normed=1, histtype='bar', stacked=True)
+ ax1.set_title('stacked bar')
+
+ ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False)
+ ax2.set_title('stack step (unfilled)')
+
+ # Make a multiple-histogram of data-sets with different length.
+ x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
+ ax3.hist(x_multi, n_bins, histtype='bar')
+ ax3.set_title('different sample sizes')
+
+ fig.tight_layout()
+ return fig
+
+def PyplotArtistBoxPlots():
+ """
+ =========================================
+ Demo of artist customization in box plots
+ =========================================
+
+ This example demonstrates how to use the various kwargs
+ to fully customize box plots. The first figure demonstrates
+ how to remove and add individual components (note that the
+ mean is the only value not shown by default). The second
+ figure demonstrates how the styles of the artists can
+ be customized. It also demonstrates how to set the limit
+ of the whiskers to specific percentiles (lower right axes)
+
+ A good general reference on boxplots and their history can be found
+ here: http://vita.had.co.nz/papers/boxplots.pdf
+
+ """
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # fake data
+ np.random.seed(937)
+ data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
+ labels = list('ABCD')
+ fs = 10 # fontsize
+
+ # demonstrate how to toggle the display of different elements:
+ fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
+ axes[0, 0].boxplot(data, labels=labels)
+ axes[0, 0].set_title('Default', fontsize=fs)
+
+ axes[0, 1].boxplot(data, labels=labels, showmeans=True)
+ axes[0, 1].set_title('showmeans=True', fontsize=fs)
+
+ axes[0, 2].boxplot(data, labels=labels, showmeans=True, meanline=True)
+ axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs)
+
+ axes[1, 0].boxplot(data, labels=labels, showbox=False, showcaps=False)
+ tufte_title = 'Tufte Style \n(showbox=False,\nshowcaps=False)'
+ axes[1, 0].set_title(tufte_title, fontsize=fs)
+
+ axes[1, 1].boxplot(data, labels=labels, notch=True, bootstrap=10000)
+ axes[1, 1].set_title('notch=True,\nbootstrap=10000', fontsize=fs)
+
+ axes[1, 2].boxplot(data, labels=labels, showfliers=False)
+ axes[1, 2].set_title('showfliers=False', fontsize=fs)
+
+ for ax in axes.flatten():
+ ax.set_yscale('log')
+ ax.set_yticklabels([])
+
+ fig.subplots_adjust(hspace=0.4)
+ return fig
+
+def ArtistBoxplot2():
+
+ # fake data
+ np.random.seed(937)
+ data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
+ labels = list('ABCD')
+ fs = 10 # fontsize
+
+ # demonstrate how to customize the display different elements:
+ boxprops = dict(linestyle='--', linewidth=3, color='darkgoldenrod')
+ flierprops = dict(marker='o', markerfacecolor='green', markersize=12,
+ linestyle='none')
+ medianprops = dict(linestyle='-.', linewidth=2.5, color='firebrick')
+ meanpointprops = dict(marker='D', markeredgecolor='black',
+ markerfacecolor='firebrick')
+ meanlineprops = dict(linestyle='--', linewidth=2.5, color='purple')
+
+ fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
+ axes[0, 0].boxplot(data, boxprops=boxprops)
+ axes[0, 0].set_title('Custom boxprops', fontsize=fs)
+
+ axes[0, 1].boxplot(data, flierprops=flierprops, medianprops=medianprops)
+ axes[0, 1].set_title('Custom medianprops\nand flierprops', fontsize=fs)
+
+ axes[0, 2].boxplot(data, whis='range')
+ axes[0, 2].set_title('whis="range"', fontsize=fs)
+
+ axes[1, 0].boxplot(data, meanprops=meanpointprops, meanline=False,
+ showmeans=True)
+ axes[1, 0].set_title('Custom mean\nas point', fontsize=fs)
+
+ axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True,
+ showmeans=True)
+ axes[1, 1].set_title('Custom mean\nas line', fontsize=fs)
+
+ axes[1, 2].boxplot(data, whis=[15, 85])
+ axes[1, 2].set_title('whis=[15, 85]\n#percentiles', fontsize=fs)
+
+ for ax in axes.flatten():
+ ax.set_yscale('log')
+ ax.set_yticklabels([])
+
+ fig.suptitle("I never said they'd be pretty")
+ fig.subplots_adjust(hspace=0.4)
+ return fig
+
+def PyplotScatterWithLegend():
+ import matplotlib.pyplot as plt
+ from numpy.random import rand
+
+ fig, ax = plt.subplots()
+ for color in ['red', 'green', 'blue']:
+ n = 750
+ x, y = rand(2, n)
+ scale = 200.0 * rand(n)
+ ax.scatter(x, y, c=color, s=scale, label=color,
+ alpha=0.3, edgecolors='none')
+
+ ax.legend()
+ ax.grid(True)
+ return fig
+
+def PyplotLineStyles():
+ """
+ ==========
+ Linestyles
+ ==========
+
+ This examples showcases different linestyles copying those of Tikz/PGF.
+ """
+ import numpy as np
+ import matplotlib.pyplot as plt
+ from collections import OrderedDict
+ from matplotlib.transforms import blended_transform_factory
+
+ linestyles = OrderedDict(
+ [('solid', (0, ())),
+ ('loosely dotted', (0, (1, 10))),
+ ('dotted', (0, (1, 5))),
+ ('densely dotted', (0, (1, 1))),
+
+ ('loosely dashed', (0, (5, 10))),
+ ('dashed', (0, (5, 5))),
+ ('densely dashed', (0, (5, 1))),
+
+ ('loosely dashdotted', (0, (3, 10, 1, 10))),
+ ('dashdotted', (0, (3, 5, 1, 5))),
+ ('densely dashdotted', (0, (3, 1, 1, 1))),
+
+ ('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
+ ('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
+ ('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))])
+
+ plt.figure(figsize=(10, 6))
+ ax = plt.subplot(1, 1, 1)
+
+ X, Y = np.linspace(0, 100, 10), np.zeros(10)
+ for i, (name, linestyle) in enumerate(linestyles.items()):
+ ax.plot(X, Y + i, linestyle=linestyle, linewidth=1.5, color='black')
+
+ ax.set_ylim(-0.5, len(linestyles) - 0.5)
+ plt.yticks(np.arange(len(linestyles)), linestyles.keys())
+ plt.xticks([])
+
+ # For each line style, add a text annotation with a small offset from
+ # the reference point (0 in Axes coords, y tick value in Data coords).
+ reference_transform = blended_transform_factory(ax.transAxes, ax.transData)
+ for i, (name, linestyle) in enumerate(linestyles.items()):
+ ax.annotate(str(linestyle), xy=(0.0, i), xycoords=reference_transform,
+ xytext=(-6, -12), textcoords='offset points', color="blue",
+ fontsize=8, ha="right", family="monospace")
+
+ plt.tight_layout()
+ return plt.gcf()
+
+def PyplotLinePolyCollection():
+ import matplotlib.pyplot as plt
+ from matplotlib import collections, colors, transforms
+ import numpy as np
+
+ nverts = 50
+ npts = 100
+
+ # Make some spirals
+ r = np.arange(nverts)
+ theta = np.linspace(0, 2 * np.pi, nverts)
+ xx = r * np.sin(theta)
+ yy = r * np.cos(theta)
+ spiral = np.column_stack([xx, yy])
+
+ # Fixing random state for reproducibility
+ rs = np.random.RandomState(19680801)
+
+ # Make some offsets
+ xyo = rs.randn(npts, 2)
+
+ # Make a list of colors cycling through the default series.
+ colors = [colors.to_rgba(c)
+ for c in plt.rcParams['axes.prop_cycle'].by_key()['color']]
+
+ fig, axes = plt.subplots(2, 2)
+ fig.subplots_adjust(top=0.92, left=0.07, right=0.97,
+ hspace=0.3, wspace=0.3)
+ ((ax1, ax2), (ax3, ax4)) = axes # unpack the axes
+
+ col = collections.LineCollection([spiral], offsets=xyo,
+ transOffset=ax1.transData)
+ trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0 / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ # Note: the first argument to the collection initializer
+ # must be a list of sequences of x,y tuples; we have only
+ # one sequence, but we still have to put it in a list.
+ ax1.add_collection(col, autolim=True)
+ # autolim=True enables autoscaling. For collections with
+ # offsets like this, it is neither efficient nor accurate,
+ # but it is good enough to generate a plot that you can use
+ # as a starting point. If you know beforehand the range of
+ # x and y that you want to show, it is better to set them
+ # explicitly, leave out the autolim kwarg (or set it to False),
+ # and omit the 'ax1.autoscale_view()' call below.
+
+ # Make a transform for the line segments such that their size is
+ # given in points:
+ col.set_color(colors)
+
+ ax1.autoscale_view() # See comment above, after ax1.add_collection.
+ ax1.set_title('LineCollection using offsets')
+
+ # The same data as above, but fill the curves.
+ col = collections.PolyCollection([spiral], offsets=xyo,
+ transOffset=ax2.transData)
+ trans = transforms.Affine2D().scale(fig.dpi / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ ax2.add_collection(col, autolim=True)
+ col.set_color(colors)
+
+ ax2.autoscale_view()
+ ax2.set_title('PolyCollection using offsets')
+
+ # 7-sided regular polygons
+
+ col = collections.RegularPolyCollection(
+ 7, sizes=np.abs(xx) * 10.0, offsets=xyo, transOffset=ax3.transData)
+ trans = transforms.Affine2D().scale(fig.dpi / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ ax3.add_collection(col, autolim=True)
+ col.set_color(colors)
+ ax3.autoscale_view()
+ ax3.set_title('RegularPolyCollection using offsets')
+
+ # Simulate a series of ocean current profiles, successively
+ # offset by 0.1 m/s so that they form what is sometimes called
+ # a "waterfall" plot or a "stagger" plot.
+
+ nverts = 60
+ ncurves = 20
+ offs = (0.1, 0.0)
+
+ yy = np.linspace(0, 2 * np.pi, nverts)
+ ym = np.max(yy)
+ xx = (0.2 + (ym - yy) / ym) ** 2 * np.cos(yy - 0.4) * 0.5
+ segs = []
+ for i in range(ncurves):
+ xxx = xx + 0.02 * rs.randn(nverts)
+ curve = np.column_stack([xxx, yy * 100])
+ segs.append(curve)
+
+ col = collections.LineCollection(segs, offsets=offs)
+ ax4.add_collection(col, autolim=True)
+ col.set_color(colors)
+ ax4.autoscale_view()
+ ax4.set_title('Successive data offsets')
+ ax4.set_xlabel('Zonal velocity component (m/s)')
+ ax4.set_ylabel('Depth (m)')
+ # Reverse the y-axis so depth increases downward
+ ax4.set_ylim(ax4.get_ylim()[::-1])
+ return fig
+
+def PyplotGGPlotSytleSheet():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ plt.style.use('ggplot')
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ fig, axes = plt.subplots(ncols=2, nrows=2)
+ ax1, ax2, ax3, ax4 = axes.ravel()
+
+ # scatter plot (Note: `plt.scatter` doesn't use default colors)
+ x, y = np.random.normal(size=(2, 200))
+ ax1.plot(x, y, 'o')
+
+ # sinusoidal lines with colors from default color cycle
+ L = 2 * np.pi
+ x = np.linspace(0, L)
+ ncolors = len(plt.rcParams['axes.prop_cycle'])
+ shift = np.linspace(0, L, ncolors, endpoint=False)
+ for s in shift:
+ ax2.plot(x, np.sin(x + s), '-')
+ ax2.margins(0)
+
+ # bar graphs
+ x = np.arange(5)
+ y1, y2 = np.random.randint(1, 25, size=(2, 5))
+ width = 0.25
+ ax3.bar(x, y1, width)
+ ax3.bar(x + width, y2, width,
+ color=list(plt.rcParams['axes.prop_cycle'])[2]['color'])
+ ax3.set_xticks(x + width)
+ ax3.set_xticklabels(['a', 'b', 'c', 'd', 'e'])
+
+ # circles with colors from default color cycle
+ for i, color in enumerate(plt.rcParams['axes.prop_cycle']):
+ xy = np.random.normal(size=2)
+ ax4.add_patch(plt.Circle(xy, radius=0.3, color=color['color']))
+ ax4.axis('equal')
+ ax4.margins(0)
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def PyplotBoxPlot():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ # fake up some data
+ spread = np.random.rand(50) * 100
+ center = np.ones(25) * 50
+ flier_high = np.random.rand(10) * 100 + 100
+ flier_low = np.random.rand(10) * -100
+ data = np.concatenate((spread, center, flier_high, flier_low), 0)
+ fig1, ax1 = plt.subplots()
+ ax1.set_title('Basic Plot')
+ ax1.boxplot(data)
+ return fig1
+
+def PyplotRadarChart():
+ import numpy as np
+
+ import matplotlib.pyplot as plt
+ from matplotlib.path import Path
+ from matplotlib.spines import Spine
+ from matplotlib.projections.polar import PolarAxes
+ from matplotlib.projections import register_projection
+
+ def radar_factory(num_vars, frame='circle'):
+ """Create a radar chart with `num_vars` axes.
+
+ This function creates a RadarAxes projection and registers it.
+
+ Parameters
+ ----------
+ num_vars : int
+ Number of variables for radar chart.
+ frame : {'circle' | 'polygon'}
+ Shape of frame surrounding axes.
+
+ """
+ # calculate evenly-spaced axis angles
+ theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False)
+
+ def draw_poly_patch(self):
+ # rotate theta such that the first axis is at the top
+ verts = unit_poly_verts(theta + np.pi / 2)
+ return plt.Polygon(verts, closed=True, edgecolor='k')
+
+ def draw_circle_patch(self):
+ # unit circle centered on (0.5, 0.5)
+ return plt.Circle((0.5, 0.5), 0.5)
+
+ patch_dict = {'polygon': draw_poly_patch, 'circle': draw_circle_patch}
+ if frame not in patch_dict:
+ raise ValueError('unknown value for `frame`: %s' % frame)
+
+ class RadarAxes(PolarAxes):
+
+ name = 'radar'
+ # use 1 line segment to connect specified points
+ RESOLUTION = 1
+ # define draw_frame method
+ draw_patch = patch_dict[frame]
+
+ def __init__(self, *args, **kwargs):
+ super(RadarAxes, self).__init__(*args, **kwargs)
+ # rotate plot such that the first axis is at the top
+ self.set_theta_zero_location('N')
+
+ def fill(self, *args, **kwargs):
+ """Override fill so that line is closed by default"""
+ closed = kwargs.pop('closed', True)
+ return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)
+
+ def plot(self, *args, **kwargs):
+ """Override plot so that line is closed by default"""
+ lines = super(RadarAxes, self).plot(*args, **kwargs)
+ for line in lines:
+ self._close_line(line)
+
+ def _close_line(self, line):
+ x, y = line.get_data()
+ # FIXME: markers at x[0], y[0] get doubled-up
+ if x[0] != x[-1]:
+ x = np.concatenate((x, [x[0]]))
+ y = np.concatenate((y, [y[0]]))
+ line.set_data(x, y)
+
+ def set_varlabels(self, labels):
+ self.set_thetagrids(np.degrees(theta), labels)
+
+ def _gen_axes_patch(self):
+ return self.draw_patch()
+
+ def _gen_axes_spines(self):
+ if frame == 'circle':
+ return PolarAxes._gen_axes_spines(self)
+ # The following is a hack to get the spines (i.e. the axes frame)
+ # to draw correctly for a polygon frame.
+
+ # spine_type must be 'left', 'right', 'top', 'bottom', or `circle`.
+ spine_type = 'circle'
+ verts = unit_poly_verts(theta + np.pi / 2)
+ # close off polygon by repeating first vertex
+ verts.append(verts[0])
+ path = Path(verts)
+
+ spine = Spine(self, spine_type, path)
+ spine.set_transform(self.transAxes)
+ return {'polar': spine}
+
+ register_projection(RadarAxes)
+ return theta
+
+ def unit_poly_verts(theta):
+ """Return vertices of polygon for subplot axes.
+
+ This polygon is circumscribed by a unit circle centered at (0.5, 0.5)
+ """
+ x0, y0, r = [0.5] * 3
+ verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
+ return verts
+
+ def example_data():
+ # The following data is from the Denver Aerosol Sources and Health study.
+ # See doi:10.1016/j.atmosenv.2008.12.017
+ #
+ # The data are pollution source profile estimates for five modeled
+ # pollution sources (e.g., cars, wood-burning, etc) that emit 7-9 chemical
+ # species. The radar charts are experimented with here to see if we can
+ # nicely visualize how the modeled source profiles change across four
+ # scenarios:
+ # 1) No gas-phase species present, just seven particulate counts on
+ # Sulfate
+ # Nitrate
+ # Elemental Carbon (EC)
+ # Organic Carbon fraction 1 (OC)
+ # Organic Carbon fraction 2 (OC2)
+ # Organic Carbon fraction 3 (OC3)
+ # Pyrolized Organic Carbon (OP)
+ # 2)Inclusion of gas-phase specie carbon monoxide (CO)
+ # 3)Inclusion of gas-phase specie ozone (O3).
+ # 4)Inclusion of both gas-phase species is present...
+ data = [
+ ['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],
+ ('Basecase', [
+ [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],
+ [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],
+ [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],
+ [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],
+ [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]),
+ ('With CO', [
+ [0.88, 0.02, 0.02, 0.02, 0.00, 0.05, 0.00, 0.05, 0.00],
+ [0.08, 0.94, 0.04, 0.02, 0.00, 0.01, 0.12, 0.04, 0.00],
+ [0.01, 0.01, 0.79, 0.10, 0.00, 0.05, 0.00, 0.31, 0.00],
+ [0.00, 0.02, 0.03, 0.38, 0.31, 0.31, 0.00, 0.59, 0.00],
+ [0.02, 0.02, 0.11, 0.47, 0.69, 0.58, 0.88, 0.00, 0.00]]),
+ ('With O3', [
+ [0.89, 0.01, 0.07, 0.00, 0.00, 0.05, 0.00, 0.00, 0.03],
+ [0.07, 0.95, 0.05, 0.04, 0.00, 0.02, 0.12, 0.00, 0.00],
+ [0.01, 0.02, 0.86, 0.27, 0.16, 0.19, 0.00, 0.00, 0.00],
+ [0.01, 0.03, 0.00, 0.32, 0.29, 0.27, 0.00, 0.00, 0.95],
+ [0.02, 0.00, 0.03, 0.37, 0.56, 0.47, 0.87, 0.00, 0.00]]),
+ ('CO & O3', [
+ [0.87, 0.01, 0.08, 0.00, 0.00, 0.04, 0.00, 0.00, 0.01],
+ [0.09, 0.95, 0.02, 0.03, 0.00, 0.01, 0.13, 0.06, 0.00],
+ [0.01, 0.02, 0.71, 0.24, 0.13, 0.16, 0.00, 0.50, 0.00],
+ [0.01, 0.03, 0.00, 0.28, 0.24, 0.23, 0.00, 0.44, 0.88],
+ [0.02, 0.00, 0.18, 0.45, 0.64, 0.55, 0.86, 0.00, 0.16]])
+ ]
+ return data
+
+ N = 9
+ theta = radar_factory(N, frame='polygon')
+
+ data = example_data()
+ spoke_labels = data.pop(0)
+
+ fig, axes = plt.subplots(figsize=(9, 9), nrows=2, ncols=2,
+ subplot_kw=dict(projection='radar'))
+ fig.subplots_adjust(wspace=0.25, hspace=0.20, top=0.85, bottom=0.05)
+
+ colors = ['b', 'r', 'g', 'm', 'y']
+ # Plot the four cases from the example data on separate axes
+ for ax, (title, case_data) in zip(axes.flatten(), data):
+ ax.set_rgrids([0.2, 0.4, 0.6, 0.8])
+ ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),
+ horizontalalignment='center', verticalalignment='center')
+ for d, color in zip(case_data, colors):
+ ax.plot(theta, d, color=color)
+ ax.fill(theta, d, facecolor=color, alpha=0.25)
+ ax.set_varlabels(spoke_labels)
+
+ # add legend relative to top-left plot
+ ax = axes[0, 0]
+ labels = ('Factor 1', 'Factor 2', 'Factor 3', 'Factor 4', 'Factor 5')
+ legend = ax.legend(labels, loc=(0.9, .95),
+ labelspacing=0.1, fontsize='small')
+
+ fig.text(0.5, 0.965, '5-Factor Solution Profiles Across Four Scenarios',
+ horizontalalignment='center', color='black', weight='bold',
+ size='large')
+ return fig
+
+def DifferentScales():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # Create some mock data
+ t = np.arange(0.01, 10.0, 0.01)
+ data1 = np.exp(t)
+ data2 = np.sin(2 * np.pi * t)
+
+ fig, ax1 = plt.subplots()
+
+ color = 'tab:red'
+ ax1.set_xlabel('time (s)')
+ ax1.set_ylabel('exp', color=color)
+ ax1.plot(t, data1, color=color)
+ ax1.tick_params(axis='y', labelcolor=color)
+
+ ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
+
+ color = 'tab:blue'
+ ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
+ ax2.plot(t, data2, color=color)
+ ax2.tick_params(axis='y', labelcolor=color)
+
+ fig.tight_layout() # otherwise the right y-label is slightly clipped
+ return fig
+
+def ExploringNormalizations():
+ import matplotlib.pyplot as plt
+ import matplotlib.colors as mcolors
+ import numpy as np
+ from numpy.random import multivariate_normal
+
+ data = np.vstack([
+ multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
+ multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
+ ])
+
+ gammas = [0.8, 0.5, 0.3]
+
+ fig, axes = plt.subplots(nrows=2, ncols=2)
+
+ axes[0, 0].set_title('Linear normalization')
+ axes[0, 0].hist2d(data[:, 0], data[:, 1], bins=100)
+
+ for ax, gamma in zip(axes.flat[1:], gammas):
+ ax.set_title(r'Power law $(\gamma=%1.1f)$' % gamma)
+ ax.hist2d(data[:, 0], data[:, 1],
+ bins=100, norm=mcolors.PowerNorm(gamma))
+
+ fig.tight_layout()
+ return fig
+
+def PyplotFormatstr():
+
+ def f(t):
+ return np.exp(-t) * np.cos(2*np.pi*t)
+
+ t1 = np.arange(0.0, 5.0, 0.1)
+ t2 = np.arange(0.0, 5.0, 0.02)
+
+ plt.figure(1)
+ plt.subplot(211)
+ plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
+
+ plt.subplot(212)
+ plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def UnicodeMinus():
+ import numpy as np
+ import matplotlib
+ import matplotlib.pyplot as plt
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ matplotlib.rcParams['axes.unicode_minus'] = False
+ fig, ax = plt.subplots()
+ ax.plot(10 * np.random.randn(100), 10 * np.random.randn(100), 'o')
+ ax.set_title('Using hyphen instead of Unicode minus')
+ return fig
+
+def Subplot3d():
+ from mpl_toolkits.mplot3d.axes3d import Axes3D
+ from matplotlib import cm
+ # from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
+ import matplotlib.pyplot as plt
+ import numpy as np
+
+ fig = plt.figure()
+
+ ax = fig.add_subplot(1, 2, 1, projection='3d')
+ X = np.arange(-5, 5, 0.25)
+ Y = np.arange(-5, 5, 0.25)
+ X, Y = np.meshgrid(X, Y)
+ R = np.sqrt(X ** 2 + Y ** 2)
+ Z = np.sin(R)
+ surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
+ linewidth=0, antialiased=False)
+ ax.set_zlim3d(-1.01, 1.01)
+
+ # ax.w_zaxis.set_major_locator(LinearLocator(10))
+ # ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f'))
+
+ fig.colorbar(surf, shrink=0.5, aspect=5)
+
+ from mpl_toolkits.mplot3d.axes3d import get_test_data
+ ax = fig.add_subplot(1, 2, 2, projection='3d')
+ X, Y, Z = get_test_data(0.05)
+ ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
+ return fig
+
+def PyplotScales():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ from matplotlib.ticker import NullFormatter # useful for `logit` scale
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ # make up some data in the interval ]0, 1[
+ y = np.random.normal(loc=0.5, scale=0.4, size=1000)
+ y = y[(y > 0) & (y < 1)]
+ y.sort()
+ x = np.arange(len(y))
+
+ # plot with various axes scales
+ plt.figure(1)
+
+ # linear
+ plt.subplot(221)
+ plt.plot(x, y)
+ plt.yscale('linear')
+ plt.title('linear')
+ plt.grid(True)
+
+ # log
+ plt.subplot(222)
+ plt.plot(x, y)
+ plt.yscale('log')
+ plt.title('log')
+ plt.grid(True)
+
+ # symmetric log
+ plt.subplot(223)
+ plt.plot(x, y - y.mean())
+ plt.yscale('symlog', linthreshy=0.01)
+ plt.title('symlog')
+ plt.grid(True)
+
+ # logit
+ plt.subplot(224)
+ plt.plot(x, y)
+ plt.yscale('logit')
+ plt.title('logit')
+ plt.grid(True)
+ # Format the minor tick labels of the y-axis into empty strings with
+ # `NullFormatter`, to avoid cumbering the axis with too many labels.
+ plt.gca().yaxis.set_minor_formatter(NullFormatter())
+ # Adjust the subplot layout, because the logit one may take more space
+ # than usual, due to y-tick labels like "1 - 10^{-3}"
+ plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
+ wspace=0.35)
+ return plt.gcf()
+
+
+def AxesGrid():
+ import numpy as np
+ import matplotlib.pyplot as plt
+ from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
+
+ def get_demo_image():
+ # prepare image
+ delta = 0.5
+
+ extent = (-3, 4, -4, 3)
+ x = np.arange(-3.0, 4.001, delta)
+ y = np.arange(-4.0, 3.001, delta)
+ X, Y = np.meshgrid(x, y)
+ Z1 = np.exp(-X ** 2 - Y ** 2)
+ Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
+ Z = (Z1 - Z2) * 2
+
+ return Z, extent
+
+ def get_rgb():
+ Z, extent = get_demo_image()
+
+ Z[Z < 0] = 0.
+ Z = Z / Z.max()
+
+ R = Z[:13, :13]
+ G = Z[2:, 2:]
+ B = Z[:13, 2:]
+
+ return R, G, B
+
+ fig = plt.figure(1)
+ ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
+
+ r, g, b = get_rgb()
+ kwargs = dict(origin="lower", interpolation="nearest")
+ ax.imshow_rgb(r, g, b, **kwargs)
+
+ ax.RGB.set_xlim(0., 9.5)
+ ax.RGB.set_ylim(0.9, 10.6)
+
+ plt.draw()
+ return plt.gcf()
+
+
+
+# The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget
+def draw_figure(canvas, figure):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+
+def delete_figure_agg(figure_agg):
+ figure_agg.get_tk_widget().forget()
+ plt.close('all')
+
+# -------------------------------- GUI Starts Here -------------------------------#
+# fig = your figure you want to display. Assumption is that 'fig' holds the #
+# information to display. #
+# --------------------------------------------------------------------------------#
+
+fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'PyPlot Three':Subplot3d,
+ 'Unicode Minus': UnicodeMinus, 'Pyplot Scales' : PyplotScales, 'Axes Grid' : AxesGrid,
+ 'Exploring Normalizations' : ExploringNormalizations, 'Different Scales' : DifferentScales,
+ 'Pyplot Box Plot' : PyplotBoxPlot, 'Pyplot ggplot Style Sheet' : PyplotGGPlotSytleSheet,
+ 'Pyplot Line Poly Collection' : PyplotLinePolyCollection, 'Pyplot Line Styles' : PyplotLineStyles,
+ 'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots,
+ 'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram}
+
+sg.ChangeLookAndFeel('LightGreen')
+
+figure_w, figure_h = 650, 650
+# define the form layout
+listbox_values = list(fig_dict)
+col_listbox = [[sg.Listbox(values=listbox_values, enable_events=True, size=(28, len(listbox_values)), key='-LISTBOX-')],
+ [sg.T(' ' * 12), sg.Exit(size=(5, 2))]]
+
+layout = [[sg.Text('Matplotlib Plot Test', font=('current 18'))],
+ [sg.Column(col_listbox, pad=(5, (3, 330))), sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-') ,
+ sg.Multiline(size=(70, 35), pad=(5, (3, 90)), key='-MULTILINE-')],]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, grab_anywhere=False, finalize=True)
+figure_agg = None
+# The GUI Event Loop
+while True:
+ event, values = window.read()
+ # print(event, values) # helps greatly when debugging
+ if event in (None, 'Exit'): # if user closed window or clicked Exit button
+ break
+ if figure_agg:
+ # ** IMPORTANT ** Clean up previous drawing before drawing again
+ delete_figure_agg(figure_agg)
+ choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list)
+ func = fig_dict[choice] # get function to call from the dictionary
+ window['-MULTILINE-'].Update(inspect.getsource(func)) # show source code to function in multiline
+ fig = func() # call function to get the figure
+ figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
+window.close()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Matplotlib_Browser_Paned.py b/DemoPrograms old/Demo_Matplotlib_Browser_Paned.py
new file mode 100644
index 000000000..3a61374d6
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Browser_Paned.py
@@ -0,0 +1,889 @@
+#!/usr/bin/env python
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import matplotlib
+matplotlib.use('TkAgg')
+import inspect
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+"""
+
+
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+
+def PyplotSimple():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # evenly sampled time at 200ms intervals
+ t = np.arange(0., 5., 0.2)
+
+ # red dashes, blue squares and green triangles
+ plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^')
+
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def PyplotHistogram():
+ """
+ =============================================================
+ Demo of the histogram (hist) function with multiple data sets
+ =============================================================
+
+ Plot histogram with multiple sample sets and demonstrate:
+
+ * Use of legend with multiple sample sets
+ * Stacked bars
+ * Step curve with no fill
+ * Data sets of different sample sizes
+
+ Selecting different bin counts and sizes can significantly affect the
+ shape of a histogram. The Astropy docs have a great section on how to
+ select these parameters:
+ http://docs.astropy.org/en/stable/visualization/histogram.html
+ """
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ np.random.seed(0)
+
+ n_bins = 10
+ x = np.random.randn(1000, 3)
+
+ fig, axes = plt.subplots(nrows=2, ncols=2)
+ ax0, ax1, ax2, ax3 = axes.flatten()
+
+ colors = ['red', 'tan', 'lime']
+ ax0.hist(x, n_bins, normed=1, histtype='bar', color=colors, label=colors)
+ ax0.legend(prop={'size': 10})
+ ax0.set_title('bars with legend')
+
+ ax1.hist(x, n_bins, normed=1, histtype='bar', stacked=True)
+ ax1.set_title('stacked bar')
+
+ ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False)
+ ax2.set_title('stack step (unfilled)')
+
+ # Make a multiple-histogram of data-sets with different length.
+ x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
+ ax3.hist(x_multi, n_bins, histtype='bar')
+ ax3.set_title('different sample sizes')
+
+ fig.tight_layout()
+ return fig
+
+def PyplotArtistBoxPlots():
+ """
+ =========================================
+ Demo of artist customization in box plots
+ =========================================
+
+ This example demonstrates how to use the various kwargs
+ to fully customize box plots. The first figure demonstrates
+ how to remove and add individual components (note that the
+ mean is the only value not shown by default). The second
+ figure demonstrates how the styles of the artists can
+ be customized. It also demonstrates how to set the limit
+ of the whiskers to specific percentiles (lower right axes)
+
+ A good general reference on boxplots and their history can be found
+ here: http://vita.had.co.nz/papers/boxplots.pdf
+
+ """
+
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # fake data
+ np.random.seed(937)
+ data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
+ labels = list('ABCD')
+ fs = 10 # fontsize
+
+ # demonstrate how to toggle the display of different elements:
+ fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
+ axes[0, 0].boxplot(data, labels=labels)
+ axes[0, 0].set_title('Default', fontsize=fs)
+
+ axes[0, 1].boxplot(data, labels=labels, showmeans=True)
+ axes[0, 1].set_title('showmeans=True', fontsize=fs)
+
+ axes[0, 2].boxplot(data, labels=labels, showmeans=True, meanline=True)
+ axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs)
+
+ axes[1, 0].boxplot(data, labels=labels, showbox=False, showcaps=False)
+ tufte_title = 'Tufte Style \n(showbox=False,\nshowcaps=False)'
+ axes[1, 0].set_title(tufte_title, fontsize=fs)
+
+ axes[1, 1].boxplot(data, labels=labels, notch=True, bootstrap=10000)
+ axes[1, 1].set_title('notch=True,\nbootstrap=10000', fontsize=fs)
+
+ axes[1, 2].boxplot(data, labels=labels, showfliers=False)
+ axes[1, 2].set_title('showfliers=False', fontsize=fs)
+
+ for ax in axes.flatten():
+ ax.set_yscale('log')
+ ax.set_yticklabels([])
+
+ fig.subplots_adjust(hspace=0.4)
+ return fig
+
+def ArtistBoxplot2():
+
+ # fake data
+ np.random.seed(937)
+ data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
+ labels = list('ABCD')
+ fs = 10 # fontsize
+
+ # demonstrate how to customize the display different elements:
+ boxprops = dict(linestyle='--', linewidth=3, color='darkgoldenrod')
+ flierprops = dict(marker='o', markerfacecolor='green', markersize=12,
+ linestyle='none')
+ medianprops = dict(linestyle='-.', linewidth=2.5, color='firebrick')
+ meanpointprops = dict(marker='D', markeredgecolor='black',
+ markerfacecolor='firebrick')
+ meanlineprops = dict(linestyle='--', linewidth=2.5, color='purple')
+
+ fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
+ axes[0, 0].boxplot(data, boxprops=boxprops)
+ axes[0, 0].set_title('Custom boxprops', fontsize=fs)
+
+ axes[0, 1].boxplot(data, flierprops=flierprops, medianprops=medianprops)
+ axes[0, 1].set_title('Custom medianprops\nand flierprops', fontsize=fs)
+
+ axes[0, 2].boxplot(data, whis='range')
+ axes[0, 2].set_title('whis="range"', fontsize=fs)
+
+ axes[1, 0].boxplot(data, meanprops=meanpointprops, meanline=False,
+ showmeans=True)
+ axes[1, 0].set_title('Custom mean\nas point', fontsize=fs)
+
+ axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True,
+ showmeans=True)
+ axes[1, 1].set_title('Custom mean\nas line', fontsize=fs)
+
+ axes[1, 2].boxplot(data, whis=[15, 85])
+ axes[1, 2].set_title('whis=[15, 85]\n#percentiles', fontsize=fs)
+
+ for ax in axes.flatten():
+ ax.set_yscale('log')
+ ax.set_yticklabels([])
+
+ fig.suptitle("I never said they'd be pretty")
+ fig.subplots_adjust(hspace=0.4)
+ return fig
+
+def PyplotScatterWithLegend():
+ import matplotlib.pyplot as plt
+ from numpy.random import rand
+
+ fig, ax = plt.subplots()
+ for color in ['red', 'green', 'blue']:
+ n = 750
+ x, y = rand(2, n)
+ scale = 200.0 * rand(n)
+ ax.scatter(x, y, c=color, s=scale, label=color,
+ alpha=0.3, edgecolors='none')
+
+ ax.legend()
+ ax.grid(True)
+ return fig
+
+def PyplotLineStyles():
+ """
+ ==========
+ Linestyles
+ ==========
+
+ This examples showcases different linestyles copying those of Tikz/PGF.
+ """
+ import numpy as np
+ import matplotlib.pyplot as plt
+ from collections import OrderedDict
+ from matplotlib.transforms import blended_transform_factory
+
+ linestyles = OrderedDict(
+ [('solid', (0, ())),
+ ('loosely dotted', (0, (1, 10))),
+ ('dotted', (0, (1, 5))),
+ ('densely dotted', (0, (1, 1))),
+
+ ('loosely dashed', (0, (5, 10))),
+ ('dashed', (0, (5, 5))),
+ ('densely dashed', (0, (5, 1))),
+
+ ('loosely dashdotted', (0, (3, 10, 1, 10))),
+ ('dashdotted', (0, (3, 5, 1, 5))),
+ ('densely dashdotted', (0, (3, 1, 1, 1))),
+
+ ('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
+ ('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
+ ('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))])
+
+ plt.figure(figsize=(10, 6))
+ ax = plt.subplot(1, 1, 1)
+
+ X, Y = np.linspace(0, 100, 10), np.zeros(10)
+ for i, (name, linestyle) in enumerate(linestyles.items()):
+ ax.plot(X, Y + i, linestyle=linestyle, linewidth=1.5, color='black')
+
+ ax.set_ylim(-0.5, len(linestyles) - 0.5)
+ plt.yticks(np.arange(len(linestyles)), linestyles.keys())
+ plt.xticks([])
+
+ # For each line style, add a text annotation with a small offset from
+ # the reference point (0 in Axes coords, y tick value in Data coords).
+ reference_transform = blended_transform_factory(ax.transAxes, ax.transData)
+ for i, (name, linestyle) in enumerate(linestyles.items()):
+ ax.annotate(str(linestyle), xy=(0.0, i), xycoords=reference_transform,
+ xytext=(-6, -12), textcoords='offset points', color="blue",
+ fontsize=8, ha="right", family="monospace")
+
+ plt.tight_layout()
+ return plt.gcf()
+
+def PyplotLinePolyCollection():
+ import matplotlib.pyplot as plt
+ from matplotlib import collections, colors, transforms
+ import numpy as np
+
+ nverts = 50
+ npts = 100
+
+ # Make some spirals
+ r = np.arange(nverts)
+ theta = np.linspace(0, 2 * np.pi, nverts)
+ xx = r * np.sin(theta)
+ yy = r * np.cos(theta)
+ spiral = np.column_stack([xx, yy])
+
+ # Fixing random state for reproducibility
+ rs = np.random.RandomState(19680801)
+
+ # Make some offsets
+ xyo = rs.randn(npts, 2)
+
+ # Make a list of colors cycling through the default series.
+ colors = [colors.to_rgba(c)
+ for c in plt.rcParams['axes.prop_cycle'].by_key()['color']]
+
+ fig, axes = plt.subplots(2, 2)
+ fig.subplots_adjust(top=0.92, left=0.07, right=0.97,
+ hspace=0.3, wspace=0.3)
+ ((ax1, ax2), (ax3, ax4)) = axes # unpack the axes
+
+ col = collections.LineCollection([spiral], offsets=xyo,
+ transOffset=ax1.transData)
+ trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0 / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ # Note: the first argument to the collection initializer
+ # must be a list of sequences of x,y tuples; we have only
+ # one sequence, but we still have to put it in a list.
+ ax1.add_collection(col, autolim=True)
+ # autolim=True enables autoscaling. For collections with
+ # offsets like this, it is neither efficient nor accurate,
+ # but it is good enough to generate a plot that you can use
+ # as a starting point. If you know beforehand the range of
+ # x and y that you want to show, it is better to set them
+ # explicitly, leave out the autolim kwarg (or set it to False),
+ # and omit the 'ax1.autoscale_view()' call below.
+
+ # Make a transform for the line segments such that their size is
+ # given in points:
+ col.set_color(colors)
+
+ ax1.autoscale_view() # See comment above, after ax1.add_collection.
+ ax1.set_title('LineCollection using offsets')
+
+ # The same data as above, but fill the curves.
+ col = collections.PolyCollection([spiral], offsets=xyo,
+ transOffset=ax2.transData)
+ trans = transforms.Affine2D().scale(fig.dpi / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ ax2.add_collection(col, autolim=True)
+ col.set_color(colors)
+
+ ax2.autoscale_view()
+ ax2.set_title('PolyCollection using offsets')
+
+ # 7-sided regular polygons
+
+ col = collections.RegularPolyCollection(
+ 7, sizes=np.abs(xx) * 10.0, offsets=xyo, transOffset=ax3.transData)
+ trans = transforms.Affine2D().scale(fig.dpi / 72.0)
+ col.set_transform(trans) # the points to pixels transform
+ ax3.add_collection(col, autolim=True)
+ col.set_color(colors)
+ ax3.autoscale_view()
+ ax3.set_title('RegularPolyCollection using offsets')
+
+ # Simulate a series of ocean current profiles, successively
+ # offset by 0.1 m/s so that they form what is sometimes called
+ # a "waterfall" plot or a "stagger" plot.
+
+ nverts = 60
+ ncurves = 20
+ offs = (0.1, 0.0)
+
+ yy = np.linspace(0, 2 * np.pi, nverts)
+ ym = np.max(yy)
+ xx = (0.2 + (ym - yy) / ym) ** 2 * np.cos(yy - 0.4) * 0.5
+ segs = []
+ for i in range(ncurves):
+ xxx = xx + 0.02 * rs.randn(nverts)
+ curve = np.column_stack([xxx, yy * 100])
+ segs.append(curve)
+
+ col = collections.LineCollection(segs, offsets=offs)
+ ax4.add_collection(col, autolim=True)
+ col.set_color(colors)
+ ax4.autoscale_view()
+ ax4.set_title('Successive data offsets')
+ ax4.set_xlabel('Zonal velocity component (m/s)')
+ ax4.set_ylabel('Depth (m)')
+ # Reverse the y-axis so depth increases downward
+ ax4.set_ylim(ax4.get_ylim()[::-1])
+ return fig
+
+def PyplotGGPlotSytleSheet():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ plt.style.use('ggplot')
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ fig, axes = plt.subplots(ncols=2, nrows=2)
+ ax1, ax2, ax3, ax4 = axes.ravel()
+
+ # scatter plot (Note: `plt.scatter` doesn't use default colors)
+ x, y = np.random.normal(size=(2, 200))
+ ax1.plot(x, y, 'o')
+
+ # sinusoidal lines with colors from default color cycle
+ L = 2 * np.pi
+ x = np.linspace(0, L)
+ ncolors = len(plt.rcParams['axes.prop_cycle'])
+ shift = np.linspace(0, L, ncolors, endpoint=False)
+ for s in shift:
+ ax2.plot(x, np.sin(x + s), '-')
+ ax2.margins(0)
+
+ # bar graphs
+ x = np.arange(5)
+ y1, y2 = np.random.randint(1, 25, size=(2, 5))
+ width = 0.25
+ ax3.bar(x, y1, width)
+ ax3.bar(x + width, y2, width,
+ color=list(plt.rcParams['axes.prop_cycle'])[2]['color'])
+ ax3.set_xticks(x + width)
+ ax3.set_xticklabels(['a', 'b', 'c', 'd', 'e'])
+
+ # circles with colors from default color cycle
+ for i, color in enumerate(plt.rcParams['axes.prop_cycle']):
+ xy = np.random.normal(size=2)
+ ax4.add_patch(plt.Circle(xy, radius=0.3, color=color['color']))
+ ax4.axis('equal')
+ ax4.margins(0)
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def PyplotBoxPlot():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ # fake up some data
+ spread = np.random.rand(50) * 100
+ center = np.ones(25) * 50
+ flier_high = np.random.rand(10) * 100 + 100
+ flier_low = np.random.rand(10) * -100
+ data = np.concatenate((spread, center, flier_high, flier_low), 0)
+ fig1, ax1 = plt.subplots()
+ ax1.set_title('Basic Plot')
+ ax1.boxplot(data)
+ return fig1
+
+def PyplotRadarChart():
+ import numpy as np
+
+ import matplotlib.pyplot as plt
+ from matplotlib.path import Path
+ from matplotlib.spines import Spine
+ from matplotlib.projections.polar import PolarAxes
+ from matplotlib.projections import register_projection
+
+ def radar_factory(num_vars, frame='circle'):
+ """Create a radar chart with `num_vars` axes.
+
+ This function creates a RadarAxes projection and registers it.
+
+ Parameters
+ ----------
+ num_vars : int
+ Number of variables for radar chart.
+ frame : {'circle' | 'polygon'}
+ Shape of frame surrounding axes.
+
+ """
+ # calculate evenly-spaced axis angles
+ theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False)
+
+ def draw_poly_patch(self):
+ # rotate theta such that the first axis is at the top
+ verts = unit_poly_verts(theta + np.pi / 2)
+ return plt.Polygon(verts, closed=True, edgecolor='k')
+
+ def draw_circle_patch(self):
+ # unit circle centered on (0.5, 0.5)
+ return plt.Circle((0.5, 0.5), 0.5)
+
+ patch_dict = {'polygon': draw_poly_patch, 'circle': draw_circle_patch}
+ if frame not in patch_dict:
+ raise ValueError('unknown value for `frame`: %s' % frame)
+
+ class RadarAxes(PolarAxes):
+
+ name = 'radar'
+ # use 1 line segment to connect specified points
+ RESOLUTION = 1
+ # define draw_frame method
+ draw_patch = patch_dict[frame]
+
+ def __init__(self, *args, **kwargs):
+ super(RadarAxes, self).__init__(*args, **kwargs)
+ # rotate plot such that the first axis is at the top
+ self.set_theta_zero_location('N')
+
+ def fill(self, *args, **kwargs):
+ """Override fill so that line is closed by default"""
+ closed = kwargs.pop('closed', True)
+ return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)
+
+ def plot(self, *args, **kwargs):
+ """Override plot so that line is closed by default"""
+ lines = super(RadarAxes, self).plot(*args, **kwargs)
+ for line in lines:
+ self._close_line(line)
+
+ def _close_line(self, line):
+ x, y = line.get_data()
+ # FIXME: markers at x[0], y[0] get doubled-up
+ if x[0] != x[-1]:
+ x = np.concatenate((x, [x[0]]))
+ y = np.concatenate((y, [y[0]]))
+ line.set_data(x, y)
+
+ def set_varlabels(self, labels):
+ self.set_thetagrids(np.degrees(theta), labels)
+
+ def _gen_axes_patch(self):
+ return self.draw_patch()
+
+ def _gen_axes_spines(self):
+ if frame == 'circle':
+ return PolarAxes._gen_axes_spines(self)
+ # The following is a hack to get the spines (i.e. the axes frame)
+ # to draw correctly for a polygon frame.
+
+ # spine_type must be 'left', 'right', 'top', 'bottom', or `circle`.
+ spine_type = 'circle'
+ verts = unit_poly_verts(theta + np.pi / 2)
+ # close off polygon by repeating first vertex
+ verts.append(verts[0])
+ path = Path(verts)
+
+ spine = Spine(self, spine_type, path)
+ spine.set_transform(self.transAxes)
+ return {'polar': spine}
+
+ register_projection(RadarAxes)
+ return theta
+
+ def unit_poly_verts(theta):
+ """Return vertices of polygon for subplot axes.
+
+ This polygon is circumscribed by a unit circle centered at (0.5, 0.5)
+ """
+ x0, y0, r = [0.5] * 3
+ verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
+ return verts
+
+ def example_data():
+ # The following data is from the Denver Aerosol Sources and Health study.
+ # See doi:10.1016/j.atmosenv.2008.12.017
+ #
+ # The data are pollution source profile estimates for five modeled
+ # pollution sources (e.g., cars, wood-burning, etc) that emit 7-9 chemical
+ # species. The radar charts are experimented with here to see if we can
+ # nicely visualize how the modeled source profiles change across four
+ # scenarios:
+ # 1) No gas-phase species present, just seven particulate counts on
+ # Sulfate
+ # Nitrate
+ # Elemental Carbon (EC)
+ # Organic Carbon fraction 1 (OC)
+ # Organic Carbon fraction 2 (OC2)
+ # Organic Carbon fraction 3 (OC3)
+ # Pyrolized Organic Carbon (OP)
+ # 2)Inclusion of gas-phase specie carbon monoxide (CO)
+ # 3)Inclusion of gas-phase specie ozone (O3).
+ # 4)Inclusion of both gas-phase species is present...
+ data = [
+ ['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],
+ ('Basecase', [
+ [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],
+ [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],
+ [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],
+ [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],
+ [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]),
+ ('With CO', [
+ [0.88, 0.02, 0.02, 0.02, 0.00, 0.05, 0.00, 0.05, 0.00],
+ [0.08, 0.94, 0.04, 0.02, 0.00, 0.01, 0.12, 0.04, 0.00],
+ [0.01, 0.01, 0.79, 0.10, 0.00, 0.05, 0.00, 0.31, 0.00],
+ [0.00, 0.02, 0.03, 0.38, 0.31, 0.31, 0.00, 0.59, 0.00],
+ [0.02, 0.02, 0.11, 0.47, 0.69, 0.58, 0.88, 0.00, 0.00]]),
+ ('With O3', [
+ [0.89, 0.01, 0.07, 0.00, 0.00, 0.05, 0.00, 0.00, 0.03],
+ [0.07, 0.95, 0.05, 0.04, 0.00, 0.02, 0.12, 0.00, 0.00],
+ [0.01, 0.02, 0.86, 0.27, 0.16, 0.19, 0.00, 0.00, 0.00],
+ [0.01, 0.03, 0.00, 0.32, 0.29, 0.27, 0.00, 0.00, 0.95],
+ [0.02, 0.00, 0.03, 0.37, 0.56, 0.47, 0.87, 0.00, 0.00]]),
+ ('CO & O3', [
+ [0.87, 0.01, 0.08, 0.00, 0.00, 0.04, 0.00, 0.00, 0.01],
+ [0.09, 0.95, 0.02, 0.03, 0.00, 0.01, 0.13, 0.06, 0.00],
+ [0.01, 0.02, 0.71, 0.24, 0.13, 0.16, 0.00, 0.50, 0.00],
+ [0.01, 0.03, 0.00, 0.28, 0.24, 0.23, 0.00, 0.44, 0.88],
+ [0.02, 0.00, 0.18, 0.45, 0.64, 0.55, 0.86, 0.00, 0.16]])
+ ]
+ return data
+
+ N = 9
+ theta = radar_factory(N, frame='polygon')
+
+ data = example_data()
+ spoke_labels = data.pop(0)
+
+ fig, axes = plt.subplots(figsize=(9, 9), nrows=2, ncols=2,
+ subplot_kw=dict(projection='radar'))
+ fig.subplots_adjust(wspace=0.25, hspace=0.20, top=0.85, bottom=0.05)
+
+ colors = ['b', 'r', 'g', 'm', 'y']
+ # Plot the four cases from the example data on separate axes
+ for ax, (title, case_data) in zip(axes.flatten(), data):
+ ax.set_rgrids([0.2, 0.4, 0.6, 0.8])
+ ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),
+ horizontalalignment='center', verticalalignment='center')
+ for d, color in zip(case_data, colors):
+ ax.plot(theta, d, color=color)
+ ax.fill(theta, d, facecolor=color, alpha=0.25)
+ ax.set_varlabels(spoke_labels)
+
+ # add legend relative to top-left plot
+ ax = axes[0, 0]
+ labels = ('Factor 1', 'Factor 2', 'Factor 3', 'Factor 4', 'Factor 5')
+ legend = ax.legend(labels, loc=(0.9, .95),
+ labelspacing=0.1, fontsize='small')
+
+ fig.text(0.5, 0.965, '5-Factor Solution Profiles Across Four Scenarios',
+ horizontalalignment='center', color='black', weight='bold',
+ size='large')
+ return fig
+
+def DifferentScales():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ # Create some mock data
+ t = np.arange(0.01, 10.0, 0.01)
+ data1 = np.exp(t)
+ data2 = np.sin(2 * np.pi * t)
+
+ fig, ax1 = plt.subplots()
+
+ color = 'tab:red'
+ ax1.set_xlabel('time (s)')
+ ax1.set_ylabel('exp', color=color)
+ ax1.plot(t, data1, color=color)
+ ax1.tick_params(axis='y', labelcolor=color)
+
+ ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
+
+ color = 'tab:blue'
+ ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
+ ax2.plot(t, data2, color=color)
+ ax2.tick_params(axis='y', labelcolor=color)
+
+ fig.tight_layout() # otherwise the right y-label is slightly clipped
+ return fig
+
+def ExploringNormalizations():
+ import matplotlib.pyplot as plt
+ import matplotlib.colors as mcolors
+ import numpy as np
+ from numpy.random import multivariate_normal
+
+ data = np.vstack([
+ multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
+ multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
+ ])
+
+ gammas = [0.8, 0.5, 0.3]
+
+ fig, axes = plt.subplots(nrows=2, ncols=2)
+
+ axes[0, 0].set_title('Linear normalization')
+ axes[0, 0].hist2d(data[:, 0], data[:, 1], bins=100)
+
+ for ax, gamma in zip(axes.flat[1:], gammas):
+ ax.set_title(r'Power law $(\gamma=%1.1f)$' % gamma)
+ ax.hist2d(data[:, 0], data[:, 1],
+ bins=100, norm=mcolors.PowerNorm(gamma))
+
+ fig.tight_layout()
+ return fig
+
+def PyplotFormatstr():
+
+ def f(t):
+ return np.exp(-t) * np.cos(2*np.pi*t)
+
+ t1 = np.arange(0.0, 5.0, 0.1)
+ t2 = np.arange(0.0, 5.0, 0.02)
+
+ plt.figure(1)
+ plt.subplot(211)
+ plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
+
+ plt.subplot(212)
+ plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
+ fig = plt.gcf() # get the figure to show
+ return fig
+
+def UnicodeMinus():
+ import numpy as np
+ import matplotlib
+ import matplotlib.pyplot as plt
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ matplotlib.rcParams['axes.unicode_minus'] = False
+ fig, ax = plt.subplots()
+ ax.plot(10 * np.random.randn(100), 10 * np.random.randn(100), 'o')
+ ax.set_title('Using hyphen instead of Unicode minus')
+ return fig
+
+def Subplot3d():
+ from mpl_toolkits.mplot3d.axes3d import Axes3D
+ from matplotlib import cm
+ # from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
+ import matplotlib.pyplot as plt
+ import numpy as np
+
+ fig = plt.figure()
+
+ ax = fig.add_subplot(1, 2, 1, projection='3d')
+ X = np.arange(-5, 5, 0.25)
+ Y = np.arange(-5, 5, 0.25)
+ X, Y = np.meshgrid(X, Y)
+ R = np.sqrt(X ** 2 + Y ** 2)
+ Z = np.sin(R)
+ surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
+ linewidth=0, antialiased=False)
+ ax.set_zlim3d(-1.01, 1.01)
+
+ # ax.w_zaxis.set_major_locator(LinearLocator(10))
+ # ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f'))
+
+ fig.colorbar(surf, shrink=0.5, aspect=5)
+
+ from mpl_toolkits.mplot3d.axes3d import get_test_data
+ ax = fig.add_subplot(1, 2, 2, projection='3d')
+ X, Y, Z = get_test_data(0.05)
+ ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
+ return fig
+
+def PyplotScales():
+ import numpy as np
+ import matplotlib.pyplot as plt
+
+ from matplotlib.ticker import NullFormatter # useful for `logit` scale
+
+ # Fixing random state for reproducibility
+ np.random.seed(19680801)
+
+ # make up some data in the interval ]0, 1[
+ y = np.random.normal(loc=0.5, scale=0.4, size=1000)
+ y = y[(y > 0) & (y < 1)]
+ y.sort()
+ x = np.arange(len(y))
+
+ # plot with various axes scales
+ plt.figure(1)
+
+ # linear
+ plt.subplot(221)
+ plt.plot(x, y)
+ plt.yscale('linear')
+ plt.title('linear')
+ plt.grid(True)
+
+ # log
+ plt.subplot(222)
+ plt.plot(x, y)
+ plt.yscale('log')
+ plt.title('log')
+ plt.grid(True)
+
+ # symmetric log
+ plt.subplot(223)
+ plt.plot(x, y - y.mean())
+ plt.yscale('symlog', linthreshy=0.01)
+ plt.title('symlog')
+ plt.grid(True)
+
+ # logit
+ plt.subplot(224)
+ plt.plot(x, y)
+ plt.yscale('logit')
+ plt.title('logit')
+ plt.grid(True)
+ # Format the minor tick labels of the y-axis into empty strings with
+ # `NullFormatter`, to avoid cumbering the axis with too many labels.
+ plt.gca().yaxis.set_minor_formatter(NullFormatter())
+ # Adjust the subplot layout, because the logit one may take more space
+ # than usual, due to y-tick labels like "1 - 10^{-3}"
+ plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
+ wspace=0.35)
+ return plt.gcf()
+
+
+def AxesGrid():
+ import numpy as np
+ import matplotlib.pyplot as plt
+ from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
+
+ def get_demo_image():
+ # prepare image
+ delta = 0.5
+
+ extent = (-3, 4, -4, 3)
+ x = np.arange(-3.0, 4.001, delta)
+ y = np.arange(-4.0, 3.001, delta)
+ X, Y = np.meshgrid(x, y)
+ Z1 = np.exp(-X ** 2 - Y ** 2)
+ Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
+ Z = (Z1 - Z2) * 2
+
+ return Z, extent
+
+ def get_rgb():
+ Z, extent = get_demo_image()
+
+ Z[Z < 0] = 0.
+ Z = Z / Z.max()
+
+ R = Z[:13, :13]
+ G = Z[2:, 2:]
+ B = Z[:13, 2:]
+
+ return R, G, B
+
+ fig = plt.figure(1)
+ ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
+
+ r, g, b = get_rgb()
+ kwargs = dict(origin="lower", interpolation="nearest")
+ ax.imshow_rgb(r, g, b, **kwargs)
+
+ ax.RGB.set_xlim(0., 9.5)
+ ax.RGB.set_ylim(0.9, 10.6)
+
+ plt.draw()
+ return plt.gcf()
+
+# The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget
+def draw_figure(canvas, figure):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+
+def delete_figure_agg(figure_agg):
+ figure_agg.get_tk_widget().forget()
+ plt.close('all')
+
+
+# -------------------------------- GUI Starts Here -------------------------------#
+# fig = your figure you want to display. Assumption is that 'fig' holds the #
+# information to display. #
+# --------------------------------------------------------------------------------#
+
+# print(inspect.getsource(PyplotSimple))
+
+
+fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'PyPlot Three':Subplot3d,
+ 'Unicode Minus': UnicodeMinus, 'Pyplot Scales' : PyplotScales, 'Axes Grid' : AxesGrid,
+ 'Exploring Normalizations' : ExploringNormalizations, 'Different Scales' : DifferentScales,
+ 'Pyplot Box Plot' : PyplotBoxPlot, 'Pyplot ggplot Style Sheet' : PyplotGGPlotSytleSheet,
+ 'Pyplot Line Poly Collection' : PyplotLinePolyCollection, 'Pyplot Line Styles' : PyplotLineStyles,
+ 'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots,
+ 'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram}
+
+
+sg.ChangeLookAndFeel('LightGreen')
+figure_w, figure_h = 650, 650
+# define the form layout
+listbox_values = list(fig_dict)
+col_listbox = [[sg.Listbox(values=listbox_values, change_submits=True, size=(28, len(listbox_values)), key='-LISTBOX-')],
+ [sg.T(' ' * 12), sg.Exit(size=(5, 2))]]
+
+col_multiline = sg.Column([[sg.Multiline(size=(70, 35), key='-MULTILINE-')]])
+col_canvas = sg.Column([[ sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-')]])
+col_instructions = sg.Column([[sg.Pane([col_canvas, col_multiline], size=(800,600))],
+ [sg.Text('Grab square above and slide upwards to view source code for graph')]])
+
+layout = [[sg.Text('Matplotlib Plot Test', font=('ANY 18'))],
+ [sg.Column(col_listbox), col_instructions],]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',layout, resizable=True, finalize=True)
+
+canvas_elem = window.FindElement('-CANVAS-')
+multiline_elem= window.FindElement('-MULTILINE-')
+figure_agg = None
+
+while True:
+ event, values = window.Read()
+ if event in (None, 'Exit'):
+ break
+
+ if figure_agg:
+ # ** IMPORTANT ** Clean up previous drawing before drawing again
+ delete_figure_agg(figure_agg)
+ choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list)
+ func = fig_dict[choice] # get function to call from the dictionary
+ window['-MULTILINE-'].Update(inspect.getsource(func)) # show source code to function in multiline
+ fig = func() # call function to get the figure
+ figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
+
diff --git a/DemoPrograms old/Demo_Matplotlib_Ping_Graph.py b/DemoPrograms old/Demo_Matplotlib_Ping_Graph.py
new file mode 100644
index 000000000..b5687502b
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Ping_Graph.py
@@ -0,0 +1,674 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import tkinter as tk
+
+
+"""
+A graph of time to ping Google.com
+Demonstrates Matploylib used in an animated way.
+
+Note this file contains a copy of ping.py. It is contained in the first part of this file
+
+"""
+
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+# =============================================================================#
+import argparse
+import os, sys, socket, struct, select, time, signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+# =============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+
+# =============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string) / 2)) * 2
+ sum = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum = sum + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum = sum + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string) - 1]
+ try: # For Python3
+ sum += loByte
+ except: # For Python2
+ sum += ord(loByte)
+
+ sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
+ sum += (sum >> 16) # Add carry from above (if any)
+ answer = ~sum & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+
+# =============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime - sentTime) * 1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+
+# =============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ # destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size - 8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ # data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+
+# =============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout / 1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ # print (len(recPacket.encode()))
+ return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+
+# =============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+
+# =============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+
+# =============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ dump_stats(myStats)
+
+#=============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return 0,0,0,0
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+# =============================================================================#
+
+
+
+#================================================================================
+# Globals
+# These are needed because callback functions are used.
+# Need to retain state across calls
+#================================================================================
+SIZE=(320,240)
+
+class MyGlobals:
+ axis_pings = None
+ ping_x_array = []
+ ping_y_array = []
+
+g_my_globals = MyGlobals()
+
+#================================================================================
+# Performs *** PING! ***
+#================================================================================
+def run_a_ping_and_graph():
+ global g_my_globals # graphs are global so that can be retained across multiple calls to this callback
+
+ #===================== Do the ping =====================#
+ response = quiet_ping('google.com',timeout=1000)
+ if response[0] == 0:
+ ping_time = 1000
+ else:
+ ping_time = response[0]
+ #===================== Store current ping in historical array =====================#
+ g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array))
+ g_my_globals.ping_y_array.append(ping_time)
+ # ===================== Only graph last 100 items =====================#
+ if len(g_my_globals.ping_x_array) > 100:
+ x_array = g_my_globals.ping_x_array[-100:]
+ y_array = g_my_globals.ping_y_array[-100:]
+ else:
+ x_array = g_my_globals.ping_x_array
+ y_array = g_my_globals.ping_y_array
+
+ # ===================== Call graphinc functions =====================#
+ g_my_globals.axis_ping.clear() # clear before graphing
+ set_chart_labels()
+ g_my_globals.axis_ping.plot(x_array,y_array) # graph the ping values
+
+#================================================================================
+# Function: Set graph titles and Axis labels
+# Sets the text for the subplots
+# Have to do this in 2 places... initially when creating and when updating
+# So, putting into a function so don't have to duplicate code
+#================================================================================
+def set_chart_labels():
+ global g_my_globals
+
+ g_my_globals.axis_ping.set_xlabel('Time', fontsize=8)
+ g_my_globals.axis_ping.set_ylabel('Ping (ms)', fontsize=8)
+ g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize = 8)
+
+def draw(fig, canvas):
+ # Magic code that draws the figure onto the Canvas Element's canvas
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(SIZE[0] / 2, SIZE[1] / 2, image=photo)
+ figure_canvas_agg = FigureCanvasAgg(fig)
+ figure_canvas_agg.draw()
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+#================================================================================
+# Function: MAIN
+#================================================================================
+def main():
+ global g_my_globals
+
+ # define the form layout
+ layout = [[ sg.Canvas(size=SIZE, background_color='white',key='canvas') , sg.Button('Exit', pad=(0, (210, 0)))]]
+
+ # create the form and show it without the plot
+ window = sg.Window('Ping Graph', background_color='white', grab_anywhere=True).Layout(layout).Finalize()
+
+ canvas_elem = window.FindElement('canvas')
+ canvas = canvas_elem.TKCanvas
+
+ fig = plt.figure(figsize=(3.1, 2.25), tight_layout={'pad':0})
+ g_my_globals.axis_ping = fig.add_subplot(1,1,1)
+ plt.rcParams['xtick.labelsize'] = 8
+ plt.rcParams['ytick.labelsize'] = 8
+ set_chart_labels()
+ plt.tight_layout()
+
+ while True:
+ event, values = window.Read(timeout=0)
+ if event in ('Exit', None):
+ exit(0)
+
+ run_a_ping_and_graph()
+ photo = draw(fig, canvas)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Matplotlib_Ping_Graph_Large.py b/DemoPrograms old/Demo_Matplotlib_Ping_Graph_Large.py
new file mode 100644
index 000000000..38f7cf608
--- /dev/null
+++ b/DemoPrograms old/Demo_Matplotlib_Ping_Graph_Large.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import matplotlib.pyplot as plt
+import ping
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import tkinter as tk
+
+#================================================================================
+# Globals
+# These are needed because callback functions are used.
+# Need to retain state across calls
+#================================================================================
+class MyGlobals:
+ axis_pings = None
+ ping_x_array = []
+ ping_y_array = []
+
+g_my_globals = MyGlobals()
+
+#================================================================================
+# Performs *** PING! ***
+#================================================================================
+def run_a_ping_and_graph():
+ global g_my_globals # graphs are global so that can be retained across multiple calls to this callback
+
+ #===================== Do the ping =====================#
+ response = ping.quiet_ping('google.com',timeout=1000)
+ if response[0] == 0:
+ ping_time = 1000
+ else:
+ ping_time = response[0]
+ #===================== Store current ping in historical array =====================#
+ g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array))
+ g_my_globals.ping_y_array.append(ping_time)
+ # ===================== Only graph last 100 items =====================#
+ if len(g_my_globals.ping_x_array) > 100:
+ x_array = g_my_globals.ping_x_array[-100:]
+ y_array = g_my_globals.ping_y_array[-100:]
+ else:
+ x_array = g_my_globals.ping_x_array
+ y_array = g_my_globals.ping_y_array
+
+ # ===================== Call graphinc functions =====================#
+ g_my_globals.axis_ping.clear() # clear before graphing
+ g_my_globals.axis_ping.plot(x_array,y_array) # graph the ping values
+
+#================================================================================
+# Function: Set graph titles and Axis labels
+# Sets the text for the subplots
+# Have to do this in 2 places... initially when creating and when updating
+# So, putting into a function so don't have to duplicate code
+#================================================================================
+def set_chart_labels():
+ global g_my_globals
+
+ g_my_globals.axis_ping.set_xlabel('Time')
+ g_my_globals.axis_ping.set_ylabel('Ping (ms)')
+ g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize = 12)
+
+def draw(fig, canvas):
+ # Magic code that draws the figure onto the Canvas Element's canvas
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(640 / 2, 480 / 2, image=photo)
+ figure_canvas_agg = FigureCanvasAgg(fig)
+ figure_canvas_agg.draw()
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+#================================================================================
+# Function: MAIN
+#================================================================================
+def main():
+ global g_my_globals
+
+ # define the form layout
+ layout = [[sg.Text('Animated Ping', size=(40, 1), justification='center', font='Helvetica 20')],
+ [sg.Canvas(size=(640, 480), key='canvas')],
+ [sg.Button('Exit', size=(10, 2), pad=((280, 0), 3), font='Helvetica 14')]]
+
+ # create the form and show it without the plot
+ window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
+
+ canvas_elem = window.FindElement('canvas')
+ canvas = canvas_elem.TKCanvas
+
+ fig = plt.figure()
+ g_my_globals.axis_ping = fig.add_subplot(1,1,1)
+ set_chart_labels()
+ plt.tight_layout()
+
+ while True:
+ event, values = window.Read(timeout=0)
+ if event in ('Exit', None):
+ break
+
+ run_a_ping_and_graph()
+ photo = draw(fig, canvas)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms old/Demo_Media_Player.py b/DemoPrograms old/Demo_Media_Player.py
new file mode 100644
index 000000000..74101bb06
--- /dev/null
+++ b/DemoPrograms old/Demo_Media_Player.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+ # import PySimpleGUIQt as sg # portable to QT
+else:
+ import PySimpleGUI27 as sg
+
+#
+# An Async Demonstration of a media player
+# Uses button images for a super snazzy look
+# See how it looks here:
+# https://user-images.githubusercontent.com/13696193/43159403-45c9726e-8f50-11e8-9da0-0d272e20c579.jpg
+#
+def MediaPlayerGUI():
+ background = '#F0F0F0'
+ # Set the backgrounds the same as the background on the buttons
+ sg.SetOptions(background_color=background, element_background_color=background)
+ # Images are located in a subfolder in the Demo Media Player.py folder
+ image_pause = './ButtonGraphics/Pause.png'
+ image_restart = './ButtonGraphics/Restart.png'
+ image_next = './ButtonGraphics/Next.png'
+ image_exit = './ButtonGraphics/Exit.png'
+
+ # A text element that will be changed to display messages in the GUI
+
+ ImageButton = lambda image_filename, key:sg.Button('', button_color=(background,background), image_filename=image_filename, image_size=(50, 50), image_subsample=2, border_width=0, key=key)
+
+ # define layout of the rows
+ layout= [[sg.Text('Media File Player', font=("Helvetica", 25))],
+ [sg.Text('', size=(15, 2), font=("Helvetica", 14), key='output')],
+ [ImageButton(image_restart, key='Restart Song'), sg.Text(' ' * 2),
+ ImageButton(image_pause, key='Pause'),
+ sg.Text(' ' * 2),
+ ImageButton(image_next, key='Next'),
+ sg.Text(' ' * 2),
+ sg.Text(' ' * 2),ImageButton(image_exit, key='Exit')],
+ ]
+
+ # Open a form, note that context manager can't be used generally speaking for async forms
+ window = sg.Window('Media File Player', auto_size_text=True, default_element_size=(20, 1),
+ font=("Helvetica", 25)).Layout(layout)
+ # Our event loop
+ while(True):
+ event, values = window.Read(timeout=100) # Poll every 100 ms
+ if event == 'Exit' or event is None:
+ break
+ # If a button was pressed, display it on the GUI by updating the text element
+ if event != sg.TIMEOUT_KEY:
+ window.FindElement('output').Update(event)
+
+MediaPlayerGUI()
+
diff --git a/DemoPrograms old/Demo_Menu_With_Toolbar.py b/DemoPrograms old/Demo_Menu_With_Toolbar.py
new file mode 100644
index 000000000..9a9afa944
--- /dev/null
+++ b/DemoPrograms old/Demo_Menu_With_Toolbar.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+
+def ShowMeTheButtons():
+ # ------ Menu Definition ------ #
+ menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit' ]],
+ ['&Edit', ['&Paste', ['Special', 'Normal',], 'Undo'],],
+ ['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']],
+ ['&Help', '&About...'],]
+
+ sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+ toolbar_buttons = [[sg.Button('', image_data=close64[22:],button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0,0), key='_close_'),
+ sg.Button('', image_data=timer64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_timer_'),
+ sg.Button('', image_data=house64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_house_'),
+ sg.Button('', image_data=cpu64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_cpu_'),
+ sg.Button('', image_data=camera64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_camera_'),
+ sg.Button('', image_data=checkmark64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_checkmark_'),
+ sg.Button('', image_data=cookbook64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_cookbook_'),
+ sg.Button('', image_data=download64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_download_'),
+ sg.Button('', image_data=github64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_github_'),
+ sg.Button('', image_data=psg64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_psg_'),
+ sg.Button('', image_data=run64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_run_'),
+ sg.Button('', image_data=storage64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_storage_'),
+ ]]
+
+ # layout = toolbar_buttons
+ # ------ GUI Defintion ------ #
+ layout = [ [sg.Menu(menu_def, )],
+ [sg.Frame('', toolbar_buttons,title_color='white', background_color=sg.COLOR_SYSTEM_DEFAULT, pad=(0,0))],
+ [sg.Text('', size=(20,8))],
+ [sg.Text('Status Bar', relief=sg.RELIEF_SUNKEN, size=(55, 1), pad=(0, 3), key='_status_')]
+ ]
+
+ window = sg.Window('Toolbar').Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = window.Read()
+ print(button)
+ if button in ('_close_', 'Exit') or button is None:
+ break # exit button clicked
+ elif button == '_timer_':
+ pass # add your call to launch a timer program
+ elif button == '_cpu_':
+ pass # add your call to launch a CPU measuring utility
+
+
+
+if __name__ == '__main__':
+ house64 = 'data:image/png;base64,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'
+
+ timer64 = 'data:image/png;base64,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'
+
+ close64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAE30lEQVRIiZ2VXYgdRRqGn6+quvucM/85iRoTNevMBJFEWY0GFQTBC1HBlaz/jMpoFFfXBdmFvdiLvRIEFRHFGBXMjUQhF/6Bol6sSNaIruCNir/R/Dlx5iRzck736e6qby/6JDlx9CIWFN10Ue/7vW+9X7XcDn8bryWPL2vERkNQQPj9Q72K7F3s7Hxb9bZ98L0bj91jt1y23kxNTxIEGUQ/aTYR6WW9cud/Prx01zf7/7FP5EHXHG7Y6bVTpBPLMSegCWKEEMKvkihgjEWDP+FbEjxTa1bjv9l/CsIKF3ypHhUDSFGACCKC956iKKjV6/hfkCjgUNK0TW1oCA3h+EJk8UUBYFCsQaSyRajArUWLnEONcTrT68nTLtZaEKmmMTiUlsREGy9HO0dgcL1y6lgtZrAsEYFexhwxq2buYfru+1mcOo+828UYg4rgUH7OSkY3zbDq1lkaV1yFP9TqEyy18jiBCMF7DjYmOOu+hxifnCSKItZuvp/F6fPJ05TEwE+dHhN33MfpGy4iFAVjf7qF8etvBV9y1IilBApGIMt6TExOM372JKqKqhLFMdOz93Jk6jx+bHVoztzLyj9eiHqP2Gq7O3UlGAuq1RwYDlUwhoChMdSAz3ZxaEeD8T/fBggaAnGtxpqZWdKFBSbOPLMCCQGJItJPdrHw4lOYRgNsBM6dSCDGErIuodtGkhoyPEr68U5svcbI1ZsQY0CV2vAw9ZGRKjEiSBTR/fQjDm9/AddcjqoSul182kYHVDhJauRffUH7wD7ilatxzVOwI6PM7XiJLO2x4rob0CgGVTSEKigidD94j/ltW9Dg0b0/4BfmyQ8ewKUdWLZ6wCIB9SXFXJvQ+hLkc6QeEznHf199jY1rpjh1w0ZUFTGm7z18/tSj2Hffor5shKLdhhJCADMcw7IlKRIkAqkJRIa4LPl6d5c/PPJkBd5vpArcArD+ue101l1Md08bFxuIBUlOyOUggUIAVIl94Kv5wKqtz7L+7r/0bRHEmApcFbwnHhljw6tv0b3kEtK5gDWmj/GbfQAWZbdaztjyPOfP3oN6D8GDCO133uDAvx9CyxKsRX1JMjbBBa+8Rnbl5RSpR35RfXUGfVLnYGFBcTfdwLo77yLkPYy14CLa773JngfuoNy7QOh2WPnw09WVkufUm8s598G/s+eT9wmBJZ1m+sVTFNBc4Wi8vJ3v//kAJk7AOhbf3MGezTfjWwuYCcv8s1s58K+/okWOxDGdjz5g7+YZtKRSoL+igCp5FKVntGk48sTTzDWb1C+4mB833wgETD2CELBjEfNbtyAjo4xdcz27N11L6B5GGoZQhN+26KiSoII9LebnJx9BkggzNIQkyfEdItiRQGvbM7S2bQHJMGN1NO8ds2dQhBORYBCjAFEE1kFSw0QxuAiTJCAGce64vz4gviTkOTJcErIMMRbyDIxg7bHTFnc47clcmpdj43VkeBRJEkytgdTqSL2OiRMkSRDroH9t4EtCUaBZhmYpIUurZ9pFfVnuX+w62xfjeq3D3/6vbifXrT1XkzgWdREmipA4RlwMUYRY21cg/X+lJ5gSbIHGOVovCHmOCSX7DrbMx599icIhVI2cA5c5mC1gbGnITm4oqAOr0PoOXs9g51HAGiITyCDByXDp4KuiaoESmP8/YC0Y5GajmEsAAAAASUVORK5CYII='
+
+ psg64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABlbkiVhkyZikyFjmShjkyhlly1mli5nlylnmS5olyppnC5qmi5rmzBpmDBpmTFqmDFqmTFqmjNrmzFrnDNsmzJsnDJtnTFunjNvnzRsmTRtmzVunTVunjVvnzZwnjlxny5toDFvozJwoTNzpjVwoDRzpDRzqDd4rThyojp0ozl1pTt2pjt3pz11ozt4qDl4qTp6rTl6rzx4qD55qTx5qj97qz17rT58rD98rT9+rz5+sEB3pEF9rkB+r0F+sEF/sT2AtD6AtT6Btk+Aqk2CrEOBs0GBtEKCtEGCtUSBskWBs0SCtEWDtUaEtkWFt0aGt0KFuUCEukOGu0eFuEWHu0eJvEiGuUiHukiIuUiIukmJu0uKvEyKvFCAp1CCqlODrVKCrl2Kr1OEs1KGsFWGsFaIsVaPvFqKsl6NsmKNsWeTuG6YvHadvlySwV6UxF+YxW+bxW6dxnKewHGex3SdwHSfx3egwXGizHmgwHqkxnyjxHio0f/RMf7QMv/TMf/SMv3SNf7UOv7UO//UPP/UPf/UPv/VP//WPP/XPv/VQ//WQv7XQ//WRP/XRf/WR//YRv/YSP/YSf/YSv/ZS//aS//ZTf/aTP7aTf7aTv7bT//cT//bUP/cUP7cUv/cU/7cVf/eVf/fVv/eV/7dWP/eWP/eWf/fWv/fW//fYvzcaf/hW//gXP/gXv/gX//hYP/hYf/hY//iYP/jY//gZf/iZP7iZf/jZv/iZ//lZv/jaf/kav7ka//maf/ma//kbf/lbv7mbP/mbv/mb//id//mcP/ncv/nc//ld//ndv/meP/ocf/ocv/oc//odP/odf/odv/peP/pff/qfY+11ZSzz5G41qC81aW/1P/jgf/qiv/qjv7qoMnZ5szb587d6eDm2+fo1+7v3e/x3vXw1fHx3gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJblQd8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcQAAAXEAEYYRHbAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAABzUlEQVQoU2P4jwNAJZIEuLJA9M2u/iNgAaiEELOgIFPc//+r6puaalvAQmAJdg4pPj4h5oT/2+raWtqaGmAS/PxC/IJAGdbEB7saW5pb20AyQAkFNiFhUSEgkGZNfjizua29u70XJJHr8j+eV0RGVkRMTJb56u2mvt7eSR0gCT2gPsbMGzbi8hJyPDl3OidPnDRlwhagRHbG/zTXe5WSqqqqmpzXb/VMmz5jztSVIDtSWFLvl3Jrampq8ZY8WThj1tx586ZCXFV9t1xRR1tbR6Lw0f6ZC+YvWDAb6tz/xUom+rrGymWPD8xaunjZ0oUgMZBEsYqZqampWsnTY/PWLF+xZhFIHCRRpW5raWFhUPT/3IJ1a9euW/H//5oTYAlDezs7Kwvv//+XbN6wcev6//+3/z8FltDwcrC3N8/7v3rHtu07Nv3/vxVo0CWQhJGPm5ubdf7/TXt279699//JnTA70j38fH19wv//33b00OGj+w6fPXz5KMRVTiH+/gHuFf//7zl+5szZs2fO7YPo+H/FOSIyPMqz5v//g+dAMocvQCX+XwsMjYmNdgSy9p0/d/bgRZAYWOL//4LgoDAwY+++02AaJoEJcEj8/w8A4UqG4COjF7gAAAAASUVORK5CYII='
+
+ cpu64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAFi0lEQVRIiZ1WS2wbRRj+/5l92O6u7WycTW03xLEd6uBUjVO1hfbSByLQEwhxoIhbCwcuvApUiEOFhAQVEiAOvK4gqoojSEhtgUNApaJKG5qkdWpa1JfcZL3teu3sZmeGQ9ZVGhIJ8Z/+2Vn93//45psBWMMqlcoXxWLxEACAaZpju3btOkkIoZRSsnv37hOmaY4BABSLxUOVSuXzteJIq32klMqyLBuqqhoAAKqqGpTSpKIoSUQESZK6OnuKohiKohiUUpkxtvivWCvWBABEOp1+sr+//5V169ZtnJub+6FUKh3Rdf3hVqv1l6Zp5Ww2ezASifQ0Go3fhoaGjsZisYdardaM4zjTiEgAQHQC4j0HkQghAAC4oiiJRCKxBQBIs9m8oOt6iRASa7VaVwEAYrFYP+e85TjOpXg8PiyE4LZtn/F93wYAgogghOD3AYS+UFW1q1AovGoYxp4wGxIEgS2EEIQQCQCAcx7gkslCCB8AwLbt07Va7SPP8xqdWPdmIElSxDTNfZZlncrn828MDg6+VavVPvF9fy4Wi/X19fUdWJHMfSaEYJlMZgwRpVqtdtQwjD31ev2HIAgWpJGRkS8VRTEMw9g9OTm5v7u7+9GpqamXq9XqxwAAmzZt+oBzjpzzYC0QIQRDRJpIJLanUqmdw8PDX1mW9ZPv+5bkOM5FVVVTiURia1i24rruDQCAUqn09sDAwCHGGEdEadnwlgOJZT5BRMIYc5rN5iXP8+ax0y9N04qc84Vt27aduHjx4uuEED46Ovo95xxEOH1ExKWEhQh9DPe4JEl0fn7+14mJiecQUWo2m7MAgNQ0zb3d3d3bhoaGjrTb7Wld1x/p6uoa2bBhw4uyLGsAEFBKKSIi51xQSjFcIiICIQRDAhDXdWue502Vy+X3hRALqqr2SoODg2/KsmzE4/GNlNJ1nPOF9evXPxYEAbiue7lWq72rKIphmub+GzdufBeNRg1d14cZYx4hhBJClFQqNRbOQlBKo8lkcms+n48vLi5a0vj4+OOKoiTT6fQzjuNcJYRIQRCALMswOzv7LSEk0tPT85TjOBeCIKi12+1rtm3/ruv6FgDgAMB7e3vHgiAAQgh1HOfquXPnXr958+Zx3/dtshopltp7nyEiUtd1rxuG8URfX99B13Un2+32rKIo3ZzztRgMdOfOnT/mcrkX+vv79zcajVOapm3XNC3HGINoNNpnWdZJz/P+TiQSOzRNK6bT6WcjkUh/q9WaQUTIZrMHEFEjhECz2fzL9/2ZkZGRz0zT3JfNZp+WqtXq+5FIJJXL5V5kjLVDdgDnnMVisYFyufxVSFHgnO9gjDFElIvF4jth34ExxgCAIiIyxtq2bZ+5cuXK5wsLC3NSvV4/BQDCsqw/hBBBLpeTO+WF/KdhC0TIHAoAIggCjogYMnjpEBAi27Z96ezZsy90aCoVCoXXVFVNZbPZ/TMzMy9xzr1ljSdhYLHicN0DCkFYWKFnGMamUqn06fXr17/xPG9e0nV9Y6jnWqiAPCydrTm5laxY+pcCABdCcEqprmnag4qiWNLExMTBZWI3Ho/Hd2Qymb1CCBpm+V8AQJZluHPnzum5ubnx8+fPH+iI3apync/nX04mk9vDXihCiMX/K9drXTjJZDK5FRHJ3bt3/9R1/cH/e+Esb0FnkKK3t3ff5s2bv+7p6Rm7devWsXK5/GGhUDjsOM5kNBp9oFKpfKNp2kC9Xv9xdHT0eCaTed513fPhlYmd4CsBOiDQarVmu7q6KpZl/XLt2rVjQggvHo8PTE9PH242m1PpdPrRy5cvf3L79u2fo9GoyRi7U61W3wsDL5fv1V8VjLFF3/ct3/ctAADP86wgCBq+7zcAABljtud5FgCA7/uWLMvWai8KAIB/ACsf4Gh+DNwbAAAAAElFTkSuQmCC'
+
+ camera64 = 'data:image/png;base64,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'
+
+ checkmark64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAD2ElEQVRIibWVe4hUVRzHP+feuTOz82gfrqwu5gM0zTQpS1yfoGQPyc3IjOwlYRElPcDICEP6Q6i/IvojCCIpTA0tSlSqJSvbTLZE0dbWxz4nXWdnxrk7M/feOY/+sHyEa7pt57/z45zP53x/B84R/B/jzeNLgeXADDHE4IeBV2Ihpo6LK1rzNqEhAW9oGw18UhelYeWUGHFL0tx5lqPZyBAI3mi9o8YRm16cWTlsVFLQVwjY2+4SSI2W+j8KXj+ybmwytO69xjo7Wyqzr8sldbaE60ksIdBlhTVo+KuHXppY5azftKzeNsbQkurntOuTKQQobYhFbCgPNsGaA5NDWm94ZlYV7fmAX3pcenIlTucDAqlJRENUxcJQLgwiwfMtYcpq4503JMJjq8M0d+XpyBRJnfUpBpJwyKYqFqbCcSCQg0gQyCeq4qHp90yr5Pd0kY6+ImnXJ1CaeDhEdSJCTSJKzLEHLXhu4oQEuWKZ79uzZAoX2hKPhOn+I6DtuEdfLriC4NE9L4CYhzEP8dH84Hz9kT0NBHLqvMlJmo5nyBQDylITj4RwM5rmw70orcEA0AL8Q/DgN8OBr/DltL8q64G1F52+obomwr6US7boE0hNhRPiVIdHx7H+EvA2sJ0tC3/+e8uFS27c/SS+7ElGrGkbnp5EfV0UArmGxt0Lzq/x5YzKWocz/T4FXyGEINvj0XE410QgJ7Fl4dqL4ecS3PVlJYgdllKzx04ZxqolY8h4mkm315JPl+z+nP8Bd++4hZ2LM/hyuokLCr7Eti28TJnOA5ndGLOUnYtLl+u2YMHnJ4BxY2bWsWj2SA72eoBBG4PnBvy2qwvpq81gVjhJp1Q7q9axLIFVMqSaz3ytfLWEpsbLwgFs6pc1o/R9+e7+eK9joSMWvjR4gSLA4FSGKLS7UyirUmRkbJFTG0VI6N17+oR0/bl8d/+A8HMJAG7bPB7BTmGL8TVz64mMiKGNQSuN0hqvq59CS59Kzq2zo8MrcH/s1V6qMIf9y5uvBL8gALj54xpgG5aYH589klB9BdoYjDY0XJ9k9HURPj2aRZ/ycL/tfouDK17+N/ilAoAbP6wAsRGLB8INI7BGJUAYLGEhLAtLCApfnDymc95NtD4eDMC8ZNiXzNKfSdLbt5K8N6o68nNMwoHqKCAwlkVwKI06ln2MtpWtVwMHBnjspHyNQO1Xe7pRbTmUEchCGbk/laKsdl0tfGBB51OKQM0hUD/ppk7kkTTy11NQku/TuUpdi+DKn/7wdyuAHzDcii0Uykwg/ezJoRMAVL9TCWwFjpJdvfpa4AB/Akx4zQw8GDagAAAAAElFTkSuQmCC'
+
+ cookbook64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAAAsSAAALEgHS3X78AAADMUlEQVQ4jY1UQUgCWxS9782M5hQzle3NTRGEQdBipCKKECoEg4JaJAqCmyBsYauEaNOqjQtXLSKINuFiKMiwIMtF1iLK2kWRZLUoDRxo5s37ixfSt4+/u7xzz51z7r3nwc7Ojt1uBwCEEPwtWKXL5eIvLy+HhoYIIYIgCIJAKa0Do5RyHPfy8nJycnJ1dcUjhJxOZygUOj09zefzFoulDp5SihCKRqPLy8vJZBI4jgOAo6Mjj8cDABjj/6WdTqdDoRAAfJeyFn8MQohhGADAY4xFUSyVSpIkAYBpmgih+soRQmxm2GazbW5u7u7ujoyMKIrCmP+ePMdxv9nhSqXi8/lmZmb29vay2Syrs1gs8EM/QogQQgipBWOMOzs7397eWlpabDYbAMiyHAwGu7u7mQTWzu/3R6PRxsZG+HERvNVqjcVix8fHfX19Nzc3T09PHo+HUjo1NVUulx8fHwFgbW0tEolQSguFwtbWVpU/rlQqs7Ozc3NzqqrmcjmXy9Xe3m61WgcGBubn5wGgo6NjYWEBAEql0t3dHQBUx8ljjNva2orFYnNzM8/zBwcHFoslGo329/cXCgUA6OnpwRh/fHwsLS3lcjm2qm9wQ0NDPB7f398fHBx8eHjIZrOqqhaLRUmSwuFwPB53OBw+ny+dTn9+ftYujed5AEilUhMTE9U9saTX66WUJhKJmv0dHh4Gg0FgF4YxJoQwANNjGIaiKLFYbHp62ul0Li4umqb5H5crSVIymQwEAolEwu12s6SiKNfX15OTkwDgcDguLi4ikUgVUv0zCIJgs9lUVWWlrP3q6qrf72dfAaCrq2tjY0OW5RowTynVNM1qteq6XqW9srJiGAZCSNd1hNDt7W04HGZm+NeFiaKYTCa3t7fHx8fdbjez+9fXV7UR87Cu66Zp1oI1TQsEAl6vN51Os9smhCCEfpbWmMw0TZbBpmm+v7+3traWy2VKKdP825I/M7Isi6IIAFxTU9P6+nomk+nt7X19fX1+fsYY1/ez0+k8Pz+/v7/nMMblcnl4eDifz5+dnWmaVgfGolQq2e32sbGx7wcok8mMjo7C396wVCpFKSWE/ANWXYLwO0+V8wAAAABJRU5ErkJggg=='
+
+ download64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAEl0lEQVRIia2WS2hdZRDHf/Odc+7NvbZpYky1Gk2rEbRa26pt8UWLitYHIqigCD426kIQxCfWhYu68U0RBBERXCq+WrXoorYIFWpbEY0lpk0NTWKtuUlzn+d834yLm5smqQspzurMcM785j+c+eYTTtUcESAzvhIAm/+azHacA4FodszAVNFTrUPm+Q6iecmUyJkEna5OiDCCXCtvJ2cnV+Ep+9R7/VIfQhmeryKeySywok+SSMMKMwqAihDXPIcPDDMURUQCgiPWjJCck6x87ZXXV3cXu3XTO5tkYOvAHbnIfZipTpghLdAMIEngi1cXvtlzwfrHpG0x5ismzsvo0E9D9z7z++M799s2EcSm67OUkAs5cpbzkkoMtPtAAzdXQ9zqjHkt1Ol5SHofx0KWYRUxrdiS3FlLtzz51wd7+v2OQl7qHnPtorUXS3ZxPRUKUT5x4mTDWu559LbCNS+9X9v025Duc4KoYdMAA7A4Mk92EMp/JFIZwR/rx9dL1teVdC2/Qe8yzQg+pS0JvLUzx3hjioPVQamGGlcu47KNq6qrPj+fsd+GeAEYA2SmRQiCNSJKP1Ad3IVaG0nnlWRxKqkkVlYxJxGZwhmFIo34U/fh0Hv4v6YYrY+ihYtkorDUNj+298GPvzv6ZRrkMzA/oyCXh9rEMOOHfiLfcx+5zhXkOnppswxEpJHVxdTjs0CycDHy9XcMlwc5a0E3EoTconOls/dyBsb6lYRLY4m/9T6blDgi8oHw3rPx83fesubl4oVPWFvXBUKoQzqB92Xitpite77n/k/epaN7AZO1CTIROtZ14fJC6ccS9ndGUhRLK0Eum1h2YGpH5eFfD47sjluzcFo+f+vp655F03alNhZhASMjloA1qtzedzab125kiw2QLhHaQ0zIFM2MztUdkBcqx1Lp+0o59NGRP49OVQs0Z3d6nEyMUMP8OGgVtAJaA19CagP4xn4e6DPuPhox1V9HTRFr/h9mRmWkwbJtGSsHK4xXq4cQGQDCDABM0ClEy6DlJiA9DLV90BgktirFzhrPXX0mT6Y9lAaqkAhRItRKGT3bjetTYd2aYM7JYcwm5wwaAP44hDyQYukokg5jliICZoFIoNjZ4Ol1HdhueOPgCLlFjt7twvo63HwztGuipml20lEBBlrGfBXzR5BsDGjOPBrAAkJKRKBwuuepNUXyP5/HN7tKXFGvcuMGY/3qhAO/NLCTJ7kFmIT0OPgjmAhiYKYIASFgGoCUyAILu+o8ckng0jSwsF1YuzxP0hYwm3tizwIIpKPQOIY4BXUYCiiYYWSIKYYHMoRAV1fKTddFxJKQOA/mmW9zFWRjoCmYw6R1lrcg2kxgAfCIeRxKMa+YBSw0Vc7fOScAZuAnMXWYE8yaIUFBDFSbS8sCgscsayZWD3jMAmhT7b8CnDPIeZw6RGTOLmwWFRALMA3BZvkamoBcwM3Zh7MA9Yb5I3v/YKoKTlr9sROKZVrlTGDWsylmkMTGxCQ4h0ObGaT1aRJzHsbtwJJmWSet0/9kIpB69gPbgersJA4oMm/pn6JlQI1/uWX87/YP06p9rkZQnAYAAAAASUVORK5CYII='
+
+ github64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAADAwMDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhyjGAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABzSURBVChTbYxRFoAgDMPQ+98Z1zbIeJqPbU3RMRfDECqyGpjMg6ivT6NBbKTw5WySq0jKt/sHrXiJ8PwpAAVIgQGkwABSYAApMIAUGEAalFmK9UJ24dC1i7qdj6IO5F+xnxfLu0jS0c7kqxd3Dk+JY8/5AKFrLuM7mfCAAAAAAElFTkSuQmCC'
+
+
+ run64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABqSURBVChTpY5JDsAwCMTy/09TMGvFpVF9aAZPRHpkcXC7OIodPg0uCjPq+MwCrWRGKkiIvLyTqzw3aqoI73eqUNAoXBXlg4zudxF+NONfPIVvbSZPgww5oW0Vz8T4Lgbt/xbjia+rahR5AEYEg4vdzh2JAAAAAElFTkSuQmCC'
+
+ storage64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwcHDQ0NDg4ODw8PFxcXGRkZGhoaGxsbHh4eIyMjJSUlJiYmJycnKCgoMTExMjIyNTU1NjY2Nzc3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAouNksgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdQAAA3UAe+RuhUAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAC5SURBVChTfZLbDsMgDEPpbb3TDv7/W7PYuAztYUeqhO2QAGowkXIMIeYkaSU4QsNBi4GcyhNINpTglmq4GWSphvy/ldkuLXZ4HmAxy3NmFJaA4guKGCwsjClfV05+fWdhYBtFw+amB292aygW3M7fsPTwjmadZkCvHEtWaAYTViBqVwgTA3tJVnB6D/xhaimItDhjMBvlhtFsaIafnEtOaAY/twAw/eslK70CbX8obUvgJNw9Jv0+Zh8D4s5+VAm/LwAAAABJRU5ErkJggg=='
+
+ ShowMeTheButtons()
+
diff --git a/DemoPrograms old/Demo_Menus.py b/DemoPrograms old/Demo_Menus.py
new file mode 100644
index 000000000..92235224b
--- /dev/null
+++ b/DemoPrograms old/Demo_Menus.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+"""
+ Demonstration of MENUS!
+ How do menus work? Like buttons is how.
+ Check out the variable menu_def for a hint on how to
+ define menus
+"""
+def second_window():
+
+ layout = [[sg.Text('The second form is small \nHere to show that opening a window using a window works')],
+ [sg.OK()]]
+
+ window = sg.Window('Second Form', layout)
+ event, values = window.read()
+ window.close()
+
+def test_menus():
+
+
+ sg.change_look_and_feel('LightGreen')
+ sg.set_options(element_padding=(0, 0))
+
+ # ------ Menu Definition ------ #
+ menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit' ]],
+ ['&Edit', ['&Paste', ['Special', 'Normal',], 'Undo'],],
+ ['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']],
+ ['&Help', '&About...'],]
+
+ # ------ GUI Defintion ------ #
+ layout = [
+ [sg.Menu(menu_def, tearoff=False, pad=(20,1))],
+ [sg.Output(size=(60,20))],
+ ]
+
+ window = sg.Window("Windows-like program",
+ layout,
+ default_element_size=(12, 1),
+ auto_size_text=False,
+ auto_size_buttons=False,
+ default_button_element_size=(12, 1))
+
+ # ------ Loop & Process button menu choices ------ #
+ while True:
+ event, values = window.read()
+ if event is None or event == 'Exit':
+ return
+ print('Event = ', event)
+ # ------ Process menu choices ------ #
+ if event == 'About...':
+ window.disappear()
+ sg.popup('About this program','Version 1.0', 'PySimpleGUI rocks...', grab_anywhere=True)
+ window.reappear()
+ elif event == 'Open':
+ filename = sg.popup_get_file('file to open', no_window=True)
+ print(filename)
+ elif event == 'Properties':
+ second_window()
+
+test_menus()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Multiple_Windows_Experimental.py b/DemoPrograms old/Demo_Multiple_Windows_Experimental.py
new file mode 100644
index 000000000..a5902d60e
--- /dev/null
+++ b/DemoPrograms old/Demo_Multiple_Windows_Experimental.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout1 = [[ sg.Text('Window 1') ],
+ [sg.Input(do_not_clear=True)],
+ [ sg.Button('Read')]]
+
+window1 = sg.Window('My new window', location=(800,500)).Layout(layout1)
+
+
+layout2 = [[ sg.Text('Window 2') ],
+ [sg.Input(do_not_clear=True)],
+ [ sg.Button('Read')]]
+
+window2 = sg.Window('My new window', location=(800, 625), return_keyboard_events=True).Layout(layout2)
+
+
+layout3 = [[ sg.Text('Window 3') ],
+ [sg.Input(do_not_clear=False)],
+ [ sg.Button('Read')]]
+
+window3 = sg.Window('My new window', location=(800,750), return_keyboard_events=True).Layout(layout3)
+
+
+while True: # Event Loop
+ event, values = window1.Read(timeout=50)
+ if event is None:
+ break
+ elif event != '__timeout__':
+ print(event, values)
+
+ event, values = window2.Read(timeout=0)
+ if event is None:
+ break
+ elif event != '__timeout__':
+ print(event, values)
+
+ event, values = window3.Read(timeout=0)
+ if event is None:
+ break
+ elif event != '__timeout__':
+ print(event, values)
diff --git a/DemoPrograms old/Demo_Multithreaded_Logging.py b/DemoPrograms old/Demo_Multithreaded_Logging.py
new file mode 100644
index 000000000..b5f0deb69
--- /dev/null
+++ b/DemoPrograms old/Demo_Multithreaded_Logging.py
@@ -0,0 +1,98 @@
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUIQt as sg
+else:
+ import PySimpleGUI27 as sg
+
+import queue
+import logging
+import threading
+import time
+
+"""
+ This code originated in this project:
+ https://github.com/john144/MultiThreading
+ Thanks to John for writing this in the early days of PySimpleGUI
+ Demo program showing one way that a threaded application can function with PySimpleGUI
+ Events are sent from the ThreadedApp thread to the main thread, the GUI, by using a queue
+"""
+
+logger = logging.getLogger('mymain')
+
+
+def externalFunction():
+ logger.info('Hello from external app')
+ logger.info('External app sleeping 5 seconds')
+ time.sleep(5)
+ logger.info('External app waking up and exiting')
+
+
+class ThreadedApp(threading.Thread):
+ def __init__(self):
+ super().__init__()
+ self._stop_event = threading.Event()
+
+ def run(self):
+ externalFunction()
+
+ def stop(self):
+ self._stop_event.set()
+
+
+class QueueHandler(logging.Handler):
+ def __init__(self, log_queue):
+ super().__init__()
+ self.log_queue = log_queue
+
+ def emit(self, record):
+ self.log_queue.put(record)
+
+
+def main():
+ window = sg.FlexForm('Log window', default_element_size=(30, 2), font=('Helvetica', ' 10'), default_button_element_size=(8, 2), return_keyboard_events=True)
+
+ layout = \
+ [
+ [sg.Multiline(size=(50, 15), key='Log')],
+ [sg.Button('Start', bind_return_key=True, key='_START_'), sg.Button('Exit')]
+ ]
+
+ window.Layout(layout).Read(timeout=0)
+ appStarted = False
+
+ # Setup logging and start app
+ logging.basicConfig(level=logging.DEBUG)
+ log_queue = queue.Queue()
+ queue_handler = QueueHandler(log_queue)
+ logger.addHandler(queue_handler)
+ threadedApp = ThreadedApp()
+
+ # Loop taking in user input and querying queue
+ while True:
+ # Wake every 100ms and look for work
+ event, values = window.Read(timeout=100)
+
+ if event == '_START_':
+ if appStarted is False:
+ threadedApp.start()
+ logger.debug('App started')
+ window.FindElement('_START_').Update(disabled=True)
+ appStarted = True
+ elif event in (None, 'Exit'):
+ break
+
+ # Poll queue
+ try:
+ record = log_queue.get(block=False)
+ except queue.Empty:
+ pass
+ else:
+ msg = queue_handler.format(record)
+ window.FindElement('Log').Update(msg+'\n', append=True)
+
+ window.Close()
+ exit()
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Multithreaded_Long_Tasks.py b/DemoPrograms old/Demo_Multithreaded_Long_Tasks.py
new file mode 100644
index 000000000..f74bee00d
--- /dev/null
+++ b/DemoPrograms old/Demo_Multithreaded_Long_Tasks.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python3
+
+import queue
+import threading
+import time
+
+# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
+# To try something other than tkinter version, just comment out the first import and uncomment the one you want
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+# import PySimpleGUIWx as sg
+# import PySimpleGUIWeb as sg
+
+"""
+ DESIGN PATTERN - Multithreaded Long Tasks GUI
+ Presents one method for running long-running operations in a PySimpleGUI environment.
+ The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
+ The "long work" is contained in the thread that is being started.
+
+ A queue.Queue is used by the threads to communicate with main GUI code
+ The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
+ a Window is created, and an event loop is executed.
+ What's different is that within this otherwise normal PySimpleGUI Event Loop, there is a check for items
+ in the Queue. If there are items found, process them by making GUI changes, and continue.
+
+ This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it
+ You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy
+"""
+
+
+def long_operation_thread(seconds, gui_queue):
+ """
+ A worker thread that communicates with the GUI through a queue
+ This thread can block for as long as it wants and the GUI will not be affected
+ :param seconds: (int) How long to sleep, the ultimate blocking call
+ :param gui_queue: (queue.Queue) Queue to communicate back to GUI that task is completed
+ :return:
+ """
+ print('Starting thread - will sleep for {} seconds'.format(seconds))
+ time.sleep(seconds) # sleep for a while
+ gui_queue.put('** Done **') # put a message into queue for GUI
+
+
+###### ## ## ####
+## ## ## ## ##
+## ## ## ##
+## #### ## ## ##
+## ## ## ## ##
+## ## ## ## ##
+###### ####### ####
+
+def the_gui():
+ """
+ Starts and executes the GUI
+ Reads data from a Queue and displays the data to the window
+ Returns when the user exits / closes the window
+ """
+
+ gui_queue = queue.Queue() # queue used to communicate between the gui and the threads
+
+ layout = [[sg.Text('Long task to perform example')],
+ [sg.Output(size=(70, 12))],
+ [sg.Text('Number of seconds your task will take'),sg.Input(key='_SECONDS_', size=(5,1)), sg.Button('Do Long Task', bind_return_key=True)],
+ [sg.Button('Click Me'), sg.Button('Exit')], ]
+
+ window = sg.Window('Multithreaded Window').Layout(layout)
+
+ # --------------------- EVENT LOOP ---------------------
+ while True:
+ event, values = window.Read(timeout=100) # wait for up to 100 ms for a GUI event
+ if event is None or event == 'Exit':
+ break
+ elif event.startswith('Do'):
+ try:
+ seconds = int(values['_SECONDS_'])
+ print('Starting thread to do long work....sending value of {} seconds'.format(seconds))
+ threading.Thread(target=long_operation_thread, args=(seconds , gui_queue,), daemon=True).start()
+ except Exception as e:
+ print('Error starting work thread. Did you input a valid # of seconds? You entered: %s' % values['_SECONDS_'])
+ elif event == 'Click Me':
+ print('Your GUI is alive and well')
+ # --------------- Check for incoming messages from threads ---------------
+ try:
+ message = gui_queue.get_nowait()
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ message = None # break from the loop if no more messages are queued up
+
+ # if message received from queue, display the message in the Window
+ if message:
+ print('Got a message back from the thread: ', message)
+
+ # if user exits the window, then close the window and exit the GUI func
+ window.Close()
+
+
+## ## ### #### ## ##
+### ### ## ## ## ### ##
+#### #### ## ## ## #### ##
+## ### ## ## ## ## ## ## ##
+## ## ######### ## ## ####
+## ## ## ## ## ## ###
+## ## ## ## #### ## ##
+
+if __name__ == '__main__':
+ the_gui()
+ print('Exiting Program')
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Multithreaded_Queued.py b/DemoPrograms old/Demo_Multithreaded_Queued.py
new file mode 100644
index 000000000..5e397925d
--- /dev/null
+++ b/DemoPrograms old/Demo_Multithreaded_Queued.py
@@ -0,0 +1,119 @@
+#!/usr/bin/python3
+
+# Rather than importing individual classes such as threading.Thread or queue.Queue, this
+# program is doing a simple import and then indicating the package name when the functions
+# are called. This seemed like a great way for the reader of the code to get an understanding
+# as to exactly which package is being used. It's purely for educational and explicitness purposes
+import queue
+import threading
+import time
+import itertools
+
+# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
+# To try something other than tkinter version, just comment out the first import and uncomment the one you want
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+# import PySimpleGUIWx as sg
+# import PySimpleGUIWeb as sg
+
+"""
+ DESIGN PATTERN - Multithreaded GUI
+ One method for running multiple threads in a PySimpleGUI environment.
+ The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
+ Other parts of the software are implemented as threads
+
+ A queue.Queue is used by the worker threads to communicate with code that calls PySimpleGUI directly.
+ The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
+ a Window is created, and an event loop is executed.
+ What's different is that within this otherwise normal PySimpleGUI Event Loop, there is a check for items
+ in the Queue. If there are items found, process them by making GUI changes, and continue.
+
+ This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it
+ You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy
+"""
+
+
+######## ## ## ######## ######## ### ########
+ ## ## ## ## ## ## ## ## ## ##
+ ## ## ## ## ## ## ## ## ## ##
+ ## ######### ######## ###### ## ## ## ##
+ ## ## ## ## ## ## ######### ## ##
+ ## ## ## ## ## ## ## ## ## ##
+ ## ## ## ## ## ######## ## ## ########
+
+def worker_thread(thread_name, run_freq, gui_queue):
+ """
+ A worker thrread that communicates with the GUI
+ These threads can call functions that block withouth affecting the GUI (a good thing)
+ Note that this function is the code started as each thread. All threads are identical in this way
+ :param thread_name: Text name used for displaying info
+ :param run_freq: How often the thread should run in milliseconds
+ :param gui_queue: Queue used to communicate with the GUI
+ :return:
+ """
+ print('Starting thread - {} that runs every {} ms'.format(thread_name, run_freq))
+ for i in itertools.count(): # loop forever, keeping count in i as it loops
+ time.sleep(run_freq/1000) # sleep for a while
+ gui_queue.put('{} - {}'.format(thread_name, i)) # put a message into queue for GUI
+
+ ###### ## ## ####
+## ## ## ## ##
+## ## ## ##
+## #### ## ## ##
+## ## ## ## ##
+## ## ## ## ##
+ ###### ####### ####
+
+def the_gui(gui_queue):
+ """
+ Starts and executes the GUI
+ Reads data from a Queue and displays the data to the window
+ Returns when the user exits / closes the window
+ (that means it does NOT return until the user exits the window)
+ :param gui_queue: Queue the GUI should read from
+ :return:
+ """
+ layout = [ [sg.Text('Multithreaded Window Example')],
+ [sg.Text('', size=(15,1), key='_OUTPUT_')],
+ [sg.Output(size=(40,6))],
+ [sg.Button('Exit')],]
+
+ window = sg.Window('Multithreaded Window').Layout(layout)
+ # --------------------- EVENT LOOP ---------------------
+ while True:
+ event, values = window.Read(timeout=100) # wait for up to 100 ms for a GUI event
+ if event is None or event == 'Exit':
+ break
+ #--------------- Loop through all messages coming in from threads ---------------
+ while True: # loop executes until runs out of messages in Queue
+ try: # see if something has been posted to Queue
+ message = gui_queue.get_nowait()
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ break # break from the loop if no more messages are queued up
+ # if message received from queue, display the message in the Window
+ if message:
+ window.Element('_OUTPUT_').Update(message)
+ window.Refresh() # do a refresh because could be showing multiple messages before next Read
+ print(message)
+ # if user exits the window, then close the window and exit the GUI func
+ window.Close()
+
+
+## ## ### #### ## ##
+### ### ## ## ## ### ##
+#### #### ## ## ## #### ##
+## ### ## ## ## ## ## ## ##
+## ## ######### ## ## ####
+## ## ## ## ## ## ###
+## ## ## ## #### ## ##
+
+if __name__ == '__main__':
+ #-- Create a Queue to communicate with GUI --
+ gui_queue = queue.Queue() # queue used to communicate between the gui and the threads
+ #-- Start worker threads, one runs twice as often as the other
+ threading.Thread(target=worker_thread, args=('Thread 1', 500, gui_queue,), daemon=True).start()
+ threading.Thread(target=worker_thread, args=('Thread 2', 200, gui_queue,), daemon=True).start()
+ threading.Thread(target=worker_thread, args=('Thread 3', 1000, gui_queue,), daemon=True).start()
+ #-- Start the GUI passing in the Queue --
+ the_gui(gui_queue)
+ print('Exiting Program')
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Nice_Buttons.py b/DemoPrograms old/Demo_Nice_Buttons.py
new file mode 100644
index 000000000..2640cd480
--- /dev/null
+++ b/DemoPrograms old/Demo_Nice_Buttons.py
@@ -0,0 +1,74 @@
+import PySimpleGUI as sg
+import os
+import io
+from PIL import Image, ImageDraw, ImageTk, ImageFont
+import base64
+import subprocess
+import sys
+
+
+def image_file_to_bytes(image64, size):
+ image_file = io.BytesIO(base64.b64decode(image64))
+ img = Image.open(image_file)
+ img.thumbnail(size, Image.ANTIALIAS)
+ bio = io.BytesIO()
+ img.save(bio, format='PNG')
+ imgbytes = bio.getvalue()
+ return imgbytes
+
+
+
+def ShowMeTheButtons():
+ bcolor = ('black', 'black')
+ wcolor = ('white', 'black')
+
+ sg.ChangeLookAndFeel('Black')
+ sg.SetOptions(auto_size_buttons=True, border_width=0, button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+ toolbar_buttons = [ [sg.Text('Who says Windows have to be ugly when using tkinter?', size=(45,3))],
+ [sg.Text('All of these buttons are part of the code itself', size=(45,2))],
+
+ [sg.RButton('Next', image_data=image_file_to_bytes(button64, (100,50)),button_color=wcolor, font='Any 15', pad=(0,0), key='_close_'),
+ # [sg.RButton('Exit', image_data=image_file_to_bytes(black64, (100,50)),button_color=bcolor, font='Any 15', pad=(0,0), key='_close_'),],
+ sg.RButton('Submit', image_data=image_file_to_bytes(red_pill64, (100,50)),button_color=wcolor, font='Any 15', pad=(0,0), key='_close_'),
+ sg.RButton('OK', image_data=image_file_to_bytes(green_pill64, (100,50)),button_color=bcolor, font='Any 15', pad=(0,0), key='_close_'),
+ sg.RButton('Exit', image_data=image_file_to_bytes(orange64, (100,50)),button_color=bcolor, font='Any 15', pad=(0,0), key='_close_'),],
+ ]
+
+ # layout = toolbar_buttons
+ layout = [[sg.Frame('Nice Buttons', toolbar_buttons, font=('any 18'), background_color='black')]]
+
+ window = sg.Window('Demo of Nice Looking Buttons',
+ no_titlebar=False,
+ grab_anywhere=True,
+ keep_on_top=True,
+ use_default_focus=False,
+ font='any 15',
+ background_color='black').Layout(layout).Finalize()
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = window.Read()
+ print(button)
+ if button == '_close_' or button is None:
+ break # exit button clicked
+
+if __name__ == '__main__':
+
+ # To convert your PNG into Base 64:
+ # Go to https://www.base64-image.de/
+ # Drag and drop your PNG image onto the webpage
+ # Choose "Copy image"
+ # Create a string variable name to hold your image
+ # Paste data from webpage as a string
+ # Delete the "header" stuff - up to the data portion (data:image/png;base64,)
+ orange64 = 'iVBORw0KGgoAAAANSUhEUgAAAiIAAADLCAMAAABkvgh7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANtvJ99sId5tIt5uI91tJNxuJNxuJttvKN90NN91Ntt3PN52ONx3Otx3PNt4Pdp4Ptx4PepfD+pfEOtgD+piD+tkD+ttD+dnFOdoE+doFOVoFuNqG+JrHOFrHuFsHuRpGORpGuRqGORqGupgEOpiEOpkEOlmEOhnEupoEOpoEupqFettEetsF+tuFOxqFetrGOtsGetvHOxrGOxsGOxtGuxuG+xuHexxFutwH+xxGOxyGOxyGuxxHuBsIOJvJ+NvKORvKONwKeNwKuJxLONyLeJyLuRwKeRwKuRxLOtxIexyIexzJOx0JOx1Ju11KOx2KOx2Kux5Iux4Kux5Le1/LeFyMOFzMuB0NOB1Nux7MOx8MOx8Mu19NO1+NO1+Ntd7RdV8RtN+S9J/TdF/TtV9SNR9Stl5QNl6Qdh6Qth7RK+Tfa+Tfq6Ufr+JZb+JZr+KZ7uMbr6KaL6LaryMbLyNb7yOb7WPdLuNcLqOcLmOcrmPdLOQd7SQdrKReLKRerGSerCTfLCTfrmQde2AN+2AOO2BOu2COu6DPO6EPe6EPsWDV8OFXcOFXsOGXcOGXsaDWMSEWsqCVs+AUM2AUs6CU82CVMqDWMmEWtCAT9CAUMKHYMCIYsCIZMCKZu6FQO6GQe6GQu6HRO6IRe6JRu6KR+6KSO+LSu+MS++MTO+OTe+OTu+OUO+RUu+TVfCNTvCOTvCPUPCQUfCQUvCSU/CRVPCSVPCSVvCUV/CUWPCVWvGWWvGXXPGYXvCWYPGaYfGcYvGcZPKdZvKeZ/GdavKeaPKebfKebvKgavKhbPKibfGibvKjcPGkcfKmdPKiePOod/OpePSpePSqevSrfPSsfPSsfvSqg/SugfWwgvWwhPWyhfWyhvWxi/Wyj/W0ifW2jfa4j/a1kPW2kva2lfW2lvW4kPa6kfa7kva5lvW7lPa8lPW8lve+l/a4mva5nPa6nPa7nva+mPa+mva/nPa8oPa9ovbAm/bAnfXAnvbCofbEo/XGp/bGqPbIqQAAAC/NnaUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAAJXElEQVR4Xu3de3zVdR3H8Xb9/sJh60LlOTtubdIZEyckSdedMzkdZyRGIePmZdqki8s0KllJmtGCTAXRlUAyrireUeZga2JRkooYRWR0JbXMLsIqZ5fT7/L5nRvj9/md0/fhw/Px/fyHP+D33fb4vPj+LvsxXpMA8IREgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgJF7Ih1Xf3bVsuu/AYXu+mUrL+u8iqbqIcdErvhme0V8SjQCIpwWe+0nli+k2R5NTolc0jYzqpQBcigV+UDltZ57SQ6JfLqyRRXRyiCIis7u7qAhj8B3Ip1tLdg/pFLR0Z+hOR/JbyIrWxGIZCp289E2Ep+J3HzEFqLKy0qhUJUfeUkZnf8lGnYWX4l0tDfTOg5VEqoJNNTXh6EgmaMLBKuaymmcJFLRSfPO5CuRtgitYisPBehDQUFrqC3O2EtUxRdo4Bn8JHJhlNawlNZh85Aj2JQeiRp9JY08nY9Euk+nFUwq1ECLgww1ZTRaS+R8mnk6PpEF8dTDkNIgLQxiHFdNw7U0d9PU07CJdLw+tRUVpy5Cxo19+bz9lYI+n5cNfdhcjWGZf2jsCTTJcDiUmnBR/HKaewqbSHfqQqSJrkLGvuuctZu3jOgBD1u99B7Fg6a+Vwrrk8kNfRX+0XE2+qg527adsc38M723d01yK3lbqhH1SZp7CpfIolnJw4udQk44ddPOn/3q6b+M6K8+/c2vF+jXVw29X/ALI7N+Z3jome+f/QZ7pOG6VCMtl9Dkk7hElifvd0uPs1cb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'
+
+ green_pill64 = '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'
+
+ red_pill64 = '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'
+
+ button64 = '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'
+
+ ShowMeTheButtons()
+
diff --git a/DemoPrograms old/Demo_NonBlocking_Form.py b/DemoPrograms old/Demo_NonBlocking_Form.py
new file mode 100644
index 000000000..f3561f7ca
--- /dev/null
+++ b/DemoPrograms old/Demo_NonBlocking_Form.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import time
+
+# Window that doen't block
+# good for applications with an loop that polls hardware
+def StatusOutputExample():
+ # Create a text element that will be updated with status information on the GUI itself
+ # Create the rows
+ layout = [[sg.Text('Non-blocking GUI with updates')],
+ [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='output')],
+ [sg.Button('LED On'), sg.Button('LED Off'), sg.Button('Quit')]]
+ # Layout the rows of the Window and perform a read. Indicate the Window is non-blocking!
+ window = sg.Window('Running Timer', auto_size_text=True).Layout(layout)
+
+ #
+ # Some place later in your code...
+ # You need to perform a Read on your window every now and then or
+ # else it won't refresh.
+ #
+ # your program's main loop
+ i=0
+ while (True):
+ # This is the code that reads and updates your window
+ event, values = window.Read(timeout=10)
+ window.FindElement('output').Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100))
+ if event in ('Quit', None):
+ break
+ if event == 'LED On':
+ print('Turning on the LED')
+ elif event == 'LED Off':
+ print('Turning off the LED')
+
+ i += 1
+ # Your code begins here
+
+ # Broke out of main loop. Close the window.
+ window.Close()
+
+
+def RemoteControlExample():
+
+ layout = [[sg.Text('Robotics Remote Control')],
+ [sg.T(' '*10), sg.RealtimeButton('Forward')],
+ [ sg.RealtimeButton('Left'), sg.T(' '*15), sg.RealtimeButton('Right')],
+ [sg.T(' '*10), sg.RealtimeButton('Reverse')],
+ [sg.T('')],
+ [sg.Quit(button_color=('black', 'orange'))]
+ ]
+
+ window = sg.Window('Robotics Remote Control', auto_size_text=True).Layout(layout).Finalize()
+
+ #
+ # Some place later in your code...
+ # You need to perform a ReadNonBlocking on your window every now and then or
+ # else it won't refresh.
+ #
+ # your program's main loop
+ while (True):
+ # This is the code that reads and updates your window
+ event, values = window.Read(timeout=0, timeout_key='timeout')
+ if event != 'timeout':
+ print(event)
+ if event in ('Quit', None):
+ break
+
+ window.Close()
+
+
+def main():
+ RemoteControlExample()
+ StatusOutputExample()
+ sg.Popup('End of non-blocking demonstration')
+
+
+if __name__ == '__main__':
+
+ main()
diff --git a/DemoPrograms old/Demo_Notification_Window_Alpha_Channel.py b/DemoPrograms old/Demo_Notification_Window_Alpha_Channel.py
new file mode 100644
index 000000000..ea645eae2
--- /dev/null
+++ b/DemoPrograms old/Demo_Notification_Window_Alpha_Channel.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+import sys
+import time
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+# Demonstrates a notification window that's partially transparent
+# The window slowly fades-in
+# Includes a small red-X button to close the window
+# Base 64 encoded button is in-lined to avoid reading a file
+# Free online encoder - https://www.base64-image.de/
+red_x ="R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+
+
+sg.ChangeLookAndFeel('Topanga')
+sg.SetOptions(border_width=0, margins=(0,0))
+bcolor=('black', '#282923')
+
+sg.SetOptions(border_width=0, margins=(0,0))
+
+layout = [[sg.T('Notification'+' '*14),
+ sg.CloseButton('', image_data=red_x, button_color=('#282923', '#282923'))],
+ [sg.T('')],
+ [sg.T('You have 6 new emails')],]
+
+window = sg.Window('',
+ no_titlebar=True,
+ grab_anywhere=True,
+ keep_on_top=True,
+ alpha_channel=0
+ ).Layout(layout).Finalize()
+
+# Classy fade-in
+for i in range(1, 75, 2):
+ window.AlphaChannel = float(i)/100
+ time.sleep(.01)
+
+event, values = window.Read()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_OpenCV.py b/DemoPrograms old/Demo_OpenCV.py
new file mode 100644
index 000000000..194980af8
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import cv2 as cv
+from PIL import Image
+import io
+from sys import exit as exit
+
+"""
+Demo program to open and play a file using OpenCV
+It's main purpose is to show you:
+1. How to get a frame at a time from a video file using OpenCV
+2. How to display an image in a PySimpleGUI Window
+
+For added fun, you can reposition the video using the slider.
+"""
+
+def main():
+ # ---===--- Get the filename --- #
+ filename = sg.PopupGetFile('Filename to play')
+ if filename is None:
+ exit(69)
+ vidFile = cv.VideoCapture(filename)
+ # ---===--- Get some Stats --- #
+ num_frames = vidFile.get(cv.CAP_PROP_FRAME_COUNT)
+ fps = vidFile.get(cv.CAP_PROP_FPS)
+
+ sg.ChangeLookAndFeel('Black')
+
+ # ---===--- define the window layout --- #
+ layout = [[sg.Text('OpenCV Demo', size=(15, 1), font='Helvetica 20')],
+ [sg.Image(filename='', key='_image_')],
+ [sg.Slider(range=(0, num_frames), size=(60, 10), orientation='h', key='_slider_')],
+ [sg.Button('Exit', size=(7, 1), pad=((600, 0), 3), font='Helvetica 14')]]
+
+ # create the window and show it without the plot
+ window = sg.Window('Demo Application - OpenCV Integration', no_titlebar=False, location=(0,0)).Layout(layout)
+
+ image_elem = window.Element('_image_') # locate the elements we'll be updating. Does the search only 1 time
+ slider_elem = window.Element('_slider_')
+
+ # ---===--- LOOP through video file by frame --- #
+ cur_frame = 0
+ while vidFile.isOpened():
+ event, values = window.Read(timeout=0)
+ if event in ('Exit', None):
+ exit(69)
+ ret, frame = vidFile.read()
+ if not ret: # if out of data stop looping
+ break
+ if int(values['_slider_']) != cur_frame-1: # if someone moved the slider manually, the jump to that frame
+ cur_frame = int(values['_slider_'])
+ vidFile.set(cv.CAP_PROP_POS_FRAMES, cur_frame)
+ slider_elem.Update(cur_frame)
+ cur_frame += 1
+
+ imgbytes = cv.imencode('.png', frame)[1].tobytes() # ditto
+ image_elem.Update(data=imgbytes)
+
+"""
+ # This was another way updates were being done, but seems slower than the above
+ img = Image.fromarray(frame) # create PIL image from frame
+ bio = io.BytesIO() # a binary memory resident stream
+ img.save(bio, format= 'PNG') # save image as png to it
+ imgbytes = bio.getvalue() # this can be used by OpenCV hopefully
+ image_elem.Update(data=imgbytes)
+"""
+
+main()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_OpenCV_4_Line_Program.py b/DemoPrograms old/Demo_OpenCV_4_Line_Program.py
new file mode 100644
index 000000000..6e032cf3b
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_4_Line_Program.py
@@ -0,0 +1,4 @@
+import cv2, PySimpleGUI as sg
+window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')],], location=(800,400)), cv2.VideoCapture(0)
+while window(timeout=20)[0] is not None:
+ window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes())
diff --git a/DemoPrograms old/Demo_OpenCV_7_Line_Program.py b/DemoPrograms old/Demo_OpenCV_7_Line_Program.py
new file mode 100644
index 000000000..b1cc0ff74
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_7_Line_Program.py
@@ -0,0 +1,13 @@
+import cv2, PySimpleGUI as sg
+window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')],], location=(800,400))
+cap = cv2.VideoCapture(0) # Setup the camera as a capture device
+while True: # The PSG "Event Loop"
+ event, values = window.Read(timeout=20, timeout_key='timeout') # get events for the window with 20ms max wait
+ if event is None: break # if user closed window, quit
+ window.FindElement('image').Update(data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) # Update image in window
+
+"""
+Putting the comment at the bottom so that you can see that the code is indeed 7 lines long. And, there is nothing
+done out of the ordinary to make it 7 lines long. There are no ; for example. OK, so the if statement is on one line
+but that's the only place that you would traditionally see one more line. So, call it 8 if you want.
+"""
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_OpenCV_Draw_On_Webcam_Image.py b/DemoPrograms old/Demo_OpenCV_Draw_On_Webcam_Image.py
new file mode 100644
index 000000000..46a1cdb42
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_Draw_On_Webcam_Image.py
@@ -0,0 +1,38 @@
+import PySimpleGUI as sg
+import cv2
+
+"""
+ Demonstration of how to use a GRAPH ELEMENT to draw a webcam stream using OpenCV and PySimpleGUI.
+ Additionally, the thing this demo is really showcasing, is the ability to draw over the top of this
+ webcam stream, as it's being displayed. To "Draw" simply move your mouse over the image, left click and hold, and
+ then drag your mouse. You'll see a series of red circles on top of your image.
+ CURRENTLY ONLY WORKS WITH PySimpleGUI, NOT any of the other ports at this time.
+"""
+
+def main():
+ layout = [[sg.Graph((600,450),(0,450), (600,0), key='_GRAPH_', enable_events=True, drag_submits=True)],]
+
+ window = sg.Window('Demo Application - OpenCV Integration', layout)
+
+ graph_elem = window.Element('_GRAPH_') # type: sg.Graph
+
+ id = None
+ # ---===--- Event LOOP Read and display frames, operate the GUI --- #
+ cap = cv2.VideoCapture(0)
+ while True:
+ event, values = window.Read(timeout=0)
+ if event in ('Exit', None):
+ break
+
+ ret, frame = cap.read()
+ imgbytes=cv2.imencode('.png', frame)[1].tobytes()
+ if id:
+ graph_elem.DeleteFigure(id) # delete previous image
+ id = graph_elem.DrawImage(data=imgbytes, location=(0,0)) # draw new image
+ graph_elem.TKCanvas.tag_lower(id) # move image to the "bottom" of all other drawings
+
+ if event == '_GRAPH_':
+ graph_elem.DrawCircle(values['_GRAPH_'], 5, fill_color='red', line_color='red')
+ window.Close()
+
+main()
diff --git a/DemoPrograms old/Demo_OpenCV_Simple_GUI.py b/DemoPrograms old/Demo_OpenCV_Simple_GUI.py
new file mode 100644
index 000000000..7399dc964
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_Simple_GUI.py
@@ -0,0 +1,88 @@
+import sys
+
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import cv2
+import numpy as np
+from sys import exit as exit
+
+"""
+Demo program that displays a webcam using OpenCV and applies some very basic image functions
+
+- functions from top to bottom -
+none: no processing
+threshold: simple b/w-threshold on the luma channel, slider sets the threshold value
+canny: edge finding with canny, sliders set the two threshold values for the function => edge sensitivity
+contour: colour finding in the frame, first slider sets the hue for the colour to find, second the minimum saturation
+ for the object. Found objects are drawn with a red contour.
+blur: simple Gaussian blur, slider sets the sigma, i.e. the amount of blur smear
+hue: moves the image hue values by the amount selected on the slider
+enhance: applies local contrast enhancement on the luma channel to make the image fancier - slider controls fanciness.
+"""
+
+
+def main():
+ sg.ChangeLookAndFeel('LightGreen')
+
+ # define the window layout
+ layout = [[sg.Text('OpenCV Demo', size=(40, 1), justification='center')],
+ [sg.Image(filename='', key='image')],
+ [sg.Radio('None', 'Radio', True, size=(10, 1))],
+ [sg.Radio('threshold', 'Radio', size=(10, 1), key='thresh'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(40, 15), key='thresh_slider')],
+ [sg.Radio('canny', 'Radio', size=(10, 1), key='canny'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='canny_slider_a'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='canny_slider_b')],
+ [sg.Radio('contour', 'Radio', size=(10, 1), key='contour'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='contour_slider'),
+ sg.Slider((0, 255), 80, 1, orientation='h', size=(20, 15), key='base_slider')],
+ [sg.Radio('blur', 'Radio', size=(10, 1), key='blur'),
+ sg.Slider((1, 11), 1, 1, orientation='h', size=(40, 15), key='blur_slider')],
+ [sg.Radio('hue', 'Radio', size=(10, 1), key='hue'),
+ sg.Slider((0, 225), 0, 1, orientation='h', size=(40, 15), key='hue_slider')],
+ [sg.Radio('enhance', 'Radio', size=(10, 1), key='enhance'),
+ sg.Slider((1, 255), 128, 1, orientation='h', size=(40, 15), key='enhance_slider')],
+ [sg.Button('Exit', size=(10, 1))]]
+
+ # create the window and show it without the plot
+ window = sg.Window('Demo Application - OpenCV Integration',
+ location=(800, 400))
+ window.Layout(layout).Finalize()
+
+ cap = cv2.VideoCapture(0)
+ while True:
+ event, values = window.Read(timeout=0, timeout_key='timeout')
+ if event == 'Exit' or event is None:
+ sys.exit(0)
+ ret, frame = cap.read()
+ if values['thresh']:
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)[:, :, 0]
+ _, frame = cv2.threshold(frame, values['thresh_slider'], 255, cv2.THRESH_BINARY)
+ if values['canny']:
+ frame = cv2.Canny(frame, values['canny_slider_a'], values['canny_slider_b'])
+ if values['blur']:
+ frame = cv2.GaussianBlur(frame, (21, 21), values['blur_slider'])
+ if values['hue']:
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
+ frame[:, :, 0] += values['hue_slider']
+ frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
+ if values['enhance']:
+ enh_val = values['enhance_slider'] / 40
+ clahe = cv2.createCLAHE(clipLimit=enh_val, tileGridSize=(8, 8))
+ lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)
+ lab[:, :, 0] = clahe.apply(lab[:, :, 0])
+ frame = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
+ if values['contour']:
+ hue = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
+ hue = cv2.GaussianBlur(hue, (21, 21), 1)
+ hue = cv2.inRange(hue, np.array([values['contour_slider'], values['base_slider'], 40]),
+ np.array([values['contour_slider'] + 30, 255, 220]))
+ _, cnts, _ = cv2.findContours(hue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
+ cv2.drawContours(frame, cnts, -1, (0, 0, 255), 2)
+ imgbytes = cv2.imencode('.png', frame)[1].tobytes() # ditto
+ window.FindElement('image').Update(data=imgbytes)
+
+
+main()
diff --git a/DemoPrograms old/Demo_OpenCV_Webcam.py b/DemoPrograms old/Demo_OpenCV_Webcam.py
new file mode 100644
index 000000000..287f485ad
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_Webcam.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+import cv2
+import numpy as np
+import sys
+from sys import exit as exit
+
+"""
+Demo program that displays a webcam using OpenCV
+"""
+def main():
+
+ sg.ChangeLookAndFeel('Black')
+
+ # define the window layout
+ layout = [[sg.Text('OpenCV Demo', size=(40, 1), justification='center', font='Helvetica 20')],
+ [sg.Image(filename='', key='image')],
+ [sg.Button('Record', size=(10, 1), font='Helvetica 14'),
+ sg.Button('Stop', size=(10, 1), font='Any 14'),
+ sg.Button('Exit', size=(10, 1), font='Helvetica 14'),]]
+
+ # create the window and show it without the plot
+ window = sg.Window('Demo Application - OpenCV Integration', layout,
+ location=(800,400))
+
+ # ---===--- Event LOOP Read and display frames, operate the GUI --- #
+ cap = cv2.VideoCapture(0)
+ recording = False
+ while True:
+ event, values = window.Read(timeout=20)
+ if event == 'Exit' or event is None:
+ sys.exit(0)
+ elif event == 'Record':
+ recording = True
+ elif event == 'Stop':
+ recording = False
+ img = np.full((480, 640),255)
+ imgbytes=cv2.imencode('.png', img)[1].tobytes() #this is faster, shorter and needs less includes
+ window.FindElement('image').Update(data=imgbytes)
+
+ if recording:
+ ret, frame = cap.read()
+ imgbytes=cv2.imencode('.png', frame)[1].tobytes() #ditto
+ window.FindElement('image').Update(data=imgbytes)
+
+main()
+exit()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms old/Demo_OpenCV_Webcam_ASCII.py
new file mode 100644
index 000000000..61232d00a
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_Webcam_ASCII.py
@@ -0,0 +1,67 @@
+from PIL import Image
+import numpy as np
+import PySimpleGUI as sg; font_size=6; USING_QT=False
+# import PySimpleGUIQt as sg; font_size=8; USING_QT=True # if using, be sure and use the second layout that is commented out
+# import PySimpleGUIWeb as sg; font_size=12; USING_QT=False # yes, it runs in a webpage too! Not as good as tkinter but works
+import cv2
+
+"""
+ Interesting program that shows your webcam's image as ASCII text. Runs in realtime, producing a stream of
+ images so that it is actually animated ASCII text. Wild stuff that came about from a post on Reddit of all
+ places. The software bits that turn the image into ASCII text were shamelessly taken from this gist:
+ https://gist.github.com/cdiener/10491632
+ Brilliant work to have pulled off so much with so little Numpy
+ What's remarkable about this program is that the animation is created by updating individual Text Elements going
+ down the window, one line at a time, every time through the loop. That's 48 lines of text every time. Rough
+ timing shows an animation of more than 10 fps when running any of the PySimpleGUI ports.
+ Also added onto this are a spinner and a slider. They do essentially the same thing, enable a pair of parameters
+ to be modified on the fly.
+
+ You need PySimpleGUI installed as well as OpenCV. Both are easily installed via pip:
+ pip install PySimpleGUI
+ pip install opencv-python
+
+ On Linux / Mac use pip3 instead of pip
+"""
+
+# The magic bits that make the ASCII stuff work shamelessly taken from https://gist.github.com/cdiener/10491632
+chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@'))
+SC, GCF, WCF = .1, 1, 7/4
+
+sg.ChangeLookAndFeel('Black') # make it look cool
+
+# define the window layout
+NUM_LINES = 48 # number of lines of text elements. Depends on cameras image size and the variable SC (scaller)
+if USING_QT:
+ layout = [[sg.T(i, size_px=(800, 12), font=('Courier', font_size), key='_OUT_' + str(i))] for i in range(NUM_LINES)]
+else:
+ layout = [[sg.T(i,size=(120,1), font=('Courier', font_size), pad=(0,0), key='_OUT_'+str(i))] for i in range(NUM_LINES)]
+
+layout += [[ sg.Button('Exit', size=(5,1)),
+ sg.T('GCF', size=(4,1)), sg.Spin([round(i,2) for i in np.arange(0.1,20.0,0.1)], initial_value=1, key='_SPIN_GCF_', size=(5,1)),
+ sg.T('WCF', size=(4,1)), sg.Slider((1,4), resolution=.05, default_value=1.75, orientation='h', key='_SLIDER_WCF_', size=(15,15))]]
+
+# create the window and show it without the plot
+window = sg.Window('Demo Application - OpenCV Integration', layout, location=(800,400), font='Any 18')
+
+# ---===--- Event LOOP Read and display frames, operate the GUI --- #
+cap = cv2.VideoCapture(0) # Setup the OpenCV capture device (webcam)
+while True:
+ event, values = window.Read(timeout=0)
+ if event in ('Exit', None):
+ break
+ ret, frame = cap.read() # Read image from capture device (camera)
+
+ img = Image.fromarray(frame) # create PIL image from frame
+ GCF = float(values['_SPIN_GCF_'])
+ WCF = values['_SLIDER_WCF_']
+ # More magic that coverts the image to ascii
+ S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC))
+ img = np.sum(np.asarray(img.resize(S)), axis=2)
+ img -= img.min()
+ img = (1.0 - img / img.max()) ** GCF * (chars.size - 1)
+
+ # "Draw" the image in the window, one line of text at a time!
+ for i, r in enumerate(chars[img.astype(int)]):
+ window.Element('_OUT_'+str(i)).Update("".join(r))
+window.Close()
diff --git a/DemoPrograms old/Demo_OpenCV_Webcam_Minimal.py b/DemoPrograms old/Demo_OpenCV_Webcam_Minimal.py
new file mode 100644
index 000000000..3d08fa037
--- /dev/null
+++ b/DemoPrograms old/Demo_OpenCV_Webcam_Minimal.py
@@ -0,0 +1,31 @@
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg
+# import PySimpleGUIWeb as sg # has a known flicker problem that's being worked
+import cv2
+
+"""
+ Demo of using OpenCV to show your webcam in a GUI window.
+ This demo will run on tkinter, Qt, and Web(Remi). The web version flickers at the moment though
+ To exit, right click and choose exit. If on Qt, you'll have to kill the program as there are no right click menus
+ in PySimpleGUIQt (yet).
+"""
+
+sg.ChangeLookAndFeel('Black')
+
+# define the window layout
+layout = [[sg.Image(filename='', key='_IMAGE_', tooltip='Right click for exit menu')],]
+
+# create the window and show it without the plot
+window = sg.Window('Demo Application - OpenCV Integration', layout, location=(800,400),
+ no_titlebar=True, grab_anywhere=True,
+ right_click_menu=['&Right', ['E&xit']], ) # if trying Qt, you will need to remove this right click menu
+
+# ---===--- Event LOOP Read and display frames, operate the GUI --- #
+cap = cv2.VideoCapture(0) # Setup the OpenCV capture device (webcam)
+while True:
+ event, values = window.Read(timeout=20, timeout_key='timeout')
+ if event in ('Exit', None):
+ break
+ ret, frame = cap.read() # Read image from capture device (camera)
+ imgbytes=cv2.imencode('.png', frame)[1].tobytes() # Convert the image to PNG Bytes
+ window.FindElement('_IMAGE_').Update(data=imgbytes) # Change the Image Element to show the new image
diff --git a/DemoPrograms old/Demo_PDF_Viewer.py b/DemoPrograms old/Demo_PDF_Viewer.py
new file mode 100644
index 000000000..48671c6d0
--- /dev/null
+++ b/DemoPrograms old/Demo_PDF_Viewer.py
@@ -0,0 +1,187 @@
+"""
+@created: 2018-08-19 18:00:00
+
+@author: (c) 2018 Jorj X. McKie
+
+Display a PyMuPDF Document using Tkinter
+-------------------------------------------------------------------------------
+
+Dependencies:
+-------------
+PyMuPDF, PySimpleGUI > v2.9.0, Tkinter with Tk v8.6+, Python 3
+
+
+License:
+--------
+GNU GPL V3+
+
+Description
+------------
+Read filename from command line and start display with page 1.
+Pages can be directly jumped to, or buttons for paging can be used.
+For experimental / demonstration purposes, we have included options to zoom
+into the four page quadrants (top-left, bottom-right, etc.).
+
+We also interpret keyboard events to support paging by PageDown / PageUp
+keys as if the resp. buttons were clicked. Similarly, we do not include
+a 'Quit' button. Instead, the ESCAPE key can be used, or cancelling the window.
+
+To improve paging performance, we are not directly creating pixmaps from
+pages, but instead from the fitz.DisplayList of the page. A display list
+will be stored in a list and looked up by page number. This way, zooming
+pixmaps and page re-visits will re-use a once-created display list.
+
+"""
+import sys
+import fitz
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+from sys import exit as exit
+from binascii import hexlify
+
+sg.ChangeLookAndFeel('GreenTan')
+
+if len(sys.argv) == 1:
+ fname = sg.PopupGetFile('PDF Browser', 'PDF file to open', file_types=(("PDF Files", "*.pdf"),))
+ if fname is None:
+ sg.PopupCancel('Cancelling')
+ exit(0)
+else:
+ fname = sys.argv[1]
+
+doc = fitz.open(fname)
+page_count = len(doc)
+
+# storage for page display lists
+dlist_tab = [None] * page_count
+
+title = "PyMuPDF display of '%s', pages: %i" % (fname, page_count)
+
+
+def get_page(pno, zoom=0):
+ """Return a PNG image for a document page number. If zoom is other than 0, one of the 4 page quadrants are zoomed-in instead and the corresponding clip returned.
+
+ """
+ dlist = dlist_tab[pno] # get display list
+ if not dlist: # create if not yet there
+ dlist_tab[pno] = doc[pno].getDisplayList()
+ dlist = dlist_tab[pno]
+ r = dlist.rect # page rectangle
+ mp = r.tl + (r.br - r.tl) * 0.5 # rect middle point
+ mt = r.tl + (r.tr - r.tl) * 0.5 # middle of top edge
+ ml = r.tl + (r.bl - r.tl) * 0.5 # middle of left edge
+ mr = r.tr + (r.br - r.tr) * 0.5 # middle of right egde
+ mb = r.bl + (r.br - r.bl) * 0.5 # middle of bottom edge
+ mat = fitz.Matrix(2, 2) # zoom matrix
+ if zoom == 1: # top-left quadrant
+ clip = fitz.Rect(r.tl, mp)
+ elif zoom == 4: # bot-right quadrant
+ clip = fitz.Rect(mp, r.br)
+ elif zoom == 2: # top-right
+ clip = fitz.Rect(mt, mr)
+ elif zoom == 3: # bot-left
+ clip = fitz.Rect(ml, mb)
+ if zoom == 0: # total page
+ pix = dlist.getPixmap(alpha=False)
+ else:
+ pix = dlist.getPixmap(alpha=False, matrix=mat, clip=clip)
+ return pix.getPNGData() # return the PNG image
+
+
+window = sg.Window(title, return_keyboard_events=True, use_default_focus=False)
+
+cur_page = 0
+data = get_page(cur_page) # show page 1 for start
+image_elem = sg.Image(data=data)
+goto = sg.InputText(str(cur_page + 1), size=(5, 1), do_not_clear=True)
+
+layout = [
+ [
+ sg.Button('Prev'),
+ sg.Button('Next'),
+ sg.Text('Page:'),
+ goto,
+ ],
+ [
+ sg.Text("Zoom:"),
+ sg.Button('Top-L'),
+ sg.Button('Top-R'),
+ sg.Button('Bot-L'),
+ sg.Button('Bot-R'),
+ ],
+ [image_elem],
+]
+
+window.Layout(layout)
+my_keys = ("Next", "Next:34", "Prev", "Prior:33", "Top-L", "Top-R",
+ "Bot-L", "Bot-R", "MouseWheel:Down", "MouseWheel:Up")
+zoom_buttons = ("Top-L", "Top-R", "Bot-L", "Bot-R")
+
+old_page = 0
+old_zoom = 0 # used for zoom on/off
+# the zoom buttons work in on/off mode.
+
+while True:
+ event, values = window.Read(timeout=100)
+ zoom = 0
+ force_page = False
+ if event is None:
+ break
+
+ if event in ("Escape:27",): # this spares me a 'Quit' button!
+ break
+ # print("hex(button)", hexlify(button.encode()))
+ if event[0] == chr(13): # surprise: this is 'Enter'!
+ try:
+ cur_page = int(values[0]) - 1 # check if valid
+ while cur_page < 0:
+ cur_page += page_count
+ except:
+ cur_page = 0 # this guy's trying to fool me
+ goto.Update(str(cur_page + 1))
+ # goto.TKStringVar.set(str(cur_page + 1))
+
+ elif event in ("Next", "Next:34", "MouseWheel:Down"):
+ cur_page += 1
+ elif event in ("Prev", "Prior:33", "MouseWheel:Up"):
+ cur_page -= 1
+ elif event == "Top-L":
+ zoom = 1
+ elif event == "Top-R":
+ zoom = 2
+ elif event == "Bot-L":
+ zoom = 3
+ elif event == "Bot-R":
+ zoom = 4
+
+ # sanitize page number
+ if cur_page >= page_count: # wrap around
+ cur_page = 0
+ while cur_page < 0: # we show conventional page numbers
+ cur_page += page_count
+
+ # prevent creating same data again
+ if cur_page != old_page:
+ zoom = old_zoom = 0
+ force_page = True
+
+ if event in zoom_buttons:
+ if 0 < zoom == old_zoom:
+ zoom = 0
+ force_page = True
+
+ if zoom != old_zoom:
+ force_page = True
+
+ if force_page:
+ data = get_page(cur_page, zoom)
+ image_elem.Update(data=data)
+ old_page = cur_page
+ old_zoom = zoom
+
+ # update page number field
+ if event in my_keys or not values[0]:
+ goto.Update(str(cur_page + 1))
+ # goto.TKStringVar.set(str(cur_page + 1))
diff --git a/DemoPrograms old/Demo_PNG_Thumbnail_Viewer.py b/DemoPrograms old/Demo_PNG_Thumbnail_Viewer.py
new file mode 100644
index 000000000..b11a71bd0
--- /dev/null
+++ b/DemoPrograms old/Demo_PNG_Thumbnail_Viewer.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import os
+from sys import exit as exit
+from PIL import Image
+import io
+import numpy as np
+
+thumbnails = {}
+
+ROWS = 8
+COLUMNS = 8
+sg.SetOptions(border_width=0)
+# Get the folder containing the images from the user
+# folder = 'A:/TEMP/pdfs'
+folder = sg.PopupGetFolder('Image folder to open')
+if folder is None:
+ sg.PopupCancel('Cancelling')
+ exit(0)
+def image_file_to_bytes(filename, size):
+ try:
+ image = Image.open(filename)
+ image.thumbnail(size, Image.ANTIALIAS)
+ bio = io.BytesIO() # a binary memory resident stream
+ image.save(bio, format='PNG') # save image as png to it
+ imgbytes = bio.getvalue()
+ except:
+ imgbytes = None
+ return imgbytes
+
+def set_image_to_blank(key):
+ img = Image.new('RGB', (100, 100), (255, 255, 255))
+ img.thumbnail((1, 1), Image.ANTIALIAS)
+ bio = io.BytesIO()
+ img.save(bio, format='PNG')
+ imgbytes = bio.getvalue()
+ window.FindElement(key).Update(image_data=imgbytes)
+
+
+
+# get list of PNG files in folder
+png_files = [os.path.join(folder, f) for f in os.listdir(folder) if '.png' in f]
+filenames_only = [f for f in os.listdir(folder) if '.png' in f]
+
+if len(png_files) == 0:
+ sg.Popup('No PNG images in folder')
+ exit(0)
+
+# define menu layout
+menu = [['&File', ['&Open Folder', 'E&xit']], ['&Help', ['&About',]]]
+
+buttons = []
+for display_index in range(ROWS):
+ row = []
+ for j in range(COLUMNS):
+ row.append(sg.Button('',border_width=0,button_color=sg.COLOR_SYSTEM_DEFAULT, key=(display_index, j)))
+ buttons.append(row)
+
+col_buttons = [[]]
+
+# define layout, show and read the window
+col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
+ [sg.Image(data=image_file_to_bytes(png_files[0], (500,500)), key='image')],]
+
+layout = [[sg.Menu(menu)], [sg.Column(buttons), sg.Column([[sg.Slider((len(png_files),0),default_value=0,size=(38,20),orientation='v', key='_slider_', change_submits=True)]]), sg.Column(col)]]
+window = sg.Window('Image Browser',
+ return_keyboard_events=True,
+ use_default_focus=False ).Layout(layout).Finalize()
+
+# -------========= Event Loop =========--------
+display_index=0
+while True:
+ for x in range(ROWS): # update thumbnails
+ for y in range(COLUMNS):
+ cur_index = display_index + (x * 4) + y
+ if cur_index < len(png_files):
+ filename = png_files[cur_index]
+ if filename not in thumbnails:
+ imgbytes = image_file_to_bytes(filename, (100,100))
+ thumbnails[filename] = imgbytes
+ else:
+ imgbytes = thumbnails[filename]
+ button_elem = window.FindElement(key=(x,y))
+ button_elem.Update(image_data=imgbytes)
+ else:
+ set_image_to_blank((x,y))
+
+ event, values = window.Read()
+ display_index = values['_slider_']
+ # --------------------- Button & Keyboard ---------------------
+ if event in (None, 'Exit'):
+ break
+ elif event in ('MouseWheel:Down', 'Down:40',) and display_index < len(png_files)-1:
+ display_index += 4
+ elif event in ('MouseWheel:Up', 'Up:38',) and display_index > 0:
+ display_index -= 4
+ elif event in ('Prior:33', 'Prev'):
+ display_index -= 16
+ elif event in ('Next:34', 'Next'):
+ display_index += 16
+
+ window.FindElement('_slider_').Update(display_index)
+ # ----------------- Menu choices -----------------
+ if event == 'Open Folder':
+ newfolder = sg.PopupGetFolder('New folder', no_window=True)
+ if newfolder is None:
+ continue
+ folder = newfolder
+ png_files = [os.path.join(folder, f) for f in os.listdir(folder) if '.png' in f]
+ filenames_only = [f for f in os.listdir(folder) if '.png' in f]
+ display_index = 0
+ thumbnail = {}
+ for j in range(ROWS):
+ for i in range(COLUMNS):
+ set_image_to_blank((i,j))
+ elif event == 'About':
+ sg.Popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!')
+ elif type(event) is tuple:
+ x, y = event
+ image_index = display_index + (x * 4) + y
+ if image_index < len(png_files):
+ filename = png_files[image_index]
+ imgbytes = image_file_to_bytes(filename, (500, 500))
+ window.FindElement('image').Update(data=imgbytes)
+ window.FindElement('filename').Update(filename)
+
diff --git a/DemoPrograms old/Demo_PNG_Viewer.py b/DemoPrograms old/Demo_PNG_Viewer.py
new file mode 100644
index 000000000..4fba5b1a6
--- /dev/null
+++ b/DemoPrograms old/Demo_PNG_Viewer.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import os
+from sys import exit as exit
+
+# Simple Image Browser based on PySimpleGUI
+
+# Get the folder containing the images from the user
+folder = sg.PopupGetFolder('Image folder to open')
+if folder is None:
+ sg.PopupCancel('Cancelling')
+ exit(0)
+
+# get list of PNG files in folder
+png_files = [folder + '\\' + f for f in os.listdir(folder) if '.png' in f]
+filenames_only = [f for f in os.listdir(folder) if '.png' in f]
+
+if len(png_files) == 0:
+ sg.Popup('No PNG images in folder')
+ exit(0)
+
+
+# define menu layout
+menu = [['File', ['Open Folder', 'Exit']], ['Help', ['About',]]]
+
+# define layout, show and read the window
+col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
+ [sg.Image(filename=png_files[0], key='image')],
+ [sg.Button('Next', size=(8,2)), sg.Button('Prev', size=(8,2)),
+ sg.Text('File 1 of {}'.format(len(png_files)), size=(15,1), key='filenum')]]
+
+col_files = [[sg.Listbox(values=filenames_only, size=(60,30), key='listbox')],
+ [sg.Button('Read')]]
+layout = [[sg.Menu(menu)], [sg.Column(col_files), sg.Column(col)]]
+window = sg.Window('Image Browser', return_keyboard_events=True, location=(0,0), use_default_focus=False ).Layout(layout)
+
+# loop reading the user input and displaying image, filename
+i=0
+while True:
+
+ event, values = window.Read()
+ # --------------------- Button & Keyboard ---------------------
+ if event is None:
+ break
+ elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and i < len(png_files)-1:
+ i += 1
+ elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33') and i > 0:
+ i -= 1
+ elif event == 'Exit':
+ exit(69)
+
+ filename = folder + '/' + values['listbox'][0] if event == 'Read' else png_files[i]
+
+ # ----------------- Menu choices -----------------
+ if event == 'Open Folder':
+ newfolder = sg.PopupGetFolder('New folder', no_window=True)
+ if newfolder is None:
+ continue
+ folder = newfolder
+ png_files = [folder + '/' + f for f in os.listdir(folder) if '.png' in f]
+ filenames_only = [f for f in os.listdir(folder) if '.png' in f]
+ window.FindElement('listbox').Update(values=filenames_only)
+ window.Refresh()
+ i = 0
+ elif event == 'About':
+ sg.Popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!')
+
+ # update window with new image
+ window.FindElement('image').Update(filename=filename)
+ # update window with filename
+ window.FindElement('filename').Update(filename)
+ # update page display
+ window.FindElement('filenum').Update('File {} of {}'.format(i+1, len(png_files)))
+
diff --git a/DemoPrograms old/Demo_Paned_Window.py b/DemoPrograms old/Demo_Paned_Window.py
new file mode 100644
index 000000000..0bc884aca
--- /dev/null
+++ b/DemoPrograms old/Demo_Paned_Window.py
@@ -0,0 +1,45 @@
+import PySimpleGUI as sg
+
+sg.ChangeLookAndFeel('GreenTan')
+
+col1 = sg.Column([[sg.Text('in pane1', text_color='blue')],
+ [sg.T('Pane1')],
+ [sg.T('Pane1')],
+ ])
+col2 = sg.Column([[sg.Text('in pane2', text_color='red')],
+ [sg.T('Pane2')],
+ [sg.Input(key='_IN2_', do_not_clear=True)],
+ [sg.T('Pane2')],
+ [sg.T('Pane2')],
+ ], key='_COL2_', visible=False)
+col3 = sg.Column([[sg.Text('in pane 4', text_color='green')],
+ [sg.In(key='_IN3_', enable_events=True, do_not_clear=True)],
+ ], key='_COL3_', visible=False)
+col4 = sg.Column([[sg.Text('Column 4', text_color='firebrick')],
+ [sg.In()],
+ ], key='_COL4_')
+col5 = sg.Column([[sg.Frame('Frame', [[sg.Text('Column 5', text_color='purple')],
+ [sg.In()],
+ ])]])
+
+layout = [ [sg.Text('Click'), sg.Text('', key='_OUTPUT_')],
+ [sg.Button('Remove'), sg.Button('Add')],
+ [sg.Pane([col5, sg.Column([[sg.Pane([col1, col2, col4], handle_size=15, orientation='v', background_color='red', show_handle=True, visible=True, key='_PANE_', border_width=0, relief=sg.RELIEF_GROOVE),]]),col3 ], orientation='h', background_color=None, size=(160,160), relief=sg.RELIEF_RAISED, border_width=0)]
+ ]
+
+window = sg.Window('Window Title', default_element_size=(15,1), resizable=True, border_depth=5).Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ print(event, values)
+ if event is None or event == 'Exit':
+ break
+ if event == 'Remove':
+ window.Element('_COL2_').Update(visible=False)
+ window.Element('_COL3_').Update(visible=False)
+ elif event == 'Add':
+ window.Element('_COL2_').Update(visible=True)
+ window.Element('_COL3_').Update(visible=True)
+ window.Element('_IN2_').Update(values['_IN3_'])
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Password_Login.py b/DemoPrograms old/Demo_Password_Login.py
new file mode 100644
index 000000000..1f7abfbd7
--- /dev/null
+++ b/DemoPrograms old/Demo_Password_Login.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import hashlib
+from sys import exit as exit
+
+"""
+ Create a secure login for your scripts without having to include your password
+ in the program. Create an SHA1 hash code for your password using the GUI. Paste into variable in final program
+ 1. Choose a password
+ 2. Generate a hash code for your chosen password by running program and entering 'gui' as the password
+ 3. Type password into the GUI
+ 4. Copy and paste hash code from GUI into variable named login_password_hash
+ 5. Run program again and test your login!
+ 6. Are you paying attention? The first person that can post an issue on GitHub with the
+ matching password to the hash code in this example gets a $5 PayPal payment
+"""
+
+# Use this GUI to get your password's hash code
+def HashGeneratorGUI():
+ layout = [[sg.T('Password Hash Generator', size=(30,1), font='Any 15')],
+ [sg.T('Password'), sg.In(key='password')],
+ [sg.T('SHA Hash'), sg.In('', size=(40,1), key='hash')],
+ ]
+
+ window = sg.Window('SHA Generator', auto_size_text=False, default_element_size=(10,1),
+ text_justification='r', return_keyboard_events=True, grab_anywhere=False).Layout(layout)
+
+ while True:
+ event, values = window.Read()
+ if event is None:
+ exit(69)
+
+ password = values['password']
+ try:
+ password_utf = password.encode('utf-8')
+ sha1hash = hashlib.sha1()
+ sha1hash.update(password_utf)
+ password_hash = sha1hash.hexdigest()
+ window.FindElement('hash').Update(password_hash)
+ except:
+ pass
+
+# ----------------------------- Paste this code into your program / script -----------------------------
+# determine if a password matches the secret password by comparing SHA1 hash codes
+def PasswordMatches(password, hash):
+ password_utf = password.encode('utf-8')
+ sha1hash = hashlib.sha1()
+ sha1hash.update(password_utf)
+ password_hash = sha1hash.hexdigest()
+ return password_hash == hash
+
+
+login_password_hash = 'e5e9fa1ba31ecd1ae84f75caaa474f3a663f05f4'
+password = sg.PopupGetText('Password', password_char='*')
+if password == 'gui': # Remove when pasting into your program
+ HashGeneratorGUI() # Remove when pasting into your program
+ exit(69) # Remove when pasting into your program
+if PasswordMatches(password, login_password_hash):
+ print('Login SUCCESSFUL')
+else:
+ print('Login FAILED!!')
diff --git a/DemoPrograms old/Demo_Pi_LEDs.py b/DemoPrograms old/Demo_Pi_LEDs.py
new file mode 100644
index 000000000..c82b9583b
--- /dev/null
+++ b/DemoPrograms old/Demo_Pi_LEDs.py
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+# GUI for switching an LED on and off to GPIO14
+
+# GPIO and time library:
+import time
+
+if sys.platform == 'win32':
+ from random import randint
+
+ class GPIO():
+ LOW = 0
+ HIGH = 1
+ BCM = OUT = 0
+ current_value = 0
+ @classmethod
+ def setmode(self, mode):
+ return
+ @classmethod
+ def setup(self, arg1, arg2):
+ return
+ @classmethod
+ def output(self, port, value):
+ self.current_value = value
+ @classmethod
+ def input(self, port):
+ return self.current_value
+else:
+ import RPi.GPIO as GPIO
+
+# determine that GPIO numbers are used:
+GPIO.setmode(GPIO.BCM)
+GPIO.setup(14, GPIO.OUT)
+
+def SwitchLED():
+ varLedStatus = GPIO.input(14)
+ if varLedStatus == 0:
+ GPIO.output(14, GPIO.HIGH)
+ return "LED is switched ON"
+ else:
+ GPIO.output(14, GPIO.LOW)
+ return "LED is switched OFF"
+
+
+def FlashLED():
+ for i in range(5):
+ GPIO.output(14, GPIO.HIGH)
+ time.sleep(0.5)
+ GPIO.output(14, GPIO.LOW)
+ time.sleep(0.5)
+
+layout = [[sg.T('Raspberry Pi LEDs')],
+ [sg.T('', size=(20, 1), key='output')],
+ [sg.Button('Switch LED')],
+ [sg.Button('Flash LED')],
+ [sg.Exit()]]
+
+window = sg.Window('Raspberry Pi GUI', layout, grab_anywhere=False)
+
+while True:
+ event, values = window.Read()
+ if event in (None, 'Exit'):
+ break
+
+ if event == 'Switch LED':
+ window.FindElement('output').Update(SwitchLED())
+ elif event == 'Flash LED':
+ window.FindElement('output').Update('LED is Flashing')
+ window.Refresh()
+ FlashLED()
+ window.FindElement('output').Update('')
+
+window.Close()
+sg.Popup('Done... exiting')
diff --git a/DemoPrograms old/Demo_Pi_Robotics.py b/DemoPrograms old/Demo_Pi_Robotics.py
new file mode 100644
index 000000000..0c2ea577a
--- /dev/null
+++ b/DemoPrograms old/Demo_Pi_Robotics.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+# Robotics design pattern
+# Uses Realtime Buttons to simulate the controls for a robot
+# Rather than sending a single click when a button is clicked, Realtime Buttons
+# send button presses continuously while the button is pressed down.
+# Two examples, one using fancy graphics, one plain.
+
+def RemoteControlExample():
+ # Make a form, but don't use context manager
+ sg.SetOptions(element_padding=(0,0))
+ back ='#eeeeee'
+ image_forward = 'ButtonGraphics/RobotForward.png'
+ image_backward = 'ButtonGraphics/RobotBack.png'
+ image_left = 'ButtonGraphics/RobotLeft.png'
+ image_right = 'ButtonGraphics/RobotRight.png'
+
+ sg.SetOptions(border_width=0, button_color=('black', back), background_color=back, element_background_color=back, text_element_background_color=back)
+
+ layout = [[sg.Text('Robotics Remote Control')],
+ [sg.T('', justification='center', size=(19,1), key='status')],
+ [ sg.RealtimeButton('', key='Forward', image_filename=image_forward, pad=((50,0),0))],
+ [ sg.RealtimeButton('', key='Left', image_filename=image_left),
+ sg.RealtimeButton('', key='Right', image_filename=image_right, pad=((50,0), 0))],
+ [ sg.RealtimeButton('', key='Reverse', image_filename=image_backward, pad=((50,0),0))],
+ [sg.T('')],
+ [sg.Quit(button_color=('black', 'orange'))]]
+
+ window = sg.Window('Robotics Remote Control', auto_size_text=True, grab_anywhere=False).Layout(layout)
+
+ #
+ # Some place later in your code...
+ # You need to perform a ReadNonBlocking on your form every now and then or
+ # else it won't refresh.
+ #
+ # your program's main loop
+ while (True):
+ # This is the code that reads and updates your window
+ event, values = window.Read(timeout=0, timeout_key='timeout')
+ if event is not None:
+ window.FindElement('status').Update(event)
+ elif event != 'timeout':
+ window.FindElement('status').Update('')
+ # if user clicked quit button OR closed the form using the X, then break out of loop
+ if event == 'Quit' or values is None:
+ break
+
+ window.Close()
+
+
+def RemoteControlExample_NoGraphics():
+ # Make a form, but don't use context manager
+
+ layout = [[sg.Text('Robotics Remote Control', justification='center')],
+ [sg.T('', justification='center', size=(19,1), key='status')],
+ [sg.T(' '*8), sg.RealtimeButton('Forward')],
+ [ sg.RealtimeButton('Left'), sg.T(' '), sg.RealtimeButton('Right')],
+ [sg.T(' '*8), sg.RealtimeButton('Reverse')],
+ [sg.T('')],
+ [sg.Quit(button_color=('black', 'orange'))]]
+ # Display form to user
+ window = sg.Window('Robotics Remote Control', auto_size_text=True, grab_anywhere=False).Layout(layout)
+
+ #
+ # Some place later in your code...
+ # You need to perform a Read on your form every now and then or
+ # else it won't refresh.
+ # Notice how the timeout is 100ms. You don't have to use a timeout = 0 for all of your hardware
+ # applications. Leave some CPU for other threads or for your GUI. The longer you are in the GUI, the more
+ # responsive the GUI itself will be Match your timeout with your hardware's capabilities
+ #
+ # your program's main loop
+ while (True):
+ # This is the code that reads and updates your window
+ event, values = window.Read(timeout=100, timeout_key='timeout')
+ # print(event, values)
+ if event != 'timeout':
+ window.FindElement('status').Update(event)
+ else:
+ window.FindElement('status').Update('')
+ # if user clicked quit button OR closed the form using the X, then break out of loop
+ if event in (None, 'Quit'):
+ break
+
+ window.Close()
+
+# ------------------------------------- main -------------------------------------
+def main():
+ RemoteControlExample_NoGraphics()
+ # Uncomment to get the fancy graphics version. Be sure and download the button images!
+ RemoteControlExample()
+ # sg.Popup('End of non-blocking demonstration')
+
+if __name__ == '__main__':
+
+ main()
diff --git a/DemoPrograms old/Demo_Ping_Line_Graph.py b/DemoPrograms old/Demo_Ping_Line_Graph.py
new file mode 100644
index 000000000..d7e8f182f
--- /dev/null
+++ b/DemoPrograms old/Demo_Ping_Line_Graph.py
@@ -0,0 +1,665 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+from threading import Thread
+import time
+from sys import exit as exit
+
+# !/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+# =============================================================================#
+import argparse
+import os, sys, socket, struct, select, time, signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+# =============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+
+# =============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string) / 2)) * 2
+ sum = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum = sum + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum = sum + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string) - 1]
+ try: # For Python3
+ sum += loByte
+ except: # For Python2
+ sum += ord(loByte)
+
+ sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
+ sum += (sum >> 16) # Add carry from above (if any)
+ answer = ~sum & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+
+# =============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime - sentTime) * 1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+
+# =============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ # destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size - 8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ # data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+
+# =============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout / 1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ # print (len(recPacket.encode()))
+ return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+
+# =============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+
+# =============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+
+# =============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ dump_stats(myStats)
+
+
+# =============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return False
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+
+# =============================================================================#
+def main():
+ parser = argparse.ArgumentParser(description=__description__)
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='quiet output')
+ parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS,
+ help=('number of packets to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT,
+ help=('time to wait for a response in seoncds '
+ '(default: %(default)s)'))
+ parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE,
+ help=('number of data bytes to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('destination')
+ # args = parser.parse_args()
+
+ ping = verbose_ping
+ # if args.quiet:
+ # ping = quiet_ping
+ ping('Google.com', timeout=1000)
+ # ping(args.destination, timeout=args.timeout*1000, count=args.count,
+ # packet_size=args.packet_size)
+
+
+# set coordinate system
+canvas_right = 300
+canvas_left = 0
+canvas_top = 0
+canvas_bottom = 300
+# define the coordinates you'll use for your graph
+x_right = 100
+x_left = 0
+y_bottom = 0
+y_top = 500
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
+
+def ping_thread(args):
+ global g_exit, g_response_time
+
+ while not g_exit:
+ g_response_time = quiet_ping('google.com', timeout=1000)
+
+
+def convert_xy_to_canvas_xy(x_in,y_in):
+ scale_x = (canvas_right - canvas_left) / (x_right - x_left)
+ scale_y = (canvas_top - canvas_bottom) / (y_top - y_bottom)
+ new_x = canvas_left + scale_x * (x_in - x_left)
+ new_y = canvas_bottom + scale_y * (y_in - y_bottom)
+ return new_x, new_y
+
+
+
+# start ping measurement thread
+thread = Thread(target=ping_thread, args=(None,))
+thread.start()
+
+layout = [ [sg.T('Ping times to Google.com', font='Any 18')],
+ [sg.Canvas(size=(canvas_right, canvas_bottom), background_color='white', key='canvas')],
+ [sg.Quit()] ]
+
+window = sg.Window('Ping Times To Google.com', grab_anywhere=True).Layout(layout).Finalize()
+
+canvas = window.FindElement('canvas').TKCanvas
+
+prev_response_time = None
+i=0
+prev_x, prev_y = canvas_left, canvas_bottom
+while True:
+ time.sleep(.2)
+
+ event, values = window.Read(timeout=0)
+ if event == 'Quit' or event is None:
+ break
+
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ try:
+ new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0])
+ except: continue
+
+ prev_response_time = g_response_time
+ canvas.create_line(prev_x, prev_y, new_x, new_y, width=1, fill='black')
+ prev_x, prev_y = new_x, new_y
+ if i >= x_right:
+ i = 0
+ prev_x = prev_y = last_x = last_y = 0
+ canvas.delete('all')
+ else: i += 1
+
+# tell thread we're done. wait for thread to exit
+g_exit = True
+thread.join()
+
+
+exit(69)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Pong.py b/DemoPrograms old/Demo_Pong.py
new file mode 100644
index 000000000..df4111e4e
--- /dev/null
+++ b/DemoPrograms old/Demo_Pong.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import random
+import time
+from sys import exit as exit
+
+
+"""
+ Pong code supplied by Daniel Young (Neonzz)
+ Modified. Original code: https://www.pygame.org/project/3649/5739
+"""
+
+class Ball:
+ def __init__(self, canvas, bat, bat2, color):
+ self.canvas = canvas
+ self.bat = bat
+ self.bat2 = bat2
+ self.playerScore = 0
+ self.player1Score = 0
+ self.drawP1 = None
+ self.drawP = None
+ self.id = self.canvas.create_oval(10, 10, 35, 35, fill=color)
+ self.canvas.move(self.id, 327, 220)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.x = random.choice([-2.5, 2.5])
+ self.y = -2.5
+
+ def checkwin(self):
+ winner = None
+ if self.playerScore >= 10:
+ winner = 'Player left wins'
+ if self.player1Score >= 10:
+ winner = 'Player Right'
+ return winner
+
+
+ def updatep(self, val):
+ self.canvas.delete(self.drawP)
+ self.drawP = self.canvas.create_text(170, 50, font=('freesansbold.ttf', 40), text=str(val), fill='white')
+
+ def updatep1(self, val):
+ self.canvas.delete(self.drawP1)
+ self.drawP1 = self.canvas.create_text(550, 50, font=('freesansbold.ttf', 40), text=str(val), fill='white')
+
+ def hit_bat(self, pos):
+ bat_pos = self.canvas.coords(self.bat.id)
+ if pos[2] >= bat_pos[0] and pos[0] <= bat_pos[2]:
+ if pos[3] >= bat_pos[1] and pos[3] <= bat_pos[3]:
+ return True
+ return False
+
+ def hit_bat2(self, pos):
+ bat_pos = self.canvas.coords(self.bat2.id)
+ if pos[2] >= bat_pos[0] and pos[0] <= bat_pos[2]:
+ if pos[3] >= bat_pos[1] and pos[3] <= bat_pos[3]:
+ return True
+ return False
+
+ def draw(self):
+ self.canvas.move(self.id, self.x, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 4
+ if pos[3] >= self.canvas_height:
+ self.y = -4
+ if pos[0] <= 0:
+ self.player1Score += 1
+ self.canvas.move(self.id, 327, 220)
+ self.x = 4
+ self.updatep1(self.player1Score)
+ if pos[2] >= self.canvas_width:
+ self.playerScore += 1
+ self.canvas.move(self.id, -327, -220)
+ self.x = -4
+ self.updatep(self.playerScore)
+ if self.hit_bat(pos):
+ self.x = 4
+ if self.hit_bat2(pos):
+ self.x = -4
+
+
+class pongbat():
+ def __init__(self, canvas, color):
+ self.canvas = canvas
+ self.id = self.canvas.create_rectangle(40, 200, 25, 310, fill=color)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.y = 0
+
+ def up(self, evt):
+ self.y = -5
+
+ def down(self, evt):
+ self.y = 5
+
+ def draw(self):
+ self.canvas.move(self.id, 0, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 0
+ if pos[3] >= 400:
+ self.y = 0
+
+
+class pongbat2():
+ def __init__(self, canvas, color):
+ self.canvas = canvas
+ self.id = self.canvas.create_rectangle(680, 200, 660, 310, fill=color)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.y = 0
+
+ def up(self, evt):
+ self.y = -5
+
+ def down(self, evt):
+ self.y = 5
+
+ def draw(self):
+ self.canvas.move(self.id, 0, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 0
+ if pos[3] >= 400:
+ self.y = 0
+
+
+def pong():
+ # ------------- Define GUI layout -------------
+ layout = [[sg.Canvas(size=(700, 400), background_color='black', key='canvas')],
+ [sg.T(''), sg.Button('Quit')]]
+ # ------------- Create window -------------
+ window = sg.Window('The Classic Game of Pong', return_keyboard_events=True).Layout(layout).Finalize()
+ # window.Finalize() # TODO Replace with call to window.Finalize once code released
+
+ # ------------- Get the tkinter Canvas we're drawing on -------------
+ canvas = window.FindElement('canvas').TKCanvas
+
+ # ------------- Create line down center, the bats and ball -------------
+ canvas.create_line(350, 0, 350, 400, fill='white')
+ bat1 = pongbat(canvas, 'white')
+ bat2 = pongbat2(canvas, 'white')
+ ball1 = Ball(canvas, bat1, bat2, 'green')
+
+ # ------------- Event Loop -------------
+ while True:
+ # ------------- Draw ball and bats -------------
+ ball1.draw()
+ bat1.draw()
+ bat2.draw()
+
+ # ------------- Read the form, get keypresses -------------
+ event, values = window.Read(timeout=0)
+ # ------------- If quit -------------
+ if event is None or event == 'Quit':
+ exit(69)
+ # ------------- Keypresses -------------
+ if event is not None:
+ if event.startswith('Up'):
+ bat2.up(2)
+ elif event.startswith('Down'):
+ bat2.down(2)
+ elif event == 'w':
+ bat1.up(1)
+ elif event == 's':
+ bat1.down(1)
+
+ if ball1.checkwin():
+ sg.Popup('Game Over', ball1.checkwin() + ' won!!')
+ break
+
+
+ # ------------- Bottom of loop, delay between animations -------------
+ # time.sleep(.01)
+ canvas.after(10)
+
+if __name__ == '__main__':
+ pong()
+
+
+
diff --git a/DemoPrograms old/Demo_Pong_Multiple_Platforms.py b/DemoPrograms old/Demo_Pong_Multiple_Platforms.py
new file mode 100644
index 000000000..2e88127c1
--- /dev/null
+++ b/DemoPrograms old/Demo_Pong_Multiple_Platforms.py
@@ -0,0 +1,172 @@
+# !/usr/bin/env python
+# Based on work by - Siddharth Natamai
+# At the moment, this source file runs on TWO of the 4 PySimpleGUI ports with a third one coming soon (Qt).
+# import PySimpleGUIQt as sg # not quite working on Qt yet... needs Graph.Relocate fixed first
+# import PySimpleGUIWeb as sg
+import PySimpleGUI as sg
+import random
+
+GAMEPLAY_SIZE = (700, 400)
+BAT_SIZE = (20, 110)
+STARTING_BALL_POSITION = (327, 200)
+player_1_Starting_Score = 0
+player_2_Starting_Score = 0
+BALL_RADIUS = 12
+# BACKGROUND_COLOR = 'lightblue' # if running on PySimpleGUIWeb
+BACKGROUND_COLOR = 'black'
+# BALL_COLOR = 'black' # if running on PySimpleGUIWeb
+BALL_COLOR = 'green1'
+num_rounds = 0
+while num_rounds == 0:
+ try:
+ num_rounds = int(sg.PopupGetText('How many rounds would you like to play?'))
+ except Exception as e:
+ num_rounds = 0
+
+
+class Ball:
+ def __init__(self, graph, bat_1, bat_2, colour):
+ self.graph = graph # type: sg.Graph
+ self.bat_1 = bat_1
+ self.bat_2 = bat_2
+ self.player_1_Score = player_1_Starting_Score
+ self.player_2_Score = player_2_Starting_Score
+ self.draw_P1 = None
+ self.draw_P2 = None
+ self.id = self.graph.DrawCircle(STARTING_BALL_POSITION, BALL_RADIUS, line_color=colour, fill_color=colour)
+ self.curx, self.cury = STARTING_BALL_POSITION
+ # self.graph.RelocateFigure(self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
+ self.x = random.choice([-2.5, 2.5])
+ self.y = -2.5
+
+ def win_loss_check(self):
+ winner = None
+ if self.player_1_Score >= num_rounds:
+ winner = 'Player Right Wins'
+ if self.player_2_Score >= num_rounds:
+ winner = 'Player Left Wins'
+ return winner
+
+ def update_player1_score(self, val):
+ self.graph.DeleteFigure(self.draw_P1)
+ self.draw_P1 = self.graph.DrawText(str(val), (170, 50), font=('Courier 60'), color='white')
+
+ def update_player2_score(self, val):
+ self.graph.DeleteFigure(self.draw_P2)
+ self.draw_P2 = self.graph.DrawText(str(val), (550, 50), font=('courier 40'), color='white')
+
+ def hit_bat(self, pos):
+ bat_pos = (self.bat_1.curx, self.bat_1.cury)
+ if pos[0] >= bat_pos[0] and pos[0] <= bat_pos[0]+BAT_SIZE[0]:
+ if bat_pos[1] <= pos[1] <= bat_pos[1]+BAT_SIZE[1]:
+ return True
+ return False
+
+ def hit_bat2(self, pos):
+ bat_pos = (self.bat_2.curx, self.bat_2.cury)
+ if pos[0] >= bat_pos[0] and pos[0] <= bat_pos[0]+BAT_SIZE[0]:
+ if bat_pos[1] <= pos[1] <= bat_pos[1]+BAT_SIZE[1]:
+ return True
+ return False
+
+
+ def draw(self):
+ self.curx += self.x
+ self.cury += self.y
+ self.graph.RelocateFigure(self.id, self.curx, self.cury)
+ if self.cury <= 0: # see if hit top or bottom of play area. If so, reverse y direction
+ self.y = 4
+ self.cury = 0
+ if self.cury >= GAMEPLAY_SIZE[1]-BALL_RADIUS/2:
+ self.y = -4
+ self.cury = GAMEPLAY_SIZE[1]-BALL_RADIUS/2
+ if self.curx <= 0: # see if beyond player
+ self.player_1_Score += 1
+ self.graph.RelocateFigure(self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
+ self.x = 4
+ self.update_player2_score(self.player_1_Score)
+ self.curx, self.cury = STARTING_BALL_POSITION
+ if self.curx >= GAMEPLAY_SIZE[0]:
+ self.player_2_Score += 1
+ self.graph.RelocateFigure(self.id, STARTING_BALL_POSITION[0], STARTING_BALL_POSITION[1])
+ self.x = -4
+ self.update_player1_score(self.player_2_Score)
+ self.curx, self.cury = STARTING_BALL_POSITION
+ if self.hit_bat((self.curx, self.cury)):
+ self.x = 4
+ if self.hit_bat2((self.curx, self.cury)):
+ self.x = -4
+
+
+class PongBat():
+ def __init__(self, graph:sg.Graph, colour, x, width=BAT_SIZE[0], height=BAT_SIZE[1]):
+ self.graph = graph
+ self.id = graph.DrawRectangle((x - width / 2, 200), (x + width / 2, 200 + height), fill_color=colour)
+ self.y = 0
+ self.x = x
+ self.curx = x
+ self.cury = height/2
+
+ def up(self, amount):
+ self.y = -amount
+
+ def down(self, amount):
+ self.y = amount
+
+ @property
+ def curr_pos(self):
+ pos = self.cury
+ return pos
+
+ def draw(self):
+ self.graph.RelocateFigure(self.id, self.curx, self.cury)
+ if self.cury + self.y + BAT_SIZE[1] <= GAMEPLAY_SIZE[1] and self.cury + self.y + BAT_SIZE[1] >= 0:
+ self.cury += self.y
+ if self.cury <= 0:
+ self.cury = 0
+ self.y = 0
+ if self.cury >= GAMEPLAY_SIZE[1]:
+ self.cury = GAMEPLAY_SIZE[1]
+ self.y = 0
+
+
+def pong():
+ layout = [[sg.Graph(GAMEPLAY_SIZE, (0,GAMEPLAY_SIZE[1]), (GAMEPLAY_SIZE[0],0), background_color=BACKGROUND_COLOR, key='_GRAPH_')],
+ [sg.T(''), sg.Button('Exit'), sg.T('Speed'), sg.Slider((0,20),default_value=10, orientation='h', enable_events=True, key='_SPEED_')]]
+
+ window = sg.Window('Pong', layout, return_keyboard_events=True).Finalize()
+
+ graph_elem = window.FindElement('_GRAPH_') # type: sg.Graph
+
+ bat_1 = PongBat(graph_elem, 'red', 30)
+ bat_2 = PongBat(graph_elem, 'blue', 670)
+
+ ball_1 = Ball(graph_elem, bat_1, bat_2, 'green1')
+ sleep_time = 10
+
+ while True:
+ ball_1.draw()
+ bat_1.draw()
+ bat_2.draw()
+
+ event, values = window.Read(timeout=sleep_time) # type: str, str
+ if event is None or event == 'Exit':
+ break
+ elif event.startswith('Up') or event.endswith('Up'):
+ bat_2.up(5)
+ elif event.startswith('Down') or event.endswith('Down'):
+ bat_2.down(5)
+ elif event == 'w':
+ bat_1.up(5)
+ elif event == 's':
+ bat_1.down(5)
+ elif event == '_SPEED_':
+ sleep_time = int(values['_SPEED_'])
+
+ if ball_1.win_loss_check():
+ sg.Popup('Game Over', ball_1.win_loss_check() + ' won!!')
+ break
+ window.Close()
+
+if __name__ == '__main__':
+ pong()
diff --git a/DemoPrograms old/Demo_Popup_Custom.py b/DemoPrograms old/Demo_Popup_Custom.py
new file mode 100644
index 000000000..718adb8f7
--- /dev/null
+++ b/DemoPrograms old/Demo_Popup_Custom.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+'''
+ Use this code as a starting point for creating your own Popup functions.
+ Rather than creating a long list of Popup high-level API calls, PySimpleGUI provides
+ you with the tools to easily create your own. If you need more than what the standard PopupGetText and
+ other calls provide, then it's time for you to graduate into making your own windows. Or, maybe you need
+ another window that pops-up over your primary window. Whatever the need, don't hesitate to dive in
+ and create your own Popup call.
+
+ This example is for a DropDown / Combobox Popup. You provide it with a title, a message and the list
+ of values to choose from. It mimics the return values of existing Popup calls (None if nothing was input)
+'''
+
+
+def PopupDropDown(title, text, values):
+ window = sg.Window(title).Layout([[sg.Text(text)],
+ [sg.DropDown(values, key='_DROP_')],
+ [sg.OK(), sg.Cancel()]])
+ event, values = window.Read()
+ return None if event != 'OK' else values['_DROP_']
+
+
+# ----------------------- Calling your PopupDropDown function -----------------------
+
+values = ['choice {}'.format(x) for x in range(30)]
+
+print(PopupDropDown('My Title', 'Please make a selection', values))
diff --git a/DemoPrograms old/Demo_Popups.py b/DemoPrograms old/Demo_Popups.py
new file mode 100644
index 000000000..a2435a825
--- /dev/null
+++ b/DemoPrograms old/Demo_Popups.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+from PySimpleGUI import Print as print
+
+
+print('test')
+sg.PopupGetFile('Get file', save_as=True,file_types=(("ALL Files", "*.jpg"),))
+
+# Here, have some windows on me....
+[sg.PopupNoWait('No-wait Popup', location=(500+100*x,500)) for x in range(10)]
+
+answer = sg.PopupYesNo('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?')
+
+if answer == 'No':
+ sg.PopupCancel('OK, we will destroy those windows as soon as you close this window')
+ sys.exit()
+
+sg.PopupNonBlocking('Your answer was',answer, location=(1000,600))
+
+text = sg.PopupGetText('This is a call to PopopGetText', location=(1000,200))
+sg.PopupGetFile('Get file')
+sg.PopupGetFolder('Get folder')
+
+
+sg.Popup('Simple popup')
+
+sg.PopupNoTitlebar('No titlebar')
+sg.PopupNoBorder('No border')
+sg.PopupNoFrame('No frame')
+sg.PopupCancel('Cancel')
+sg.PopupOKCancel('OK Cancel')
+sg.PopupAutoClose('Autoclose')
diff --git a/DemoPrograms old/Demo_Progress_Meters.py b/DemoPrograms old/Demo_Progress_Meters.py
new file mode 100644
index 000000000..0ffc4c8e9
--- /dev/null
+++ b/DemoPrograms old/Demo_Progress_Meters.py
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+from time import sleep
+
+
+"""
+ Demonstration of simple and multiple OneLineProgressMeter's as well as the Progress Meter Element
+
+ There are 4 demos
+ 1. Manually updated progress bar
+ 2. Custom progress bar built into your window, updated in a loop
+ 3. OneLineProgressMeters, nested meters showing how 2 can be run at the same time.
+ 4. An "iterable" style progress meter - a wrapper for OneLineProgressMeters
+
+ If the software determined that a meter should be cancelled early,
+ calling OneLineProgresMeterCancel(key) will cancel the meter with the matching key
+"""
+
+
+
+"""
+ The simple case is that you want to add a single meter to your code. The one-line solution.
+ This demo function shows 3 different OneLineProgressMeter tests
+ 1. A horizontal with red and white bar colors
+ 2. A vertical bar with default colors
+ 3. A test showing 2 running at the same time
+"""
+
+def demo_one_line_progress_meter():
+ # Display a progress meter. Allow user to break out of loop using cancel button
+ for i in range(10000):
+ if not sg.OneLineProgressMeter('My 1-line progress meter', i+1, 10000, 'meter key','MY MESSAGE1', 'MY MESSAGE 2', orientation='h', bar_color=('white', 'red')):
+ print('Hit the break')
+ break
+ for i in range(10000):
+ if not sg.OneLineProgressMeter('My 1-line progress meter', i+1, 10000, 'meter key', 'MY MESSAGE1', 'MY MESSAGE 2',orientation='v' ):
+ print('Hit the break')
+ break
+
+ layout = [
+ [sg.T('One-Line Progress Meter Demo', font=('Any 18'))],
+ [sg.T('Outer Loop Count', size=(15,1), justification='r'), sg.In(default_text='100', size=(5,1), key='CountOuter', do_not_clear=True),
+ sg.T('Delay'), sg.In(default_text='10', key='TimeOuter', size=(5,1), do_not_clear=True), sg.T('ms')],
+ [sg.T('Inner Loop Count', size=(15,1), justification='r'), sg.In(default_text='100', size=(5,1), key='CountInner', do_not_clear=True) ,
+ sg.T('Delay'), sg.In(default_text='10', key='TimeInner', size=(5,1), do_not_clear=True), sg.T('ms')],
+ [sg.Button('Show', pad=((0,0), 3), bind_return_key=True), sg.T('me the meters!')]
+ ]
+
+ window = sg.Window('One-Line Progress Meter Demo').Layout(layout)
+
+ while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ if event == 'Show':
+ max_outer = int(values['CountOuter'])
+ max_inner = int(values['CountInner'])
+ delay_inner = int(values['TimeInner'])
+ delay_outer = int(values['TimeOuter'])
+ for i in range(max_outer):
+ if not sg.OneLineProgressMeter('Outer Loop', i+1, max_outer, 'outer'):
+ break
+ sleep(delay_outer/1000)
+ for j in range(max_inner):
+ if not sg.OneLineProgressMeter('Inner Loop', j+1, max_inner, 'inner'):
+ break
+ sleep(delay_inner/1000)
+
+
+'''
+ Manually Updated Test
+ Here is an example for when you want to "sprinkle" progress bar updates in multiple
+ places within your source code and you're not running an event loop.
+ Note that UpdateBar is special compared to other Update methods. It also refreshes
+ the containing window and checks for window closure events
+ The sleep calls are here only for demonstration purposes. You should NOT be adding
+ these kinds of sleeps to a GUI based program normally.
+'''
+
+def manually_updated_meter_test():
+ # layout the form
+ layout = [[sg.Text('This meter is manually updated 4 times')],
+ [sg.ProgressBar(max_value=10, orientation='h', size=(20,20), key='progress')]]
+
+ # create the form`
+ window = sg.Window('Custom Progress Meter', layout).Finalize() # must finalize since not running an event loop
+
+ progress_bar = window.FindElement('progress') # Get the element to make updating easier
+
+ # -------------------- Your Program Code --------------------
+ # Spot #1 to indicate progress
+ progress_bar.UpdateBar(1) # show 10% complete
+ sleep(2)
+
+ # more of your code.... perhaps pages and pages of code.
+ # Spot #2 to indicate progress
+ progress_bar.UpdateBar(2) # show 20% complete
+ sleep(2)
+
+ # more of your code.... perhaps pages and pages of code.
+ # Spot #3 to indicate progress
+ progress_bar.UpdateBar(6) # show 60% complete
+ sleep(2)
+
+ # more of your code.... perhaps pages and pages of code.
+ # Spot #4 to indicate progress
+ progress_bar.UpdateBar(9) # show 90% complete
+ sleep(2)
+ window.Close()
+
+
+'''
+ This function shows how to create a custom window with a custom progress bar and then
+ how to update the bar to indicate progress is being made
+'''
+
+def custom_meter_example():
+ # layout the form
+ layout = [[sg.Text('A typical custom progress meter')],
+ [sg.ProgressBar(1, orientation='h', size=(20,20), key='progress')],
+ [sg.Cancel()]]
+
+ # create the form`
+ window = sg.Window('Custom Progress Meter').Layout(layout)
+ progress_bar = window.FindElement('progress')
+ # loop that would normally do something useful
+ for i in range(10000):
+ # check to see if the cancel button was clicked and exit loop if clicked
+ event, values = window.Read(timeout=0)
+ if event == 'Cancel' or event == None:
+ break
+ # update bar with loop value +1 so that bar eventually reaches the maximum
+ progress_bar.UpdateBar(i+1, 10000)
+ # done with loop... need to destroy the window as it's still open
+ window.Close()
+
+
+'''
+ A Wrapper for OneLineProgressMeter that combines your iterable with a progress meter into a single interface. Two functions are provided
+ progess_bar - The basic wrapper
+ progress_bar_range - A "convienence function" if you wanted to specify like a range
+'''
+
+
+def progress_bar(key, iterable, *args, title='', **kwargs):
+ """
+ Takes your iterable and adds a progress meter onto it
+ :param key: Progress Meter key
+ :param iterable: your iterable
+ :param args: To be shown in one line progress meter
+ :param title: Title shown in meter window
+ :param kwargs: Other arguments to pass to OneLineProgressMeter
+ :return:
+ """
+ sg.OneLineProgressMeter(title, 0, len(iterable), key, *args, **kwargs)
+ for i, val in enumerate(iterable):
+ yield val
+ if not sg.OneLineProgressMeter(title, i+1, len(iterable), key, *args, **kwargs):
+ break
+
+
+def progress_bar_range(key, start, stop=None, step=1, *args, **kwargs):
+ """
+ Acts like the range() function but with a progress meter built-into it
+ :param key: progess meter's key
+ :param start: low end of the range
+ :param stop: Uppder end of range
+ :param step:
+ :param args:
+ :param kwargs:
+ :return:
+ """
+ return progress_bar(key, range(start, stop, step), *args, **kwargs)
+
+
+# -------------------- Demo Usage --------------------
+def demo_iterable_progress_bar():
+ my_list = list(range(1000)) # start with a list of 100 integers as the user's list
+
+ # first form takes an iterable and a key and will return a value from your iterable
+ # and bump the progress meter at the same time
+ for value in progress_bar('bar1', my_list, ):
+ # do something useful with value, a value from your list.
+ print(value)
+
+ # Since the progress_bar is an iterator, you can use it within a list comprehension
+ my_list = [x for x in progress_bar('bar1', my_list)]
+
+
+
+demo_iterable_progress_bar()
+manually_updated_meter_test()
+custom_meter_example()
+demo_one_line_progress_meter()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_PyGame_Integration.py b/DemoPrograms old/Demo_PyGame_Integration.py
new file mode 100644
index 000000000..dae260ffa
--- /dev/null
+++ b/DemoPrograms old/Demo_PyGame_Integration.py
@@ -0,0 +1,39 @@
+import pygame
+import PySimpleGUI as sg
+import os
+
+"""
+ Demo of integrating PyGame with PySimpleGUI, the tkinter version
+ A similar technique may be possible with WxPython
+ Only works on windows from what I've read
+"""
+# --------------------- PySimpleGUI window layout and creation --------------------
+layout = [[sg.T('Test of PySimpleGUI with PyGame')],
+ [sg.Graph((500,500), (0,0), (500,500), background_color='lightblue', key='_GRAPH_' )],
+ [sg.B('Draw'), sg.Exit()]]
+
+window = sg.Window('PySimpleGUI + PyGame', layout).Finalize()
+graph = window.Element('_GRAPH_')
+
+# -------------- Magic code to integrate PyGame with tkinter -------
+embed = graph.TKCanvas
+os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
+os.environ['SDL_VIDEODRIVER'] = 'windib'
+
+# ----------------------------- PyGame Code -----------------------------
+
+screen = pygame.display.set_mode((500,500))
+screen.fill(pygame.Color(255,255,255))
+
+pygame.display.init()
+pygame.display.update()
+
+while True:
+ event, values = window.Read(timeout=10)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Draw':
+ pygame.draw.circle(screen, (0, 0, 0), (250, 250), 125)
+ pygame.display.update()
+
+window.Close()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_PyGame_Snake_Game.py b/DemoPrograms old/Demo_PyGame_Snake_Game.py
new file mode 100644
index 000000000..6d1485e74
--- /dev/null
+++ b/DemoPrograms old/Demo_PyGame_Snake_Game.py
@@ -0,0 +1,138 @@
+import pygame
+import PySimpleGUI as sg
+import os
+
+"""
+ Demo - Simple Snake Game using PyGame and PySimpleGUI
+ This demo may not be fully functional in terms of getting the coordinate
+ systems right or other problems due to a lack of understanding of PyGame
+ The purpose of the demo is to show one way of adding a PyGame window into your PySimpleGUI window
+ Note, you must click on the game area in order for PyGame to get keyboard strokes, etc.
+ Tried using set_focus to switch to the PyGame canvas but still needed to click on game area
+"""
+
+# --- Globals ---
+# Colors
+BLACK = (0, 0, 0)
+WHITE = (255, 255, 255)
+
+# Set the width and height of each snake segment
+segment_width = 15
+segment_height = 15
+# Margin between each segment
+segment_margin = 3
+
+# Set initial speed
+x_change = segment_width + segment_margin
+y_change = 0
+
+
+class Segment(pygame.sprite.Sprite):
+ """ Class to represent one segment of the snake. """
+ # -- Methods
+ # Constructor function
+ def __init__(self, x, y):
+ # Call the parent's constructor
+ super().__init__()
+
+ # Set height, width
+ self.image = pygame.Surface([segment_width, segment_height])
+ self.image.fill(WHITE)
+
+ # Make our top-left corner the passed-in location.
+ self.rect = self.image.get_rect()
+ self.rect.x = x
+ self.rect.y = y
+
+# --------------------------- GUI Setup & Create Window -------------------------------
+
+layout = [[sg.T('Snake Game - PySimpleGUI + PyGame')],
+ [sg.Graph((800,600), (0,0), (800,600), background_color='lightblue', key='_GRAPH_')],
+ [sg.Exit()]]
+
+window = sg.Window('Snake Game using PySimpleGUI and PyGame', layout).Finalize()
+
+# ------------------------ Do the magic that integrates PyGame and Graph Element ------------------
+graph = window.Element('_GRAPH_') # type: sg.Graph
+embed = graph.TKCanvas
+os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
+os.environ['SDL_VIDEODRIVER'] = 'windib'
+
+# ----------------------------- PyGame Code -----------------------------
+# Call this function so the Pygame library can initialize itself
+# pygame.init()
+screen = pygame.display.set_mode((800,600))
+screen.fill(pygame.Color(255,255,255))
+
+pygame.display.init()
+pygame.display.update()
+
+# Set the title of the window
+pygame.display.set_caption('Snake Example')
+
+allspriteslist = pygame.sprite.Group()
+
+# Create an initial snake
+snake_segments = []
+for i in range(15):
+ x = 250 - (segment_width + segment_margin) * i
+ y = 30
+ segment = Segment(x, y)
+ snake_segments.append(segment)
+ allspriteslist.add(segment)
+
+clock = pygame.time.Clock()
+
+while True:
+ event, values = window.Read(timeout=10)
+ if event in (None, 'Exit'):
+ break
+ pygame.display.update()
+
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ break
+ # Set the speed based on the key pressed
+ # We want the speed to be enough that we move a full
+ # segment, plus the margin.
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_LEFT:
+ x_change = (segment_width + segment_margin) * -1
+ y_change = 0
+ if event.key == pygame.K_RIGHT:
+ x_change = (segment_width + segment_margin)
+ y_change = 0
+ if event.key == pygame.K_UP:
+ x_change = 0
+ y_change = (segment_height + segment_margin) * -1
+ if event.key == pygame.K_DOWN:
+ x_change = 0
+ y_change = (segment_height + segment_margin)
+
+ # Get rid of last segment of the snake
+ # .pop() command removes last item in list
+ old_segment = snake_segments.pop()
+ allspriteslist.remove(old_segment)
+
+ # Figure out where new segment will be
+ x = snake_segments[0].rect.x + x_change
+ y = snake_segments[0].rect.y + y_change
+ segment = Segment(x, y)
+
+ # Insert new segment into the list
+ snake_segments.insert(0, segment)
+ allspriteslist.add(segment)
+
+ # -- Draw everything
+ # Clear screen
+ screen.fill(BLACK)
+
+ allspriteslist.draw(screen)
+
+ # Flip screen
+ pygame.display.flip()
+
+ # Pause
+ clock.tick(5)
+
+window.Close()
diff --git a/DemoPrograms old/Demo_Pyplot_Bar_Chart.py b/DemoPrograms old/Demo_Pyplot_Bar_Chart.py
new file mode 100644
index 000000000..34265b3de
--- /dev/null
+++ b/DemoPrograms old/Demo_Pyplot_Bar_Chart.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+import sys
+
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import matplotlib
+
+matplotlib.use('TkAgg')
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import tkinter as Tk
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Paste your Pyplot code into the section marked below.
+
+Do all of your plotting as you normally would, but do NOT call plt.show().
+Stop just short of calling plt.show() and let the GUI do the rest.
+
+The remainder of the program will convert your plot and display it in the GUI.
+If you want to change the GUI, make changes to the GUI portion marked below.
+
+"""
+
+# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+
+import numpy as np
+import matplotlib.pyplot as plt
+
+values_to_plot = (20, 35, 30, 35, 27)
+ind = np.arange(len(values_to_plot))
+width = 0.4
+
+p1 = plt.bar(ind, values_to_plot, width)
+
+plt.ylabel('Y-Axis Values')
+plt.title('Plot Title')
+plt.xticks(ind, ('Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'))
+plt.yticks(np.arange(0, 81, 10))
+plt.legend((p1[0],), ('Data Group 1',))
+
+
+# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
+
+# ------------------------------- Beginning of Matplotlib helper code -----------------------
+
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ """ Draw a matplotlib figure onto a Tk canvas
+
+ loc: location of top-left corner of figure on canvas in pixels.
+
+ Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
+ """
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = Tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w / 2, loc[1] + figure_h / 2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+# ------------------------------- Beginning of GUI CODE -------------------------------
+
+fig = plt.gcf() # if using Pyplot then get the figure from the plot
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+# define the window layout
+layout = [[sg.Text('Plot test', font='Any 18')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', force_toplevel=True).Layout(
+ layout).Finalize()
+
+# add the plot to the window
+fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
+
+# show it all again and get buttons
+event, values = window.Read()
diff --git a/DemoPrograms old/Demo_Pyploy_Bar_Chart2.py b/DemoPrograms old/Demo_Pyploy_Bar_Chart2.py
new file mode 100644
index 000000000..fa02b35fa
--- /dev/null
+++ b/DemoPrograms old/Demo_Pyploy_Bar_Chart2.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import matplotlib
+matplotlib.use('TkAgg')
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import tkinter as Tk
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Paste your Pyplot code into the section marked below.
+
+Do all of your plotting as you normally would, but do NOT call plt.show().
+Stop just short of calling plt.show() and let the GUI do the rest.
+
+The remainder of the program will convert your plot and display it in the GUI.
+If you want to change the GUI, make changes to the GUI portion marked below.
+
+"""
+
+#------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+import matplotlib.pyplot as plt
+import numpy as np
+label = ['Adventure', 'Action', 'Drama', 'Comedy', 'Thriller/Suspense', 'Horror', 'Romantic Comedy', 'Musical',
+ 'Documentary', 'Black Comedy', 'Western', 'Concert/Performance', 'Multiple Genres', 'Reality']
+no_movies = [941, 854, 4595, 2125, 942, 509, 548, 149, 1952, 161, 64, 61, 35, 5]
+
+index = np.arange(len(label))
+plt.bar(index, no_movies)
+plt.xlabel('Genre', fontsize=5)
+plt.ylabel('No of Movies', fontsize=5)
+plt.xticks(index, label, fontsize=5, rotation=30)
+plt.title('Market Share for Each Genre 1995-2017')
+
+#------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
+
+#------------------------------- Beginning of Matplotlib helper code -----------------------
+
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ """ Draw a matplotlib figure onto a Tk canvas
+
+ loc: location of top-left corner of figure on canvas in pixels.
+
+ Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
+ """
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = Tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+#------------------------------- Beginning of GUI CODE -------------------------------
+
+fig = plt.gcf() # if using Pyplot then get the figure from the plot
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+# define the window layout
+layout = [[sg.Text('Plot test', font='Any 18')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', force_toplevel=True).Layout(layout).Finalize()
+
+# add the plot to the window
+fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
+
+# show it all again and get buttons
+event, values = window.Read()
diff --git a/DemoPrograms old/Demo_Script_Launcher.py b/DemoPrograms old/Demo_Script_Launcher.py
new file mode 100644
index 000000000..7dff6a4fd
--- /dev/null
+++ b/DemoPrograms old/Demo_Script_Launcher.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import glob
+import ntpath
+import subprocess
+
+LOCATION_OF_YOUR_SCRIPTS = ''
+
+# Execute the command. Will not see the output from the command until it completes.
+def execute_command_blocking(command, *args):
+ expanded_args = []
+ for a in args:
+ expanded_args.append(a)
+ # expanded_args += a
+ try:
+ sp = subprocess.Popen([command,expanded_args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out, err = sp.communicate()
+ if out:
+ print(out.decode("utf-8"))
+ if err:
+ print(err.decode("utf-8"))
+ except:
+ out = ''
+ return out
+
+# Executes command and immediately returns. Will not see anything the script outputs
+def execute_command_nonblocking(command, *args):
+ expanded_args = []
+ for a in args:
+ expanded_args += a
+ try:
+ sp = subprocess.Popen([command,expanded_args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ except: pass
+
+def Launcher2():
+ sg.ChangeLookAndFeel('GreenTan')
+ window = sg.Window('Script launcher')
+
+ filelist = glob.glob(LOCATION_OF_YOUR_SCRIPTS+'*.py')
+ namesonly = []
+ for file in filelist:
+ namesonly.append(ntpath.basename(file))
+
+ layout = [
+ [sg.Listbox(values=namesonly, size=(30, 19), select_mode=sg.SELECT_MODE_EXTENDED, key='demolist'), sg.Output(size=(88, 20), font='Courier 10')],
+ [sg.Checkbox('Wait for program to complete', default=False, key='wait')],
+ [sg.Button('Run'), sg.Button('Shortcut 1'), sg.Button('Fav Program'), sg.Button('EXIT')],
+ ]
+
+ window.Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ event, values = window.Read()
+ if event in ('EXIT', None):
+ break # exit button clicked
+ if event in ('Shortcut 1', 'Fav Program'):
+ print('Quickly launch your favorite programs using these shortcuts')
+ print('Or copy files to your github folder. Or anything else you type on the command line')
+ # copyfile(source, dest)
+ elif event == 'Run':
+ for index, file in enumerate(values['demolist']):
+ print('Launching %s'%file)
+ window.Refresh() # make the print appear immediately
+ if values['wait']:
+ execute_command_blocking(LOCATION_OF_YOUR_SCRIPTS + file)
+ else:
+ execute_command_nonblocking(LOCATION_OF_YOUR_SCRIPTS + file)
+
+
+if __name__ == '__main__':
+ Launcher2()
+
diff --git a/DemoPrograms old/Demo_Script_Launcher_Realtime_Output.py b/DemoPrograms old/Demo_Script_Launcher_Realtime_Output.py
new file mode 100644
index 000000000..12b54c6b7
--- /dev/null
+++ b/DemoPrograms old/Demo_Script_Launcher_Realtime_Output.py
@@ -0,0 +1,48 @@
+import subprocess
+import sys
+import PySimpleGUI as sg
+
+"""
+ Demo Program - Realtime output of a shell command in the window
+ Shows how you can run a long-running subprocess and have the output
+ be displayed in realtime in the window.
+"""
+
+def main():
+ layout = [ [sg.Text('Enter the command you wish to run')],
+ [sg.Input(key='_IN_')],
+ [sg.Output(size=(60,15))],
+ [sg.Button('Run'), sg.Button('Exit')] ]
+
+ window = sg.Window('Realtime Shell Command Output', layout)
+
+ while True: # Event Loop
+ event, values = window.Read()
+ # print(event, values)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Run':
+ runCommand(cmd=values['_IN_'], window=window)
+ window.Close()
+
+
+def runCommand(cmd, timeout=None, window=None):
+ """ run shell command
+ @param cmd: command to execute
+ @param timeout: timeout for command execution
+ @param window: the PySimpleGUI window that the output is going to (needed to do refresh on)
+ @return: (return code from command, command output)
+ """
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ output = ''
+ for line in p.stdout:
+ line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip()
+ output += line
+ print(line)
+ window.Refresh() if window else None # yes, a 1-line if, so shoot me
+
+ retval = p.wait(timeout)
+ return (retval, output)
+
+
+main()
diff --git a/DemoPrograms old/Demo_Script_Parameters.py b/DemoPrograms old/Demo_Script_Parameters.py
new file mode 100644
index 000000000..82fdda642
--- /dev/null
+++ b/DemoPrograms old/Demo_Script_Parameters.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+
+'''
+Quickly add a GUI to your script!
+
+This simple script shows a 1-line-GUI addition to a typical Python command line script.
+
+Previously this script accepted 1 parameter on the command line. When executed, that
+parameter is read into the variable fname.
+
+The 1-line-GUI shows a form that allows the user to browse to find the filename. The GUI
+stores the result in the variable fname, just like the command line parsing did.
+'''
+
+if len(sys.argv) == 1:
+ event, (fname,) = sg.Window('My Script').Layout([[sg.T('Document to open')],
+ [sg.In(), sg.FileBrowse()],
+ [sg.CloseButton('Open'), sg.CloseButton('Cancel')]]).Read()
+else:
+ fname = sys.argv[1]
+
+if not fname:
+ sg.Popup("Cancel", "No filename supplied")
+ raise SystemExit("Cancelling: no filename supplied")
diff --git a/DemoPrograms old/Demo_Sort_Visualizer.py b/DemoPrograms old/Demo_Sort_Visualizer.py
new file mode 100644
index 000000000..1f07a1b97
--- /dev/null
+++ b/DemoPrograms old/Demo_Sort_Visualizer.py
@@ -0,0 +1,59 @@
+import PySimpleGUI as sg
+import random
+# ------- Sort visualizer. Displays bar chart representing list items -------
+BAR_SPACING, BAR_WIDTH, EDGE_OFFSET = 11, 10, 3
+DATA_SIZE = GRAPH_SIZE = (700,500) # width, height of the graph portion
+
+def bubble_sort(arr):
+ def swap(i, j):
+ arr[i], arr[j] = arr[j], arr[i]
+ n = len(arr)
+ swapped = True
+ x = -1
+ while swapped:
+ swapped = False
+ x = x + 1
+ for i in range(1, n - x):
+ if arr[i - 1] > arr[i]:
+ swap(i - 1, i)
+ swapped = True
+ yield arr
+
+def draw_bars(graph, items): # draws all the bars for all values across screen
+ # type: (sg.Graph, List)->None
+ for i, item in enumerate(items):
+ graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, item),
+ bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='#76506d')
+
+def main():
+ sg.change_look_and_feel('LightGreen')
+ # Make list to sort
+ num_bars = DATA_SIZE[0]//(BAR_WIDTH+1)
+ list_to_sort = [DATA_SIZE[1]//num_bars*i for i in range(1,num_bars)]
+ random.shuffle(list_to_sort)
+
+ # define window layout
+ graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
+ layout = [[graph],
+ [sg.T('Speed Faster'), sg.Slider((0,20), orientation='h', default_value=10, key='-SPEED-'), sg.T('Slower')]]
+
+ window = sg.Window('Sort Demonstration', layout, finalize=True)
+ draw_bars(graph, list_to_sort) # draw the initial window's bars
+
+ sg.popup('Click OK to begin Bubblesort') # Wait for user to start it up
+ bsort = bubble_sort(list_to_sort) # get an iterator for the sort
+ timeout=10 # start with 10ms delays between draws
+ while True: # ----- The event loop -----
+ event, values = window.read(timeout=timeout)
+ if event is None:
+ break
+ try:
+ partially_sorted_list = bsort.__next__()
+ except:
+ sg.popup('Sorting done!')
+ break
+ graph.Erase()
+ draw_bars(graph, partially_sorted_list)
+ timeout = int(values['-SPEED-'])
+ window.close()
+main()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Spinner_Compound_Element.py b/DemoPrograms old/Demo_Spinner_Compound_Element.py
new file mode 100644
index 000000000..dc9bb246d
--- /dev/null
+++ b/DemoPrograms old/Demo_Spinner_Compound_Element.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+"""
+ Demo of how to combine elements into your own custom element
+"""
+
+sg.SetOptions(element_padding=(0,0))
+# sg.ChangeLookAndFeel('Dark')
+# --- Define our "Big-Button-Spinner" compound element. Has 2 buttons and an input field --- #
+NewSpinner = [sg.Button('-', size=(2,1), font='Any 12'),
+ sg.In('0', size=(2,1), font='Any 14', justification='r', key='spin'),
+ sg.Button('+', size=(2,1), font='Any 12')]
+# --- Define Window --- #
+layout = [
+ [sg.Text('Spinner simulation')],
+ NewSpinner,
+ [sg.T('')],
+ [sg.Ok()]
+ ]
+
+window = sg.Window('Spinner simulation').Layout(layout)
+
+# --- Event Loop --- #
+counter = 0
+while True:
+ event, values = window.Read()
+
+ if event == 'Ok' or event is None: # be nice to your user, always have an exit from your form
+ break
+
+ # --- do spinner stuff --- #
+ counter += 1 if event == '+' else -1 if event == '-' else 0
+ window.FindElement('spin').Update(counter)
diff --git a/DemoPrograms old/Demo_Stdout.py b/DemoPrograms old/Demo_Stdout.py
new file mode 100644
index 000000000..1ad900907
--- /dev/null
+++ b/DemoPrograms old/Demo_Stdout.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+"""
+ Demo program that reroutes stdout and stderr.
+ Type something in the input box and click Print
+ Whatever you typed is "printed" using a standard print statement
+ Use the Output Element in your window layout to reroute stdout
+ You will see the output of the print in the Output Element in the center of the window
+
+"""
+
+
+layout = [
+ [sg.Text('Type something in input field and click print')],
+ [sg.In()],
+ [sg.Output()],
+ [sg.Button('Print')]
+ ]
+
+window = sg.Window('Reroute stdout').Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None:
+ break
+ print('You typed: ', values[0])
diff --git a/DemoPrograms old/Demo_Super_Simple_Form.py b/DemoPrograms old/Demo_Super_Simple_Form.py
new file mode 100644
index 000000000..48bf949af
--- /dev/null
+++ b/DemoPrograms old/Demo_Super_Simple_Form.py
@@ -0,0 +1,11 @@
+import PySimpleGUI as sg
+
+layout = [[sg.Text('Please enter your Name, Address, Phone')],
+ [sg.Text('Name', size=(10,1)), sg.InputText(key='-NAME-')],
+ [sg.Text('Address', size=(10,1)), sg.InputText(key='-ADDRESS-')],
+ [sg.Text('Phone', size=(10,1)), sg.InputText(key='-PHONE-')],
+ [sg.Button('Submit'), sg.Button('Cancel')]]
+
+window = sg.Window('Simple Data Entry Window', layout)
+event, values = window.read()
+print(event, values['-NAME-'], values['-ADDRESS-'], values['-PHONE-'])
diff --git a/DemoPrograms old/Demo_Table_CSV.py b/DemoPrograms old/Demo_Table_CSV.py
new file mode 100644
index 000000000..0662e83d7
--- /dev/null
+++ b/DemoPrograms old/Demo_Table_CSV.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import csv
+
+def table_example():
+ filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files","*.csv"),))
+ # --- populate table with file contents --- #
+ if filename == '':
+ sys.exit(69)
+ data = []
+ header_list = []
+ button = sg.PopupYesNo('Does this file have column names already?')
+ if filename is not None:
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ if button == 'Yes':
+ header_list = next(reader)
+ try:
+ data = list(reader) # read everything else into a list of rows
+ if button == 'No':
+ header_list = ['column' + str(x) for x in range(len(data[0]))]
+ except:
+ sg.PopupError('Error reading file')
+ sys.exit(69)
+ sg.SetOptions(element_padding=(0, 0))
+
+ layout = [[sg.Table(values=data,
+ headings=header_list,
+ max_col_width=25,
+ auto_size_columns=True,
+ justification='right',
+ alternating_row_color='lightblue',
+ num_rows=min(len(data), 20))]]
+
+
+ window = sg.Window('Table', grab_anywhere=False).Layout(layout)
+ event, values = window.Read()
+
+ sys.exit(69)
+
+table_example()
diff --git a/DemoPrograms old/Demo_Table_Element.py b/DemoPrograms old/Demo_Table_Element.py
new file mode 100644
index 000000000..4a2eac26f
--- /dev/null
+++ b/DemoPrograms old/Demo_Table_Element.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+import sys
+
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import random
+import string
+
+
+# ------------------ Create a fake table ------------------
+class Fake():
+ @classmethod
+ def word(self):
+ return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
+
+ @classmethod
+ def number(self, max=1000):
+ return random.randint(0,max)
+
+
+def make_table(num_rows, num_cols):
+ data = [[j for j in range(num_cols)] for i in range(num_rows)]
+ data[0] = [Fake.word() for _ in range(num_cols)]
+ for i in range(1, num_rows):
+ data[i] = [Fake.word(), *[Fake.number() for i in range(num_cols - 1)]]
+ return data
+
+data = make_table(num_rows=15, num_cols=6)
+# sg.SetOptions(element_padding=(0,0))
+headings = [data[0][x] for x in range(len(data[0]))]
+
+layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, background_color='lightblue',
+ auto_size_columns=True, display_row_numbers=True, justification='right', num_rows=20, alternating_row_color='blue', key='_table_', tooltip='This is a table')],
+ [sg.Button('Read'), sg.Button('Double'), sg.Button('Update')],
+ [sg.T('Read = read which rows are selected')],[sg.T('Double = double the amount of data in the table')]]
+
+window = sg.Window('Table', grab_anywhere=False, resizable=True).Layout(layout)
+
+while True:
+ event, values = window.Read()
+ print(event, values)
+ if event is None:
+ break
+ if event == 'Double':
+ for i in range(len(data)):
+ data.append(data[i])
+ window.FindElement('_table_').Update(values = data)
+ elif event == 'Update':
+ window.FindElement('_table_').Update( row_colors=((8,'white', 'red'), (9,'black')))
+
+ # sg.Popup(event, values)
+ # print(event, values)
+window.Close()
+sys.exit(69)
diff --git a/DemoPrograms old/Demo_Table_Pandas.py b/DemoPrograms old/Demo_Table_Pandas.py
new file mode 100644
index 000000000..bc192046b
--- /dev/null
+++ b/DemoPrograms old/Demo_Table_Pandas.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import pandas as pd
+
+
+def table_example():
+ sg.SetOptions(auto_size_buttons=True)
+ filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files", "*.csv"),))
+ # --- populate table with file contents --- #
+ if filename == '':
+ sys.exit(69)
+ data = []
+ header_list = []
+ button = sg.PopupYesNo('Does this file have column names already?')
+ if filename is not None:
+ try:
+ df = pd.read_csv(filename, sep=',', engine='python', header=None) # Header=None means you directly pass the columns names to the dataframe
+ data = df.values.tolist() # read everything else into a list of rows
+ if button == 'Yes': # Press if you named your columns in the csv
+ header_list = df.iloc[0].tolist() # Uses the first row (which should be column names) as columns names
+ data = df[1:].values.tolist() # Drops the first row in the table (otherwise the header names and the first row will be the same)
+ elif button == 'No': # Press if you didn't name the columns in the csv
+ header_list = ['column' + str(x) for x in range(len(data[0]))] # Creates columns names for each column ('column0', 'column1', etc)
+ except:
+ sg.PopupError('Error reading file')
+ sys.exit(69)
+
+ layout = [[sg.Table(values=data, headings=header_list, display_row_numbers=True,
+ auto_size_columns=False, num_rows=min(25,len(data)))]]
+
+ window = sg.Window('Table', grab_anywhere=False)
+ event, values = window.Layout(layout).Read()
+
+ sys.exit(69)
+
+table_example()
diff --git a/DemoPrograms old/Demo_Table_Simulation.py b/DemoPrograms old/Demo_Table_Simulation.py
new file mode 100644
index 000000000..32018c5a8
--- /dev/null
+++ b/DemoPrograms old/Demo_Table_Simulation.py
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import csv
+
+
+def TableSimulation():
+ """
+ Display data in a table format
+ """
+ sg.SetOptions(element_padding=(0,0))
+
+ menu_def = [['File', ['Open', 'Save', 'Exit']],
+ ['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
+ ['Help', 'About...'],]
+
+ columm_layout = [[]]
+
+ MAX_ROWS = 20
+ MAX_COL = 10
+ for i in range(MAX_ROWS):
+ inputs = [sg.T('{}'.format(i), size=(4,1), justification='right')] + [sg.In(size=(10, 1), pad=(1, 1), justification='right', key=(i,j), do_not_clear=True) for j in range(MAX_COL)]
+ columm_layout.append(inputs)
+
+ layout = [ [sg.Menu(menu_def)],
+ [sg.T('Table Using Combos and Input Elements', font='Any 18')],
+ [sg.T('Type in a row, column and value. The form will update the values in realtime as you type'),
+ sg.In(key='inputrow', justification='right', size=(8,1), pad=(1,1), do_not_clear=True),
+ sg.In(key='inputcol', size=(8,1), pad=(1,1), justification='right', do_not_clear=True),
+ sg.In(key='value', size=(8,1), pad=(1,1), justification='right', do_not_clear=True)],
+ [sg.Column(columm_layout, size=(800,600), scrollable=True)] ]
+
+ window = sg.Window('Table', return_keyboard_events=True).Layout(layout)
+
+ while True:
+ event, values = window.Read()
+ # --- Process buttons --- #
+ if event is None or event == 'Exit':
+ break
+ elif event == 'About...':
+ sg.Popup('Demo of table capabilities')
+ elif event == 'Open':
+ filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files","*.csv"),))
+ # --- populate table with file contents --- #
+ if filename is not None:
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ try:
+ data = list(reader) # read everything else into a list of rows
+ except:
+ sg.PopupError('Error reading file')
+ continue
+ # clear the table
+ [window.FindElement((i,j)).Update('') for j in range(MAX_COL) for i in range(MAX_ROWS)]
+
+ for i, row in enumerate(data):
+ for j, item in enumerate(row):
+ location = (i,j)
+ try: # try the best we can at reading and filling the table
+ target_element = window.FindElement(location)
+ new_value = item
+ if target_element is not None and new_value != '':
+ target_element.Update(new_value)
+ except:
+ pass
+
+ # if a valid table location entered, change that location's value
+ try:
+ location = (int(values['inputrow']), int(values['inputcol']))
+ target_element = window.FindElement(location)
+ new_value = values['value']
+ if target_element is not None and new_value != '':
+ target_element.Update(new_value)
+ except:
+ pass
+
+TableSimulation()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Tabs.py b/DemoPrograms old/Demo_Tabs.py
new file mode 100644
index 000000000..733cb334a
--- /dev/null
+++ b/DemoPrograms old/Demo_Tabs.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+sg.SetOptions(background_color='cornsilk4', element_background_color='cornsilk2', input_elements_background_color='cornsilk2')
+
+tab1_layout = [[sg.T('This is inside tab 1', background_color='darkslateblue', text_color='white')],
+ [sg.In(key='_in0_')]]
+
+tab2_layout = [[sg.T('This is inside tab 2', background_color='tan1')],
+ [sg.In(key='_in2_')]]
+
+
+tab3_layout = [[sg.T('This is inside tab 3')],
+ [sg.In(key='_in2_')]]
+
+tab4_layout = [[sg.T('This is inside tab 4', background_color='darkseagreen')],
+ [sg.In(key='_in3_')]]
+
+tab5_layout = [[sg.T('This is inside tab 5')],
+ [sg.In(key='_in4_')]]
+
+
+layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='_mykey_'),
+ sg.Tab('Tab 2', tab2_layout, background_color='tan1'),
+ sg.Tab('Tab 3', tab3_layout)]],
+ key='_group2_', title_color='red',
+ selected_title_color='green', tab_location='right'),
+ sg.TabGroup([[sg.Tab('Tab 4', tab4_layout,background_color='darkseagreen', key='_mykey_'),
+ sg.Tab('Tab 5', tab5_layout)]], key='_group1_', tab_location='top', selected_title_color='purple')],
+ [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='_mykey_'),
+ sg.Tab('Tab 2', tab2_layout, background_color='tan1'),
+ sg.Tab('Tab 3', tab3_layout)]],
+ key='_group3_', title_color='red',
+ selected_title_color='green', tab_location='left'),
+ sg.TabGroup([[sg.Tab('Tab 4', tab4_layout,background_color='darkseagreen', key='_mykey_'),
+ sg.Tab('Tab 5', tab5_layout)]], key='_group4_', tab_location='bottom', selected_title_color='purple')],
+ [sg.Button('Read')]]
+
+window = sg.Window('My window with tabs', default_element_size=(12,1)).Layout(layout)
+
+
+while True:
+ event, values = window.Read()
+ sg.PopupNonBlocking(event, values)
+ print(event, values)
+ if event is None: # always, always give a way out!
+ break
diff --git a/DemoPrograms old/Demo_Tabs_Nested.py b/DemoPrograms old/Demo_Tabs_Nested.py
new file mode 100644
index 000000000..8868cb530
--- /dev/null
+++ b/DemoPrograms old/Demo_Tabs_Nested.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+sg.ChangeLookAndFeel('GreenTan')
+tab2_layout = [[sg.T('This is inside tab 2')],
+ [sg.T('Tabs can be anywhere now!')]]
+
+tab1_layout = [[sg.T('Type something here and click button'), sg.In(key='in')]]
+
+tab3_layout = [[sg.T('This is inside tab 3')]]
+tab4_layout = [[sg.T('This is inside tab 4')]]
+
+tab_layout = [[sg.T('This is inside of a tab')]]
+tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout), sg.Tab('Tab 8', tab_layout)]])
+
+tab5_layout = [[sg.T('Watch this window')],
+ [sg.Output(size=(40,5))]]
+tab6_layout = [[sg.T('This is inside tab 6')],
+ [sg.T('How about a second row of stuff in tab 6?'), tab_group]]
+
+layout = [[sg.T('My Window!')], [sg.Frame('A Frame', layout=
+ [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), sg.Tab('Tab 2', tab2_layout)]]), sg.TabGroup([[sg.Tab('Tab3', tab3_layout), sg.Tab('Tab 4', tab4_layout)]])]])],
+ [sg.T('This text is on a row with a column'),sg.Column(layout=[[sg.T('In a column')],
+ [sg.TabGroup([[sg.Tab('Tab 5', tab5_layout), sg.Tab('Tab 6', tab6_layout)]])],
+ [sg.Button('Click me')]])],]
+
+window = sg.Window('My window with tabs', default_element_size=(12,1)).Layout(layout).Finalize()
+
+print('Are there enough tabs for you?')
+
+while True:
+ event, values = window.Read()
+ print(event, values)
+ if event is None: # always, always give a way out!
+ break
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Tabs_Simple.py b/DemoPrograms old/Demo_Tabs_Simple.py
new file mode 100644
index 000000000..d666c3268
--- /dev/null
+++ b/DemoPrograms old/Demo_Tabs_Simple.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+tab1_layout = [[sg.T('Tab 1')],
+ [sg.T('Put your layout in here')],
+ [sg.T('Input something'),sg.In(key='_IN0_')]]
+
+tab2_layout = [[sg.T('Tab2')]]
+
+
+layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), sg.Tab('Tab 2', tab2_layout)]], key='_TABGROUP_')],
+ [sg.Button('Read')]]
+
+window = sg.Window('My window with tabs', default_element_size=(12,1)).Layout(layout)
+
+
+while True:
+ event, values = window.Read()
+ sg.PopupNonBlocking('button = %s' % event, 'Values dictionary', values)
+ if event is None: # always, always give a way out!
+ break
diff --git a/DemoPrograms old/Demo_Template.py b/DemoPrograms old/Demo_Template.py
new file mode 100644
index 000000000..581bf9340
--- /dev/null
+++ b/DemoPrograms old/Demo_Template.py
@@ -0,0 +1,39 @@
+#choose one of these are your starting point. Copy, paste, have fun
+
+# ---------------------------------#
+# DESIGN PATTERN 1 - Simple Window #
+# ---------------------------------#
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[ sg.Text('My layout') ],
+ [ sg.CloseButton('Next Window')]]
+
+window = sg.Window('My window').Layout(layout)
+event, values = window.Read()
+
+
+# --------------------------------------------------#
+# DESIGN PATTERN 2 - Persistent Window (stays open) #
+# --------------------------------------------------#
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[ sg.Text('My Window') ],
+ [ sg.Button('Read The Window')]]
+
+window = sg.Window('My Window Title').Layout(layout)
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None: # if window closed with X
+ break
+ print(event, values)
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Threaded_Work.py b/DemoPrograms old/Demo_Threaded_Work.py
new file mode 100644
index 000000000..e4dd3b9b0
--- /dev/null
+++ b/DemoPrograms old/Demo_Threaded_Work.py
@@ -0,0 +1,102 @@
+#!/usr/bin/python3
+import queue
+import threading
+import time
+import PySimpleGUI as sg
+
+"""
+ You want to look for 3 points in this code, marked with comment "LOCATION X".
+ 1. Where you put your call that takes a long time
+ 2. Where the trigger to make the call takes place in the event loop
+ 3. Where the completion of the call is indicated in the event loop
+
+ Demo on how to add a long-running item to your PySimpleGUI Event Loop
+ If you want to do something that takes a long time, and you do it in the
+ main event loop, you'll quickly begin to see messages from windows that your
+ program has hung, asking if you want to kill it.
+
+ The problem is not that your problem is hung, the problem is that you are
+ not calling Read or Refresh often enough.
+
+ One way through this, shown here, is to put your long work into a thread that
+ is spun off, allowed to work, and then gets back to the GUI when it's done working
+ on that task.
+
+ Every time you start up one of these long-running functions, you'll give it an "ID".
+ When the function completes, it will send to the GUI Event Loop a message with
+ the format:
+ work_id ::: done
+ This makes it easy to parse out your original work ID
+
+ You can hard code these IDs to make your code more readable. For example, maybe
+ you have a function named "update_user_list()". You can call the work ID "user list".
+ Then check for the message coming back later from the work task to see if it starts
+ with "user list". If so, then that long-running task is over.
+
+"""
+
+# ############################# User callable CPU intensive code #############################
+# Put your long running code inside this "wrapper"
+# NEVER make calls to PySimpleGUI from this thread (or any thread)!
+# Create one of these functions for EVERY long-running call you want to make
+def long_function_wrapper(work_id, gui_queue):
+ # LOCATION 1
+ # this is our "long running function call"
+ time.sleep(5) # sleep for a while as a simulation of a long-running computation
+ # at the end of the work, before exiting, send a message back to the GUI indicating end
+ gui_queue.put('{} ::: done'.format(work_id))
+ # at this point, the thread exits
+ return
+
+
+############################# Begin GUI code #############################
+def the_gui():
+ gui_queue = queue.Queue() # queue used to communicate between the gui and long-running code
+
+ layout = [[sg.Text('Multithreaded Work Example')],
+ [sg.Text('Click Go to start a long-running function call')],
+ [sg.Text('', size=(25, 1), key='_OUTPUT_')],
+ [sg.Text('', size=(25, 1), key='_OUTPUT2_')],
+ [sg.Graph((10,10),(0,0),(10,10),background_color='black',key=i) for i in range(20)],
+ [sg.Button('Go'), sg.Button('Popup'), sg.Button('Exit')], ]
+
+ window = sg.Window('Multithreaded Window').Layout(layout)
+ # --------------------- EVENT LOOP ---------------------
+ work_id = 0
+ while True:
+ event, values = window.Read(timeout=100) # wait for up to 100 ms for a GUI event
+ if event is None or event == 'Exit':
+ break
+ if event == 'Go': # clicking "Go" starts a long running work item by starting thread
+ window.Element('_OUTPUT_').Update('Starting long work %s'%work_id)
+ window.Element(work_id).Update(background_color='red')
+ # LOCATION 2
+ # STARTING long run by starting a thread
+ thread_id = threading.Thread(target=long_function_wrapper, args=(work_id, gui_queue,), daemon=True)
+ thread_id.start()
+ work_id = work_id+1 if work_id < 19 else 0
+ # --------------- Read next message coming in from threads ---------------
+ try:
+ message = gui_queue.get_nowait() # see if something has been posted to Queue
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ message = None # nothing in queue so do nothing
+
+ # if message received from queue, then some work was completed
+ if message is not None:
+ # LOCATION 3
+ # this is the place you would execute code at ENDING of long running task
+ # You can check the completed_work_id variable to see exactly which long-running function completed
+ completed_work_id = int(message[:message.index(' :::')])
+ window.Element('_OUTPUT2_').Update('Complete Work ID "{}"'.format(completed_work_id))
+ window.Element(completed_work_id).Update(background_color='green')
+
+ if event == 'Popup':
+ sg.Popup('This is a popup showing that the GUI is running')
+ # if user exits the window, then close the window and exit the GUI func
+ window.Close()
+
+############################# Main #############################
+
+if __name__ == '__main__':
+ the_gui()
+ print('Exiting Program')
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Timer.py b/DemoPrograms old/Demo_Timer.py
new file mode 100644
index 000000000..4bf3d386f
--- /dev/null
+++ b/DemoPrograms old/Demo_Timer.py
@@ -0,0 +1,44 @@
+import PySimpleGUI as sg
+import time
+
+# form that doen't block
+# good for applications with an loop that polls hardware
+def Timer():
+ sg.ChangeLookAndFeel('Dark')
+ sg.SetOptions(element_padding=(0,0))
+ # Make a form, but don't use context manager
+ window = sg.Window('Running Timer', no_titlebar=True, auto_size_buttons=False)
+ # Create a text element that will be updated with status information on the GUI itself
+ # Create the rows
+ form_rows = [[sg.Text('')],
+ [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
+ [sg.Button('Pause', key='-RUN-PAUSE-'), sg.Button('Reset'), sg.Exit(button_color=('white','firebrick4'))]]
+ # Layout the rows of the form and perform a read. Indicate the form is non-blocking!
+ window.Layout(form_rows)
+ #
+ # your program's main loop
+ i = 0
+ paused = False
+ start_time = int(round(time.time() * 100))
+ while (True):
+ # This is the code that reads and updates your window
+ button, values = window.read(timeout=0)
+ window.FindElement('text').Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100))
+
+ if values is None or button == 'Exit':
+ break
+
+ if button == 'Reset':
+ i=0
+ elif button == '-RUN-PAUSE-':
+ paused = not paused
+ window['-RUN-PAUSE-'].Update('Run' if paused else 'Pause')
+
+ if not paused:
+ i += 1
+
+
+ # Broke out of main loop. Close the window.
+ window.close()
+
+Timer()
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Touch_Keyboard.py b/DemoPrograms old/Demo_Touch_Keyboard.py
new file mode 100644
index 000000000..350eab314
--- /dev/null
+++ b/DemoPrograms old/Demo_Touch_Keyboard.py
@@ -0,0 +1,103 @@
+import PySimpleGUI as sg
+# import PySimpleGUIQt as sg # 100% portable to Qt by changing to this import
+
+
+class keyboard():
+ def __init__(self, location=(None, None), font=('Arial', 16)):
+ self.font = font
+ numberRow = '1234567890'
+ topRow = 'QWERTYUIOP'
+ midRow = 'ASDFGHJKL'
+ bottomRow = 'ZXCVBNM'
+ keyboard_layout = [[sg.Button(c, key=c, size=(4, 2), font=self.font) for c in numberRow] + [
+ sg.Button('⌫', key='back', size=(4, 2), font=self.font),
+ sg.Button('Esc', key='close', size=(4, 2), font=self.font)],
+ [sg.T(' ' * 4)] + [sg.Button(c, key=c, size=(4, 2), font=self.font) for c in
+ topRow] + [sg.Stretch()],
+ [sg.T(' ' * 11)] + [sg.Button(c, key=c, size=(4, 2), font=self.font) for c in
+ midRow] + [sg.Stretch()],
+ [sg.T(' ' * 18)] + [sg.Button(c, key=c, size=(4, 2), font=self.font) for c in
+ bottomRow] + [sg.Stretch()]]
+
+ self.window = sg.Window('keyboard',
+ grab_anywhere=True,
+ keep_on_top=True,
+ alpha_channel=0,
+ no_titlebar=True,
+ element_padding=(0,0),
+ location=location
+ ).Layout(keyboard_layout).Finalize()
+ self.hide()
+
+ def _keyboardhandler(self):
+ if self.event is not None:
+ if self.event == 'close':
+ self.hide()
+ elif len(self.event) == 1:
+ self.focus.Update(self.focus.Get() + self.event)
+ elif self.event == 'back':
+ Text = self.focus.Get()
+ if len(Text) > 0:
+ Text = Text[:-1]
+ self.focus.Update(Text)
+
+ def hide(self):
+ self.visible = False
+ self.window.Disappear()
+
+ def show(self):
+ self.visible = True
+ self.window.Reappear()
+
+ def togglevis(self):
+ if self.visible:
+ self.hide()
+ else:
+ self.show()
+
+ def update(self, focus):
+ self.event, _ = self.window.Read(timeout=0)
+ if focus is not None:
+ self.focus = focus
+ self._keyboardhandler()
+
+ def close(self):
+ self.window.Close()
+
+
+class GUI():
+ def __init__(self):
+ layout = [[sg.Text('Enter Text')],
+ [sg.Input(size=(17, 1), key='input1', do_not_clear=True)],
+ [sg.InputText(size=(17, 1), key='input2', do_not_clear=True)],
+ [sg.Button('on-screen keyboard', key='keyboard')],
+ [sg.Button('close', key='close')]]
+
+ self.mainWindow = sg.Window('On-screen test',
+ grab_anywhere=True,
+ no_titlebar=False,
+ ).Layout(layout).Finalize()
+ location = self.mainWindow.CurrentLocation()
+ location = location[0]-200, location[1]+200
+ self.keyboard = keyboard(location)
+ self.focus = None
+
+ def run(self):
+ while True:
+ cur_focus = self.mainWindow.FindElementWithFocus()
+ if cur_focus is not None:
+ self.focus = cur_focus
+ event, values = self.mainWindow.Read(timeout=200, timeout_key='timeout')
+ if self.focus is not None:
+ self.keyboard.update(self.focus)
+ if event == 'keyboard':
+ self.keyboard.togglevis()
+ elif event == 'close' or event is None:
+ break
+ self.keyboard.close()
+ self.mainWindow.Close()
+
+
+if __name__ == '__main__':
+ app = GUI()
+ app.run()
diff --git a/DemoPrograms old/Demo_Tree_Element.py b/DemoPrograms old/Demo_Tree_Element.py
new file mode 100644
index 000000000..e83ec3e80
--- /dev/null
+++ b/DemoPrograms old/Demo_Tree_Element.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+import sys
+import os
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+
+"""
+ A PySimpleGUI or PySimpleGUIQt demo program that will display a folder heirarchy with icons for the folders and files.
+ Note that if you are scanning a large folder then tkinter will eventually complain abouit too many bitmaps and crash
+ Getting events back from clicks on the entries works for PySimpleGUI, but appears to not be implemented in PySimpleGUIQt
+ If you need tree events using PySimpleGUIQt then post an Issue on the GitHub http://www.PySimpleGUI.com
+"""
+
+# Base64 versions of images of a folder and a file. PNG files (may not work with PySimpleGUI27, swap with GIFs)
+
+folder_icon = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABnUlEQVQ4y8WSv2rUQRSFv7vZgJFFsQg2EkWb4AvEJ8hqKVilSmFn3iNvIAp21oIW9haihBRKiqwElMVsIJjNrprsOr/5dyzml3UhEQIWHhjmcpn7zblw4B9lJ8Xag9mlmQb3AJzX3tOX8Tngzg349q7t5xcfzpKGhOFHnjx+9qLTzW8wsmFTL2Gzk7Y2O/k9kCbtwUZbV+Zvo8Md3PALrjoiqsKSR9ljpAJpwOsNtlfXfRvoNU8Arr/NsVo0ry5z4dZN5hoGqEzYDChBOoKwS/vSq0XW3y5NAI/uN1cvLqzQur4MCpBGEEd1PQDfQ74HYR+LfeQOAOYAmgAmbly+dgfid5CHPIKqC74L8RDyGPIYy7+QQjFWa7ICsQ8SpB/IfcJSDVMAJUwJkYDMNOEPIBxA/gnuMyYPijXAI3lMse7FGnIKsIuqrxgRSeXOoYZUCI8pIKW/OHA7kD2YYcpAKgM5ABXk4qSsdJaDOMCsgTIYAlL5TQFTyUIZDmev0N/bnwqnylEBQS45UKnHx/lUlFvA3fo+jwR8ALb47/oNma38cuqiJ9AAAAAASUVORK5CYII='
+
+file_icon = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABU0lEQVQ4y52TzStEURiHn/ecc6XG54JSdlMkNhYWsiILS0lsJaUsLW2Mv8CfIDtr2VtbY4GUEvmIZnKbZsY977Uwt2HcyW1+dTZvt6fn9557BGB+aaNQKBR2ifkbgWR+cX13ubO1svz++niVTA1ArDHDg91UahHFsMxbKWycYsjze4muTsP64vT43v7hSf/A0FgdjQPQWAmco68nB+T+SFSqNUQgcIbN1bn8Z3RwvL22MAvcu8TACFgrpMVZ4aUYcn77BMDkxGgemAGOHIBXxRjBWZMKoCPA2h6qEUSRR2MF6GxUUMUaIUgBCNTnAcm3H2G5YQfgvccYIXAtDH7FoKq/AaqKlbrBj2trFVXfBPAea4SOIIsBeN9kkCwxsNkAqRWy7+B7Z00G3xVc2wZeMSI4S7sVYkSk5Z/4PyBWROqvox3A28PN2cjUwinQC9QyckKALxj4kv2auK0xAAAAAElFTkSuQmCC'
+
+starting_path = sg.PopupGetFolder('Folder to display')
+
+if not starting_path:
+ sys.exit()
+
+treedata = sg.TreeData()
+
+def add_files_in_folder(parent, dirname):
+ files = os.listdir(dirname)
+ for f in files:
+ fullname = os.path.join(dirname,f)
+ if os.path.isdir(fullname): # if it's a folder, add folder and recurse
+ treedata.Insert(parent, fullname, f, values=[], icon=folder_icon)
+ add_files_in_folder(fullname, fullname)
+ else:
+
+ treedata.Insert(parent, fullname, f, values=[os.stat(fullname).st_size], icon=file_icon)
+
+add_files_in_folder('', starting_path)
+
+
+layout = [[ sg.Text('File and folder browser Test') ],
+ [ sg.Tree(data=treedata,
+ headings=['Size', ],
+ auto_size_columns=True,
+ num_rows=20,
+ col0_width=30,
+ key='_TREE_',
+ show_expanded=False,
+ enable_events=True),
+ ],
+ [ sg.Button('Ok'), sg.Button('Cancel')]]
+
+window = sg.Window('Tree Element Test').Layout(layout)
+
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event in (None, 'Cancel'):
+ break
+ print(event, values)
+
diff --git a/DemoPrograms old/Demo_Turtle.py b/DemoPrograms old/Demo_Turtle.py
new file mode 100644
index 000000000..dcc2b0b22
--- /dev/null
+++ b/DemoPrograms old/Demo_Turtle.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import turtle
+
+"""
+ Demo showing how to integrate drawing on a Canvas using Turtle with PySimpleGUI
+ The patern to follow:
+ Create Window & Finalize
+ Get the tkinter Canvas from the Canvas element
+ Draw on the tkinter Canvas using turtle commands.
+ Results are shown on the canvas immiedately after button press / drawing command
+"""
+
+
+layout = [[ sg.Text('My layout') ],
+ [sg.Canvas(size=(800,800), key='_canvas_')],
+ [ sg.Button('F'), sg.Button('B'), sg.Button('L'), sg.Button('R')],
+ [sg.Button('Spiral'), sg.Button('Inside Out'), sg.Button('Circles')]]
+
+window = sg.Window('My new window').Layout(layout).Finalize()
+
+canvas = window.FindElement('_canvas_').TKCanvas
+
+t = turtle.RawTurtle(canvas)
+t.pencolor("#ff0000") # Red
+
+t.penup()
+t.pendown()
+
+while True: # Event Loop
+ event, values = window.Read()
+ if event is None:
+ break
+
+ if event == 'F':
+ t.forward(100)
+ elif event == 'B':
+ t.back(100)
+ elif event == 'L':
+ t.left(90)
+ elif event == 'R':
+ t.right(90)
+ elif event == 'Spiral':
+ canvas.config(bg='light green')
+ t.color("blue")
+ def sqrfunc(size):
+ for i in range(4):
+ t.fd(size)
+ t.left(90)
+ size = size - 5
+ sqrfunc(146)
+ sqrfunc(126)
+ sqrfunc(106)
+ sqrfunc(86)
+ sqrfunc(66)
+ sqrfunc(46)
+ sqrfunc(26)
+ elif event == 'Inside Out':
+ canvas.config(bg = "light green")
+ t.color("blue")
+ def sqrfunc(size):
+ for i in range(4):
+ t.fd(size)
+ t.left(90)
+ size = size + 5
+ sqrfunc(6)
+ sqrfunc(26)
+ sqrfunc(46)
+ sqrfunc(66)
+ sqrfunc(86)
+ sqrfunc(106)
+ sqrfunc(126)
+ sqrfunc(146)
+ elif event == 'Circles':
+ t.speed(0)
+ for i in range(400):
+ t.circle(2 * i*.25)
+ t.circle(-2 * i*.25)
+ t.left(i)
diff --git a/DemoPrograms old/Demo_Uno_Card_Game.py b/DemoPrograms old/Demo_Uno_Card_Game.py
new file mode 100644
index 000000000..a275789ee
--- /dev/null
+++ b/DemoPrograms old/Demo_Uno_Card_Game.py
@@ -0,0 +1,1531 @@
+import os
+import sys
+import random
+import math
+import time
+import PySimpleGUI as sg
+
+
+#-------------------------------------------------------------------------------#
+# Works on Python 3 #
+# Uno card game using a GUI interface provided by PySimpleGUI #
+# Based on this excellent text based version: #
+# http://code.activestate.com/recipes/580811-uno-text-based/ #
+# Contains all of the graphics inside the source file as base64 images #
+# Cards were obtained from Wikipedia #
+# https://en.wikipedia.org/wiki/Uno_(card_game) #
+# Up to 4 players... any number can be computer controlled #
+# Still needs some work but close enough for fun #
+#-------------------------------------------------------------------------------#
+
+yellow_color = '#FFAA00'
+blue_color = '#5555FF'
+red_color = '#FF5555'
+green_color = '#55AA55'
+
+
+
+wildblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19R13JWlvZWVrcS13gU07kVE3jUE/sW07gU1DtU1frU1ftVFDuUVzsXlnvUlL3UlL5VVX+U1rwXFz1Wlr9TXTDU2ffVGvcVW3aVH3AWnXWXHbWXXTYXnnVUmPjUWLlUmTiVmHlXWLjak7PbE/PZV/VY13aZF3aal/Zal/dYFHmY13tbV7obl/vYVfzY1jzZ1rxalzwaWPaYHHaYX3UZH/Ud2bCdmbEc2TOemnJcmPQeGPcaGHoZWL6amH1a2f5amr/bm7/cGflcmLudmXtc2rjdWzieW/hemntfWztfHLhcnL/e3v/W4TAYorBZo7CaITUbIjUbJLEcY3VdJjHepzJd5LWfJbXf6HMgGq7hWTdiW/Xi2vejW/fiHbKjXvKgG/tgnLuhnfvg3nhi33wk3Xglnnhl3zimX/kgYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhoaOlpaWloqWqqampra2tsbGxtbW1urq6vLy8gZnZhp7alYTNmIjPmorQm4zRnY/Un5HVi4LjhIT/jYHxlY3om4HlnIPmnofokoj0lo31k5P/mZP4mJj/haXOjaLdi6nRkazUmrLYlqnhoJLWopXYpJfaoZjYpprcpJzYp5zdoo7qpJLspZXtoJvyqJrwq5/zoLbdq6LjrqbooaH/pKT/q6L1rab3qqr/r6n5rq7/oLDlp7XpprrgqrzisKnqs63vtK/xsa37tbHzt7T3srL+ubf6urr+scHmucXrvsjv3Zi53py8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/wcrxycn/y9D20NL60dH/1dX+3Nz+3unt4eHh5eXl6enp7e3t5eX+5+306eTz6ef46en+7O/57Oz/8fHx9fX18vL+9PT++fn5+Pj+/v7+AAAAP81AhwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABapSURBVHhe3Z15YB3HXcff02mrPmRZdnxIogVaDkMEjhPSug6Uoy03xPQAQwPldJJSk0ALuNBCaSzbcozxIZUAaQMhHA1JablCcNOkdh2gARfVdsCWLKk5cJD0FioqUWXN7zfz293Z672Z2d97+zafP7y23r7VfLyz353dnZ0pXa2B21RQoWpRw4o21lxQ2apQ1Yq20pxQGROpYkXfbnKosGFSrehLBYAKrJJiRV8oBlRmhUQrWrswULEDEqxo1UJBRfeIWdFqRYNKT0StaKXiQeWXRKxolSJCBoKwFa1QTMgBCVnRx0WFLADVij4sLKQBKFb0WYEhEdWKPikyZKJY0Qdxpi+NjjQVo5emqGgxyMW3oh9HmB7obis1Ia2r+yepiGHIpprVyBraSFPSfZyKqUI2ZEU/VJnroa83Ld0zVFQFqSOt6Ecqx5qy6oVpO0yFDRA6qVaH6ItNzgEqboDwEVb0A4WCSCVoVbE6Tt+pTrm9c1nu9fQIFdkn1Wqunb6SRtuagaMTFbnusbX0w3xojUZGqlUvfSOZl+2boPWIyVX0SS6soVL4pFhdpPWTaOtLOv1tpk9z4QQVwoOs6F8+6buqc3hRruKMnXn0j3/r3//6iSeviH/nqdUtSqCQaDVDa8doO7iEnztjp+76/kHkdfjHLf+JP8yzEsaahUlW+2nlKBtEPDhnflYYIa+UizH48WVaKQ/6sVwqSVbJmdY5ip85n/huaYK8ipaDuLdyTMJ4FQQr+qtPJ60cogd3lHNKcRocvJaWg7vhs6O0Yg60iWIrJFjN0bohBuADZ+xnyELyFbQEIDISv9YgYgdW3GqSVlUoYyvS+RNSIN5ISwSPrFZa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'
+wildgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19Ap0AC5UADp8LD5kUCpwYCZ4cFZoAGpcUCp4gDpksEZImEZgzAKMABKQNAKoABKkABasEBqwGCqYPDqkACqwKC6YWCKAZFaYKEqoCG6EAHKALGaoAHKwKFKQUEa8QGKMQH6YRHa8RE7ASGbAUGrIaE6chFackHaguJ5oNL5sANJYRIKcMIa0KLKoAKa8PIqcTJqcXK6gcLrATK7IZMaoAOaQYMbEVN7IaO7MeIaEiIaM6IaoyJao2La4+I7UjKbcpLLgsMakgN6smOqwpPa0sMroyNrs2O707K6hBL6RQNqNINqZWOKdYPKpbP6tdNLBETbIZR6olRKouSaEoQa8wRLcnSLgsRLAzRbE1TrU3SrM6VKY1Wac5XKs+VLQgWrcnX7gtUbs2VL06aaoAYroyab08Sp9yQq1fQLZPQb9BS7tXX6xCUbdDVLlHV7tLVb9fXL5RSrBlUbRqVbdtXbtyYq5FZ7JMabNPbb9Ca7VSbrhXcrhNYL10db1hRcBFTcNNVMVUWMdYXchdWsNiYMJJb8FFYsJZc8JLd8VSesdYfMhbZsZgY8pja81raMF5cctkecFofcVvcsd/cM9wddB1fNJ8c5+YeMuCrKlxgMpihM1sgcl1gsx4hc99idB1jdN9gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8gNCFgtWCh9GBhdOIitSFiNeIi9iLjNiMkdaGk9iLk9qTl9qSmNyYo+CjquKqsuWyuOe4vOi8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dwurCzevHy+3L0e/R1Oza3u/S1vDW2/Lb3vPe4eHh5eXl6enp7e3t5PXk6ffp7Pjs8fHx9fX19Pv0+fn5+fz5/v7+AAAAeLMFJAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaXSURBVHhe3Z15fBznWcd3ddqqbcmyfEviKlfJQkCBQIoB1dz3faXCHMGUlFLuI9yEpuXoQSENxbH9CUc46pCkNgU3DpJtOZZlS7HjopI4dmtLlmQKZCXtupaqvuZ53nlm5p1r931nnt3ZyfcPr6yd2X2/et/5zTsz78ybu10F0VBQoapRxYo+rLGgslWgohV9SmNCZQylghWt3eBQYb1EWtFKGYAKrBJhRStkAyqzQqgVLZ0ZqNguIVa0aKagotsErGixrEGlJ/xWtFD2oPJb+KxokSxCBhKvFS2QTcgB8VjR21mFLADVit7MLKQBKFb0XoYhEdWK3skyZKJY0RtB5q9NTjQUk9fmqGgByMWxol/7mO/vask1IM2dfbNURC9kU8lqYiN9SEPSdZaKqUI2ZEW/VCl10+oNS9ciFVXB0rGs6Fcq4w3Z9Ly0nKbCukidSKtTtGKDc4KK6yJ9pBX9QiEjUiFaFazO0jqVybe2r0m9nY5RkR0irUqttEoULRv7z8yUrWXHN9Ev06HZHxmRVj20RjivGZ6h5YjZDfROKmykUjhEWF2l5cNo6Q3b/e2kd1PhHBXChqzofw7RVdU+umItUpy68ORf/eW//ez9b9k3VYT/p6nVZRXJJdRqkZYO0HJyFd8vTj3z8HcWkM+T/74dtdJshIFuYZjVcVrYzzYZD8ULPyVdkNdaL/eC1nVaKA36ZLEVwqzCM619Et8rfvi7LBPks+lV1laKSRhsgmBFPzq008IeurGiis8oTk5VAVNCnKEFU6DFKrdLiFWJlvXQD28Up36SJCw+h16BfRGr1YnAhhW0mqVFFfLYiyy+mxSIz6JX5CF4v5kWToFrsuAK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'
+wildred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19tEx6tEx8y19C3ltJ3lRx3VR0w3RNwH1U32dT2m1V3GtU1nVa1nZc1Xle2HFYxHF32Gx01H1h1H9k415D5V5E4FxK5FpJ7VpJ4lBd5lBZ7VFY7FJc7FxR9lFS91dT9Vdf81tT+VJT/VRU+llS/VhS/l1T+Fpf/1tb/l1e71Ri7ltr8lZh8lpl8F1r+Fpg42NS4mRS5WJR4W5b/mFT/mNU/mdX/mpZ/mxa/m9d/nZU/nJf/ntZ4mBm5WN87WR17Wd47Wt8/2Ji/2ho/21t/nVn/nhl/ntp/3Jy/nZ2/3t73WyC2myP3mqK3m6O3nCP3HCT3HKU3XWW3nqZ6m2B7nKC4HSS4niU432Y8HuJq7F7wIRbwYtjxJJrx5h0yZ161IRo1Ihs1Y1x1pJ315Z8zKF//oBe5YFn5YNq94Nk/oNj/oZm/ohp/ops/oxv/oFw/oRz/o9z/o1+/pF1/pJ4/pV8gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2dsbOBoaGhpaWlqampra2tsbGxtbW1urq6vLy82ZmB2p6GzqWF0amL3aKN1KyR2LKa3bag5YOb8oOP/4KC/4yM9YyV/pqE/pyH/5CQ/5WV/puT/5ub/p2d44Wg5Ymi6o6h6ZGm7ZWl7Jiq8Zyp4amW/qCM/qOS/qWV/qaY/qmc5bCg4Lqm4ryq6bWn9KGr/qOj/q2j+Kit+qyv/6mp/62t+Kyy/rGq/rSv+rG0/rKy/ra1/rm5/76+5sGx68W578i+wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d8crB/8LC/8XF/8vL9tDL/dTT/9nZ/tzc7ene/uTd4eHh5eXl6enp7e3t9O3n/+Pj/ubm+e/s/ujo/+3t8fHx9fX1/vHx//X1+fn5//n5/v7+AAAA1zju8QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABZTSURBVHhe3Z17YBzHWcDv9LRV2ZZl2ZatB7QQnKQGYmhLqXnkgPJoSuMChfJoEwqkLaWFAgGStJS2vAqFQCvZloJfkUpCGkh4BBfSECgJFNyEUvAztmRJcRzFIOtQOOthj/t9s9++d+9mZr+73c3vD691t7uan2bmm9nd2ZnC1RqITEGJqkUNKzpZtqC0VaGqFZ0lm1AaI6liRUdnHEqsn1grOigHUIK9xFjRAfmA0uwh0or2zg2UbJcIK9o1V1DSbUJWtFveoNQTQSvaKX9Q+i0CVrRLHiEDid+Kdsgn5ID4rOjrvEIWgNeKvswtpAF4rOi7HEMiXiv6Js+QiceKvggzc2Z8LFOMn5mmpIUgF8eKPg4wM9jVUsggzesGpiiJfsimmtXYejpJJuk6RMn0QjZkRR96me+mwzNL1xwl1YOlY1nRR14OZrLo+WnZR4l1kTqxVqN0YMbZQ8l1kT7Sij7wkBOpCK0qVofomOoUW9tXpV5O91OSHWKt5lvpkDha1g8emCxb+x7cQB+mQ3MwZMRa9dAR0bxsaJL2I6bW0jepsJ5S4RBjdZr2j6KlP6r566NvU+FeSoQNWdFPDvFZ1T6yRPuIlQvPHfvMu9/3/s9W8Kc0tbpkejxEWs3R3iFa9l629rh04pF3lIDX4j9vkF5pFsJQtzDKajftHKTXCg8rx9+FMsCNtP1F0DpLO6XBgEyXhyir6JjWPi6/rBz+bnIplV5H29JnY49qCOEiCFb0X4d22tlHt8yoSx6n0jfTFgohZNYB2jEFWmSyPURYzdO+PgblV8c8Tj4gsyIPaxChihW2mqJdPRRlL3LBrk8WMlQQ74evm2nnFDiDyfNSCBXA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'
+wildyellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKysrMTExNTU1OTk5PT09QUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX1915U1xa4Ny6oAw68SwrEVwLMe364N3K8Q1rMc1rQf2rAT2LEY2rMdz6Q3wLYnwLgtyLgtwbozw7062ag31LUj1Lgr1Loy1Lw41b8/5pgW5pwW5ZoZ554e6pUW7J8R858L5p4i4qEA56IA5asG4KwK6KIA6aQA66oD5aYd4K8Q47AU9KYA9aEI9KwI+qYD+KYF/KYD+6YI/qYK/qYO/qoA/6wJ86YW8qMa/qYR/qcX/aQa/q4Q/qgc/7AU/7Md6aEl76ck7agu7aoy7ao27a4+5bUi8Kch/qEo/qkh/qsm/qwp/q0s/qUx/qc2/q8w/qs+/7Uj/7cp/7gr/rAz/rE1/rM6/7oz/749xL9C3qNI3qVK3qRQ3qZW3qdY4Kpb4Ktd4q1f7rBE/qxC/q5F/q9I8LZP/rdD/rJN/rlH/rtL8rtX9L9f/rVS/rhX/r5R47Bl5bRq57dt6bty6710/qpp/qlx/qt2/r1hxcBEx8JKycVSzMdZ1sFH18RO2cZV2shczsphycFz0sxq3Mlg3sxo1c9z2NJ6/8BD/8NM/8VU/sJZ4c9x7cF55dN998Ni/sZg/sFo/sVv/8pj/81r8cd//sl1/89w/sx4/s99/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy83dWC4NeJ4tiO6daF5tyW9MuC+NCF/tGB/9WD/tSG+tOI/9eI/tiM/9uU/92c696g/9+g7+Cm8eKq/+Cl/+Kr9ua1/+Sx+ue6/ui8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3d7fHX/urC/+7N/+/R//DV/vLa4eHh5eXl6enp7e3t9PTg/fXj//fo/vjs8fHx9fX1//ry+fn5//z4/v7+AAAAA7tHUwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaESURBVHhe3Z0LfBzHXcfv9LRV2ZJl2bGtB7TgpAFaCDblDa1NDJQ3R3gUAjQFysM8CqWFpjQ8WvNooMFASAslNVAIBIihxaaSZSuWH1Iopq6DapM0qWtJlkRKVtYRIlkZ9/+f/d/u7OtuZvZ/t7f5fj7JSbq9vfl6Z387uzs7U7hRA9FUUKFqUcOKVtZcUNmqUNWK1tKcUBljqWJFn25yqLBBEq3oQzmACqySYEUfyAdUZoVYK1o6N1CxfWKsaNFcQUWvELGixfIGlZ4IW9FC+YPK7xKyokXyCBlIgla0QD4hByRgRW/nFbIAVCt6M7eQBqBY0Xs5hkRUK3onz5CJYkVvRFmcmZpsKqZmFqhoEcjFs6I/h1gc7m0rNCGtPUPzVMQgZFPNanITraQp6T1DxVQhG7KiP6os99HHm5beJSqqgqvjWtGfVE43ZdUL0naSCusjdRKtxumDTc4YFddH+kgr+oNCTqRitKpYnaHPVKfY3rku83o6QUX2SLRabqePJNG2afjUXNld9vRm+mM2tIYjI9Gqnz4Rz0tG5mg5Yn4jvZMJm6gUHglWV2j5ONoG4w5/A/RuJpylQlQgK/rNI3lTdZ5YdRdxps8/8u7f/ONfufsdB6cd+D1LrV63SD6xVku0dIS242v4vjN95MD3lZBvkf9/J2plWQkjzcI4q2O0cJhtMh6c8z8tXRTuAq2rtFAWDMliK8RZxWda5xS+53z4+0kF+DZ6lVsrwySMVkGwoh89OmnhAH24oZwjilPpO+gVmBbiFC2YAW1uuX1irJZp2QDD8IYz/VMk4fLt9AocTPhYg4jsWFGreVpUoYitSOf3SYHw6h9wD7zfSgtnwIwsuEIhUgHnaFGfIp7JOL9EBnHcDQvEVtzGIHd5lajVLC3qUTwNf3XeSAIV1E1Vejss0UGLZ4CN1aPwR8c9QPkoUQH8GiySYTvXwgqPBhEpNSoA3K9o8Swwt8KDQVQqUP9KpfuyzUBjq47lmH0qwsMxFbeBGFtBg9h5M5XdJ7SpSo8LMUEfyAJTqy3whw9T0X2CUQFA22KQPpEFhlatWP++i4ruE4yKUulHoB3YSx/JAkOrUZCKNNEj9a/0HiHWMmxaGFq1wzniUSp5NT4mxAx9JBPMrI7BpvpBKrlPZFPdARVwiD6SCUZWLXD2cYRK7hOJCqyAYj19JhOMrLbBb/up5D5f+TlBvhorYLRJ3EiMrKCB/8LryMXjtfTq84VQAbfTR7LBxGod/PJJKrlHVKp0SYiVLBPQzGoAfvlbKrnH7fTq8/LnhRijj2SEiRUse51K7vEaelV4UojVDM+tEAOr4poQn6KSV+HLYVMlXWtrFAZWG+Dnf6GiV3g1vfrsBanlbPcqI6sd8PMvU9mJ+KgQW+gTmWFgNQ4/fw+VnYhGxfthU52lD2SHgRUs6lDZiWhU7Mb6l3FUAAZWi0JcpsIncQtIZXoKQhhYQXv9v6n0LpGouBWlsjxbrKBvVYQfp6n4kkhUyC3VFLfF9a1a4ccLVH5JOCpwn8rynoGCmdXHSQAJRwWmnzhVdBfOGLMaeJEMouy9hFIn3EUzxyAt5oV4lhyAYFRgMynje9wqBlYn4Oe3kEUwKnY9iVLLPbRg9hhYYTvwfyuNCyUqdj0hN9SZWj1NGoiBVWESfvmUq+VFxc4HL0una5m3/VRMrNZj34pn/4Z8SqU9rzz0tFQSqyNZt9KDmFgVNsvfnYv/9YEH3vfX555xjYQoj9a78hU7ujb2bdk2MDg8Mjo6MrR9c3f1f0Ujq8Jm6gmjMrOthd5lp7i+d9voxNTCCn2VytLpgZfQYlHMrArrcd/yWZ0cWEfv8FLs2jJ6ZkH2vKnCtRMbaPkQhlaFQvfxq/hl5YXJE9u769KS6LppfC7Gx5mWfBr/59DfhFjYEVcXja2QlnrVueLGoclAdQOV84fvP/Ab+3/mJ+hOzA/j/+542z0HHye38nDUy8qqPnQNTCq7rTN99P4D+79bmih8L70id33IFVveRmvwaBKrlr5xvwumM334wP7oTTLJ19Mr8YaPSa/ZLloP0QxWrVtOVzaSM33+3iQhRN1ULq+XXmvBJmjmVi39vtL5e6O3kQJ8J70GuEvWwzPq3pWx1YZxCgeodT9XZRsRMiqi/C5qzSvHmCyt2gepb5gzfb/aIy+RaP0jsJuluObvXNlZbZhwD0q6SkAoKhTuwL2r7DU2MrIqbnU7i0PFq7ErKSRuKuQfQWu5srUysWobuibXHNNltwqxUeHze6C1RM3sDKzaj8mEcKYfifSGqkpCVHig1ozbhmu4VcdxGeTOhV+kwuhStf5JsBK614MabNU+5jqd/0kqiT7JUeHxOKxaPvrWUKvWEbfuHdFPCI/am6pU+nFMDOxs2Uir7cu4umBvcV1qRAXx66CFl8QbZ9Urn5Jxjto41Y4K4j/hK7obZ7VOPiDqnLeoe4hO/UOwDk41yqo4jCHhXAj26jdAIypcsEnY0xirHtnei+kCqovupgKmhZhshFUb9hQXzuHaTfIk9KLC5SB8V1f9rfqwdeRcsNyhJJpRIcFefMfqbdUqn0tOUfkAg/oHQAwu19mqB69GOEfNGnxhtKNC8nrYWKGnR3mtiqP4+aqPyWhgtqlkXkSex2e0WjcLn3aORq5+mWESFZIPCVG5EuLBZ7UZG33p9ijEJCokf+AWOwCXVREfiHcu2LWPFEzrn9u+CMNk1X4FPhl+ms4Gs6iQwI4VhseqWx6kTE8MYzDfVLI3fRgWqy2wuzLUPouoQCAuwnBYYaA7f0ffkQrjqEDuc8utkt6q5RR8yPlt+opU2NS/2BBMbdWGj7U6P0vfkA6LqADw8cMQaa068ZQ35mESG+w2VekdbrlVUlp1Qfg5F1I2JwirqADYrbrLIPVPtPa0WEUFwG21ERpJPOEHWNY/9v2qFw9TDO0JF7uoAHitpNTv0KpTY72peJO9dw2kWA5TiG1UAPhQWwhrqx7cUu+iFafHNioARqsNvFL29a9U+kMquIKlVRdGOp+UfVQAD1PBFeys1uHBly0o0m0qtjZ7+yJIsUV6qqgAmM6vWmZBiuvgi6SICoDpXPgMSHE1k5BU9Y/L6jgsdJ7WyEKaqABYrPDZaIenle6SclPhlfYwxlY9sIjDcInCI11UlEpvc4sdwNSqE0e8sL7bFke6qHDHFwpjaNUyB1KMR9/U9S+2wWRq9ShIMR6ogJRRIe/LUfc8HzOrm+D9wKNmqUm9qfAGlhzYUMXIqgubtOluToVIGxVA2js9LfPcSZE6KgCwihlpj37wSLbCnYrtNFGSvv7JWyJp7jX2w5usbQqGqHCvMOENmQD6Vh14SsW6U3FsKrzKXk5xtxvHBuO58FyBISpkBE7ZW0Hzj/XsA2CIChkWx62tOuFIF3jUOz0c9U+2bbdaW2H9M++QWRWGqHDHzrTu8bMVpHhbSjybCsNi1bZ3Vhu01JnrH0tUyLC4YmuFx1+TvugasESFDItRSyt8IDo64FkqeOqfbFn0WVrhSRXv8ZcnKtw7B212VttBivVMkW1T4W511a7fLQ5j2ZxR4R6D7azG+A9VTFFBu5WN1bo1vWEsDeCqf3jNAgcEtbCagE3FeaUMYIoKb0BQc6su+NNhWgkTbJsKdyscENTcChuAnFdqGaNCPt+IjwEaW3XDXx6hlTDBFRXyzpWcJsTYahI2lX1/+zj46h9WQPlYmakVbqr7aR1MsEVF6UehAspR1kytcK9q2k0FFbAsH2w0tMIA5N1UfFEhK+CjspiGVnis4g1AvqiQTx24w/yZWXVCs4L3WMVY/7ACLts8WYstQN4zEMZN5SWgoVXrCvfJIuemegNUQBodx8gKz6t4+p4SnFGBbcAFKqiR1Tz3zSrO+ocnIZVB4U2s8L72AVoHC5z1D28xrlVGbzWxwpkQ/+gHGPmib+TjS2FTebNKGli1Qax/hv5hWNhJryw8ACX1ptQ1sMKBzP+Z1sHBN9MrD08LsUgFNbK6KsT10IjLqdhHryzgoPD+6EX6VtgETB5t1Jxvolcezgmx6k9NpW+Fz775IyKm5lvplYebYVMdd8uJ6FtdE+I5WgcHe+mVh8egnMpcH9pWeLBSB/FNCW9U4FD36qjI2lY4LuybaCUMsEZF6YNQuG5ZTBdtK+wuTOtggDcq9sCmmpSlJHStNsIPfBWQNyrkpgrMJqtrhQkYmvQgBbxRgXvVlLSpoGu1wJmAvFER3VS6Vuvh9RO0kvTwRsXO8F6lbYVtQLZDMG9UlD4KZVMDENC0moyZzMYW5qjAeQnCI/jrWbWsak1mowdvVJSegLPF8BRielY4n2Z4MhtbmKPiy2BTKS1AFz0rfAT9F2g1aeGNitJlIcqReWT1rGb4cp05Kv4CNtUOcvHRsmqBc/vIJGV2MEcFnoHEzOauZYXtdabdijkqcAanmJn3taxw6nGe9jpzVLwKNtVJMlHRsjrLdrTijQpsq5fjxvHXsloW4tO0onQwR8U5KN1NJBJAxwpnNGQ5C2GOCjxUhRqAhI4V9luPzGhoA29UYP1biZ+gQMcKj8F30qrSwBwVWP8SpvDUsYKweJ7WlAreqMCpgeLrn57VEk9Y8EYFHn/LnWQRRsMKHyVhOGNkjoqnoVT9JBFBwwqHt2G4a8AbFX8Pm8rthRCHhtUi/OfNEGUNb1Rgo2IheVYbDSscsuyHaG32sEYF7lSroXkpVDSsyhztJdao2Pd/UKzIJCIKGlZwdp/6FiNvVOCRKq5R66FhBSdXT9HqrGGNCjxTnKs6qY6GFZC2nzdrVGBSLFefyknP6l9phbZwRgVeKVurMTGfntVDtEZLOKMCr9TWnMFdzyrd4YozKmT8Ra6UhdGz+nlapx2cUfEElMbrLJKInlWqDgmcUfEfUP9ma88ppmX1Aq3TDsao+AeQWtCYcFDLKtUVTsaowCZtjUx30bJSJnU1hjEq/gqkylVafz5aVmkaTHxRgVIrCVMZhtCySnEmzBcVKLWqOS2ullWKZiBbVOA+tao7fXudrdiiwkhKz8q6qxlbVOBxSl+qzlZMUbEPJwVfibn3kYSWle0VJqao2PM/UIZy6DZ9VepqxRMVNz8HRVjSOk5VqKcVT1Tsgton5pOuZ8ZTx/2KJyr+DKWuRO5nV0fLyi7ZWaICj71iwnQeYy2rZ+grjOCIij0YfmKEyqqPlpVVm50hKm7BnFhNvJqejJaVzVkjQ1T8OW6opeQ5x5PRszLv75g+KvadQ6kpq0np9azMO1ukjopdWPvEMbv5zvWsjEMwdVT8JW6ospxS0gINqxWLG6gpo+LWJ1FqxuzQq6BhhXd6DC8IpowKGRMWge6hYYX3Gs3aTOmiwt1Qi3rn8vFoWM0uQBU0yvZUUSH3KDGefCNRAx2rIfifyY3hNFGx6zJKLemfIMaiY9WxZnbxzD4qdspjlDiRakMBOlYFnJ1Q/7aIdVTsOySd5tPsUS5aVviYnPajL9ZRgZ1doNk3aHfgDaBlJZ+p/Tf68lpYRsXup6XUKetjlIqeFQ7BdF2vg5ZdVOySaS7mDK64VEPPqjACr3pnWTZRQU5LsT0YbdC0asHRfj9ChaiGRVTsdp3Kg7XvS+miaVXohjqo0fXRPCpe5e5PK6OGlyaqomtVwEPx9ZrnWYZRsffQM+RkdRqViLYVTkQhnqtxg9gsKm75qFQS5WHO7YToW7ViP8HnqndrN4iKPe9zq55Y3MG3P1XQtyp0YJe656udk+hHxW63aQTnUP0MB90IBlaFTtS6ntzO1Y2KXY+5e5NYHbe51KKBiZU7a6G4mHRWohMV+26rKIm57WkbsYkYWRXa5MDnTvwTjrWjYucDlYonlo/XaTNJzKwKRXxwXYin4rKwelTsve2D8tQJWTm5qR57k4+hVaHQL+d/eOETEa8qUXHzW30jUT7ZV18lwNiq0IEHLvB6KtjSSIiKm287dKmyIwHzYz11VwLMrQqFPpoC4v8vPvQ6Knw0Kva84rYH//2yIiTKp7fp9GvhwMaqUNyGGS959pMfeegtb7rzzh+D/epzX/Z5n/+KL3nrew89dukZVQe4dmqH0c1CA1o7OiJZamUFXv2haSCeD3t4lKeO9bOcCoZp7R2amMWLlfCPNuENWiSxtALWj1ylBZJYmT051FcXoUKhaxinMVa4ql7tsLcCOreOz+EZSpDVpdkzJ4a2bOBthqu07Yj5B11Tuq2mspKs6+nfPjA4OLBj+039mzZ2ddatwVCh4/iqWzBn+sLhe3/rT3717fc8PO3A775WeqsG0zbm1g7n6AF32Oevkf9/J2p5lTBvVluXsUjO+QPeQK40sCyOieg9D50vq46zWCDniDI041fQq9xalftdubLahBvKORoYcNwfA3jaH+ciT1Z46cSZDk6N8VX0ChyEMwFaMkdW41CW8MxAX0evCE5sTQGcG6viaSiK82YyqKCOQX03LEDH/NxYnYKSOG8kgQpeVCA5tJLVLzIvQWC4cJx9ki7B5cRqEMoRHRVZiQoA9ytaPB9W8XOtqlEB3JezDGyH41Rkn4oMV/+wX9RcWOGszOH0C0UF8LgQE/SBPFjhSBQxg3KHNlVl1g0kB1atOCBjdFaCYFS440hXOjTkwGoEpKIzKIaiwp2At3Ju1/xW7SuxM3iG619lMhtJ81uNwqaKDgofjgo5o+EwfaT5rVrKsTM4RTYVTlLmXZxreiucl3k/ldzna+nVB3LdHxqs6a1mhHjBv0JM3F7a89IgXwwV0B/FrdmtOqEAkf6xr6VXhUtCrPhXt5rdCgcEjXSIuJ1effDhfKvRsbMBBwQN39v8BnpVeFKI1cqkB0CTWxX1BgTFwSHG6CNIk1vhJJ7hYSheTa8+ODbYstpno8mtdsD3hzrkxEQFjrgS6NnV5FZ4Yh/araJRgR3Fg2ODNbkVFC/UiTQaFbtBqqxEBdDkVou1Hyz/ApDyZxJxaXIraK8HHz+MRMWtKFU5W6zQ3FZF+PrAYw+RqJBbKjLgWXNbtcLXB8bODEcF7lPiNC3to2E1R4tmQNgqHBXvl1LRHhwaVvO0aAZgDUx+rNd9ljNuvL3QnXC0CmtVLh1mwXzgWY5gVGAzKRoUEq87SIWolWhUj5YY8Cjs9bMMRMXLZc/q5VCku7TJYqvEWFk82soFtgO98V2UqNglK584Gzz4VtiE76ncAKuwltoabjS43z/ltpm8qNhJXXaXt9JCYXDc6wBxVjS1YyZ0Yd+Kz/idffe98kHqhbx6LLFnR3i3uhFnJZL+TRoBXo6GyLj48Q/86XsPnfM6S62MxVc+pI+W8XCtwlpZtpkK/dQTRqV6l104fw4SbxU/sHaj6AoeU9euDIanpAiymRb0AKFYq5U69RzTZMMJ2c9ydfHKowMba/Xpx5tdQSpWEa2kAZsbR2urZmbhvf4giVaR2VWaFjxuB0GfBKu8aEWlFKsYrals9y0t2t3+20FQJ9FKrGSahDq4fe3DoA5ZxWmJ2a0ZtjJqUeyPnH9IpE01K2g8jfVn2IJPpnPzMbe3dBRpU7FK0ALK83OzTcXcfOQQ5ePK1LbKFSTjWb04tMjlxWVFKorVi0CLRAJW+dcij6BV3rXIAghY5VqLFCRBqxxrkYBLyCqvWlT6CmGrXHpRyX2iVrnzolKrxFnlyotKHCTeKjdeVNowSVZ50KKSxpBoBdCHmxMqYzzVrCS0kmaCSpbIjRufBfx2CZjxr72TAAAAAElFTkSuQmCC'
+
+
+plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEB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'
+plusfourblue = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQDBQUFBwgHCQkJDQ0NDxEPERERFRUVGRkZHh4eDAwmDg4sDxAuFBQuFhY2FxU4GxgzFyE0ISEhJiYmKSkpLS0tMDAwMjQyNDQ0OTk5Ojw5PT09KipNJzFFMTJRPTtcPkA+Qj9hQUFBREZDRUVFSUlJTU1NT1FPUE5QUVFRU1RTVlZWVlVYWVlZXFxaXV1dRkdqSUptUVF0U1N4WFl9YF5hYWFhY2RmZWVlaWlpbW1tcXFxdXVzdXV1eHl4fX19LCuAMjKXMzOYNDmROD2WOzyiPD2pPj+8PUOiXVyEQEanQUepQkirQECwRkyySE21Sk+5RVK1SFS3SVW7Sli/ZGOJZ2iMbGyUcnKXRkjOSUrERknQSEvWS0zcTlTDTVjBTFTXTFTZUFbHUFrFUFbfTU7iUFTjUlbsUljrUlP0VFX+U1jwWVzzWl74XmXuXWH0XGD4Y27bZnLbaXfcbHvccHHfYmvtYmX2ZWr1aGv0a3bpbHD1c3TrdH7qcHT0dXn2en72cIDedYDqeYPrf4ntfID3fID4gIJ/goKCg4OEgoSAhIOEhYWFh4iGiYmJi42KjY2LjY2NjIyQkZGRlJOUlJWSlZWVl5iXmJaZmZmZnZ2djo+1oaGhpaWlqampqqysra2tr7CvsLCxs7G0s7S1tLKztbW1ura7ubm5u726vbu9vLy8hofQiInRgoPug4zuhofwgoP5hozwh4j7i43yi5Hvi5Hyj5D5kZXzkpL9lpr1mZz2m574m6LunKPwnqH5pab9pqj9qKf+qKn+trbvtrb+v7/+vsC+wcHBxMTEx8nHysrKzMvLzc3Lzc3N0c/O0tLS09TT1NPU1dXS1dXV19jW29nX2dnZ3d3dzc7rzNnl1dby3d303Nz43+Hg3uD54eHh5OTj5eXl5+jn6Ofo6Onn6Ojo7e3t4+P95uj86Of96Oj98O/w8fHt8fHx8/Ty9PP09fX19/j29vj4+vf6+Pr3+fn5+vr8+v76+v38/fr9/f36/v7+AAAAAAAAOABVigAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABpySURBVHhe7Z0JfCvHXcdVIaGj5ZRs18JQwNgGYYwplIcPbPN6UI5wPMJVQgiBNq9xWwoh0KQkJCQfwBRjakwNNrYxBozB0JRSwkuaJnYfh12Ba8BgccYVRVL6qIKAqs/Rfh5z/Hf2mJndWWklS/68b94n8q52pflpjv3Pf/4zE7hxHnFUday1MFlIpAi5Kri5pYGkckhUleC2lqcMCbYiVFWBW9qCCiTajEBV2+STDp9fnKoMXNpWHELideyqynBdm2HLLpsquKgNAQEUqyq4oi0BCQSLKni/TQERGLMqeLdtARkIkyp4r40BIWZV8E5bA1IMVXC+zQExuqocnG5zClSNrgrOtj1UDaiCczwn65MXhgZbiqELE2tZSB4PkUNVHcIpGyeTsUCLEp2QCCOdSaoKzljJDgbhI1qTAXFXnakSvr0UhrtbltA8JNVCTlcFx2bK/XBrS9Mr6gvKVZV74b4Wp1sgK0NVwZGJdhElliVTNQr3tAHDkGQTElXbcEdbsAGJNjjEqjiPUjkON6iT3Aa2InCmaUQLkGwDrAr+NFiE6z2wArdqq3CiiczBVxsIVXXC5eokWH53wJkmEoevNhCpqqFWLcGt2hqcaCrr8OUMpOoI/mSMw8XqxFlWec9mHxiBL2ecBHgPYA9crM4i3Kmtw4nm0gnfbhDgq1UILlYmxn6YLjjTXIJcxvCqjuFadRbgTm0TTjSbA/h+Bq/qEC5VJsp+qm4402z24PsZvKoMXKoM6w9swYmmsw0JYNSvysiqFJxpOg1QNQv3naH16L+qCOsKnF3vxX9VM3CbtgcnzgDfVYWZxdwHZ84A31VNwV2eq6Of+K3KyKqz9N74rWoS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'
+plusfourgreen = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwgHCQcKCwsLDBYMCxgMDRsTEQ0NERkNFBQUEh0RER4bGBUXHBwcFiwWHSkcHygiIB8eJCQkIi4jKCYnLCwsJDEkLTosMS8yMD4vMTExMT0wODU2Ojo6Pz5AI0UjJkslJ00oKkskKU4pL1AmK1EqLlg1NEM0PkA+MVMmNFYsN1knN1kvOlsrM1syMFw6PV0yP2AsNWU0OWU3OGY8PG05NWRDOGhHOmtLQEA+Q2UrRGQ2S2s5THEvSnc0U3c2Q0NDSEdIS0tLT09QQ1JDR1dIT1FPUE5RUVBPVVVVVlZYW1tbR3FAQn5MQHZUVnZBW3xDYF5heHlEY2NjaGZoa2tra35rc3NzeHd1ent6ToE6YpE8Q4FORYJQSo5WTJFWT5dYT5hYUYVFU4dIVIxJW4xKV5BLWJRDWJRMWZlGWZlNUZxYWZ1QTqtQWqJNVKZTU6FYValUVqpYWKpVW6xbXapiXrBgYp9hfZB8Y6tcaa9bbLBdY61kY6xqbK1jY7FjZbJqaLJnbLRsbLJycq1xcrNidrJueLVnebZpfbhucbVzdLl0eLNwerl2e717fMF7dIiBe7OLfLqBgIJ/k456ha9yiLF1jLR8iL98kL1zlMB6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gg76BhbqRir6UkbqDlL2JoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+hcGGh8eLi8ODisOKjMiLjsOUksaNmsSCm8WKnsiMk8SblMqTm8WSmceem8mXmsqdmNCYnsygoMmPo8yVo8yaoc6hpNGjqdGjrNSrvsC+sNetsdextNm0vd28vd/Ewb/BwMy/wd+/w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbxOHEy+PL0+bS1OnT1uvY2OnW2+zb3OTg3uvg4+3e4fDe5OTk4u3i6Ofo6Onn6urq4/Dj6/Tq7fbw8O/w8PTt8fjv8/Pz9Pn09vn4+Pb3+vf6+Pn2/v7+AAAARX10/QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlESURBVHhe7Z0LlCRXWccbayOpaBvT0AkMtkl2zxgSTQCVoCQkzQBqM77i2A6Db3wlm8DauxsUCaxuRCUr4BMkY0sfHYGIPce2MSREMAFizCZZhfgY6dDSmwSXbHpi92qoRam1qu6/bj3u/apuVVf3dM/ZX87JTFfd2rn//u7ju999VO7UdiRSVc+cYnrIpAxaFR6eapBVAUKVgcemHgMZDiJVhSdmBGTaj0TVzNjJRbSXoKqDpDNFF5l3CauaOUMxQuYKqUKiGQQCGEFVSDGTQIJDQBXuzygQYeNXhbszC2RY+FTh3gwDIX5VuDPTQIqnCtdnHIhxVfVxecYZMDWuKlydeZgaqMI1kf76ytJiZapYXFpep0d+jhymqotLIfor+dyUoi8TwpzBJFOFK0F6FfwLU8qCXBdXJb29puHp6aWBrAbou6rw2Y+xgCenmrJsiEGrMsp4bsqZk8jqMFX45GNWRMllUaqqeGYGWESWfRCq2nhiJmgh0x5dWxV+9zCS91KFtouOKxNDHyDbHlJVDaRPQBOPmk1cmCB1/GkPqaoikqtTwJNpnh2ZPP60h0xVilq1hkfNdVyYKOv44xxLleADLiOxOt63tQWmyuWW8Mc5/ZwYASwhsTrcc9kSU+Xm8Nc9cmK1Suz/eaaaw5UJIxhGVNVDUnV4I9TChUkjRNFFVV0kVUbHg1tmqtwG/j5HVNVBUmW4qbbMJWkjA5zRVem8VCdvZjJiDKpW8dwWeo/Zq/JMtXWjl+xVcVNt4MIWkLkqjXvMWzjQzFzVCp5KXB2zJGtVnqm2MnqTtaqpMFViVc0+kDvjnqkqVmuIpP2JN/FJVfGggNwZWsZdx83inlNi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'
+plusfourred = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQECQcKCwsLCgoeDxEPGQkJFBQUFxQaFxgZGBUXHBwcFxkhJQwLJA4SJA8aLw8SKxELJhISJhEdIB8eLhkZOhwKNxMTKBQlLhYvMhgzJCQkKCYnKScoLCwsMyYnMS8yMTExODU2Ojo6Pz5APkA+RRcZVBweXx8gXyAgYiIeZiMidycnezAifi9CQEA+fVg8Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hdld6Y2NjaGZoa2trc3NzeHd1ent6fn6PgSsrhDMkjjAyky8ylz0nmTMyqDg3uDw8gjFEhjNIiDRJlDpUmDxXmz1Ztj1An0EpqEYquU4uvEA9mGhDpUFhrURmsEVpuElsyEA/wVAvylQx1lc25F45xkJDxEhc10dHw01w1Exg2U9h3Xxs5ExM709Q6VdD7FJe9U5S9lZL81FQ8VNc9VtX815Y/lRU/VVY/l1T/Vpa41Bg719u9Vdg81hj8F5s7mZe+GRY/nhW7Wxj7mNy7HFo7Hlx/Wdn/25w/npo/HZ1i2TD3mSF3muK7nCB4XWT4nqVgIJ/3oV14ol7/Yhq/opz/pN6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+gpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+0JeX442A5oOb6Ied6Iuf5pOI7JyT+omH/ZqG/pWW+5yb6o6g7ZOj8Jel8pyn8p2o7qGZ/qGM+aWa86ei9aGq9Kmk9q2q/aCg+Kat/qyi+ayt/q2w/rKr/bSz/ra7/Lm3/by8wb/Bw8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzb3t/+3+Hg6NnP7t3V/cPC/8DJ/snK/d7M8N7W/dPT/tfZ/tjX/Nrb7dTj89rl+eLa5OTk5+jn6Ofo6Onn6urq9+Li++Xk/ebo/ejm/enp8O/w+fPs8/Pz8fL+9fj09vj4/PPz/PX5+vr2/v7+AAAAAAAAAAAAAAAAAAAAHYHLzAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABlASURBVHhe7Z17lCTVXcfbrCVTxg7xgAmr1qHDWAY87h616ajNYKcnoyjPqDFqiMoGMUIWJwkzm5cuhJBgYghgOm366PjoPrYddZVlMaKJq4kGxeCYTptWdwWJwJZLM+yGMpDtf9aqur97q+re+6u6VV39mrMfOGe7q27N3O/87uN3f/dRudPbkUhV/eEM04dMysBVwcMzDWRVAFFlw2Mzjw0ZDiNVBU/MCZDpIBJVc2MnimgvQVUXks4VPcg8hVc1d4YicObiVEGiOQQEEMKqIMVcAhI8Qqrg/pwCIlyCquDu3AIyHAKq4N4cA0KCquDOXANSfFVwfc4BMVSVBZfnnAFRQ1XB1bmHqAFVcE3Eaq1UlsozxVJluYWP/Dw5RFUPLnFYK/ncjKIvI8K8wSRRBVfC9MvwE2aUklwXUyW9vaHB07NLA7IawqKq4HsQuwRPzjRF2RADV2UX4bkZZ1Eiq0tUwbcA8yJKLgtTVYVn5oAlyHIARFUHnpgL2pBpn56rCj772Ml7KaND0eHKxNAHkG0fqaoGpE9AEx4dNuHCBKnDr/aRqipAcnUMeDLNsyOTh1/tI1OVolZtwKPDFlyYKC345QxHleADLkNidfy/1hRMlctV4JczrJwYATQhsTrMc5mKqXKL8Nt9cmK1Suz/+aZahCsTRjCMqKoPSdVhjVAbLkwaIYouqupBUmV0eHBqpsptwu9niKq6kFQZZqqpuSQdyABjdFU6K9XJm5mMGIOqGjw3Re8xe1W+qaY3esleFTPVJlyYApmr0pjHPMWBZuaqVuCpxNUxS7JW5ZtqmtGbrFXNhKkSq2pagNwZ901VdlpDSGpNvIlPqooFBeTO0DLc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'
+plusfouryellow = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgQJBwgHCgQCCQcKDAgACwsLCgoeDxEPFAoFHBMBFBQUFxQaGBUXHBwcFxkhIRUCJBkEIxkNKxsCLB8MJhwTIB8eKB8aNhwHLiQOLyQQOCUANisUJCQkKyQlKCcoLCwsMiQnMC0vMS8yMTExODU2Ojo6Pz5APkA+QiUGSjIBWTsAUjceSDojQEA+ZkQCdUoCe1EBflYbZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2tqdmdqc3NzeHd1ent6fn6PhVcBhFsdiF4fmFwKhl0giF4gmGUBjWEjkmcomWsqp2YKrXQBtmsOvW8Qt3oApXMvpnQwrXgysHs0gm1AynYQ134Ri3ewv4EAuIE1gIJ/t41rwoMBxIYe1YgG24AS2pIB1JAe2ZQcw4g23bU054cR65gD5ZsX4pkY654T9ZsH7qMA7aAS764X7q8Y7bAe9KQA8aIO86sM/KUB/qYM/qkA/a0L9KYU86YY8K0S/qYR/q4R/qga/bIY76gq76My7qkw7LMl6bg48Kcj/qMv/qol/qwp/qc2/rYl/rg03qBH3qJM36dV3rpA7q9B4atd4r5M5L9Q/q1G/bNK/rVU4q1h5LFl57Vr6Ldu6blv671z/b5j48BP5cFV+8FK/cZY68hn7cB278N578xw/cNr/stj/Mtq8cV88c508sh+/sdy/cx0/c15/tBr+NF6goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+goJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7vb7Bv7/+vsC+wb/B9cuB+M+E9tOC+NKE+9WI+9iH/diL/dqT/eGn/ea3w8PDx8nHycnGysrK0c/O09PT19jW29nX3Nzc3t/+3+Hg7N/Z7OnI7eLU7uLY++nI8+XZ9e7T9erZ/OzT+u7Z9/DW+vDV/fLb/Pje5OTk5+jn6Ofo6Onn6urq8O/w/fXl8/Pz8fL+9fj09vj4+/X1+vf6/Pr1/v7+AAAAeSzGFgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkISURBVHhe7Z17lCTVXcc7Z0MJW0nL48ghYpn2ZKyTTdRBbSZ6OsOknUzAXVazCEoE8ahIlGDccExkMyDqRkN8gM9FwAdhYGMCEqP06djqGLu1bZ/Bw7JDOi2tEjcEsmNl004Z4vRaVfd3b1Xde39Vt6qrHzVnP/vHdlfd7rnf/t3H7/7uowqndyKRqvrDGaYPmZSBq4IPzzSQVQFElQ0fm3lsyHAYqSr4RE6ATAeRqMqNnSiivQRVXUiaK3qQeQqvKneGInDm4lRBohwCAghhVZAil4AEj5AquJ9TQIRLUBXczS0gwyGgCu7lGBASVAV3cg1I8VXB9ZwDYqgqCy7nnAFRQ1XB1dxD1IAquCZitVaWFiszxeLScgsf+XlyiKoeXOKwVoqFGUVfRoR5g0miCq6E6VfgG2aUBbkupkp6e12DT88uDchqCIuqgvdB7AX45ExTlg0xcFV2GT4348xJZHWJKngXIC+i5LIwVVX4TA5YhCwHQFR14BO5oA2Z9um5quC1j528lzI6FB2uTAx9ANn2kapqQPoENOGjwyZcmCB1+NM+UlUlSK6OAZ9M89mRKcKf9pGpSlGr1uGjwxZcmCgt+OMMR5XgAy5DYnX8X2sKpioUluCPM6yCGAE0IbE6zHOZiqkKc/DXfQpitUrs//mmmoMrE0YwjKiqD0nVYY1QGy5MGiGKLqrqQVJldPjg1ExV2IC/zxBVdSGpMsxUU3NJOpABxuiqdFaqkzczGTEGVTX43BS9x+xV+aaa3ugle1XMVBtwYQpkrkpjHvMUB5qZq1qBTyWujlmStSrfVNOM3mStaiZMlVhV0wLkzrhvqorTGkJSa+JNfFJVLCggd4aW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'
+
+
+bluebutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAE5a71VV/kZq1ICN7pal7QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJIhjsUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC'
+greenbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAGmCwCqAAyjKU/AWXHLfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFeD53sAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEgaP//8lYoLVgcomJ3T4Y59EYJrtGKKldIAdkKWVzEP1ycaDumsVBVV7xoC4Wc3gaOlXWNQe5lLSRNYo4vENMJMp0YBQqGQ6UopRRV3eQPACQ1YGLMdtiBzAGw22xAxljBEngGD1IjANbVS8roWNwkM9xm89xnxhHxD/4mv0qYm8POaMiztrW/Oc35ZwZgG2dsw+urWWGg4y7zFSoA/JNRGEO977sBmKOiDsOQ06a/PeuNpBb4zNkLeXq8Ke1A1yYxppnbkkqAAAAAElFTkSuQmCC'
+redbutton = b'iVBORw0KGgoAAAANSUhEUgAAAGMAAAAnCAMAAAAsLAbdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAALhqYuVaWP5VVeSNi+KlogAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXdpGwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAAzElEQVRYR+2X0Q6EIAwEEej/fzIWaC2YXGJy3T4Y59EYJrtGKKndIAdkKWVzEB25OFB3zeKgKq94UBeLOTwNnSrrmoNcStrIGkUc3iEmEmU6MAqVDAdKUcqoqztIHgDI6sDFmG2xAxiD4bbYgYwxgiRwjB4kxoGtqpeV0DE4yOd4zOd4Towj4h98zX4VsbeHnFERZ21r/vObcs0MwLau2QfX1jLDQcZdZirUAfkmojCHe192AzFHxB2HISdN/nlXG8it8T9kLeXu8Ke1E2qb0ylAVTgZAAAAAElFTkSuQmCC'
+
+
+blank = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAFbSURBVHhe7c8BDQAwEMSg+Td908GnOODtolaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5WjlaOVo5Wjour7QMC20VI3QCuyAAAAABJRU5ErkJggg=='
+
+plusfour = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAwQKBwgHCgQDCAcJDAgACwsLBwgZDxEPFggGGxMAFBQUFxQaFxgZGBUXHBwcDQ0qDw8yEQ8uFxkhExQ8JQsNLw8SKBgEIB8eNxMTOCUAJCQkKCYnKScoLCwsMigpMS8yMTExODU2Ojo6FxVEHB5XICBfPz5AJiZvJiZ0PkA+RRcZVBweXx8gQSsASjIBWTsAXyAgZyEidycnQEA+aUcAcksAe1EBZFk4Q0NDSEdIS0tLT09QT1FPUE5RUVBPVVVVVlZYW1tbYF5hY2NjaGZoa2trc3NzeHd1ent6LSyHMC2SMTSaOjipOzuzPkDAQD+8VliDfn6PQ0LISEjcTU3rT1T4UE7sVFX+XWH+YF78aWnkZGT9Z2n7a2v+d3f9TqtQValUXq5gXrBgYK1eY65kaLNobrZwdrp2fMF7gSsrjjAyky8ymTMyqDg3uDw8tj1AhFcAmGUBvEA9p24ArXQBt3oAgm1AyEA/xkJD10dH5ExM709Q9U5S91JO/lRU/Wdn/25w/HZ1gX/+v4EAgIJ/woMB0Y0A2pIB6poA7qMA/qkA/q4R/bIY/rYl/ro0/YB9/r5B/cJK/cZY/stl/s5y/tBr/dF5goKCh4iGi4uLjIyQkI+Rk5OTl5iXmZeWmJaZm5ubnZ+ggr+CpoaGoJ+eoaKeoqKiq6urr7CvsK+wtLS0ura7u7u7hIT+iYf+ion8lpX9oZ/+vb7Bp6j8sq//tbP7ubX9vLv+icSJj8aRmMuYmNCYoM+gp9OnvsC+sNetu9y7vd/E0JeX/YmJ/ZGP/Zua/aOi/q2w/bu7wb/Bwd+//NeH/duV/eGn/ea3w8PDx8nHycnGysrKw97C0c/O09PT19jW29nX3NzbyMn90tP819j729v9xuLG1+rX3+Hg/cTF/djY4N/74PDf/evG/u/R/fLa5OTk5Ovk6Ofo6Onn6urq5eT+5uj76Of76+v+6PPn7fbw7vD+/eno8e/3/PXm8/Pz8vP99Pn09vn5/PTz+vb6+/r1/v7+AAAADa/O5QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABkUSURBVHhe7Z1/kCTlWceHutBh6ehQBak76MokaxM1IUELJDqMWsOymc2eIf4gKEYDOZXLJQokaFBAsxopA7kAGrCYTDKlq8aZchwiBiNHDIpSKprjVoeMGfDuvLPwOpdBOT22uSM7Z3e/z/t29/u+T/fbPT2/tu5zf9xM9zs773ee98fzPu+Pzp3ajESq6g2mmB5kUgauCj481UBWBRBVNnxs6rEhw2GkquATMwJkOohE1czYiSLaS1DVgaQzRRcyT+FVzZyhCJy5OFWQaAYBAYSwKkgxk4AEj5AquD+jgAiXoCq4O7OADIeAKrg3w4CQoCq4M9OAFF8VXJ9xQAxVZcHlGadP1FBVcHXmIWpAFVwTsZrLiwvlqWJhcamJj/w8OURVFy5xWMv53JSiLyHCvMEkUQVXwvTK8BemlJJcF1Mlvb2qwaenlzpkNYRFVcH7IHYJPjnVFGVDDFyVXYTPTTnzElkdogreBZgVUXJZmKoKfGYGWIAsB0BUteETM0ELMu3TdVXBax87eS9ltCk6XBkbeh+y7SNVVYf0CWjARwcNuDBGavDVPlJVBUiujgGfTPPZocnDV/vIVKWoVavw0UETLoyVJnw5w1El+IBLkFgd/9eagKlyuUX4coaVEyOAJiRWh3kuEzFVbh6+3ScnVqvE/p9vqnm4MmYEw4iqepBUHdYIteDCuBGi6KKqLiRVRocPTsxUuTX4foaoqgNJlWGmmphL0oYMMIZXpbNSnbyZyYgRqKrC5yboPWavyjfV5EYv2atiplqDCxMgc1Ua85gnONDMXNUyfCpxdcySrFX5pppk9CZrVVNhqsSqGhYgd8Z9U5Wd1hCSWmNv4pOqYkEBuTO0BHc9N4t5Tol9rmHJVpXG5ofc4DVz3WdcVQVuEh2bxVbMVAvuu01iK2YqMiTbJLYKm2qT2IoFQWD0vDlsxWa9Fsn7qbfVqj0g/4KQKwb5Q4GwvQUXpt5WLMAswlQxU9EJlKm3lYIqwVSbwlYs5MvmujaBrcrwdtBnQdFNYCtmKj8qP/u2KsG7gKk2ga1YDHjZe+sx9bZ61AbgmtNZUbzZVWYqO68x2NRc13vrphsTiqoYiG/BwmURjHEq67Qql9OqOE6rGpLTqlxOq+KYYlWrPSCcxyW4GsJfPO69HV6Vput5Bz22Q0+qKgnZ+IF5s1ypNtrd4Joru10r0xGQjFGqGs4P1IvLq2EtHP32EraebSptpRWjFqgHsFflxXrabKWZSw0lQZQ12XL0qbJVsY7sDojEEqdqp8ZWWrkhrD5SRVhpPx22yi+yfjAVPc5cU2CrwnIGW5LrIXON1FYdIGLtrVFN1DbgrAVljVJVPMXhCl6IoKwJqtIqGZkJCMiamKpCPXWTh9Fhsiakqix8bxYwa01Clb40qq2gq/AN41elLWde9HxgmdHYVS2Oyk4eFvHix6yqnG2zJ0K6xrGqMoW1y9njlcExqjKE7RujwJuTGZuqPNsQM2Lcqc5xqRplwxfGdaXHo6qQZjSYFmdUMhZVbIHnWGiORVVh3Cc65cegamlsNYpSG7kqA+mijlrdzr/+C4wqMbq9iHAgTnfUqipyQ/1bbcGM33GrGWallcbS2khVIYbqfdrUy8v1Rhz1SumsVMMwc5SqyvIMWYa+2FEqWnZ/NS/+7vEsjVAV0p73coZ6tMKu6yxSpU5jZKo0xOtrnzufxG+3y/6UmTK9UanKI53UN8rGf8BLNapKM34cI1JlYmPDli7uko+kpkWsNsIYxW7NXG4Ba7j6C/MJXcKauP88HoWdtclV4ebo6aHy9PL/vSjy8jfhrseiv55cnRGo0iKq95oWGGbt/+JD110r8N7rH34OEjj0iynawBGoMqKK2ILv6r74yPWgQ+C6R1+GRINWPo3Dn7kqI7LAaKxn3v8QSJBx3bOQyqlWaYZmWauKFtXU6GkKJ1FDeTwCxrLK0hOW4shYlRHtCS3moc19OVrUtde9QNJ1CmyfWhKyVRVtqcFgmwG//COQe4zrXyTp2ml6q4z7qxhLDboarA9/QdL2hXgIVNWocZORpao4Sw2q9Jd/9ich9xgPk3plm6UUvVWmquIs5UZ/4MXDkHmUvyTp+ikDOdmpirXUYK0AO7T+M6atuPa6fycJa9tSTbHamXm38ZYaNHTI47M/DbnHoNXKTDRqYWQ2Eom3lDuogESPQuZRHibpBmcVN+BVItYyUqUpeABW2STt+stx1eo9UK3aacZWDs2MVAl/RsJaHnrU/46tVvtJwrKWql0f1LNRpTQSbNA8PguZR7mepOsbBfIiKdlEY4QTuOxOq17lWDaLUPWjCuA1V79r+/YfJZ9Y1ObJC556ox3ZiixkoQqqC8NulwtGYKUKpQLNJF4Ar7nqwnPPgdQRaLpRivKkihmoynNteqes6cutnncGRIAuq/ogQeRd553xumrbso5+3bL6favvvDp6tG8578J0amXNiCj1heFVaZyDvJYzqrLRQy0PvRXWrv/49i2FPyBJYrHrekQLlUFEOhwssRu5BWEc4GGYUBd+E1Rw/MQPJVldYtfkZ9u62MPPHnA9yqpekWetS0/0eAFU8Hznqz4d75742EYeM1ZvaFVs6ymhZ5pI1qo0SPNFUMHxw69GwvIYZVqiBb4wrCo6CqSsovFjUwcb/hnI4Ph2f2+4GgvY1NigMawq7g9blxeRqmHn6S5Hebt+9TlCpxdD2ZDXX3dtwnCq+KBCVwu2t+uHDz1F+aM5qIDPvRd0hHln6CTDYwcPPMFz4MDBY3DbQy9gJdYcTpXg0DS+xW8Rv3noyY/9+grlElrAHgEZHG8KOP0nntiz8+d2iLx/zwFI4dAVPRrKluFUCUWgaDLf/fCTvqSVldvPL5LLL8qr1bvPWWCtzIFdPwsyBHb+LaRxt5Bj8Xcnv8OoEkff/u93KKhpZeVDr/0Mub5fHoe5mu2zPvEEqslhJyuEJo0WCKwOpUp0qOs6zdvh3wA5wI3Uroi//qYCtfsTN4AAOU9AsrbBjt7hWRxKlThQLNEY+/GwpVZWLs1DtfkLkMFxXhnuH4wWtWMXSTao4/PF88OokgxTWbP0JIih3L5t4SXvxkufBxkcZzhF1xvM74LcY+zx/oxbrXB/aQhV4vm/jl8LpeIwb6pfyX2O3PkfUMFxlQ4TQAcg8yhfIums0pvJCxE3u6lVSTyBCnUsngIxjEtfD9UGK4C0R/0ryDwK1Kt2Ho1ouMeup1Ul+aO2CRNor/AFcOV8Wm3kjsU19MyF9ZhateMGaAM/qwu9CsU9NimlKtkEYNuApv7wx0AM5aNbKifJLZDB8U568nlsAdxzwkvXL2OeGdnAm1KVbHxdo9EWrq9aWbmZVpvnQAbHG2l7+jhkHuVxks7KoyvZ3MYipSpp7AeapQ2xWl1E3es/Bxkc59EedQ9kHgVcpp78KS8u3rmS6VQJn3LoFUvk9zsuVKvc5d6Nwcn3gIwwP/Lqt5P7B6Pb9fft2HWQJFw2ZDnw8M5NSqUKfLowbR1+P6ELvpH+sohjsf2MfyL3/zmusXjsf0lCA69W3oEvqVRJ258qXeQjFMC3al8ld+T++jVvhAJ94kuQeRRo1zsaOgFEMptGleTpKk6zVKITaGK7voXcGHz+2ndftf3C88JceN4ZMEw7FudY7KQFkE6uiJAjhtKokg7FLZ0uWecL4G1z4Mnv/6ntZ8CfCNMiMx8Hd0LuMXate+kGBT4E6UP2eqdQJZ9V79LKcxzEMD64hfyy1o+dmy83e8LcTZ1GFON7K5LO1iTuGgHOY0yuyj+oN0SFtt7/CGIov/YW0mX3r8wvCt/m0C9B1T+pWq1WQ3GEEDWSx+SqEAdMvxzUciOrldu2esbt/YDxOShAYb5Gi+6JuAK4A9ylBTwcBaf3J1aVl3fqLQ3UHgYxjJvmvKG4qbXAa+Ko07ieagHsFthJXTx9yGRiVYipKjoUwH8AMYwbPXeoocur42Dw/TTWEetYPEPSNfOoY0G3WydWhbQ+rFni2/U73uJWG7tEg5wC+hVg/dgCCAW4hhdAenp6UlXSvspt18HfEByL2+fcatNEx0PdV0GPegzyjvJ+km797XzAmGGn3VmLDGtq2u+TF4K/fqNXbeq5r5H7Hs/vfeB+yvd9K1SrWH/9y16yk18tLGKq2KNmEqrCOopyDorH34MYxlvdatNfMPusnzrywD27fc42YNFcnGOxAxyLFr4UnB3fn1AVMm/ZKUDJPM4PGFfm3JXFHYNtGNnYC3IIt26BAhgXXNrxAdKun6ig65H9BwolU+U/KyRM8zUgV4jD3OG5Ik22Fnf9AZADfG/uC+TG43GqIA7z0rwf5eXwTwRNpgpzlVmzdAjEMC71qtUCbb3Xf/eTIAf4LhoBU3Us+qi/ztqKpKqQ1rm/ME9+v1eEajVXcO7YBv19nwYxlLsu+B5y41hcb7UThsFNFh/mCTzTL5EqbmKRwarN8d8GMZSbiS/MPGIQw7hlDnrUeH8d3KUii13zBI5mSqRKSAy06B3BXbo096fO5Voe5i/CLYXD2zRoO2PbdahWNvrTBh+EkUQVuv5mkVYbwV26KOdGogsFqHb3gxjKXRdfQdp15QJYDy7zDxE8bSqJKsz9sgu02vDt+h3nux0cm0A7AmIYd54NE0DH4gogneIp60i7zs7kdkmiCvPk/HWkIIZx22vdfqxKJ9CEAvgRr4A6HITMo9C5EIMd8sQROD04kSp0AFqn1UZo12+eu9K5XKKPGeEL4O7LaI+qGt5c05FpKzu0+TOBKsw/HczTvAlxmJvmvs12CiiNX/8OiKHcvXXhG+TOH0LmUcBdWsLcpfCRTwlUIQXacVSg2ggRi5U7LnJ8rKYOBfT5e0EN5U7t98gdVX+9X/IfsBomfKCmuirs7/m72YRAoGOsXKFRoY6HUK0uK8BQU7kAYhssuGd4qqvCxrJOtYFcC46FY6xLcvpZ4D6sC9VqaxHaTtWIxSo2b8o9AFldFfysIqxZEvx1l1+coxXy+ftADIP1qJB3HBjGYMNg/gHIyqqwFnXQotVG8NcJv7AFvmMfaGHcQnvUZyDvKBCHsUowQcERbgAdlFWxlRQ8S3R8LKlWDh/9YB6rVhe8Bu6o+utrek2qKtRXuSirwgagdhH6sXWhXfe4/fzyUXKfr1Yfn4MCGO9YfJ0krMuXBFrCGl9VVRoyXnT8dRoIlFarldupo7UOYhi3nPnH5M6BOFWPQWNRoqusw8ADdAKoqsI85UFD+2vyQojDEC6lrfdXQAzjMuqCfRkyjwLtuq1L4zCSkyRVVWFDtUFVh99PXq1WLirCDvVPgRjKJy4Gl0N52qpH48NhJEfDqqrCPFvbLMMwWF6tVrZcCa0yN7TffSuJv8fOmzqeLbhLFem8qezBpIqq0Ha9Q3eVCuFNwofo/IXYrtO2U3U5wkCHOEIY2eN+FVWh8foqneDBCuA2uP8giKHc/d1vJnlULoAtqX8tfd65oirUXy+WoFpJ3CWXnElubwQjmy4f3wpLJtZjh8FQAN8hZtbxd6XHzyiqQsOl2iKcBSCvVjflPktuP81Xq9/aAgu2YmeD6TIzk8Y4gpAn2PEoqpIVaJcOm/aT91aX0MojtOu30B41ThUd2/cMMHsQ5Hn7aqpky5Y8yqy3l9eri+iqF8Ffv4D2qDH16meg/Dn+uhg3kZc/VVVoH+wP+6WuBYlbOBzh/fVP5N5B7ji+rcy1eB/8TyuV60HAiwDY037VVGGNRTOwS07mW/z8FohoPM03Fh/e9ifkjmOsiDHjHiaqa4pTZ+hJzmqqhFRAJTjqOvQkb65fvQSK7gbfru+++A2+S3fibz4gM9cNux57HOqUQ0ucN4WjRSWoqcIaCzO4+nXj+OFDT/m7DRz+7vWw7OoIH4fZfeZ3BD55UrbX4JkDB4Ne36o4IYiVP0VVWMiia6C9s0eLRvqf5wvgnUm3olt0VYYPPbJXgpIqrLFYM5BpYqABBXTjeRDD+IjatlWfDl3uyRBHVT5KqrActPJo4+jSX6CtNzcV5zqBqLcixTbpTjtG1IPplVRBQybQzkduVLd0mADa4AOBjqor/IYgnn4lz5uqCgKkKKnCZozscmRBatBIteCv7757a5617PF0yvpqsOVwQJwKQEkVapB2TpfuNyWwc7KEAuhWrG1YCeCx6wb9eRj+UexSlFTBC5GjnzlbK9ZafRmWladxLr4FdLjrbWfqP1hfg7QoVq+1nNfoanhGn4tq8qioQoeMDp3LDbQvpBsshDiMxy9dsHUO0kWgGUapLRQH2UgxiIoqdIrHxWo3YHc8T0GHciMEAgl33XrLhwm/TD6wqJvL5JXPamtNLOJiUIlDRVV0V4ti0AVbgmPBs4+ka6Ozo2FgaWMEKqrQsG0kbQ0KoOBY8Nx3hCRcRqfnQwSntRFUVCV0boAaHUDv5YfBPA+QMa5tCq2CjG508+ehokqtXPCUqU8s+Os8XyHpbGx2NEQ/6hllFBVVaNAiCsuk8Xc+vMlzz9MkoVq1inKUGCqqlEo7D1vnKMyb8tz3XyRhicauo8BHH0FUVKmUdoEqLYBIu+5zP0k3kG8/CaNkKTVV8H8ienQCTZw35aAFsIHvPmKoWUpJFWxdSQabAIqvVtCuL/KHmogoWkpJFbYiIZI2Hb4I0SWeB0m6wTw6RUZRtdToVLEe9UhMY3EfTJl08tHj6gSWGpmq/utojyqGl0Lc+wpJNqhiB09T1C01MlWBgy72RRnrfqhUzgA0amTgkMBSI1NFNx46xWtjLyrrngepqEGnEO1YJLHUyFS9IXA89sa+B2Qtxr2f2rvPn+Ro0mGLlH4iS41MVXgab+OVdRlw16MedVpvT8X3CzIaVc0zE4b7evgqdddBhMwqMxpVjaRBTHa4pYT4QaLAaFQlPQC/Z+BDq9jhvAQFVSn8wFYu0Tm1vfl5IR9APy7wIkVFVQpjmegOAQktAz0GqxsTIkNQUZViLNzStLqF138fu99dys9jopqJ2wmCiiqVgTdHv17QzUoVHuKCU6+W8yYa/o2MpUehoioyHojRrpgKvUy+WKxhBVzyjGdVVFRp8CIZ/V4XHo0UQddCWxXhAc8JUFGFzomMECuZ48ehpCphl5oBDTx4r4KSKnQRyYjoy54GnwQlVfgyppHQHM5QDmqqFGJamdGXL7hKhJqqqGFCxjTTeRNhFFWl6IhTsZbK7RNQVIUc1ZExvWFbCYqiKuxUgSyx0ow55KiqQtdcZIW9PIQvwaOsSh9tGawP3ZoHUVaFr3zMgGbScEsM6qpGVwYb4e17GZBAFbZTdzis5UzLHiGBqlHIWsuqLQ+TRFXWsuzVwIEAmZJIVaayeksjKHpAMlWZybJbEaPCZQhqpB9kJVSViwzyK9JvlCN7XBZxSt3eJ1Xl+E7DdcdWPTbIMglVOfR5A/F0qypd00RU5XLoMU9R2O0lxaHThFTl9OUkYXTnT6wuJvAfJqXKoSx8Uk53tZLUIZqgqlyuUOeXmIfprTWWzDTDi4mqctCLy02uLFqdZn15sVgYooudtCoPvWCaxaJpzs8XhtHiordcWNex5r3lCI+Y83C1FZqRzEBVhqiEU8OnPrCNOaFtw9OlCj3vJEB4mpidETXFqk7binDaViFO22pITtuKMAu2ys27sPF22XtLYF2z9wgADeaV/bUgNlzouKqnTJWHzGNicX5yol7EEkn30NtZUcVsQg5KjVDl7g2cEVUsHA6nem8OW7G1EXCm7aawFVsZ2ofx2qawFTMVPftrM9hKMNWmsBW7wBahbQJbsdUegZOijTz5x+514IK30XcWVImm8pkFP5DAqWJH+wiHHzrMhB/owaliWQz7tYRZtVWkqWbWVmyuQmaqWbUVW/RrS+ceZtRWzFT86a+E2bSVvz5bPk00O7bSKM5rNmErN1U4MWMaVQVgpiAthypTroqZKuJIKQnTrcqPOSUy1ZSrYhuD0NPn5Ey1qrSmmm5VbItUQlNNtSrfVElXcU2zKmaq6OO/JCiokpw+PRb8pw0mXnDHvBOKqMp/WNZ4YYd4sAerKSNsrRJVDSDpmPFNlXxZrrAiSaIq88W+SrBNX8lN5TczlNwpYcWLN7cybvyHvSXfOiJslOjnTgnGStwEZQEzlcIBYDzCXuVTElXI0GakDGMq8Zl+UlWp9+2mh+3jD40G1RDPZZOqwg6hHh1a1wKSbxqmz6UK4KoSN9Im9cMminhYVc9VJRpL9hyIaUWyB7OGqFI6324qkJ3AW8u7qiR7uWdFliFZX9o75dlKYqyBNao9HZkiEzWogCrZCmjbf3jq1MKejBuk7wjyVMmM5XQdU26ugjCs8qgyVchy9RFtl8qEklyTZypQJTeWQ79dLZuwtGhqMEtVfwkyj1OrmCpU1qzR8dRQVbJ6N4PYi54aqmqTGMsrfwFVm0JWE7T4qjaBLFKpHAKqMtyaORkcVwkIqJp1Wb6okCqZmzs7dK8EFQ5hVTNct9qgwSOkygHSzBw1yD+BV4W5hNMN5J0hqOrOoLkg6z6CKhdIPCOs6ZBtH6mqWdLVzkOWgyCqZqR+QV4FUFUu8NkpBTIpI1IVEPX5aeTUqf8HHRhC11FdSQQAAAAASUVORK5CYII='
+
+wild = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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'
+
+
+b0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sbH/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFxsbGx8fHyMjIycnJy8vLzMzMzs7Oz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra3d3d3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4uLi4+Pj5OTk5eXl5+fn6Ojo6enp6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9PT09fX19/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAV9lm+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGoSURBVHhe7Z3nf9vGGYBNUpRESZa1t+RYw5qWrdnldKRO26TWHrakNt21ZI2kaTSahLRp/uEsSLw4HHAD7x1ADP/4fLF4OMh4BBC337tX/hiRWX36QynGfP9zuEwOQqu/wcmx5iu4WDcCqw9wWux5DxfshGsFZyQEuGgajlVi7pPFO7hwG8YqEd8nN3+Gi7dwWyXuRpm4vl4uK8iUQEDAxGH1AnIkkl+CRAXa6ks4nlBegIYBZfUFHE0sn4EIbfUpHEswYEJbwZFEAyq2FaQnmw8gY1l9B+kJ5xvTBqyeQ2riMXXACtIYbvYWhnu6OmNFV8/Ik/0buECGqo5p9Q9IcrE/nE7FlPToIVykiz/ZVpDiZP8B/IaY0vkKLtQJsfo3JNDcTcLJ8SU9k4eLpfmrZQWfac7vw6mxpuMKLpcGrH4PHynO2+C8mPOAo/XctIJPFJcJkUql2q/hkm2MophrVRyAcxLAKFwzRdWKbYCswBmJYAMu2uZXFSv42eYyCydQdIyvvH578fZoZbwDUuJCE1Mgv+dazUJ+QsPEGzhU4c0kxzpCFuG6bHhW+SbIbvHY/de4nY5TnaO1CJdF4FmtQ26g7QDSaQ7j9JLchosiGFZ/hx8Jn0Bmk75bSHZy1w/HY8AUXBPhi3tsD2A7ZK7SdwepbmKk1Q2XRPjuHvMA3kLeKt0iKUOrB/JETqYAl0RgrY4gb4XsW0jkcR6bV+EZXBGBtTqErBWWIY1PbArrE7ggAmt1AFkNuql3ZmGzL5fN9W3Qd7sX8kXNMVwPQWq1CUkGyy2QlnsGKQZbkBY1SlYt9n1ZgKQKc5Bm1IJbISlilKzmIcUpRWs50yNDyYpUKt5A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'
+b1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/v7//xMTExcXFyMjIycnJy8vLzc3Nzs7Oz8/P0NDQ0dHR09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5ubm5+fn6enp6+vr7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6en/6ur/7Oz/7u7/8PDw8fHx8vLy9PT09fX19vb28PD/8vL/9fX/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqB9+GQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA0jSURBVHhe7d35XxNJGsdxkgAiioiI4sUI3iKisLizs8fs7LrXzIrKeONezs4oLLDrjGhGBzTmD8/28U1fVZ081fVUH3n15xdD6DT9NpCrq6v7Wr1YR9WrZo57/1tspaRY1Ve4ca77DhsbLUb1E26W/36BLQ4lVX3ELYrR59jqQBLVWyxdmD5iw/0E1R+xaKH6Lza+XVRVuDsKYfNRRIVlCtivIXAKq7BEIfs7DHZB1af4fkF7BoZVUIXvFrZ/wRFS4XsF7i+QBFT4TqEDxVd9wDeKHTBt1T9xdcF772raKlxb+L50NFDFvZ6tP5yfmjg0lq8OH59d2cIGCjkcV/U5roq0Ol2r5LXJuw1sZbhXvgrXhHs6gRXktP23saHhPNUXuCJYYy6/91O7qdfY2GBv2yp8HexNzu8ot73PsbnB4lVvDuN2OW9IwvrGVb3Dl371gqAs1gtsciBXhS8CncNtCtDYLrbZL0b1ALcoRLPYaL//2arv8YXXzj7cwK26tIkWcU2uqop/WrYKF/1uYHm36i1c3WzewVX5ahpb5ydVHcLiTgFUTlW1bWyel0z1BEs7BVE5VVWuYvO8vpKo5rCwXQiVV9VRbJ7X+77WX3HR6yQWtgqj8qoaFF7n9rV+cC/4DWNhAZVXVWUN2+fVJ7y1qmNREZVb1Qq2z6tP+LPaxqIiKrcq4S2JqNrEopWDuMIvryrhv5+i8l5p9ZJq6ywu9JJq64D3fNA7qq0D/rNcz6gsVO+pbFTPqRxUr6lcVI+pgOot1T6gekvlVaoyqVR5lapMKlVepSqTSpVXqcqkUuVVqjKpVHmVqkwqVV6lKpNKlVepyqRS5ZWJamh07ND4xJHJ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'
+b10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79vb29gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr9qqr+rKz9rKz+r6/9rq7+sLD+srL+tLT+trb+uLj9uLj+urr+vLz+vr7+wcH9wMD+wsL+xMT9xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+9/f38PD+8vL+9PT+9vb++Pj++vr+/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHJ0rWgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVmSURBVHhe3Z1pQ9u8loAnCRC2t5R1WFrKTgtcLkOBoTBwoSwt20BfoMOSBP//P9FxkhNZ8jmSj2THce7zBZAd8IM3LUdH//Enmv+Er+1DtJWXTeDoaExW8PnsAseJ0VrBB7MOHG0IjRV8ph2AI1agrGD3tgEOWwJbwa7tBBx5ALKCHdsMOPgGYSvYq+2AwwdCVrBPGwICdVQr2KMtAYUaihVsb1NAoopsBVvbFtDwkaxgWxsDIv9mVkIrsIINbQ2oBFZQ3uaATMMKSkNU7g6WxocHs8Xw2MLeTQWOMEzdBqygTOV5669cVuld/w1HGaKmo7cqfemE35BNCgsvcKQKNZ26FZTIXL2DT2eXvnM4VgWT1W4ePppp1t7gcCWEFfwssQMfyzqrWEtv9Q0+lH3W4IglwAp+CrgtwGfaAHxv1a3gh4DyIHyiHejDT0LaagM+QNA5urx/9ev+/tf1weexLihsLYtw1AGkVakb9g/TvXKnvNIrv9Z6YVML6XiCwxGQVvuwe4jxozLsIFE+noDNrWMDjkVAWg3D3gpDN7AVcUvunyJ9qE5IWL3AzjKFDeI8Nah87YDdWsQdHIjAt4LvBOewr8QI+pzKrxHYsTUcwGEICKtN2DdgXlftF1QWYdeWsARHISCs5mBfwedIKZ8V2LkVTMAxCAirT7Bvg2Uoj+AL7N4CRuEQBITVR9gXmFPP1MPe0mh3Z2fP4OfTVygCFuAD6TMMRyCItHovP/wqJ1NSA6Uwdiwbl4egPHWsrfLXUFrl+j2UCj7AlhotqxNbW61CoU9pBTUke/+GbXXWoThtbK0GguvvZRTKAkJSXhmdy3SwtfoJZb4UvmvCUp53CVtS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'
+b11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD9sLD+srL+tLT+trb+uLj+urr9urr+vLz+vr7+19fXwcH9wMD+w8P9wsL+xMT+xsb+ycn9yMj+y8v9ysr+zMz9zMz+zs79zs7+0ND90ND+0tL+1NT+1tb+2Nj+2tr+3Nz+39/+4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8PD+8vL+9PT+9vb++Pj++vr+/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5tFg+wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA+7SURBVHhe3d15Q9NcFoDxSQtlE0VBQUVBXhdAZFwYZYZRX8dxGFFRVJB9Yr7/d3CS3JM0yV1yzrlJmuvzT7FNSn4CbZrl5i+/fscwqqBtwXLpM6rgSdoZLKMygwrmbm+wnIq0Kpiz5cHCFtOoYCYHggXOp1TBDI4EC51NoYKJHQoWvJ+sgindCpY9SVLBZK4FSw8VVTCRgwEgrqCCKZwMCFF5FTzuaIAIy6rgQXcDR04FDzkcQLIqeMTpgNJXwf2OBxiz6uf+q+W56cvt6srVO892z2AJCwEmUcG9uc42r3htrffgOyxlPqEBFdyXzX8yCs/QzjrzB7Ck2QRHqOCubN+vwdztrbf5ExY2U+yJVXBHtu1hmLXVLfiwuP1S1f/gjkzbXZiv5d2WWKkK/p3pvSMoHStU/R3+2e+o3a8TuTZgmdNAJf3J/bwFc7jQcPEVHlTwr36vYQap6wc/CrXghzoLS52mUU3D9HKLxd/iMXhgkO3CsiSpVbswtaoiqw2qRViWJLVqEaZWVmC1QdU9goVJUqrGYWp1j2EqURtU3htYmKRIBV+m/YBp1c3mV5ZboVqBhUlTqN7AtMoKqHao5mBh0hSqdZhWVRHVDtU4LEyaQvUQplUkodqhGoGFSVOoVmFaORnVDlUPFiaNolKg3FepUM6rlCjXVTLqQ7SW4bZKRr2IV56cVqlQ8Tqhyyo1KmI5rNKhQlYrNgWwVGrU6MfL4uHBx1FpUHvBXls2RDFUWlQQrIgpBh5dZUAFhx0xzaAjq64ZUEFwXUw06KiqiRO4My2LCp6JqQYdVVXcIpBHBR/EVIOOqLoGd6XlUcGhmGzQEVWbcFdSARWciMkGHU3V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'
+b12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAQEBgYGAwMKBAQMCAgICgoKDAwMDg4OEREREhISFRUVFhYWGBgYHBwcHh4eDw8sICAgIyMjJCQkJiYmKioqLCwsLi4uMzMzNDQ0ODg4Ojo6PDw8Pj4+GRlLGhpQHR1WHx9cIyNoJSVuJyd0LS10QUFBQkJCRERERkZGSEhISkpKTExMUFBQVFRUWlpaXFxcX19fYGBgYmJiZGRkZWVlZmZmaGhoampqaGhvbGxsbm5ub29vcnJyc3NzdHR0dnZ2enp6f39/MzOYNTWfPT23Pz+8RkbSSEjWSEjYSkrcS0vgUFDuU1P3VVX9Vlb9WFj9Wlr9XFz9Xl79YGD9YmL9ZGT9Zmb9aGj9amr9bGz9bm79cHD9cnL9dHT9dnb9eHj9enr9fHz9fn79gICAhYWFhoaGh4eHi4uLjIyMjo6OkJCQkpKSmpqam5ubnJycoKCgo6OjpaWlp6enqampqqqqrKysrq6usLCwsrKytbW1tra2ubm5vLy8vr6+gID9goL9hIT9hob9iIj9ior9jIz9jo79kJD9kpL9lJT9lpb9mJj9mpr9nJz9np79oKD9oqL9pKT9pqb9qKj9qqr+rKz+rq7+sLD+srL+tLT+trb+uLj+urr+vLz+vr7+wMDAwcHBwsLCxsbGyMjIysrKzMzMzs7O0tLS1NTU1tbW2NjY2tra3Nzc3d3d3t7ewMD+wsL+xMT+xsb+yMj+ysr+zMz+zs7+0ND+0tL+1NT+1tb+2Nj+2tr+3Nz+3t7+4ODg4uLi5eXl5ubm6Ojo6+vr7Ozs7+/v4OD+4uL+5OT+5ub+6Oj+6ur+7Oz+7u7+8vLy8/Pz9PT09vb28PD+8vL+9PT+9vb++Pj4+vr6+Pj++vr+/Pz8/f39/Pz+/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA47wMlAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQYSURBVHhe3Z35Yx5HfYc3xuCYkoQU2pCkCRRoS5NACKRHWrcQWtrSlqL79KXDJUBaWo42TeqCfMiyJVu+FFk+YlEITUvSxrIl+bZJaRNZliyIdQS95dX+Je6++352d2Z3dvY7++7su8vzi0ezs8fj932/Ozs7h3FLytfxb5b4Pv6VILcyMwsuMIS8WpXARQqQWWHnLIMr9RNuhf2yDq6WJ8QKu+QCXDKL0ArFcwMu20NkhbJ5AlfuELRCuZyBiwcBK5TKH7h+G78ViuQRGJTwWaFAPoGDBW+FzXkFFj4rbMwt0OCssCnPwISxwoZ8AxfXCtl5pyzjWCHTz9zE0I6uzdmio7tv5MISLtDPim0DK+TxFMd7arJKff8VXKWPV0o6EqvT7ThCRum+igvlKemUrZDBMt+HnbNL3XARF8viWuFvlqkW7JppuhdxuSzhVlPN2C/jdAm0Qq2u5UTK0goGQ1jhL4/CZuyTAwZxzQwhVoexRy44j4v2EFtdrcUOJOq3HDw9NTM7fe7IrlZkpUrbMi7bxbZC2qMf5SmsP7qAvSyKE9uRnSancHYXodV8HYpH0zzmv2Nc24JN6dG5gnM7CK2GUTqaXfPYhaF4rB5bU+MyTu0gtCJX/kawg4+rad8WhnFiB5FVsRGFoziKHQKkfQvvxXldBFbTKBuF/3+IYaoBZdKhFad1EVhNoGwEPaKapcMLKJQS/vqFZYWUyxiKymmYQXEx6Ub4QNAKWp1CUTnsj2pueGNTY9seNhTN0u8OCXADZ3WJadXofeiLexyDzovIstiNvFRIysqrUy52Isui4QIyTfMSslIhKaspFOakOK1NyEqDhKyaUDZQvV/vRsZB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'
+b2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xMTExcXFx8fHycnJzMzMz8/P0NDQ0dHR1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4eHh4uLi5OTk5eXl5+fn6Ojo6enp6urq6+vr7Ozs7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9PT09fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/IkxoQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABI6SURBVHhe3Z1pQxRHGoBhZhgmIIcgAh6IqAiIiCBmc+2VZLNZRUUO0exu9gxyyF5JYFizg47zu2f7eLu6uuvouvoony/MVPeM9dg9XfdbHe33Ea7VP1oF5t2XkEsKTKtP38Gni8z3kNk4DKsf4GPF5wvIcQSq1U/wCTv4BnKNQbEq9K+JykeQcwRpBWdaxWvIe0Dcyr4L5QPZB2JWb+Ek+/gDGHhEreAMK/knOLhErOC4pfwAFg64FRy1llALs4JjFvMdmGBWNtSQkgiqhsjq33DAbkAmsPoEkm3HtwmsINF6/Oc7WLHq6I3tpasjQ2eLxfDYzOo+ZJDA0wErSIqxd7PaWVSG7jcgl1HeuTq+FfX5d3AJvqCg1O42IacRQitIiHC/uNcp4Dz1Pgys3sB7jOYV+GSh6XoK2cUJrOAtRnMCPldwKhStN77VH+FtiC1SnZ3ldcgyhm8FbzCW4DMWUDuCPId8Rrfa64KP2MBlyHTIO9fq5/AmZBQ+gNFzeWF992B/Z3VmtAJJReER5DrEtSJa9dtwesj4E6xoOF48A8nFYBjyFeJawcuQSTg94PxLOBDQfFiDQ4VgG7KF+JxidVSGs30qtCL86DIcLQJXIVOINxSrR3CyT+0FJMe4A8cLQA9kKYRiNQsne9R2IJVgEc4oAK8gS4gOsr2IPwG7mFKt1m04J3+eQI4QHe2v4BWiB851uQdpNJqUAiAfFiBHiI721/AK0Q3nOoxDEp39ohTW85AhREf7t/AKEbZAygeQ5LI92VvtHpg/hLcuRflpzUF+EB3tb+EVIrS6AikOW8OQVp6sQ1KrVS/IxZKzegYprdYmlv/hUOsGJOWMlNUgJESl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'
+b3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/w8PDxMTExcXFx8fHyMjIycnJy8vLzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV19fX2NjY2dnZ2tra3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq7Ozs7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9fX19vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEN6WYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLjSURBVHhe3Z37Q9RGHsCbfYE8RUBARUBQFBEBxbZ3vWvv0bve9RQRxQW37fXaayvKo71rC2x7Ze26//beJvvdySTfSfKdx24SP78Ak2TJZ/OazHznO2/V30TCrL6sJZlPYS9FBFr9ChsnmV9gXxFiq69hs+TzOeyxF5HVf2GLdPA17DUPtvoM1k4PH/0Gdp2BrGDNVPEa9p3hs/oE1ksbH8L+A16rn2Cl9PEdGDTxWL2GVdKI5y7PW8HylPIrWNhwVrA0tXBarlWaT78m//sGVFyrH2FRmvnmbyDTskrrLd3L+2DTsoLitAM2YAWFqedV87nVtPoUCv1US2uz54eHksXw2NX7u1XYQz8fOD5NKyjycbjYYyWV/uUT2Esfjo9jJXz1OJnNwickk/z1U9hTD5+93bKCAg9PemHr5DK4A/vqwRayrb6Cv3luwpaJJnMH9pbnI7CCP3kWYLukswr7y/MqyCoVR8rhLuwxR/NYvYK/XJ7AJikg+xz22eW7D2wr+MPlJPk3CpehCuy1i3Os4HeXOdiAp3durbS392xtNnGPsFuw1y621b/gd8YRfk4NP2TP8sr6OShMCN3osfW7hhX86nILVmfklj31k+pSsh7P92C/GD//FVtV/edYVwmWMHYKsCgRDMNeubzCVruwcgsslTQtVCMUnIH3YN0Wj6HcwwYsTARbsFMMgdVVWBeYhWIf07A4CSzBPjEEVuOwbpPcMRT7OEzQHWMG9okhsBqFdZsEHKpEHazLsEsMgdUwrNvErezvXC50TT2DP2q1p7BCArgEu8SIssqxJ9Wmc8rlnsCftdPknILSVqNQWDvtahacYdWuoWZBApC2mobC2gMo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'
+b4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/qKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKytLS0tbW1tra2uLi4urq6u7u7vb29vr6+gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0NDQ1NTU1tbW19fX2NjY2dnZ2tra29vb3Nzc3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4uLi4+Pj5eXl5+fn6enp6urq6+vr7Ozs7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PDw8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1va/bwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABBfSURBVHhe7Z35X9zGGYfNch82YGzSpk2TNGma+Ai+MLZjYzAG47Q52qZJm54QGxuDgaZN0iQ2tnFzEUgccNb736qS9qvRMaPd95VGWg0fnl+8Gh3MY2lX0sw77+yx6vGiZf2mSDz11K9+gqrFUsvqX08qBebTZ1FNBXFWz3+PnYvMkzdR2yhqqw+xW/H5H2ocRmX1MfYwg69R6yCy1XvY2hw+Rs19JKsfsalRPI/Ke0Ss3sFmpvHRKxCoErb6FBuZxyMYVAlZfYdNTOQJHFyCVo+xgaHAwiFg9QPWGgs8bHyrb7DOXPyLUFiZdetV8+ivkPGs3sIKs/nomaqNZ4Vi03mhagOrRyg1nqpO1Sr2+ludPXtooL9YDAwOX1neRgWjfPK0b4WiCBuT+5qKSufoGmoZwfVxrf6GkhDbo604QjEpnfoWNQ3xzW89KxSEWOnH3sWlcw51DeEIOVaqB/WZZuxaaM6htkG+eq5qhcUgV0vYr+CcRX2D4FxhKcCsIVLKs/V710p+VrrXgn0M4Drq7PPkXccKCz7lA9jDBDrXUWsf91zhs89l7BDlxho4i4JCcBK19nnRtnoFnwXlbmwf4RDWVzbbUVIISg9QLcEXttWX+Cy4hs2j3ML6yjgKCsJ5VMvn/T3yBXgIW0c4iNWVzQ6UFIQO6ZnwsWy1FXP/ncf6ygQKCsMSKiawr0B8Eixh2wgHsLqy1YmSwjCJmgkUVpPYNsINrI79hWwcp1AzgcLqDLYNsx9rK9tdKCkO4jLyUFgNY9sw4hY+hYIC0Y+qCRRWp7BtiL4y1m7H3MwaSS/qJqBaXcPKyjQKikRSq17vVJX3oqRIJLWaxbrKDAoKRUKr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'
+b5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/t7e3ubm5urq6u7u7vr6+v7+/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMDAwcHBwsLCw8PDxMTExcXFycnJysrKy8vLz8/P0NDQ0tLS1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/fwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4ODg4uLi4+Pj5eXl5+fn6Ojo6enp6+vr7e3t7u7u4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8fHx8vLy8/Pz9vb29/f38PD/8vL/9PT/9vb/+Pj4+fn5+vr6+/v7+Pj/+vr//Pz8/f39/Pz//v7+/v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3CowtwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLMSURBVHhe7Z35X9RIGodNQ4MCcgnuzO4K3gLKCIojqLM7s9esu7Ozp6jgBbjjXjOOAq4zgzAH7bb9T/cmnW+/qaTeqlSuTvL5+PxCUlWd1EOnk0qdB5oG/KxINJvvIltqdFafvGkUmJcaOaXVV/hwobmJzAbhrW7iU8XnW+TYD2f1J3yiHLxGrkVkqw+Qujx8hZx7SFbfIGmp+BUy3yZohWRl46ufIP8ufqs/I1H5eAMDF5/V50hSSuDQQrQqxSNKDSwcBKuXiC0t8LDxrP6NuBIDE8Hqt4gpM3TLICtElJtvINO2QnDZ+Z1rA6v/ILT0uDqwQpjE1p2Lk2MjxWJ0/OzVtX1kMMj3LR3X6n8I81O7dcQqKtXzXyKXAVo+rhVC/CwdwhEKyuRzZNTHmw/bVtyb/NYEPlxcqkvIq4932lbYF3nYg48WmpM1ZFfAeWg5Vt9hX+BhFZ8rOMcZLVhhT+BRSaRsrTqy7PF5y+oj7Hns9uMzJWABeRb42LF6jR2Pc/hEGeh6ikx7tL4rbHvcc9PPbYdx0k2YL0eQa4+/slbH3ORXsKvmrJswZx4gN8Qb2+rX2Ca+ROqyWJ1Ebjz+cKD5NTaJ80hdFqvKFrJD2N8VtjwGkbosVtYNZIdgrHaRtjxW55Ed4kPZ6gHSlsdKugt+KlstIW15rHqQHeKJbHUFactj1YXsEJ/JVgtI61lNdyuoIGXeIJ+EkVXhC1DIJ/GPt1aFBfkk3loVF+STeGtVXJBPwshqugoK84AKgHwSRlYCL1YvTRZPDZkjolo5bM8XrVIXGSPiWDUa+3PF+r6QLSKeVaOxPoREhQCZIuJaNfbGkaoIIE9EbKtCaSFLRHyr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'
+b6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz8/f39/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfdmegAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMCSURBVHhe3Z3nQtuwFoCvk7DLDLNQoGxoWQXKLrusQAPkXvv9X6TXTo5l2Ro+Gknsfn9KFcf4I7GscXT0n7//InIrzyM/ZIDoSuo/SRBb1d+eaeBCOYis4I0ZBy6WgW8Fb8oDcMVxeFZwfE6Ai47BWsHBOQIunIKxgiPzBVw7IWkFh+UNuPqQuBUck0NAAIhZwRG5BBQa0Fbwek4BiTqUFbyaW0AjILKC13IMiPj8S1aRFrGCF/INuPxjVqFWaAWlSf6cf58eHRnOFCNjX7Yu3+ACkzRswArK4rjnU05WKc7dwFXGaehIrM764QwZpXwLF0rT0GlYQRHN21d4c3YpbNTgYinqPnUrKKB57IO3ZppyFS43Qmb12AvvyzjDjJbE6jknUr4WUxmGVvDfCHcU3pMDvsI1E4RWW/COXHAGFx0isnoqwhsohhf3b58qD7eHs51QkhV63uGyQwRWy3A8oWP5AV7yqV2tdUB5NvgBFxbSsIL/EN4SF11YS96RlWl4KRMMwlURuFY/4GhggNc0Oc1SJXkJFxXCtYp/EFMfUBznLUPV5DpcUwjXKvYxCKQ8rzoIR7SfSbgkgm8FPxFe4Ng64yIp/+bKTJuq04VLCvkfa3UJxwZ0VqCQx0MXHNV2XuGKCKzVORwa8BPK+CSqlfbxDBdEYK1O4VCfCSgKqB2O9XR0zxxQtXxtAI5rN49wQQSp1TkU+Wx3Q1kvaaG8rJSgrN0oWfVHd+EqFAV8r5dkx0nRahtK4lKOs58tJ0UrMi5wAwVA8TpTTmpWRTIqMAclWUXFagQKvFdOzyRTqFjNQoF3CAWZRcWK9J13oaBQKsBPGUPFagEKgg5/cXzzNuhz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'
+b7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/ra3/rq7/sLD/srL/tLT/trb/uLj/u7v/vLz/vr7/wMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3d3/3t7/4eH/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/9vb28PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYmWdhQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2DSURBVHhe3Z39Q9M6G4bPGN+ICA6Rj6PgJyKichT1KIKCeJCPF5Ct//9f4ru197q2SdsnyZM24frFrUtKLrfdzdok/evPTYRoFTgEmlREgRV24iRoYh65VqjuLminlBwr1HQcNFZEaoVKHoAGZ5FZoYYnoNEpRCsU9gg0PIFghZJ+gbbHZK1QzDfQ+j4ZKxTyEAhEpKxQwFMg0SNphVe9BRpdElZ4zWMgkrTCKz4DkxtmFWvFVtjuOZDpW2Frlqv9rb/n52adYq61vLl7gQZmiWwKrQ4eNhuusrjbQSvThDawwqYUh3exA0eZ/oKGpgh1IitsSdLeGEJtd1m7QmOTFFldzKGm00wdo7kJCqwuZlHPcSZFrdgKzwdceSLV1TpBkwfkWq2hjge0hCjMs/qCGl7wGo0eEFnhSczvibD43Fk5T8KStdL8hWbHyK22o+LzeFrEelS0Vp6iLTGhFR7HdG5HpX2xGhGOWjKrPZT2xaqxjcbEyKxeoLA3VitoTIzMagGFvbGaRGMGiFadURT2xqpxhtbEiFbnKOqR1T5aE/OX8AH8haIeWe2iNTGi1TGKDqy+DGf5hFeC+yhbL5/RmhiSFTbEjF/jlfh9rRceq+d4IT4I1AyPVf9HTTvqMNYOi9U9bA/+xYa6YbH6iO2OZAWPlWtZwWPlWlaoWbV+g0/YAFzLCjWrHJzLChYr57KCw8q9rOCwci8rOKzcywoGKwezgsHKwawwtxpvo5RDWWFutY5CLmWFuZWLWWFs5WRWGFs5mRWmVm5mhamVm1lhauVmVhhaLaCEY1lhaOVoVphZuZoVZlauZoWZlatZYWTlbFYYWTmbFSZW7maFiZW7WWFi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'
+b8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/i4uLgID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/xcXFwMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/6urq6+vr7u7u7+/v4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8vLy8/Pz9PT08PD/8vL/9PT/9vb/+fn5+Pj/+vr//Pz8/Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbZCRbQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOaSURBVHhe7Z17X9NMFoDtjbYgyE1WkFduioIIAgLLRXhFeHEvgoC7C+Vtt/n+H4Jt05OZSeZMcs4kbRN/+/wjnaSYh6aTuZw58+Qxmr/Av9mBYOWkDrgwM2Yr+A3pBa4Tw2gFb003cK0aJit4W+qByw2AW8FbMgFcsg/MCk7PCnDVKroVnJsl4MolmhWcmC3g2gVBKzgta8DVe/it4JwsAgYdfFZwQjYBBxfVCg5nFbBo8wtZKVqKFRzLMCCiWsGRTAMqv5iVpyWsoDhA/Xxr4fn4WLqYnFk9uoELDNKR8ayg0M/lcimXVib3G3CVflwbsIIiHz9m4BeklOonuFA/bR2z1af0fk4e09h92NbpWEGBQuM3eGeqGfgKl6sQYtV4Ce9LOSVcC7dqZkSqpXUGlywxWm3AezLAUA2uWeBZwUvB9wK8JQsswkVLDFbj8AaVsZXDy5vrs6351FWNX+CqBR0reCE4hdMVXsnbt7Y9BIUpYRouTIBbzcLpguoxHOlQW4LylHAJ1yVoW8GPgps8nO0xegdHBHvBU/rKMlyV4E/Eag9O9tClHGc/TVojcFESxGoZTgZK11DuYxWOpgKtckesJuBcYAeK/TRG4XAaOIWLEiBWA3Buh1EoDfIFjqcBrfGOWPkfwfhH1WpUjcAJKWATrkmAWMGpHYoPUOo4n6dK1bey7f8RzkgBG3BJgieP/4GfBHBqh+dQ6LUNh37AS+fcfZ0KEKt/wU8COLXDWyh0vkPBDLx26ump3NlW21DovIWCnLgH09NwYluJyuIVFOTOocAZhoL+w7YS1cs7KMjfQoFThZL+w7Z6D4XOJRS8hNdOswgl/YdtNQGFXk3+VLSf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'
+b9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVVX/Vlb/WFj/Wlr/XFz/Xl7/YGD/YmL/ZGT/Zmb/aGj/amr/bGz/bm7/cHD/cnL/dHT/dnb/eHj/enr/fHz/fn7/gID/goL/hIT/hob/iIj/ior/jIz/jo7/kJD/kpL/lJT/lpb/mJj/mpr/nJz/np7/oKD/oqL/pKT/pqb/qKj/qqr/rKz/rq7/sLD/srL/tLT/trb/uLj/urr/vLz/vr7/ysrKy8vLzMzM0tLS2NjY2dnZ3Nzc3t7ewMD/wsL/xMT/xsb/yMj/ysr/zMz/zs7/0ND/0tL/1NT/1tb/2Nj/2tr/3Nz/3t7/4eHh4OD/4uL/5OT/5ub/6Oj/6ur/7Oz/7u7/8PD/8vL/9PT/9vb/+Pj/+vr//Pz//v7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQLQ3wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABNHSURBVHhe3Z1pQ9s8EoA3CQQKFMp9lqaQQqFQyrm77x4c5aaw5Sbk+v+/ouskE1m2RvJIchKL50uDbKd+EsfWMRr97c9bhG5VTQ5wRnIirOBtEgicII7cCo5OMHCiCDIrODDpwNmGkVjBQQ4AJxwEs4L9nQFOm0O0gl1dAs7cR7CCHR0DTr5J2Ar2cg44fSBkBfu4CBjUCVrBDm4CDjUCVrDZVcDCg7eCje4CHgEr2OQyYMJZwQa3ARdmBcWOAzIRVuXrnYWJ0eFkMTq5dHAHJximIdO0gsIgT6u9qaQyuPUKZxmkbqOwevmchndIJtlvZTjTADUbsIISnuN3cHRyGb6Bc+Wp6UitluHIRJPZh7PlYVbwN8cSHJdw0ntwvhxyKye+qRrpAzhjDrCCv3x+wjEO0H0P5+wjsXpJ7g1dZLwCZ81oWMEfPjk4gKNnZu3k9uHh9ufKVDcUJYVNOGsf1OpReE6NHXCPhuL2EBQng37xy8KsVmD3Jh+uYAPjuA82JYKfcFYMzKrcA3s3SK8gj/DXz7A1CUzCSfl4VvCK8Qt2btB1BsUhdpNTncoIHztitQU715FJVat7ydH6BafEQKz4iystlfK+Ldin82zBGTEQqzHYt8YqlKHMw04d5wucEAOx+gD7enxA6/pNXpJSq1+AE2IgVtzTiL9gb/MD2Z7BlUf4s8YB7NZpPsP5MJRW41DicTsJZem5ZyiqViv9UNhhEKv/wSuGb3UIJZ4UVzMc9LXWoajDIFZ/wSsGs+plvypeitd6ScbdHbH6B7xiMKs5KKhWJ6AE8H+d3J2lgyBWf4dXDGa1DgXV31DQpKsAG6oLUNJZtKzYE3gRChgbsKG6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'
+g0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A0NDQ0tLS3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e5+fn4O/g6Ojo6enp6urq4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiD0LYAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGuSURBVHhe7Z39XxNHHsebYKiI2uJD42FV1BYLRcUHUHwAaVEK9YHenVQtLRWxoJ53Jz6gcBXhOGLIH+1tsp/Mzu487MzsZDfrK++fYHY2mTchu7Mz3/nOJx+UKNUNaJAcJav//Puf9cM//v4vNEtMiBX+QHUIGshHZoXz6xY0k4PQCmfWOWhsEIEVTkoBaLAfrhVOSAloNA3HCpVTBBruwVqhZqpA0wlBK1RLG2h9lYAVKqUQCLj4rVAjlUChgs8Kx1MKJMrQVjiaWqDh4FnhUJqByUdvhQPpBi7ECsVpBzawQmGQzfmxk3u2NefqiuZtX/SOP95EE/24NrD6Lwr9rI3vydQt+RvraKaPig6sUOSjOL4VL1CntEzwPq+KT8XqfyiheX0EJ9cxx5bRWArPCgU083X+Qbm0PkNzKSRW6ZDialWt8CvFs5RIOVov0WSC0KqwD+ekgINFNJogshrEGQGyuSx+qieuodEEgdUC2/hc98jMinPo3czV7maU1QlbXrutJgis+lCf0DZaNqqyMroL5fXBJbSrimuFXwgrgQ+jeTz4r1u8Xk+f17YNNKsK12oMtcEh5irj8KoDR+uBn9CoKlyrblR2OclcYyoUe3G8DjiNNlXhWn2OyhUEUnWltQ9NIjhW+InwJ+pW+EYk5Wh1oU7iZJneO2s1h7plWt+ikMfKdtRKnOdoEYG1eoCqZe6hzGV1aRU/uUyhVuI8QYMIrNUMqjp0oqjM8vBOp2T7lSX8XuaYWy1xHqE9BKnVNIqcL1F/E8qa+t6jzFc1UbSs9pBLRfEEisr0eFp7UZQwWlZXUVIqnUSJSw9KS6VRlCSMltUfKCnNoqDKDMpL8yhIGB0r7zbQg5IqXSgvbVS/bcmiY5VHQWkp+GSSJZ3/dpQki44Vua7fRYHHzzhS+gYFyaJj1Y2C0g0UeFzHEeZ/Mxl0rMil7kcUeIzhSIm+4idHw6phlSwNq4ZVsjSsGlbJ0rBqWCVLw6phlSwNK2J1HQUexOo4CpJFx4qMJN1GgccEjgTmupJCx+owCkoPUeBBBgSPoiBZdKxaUFAqBkPPdpGh6laUJIuOVYZMCAdmijOjKC8toiBhtKzIqN+q/yPZRuIU2JHCRNCyIhfB0lNaq8WbBKuPS6CeVfYNinxalNRyfQyz61llhlDksDTkzgK3DnqqpeFKUfLoWbXQsZKFO8MXhyfpOJTl2l0Bm/d0dPWc6D3d13++r7en41MUC9CzyhxDGR/roQm5toM956/ennnun1V37i0LP50/kEMtFk0rrxPBge1ymJPdd+bGIzoEjEPhfpcgkk/XKvcApSyzliK0snt7x+eCAVYCFi9tw1k+dK3EWlakdh8fnV3DC6qxMcGJM9W2yuTuotzPvchSTV9fp2M3lCmObMErEPStMpnj7P/7in9SX5+tx+8ErwjqPAvO25pYZXaM+VuwOl4OkzFnZ//9Al7KjMKw//ZvZOXcPvoeVv/91x/2h9w95OQHmTYY8MT3GGFo5ZDN9w5cHujNRwqTbrn4Au8SlWU6LMfcygKCZThm0FrJWWV7HuINLEFpJWW1fcjoKi7F00rG6sBktGuegOU2vH4CVtnjzJvaohp2Gr/VV0z4qEXOu+8Rt1X7fbxqbVh3b1vxWrVNigPH7fBH5fYZp1XrDzW5Rvi5VH6n+Kxyg+bdVw02ysMpcVllT9u/P/EZct4tJqv2p3ix2vPG+WbFYtU0HMMXitATj1W+lncoltk4rLKDcX5QZfK1t9o7j5eJjx9rbZW9qDgEZpOFGlvtsvwIpUaxuaZW5/SG9qzRUUOr3B28QOwM1M7qs8c4P34ma2Z1gJNAIy5e1sqqN4FrH6FYG6ssk7cgXvRWayqy9TecmhRMX9qC1a4FnJkYTAOiWx0JmSJ0WJ0Z6e3uPHKk89tT1x7U4KZm3+qMvDO7OTd6fI9vbD679+SY5c6idat+nMVndUyQfSt/w+ZHZvt7JZVakM0JtQzw8maYYdlKJjUfFmWX7bT1eGnXSiJVuKww0dU07C0Tj4LV+5VE6nEedULYb+WuYNNKLFW4ohy2lbtqYXjXopVY6k+ttdGH3uE0Ywr2+oESKcX/vir7o2q9tmZlTyq61pwtq1OozKIvFVnrniWrg8JukolUVK1xO1af/4m6DO/3o4omh/kpUdVg41JMrJrFfQLjmFWyRsOAXitWv6AmyxPj8OJchKCZozasvkNFloLRl8rlgPndOG/ByotyZxDkiFTDy72jy7boVu3iWKR5YYe2teu76ZdLSy9/Gz7GDTEtkzPtEm5EH2ffQYWzB/kKdYIcpENjNiZE/SnJP4GUxchWOcmz+Qv+R5Wfw3HCg9045KfJcCr5YWSr26jEA4EqfrKXOTfs9fPcP8AVHNbkblSrXtThscbL/JvzUqX5uMu7BeyQD+yIGI5otVPWsWHXdDpSv+Mgwz2e1iQO6vFNRCvBH97lC1SiyEpO4C3dOoBjeuyMZnUGNbg8QiWaizjG5Qwq0ZgMOy1Fm8Nvkw7hjaMWxV7pRMlaNWaRwuRfcCqaFVl4yoWTUjVklvhXVKM4j0M6DEWyOofjAtgu4H4cEbHJjusexCEdvo5itVs+hLzG3oFkq5wqBJe2Os84Bl3c1ghW2ZB/J3aldEvo3WeVXSfGyfgfQnlxr7GV9HLmwOay/ApHJBxAVY/Qz5ehfIcwtZJfzhzOoqIHtdRTxDlU9Qj747GUgzlNrUKDXtilS1M4ImECVT0kg9wCyhuEGFqR9AlC2OQJCl8R9ssYTN8dSrHc+zSzyjKJmhk6UdVDoZ/wGFU9TuCIMi/KZ5lZncUhCewT4yKOSHiCqh7aT46VjCJGVs0KcS9JWVXe18hK4WqWlNVq5YHGxKpVJTA9IaufK2eZWI3jgJSErNzMtAZWu5Seu5OxKrijCgZWasGMyVhNu2fpW+1X60YnY4VdavStxOkFfCRiVcRqbG2roygNIxGranp4batfURpGIlbV2QpdqzbVh9NErKqDdbpWyqGnSVhVerZlNK1y4RGNIAmr73GSrpV0XNNHAlbvP8NJulbqoW4JWN3DObpWHShSIAGrwzhH10pj5Uf8Vgs4xUHLaqfGfFL8VtSeflpWwyhRIXard1SSIR2rJp0FLbFb0cPZOlZa4z1xW/myaupYyWd2AsRthScrFw2rFq345bitfOOPGlYn8bsaMVu99E0saVj5d8oLI2arC6jvom6V01vIEa/VW39sh7qVPM0jQ7xWA6gO1K1u4ldFYrVaDISgKFtlNdeUxmoVzJ+ubKU7mx6nFTNBpGylu6o0TitmCZSylW7sTYxWvm5FBVWrL/CLMvFZFdl0o6pWg/hFmfisOGl2Va2YqNIwYrPa8G1V7aJotUU7qpLduFEh7J7dcFQWLOrC23pV0SossIqF3bhRYU3w76jqETqvvtKCmjSKVn34WR02kO4Gjki4iqoeoaF03JBlRSv9cKKL7utTKIyQfouqHuLVGi709tseilb6oV+T7utTMPu5s7DRnNLIXn78p4OaVU5/Ge9LvIFHNvRGzobGZGR7ujtQo2U0alYGIZWb7Lc49DtyChU9PscRAezVxUXNyiT8lV2fvjXkufMtG/RItsnl8o5MFwRQszIJVa4kXfQTskKCczkbwSE+7GcL1KxM1q1xou6bpMmMZjlrRaS5STkx1UDJaqvJsrW3TC74TCYv6aLwLmefyv5nV3agFouSFdlMSQveBl/dQq0NtuMYEskp2WdGyeoSftJjDm/hQ6TFlcrIVsvJtgRSsiK7DunBXSrcyb0DLXszahSy2A7pjixKVmR3fz3Y2OAy2znrcG/zuqiyFbulAhskTqFkpfBkxGND8OfsCgRYz7AxuhVksR3Ci3oFJSvthytQTj3Lpf3GC6xILy6Mc9ZpuZC9wlh4D1UUKlat+EGbDUGaojItR/oGzp/t4K0SBO3iP+Y0fx0oQcUqjx/0mQt5dxlbxM8JC5K/RQUVK4UFHiLYpyxlvsdLsKzsQhUhKlba8f8eBeGXJowvhZeKQvjuiSpW2qNmFI8MkybkxKsb2CUyDCpWP+IHI0KuVgKyt3A6yw1UkaFiJbkZKsCOsISTvY6TWR6ofPgqVhHT4OlrSaSeClMs0KhYSbIiKKGrJZNS249Pxcq0a0HQ04oupWJlIRf07bDbJkWrOFZAVUrFyrDH7uMN9/GJR5cwCZK6VFxWzgVZaeuvFsm4j7qUipWlTKCL3AdDP52S7CMaUjFalTanO6Wd3Wy3LPxLRypOK4dXF/kPvQ6tg69RiYuWlIoVUyUKGzcPcrYvbe74SX770JOK3crh/ZObZ9tJvye3v3/iWdh447TGnaFMAlYVCgvzs9PTs/MLKrf4Ud2Hz6SsNCicRlvVUbCyeLUw4c+DaKoGClZ27sKmPOEEHoSiYDVjJ1+wGWZb4apY6U8KW8MwVaSKlf4EviXW2aANNVSs9IMt7LColdKYRsVKPzDGCmq9fC4qVvpBTBZQfyLjoGLFVqo9E5p9JD9KVpfxU2wsH0PzDFGyao15e5pJpeExCUpWBsFZEXjLpgfSRc2qHT/GwT29Rykualb6AaqmLJreeH0oWmmnRTJjZYATemKAolWTrQ3eZayPRLqcUyhaRclVrUjxFlJuWEDVKkKuajWmjGclOShbbbGyfYmI+Y7Km9hC2UoWKBCVF9HvUH7UrbRWdutwvytC/AIfDatsLXaVXBvfi5e3iYZVDbRenLN1LfejY2VZqzgVHjhhiJaVTa2Va/wAeyvoWdnSWp/q5cwhKJPtuDD5fHll+dlEP38TFk2rTKZfbzE0h7cTXVGUAnNCz89xhje0rSLuhPxqtCPadXzLSPARdnWAeUV9q0x2wPTR+PEQuwRRk3bekOtsMAjNwCqT2aOV6cJl8e450foHDXr4HZy1QzgOjKwymb/cEu+NwrA0NfS1hQdchx7RkH9Ay9Aqk2m5qBJj/HZ6+Ji9B4xj4nmMNd84r7GV8/3qHJsTfWIbrx7eGbvUbfeWtF22GGuBvq5GsCqT3Xf6+vzr5dXC+urK8pvFl3P3xgd7j+aFM/WRCET0BZ5j6UDEiFZxQmfkXh3PN2c+PTBBXY3pJd4psppFexyBy9U7b+sPKHKgljqkx8qLPy/S09/eU9+GN+KbHiuSEdknRWt5aVbSY0U6FcElmmRQ7xcUpMiqmdyrgvMlZCnpEgpSZEUW974K9mW9pa1kSWBqrEjmLjaenfRKSbxJaqzIKv4RFHjcxRFviXJqrEggARuCQXaBI1PJDatEaVg1rJKlYdWwSpaGVcMqWRpWDatkaVg1rJLl47QiiRt+QIEH2d6SrJxMjRVJ0HkHBR5k0RGZ7UmN1V60prQenHAhR96TyZ7UWGXJqF8wvwlJVPEUBSmy8qZEXvlzQbQQ3VsoSZPVBTSnVJqitbZ6S/m6UJQmK+8zobUoqdfeUHV6rOjMso9PuF7NfVSuz8uVogopstpNB68sj5w93jf+Dr+VWaaujQpW7FbGCTGABvHxvlWcRLaslXfBTBjptu6+zN/Mkn7WqmBnPYAFdooz5s7RkWfbkBqOsPnJByYA5UtUTh6h1pwv0pVJYfafTz4wH1Y/KtcBO/lZWAPZB5hkX3/jWNXLRbBMdpiNOlsL5l1m9vT7K8dqM4/adUH7r/5Qn8JkMFrqEI54fHCsGC2V1GIx0nbNu8a9GNqOUg8mNvgD10qWszEZtncOjo5fu3SUFwbGLv3gW0XK2Rg3nByRrhWrRfWx6h1OQm2RVcH2qpuacYpd/uYIVazSq8WRkliVCmdxXl1zgS8FK45WadpeWHCNaOPulF7WEVuVVi5FXUleU7YPcRd7VHRgxdUqrd88FGmJR+1oPnxbsEKxYiO1cnj/5NbIlaG64sqIJPuWaxNmlTJgU7X6SLQgQ6w+Ci2oUFYfgRZEfFap14KGA22Vbi04VPBZpVkLBi5+q9RqoflVAlYp9ULbCYxVGrXQcg/WKnVeaDUNzypNXmhwAL5VKrzQUh4iq3rXQisFCK0c8AJ1CBooRGblgFepL9A2IR8+/B9nwIX/K2bN6QAAAABJRU5ErkJggg=='
+g1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+gotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixtNm0tdq1t9u3uNu4udy5uty6vN28vd69vt6+wN/A1NTU39/fweDBwuDCxeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5eXl5ubm4O/g6Ojo6enp4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8Pfw8fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl8giSgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAy2SURBVHhe7d35QxTnHcdxFlwUQZCq0WokGK0GxaLUqxqNFVHj1RZCRaNEq8YetlhUAhWKpawLfzWdmf3sXM8c32ee7zPHZt6/uMfMw/OKcdnjmdm2TUIbeQpzioyi+sM//5Gn/vj3v/wVMwsrWoX/PHkMMwwuQoXdcxumGVSoCrvmOkxVLESF3fIeZisUpMIuhQhT9hWgwvZFCbP2JKqwcXHCvN0JKmxaqDB1J58KmxUuTL+ZV4VtChgAyK3CBgUNCCuXCvcWNjDMHBXuK3CAGLWSymHZKtxR7GD5eapm74zu6+6s5quuXcPjT+uYoTdgmirc6qk2ebCS23aOLWOanhqaCNWDXgyQ06pXa5ipO0sDFW5ytTyCnXPcgTeYrCuL01DhFlfz/dgz11W/x3SdLE+IqhioUFaw6kNBUAbrKaZsZ6tw3W59CPsUoL4VTNouTDWBPVB7J9qCG3LVKCZtF6Ja6cIOjTrtv+Qp3JKvfsDsmoWobmDzRg4qp6qvMDu7hgpXmtV3YXMrFyqnqvb3mF6zQNUTbG3lRuVUVfka07MzVbhodwUbm3lQeVUNYHp26wGqI9jYyIvKq6r6CfOza9v8Hy41W9+OjQVUXlWVV5ifXZvwV7WCTUVUblUPMD87UbWITQOejORVNYn52YmqBWxa2YsbnPKqmsD87Cgq+5lWK6leD+NCK6ledx9qXGgl1evuSuupDFTrqUxUy6ksVKupGqgWUwHVWqpuoFpLZVeqMqlU2ZWqTCpVdqUqk0qVXanKpFJlV6oyqVTZlapMKlV2pSqTSpVdqcqkUmWXgaraPzA0fHJk9My5C2dPDR92lhUElm9VR9/BoXPX7j+eFRYK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'
+g10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+ArKyssLCwt7e3uLi4ubm5urq6vb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCw8PDxMTEyMjIysrKy8vLzMzMz8/PwN/A0NDQ09PT1NTU1dXV2NjY2dnZ2tra29vb3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4+Pj7fbt7vbu8/Pz8Pfw9vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAji4xRwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABaPSURBVHhe3Z37QxRHnsDTg4P4QlEUJUFh77EXjFl8EUEIPoKiRAxrlN175zZ3t7cn4iMajc94BzEnj102jBn6j62bnvlOVXV/v1VdVd3T07OfX4CqmqE/0z3d9fzWeyw7fArIS5csrbJDZ/UOPs58svk/cJgESit4bb6BY0UorOBV+efdX8ERh6Cs8n3lRdmEo5YhrKB06/AjHLggavWPULK1+BqOvk7Y6u9b70TV+AEEgLDVT1Co9Qh/u0JWm1CkJQGHKrIVZLcqYBEgWUFm6wIeFYRVS19+NcBEsvoj5LQyP/8JZLgVZLQ24MKtILnV+c+aDVhBYutT09FbrdyfHOzsKOaLjp39FxaW4Aij1HRqVpAUgY0WvbzSdvoFfdOu+qitln4Fb5BX+snD/olbQYLM5vw2eHF+aZ8tw9HKaKw2z8Er880pooH7f2AFf0psTsDL8s5JQqtm9Vv4S+IivCj/DON7xv9Wrf4EfwmewEtagdtwzIJKU6tiBX8IVvfAK1Rs2QK/5IAOfPy0lfpL1dY7Mvt8tXLnKa+9vDHamwu543DUgsDqv+B3zmo7lI/ywa01KAJs3D4MWU2kgE5LYIXuIteheJitY68hPwQb74ACTeMCHIqgYgW/CbqhdIgTqoqX//Y0FGkW20pwJBzCagkKy+y8C5kkD3ZBsSaBLiLC6hsoK3HqLeQpWB6Ggs3hSzgMDmF1GcoKpiFHwwwUbQqjcBAcwgp97jcgQ8utApRuAh/CMXAIqxNQts4spAuW2WLwzArzJRRvAn1wCBzCagjKAlOQDDy5MLgjSG4/NhN55XS1eDP4AI6AE2s1IJ+U5Wuhu/6uqdBT+SNIzhxrq3Y5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'
+g11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAW1tbVapVVqpWV6tXWKtYWaxZWqxaW61bXK1cXa5dXq5eX69fYK9gYa9hYbBhYrBiY7FjZLFkZbJlZrJmZ7NnaLNoabRparRqa7VrbLVsbbZtbrZub7dvcLdwcbhxcrhyc7lzdLl0dbp1drp2d7t3eLt4ebx5erx6e717fL18fb59fr5+f79/l5eXmJiYmZmZm5ubnZ2dgL+AoKCgoqKipaWlqqqqq6urra2tsbGxtLS0t7e3urq6u7u7vb29vr6+v7+/gcCBgsCChMGEhsKGh8OHiMOIicSJisSKi8WLjMWMjcaNjsaOj8ePkMeQkciRksiSk8mTlMmUlcqVlsqWl8uXmMuYmcyZmsyam82bnM2cnc6dns6eoM+godChotCipNGkpdKlptKmp9OnqNOoqdSpqtSqq9WrrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6u927vN28vd69vt6+v96/wMDAwcHBwsLCxMTExcXFx8fHyMjIycnJysrKy8vLzMzMzc3Nz8/PwN/A0tLS1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/fweDBwuDCw+HDxOHExeLFxuLGx+PHyOPIyeTJyuTKzOXMzebNzubOz+fP0OfQ0ejR0ujS1OnU1erV1urW1+vX2OvY2ezZ2uza2+3b3O3c3e7d3u7e4ODg4+Pj5eXl5+fn4O/g6Ojo6+vr7u7u7+/v4fDh4vDi5PHk5fLl5vLm5/Ln6PPo6fTp6vTq6/Xr7PXs7fbt7vbu7/fv8PDw8vLy8Pfw9PT09fX19vb28fjx8vjy8/nz9Pn09fr19vr29/v3+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6+/37/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8fCpXwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABEwSURBVHhe3d2LnxV1Gcdxm2Vb1oW4qHhDXE0NCTOjzEqzBCVDRDJQFBAhBC+gYIpkVl7SzLJENPKGICCoWFEKiCAgSoqKm5eFbXf+lW0u3zNnZn6/mXmeZ2bOmV+f18vXOWfOzGHe7tmzc+Z6RP//Y1mq79736P0P/7NK/f3VV3934TcxewmlqO7+xK5yfX/+OmZULUn1YB8mrnSvn43ZjaVXvYupql/fDzHLkXSq9zCFIWlcqupvGNmcejDn9eKqbxnx+xTvMcx9rZjqjxjNtD7H/KOoypxPCaVzQfCKqD7HGEZ2IRBuYdV/8byh/QoMp5DKcFT4p1VXVXv5iFTwuxWo/oVnjA6WQPVrDDe72gd8TYXBpoc/x1D9H/xS+fkcX3U3hsXrXr1w4rGDBlarI4eNnvnQLsxhPH+Z0FdhUKy3rh9iVbaLn+vFbEb7QaB6GEMifTyjBS9Q0U7eiDmNFqjwONILx2Hi6tYy9xBmNpz7w3JVv8TjcLdjymp35kHMbqg+qDRfqZZisqo3WsOCCo9C3YWJqt+Z6pvwNU/1Jzyqt2MgpjGgeZjnUJ4K9+v1jsEU8dra4+GJJtayCXNd72taVeInxdgujBF0FJ5pYp3K361HHdV5uB/UOxLjqymsCqis5zEvQX2O6lXcD1qNsXXFWVVQTcS81HNUyuf6pRhbW4xVBVXLbsxMkKPCvaC+9IW/RRjNrwoqayVmJugbqupNjKtvWvR3sxKq2ZiZoAtU1RMYV1sMVQ3VGMxM0L2q6iaMqyuOqobqaMxM0AOqaj7G1aSgqqEajJkJukdVzcO4aiqqGqoOzEzQfQyVBlVR1W/pKh3KeJUWZbpKRd3hLmWY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'
+g12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAgICBAQEBAkEBw8HCAgICgoKDQ0NCBEIEhISFBQUFhYWGBgYGhoaHBwcFSoVFi0WICAgJCQkJiYmKSkpLi4uMTExMjIyNTU1ODg4Ozs7PT09IUMhIkUiJUolLVotL14vMmQyNGU0OXM5QEBARUVFSUlJTExMUFBQVlZWWFhYWlpaXFxcXl5eYGBgYmJiZGRkampqbGxsb29vcHBwcnJydHR0d3d3eHh4enp6fX19QoRCRIpESJBITJlMTp1OUKBQUqVSVKlUVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gICAgoKChISEhoaGiIiIioqKkJCQkpKSkZSRlpaWmJiYnJycnp6egL+AoKCgoqKipKSkpamlqKiora2trq6usbGxtra2uLi4urq6vLy8vr6+gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wMDAwsLCxsbGyMjIzMzMzs7OwN/A0NDQ0tLS1NTU1tbW2NjY2tra3Nzc3t7eweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4uLi5OTk5eXl5ubm5+fn4O/g6Ojo6urq7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9PT09fX19vb28fjx8vjy9Pn09fr19vr2+Pj4+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+AAAAAAAAGpDFhgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSPSURBVHhe3Z19nBXVeccPJMRohcZEIybpS1pN1JgUm5im1jZJ770s7nZZBFmyuBuIbU1iW0NtE1NSA6gIiK4soiDrxpUVRNEk9aU1CStvYtEVxLVpTKQBWRcWqw3LbnDv9s6HzNz7m9czc+Y5c+fMvcP3H849c+bly937zMw5Z55hJyj87Oc/QykdCK20qgYH6Ueg1f9j3aoGx8oRYIW1qh8crwc/q7exRjrAQbvgrX6O1ukBB+6AsxpF0zSBQ7fxWqFd2sDRm5wkVh4tjxXapBEYFHFboUE6gYOB0wpLUws0dBxWWJZiIHKSWVlathUWpBu4WFaoTjmQMa1Qm3pKNrBCnZfRnnVLZ9bVVBdT6me3PrwfR8hR1ClZ+d9MDXZOz1Qtc7rzOEw3RZ+SFWpc5DtqsIEqZdp2HKkby8rvqzrQjJWrmOWDOFgnlhU+O3muyr+oEjMO4XCdwOpX+OggHVL+WrDCJwc9KZHStd7CIdsEWQ1dgXVSwGIcs4Oi1Tv4YNOKNejkKvflduOgbYpWKNu8gPY0Zqx4pFc/dRQObVt7NaoSpW4Ih23hb3Uz2lNY+GwBaxm8vqoW9QmyHju38bN6I4vm4TS9jHUsjsn/9ZbLTOf/axHd6k0ULdagdSjZtX4XLTunYXFi7MKeLXQrlGzmoHEYuW1YwcNAIxokRTt2bOFjlSeGsyCp5LUWYb8W+/jfVS/ahsFHVIuBBrRJhnrs1uJXvNU2tA3hNjT35Vk0SggutvN/gd1oKmaa63J59OiRERRL3IFmyXAEe7XgrTajqZjNaG2wZ/lkvablCYfY4OWlZskwgL1aRLSaasf0/hbUZeodP7WVqEuEuKzsYNo/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'
+g2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL6AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsWOjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cns2enc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4utu6udy5uty6vN28vd69vt6+y8vLwN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ufS0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg5eXl5ubm4O/g6Ojo6enp6urq6+vr7Ozs7e3t7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWJ+1wAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABiESURBVHhe3Z39Q9tGf8DL+QWDeS8UmjxJYdBQWKGhUFjhMSUhbzTJCmEpjISErFDaELaHPu2zBcKrN54VG3d+Zrk6/lkmWd/T60m+k2Rb3ucncTqb+1h3p7vT3em9SwYuAgMkqBgsVv/0Uzn4sy0/6/nl3yFVThSz+vXX3/72W97M77ZgW+DX9gdInR1OVnl/U+IzkEgqdla//Q4fDjaQWjM2VoG+SkYgxQboVvCB6gDSrIdmBbGrB0i3BsUKolYTkHIVqxVErC4g7QSzFcSqPiD9CiYriFKNgEEBoxVEqE7AQcZgBaerFbCQ0FvByeoFPP6fWalaOis4U82Aic4KTpQajEWZfF5QyMlksxmFc5m0RErh7OzsVCKpcHJyciyTPDsX6C1VcHG2Enaf/rGvq739fYm2trZWhRaJ5ubmJoVGmQaJuEJ9fX2dREyhtrY2KhHxk1hb/8zzg/M8JNKA4qJaQagOnFoeaKqPhlBNAEHv33qTplwvRcbeKvP8ejwM3xFI4tMHAqRVR0GGWEGYCj6YbAjkRdIR/mgtA8nVKNjYWInbvVH4bJBpXqBrgRWEEMTt7kBnPpXmhSwkWUXWoVrht38Xgo8FnZanlqpQtYK/CcnJ6rhSEujKjrkmtLHKLsXgMyaCWMlHb55DsgnECv4E8O4V+IRGtCex9OYoefxudXYgDmEBoXnRerEoVpl5U6FCzYkfz85zIpaaO0I2vTdnta4g4X5zhUG12u+D+ED91Dt96wSL2eOFFjgXBN7/DlJGUKzgD0BYi0D0AqErz9MinCLg3NYQnA4AsUlTFsQUq9Q9iF0g3LtLaZZg8ehWYGoO1GNOIbZaHd+E2DKSlPlC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'
+g3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+kpKSmZmZm5ubgL+AoqKio6Ojp6enqamptLS0ubm5gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+z8/PwN/A1dXV19fX2NjY3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj5+fn4O/g6Ojo6enp7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9PT09vb29/f38fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8DgQ0gAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMISURBVHhe3Z39QxTHHYfdQxBEfAHjCwmGtvZVDAqiKIqiEAxqRIlGm75pUBGiETHSNm0jgYjQpg0XqSlHjv1P6b18bvZlZnbnbe92eX65u5m5u31gb3Z2Xr6zaT2YP/zjRztO4LBCCLH6xfpv/7j+l7/FiT//7e84OD58q5//bg1/n3iCw2TCs/on3htvcLAUHCu8K/78FwfshWmFdySD/+Gg3TCsUDo54LhdUFYomSxw7AS/FYolDRx9CZ8VCiUPHD/wWqFIEoFBEY8VCiQTOBRwWyE7qcAij8sKmckFHjkcK2QlGZg4Vv9BRqKBC7H6PdITTlGGWCE18RRtYPUVEv0sjva3bqutjhe129sGH3yPI/RRsIHVb5DmZW3qeJUVV2rOvMBheig4weoHpHmYa8UHxJWjizhSNwWpohVS3GRHqvHm+FJ3l+6DKEjxrFa78M54c56jlbfCaxcJkbKsPkqLb7XWjTfFnwEcsgPX6hO8JQk8xjETYIVXDq9q8Q4fmzfjSZzY+RpHTeBYdeINblqvTy7b9vLk8LtIiA19OGpCwepfeEH4JoXyDt2uS950zGqSGv8/q2CF5w79KE5oeIgc8KAeGfHgOg6LwLLK1KF0iaYF5BDmdyErFuzGURFYVs9RuEQjJRU3rW9xVIT1TT/BM8JNlAVVz5Hu4Sn926sc4zgowvqmX+IZoQdlwRCSfVA/vgpCHeL6pl/jGeEgyhbZuoJkH6+3oEAM6MYxEdY3/RTPCC0oW6QfqXkW3SfwWRSIAcdwSA6bfoUnhHdQtsgMUm17dJ9lNT/AC9v+AgViQAcOyYGuAz1WtVmk2jcKr1O38dLOxOf+i7Ji1Oweq4NI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'
+g4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A3d3dweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+fz5+vz6/Pz8/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzAkGwwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA/HSURBVHhe7Z39f9TEFofvbtlSbAWBcgtoeRORNylF3q6VF+0tWqnFaxUpIAiCIO9Ir0rpQin5v3E3+e5kkjPZnpNMspn99Plld2cy23m6bTaZOXPmX2+7kbRWf/35/yZ//oXX5WI5K08GWpF2KC2KZCv0p8ygp5REKzQsOehsnAQrNHIAdDiK0QoNHAGd1jFZ4Wh3QL9DqBWOdAp0XUGscJxjoPMt4lY4yj3Q/4CYFQ5xERj4RK1wgJvAoUnECtWuAosG3W+FSneBR8QKVS4DE80KFW4Dl/ZWC7Ond6/tq5WLvoHtJ2eeoYcx4KKsUKzz4NjqSlmp7r/5Bt2MEMgkWz0/gDcoK8P30dMIvkzLCmUhl/rRuLzUJpbQWQ3fJsHqzWm0LDd7FtFfjaYNrFDSwhEpo1ZTJ7BCgeJLNCo/e+kfYcsKLxW3qmjjAN+gzyEJVi8H0SJGTy9YhYIy0PsIvVbACq8Up9AgjjqTnkBBKdiNToUYrV69g+Nj7Ee9N1dDSTm4h24pfCs8V0zj6Dh3Ue99hoKScBTdUhittuLoGHtR7T3vRUlJ6K2jYy1MVvWEE+Ad1Cf+23WMG+iYwmB1A8fG+AjV3nwfSkrDOfRM0bDCM8UEjo1xC9XeGRSUhwPomcJgdRTHRvkQtd5C6T6qyvvomsJgNYpjo9xErfcFCkrEELqmMFiN4NgIO1Hp1RO+zDrJJvRNwbW6jkpvHAVlIq3VNtR59TLeS6a1uoo67xwKSkVKK3WSefUuSkpFSqvLqPImUVAu0lltRY23uBYl5SKd1SXUeFMoKBmprIZaQwOL6yuV9VtBiS4xUln9iAr/xmsGz73dQWUZSGO1qfVRvd7Q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'
+g5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+Avb29gcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatr9evsNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+y8vLwN/A09PT19fX29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4uLi5OTk5eXl4O/g6Ojo6enp6urq6+vr7e3t7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8vLy8Pfw9fX19vb29/f38fjx8vjy9Pn09fr19vr2+Pj4+fn5+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo18IGgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABKcSURBVHhe7Z35f9TGGYejNb6AQAzmjhNTIAQwGOwApgYbFzAEnEDTA2ICiYMbg7GblLRNoTg20NLWJrQuS5f9a+keX7065p3RaCStJD5+ftnVOyPtPPaupNFcb71+E8mS1d//8uc/fi/hTz/8Dbl0UFn9uxwA8oUEO0cBR5Iit8IBMgwKyiCxwn6ZB8X1w1n9C7vkApTZi2j1A7LnBRTbg2D1CplzBEruwmf1PTLmDJSe8Fr9A7lyB8pv47H6L/LkEBgAt9VL5MglcKjjssrxf6oKLGo4Vv9Eam6BRxWy+g5pOQYmFWyrnyEl18DFsUI850DGtsr9jwrUbWwrBP0Ub53Z39HenC1a1uw4emUOJfRT11FZPR5ea2WW3TdLKKaHuk7dCiEPywNNOEBG2fgNSuqh5iO1utOJnTPMwDIK60Zl9VkBe2aa7UsorguFVT6kLGsbr1WzwqbDeE6kKlrPUWSH/0isFtqwTw4YQJld8FavdtfyN7UEkYn/6CRK7VC3wgZxtZ59FJtyeusZ06VDqBayVq+217PnxMq6jtIQNSu8J6aQOy9W3SiNA2dllzUvVtYDFIeoWOGdwzvInBurT1AcgrF6irz5sepDcYhfilZfIW9+rLaiOMRvRKuLyJsfq1YUh/hWtBpFXsdqcUHCfuRMmQLKSfxetDqLvI7VYQQyC8pJfPdGWv1hxSqzoJzEilV2QTmJFavsgnISWlant4Otm7JZ9Uc5CS0rN3OfD6xBenZA2YjQVhVeXN2BHFkBBSNMrCpcydY3EaUiDK3Kj+qPoTICCkWYWpVfHkSuLIAyEcZWmdJCkQhzq/LLXciXPigREcEqQ8+tUSBCZdU/4Wdy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'
+g6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+yMjIzMzMzs7OwN/A0dHR2dnZ29vb39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4uLi4+Pj5OTk5eXl5ubm5+fn4O/g6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9fX19vb28fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzLH1jAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABQfSURBVHhe3Z39QxRHnoe3B3kxKBoXg0FREaOLwaAiBoNCSFASBXV3c7cr51tEDZwc3Nte9jZxT5R1lKx3mTBHGHfsf9Xtnv5MdXXXS1dV98x0+/ziTHXNUI/TXd319q1fvFHArhf4e7FRsvrzH+vEn6p899133z969Oh/Avzw6HuH7/7jv/71dyiYCKkV/gdTCgrJQ2j1Cp9NNT+jsGEEVvhUBkCBg3Ct8IGM8AeUmoJjhcwZAgX3YawycT2FQdkJIat/RLasgeJXCVr9OzJlEBh4BKz+jByZBA4VaKu/4nhGgYULZfUDjmaWP0GEtvoDjmWY30PFt/oHHMk0v4FM1erXSM84sKlavUZyxvk/z6ZqhdTM89uKDayQFqa8MHW8c2tLc6poae86Nb0sOrkqOjKrn6Z2Waml+9omihnkj66OZ4WUAOWLLfiClNI+y/29pFar+/HhFPPhjygszaOqFd7TzKf8h/LoWEVxacRW2ZDia/2byGoxI1KOVh5F9nntWeGdz0YnPpMB+tgqQ2A1gk+EyDXjRaqYRqF9KlZ47bOI/BQtAxe/WXdq+/WH491ISgstL1FsAt/qI+QndF5yjAgvrryL9HTwGcrlw7Naa0J20Ha1jCNVNs7lcCwNdJRQLIJj9d94SfgcuUEfW8vY9vJeHE0Dt1EogmP1M14SDiOzx+nwD+VR/hDHU8BZlIngWOEV4fU7yFxBIGXbpV7kaDz7USQCx2oVeSscF0nZ9vr7yNNwmkP9zW4diJeE+8jrsoOu+8Ks7UCuhvMCJSKwVneQ1eUe0jzWn/+EVx43kKvhMA+DrNVtZHUYQJLL87F2J+W9c/Q3pOUcfIryEKRW/4wk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'
+g7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/A2NjY2dnZ29vb3Nzc3t7e39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4eHh4+Pj4O/g6Ojo6enp7Ozs7u7u4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8/Pz8Pfw9/f38fjx8vjy9Pn09fr19vr2+Pj4+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAurfsHQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA4VSURBVHhe3Z39QxTHHcZzKChijPieRONbNBgploZEY6PFUGkUG9r0LYkRYzVGiPY9VCJC2opSy5lj/2F7t/fsy93M7n5n5ju7M35+YW93Zm8+cPcwuzuz+9LzYgLXeIaGZUKx+u3f/uoSv/vzJ79Gy7LItcKvxlH+g1ZKyLZCXaf5AW3tJssK1dznH2hwB3Ir1PCD79HoFDIrlPaHP6HhMRIrFPWJ/6HpEaIVCnoGGg8EK5TyDjS/TbcVyngIBEI6rVDAT+DQosMKm30FFk3SVtjoLdBokrLCNo+BSNoKW7wGKokV1nsOZCIrrPUd2MAKK7tZvzc1unegr9cp+vp3DU9+3UATu2jr5FmtTb9ac5Ydk4/RzA7aOm0rrOpg/dMB7MBR+i7K/l6hT6bVoxOo7DAHFtDYNLEVXqe5vw01nabvNpqbIsfKD6lMLbnVoidSTa05NDkBVniVsH4EdTxg11M0OiHDaios39NXzIawZKWcRqMTQqsf8CJmuS8sfgAv8zgblqyWb9CWhJYVFhPG26V9sRpBWxJkVnVEhS9WG5bRmBiZ1Rco7YtV7UM0JkZmdRqFvbE6isbE/FdidQCFvbHaso7WxIhWz3pR2Bur2ndoTcxLwp/qIYp6ZHUTrYkRrRZQNLF6uthNfGjjhtUMWhMjWt1H0cRqBisSvsSW4DWsqJZraE2MltX26HDtHlZUDI/VODYEY1hRMSxWPUvYsLoZayqGxWoI64NfYkXVsFg5lhU8Vq5lBY+Va1mhZrXvLpjEijbOZYWaVQbOZQWLlXNZwWHlXlZwWLmXFQxWDmYFg5WDWcFg5WBWmFu5mBXmVi5mhbGVk1lhbOVkVhhb3UAZ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'
+g8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+wN/AweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4O/g6enp7e3t7u7u7+/v4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8PDw8fHx8vLy8/Pz8Pfw9PT09fX18fjx8vjy9Pn09fr19vr2+fn5+Pv4+vr6+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB03dHgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABRlSURBVHhe3Z2NWxPH2odNIDRURKlYv0pLi9WqWBA/itJqqaIt1eqpPR6t+EXlyHl7rEpFrOfwlkiO5yU07p/Mu0l+Ozu7M7v7PLObZLf3dbWE2dmwt0k28/HMM5s2yFguKEktDCuVl4/+iUdc/vVvPKDw8rdHP//88z8fPXr028uXv/32P9F/NNQKr0w6wTVqCbbCyanmDa7VT5AVTks/uF4veiuckQ1wzTI6K9TODrhuF9UKNTMFLl2gWKFe1sDVA78VKmWPlxCo47NClSzyHyjU8FqhQjZZh4SNxwqHs8r/QcNjhWMZBiKyFY5kGqi4Vn/gQKaBi2uF8owDGccKpVkHNhFWC1dP7N3cVUgX3X0Hz92p4Ap9NGxghTIv1ZtDudTSc3YJl+mlrhNidW87niCldIy/xpV6qOk0rFAg83ocJ6eY/ge4WJkwq9IenJlq8t/jcmUcK/wqUdqN81KOTuuPIKtyRqRsreu4ZIkgq89wTgYoPsc1u9hW9n/4xeUuzvBT6MCDNLHvDa5a8Kb+WuEXwXofTpDoGP5u3v7iW5mZ7EdJariGy3bRWl1HdZeOM+5XXvX2AEpTwh7lxdJaDaK6YPc/cKRB9UInDqSDn3BdgpoVHgoeo7Jg3xqOCO534VAqGMFVCf6rsbqEyg6qlK1VwME00IeLctFYjaEy6C2h3MM0jqaCFVyUQGO1E3XBLRR7qX6Ew2lAuUSNlfczM4hSP3M4ngamcU2CTRu/45Egj7oNpBbJ+tIrPKrxHiqkgAu4JMGmjf/FIwGqNiiKPmd1qjeX+/ghflNvKm3kPC5JsGnj33gkQNUGH6HQuYkU5/CrNV//PRVorP6FRwJUbfA5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'
+g9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAVapVVqpWWKtYWaxZWqxaXK1cXa5dXq5eYK9gYbBhYrBiZLFkZbJlZrJmaLNoabRparRqbLVsbbZtbrZucLdwcbhxcrhydLl0dbp1drp2eLt4ebx5erx6fL18fb59fr5+gL+AgcCBgsCChMGEhcKFhsKGiMOIicSJisSKjMWMjcaNjsaOkMeQkciRksiSlMmUlcqVlsqWmMuYmcyZmsyanM2cnc6dns6eoM+godChotCipNGkpdKlptKmqNOoqdSpqtSqrNWsrdatrtausNewsdixstiytNm0tdq1ttq2uNu4udy5uty6vN28vd69vt6+ysrKy8vLzMzMzc3Nzs7Oz8/PwN/A0NDQ0dHR0tLS09PT1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d39/fweDBwuDCxOHExeLFxuLGyOPIyeTJyuTKzOXMzebNzubO0OfQ0ejR0ujS1OnU1erV1urW2OvY2ezZ2uza3O3c3e7d3u7e4ODg4eHh4+Pj4O/g4fDh4vDi5PHk5fLl5vLm6PPo6fTp6vTq7PXs7fbt7vbu8fHx8Pfw8fjx8vjy9Pn09fr19vr2+Pv4+/v7+fz5+vz6/Pz8/f39/f79/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHWfsaAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABSfSURBVHhe3Z39QxRHmsd3BlAMqDE7vqxGxagQFIKBlYioiBIJGFbubbN3t7f3vixGIqKgBvdOjSiBE3Rchh36j/V6Zr5TXd31VHVVdQ/T7ecXmuoa6A/MdNfLU0/94r0xTl3BRaixsEoBSqst/H2SCS6SQm6F1yYaXKqAxOqveFniwfUGIK2S/c4LgovmoaxQOzXgsjlEK1RNFbh0hmCFeikDF18laIVa6QPXXyFghSppBAZl/FaokFIg4eKzwtm0AgsX3gon0ws8fFY4lWZgwlnhRLqBywduheK0U5GpWqEwyMrUwPHW5qZk0bzn1NDMW1xhkLINrFDkZ2v+bDaTVHb2/4TLDFDSUVg9P4ofkFS61nClPko6FSsU8BRvNOLFyaX1Di7Wh8Kq0IFXJpshooMrt0qJFKlVtcK3HsVOvCj5XMclc8isxvGSFJB9hGv2kFgt7cBLAjQ24CBJ5N7hqhkVK3zjcRIv4Dh8cWqp6H7enk/251CUFIZw1R6k1TNUZzSee4xTZe53Jurh/NEGrotRssKhx69RvUr7Ck4wnn+KU4ngFq6KQVnl/Z+q5kmU82yOJOgjdgQX5UFYzaNyhdbnKA5wvwkV6k82j2tiEFY3ULmMTCpRWvO4JAZh1YW6JXY8QyHBXGLuGaO4IgZhdQR1S4yjjGQAlepOPy6IQVgdRF2Xz9xHlEdh9XUBh2U2kvLk6sUFMQir/ajrfgyXUOSyeeezUknnfXxf4l6lWt05h+thuFZBLc+qAyUucx+jLHPgKYpcvKp1hbLCEcO71FmUuFLcDa/F07qJojpjZPUx+1T57+It7G6fT0Z/2ciqGwW+G0iJThT775f1w8iKPQb8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'
+p4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICAwMDBAQEBQUFBgYGBwcHCAgICQkJCgoKCwsLDAwMDQ0NDg4ODw8PEBAQEREREhISExMTFBQUFRUVFhYWFxcXGBgYGRkZGhoaGxsbHBwcHR0dHh4eHx8fICAgISEhIiIiIyMjJCQkJSUlJiYmJycnKCgoKSkpKioqKysrLCwsLS0tLi4uLy8vMDAwMTExMjIyMzMzNDQ0NTU1NjY2Nzc3ODg4OTk5Ojo6Ozs7PDw8PT09Pj4+QEBAQUFBQkJCQ0NDRERERUVFRkZGR0dHSEhISUlJSkpKS0tLTU1NTk5OT09PUFBQUVFRUlJSU1NTVFRUVVVVVlZWV1dXWFhYWVlZWlpaW1tbXFxcXV1dXl5eX19fYGBgYWFhYmJiY2NjZGRkZWVlZmZmZ2dnaGhoaWlpampqa2trbGxsbW1tbm5ub29vcHBwcnJyc3NzdHR0dXV1dnZ2d3d3eHh4eXl5enp6e3t7fHx8fX19fn5+f39/gICAgYGBgoKCg4ODhISEhYWFhoaGh4eHiIiIiYmJioqKi4uLjIyMjY2Njo6Oj4+PkJCQkZGRkpKSk5OTlJSUlZWVlpaWl5eXmJiYmZmZm5ubnJycnZ2dnp6en5+foKCgoaGhoqKio6OjpKSkpaWlpqamp6enqKioqampqqqqq6urrKysra2trq6ur6+vsLCwsbGxsrKys7OztLS0tbW1tra2t7e3uLi4ubm5urq6u7u7vLy8vb29vr6+v7+/v7/+wMDAwcHBwsLCw8PDxMTExcXFxsbGx8fHyMjIycnJysrKy8vLzMzMzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3Nzc3d3d3t7e39/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3+Pj4+fn5+vr6+/v7/Pz8/f39/v7+////AAAAAAAAAAAALXB5YwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA7sSURBVHhe7Z15mBTFGYdnl0MEQbkWMMKiqEAUQYOokBBQMNEoiAoxJqIxXhFFg0GCxhuNiaiIEY8IHhEUUaPigRoPJC6ooLgKBJC4gCCIAgvsAjv1PJM+flPTPd09W9VH9dfz7PvPVH1d1f29zNLTR3V1KlOMFLT6b5qRJb0aSbrhbbUX3QlTh1QdeFhtRT/yVCNhO65WteiSCPYgaSsuVon5nrI4vy+H1QdomiiWIPks+VbVaJcwdiF9kGdFeFdeDxAwsVuhRSKBgoHNCssTCiR0rFZYmligoWGxwrIEAxGrFZYkGqjkrBJw2Fc/achkrdYhnnA2mzZZK0QTj2kDK69f3/SaZ8aPHjWSFKNGj5u52vNwwdAxrZYilEfVhE4porT/w2okmYdxMmlaIWJn9VmNsAqSlJy2DIna4VYrELCSnrYfupOl2eQ6JGtlbdYKdSvVp6IraQZ9j3SteFtV/xT9iNPPRavCtHJ+jzsSIqVpOc/ctZ9i3Qo1C79HnwTwG6RswcNqHnokgueQdI5PdKs9qHCqu6CDOIfNA68egIgyyrYgbU5at0I5x9/RXoJH0ZU9gYBC7sCmc7hZpY9Ac3EO3o2+dT0RUUi543TDzeoNtJbgQXRlsxBQyhxsnKNZVaLIuQqNxemSvdhb1wsRpVyIrXOqUs4rgD9BY3HuR082BwG19MbWOXUpxx/g3hZoLMyBu9CVHYOIWhrtwOY5TquVaCvOPejJXkRANR9j+xyn1RI0FabDTvRkxyGimnexfY7TahGaCvNXdGSvIqCceUiAE9yqHd/dDEBEORFYTUI/9iYC6gnfqvU29GODEFFP+FY3oRt7D4EYCN2q1XfoxoYi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'
+r0 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/iYmJi4uLj4+PkZGRk5OTlJSUmJiYmpqanJycnZ2dnp6en5+foKCgoaGho6OjpKSkpqamqKioqqqqq6urrKysrq6usLCwsrKys7OztLS0tbW1urq6u7u7v7+//4CA/4GB/4KC/4OD/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/w8PDxMTExcXFxsbG09PT1dXV2dnZ/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi5eXl5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8fHx8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/fz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATF6XsQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABMBSURBVHhe7Z39gxTFnYd3ZndhBeQtKIuuBgVxs7lL7uLlXvRyMYl3ueNNBEUgQNDjEoKKCL5tFiSAHHAvSdwAIhAQFnFVRO5yl/PuEszyqq4kxgRB2Mi6zM6/Mdfd85mq6qmXrqru6Z7OzfPL9lRV99SzM93TXS/fqiso+PIPfpuvSj74/pdQRSFSqbs+wAGqlve/gqpyiKX+vOqNirx/GyrsRyT19UHskwIG70KlWXipO1Ok5JK7AxWncFK/RtkU8StUnVAm9XcolzL+BtUHfqn/QqHU8RMIFPFJ/a5YIo38BgoerFQOBVLJFUi4MFIpu+qVk4OGA5VK9efkQj8rIpXi86nEB1AhUqm97rH8O2QgldLfp3K+VrSBFBJTT9GmKCW/N8qd6O46UFV0dZ+SX6d/7ul4UnciqZzjK6cNz1QhI2asPoUqlvNFIiU0H9wzA8eoRrL37BfW2ruuu1J/iwQf78zE7lXLvWdRVR93Qkqk3FmV3zs/I19AZVncGwtH6i/wkqUD+1U5m1Bdls97Ur/BK4aUOAmtnAugI4UXDD/CLilgD6rM4ErdhW3Kuyk4n0qM/hCVptzhSHGtYYPC695VrXPmzfnMVXhVPcxDrSn/60hhk/JjFGeYubWn+GSSO/7cLKRVC91exVhEUuUf1JBlJ5BT5OTyocipCviPqlD3ZWwRTqBwiSl+JZeTrcirBup7USvCF+t+gC3CShQukm0XPRHnOrLIrwI6UCnCv9Zxv1LTUdYj24nUcrZXj9VcVInwZh02CDn2ei51qiara1AjQo6TOomiHu1IFFE9dx3nUCMCJ/UKSrpMUbUw5armatGDGhE4qYMo6TDEd9073Lmx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'
+r1 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/s7Oztra2urq6u7u7vLy8vr6+/4CA/4GB/4KC/4SE/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6io/6qq/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7m5/7q6/7u7/7y8/729/76+wMDAwsLCxcXFx8fHyMjIysrKzMzMzc3Nz8/P0dHR0tLS09PT1dXV1tbW2dnZ2tra29vb/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi5ubm6Ojo6enp6urq7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+jo/+vr/+zs/+3t/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiWNr1QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA2QSURBVHhe7d35fxR3Hcfx7HIfclquJlAoh2cEGkRKSpsgEKCUcmMErVhatWrDjUq5WsNRsFWxVUiBCCjaFoQQEULY5C9bZ2fe+53jO7Pz/c73852d2ce8fpnZ2ZnZeT5ybXZnvltXrNRbtwcT2cNf4gD9C0Z9ih0ktv9+E0fKFYD6BBsmvIc4XE++qKfYJg39BMfszAf1CKunpW/guO041J+xaorivgm9KKyXsvbi6JEb9Q5WSl3/BMDKhUr8b/HgCiCYOVFfYoV0BkQpB+oh7k1rYBjZqC9wX3oDxIH6C+5Jceznqox6G3ekun8BU0Zhccr7mYUBagBL056lsVAfYRnfQPeZ0yeTVWdXAQfH98jkWCgs8nZj4+LxuQQ2cn7bBRyitzcY6nMscXdm2VDsJInNPeD/DxJD4barnhXYOrHNuYpDdfVzoPy+UKcnY9MEN3yb3+83oHDL2dEkf+fZtfmojP8ZDdSvcctRSky+KuN5hYHCDUdn02LK5TbjkB35ox5PwxYpaNhlHLTdXgP1C8zbrcIGaOqL6HksSFSz+nHUrAEDxX1XXsXqqOEulg8ewpJk1Y6jszNQmLNzf6FsU0JRDdxXxQf1YDTWNnOYEorKfYDDY73BozqwrpnTlFTUyzg81l/r3sIc6/tYt5TLlFTUszg8u7pLmGHNwbpGblNSUfkHOD5WnfeV86fDsS5nSiqK/6Gqw5R1D2vypsSiDuP4WBzqJtbMTfCaEovqwPGxONQNrJlrwAK7WkKdx7SWUDu/g5kaQu3MNVozNYTamas9lGGqOVTJVGso01RjKMtUWyiYagrFntjWEoqVoapRhkIZqhplKJShqlGGQhmqGmUo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'
+r10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ur/6ys/62t/66u/7Cw/7Gx/7Ky/7S0/7a2/7i4/7q6/7u7/7y8/76+x8fHyMjIysrKy8vLzMzMzc3Nzs7O0dHR0tLS09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d39/f/8DA/8HB/8LC/8TE/8bG/8fH/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+jo/+rq/+vr/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6+/v7//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6KyZgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABdwSURBVHhe1Z35QxRZfsDNUQ2CgIDiAQNB1wPHcfAcHG/wGHQQD7K7ySabTTbZrIqiI+LFKOwms9kkG0FhPLJJZkYHHWZXm6b+P1LHt1+9V9/vq3qvqrq6+vOD0u8V3fWhql+98/uWLQXyRcHMIov/DucnQW7100V4i8zyCzhTjMTqx5lXcvl7OF8fpNW/we9UAr+DcxYgrH4Fx1cK/wHnzYGt4NhKAs7cw2/1X3BgZfE1nH0Rn1WFFBIYOH9AtIJDKpEfgoIDb/WXcEBl8nOwsOGsfgTZlQr3UOasILNy+VsQ4a0gq5IBE84KMiobcClamd9DemVT+MrVca3+8DNIrnR+82PHx7H614D7b37i3li2uPvgDZwbgSPlWplfQ5qPhWv723JGBlm379I7OEcfhf8pWi3Sl+pV/yp4kyzS0PcMzlPElrKtfmEuQIrA1Qb4/axSe56stX7vWpnUpZrbA7+bZbY9h7Plca/Vb81v4DXHXAf8YrZZ8xTOl2Px97YVdakqRIrWsq/Vz8y/glcehR/AL2Wf9W/hnD1+Y1lZlwxeeZyBX6kEDsM5cyxYVvgGnFoOv0HSsHnHzp07tjTCy7JzB87aw75W2Op9OB5Rtf3kDXYjP//s1I5A/ZR4D91rttUX8DPjCRzup6X/BRzBeHlmDWSWkXtwMozv/8H6Xvk5DEeLdI2SXe6FW9Irmxa74FQ8CtiqUA9H89RfhlyC4TJXQqpwZdd6XvmgbsBudO/xvNwFh5UJVF7YT2Efl+FYj9phyJJytQ4OLQtn4CwYhNUROJZR/znkBDBRzrsQfbEIq71wbJGGKcgIZLqMz68tcA4Mu27hYyccC9RNQHqR+fGh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'
+r11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8/S0tL/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3x8/35+l5eXmZmZmpqanJycnZ2dnp6eoKCgoqKio6OjpKSkpqamqKioqqqqq6urrKysra2trq6usbGxsrKys7OztLS0tbW1tra2t7e3uLi4urq6u7u7vLy8vr6+v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Gh/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBwsLCxMTEx8fHyMjIysrKy8vLzMzMzs7Oz8/P09PT1NTU1dXV1tbW19fX2NjY2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4eHh4+Pj5OTk5ubm5+fn6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+zs/+3t/+7u8PDw8fHx8vLy8/Pz9PT09vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeyflvwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABGPSURBVHhe1Z2Lf9XUHcC7R9oCBWqHIKgrAkK3idvUTbe5qduUIiDyUhk4R3lIsQNB3eZrvqcrpVrAjjkQcT7mhMlAimxzSktXkNKW/EN3Sc4vuUnOSfL7/ZLcm/P9fPDmJuek52tukvM+NaU4bv3jF2YRuXjkd9dAEpVEW/12FE5RWN77FiRVIsLqZ2MQs+C8A+kNobR6AeLowGeQ5gCy1Y1PQ3hd+C8k3Idkdc1FCKwRL/4AEu8SsrrjbQioF6OQfJeQ1TkIph2PgIAgaAVBdOSVG8HBxm/1fQigJx/cARoWPqub4LCuHH4MRHxW354PB/Xl/Z+Ai2f1HZ3vKZfnQaZ8rTTJIsXzQ5ABK/MD2K85wgaszt0Me3Xn8yccH8fqnZib6sKhfXuLRe/+05A2BeI5aFtdb74L+0JcfP0Xc8YZBeSypR1nII1h/uNaXVRfqvNbvw4nKSINq49BOoO8/Q1h9QfzCOwJ8MYMiF9U6taPQFIDwLUyVZdq5IFaiFxgrjoKqfXzimP1vqkofYwsgYjFpvEgpNfPv20r1aXSREqt9WPL6lnzu/DNxz0Qqfg0noQklzl3e6nGNP8F38q8ClF0YKFcI2FdK8UPsH8KxAgza3mY8XCkimyDVJe5UWl1P4SXaPoIQnhcCkeqyOQhSIvH4fk15s9h22NoEoSXkbQKYKW4WM/XmIdh02MrhFYR1iqCVbN0Z41ZT4swcyG0kpBWEawM6eluv69CjMTmZ+t2QTBBIax+DYnxuF62OghhldR1QSigEFarIDEej8hW2yCsirBUMayaITEej8tWmyCsAkmqGFZTIDEeT8pPizYIKyNLFcNqEiTG41H5WkVaKaQK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'
+r12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAQEBAgICBAICBAQEBgYGCAgICgoKDAwMDg4OEQYGFgcHHAoKEBAQEhISFBQUFhYWGRkZGhoaHBwcHx8fNxISISEhIiIiJCQkJycnKCgoKioqLCwsLi4uMDAwMjIyNDQ0NjY2ODg4PDw8Pz8/QBUVTBkZUhsbZSEhQEBAQkJCRUVFR0dHSEhISkpKTU1NUFBQUlJSVFRUVlZWWFhYWlpaXFxcXl5eYGBgYWFhYmJiZGRkZmZmaGhoaWlpampqbGxsgysrii4urjo6tz09wEBAzURE00ZG1kdH2EhI5ExM7k9P5F1d8VBQ9VFR+FJS/lRU/1ZW/1hY/1pa/1xc/15e/2Bg/2Ji/2Rk/2Zm/2ho/2pq/2xs/25u/3Bw/3Jy/3R0/3Z2/3h4/3p6/3x8/35+qampqqqqq6urrKysrq6ur6+vsLCwsrKytLS0tra2ubm5urq6u7u7vb29vr6+/4CA/4KC/4SE/4aG/4iI/4qK/4yM/46O/5CQ/5KS/5SU/5aW/5iY/5qa/5yc/56e/6Cg/6Ki/6Sk/6am/6io/6qq/6ys/66u/7Cw/7Ky/7S0/7a2/7i4/7q6/7y8/76+wMDAwsLCxMTExsbGyMjIysrKzMzMzs7Oz8/P0dHR0tLS1NTU1tbW2dnZ2tra3d3d3t7e/8DA/8LC/8TE/8bG/8jI/8rK/8zM/87O/9DQ/9LS/9TU/9bW/9jY/9ra/9zc/97e4ODg4uLi5OPj5OTk5ubm6Ojo6urq7Ozs7e3t7u7u7+/v/+Dg/+Li/+Tk/+bm/+jo/+rq/+zs/+7u8PDw8vLy8/Pz9PT09vb2//Dw//Ly//T0//b2+Pj4+fn5+vr6//j4//r6/fz8/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfVCjXAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVDSURBVHhe3Z35Y9XGncAnbCjp7qZpmt2w2zSEdrNH98g2zZY2QAN7H93DzzYGbGzsgMvSpkma5XLAnMEEGxsMhjSwaa4t2OAYAwaWhCSLsY1DOewGW9Zfo9Xx1UijGY2+oyfpPfXzQyLrjd7TB0lfjUYz3yGGjB+/97leltx8C/ZQTJjV95575VfwDWXLp7CvPGKrZ/+zTI9RkE9ghwMIrX4G2+QBzXgO9toHb7X+FSifF+7BjvvgrXJy7vn56Eew7y4Bqw0noGDOgN13Ya2Wfgalcse7YODgt1pgaFAmh3y6HiwsmGMFBfLJ7Q1gYeK3go/zyufHwIOxgg/zy+0XwcRnleNryuVjUPGsfgmf5JqfL3RkHKul+tuwPufYNq7VvfxfVA4zx20f2+qy5KLShs8NlBdnz4/NwM7xXPKs9DdgXZChtubqijJkxZaOG7CLQajVjPj803rXwpeUI5XbzsN+stwCq/fFoeL687B92bJzAnaVAax00aGaOVgF25YxtWdhb/1YB4sYH+o/hb99zOyFDcubytOwv35sK10QAHMiJdZ6caFB3hGdgJ2wUflTKYgZGwyi6/zj77VK2CYH1E/BTnuYx0p/jrulTTfBFlhqN7+6tWV1Af7KmNdgrz3Wm1b8CXgYyqNYtqd/3Nls6nxnPazMlBHn5z0+EVnNrIbiCFZ1T8JWDgMt8EGG8AfrXcLXls5C6WgKbfxJfXoFfJgZy9h/WBON6P8Hi5QdUDqS2nOwBcOdV+HjzDgJv0wxyEJY8miAwlHUjcIGAbTtUCAr9sAPU6y7cIAJZCwLk8peaw38LuUoWQxLlEEoG0HVdSgvQGuGQtlQFawcHSfPwRKl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'
+back = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABQUFCQkJDQ0NERERFRUVGRkZHR0dICAgJSUlKCgoLS0tMTExNTU1OTk5PT09Pn4AQn4AQUFBRUVFSUlJTU1NUVFRVVVVWlpaXV1dYWFhZWVlaWlpbm5ucXFxdXV1eXl5fX19az+RUUGvU0G0UkK4TUrcUVH0U1P6VVX+XV30Wlr+YmH9amr/bm7/cnL/eXH2e3v/BJUAFYUAGIQAAKMAAKoAC60LEa8QE7ASGrIaI7UjKbcpK7grM7cpNbgqMroyPL08e4UAZb48Qb9BRMBETMNMVMVUWcdZXchdY8pja81rcM9wddB1fNN8Z5a2cJuqlkJ0mkNyzktfykpg81FS+lNT/lVV/1tb819p/l9g82Bs/2Ji/2ho/21t/3Jy/3t7vHy+gXn2mn3hvH3A3W+Q3XCSgYYAl749mL08vZUAwpYAyrcpyLgq7aMA7K8Q8KQA/qoA/6wJ/68Q/7AU/7Md/7Uj/7cp/7gr/7oz/7499Zhr/5ZnzsBD/8BD/8NM/8VU/8pj/81r/89w/9By/9J7gYGBhYWFiYmJjIyMkJCQlZWVmZmZnZ2doaGhpaWlqampra2tsbGxtbW1urq6vLy8hIT/k5P/mJj/gKfCoZjYpJzYoaH/pKT/qqr/rq7/s7P/u7v/gtWCiNeIi9iLk9qTm92bo+Cjq+OrsuWyuOe4vOi8/4KC/4yM/5CQ/5WV/5ub/6qF/qOj/6mp/62t/7Ky/7W1/7m5/76+wcSDwcaJ/9WD/9eI/9mO/9uU/92c/9+g/+Cl/+Kr/+Sx/+e5/+i8wcHBxcXFysrKzc3N0dHR1dXV2NjY3d3dw8P/ycn/0dH/1dX/3Nz/w+rDy+3L0e/R1fDV3PPc/8LC/8XF/8vL/9TU/9nZ/9zc/+vE/+7N/+/R//DV//La4eHh5eXl6enp7e3t5eX/7Oz/5PXk6ffp7Pjs/+Pj/+np/+3t//Xj//fo//js8fHx9fX19PT+9Pv0//Hx//X1//ry+fn5+Pj++fz5//n5//z4/v7+AAAAwISkTAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABclSURBVHhe3Z15YBXHfcff0wkoQIsQAnNIpGlcFWLqtEGA6tYkMTS2oadLDzdO77vp5TZNL/cIt7ksuWnrxA6JDxK7pooP2rShcVqQkKjrJG0wmKa20GsOgRspAeTgob/fzG/v3fdmZn/v7Vt//rCl92af5sPb/e7szuxM4WoFRF1BlapEBSv6sPqC6laGslb0KfUJ1TGWMla0dZ1DlQ2SaEUb5QCqsJ8EK9ogH1CdfcRaUencQNX2iLGiormCqu4QsaJieYNqT4StqFD+oPorQlZUJI+QgSRoRQXyCTkgASt6O6+QBeC3ojdzC2kAPit6L8eQiN+K3skzZOKzojeinDw+0F9XDBwfpapFIBfXil4OcXJ5e1OhDmmc1z1CVQxCNuWs+ufTh9Ql7Qeomn7IhqzoRT/jHbR53dI+RlX1oXSUFb3kZ39d7npBmvZQZT2kTqLVbtqwztlB1fWQPtKKXvCRE6kYrTJWB2ib8hSbW2dkvp/upSq7JFqNN9MmSTTNX75vuKTK7l9AL2ZDYzgyEq06aYt4Xrd1mMoRI3PpnUyYT7VwSbA6RuXjaOqKO/0to3cz4R6qhANZ0W8uyV9V664pKiMunX3+qY//zX33Pyd/y1KrXdbAR6zVGJWO0LRzWpW4cOTxd24BfrAHuO4/8KUsd8JIszDOajsVDrNYxcOlp9+FRsBtb0Srnp4H4NUTVCgLumW9fMRZxWda64B88/zhHyOnLVter6R6evDbyjAJo7sgWNGPLq1UOECH/KIu+Jy2/Mi1JNWzCt7aRwUzoAmr5ifGapzKBlgu33rK57Rly7eSEwCREbtZjYgcWFGrESrqoyhbkRPO8aSQUUHgkdVI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'
+r2 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAA/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3l5/3p6/3x8/35+/4CA/4KC/4OD/4SE/4WF/4aG/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5KS/5SU/5aW/5eX/5iY/5qa/5ub/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7a2/7e3/7i4/7m5/7q6/7y8/76+09PT1NTU1dXV1tbW19fX2NjY2tra3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4+Pj5OTk5ubm5+fn6Ojo6enp6urq6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+bm/+jo/+rq/+vr/+zs/+7u/+/v8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0cgG7QAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABLQSURBVHhe3Z15QxRHGocdBgcEQVwSNR6wKsR4xIsENBohaASNQI5NdhfwjjEuKxpybJJNNsEbybEehDURYegPOtvT/aP6qGOqqqtnun3+mZnq6qYeeqa7uo63lhVEvP9fyypY+JAMrCK/vItPbPhSvxRl/rPoHCRp/PF3u2w/OcVkwZH6pVD4CgdILAtcL6bUYuEL7Jhw8ihwCIbUYuFX7JMGPkSp/VBSPxd+Rva0gIL7oKQ+QtYUsYiiE4JSXxcWkDFdfI7yg4DUE/cukEJ+h4GLXyr/N2RJI3Bw8Et9i+3pBBJFfFLfY2tagYYNkXryL2xLLzDxpL7+C7akGbh4ZwrpqcauDTosSSE55XzryrhSP9vPTc8Fjs3SmUIagwdXL19KFlcmnqFsDBwbVwopYR6f3P2nTAJZ3nrgE87T6xdE6nOkBLnZVYODJJGXTj1FOYMQKXwOMN+Txe5J5YUxFDXAfyDFqvJNbsSuCabq8DxK6wdS+OTnWj12TDa7GFb2YwhbKiVObCtH6nd88LiXFqdM5jUU2Ycjhfceiy9jjzRwDoX2+IEpdQr5A2Q37Njz6rbV+JQcGh+i1B62FPUYNVuH/B5rj1+dczdOXzi4AokJ4ZBbMB+2FN55UCdqxyVscfntnRewIRHUzaJcBIbU4nrkBo1nscFj7nAVNiaBAZSK8D0tdQ15wS76O2szlqA64WaUyYOWOom8LvvzSA5xpxkZKk+OulfRUh3I68BzSpTVdRSJsOw9vCH4f1JbuU6WdSuHTBWH+lEtox47GpHVpuY20pj0IVfFOYoCEZZ9iDcE323oJJIcpkYHBi/gbuWQ34JslaYbBSIs+xJvCJ5Us+/L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'
+r3 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0/1VV/1ZW/1dX/1hY/1lZ/1pa/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Jy/3Nz/3R0/3Z2/3d3/3h4/3p6/3x8/319/35+/39/gICAgoKChISEhYWFiYmJioqKi4uLjIyMjo6Oj4+PkZGRlJSUlZWVlpaW/4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5OT/5SU/5aW/5eX/5iY/5qa/5yc/56e/5+f/6Cg/6Ki/6Sk/6am/6en/6io/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7y8/76+/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7u7u7+/v/+Dg/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8/Pz9PT09vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+fn5+vr6//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA75ob3AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABOtSURBVHhe3Z39QxTHHYdteweCUDSgUYMBJS9N39JXI7EYojEq+IJGQo0GCvgWNSI10RASmqavhhhjlNA2DVU0CZ7H/ovXvb3Pzc7uzM7O293t+vxyx8zs3T7s3u7O23dWFAT8pvDXZSeJ5D8q/BL7yCNS6vkCPiCxLBd+jH0NEyWFDRPOMvY2BFfqH9gmDXyMfabhSP0NxdMCdpuClULRNIE9J4SlvkK5dPEP7D0ISaFQ6lj+BQQ8glIokkZg4BGQQn46gUMRWgq5aQUWLpQU8tILPGgp5KQZmBCpnyE93UCmLJVHcrr5piQDqY+RmnZKNpBCGofF6SuXk8XVD+9j3zj8qGhTkoo4+ZZO7d6YSSDZTXsvPMQ+hvjKl0JKkNtHWvAhSaRtaAH7GYRI4e8Ay6ON2DyptFzArgZ4KJCa68amSWbXXewtDaQ4jSu31mO7ZNN5B/tL8V9P6uf4iyIlTnwrT+rP+MPn/hPYJvk8zV64PSm8pziALdLAceyzz7Ir9WO893kX5YM0v9Dbu7UZfySHlZ9gr314R2r5SZSnWH/i81LmZ2+sQ1JS2F7aMQpX6hu8JVxBaZ/V56gzN38mYffkz7BjhI9WsD+pXhQm7Ajdu+e3IyMZHMRuEZZZqcU6FC7zCnOByb2MrETQzOwfKxW+TLzEedrNJepYXcdeEVipYygKHuPc3twzMEm/qzPYKQIrFTq1LiI5xFlkJwHmR8VKPYuiJdqRGiafoAep3dgnwgqmxaULRUuMItXl87HxL/DW5QQKJIBe7BKBPVJbULTEPFKd3KtZt8q5j1Q4b6JAAngJu0SIkWpDouPsKiXsxZ+Ok5xLharUDiQ6s0jI3kSC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'
+r4 = b'iVBORw0KGgoAAAANSUhEUgAAANQAAAE/CAMAAAAJ9B3fAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwNDQ0PDw8Pz8/QUFBSUlJS0tLTU1NUlJSV1dXWlpaXFxcXV1dYGBgYWFhYmJiZGRkZmZmbGxsbW1tbm5u/1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Jy/3R0/3V1/3Z2/3h4/3l5/3p6/3t7/3x8/319/35+/39/urq6u7u7vr6+v7+//4CA/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5mZ/5qa/5yc/56e/5+f/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ys/66u/7Cw/7Gx/7Ky/7S0/7W1/7a2/7i4/7m5/7q6/7y8/729/76+wcHBwsLCw8PDxMTExcXFxsbGycnJysrKy8vLzc3Nzs7Oz8/P0dHR0tLS09PT1NTU1tbW19fX2NjY2tra29vb3t7e39/f/8DA/8LC/8TE/8bG/8jI/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm6urq7Ozs7e3t7u7u/+Dg/+Li/+Pj/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6//j4//n5//r6/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASP4oJQAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABDtSURBVHhe7Z39YxTFGcdTa99b+4oJgTRAIFERkqooUAtBSoiABBEsIUIJIK+GWvtisa1W25KAsWmAIFparW/QiIQ3a0F5qybhsn/U9Xb3ezO7O3N3z+zO7u2k+fxytzM7y3643N7uzDPPVGSL8eCbGSuNjL39DM5QSiGpb2afG8MRUsufca4CcqlJv0y9kctLOGE/Uqk30MQEPsQ5e5FI/RG7m8K7k3DiDFEKu5rEb3DqeQJSi97GfmbxX5w+CEil8wpOAOfv4pW6zcQ/vTzPQcLGK7UI9WbyJ1jk8Eg9jVpT+Qc8PFLfMPlvz4X9EvNPCjUmk78hZFIoNxu4QGrRf1BsNmOuDaSeRanpvOPYQAplEoZfP9qfLo68egXnJsGxcaX+jaIAmd61TZMrU8jsVV3DOMcAzh+gK4USP1e334ljpJHp7Wdwnn6ehdSDn6LAR+8sNE8rU3ZK71QhJfugrq9B0zSzcAhn6+UXrpTkG3X9AbRLNw2ncb4ect8qWwpbHgxxklvZUt8Sb87HlqBN+rnzGs6Z8679Sd3EBmcPWpjAGpyzB1sKbzmna9AgwP0rwb0oSAW9OGuOVGoFdg9Qy37Il6IkFcwWLuy/r8j+AW8Z5wrcRDyBeus1FKSEV3BajEyF2NeyCTsHqPkY9VYLSlLCEpwWp+LreMNpwM4B2lFtnUBBariAE2NUCF+p89g1wJSLqLceRklqEC4VotTL2DXAT1BtnUJBetiMM2OIUpuxq58p51FtrUJJehC+VKLUOuzqZz1qrcEqlKSHe3BqDFGqDbv6qD6LWnl1eZmLU2MQpdai0jqdwifhkFKT2VPmoyhJEyGl2lBnnalGSZoIJ1X1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'
+r5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPDw8Pz8/QUFB/1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/25u/3Bw/3Fx/3Jy/3R0/3V1/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+k5OTlJSUlpaWmZmZnJycnp6en5+foKCgoqKipKSkpqamrKysr6+vsbGxs7OztLS0tbW1tra2ubm5urq6vb29v7+//4CA/4GB/4KC/4OD/4SE/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5OT/5SU/5WV/5aW/5eX/5iY/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7q6/7y8/729/76+wcHBw8PDxMTEx8fHycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/87O/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5eXl5ubm5+fn6Ojo6enp7Ozs7e3t7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TpPMwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABPrSURBVHhe7Z35n9bEHcftld2VZZeVQ0SWywPQ3vdtixUXqaJSClK5u4iwImXtutvb3pcgRURcFxTkUNrS1l4CUhTQ2kvAhday7D7kH3ma4/N8kzxzZDJJniSv8v6BJ5n5ZjJvsrkmk8klZRmf+Nl/zVzy52+/H1XkIrb6ek6FPP7wPlSVQWD1qSEsmXN+h/pWwbX6PpYpAv9+Dyrth7X6yLcQXxT+iYr7YKzeVUJwgXgYdSeqrD77UwQWixKqXyFo9a5/I6xwfBMGLkGrC4gpIAeg4OC3+gACismfYWHjs/ogsovKa/CwIKsPlJFZXP4EFc/qg8WXMs2fQ4aszDeRU2g+AxtYmQeQXnBcG1i9+WGkFp03HR3X6oApPlENHtzZly927H4FdePwEFl92BRcJ114+ktThxk55PJZ606hjtWQ1QX+8W/gwckoJI8Mm/cC6hnk97D6qfk8UgLsnYDl80rdkgFUNQCsMBdkqL0eC+eYCc+itn6ed6yeN3+IeR9Dt2PBfNO0C/X141hhOkBBpPhaX7Osfmi+G3M+7sZC+afpKKrsYd1CXmL9IWLOYzsWKQLT2RYJx4qh/wonfvJtYbhxGbMWtfb4tGXF7ljtovBq7nADs6XxNGpD/MOy+iimifOj3PCCWHHqaVn9CpPEI8LoavJhNY7Zsywr5sL2JkQXxcp4CtUhOEeL0ggEF8aqA9UhPs5aHUFscaxmozrEd1mrTYgtjtUVqA7xS9ZqPWKLYzUc1SF+w1p1INaz6usUcA0iM6YO9SQ424q1mouE3IJ6Er9lr9kvWuUE1JO4aJVfUE/iolV+QT2J/2OrrfeA9mV3TqhDbp5APQklqwBntt9x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'
+r6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/19f/2Bg/2Ji/2Nj/2Rk/2Vl/2Zm/2ho/2lp/2pq/2xs/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3d3/3h4/3l5/3p6/3t7/3x8/319/35+/39/kpKSlJSUlZWVl5eXmpqanJycnZ2dn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4mJ/4qK/4uL/4yM/42N/46O/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5ub/5yc/52d/56e/5+f/6Cg/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ur/6ys/66u/6+v/7Cw/7Gx/7Ky/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/76+wMDAwcHBxMTExsbGx8fHyMjIycnJz8/P0dHR09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3Nzc3d3d/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u/+Dg/+Hh/+Li/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u/+/v8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6r+4xAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABV+SURBVHhe3Z35YxbHfYfpsa9eBAhhECABsjC2MaRO3LS1G6dN0nIYsMCACSaAwQILDOJQOAzI6Zkmbdo6AgFCxpj7MiaOU7dukA2YK04b21yWnVhIr/YvebvH592d3ZnZnZnd9313+/xg7zs772of3j3m/M6gfBBP/svneiL53x8+gVNkwrf61ic4QmL56M9xqhQcq8cTr2Tzq0dxwl6YVj/Ad9JA7kmcNAlt9Y2/GMAXUkL/YzhzF9oqJdceyXs4dQef1V//LTKmjG/g/IHX6o/eQ67U8SoMbLxWv0OeFPJrKFh4rFL2mPDyW0iYkFbYnVZ+Bw0Dx+pP0v1LmXwBFdfqT9N8TxX4CDKOlf7f2JNqfgIbWOn/gPSU87itY1v9Nu1PCgdLx7b6uf4FEmly7588cjhRHD31If/B9q5j9YT+HaT5ubB66jAtgYx4av1VnKIfx2qAff3l9k3DQZJIZu4xnKcX6/FuWP2b/vdI8XB5Cr6fWBbcwql6+LpthU8+dg7FdxPMqIM4WRKz5DQo/x/6k/hMsg5fTDaZ3ThdEsvKsMNHgnRIsbV+YVj9WGdcgi/jS8kncwSnTGBY6for+OByKQX3VIExd3HSLl81rahibW4yvuGhakrjM7OmjMSn5LAYZ+3ytmFFX4B7kN8lM6f9g5y1L3d23SQkJoW3rBMjYVo9jOwFhjZdxh6b60uwIxnQP5Zh9W1sOpxD7gJTP8QOlxPjsS8JVFIvY8PqbWw6rEBum+wW+9Lzcm9dBvsTwMs4KYfvDNKpk34QmS2y+5HqZwcyJIDv4pQc/t14BvroG4zMJlwpXV+PLOWnHmfk8DFt5bmttiGRxTLkKTuZHpyR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'
+r7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1pa/1tb/1xc/11d/15e/19f/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlZWVl5eXmJiYmpqanJycn5+foKCgoqKio6OjpaWlpqamq6urrKysra2tsLCws7OztbW1t7e3uLi4ubm5urq6v7+//4CA/4GB/4KC/4SE/4WF/4aG/4eH/4iI/4qK/4uL/4yM/46O/4+P/5CQ/5GR/5KS/5SU/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6io/6mp/6qq/6ur/6ys/62t/66u/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wMDAwcHBxMTExsbGx8fHycnJz8/P0dHR09PT1NTU1dXV19fX2dnZ2tra29vb3Nzc3d3d3t7e/8DA/8HB/8LC/8PD/8TE/8XF/8bG/8fH/8jI/8nJ/8rK/8vL/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9XV/9bW/9fX/9jY/9nZ/9ra/9zc/93d/97e/9/f4ODg4uLi4+Pj5OTk5ubm5+fn6Ojo6+vr7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Pj/+Tk/+Xl/+bm/+fn/+jo/+np/+rq/+vr/+zs/+7u8PDw8fHx8vLy8/Pz9PT09fX19vb29/f3//Dw//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA46UD8AAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAA93SURBVHhe1Z35YxTlHcbTY0NCFBpbClgExFCO1lZ6SIutRxWJKIqAQhURzxpEsIh4tLb2sK01giJQpAERRcSrVlsNKEeg2iqCIXhA2My/Mt2ZefadnX3neI/vHO/nB3aO9528H3b32dmd932nwY5j6sP/swrJsT9OQxNDibb60Xs4QmE5dD6ayhFhdfZ/ULPgHDoXDQ4SajWtjEom8CAaXQtv9eMpJ1HeEAZ+gpb78FZvorBBHELTGXVWP5uGgobxa7QfBK2+/ShKGccbMPAIWr2PMgbyGRRcAlafooSRDEDCodbqM+w3FWhUYFbftz/BTmPxn62q1Q/swp8gJcPeW1Ur6xHsMZp/wQZW1rnYbji/8XQ8q09tbDUeV8ezesV6HRt5BvY9t6WrUGzetjv67PsYs5pqRT1V+2+f0VoqIKdMXvw2mljPhVWrgYhQf+aKRhyliFz8VPgzBqs/W9/DhgCHr0L1wjJ5H5oa4CHPyrLCzpQ2fg11C0zLSjQ2gGv1j9B31eNFfvH53Ibm1jLNsbKs17BagyFSoVqfVqz+EPZUbTZFqlRagSbXULGyrO9ixad3OKoYQMseNNrnAcfqZaz4zHPLt16VzBluyVyZyAX8ZxUr/gX4old8AlbjuNErmitr0BafUCvvqTLGim9nmNXh5qjSPEWwKu1AYxgXNFgXYpGxAoWNsboOjWG83GD9BYuMuShsjNV4NIZRbrA+xCJjDAobY9Xcj9YwKsleR1/1E9gYK/6NxVv1oKhBVn9Haxi81Tso6lvtXV4P+89ZgLL5sh6tYYhYrccGn27s6R+GDfmyDs1hOOfsQQSs2J512JAzNFaPYYfVjg05Q2I19Dh2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'
+r8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPT09Pz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Nj/2Rk/2Vl/2Zm/2dn/2ho/2lp/2pq/2tr/2xs/21t/25u/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3t7/3x8/319/35+/39/k5OTlJSUlpaWmZmZm5ubnJycnp6en5+foKCgoqKipKSkpqamq6urrKysr6+vsrKys7OztLS0tbW1tra2urq6u7u7vb29v7+//4CA/4KC/4SE/4WF/4aG/4iI/4qK/4uL/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5qa/5yc/52d/56e/5+f/6Cg/6Gh/6Ki/6Oj/6Sk/6Wl/6am/6en/6io/6mp/6qq/6ys/62t/66u/6+v/7Cw/7Gx/7Ky/7Oz/7S0/7W1/7a2/7e3/7i4/7m5/7q6/7u7/7y8/729/76+wcHBw8PDxMTEyMjIycnJysrKzMzMzc3Nzs7Oz8/P09PT1NTU1dXV1tbW2dnZ2tra29vb3d3d3t7e39/f/8DA/8HB/8LC/8PD/8TE/8bG/8fH/8jI/8rK/8zM/83N/87O/8/P/9DQ/9HR/9LS/9PT/9TU/9bW/9fX/9jY/9nZ/9ra/9vb/9zc/93d/97e/9/f4ODg4eHh4uLi4+Pj5OTk5ubm5+fn6Ojo6enp7Ozs7e3t7u7u7+/v/+Dg/+Hh/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8PDw8vLy8/Pz9PT09fX19vb29/f3//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXn6cBAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABYNSURBVHhe1Z35YxTnfYfVYxdJyAghQMiYw0KSFTvpmTg90tZtJTCYOBibIB8EsCorHAoGQznSNG2aJo3jxLLAXEYGc1t13bqpU4SMxaUmbW0QshobHav5T6ZzfPadd+Z9Z+Z935ndnXl+2d33fWc1j2Z39j2/b5kexO//3X9qieSzV/4Ep8jF3+r3foZ3SCyf/Q1OlcHP6t9wZMKZ+jOcrxuu1W//Hw5KA/+Ik6Zhrf5Q/1+UTwvfxZk7sFY/RdkUkfsCzj2Px+ov9WmUTBcv4/yB2+oLf4tSqeMjGNi4rf4VZVLINBQsXFYJ/ckV5IuwMKCtfoHstPIleFBWX9TfR2Z6gYpj9SX9J8hKM5AhVtpfICPVfAobWGk60lPOu7aObfWp/imS086XLR/L6l3te0jkcPPsyb5k8dbAJM6Nxf7ZMq2+7Pv5u71j1fxMAqlsfuYtn6rdj/NW0/q/I8nNpXWVeJck0rBvHOfpBlY/5l+q8Y1ZHJ9UFp/Hqbp4z7YyniCB5uJiHJtgZnRO4WxpLKv3uJfqdBWOTDZPcLR+aFpp2rfxkiIlUnwtw+qHmp7DK4cP7sFByedZnDLFb+llhhpeOORacEgaOImTdnjPtHoELxy6cYCbuhVffaw5eff6BaM4awfDSv8fPCeMzMQBFM09w1be5NvfqEZSUnjBOjEa0wpPHdhLtfQsskzGvlmO5GRQy9Sf/ohjlatHccLmCWSB/iXISAa9OC3COxyrkyhM2IEMh1v3IysRLMdZEabLtK/gKWEbCufZgnSaWwuRmQSqmYpumfYPeEZYjcLgQfbnzOB0kiqJH+CkCGXaO3hGWICyNhUfItnDBuQnAeaLVaYx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'
+r9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAALi4uMDAwPz8//1VV/1ZW/1dX/1hY/1lZ/1pa/1tb/1xc/11d/15e/2Bg/2Fh/2Ji/2Rk/2Vl/2Zm/2ho/2lp/2pq/2tr/2xs/21t/25u/29v/3Bw/3Fx/3Jy/3Nz/3R0/3V1/3Z2/3h4/3p6/3x8/319/35+/39/kpKSlJSUlZWVl5eXmJiYmZmZnJycnZ2dnp6eoKCgoqKipKSkpqamqKioqampqqqqrKysra2trq6usrKytLS0tbW1tra2uLi4ubm5urq6u7u7vr6+v7+//4CA/4KC/4OD/4SE/4WF/4aG/4iI/4qK/4yM/42N/46O/4+P/5CQ/5GR/5KS/5SU/5WV/5aW/5eX/5iY/5mZ/5qa/5yc/56e/6Cg/6Ki/6Oj/6Sk/6am/6en/6io/6mp/6qq/6ur/6ys/66u/7Cw/7Gx/7Ky/7Oz/7S0/7a2/7i4/7m5/7q6/7u7/7y8/729/76+/7+/wcHBwsLCw8PDxMTExsbGyMjIysrKy8vLzc3Nzs7Oz8/P0NDQ0dHR0tLS09PT1NTU1dXV1tbW19fX2dnZ2tra29vb3d3d3t7e39/f/8DA/8LC/8TE/8bG/8jI/8nJ/8rK/8vL/8zM/83N/87O/9DQ/9HR/9LS/9TU/9XV/9bW/9jY/9ra/9vb/9zc/93d/97e/9/f4eHh4uLi4+Pj5OTk5+fn6Ojo6urq7Ozs7e3t7u7u/+Dg/+Li/+Tk/+bm/+fn/+jo/+np/+rq/+vr/+zs/+3t/+7u/+/v8fHx8vLy8/Pz9fX19vb2//Dw//Hx//Ly//Pz//T0//X1//b2//f3+Pj4+fn5+vr6+/v7//j4//n5//r6//v7/vz8/v39/v7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI8jCgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAABVhSURBVHhe3Z39YxTHfYfV9g4hhGSwZMybsSwJk7Zum7R22/QlTdNaMkaigDHYCCTABgvzHgQ0tZu3NmlaN22RMAgkMCK8JWnqJiBj8WK5bRAKqE4R0mn/m+2+fG52dmdmd2Z272V5frm92dnTPrrb3Xn9ToUZxnPvfDhjlCO5H/8FTpFLiNW/4RPKlplv40wZRFb/jCPLnJl3cb5++Faf4qA08COcMw1r9UXzp8ifFr6PM/dgrb6JvGnij3HueQJWL5r/i4zp4kOcP/Bb/cYfIVfqyMHAxW/1d8iTRr4IBxuf1b8iQzp5ERYWtNUPsTutfA0elNXvpuXBG8KX4EKsfs98B7vSzG/CJm9lPIcdqWYGNrAyzPIsm6vyP66Oa/VL8z+RnHa+4fg4Vj82fh+JHMZ/8MGZ8uLcpQc4Nw7E6gXh72/i8LqFmTJkVsPr/TmcY4D/ylvNmN9Akp+Rrlp8SjmyYPcvcJ5+nnOtvm+YSPCR21uF48uVx0/hVH185loZxrtIoLmxAseWMxvv42xpHKufcL+q6/U4sLxZztH61LYyjN/CW4qUSPG1LKvvGebP8M7j3gIcVP6sZG/ff2lWWGp4Q7EBh6SBgzhnj2m+VT8O8JFdumr16pefxLvyofo6ztrDsjK/i21Cjn3y1u88d8/deXew6zEklglr3BOj+LxlxTykma9q+fvT2OUweWQZdpQFs27jvAj/ZFlh02MlsoO5h5DuMfVWJXaWA2/irAg5jtUnyAyWjyDdx+Wl2F0G1OOcPDhWJ5HZpVVQPr5TRr/CT3BOhArjBWwR3kBeB5FUWWn145QIFcaXsUWgL6vFE0jkcLtsSvTMhVVhMK0wjchr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'
+y0 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiIiIiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0BAQEpKSktLS0xMTE5OTk9PT1BQUFJSUlNTU1ZWVllZWVtbW11dXWBgYGFhYWJiYmRkZGhoaGpqam1tbW5ubnBwcHFxcXJycnNzc3V1dXZ2dnl5eXp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoODg4SEhIWFhYeHh4iIiIuLi4yMjI+Pj5CQkJKSkpOTk5WVlZaWlpiYmJqampycnKCgoKKioqSkpKampqioqKqqqqysrK6urq+vr7CwsLa2trm5ubq6ur+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsTExMbGxsjIyMrKyszMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NbW1tjY2NnZ2dvb293d3f/qwP/qwv/rxP/rx//sxv/syP/syv/tzP/uzP/uzv/u0P/v0v/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Ofn5+jo6Orq6uvr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAHrYiUMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAATyUlEQVR4Xu2df5wUZ33Ht9ra2lh/tNa21ljbmBil0Vp1j+M4OCCQu3CQAwnhVwg/EjgCgUDANqaNqVVr1bRqld+EI/y4C+EgEEitabVaf8AVKFACAY0xNhwcKDX3I9yS3Vnnx2efeWaeZ2ae55nZmZ3Xa99/hNnneXZ33rnd2Wee5/t8n0zRm7e/+8F//s+XXtMqjqs//dY//dW73oHT5OBl9d4/e/i/CniRCqXwnYfei7N1w7e65i9/iKdWON/70Ftwyg54Vm/99C/xpBRw+eHfw2lTsFav/2SKnAwuf/QNOHWC2+qmP/wRGqeIH9yEsy/hsvr65yr8EsHntU/9OgQsnFa/+x00Sx3P/j4UTGir6679GdqkkJ9cBwsDymrIO1N2mXByeQg8dGyrv/3jV1GfUn5paxGrz1/7CmpTy2XyISxZ/ePb/g91KebF0iUDVo8M+R5qUs1/4AJvWX1A+wLKU85nTB1YXXkPStNOweplmFY//rWfopTDYM+5CqMnh1Pj8GOzT2hYfVH7DMrc9O64t2VotuKonbSkox+n6OahklXhTVdQ5OT0kuF4mQpkxLIzOE0nrxg3JrrVD7QvocRB/xI8v1KpWT6IU3XwWdNqiPZbV1FA09WIJ1cw44/hZGlefath9RPtETym2VWBXyeW2n04XZpPGFban3N6FemQ4mu9cEMx813tT/CIYn9KpHStIzhliuuLGY1zrei9Gc9JAU3sJf6zutWN7AdwAZ7hpKFpQlMDjiuIpThpmxd0qzfj2KYL7SnGreg8Z9Z1737gFpRVCifNE6P5g4x2Ew5t5qI5YfqePKoM8k/NQHllsAjnZXND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'
+y1 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTlBQUFFRUVNTU1RUVFZWVlhYWFtbW1xcXF1dXV5eXmBgYGFhYWJiYmRkZGhoaGlpaWpqam1tbW5ubm9vb3BwcHFxcXNzc3V1dXp6enx8fH19fX9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wE/+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3Kf+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/DS//DTf/ETv/EUP/FU//GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Uf4CAgIGBgYKCgoSEhIeHh4iIiImJiYuLi4yMjJGRkZKSkpSUlJWVlZiYmJqampycnKCgoKKioqWlpaampqioqKmpqaqqqqysrLCwsLKysrm5ubq6ur29vb6+vr+/v//UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/dmf/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcLCwsTExMbGxsnJycrKysvLy8zMzM7Ozs/Pz9DQ0NHR0dLS0tTU1NXV1dnZ2dra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ujo6Onp6erq6uzs7O3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAAvkMikAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAOwklEQVR4Xu3deZwT5R3H8VRbe1hrLw+0WouKWrS2FrMHLHLIscqxIqJsC4qC3LgqWM9aa7WltbbaCgIKVASRywXU3traVi2Iq4Cg1Wq1FhfZ9YAFFskmneObZ45nknlm5vdkZvKazz87mUyenfcLkp0kc6RyhfvS4d1++qc39mYj1/63n/rFjV89DKvpUCHVCced+cf9GCSqPXvLCVhbe86qz5z8Zzwy4r123eewypacVIde8188KAbtuf2LWG1TvOrAU9/CA2LSnlsOwqqz7KrTD38SC8eoN4/D2uezqX7dbQ+WjFc//zgAelbVF+7CUrHrn18GQcus6nz001gmhr3fCQo1k+q0I9/EErFs74lwKBmqmzq9jftj2v6TIDGpbj8q1v9Sah8dAwtT/fjzMX5O5fsg/5IB1c2nxfbVz9zreIHXVV2z3TA/5t2tcaDac2w8//jyna55NNWrHyuymZRpaX4nWu1ox6o59L62TaiqZmZPxTx77cunDe+ejlwVgyc8sAOraO/OvKrjYOet9ObpvTFMBKu+/EWsprUO9Y2Jono6eybmWMrMqcIAUe2yVqyqpcc11anZTzq9SdwyDI+NcH0ewcpaOlRVvZ49GTfNNdXgkdFuIVbX3B2qKvsNh88oYoJyZO3ukkv9LfuVDtw02hIXVDq9FKtsqmsulXV4rcjE4DmVr+YdrLTRY4rqlD/ghtEcPAL1HIL6YUakGsn9V9urqA75CDdY260v6X22YH52GeZEq+VYO6NOqezpmDSagcX1DFREVcOxdkY3pbLfxiSrvQ8W1zKhIqpKb8TqsX6Vys7EJGsFFtYyo6KqmozVY/0n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'
+y10 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlFRUVJSUlVVVVZWVldXV1hYWFtbW11dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWhoaGtra2xsbG1tbW5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/Tff/UfoCAgIKCgoODg4SEhIaGhoiIiIqKiouLi4yMjI6Ojo+Pj5GRkZKSkpOTk5SUlJaWlpeXl5qampubm5ycnKCgoKGhoaKioqOjo6SkpKWlpaampqmpqaqqqqurq6ysrK+vr7CwsLKysrS0tLW1tbi4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsHBwcPDw8TExMbGxsfHx8jIyMrKys3Nzc7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5efn5+jo6Ovr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAM9q+HsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAYc0lEQVR4XtWdeWAc1XnAt3dpKGkbSppSjkDTxAmj2xK2ZRnjU7Z8gPGJMTbCJ24hJJSkaQu5ILQpadPEt3yCjeVDtrGTNqVtCm5DsC2f8tHmaKkl2VYJtkWJRFazmePbN2/m+97MezOzs7O/fzz73ux6ftrZmTfvfe97mZyYX7v5L77x+lsDeur4yX9+66nbbrgGDpNAZPWhG/76f+Ez0spbX7vpfXC0Xmira7/8E3hrunn3q0/+ChyyC8rqg9+BN5UC3/3Ar8Jhc2Cra74F+5cK//KlX4RDZ3it/vDJ92Dn0mHgCx+Go8/jsbr232HP0uJH3/gFELBxW938DuxWarz3iV8HBQve6obPwj6lyFf+ACxMOKvbn4MdSpNvDgIPA8fq01+F6lLl258AE87q81+EytLl67eBC7P64p9AVSnz9HVgA1af+a0UNmLVuRUu8LbVh/W0N2XleOe7lg5YvVtqrSQRrz5h+VhWP7gZCimudHemi+7LPr+WR602oWn1rP4mlHk5uWZGvZY+hkxb2S4we+eVvNXAk1Dkpn9HE3xKGhm7tReO081z19tW/6G/DSUujt0N708r9fvhSF387KBldZv+BBTw9C8vgzenmOarcLQ8z/6OafVj6qreNw3emG4mXIbj5Xj3H00r/ffhJUeJSNFaH78xl3lV/ya8chiYBW9KP01ZOGaHg4/nMsYTF7xy2AZvKQXWwDFzfM+w+iBsO3TVwDtohowYNWrEEHhRdCpOwlE7fMyw+gJsO8yBN2AaZq99+aK9U8+BdXNGQHFRabKPh+Pvb8no34NtRlc57O+h4v7DsAfj6LxKqCwiJ+BgGG89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'
+y11 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0tLS0xMTE1NTU5OTk9PT1BQUFJSUlRUVFZWVldXV1hYWFpaWl1dXV5eXl9fX2BgYGFhYWNjY2RkZGVlZWZmZmhoaGlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3R0dHV1dXZ2dnl5eXp6ent7e35+fn9/f/+qAP+qAv+rBP+sB/+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Na//ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZOTk5SUlJWVlZmZmZycnJ6enqCgoKGhoaKioqSkpKampqmpqaqqqqurq6ysrK+vr7CwsLKysrOzs7S0tLa2tri4uLq6ury8vL+/v//UgP/Ugv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/dnf/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcLCwsTExMXFxcbGxsfHx8rKyszMzM7OztHR0dLS0tTU1NfX19jY2NnZ2dvb29zc3N3d3d/f3//qwP/rw//rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09PX19fb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAD9msOwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASQElEQVR4XtWdCZgUxRWAJ3c8IsYzhnjFMwfRnnUXkJtFVEAUxGNFFBYUVI7EK0ZDjFcukmhYCTdEblwSRIkxQQ1JTFROLyRqojHcq0YFVlnd7Ukfb3q6u6q733vdPdP1fx92dXfVTP3uTE91ddWrXCGYzx313V/+9e02PXN88Nqf7vjGEftBNSUEWR110O2vw2tklQ9Wnro/1NaP3OqAW/8LRbPNx7869DNQZQ8yqyMnZfBTF8Qrx38Wqu1CtNrvHoWcTJ4+5JNQdQe/1clffw8yK8S9J0Dti/isDngMMqrFO1/6BAjYeK2OVeMiIeEHnwcFC7fVESd9BHkU5LGvgIWJy+qkGyCDmvylA3gYlKxuuglOq8rfTwMTl9Xt34KT6rL6RHBxrO44XLFfKRkrDwIbsLrl4PfhjNLcBhd42+oE/Sk4rjZtX7R0wOrD78Nh1XnzZsvHsnr12JAv1d4dW7PFtqaQ2v7YahOaVnfpq+GYny0zhvXRskfnweNWtEIVfbStKlq1HQOHvLQ9fGkeXiaD1E7fDfX08uRhttVT+qtwxMPmC6B8Vum8QPpJPNSyOlFvD/tu2uZ2hMIZ5tIdUFs3TxxiWr2u/xn2XbSNgYLZptcWqK+bP5pW+pdhz4UiUnKtO9sXcqv122DPxQQolH16N0GVS7x3YyGn62IP2doMX/v8DIc6uzjEsDoS0iX2Bv1G9TzXTwb0G6HWJe4wrL4J6RINkF+gz3bI4dANzlSQHi1QF4fXjs/pkyDtsC+4qoJWBqy0xVCXEnflxK/VIsgtw6+VBavzoC4lDs6JP8GDILcUn1YWrLQXoTIOp+WEi0VrDWSW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'
+y12 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAFACAMAAAAcQsn1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAAICAgYGBg4KAAkJCQ0NDRIMABcPABERERUVFRgYGBoaGh0dHR4eHiUZAC4eACEhISUlJSkpKS0tLTAwMDY2Njk5OTo6Ojw8PD4+PlI3AHZOAEFBQURERElJSUpKSkxMTE5OTlBQUFJSUlRUVFZWVlhYWFpaWlxcXF5eXmBgYGNjY2RkZGdnZ2hoaGtra2xsbG5ubnFxcXJycnV1dXh4eHp6enx8fH5+fo5eAJNiAJxoALx9AL2BC5yQecCAAMSCAMaEANaOANmQAOGWAOSYAOucAPGgAPqmAPyoAP+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSf/DTP/ETv/EUf/GVP/GVv/HWP/IWv/IXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI6OjpCQkJOTk5SUlJaWlpmZmZycnKCgoKKioqWlpaampqioqKqqqqysrLCwsLKysrS0tLi4uLq6ur27ury8vL6+vv/UgP/Vgv/Whf/XiP/Yiv/YjP/Zjv/akf/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMLCwsXFxcjIyMrKyszMzM7OztDQ0NPT09TU1NbW1tnZ2dra2tzc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5Obm5ujo6Orq6uzs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vLy8vT09Pb29v/68P/68v/79P/89vj4+Pr6+v/8+P/9+vz8/P/+/P7+/gAAAHdvKjQAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWDklEQVR4Xt2deYAVxZ3HCxZ2PbIbDMGV3RDBA1BchEjQva9k152BgUFAUA4PRETkkkPwQCLHGrMSF3Q1GuO6yDWAUUBAcBSTJRIP5D5UJHiCyKAwMwww/dLd79vVR3VX/6pfd7/X+fwB9epVv+7PvNe/rq6ug+WCOa/9Qz9/8/PTWsnR8Mlvnrjy/NY4TB+CrC5t98hmfEapcnrjVefjaL34W7V98CNsWuK80fnbOGQXflaXPNqAjTLAZ7PPxWE7EK1aP5IhJ4PPuv4pDp3jtfpeh09ROENs6oKjt/BYtX0SBbNFw5VnQSCP26rzuyiWOZ45DwomTquO7b5GmQzyzmWwMHBYdb20BC+4dD7tDg8d2+onl2VaStM+vwomDqtHL8q4lP5tdYULt3qswzG8l2HeaQcbWM258GO8k2meQYDPW3XRnkV+xrnS1IFVw/eQm3Ua/sv0Ma0OdJZcqE4eOVRafFHTiEPzYZNZJzSsHteeQp6XI89PubG8rOToNWLampM4RC9mHDSstL9Cjofdk3viY0qQfjO/wGG6+ax93uod7VfIcVEzEduXKj0X+v4SjWsxy3XVOuG1i/X9sXEJM/wDHKyTzy42rD7WfobXTpZhw9KmcicO10lnw0q79AReOsiGlL/Wbzrl2JtaF7xysAoblT6V+3DIDh7KMc0nVhyqxDYZYLgYMq7SrS4RG1/uwBZkrht6w+BeSKfNQhy0zUbd6gKkbVajPI1Ri7fWGls1vvfilN7IS5Oeh82DdnD6cqb9BGmbEShPoPd9ruB6fOkQvJEi87Fzm8eZ9n9IcnajNIExwt+pcWHq9ZH+QuWpO+sktP/d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'
+y2 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABUVFRYWFhgYGBkZGR0dHR4eHiUlJSYmJigoKCsrKywsLC4uLjAwMDExMTIyMjMzMzQ0NDk5OTw8PD09PT8/P0pKSktLS0xMTE5OTk9PT1BQUFNTU1RUVFZWVldXV1lZWVpaWltbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmhoaGpqamtra21tbW5ubnBwcHJycnNzc3V1dXZ2dnh4eHp6en19fX5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+zHv+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ET//EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjJCQkJGRkZKSkpSUlJWVlZmZmZycnJ6enqCgoKKioqWlpaampqmpqaqqqqysrK+vr7CwsLKysrOzs7i4uLq6ury8vL6+vr+/v//UgP/Vgv/VhP/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ou//ovP/pvsDAwMHBwcPDw8TExMfHx83Nzc7OztHR0dLS0tTU1NbW1tjY2NnZ2dvb29zc3N/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ufn5+jo6Ovr6+3t7e7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vT09Pb29v/68P/68v/79P/89vn5+fr6+v/8+P/9+vz8/P39/f/+/P7+/v///wAAAB2rsOgAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUOUlEQVR4Xt2de2AUx33Hr2mbPtL0ncQ1bmiTOI7dBjduXd8dQpKFRAUIyYBlEMQ4CIwBY4wskGnjJE2cunEa9+EmDRQLxMM2CGSCa2TLrds4zsOxEGAeAjdJQ9MIS7ZqOwglUnzay+3eV7OPmdmbmZ292/Xnn9ubmV32g253Z+fxm0SWz++8+0/v/8/v/diIHBOvfeOf//ryd+E0GfCsLn/fR56OoI+Lc5+7FGfrhW31q1O//CZ2jTY/vPfXccouWFa/8cffwU4xYOLB38ZpO6Ctfv6938YOMWHigbfj1Aleq6vf/UUUjhFvXIOzn8Rj9eXLX0fJePHML0Agj9vqt/4WpWLHD38XChZOq/dPeQZlYshPp8HCxGE17ZKvo0Q8uQceOWyrT/7e88iOK5+EicPqc1OeQ2Z8uRYuxOr+33waWTFm4g9hA6tPT/sscmLNj3CDz1t92Pj9CWTEm29ZOrD6ydT/Q3Lc+RvLx7L67s/9PRIZTAy/fD5aDF3EqTGYsOqEptXfGdM4v79Md9vSymT0qFu1cwCn6OW5SauJdzyLJDfDHXNwlAiSWv4U+09xZd7qW8ZUJLiY6IziX8lJ00s4VRfftaymGb/0VSQ4GVqOfSNM+SOsP9cVptU54yp8dTIwG3tGmxaG1tdMK+Pqz+Org5hIsbWuyCaeMy57A99shiN8m/CwGafs4LPZhMG6V6zGLjEgdRTnbHMuZ3XV/fhicwh7uJlR11AfwR9m3SjO2iZn9c7vYZswXoMdbMpv33cqY+aN9HYsRVpU2GqdtJM/SxhXY9PmAIoT5u2+gCyL/g3lyIgENeM4L8KDCeMybNrchOJg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'
+y3 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEJCQkREREZGRklJSUtLS0xMTE9PT1FRUVJSUlZWVldXV1hYWFpaWl1dXV5eXmBgYGFhYWNjY2RkZGVlZWZmZmhoaGtra2xsbG5ubm9vb3FxcXJycnV1dXd3d3h4eHp6enx8fH5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoiIiIuLi4yMjI+Pj5CQkJKSkpSUlJWVlZeXl5mZmZqampubm5ycnJ6enqCgoKGhoaKioqSkpKWlpaampqmpqaqqqqurq6ysrK2tra+vr7KysrS0tLa2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMXFxcbGxsfHx8jIyMrKyszMzM7Ozs/Pz9LS0tPT09TU1NbW1tjY2Nra2tvb29zc3N3d3d7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4ePj4+Tk5OXl5ebm5ujo6Ovr6+3t7e7u7u/v7//04P/14v/25P/25v/36P/46v/47P/57vHx8fLy8vT09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAJQ+NvAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAU6ElEQVR4Xt2deWAc1X3Ht3dJL9IcjSkFktCkJKwky5J8yadsfFs+hLGNbXziM4SQENI2bUoh0JomLbGx5QtjG98HQiW9krZxSRowNr4tt2mcUIwPqRB04Ep0Nds5vvtmZt+bmXft7ow//+zse29G89Huzrx5x++lssH8yie/+tJ//MyIHb3v/PDpP7ztphtwmgyCrG665a/ewUHiypt/8bEP4mzzYVv9xupr2DXe/OzPH/klnLIPltVHvoedksA//uYv47Q90FY3/DPKJ4WXnvx5nDoh3+r3/6wXhZPD+1/6NM4+R57Vr/8YJZPF9//+5yDg4Le6830USxrv3farULDxWn3s6yiTRL58OywsPFa3fwsFkskTD8LDxLV66NvITiqrH4KJx+pr30Rmcnn0M3AhVo/+KbKSzAO/AxtYPfwJZCSa3g/hAu9YfcJ4DxnJ5s0f2DqwunYYyUnnpT+yfWyrHz2ARAa97ZffiheXO3BqLG6z64SW1eNB37/eo2unD0zHj9oZ60/hFPN543DOqvdJJPnp2n4XjhJHJu7twXn6+dKtjtUPDGY1/cVa7B9XRh7Hmfp490e21SeNx5HgpXMR9o0x5atYH9dDN1tWFwzG03z7OOwZb6Z343w9vPmvlpXxWbz1kBApttbv3pxNHTa+j3cuPROxU/yZSV8TvvWVbAqbPtZhlySwE+fs8v4F0+oOvHE5VY49/AyqqxuEzRhRfQln7dLHtHoa2y6M71/l/ENXrawrB+f1RVJcmG2fs5ev3ZEyqCbakyjuUrG2DXkmrSvZH2WpKL+MEyP8+1OM39U8FCeMzquenKhDRjxYhdMi9F5I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'
+y4 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRktLS0xMTE1NTU9PT1FRUVNTU1RUVFZWVldXV1hYWFlZWVpaWl1dXV5eXl9fX2BgYGFhYWJiYmRkZGZmZmpqamtra2xsbG5ubnBwcHFxcXJycnV1dXh4eHp6en9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov+9Pf++PP++Pv++QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/Tfv/UfoCAgIKCgoSEhIaGhoeHh4iIiIuLi4yMjI6OjpCQkJOTk5SUlJWVlZaWlpiYmJqampycnJ2dnZ6enp+fn6CgoKKioqSkpKampqioqKmpqaqqqqurq62tra+vr7GxsbKysrS0tLW1tbe3t7i4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Xiv/Yiv/YjP/Zjv/akf/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsnJyczMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19jY2Nra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Obm5ujo6Orq6u3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAGcqjO8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAASDklEQVR4Xu2deZzWxBnH397Vth5tvVqLtNjisRcILCBUuxwrVAW5VHRFUXAFuopASyse9a5t1VZbri6KyKnAUhFQa6vV1mJVEN1yqWjLcnoDCstu3r5Jfu/kmMn7PpNM8ib72e8/bzJHNt99d5PJZOaZVNqbL7W97v7V7zdrseOjN5666fvHH4LTFOBldfwxd/wXx4grH/7+u0fgbN2Irb568weoGm/233PYF3DKDkRWRz0Zw786L/75rS/itG3wVofch/JJ4bm7PotTZ7itfjDhUxRODs13noSzz+Ky+spzKJks3jnsMxAwcVod9yGKJY3miV+GgoHd6rgJCbpKuLn7RFjo2KxOvBkFksnTE+CRwbKadBuyk8rfJsHEZnXLFGQml6dOgQuzuvUkZCWZO4+FDawmtzuInERzMi7wplU77R2kJ5v9qw0dWH16L5KTzr+vN3wMqzePRaKIPdsb4sX23Tluq5ONNqFudbu2BWlu1tde2KMofpQPrnnZw2z/c1mr5muQ5KSpbiCOEkd6z92L83Tyu7am1WrtPaQ4qO+D+nGl23KcqYPmNw2rE7VTkWCnaWYpKseYSz/G2dq5p41utUV7G/s2GoejYrzpswvna+Pg33Ur7RvYtZEQKbHWxDbp1PPab7Fn41JUij+VB3DKFm9dl05p2ifYs1iKKklgLM7ZxpaM1ZHYtthZjhouuvcBpyMhDhSvxVlbXJux+gW2LS5DBRclDcjXLkZKLOjL3Y//enJKewbbjF1lKO/iMuRrG4uREg9ewWkxPr07pXE9ZbUo7aJkM/K1EUiJCRfitCy2pL6JLYszUNrFJcjWNpcgJSaU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'
+y5 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE9PT1FRUVJSUlRUVFZWVldXV1hYWFpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6ent7e35+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4K/+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIODg4SEhIeHh4iIiIuLi4yMjI6Ojo+Pj5CQkJOTk5SUlJmZmZqampycnJ6enqCgoKKioqOjo6SkpKWlpaampqenp6qqqq2tra6urrKysrS0tLa2tri4uLq6ury8vL6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uTk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAIAkMWMAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAUiElEQVR4Xu2deYAW5X3H3941bdWkidbGkFpjUptWbWfZw11YUETlEEGR+wjIIcppo6a1qWnSNDFqeiD3ERCX+xCSpo29kpAUkFsEj6aNgZVlm7TCrpaV3Xk7x/f9zfE8z8wzz8y8M5Py+eed+T3PzDyfffed45nnKJXF/NJVf/zV7/xXj5473n3jH754w9WXoJgcRFZXX/q517GPvPK/f/f7l6O0fvhWv/onP8Sm+abnm1f9AorsgWf1oa9cwFYF4N+v/0UU2wVrdclfFMjJ5PXf/FkUnfBb/c51P0bmAvGNT6L0FXxWv/K3yFgs/ue3fwYCNl6rq/4T2QrHl38ZChZuq6s++i7yFJB/+gQsTFxWn7gphxdceb7/CDwMHKvH/gDJReW1x2Disvr8xwv9TZl87ya4kNUXLi/YVYrHt66EDawe/1gBL1MsX8AJ3ra6Tv9XxAvORywdWL37GUSLzo//zPKxrF678j1EOXSePpUvWs90o2gc/sq6JzStvqS/iJifUyun3K7lj5vvnbNNZPaBilXPlYh46dk7oQa7ySG3LDmDcnrZfY1ttVvfjYiH1lHYPq80rOFeYT9qWX1c/yDW3fS0NGLjHDOqFaV1s7uXafUD/e+x7qJnPjbMN/1eQXndXGZa6b/OfpEFkeJrPd2rXPq2/ijWXCzDRvmnXxuK7PDuZ8sl46YQaw6He2ObAjCe/U8zviv9/Vh2OD/Iyt88OIxcnFBaUGqHpwyrj2HZYYWdfSlWxXzKzpgtTR0oDfGjG0r6l7FMdA+wsxfESluD0jg8XWIvwduQuyhWg5hf1tWlDzI3tuOQuyhW2n4Uh3isxJws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'
+y6 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWlxcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXZ2dnh4eHp6ent7e3x8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpWVlZmZmZqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbKysrW1tba2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMbGxsnJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb293d3d7e3v/pwP/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uDg4OHh4eLi4ubm5ufn5+np6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PHx8fLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAAKxo9DAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV8UlEQVR4Xt2deWAU133Ht3fdNnZrpy2mbpripnFSu2mOkYQEAmQQt5A5TEAgwGAhwOauY9duHbdNmqRp67TmPmQjJAtzI8dpk7ZJmjStzI0wUDtOYw4BbhxLyHF2YTXbOb775nhv3rw3M7s7488/zL55u5oPu/v2Hb/3m1TOm1/67Uf//t9+eEONHdd/8PUvf+qWm3CZDLysPnjzk98dwIvElBvfeORWXK0bttWvffJVPDXm/PtHfgGX7IBldftfv4MnJYA3P/OLuGwbtNVNTyTISefNP/5ZXDrBbfVH7/8+KieIb92Dq8/jsvrVL8a8iWBz/TM/AwETp9UH/gPVEsdLvwwFA7vVB+78P9RJIK9+FBY6NquP3v4T1EgkbzwKDw3L6vHB13E+ofzocZjYrP7mfe/ibGJ54+NwIVZfuPUtnEswr90BG1h99q7/wZlE8zU08KbVXerTKE84jxk6sHr3TpQmnRt/ZfgYVq/d8SZKGaQvX4gXF69kcGkMvmP0CXWrv1W/iDI3V1ubJ5crsWPo1Id29eMS3RjtoG41cAd7vHuquRIvE0OqV53HZTr50YdMq/9Uv4ISB71NeH5cKV/L/CQ+YVh9RB3E6qd3jsaTY0zdKVysnbeG6Favq5/DYzvteGK8qXwZl2tHG2ylcupv/RgPbSRDiq313SG51DfVD+KRjX14UvypPIlLtvGXuZTKaCsuj8BzEsCkNC7a4nHN6ra38YAw0IhnOBk5fmLtSBzHiDW4aotva1Z34djiIOrbGLtm70Xj3OX2BcNRFhPKzhoXZmPgYyn1kzi2mIX6hIaDWZzSyXRNR3k8WI7rshiUUv8B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'
+y7 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlNTU1RUVFVVVVZWVldXV1hYWFlZWVpaWltbW1xcXF1dXV9fX2BgYGFhYWJiYmRkZGVlZWZmZmlpaWtra2xsbG5ubm9vb3FxcXJycnV1dXh4eHp6enx8fH5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2Jf+2Jv+3KP+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++Pf++Pv+/QP/AQv/ARP/BR//CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/Rdf/Rdv/SeP/Sev/TfP/UfoODg4SEhIaGhoeHh4iIiIqKiouLi4yMjI2NjY6OjpCQkJGRkZKSkpSUlJqampycnJ6enqCgoKKioqOjo6Wlpaampqqqqqurq7CwsLGxsbOzs7S0tLa2trq6ury8vP/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enf/env/foP/go//gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMPDw8TExMfHx8nJyc3Nzc/Pz9HR0dLS0tPT09TU1NbW1tfX19jY2NnZ2dra2tvb29zc3N/f3//pwP/qwP/qwv/rxP/rxv/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03+Hh4eLi4uPj4+Xl5ebm5ufn5+jo6Onp6evr6+3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09Pb29v/68P/68v/79P/89vj4+Pn5+fr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAACsZAT0AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAQLUlEQVR4Xt2de4BUVR3Hp3dWvoAKVs0MKtFE090FBEFeCriISBAqkgjyCAmENDVTy8qyBwXiIg9BFHkoIqilFZamLQQIqKBZZro8NRUWH7uwe6f7+M6ZO3Pu3DmP332cPv/sufeec+d8dma+c+fOuedmsqX5xJFn3PbYqwet1HHotT/+8nufPwzdDKCU1QlHXP34IewkpbQ8dWMr9LaYYKvPnPQnNE05L53+MXS5gCCrdte8iUYG8O6PPo5u++CtDuv0OhoYwrs3fBhdZxRbfa3NE6hsEP9qg97nKLL69DUpjLzytNz6IQh4FFod/wiqGcdfPgkFF7/V8R1eQh0DefNkWDj4rE5uZ1hMFPJeO3jY5K2ur/gvthvKwQqY+Kx+crjRz5TD+4fDhVn9tNU/sM1g3joWNrC6qeOj2GI0zyDgPauO1nVYbzi/cnVg9X6HlB+fC9PB9XGtXj7uSawMoGnvzh3pYk8juhbAm+4xoWP1c+s0rCvmwNJJQ7pUpo7qmvF3v4EuFnNrzqrl2OBPqvopZ2E3KaTr+K3oZiGHvuJZ/dX6PtYU0DS9GjtIK+P2oasFzHCtTrLavoUVfrbWoG2K6bManfXT0t6xesXqhGU/dV3RMt3ci+76ucWxsj73FBZ9GCIVqPV2+2xmrXUClnxsMUWqsvIBdNnHCdmMFZAVjeehiQH03INO55lhW7X+MxbyXOXW71pTnh5uzUQZ1YJeM96xrTpya7dXudWHYDGM77g1k2UV+pLn1IzVFsU8k73aplhdhL7kOT1jXYsio6G7V9sUq8pt6AzjV5m2M1Bk3IPKxlhNRWcYT2f4sBiPysZYDUVn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'
+y8 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0BAQEREREZGRkpKSktLS0xMTE1NTU5OTk9PT1FRUVJSUlRUVFZWVldXV1hYWFlZWVpaWlxcXF1dXV5eXl9fX2BgYGFhYWJiYmRkZGVlZWlpaWtra2xsbG1tbW5ubm9vb3FxcXJycnNzc3V1dXZ2dnd3d3h4eHp6en5+fn9/f/+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+4Kv+4LP+5Lv+6MP+7M/+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/DTP/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/LZP/MZv/MaP/Nav/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoGBgYKCgoSEhIiIiIuLi4yMjI6Ojo+Pj5CQkJOTk5WVlZqampycnJ2dnaCgoKKioqOjo6SkpKWlpaampqenp6urq62tra+vr7KysrS0tLa2trm5ubq6ur29vf/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/mtP/mtv/nuP/ouv/ovP/pvsDAwMHBwcPDw8TExMbGxsjIyMnJycrKyszMzM3Nzc/Pz9DQ0NLS0tTU1NfX19jY2Nra2tzc3N3d3d7e3t/f3//qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4eLi4uPj4+Tk5OXl5ebm5ufn5+jo6Onp6evr6+zs7O7u7v/04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29v/68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P39/f/+/P7+/v///wAAABfKiGAAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAWaklEQVR4XtWdeWAdx13HH2dJoXFJg+OG0DSmTgrhaGB1WbJs+YyP+IitxLcdK/J9xDYQAoGUltJCkxZ8yld83zdQIFxt0oJvy7YslxoKTX1ICikgWwQpedrHHt83O7szuzszu++93c8/fm9m9mk/fm935/xNJufPh/p85gt//a/v6Ymj9z+/8ZXfeegenCYHP6uH7/3Vv/w/fEhSuf7Ze3G2XvhWP/XQ13pxaLL53u/+GE7ZBc/qgcf/DQelgA/+5Mdx2hSs1T0/dx0HpIQP/vCHceoEr9Uv3v8XKJwi3n0MZ5/HY/WTn/pvlEwXf/ZDELBxWz30JZRKHf/xE1CwoK0e6v93KJNC3usPCxPK6hce+CeUSCW9T8DDwLH67X7/gvy08mswoaw+95FvIjO19H4aLsTq8/e9gbwU8/59sIHVy49+Hjmp5l3c4G2rx/RPIj3l/KOlA6v3+r+L5LTzkuVjWX3nwa8ikUO249bNZNHWhVPj8L5VJzStvqjfjzQv2SMr6qu15PFkw5ZbOEUvb+Steh98C0luOjYMw6ckkLLZp/lNwI/bVm/p/ZHgonf7QHxAUpnK/b7etKw+rfflfVW3puLYBFOzh/d19TWtvqv3wVuaq3U4Mtms5mj9lWml/8yreEuREimuVu8juczX9YfZvrG2tEhpWhNOmeLFXEbn3Ct6Z+GQFFB+CSft8E3D6mNfxhuHPTjCw/Axo2vwMkGM68ZZOxhWj34frwl3B+EAisGrTt8x867tm46UxLDZOmmaARm9L146bEdxh9pd1H9I6zykJoSRWZwY4UsZ/WG8JPSOQXHCzDZkgUO1yEgGR3BahDcz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'
+y9 = b'iVBORw0KGgoAAAANSUhEUgAAANUAAAE/CAMAAADmNnbhAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABkZGR4eHi4uLjAwMDExMTk5OTw8PD09PT8/P0pKSktLS0xMTE1NTU5OTlBQUFNTU1RUVFZWVlhYWFlZWVtbW11dXV5eXmBgYGFhYWJiYmRkZGZmZmpqamtra2xsbG1tbW5ubnBwcHFxcXJycnV1dXh4eHp6en5+fv+qAP+qAv+rBP+sBv+sCP+tCv+uDP+uDv+vEP+wEv+wFP+xFv+yGP+yGv+zHP+0Hv+0IP+1Iv+2JP+2Jv+3KP+3Kv+4Kv+4LP+5Lv+6MP+6Mv+7NP+8Nv+8OP+9Ov++PP++Pv+/QP/AQv/ARP/BRv/CSP/CSv/CTP/DTv/ETv/EUP/FUv/GVP/GVv/HWP/IWv/IXP/JXv/KYP/KYv/KZP/MZv/MaP/Nav/NbP/ObP/Obv/PcP/Qcv/QdP/Rdv/SeP/Sev/TfP/UfoCAgIKCgoSEhIaGhoeHh4iIiImJiYqKioyMjI6Ojo+Pj5CQkJOTk5WVlZaWlpiYmJqampycnJ2dnZ+fn6CgoKKioqOjo6SkpKampqioqKmpqaurq62trbGxsbKysrS0tLW1tba2tri4uLq6ury8vL29vb6+vv/UgP/Vgv/WhP/Whv/XiP/Yiv/YjP/Zjv/ZkP/akP/akv/blP/clv/cmP/dmv/enP/env/foP/gov/gpP/hpv/iqP/iqv/jrP/krv/ksP/lsv/ltP/mtP/mtv/nuP/nuv/ouv/ovP/pvsHBwcPDw8TExMbGxsnJycrKyszMzM7OztDQ0NLS0tTU1NXV1dbW1tfX19nZ2dra2tvb29zc3N7e3v/qwP/qwv/rxP/sxv/syP/tyv/uzP/uzv/v0P/w0v/w1P/x1v/y2P/y2v/z3P/03uHh4ePj4+Tk5Ofn5+jo6Orq6uvr6+zs7O3t7e/v7//04P/14v/25P/25v/36P/46v/47P/57vDw8PLy8vPz8/T09PX19fb29vf39//68P/68v/79P/89vj4+Pr6+vv7+//8+P/9+vz8/P/+/P7+/v///wAAAJqY7cUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjVkR1hSAAAV7ElEQVR4Xt2deWAVx33HX++6ce06dd3Ubp24dWM/ISEkLiFQOQRGnKKY+zCUSxxNGidtnaZuYsd2mto52iIQUC6Jw8hABQXiuKldp3XtIsRtjtRxmhQkJOqkNgg7T0j7usf3zR4zszszu+9Yf/5A+2Znn/aD9pjzN4k0n1/63S+++L33tIKj78ev/+1f/PZdt+A0GfCsPvY733gXX1Ko/OiZOz+Cs/XCtrr1uZ/i0MLmJ1/681/AKbtgWf3mv+OgGND3ra/+Ik7bAW11y6s4IC5888s/i1MneK1+7yt9yBwfPvjMJ3D2GTxWt/4AOePFq3/3MxCwcFs9Gr8/lMX/3fXLUDBxWt31LPLEkL7P3AMLA4fVfS8hRzz50gPw0LGtPvcv2B1XnnoQJg6rJ17EzvjyhfvgQqye/Ap2xZnfvw02sHrsk9gRa26+gwe8ZfUJLR7lviB+8K+mDqw++E8kx52v/anpY1r912NIZNB3teNyYdFxHafG4jfMMqFh9TTv+utrXVM7KFl4DJu14U2copfvfydj1fcNJLnpbhyFbylEJu/rxXm6+dSdltXrGrP01zIYxxcq1Wdwpi7eec20uk97DglOri3EsQVMcQPrz/XgRw2r72s38dlB1xgcWdjM7sH5Onj7JcNK+xw+OoiJFFvrjrvTie9qb+GTTWosDip8FuKUHfzNo+kENl2swiFxYB/O2eb9N3SrP8EHm+NFOMJFceWokcOYe/LKoE6ctc3tutV3sE3oq8YBNsWzt59MGfu627ZMKzCzReZJO/n8vQntA2wTWpGdMHSd6//jYl05dhQE/a/ivAgvP824r2Yhe4blN7CD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'
+
+
+
+Update = lambda elem, value: window.Element(elem).Update(value)
+
+class BadInputError(Exception):
+ pass
+
+
+class Player():
+
+ def __init__(self, name):
+ self.id = None
+ self.name = name
+ self.type = 'Human'
+ self.hand = Hand()
+ self.legalCards = []
+ self.wildCards = []
+ self.valueChangeCards = []
+ self.zeroCards = []
+ self.canSkip = False
+ self.canReverse = False
+ self.canDrawTwo = False
+ self.canDrawFour = False
+ self.canValueChange = False
+ self.drew = False
+ self.scrollMax = 0
+ self.points = 0
+ self.forceDraw = 0
+
+ def addCard(self, card):
+ self.drew = True
+ if self.forceDraw > 0:
+ self.forceDraw -= 1
+ self.drew = False
+ self.hand.addCard(card)
+
+ def beginTurn(self):
+ self.drew = False
+
+ def didDraw(self):
+ return self.drew
+
+ def getLegalCards(self, color, value, zeroChange=False):
+ self.canSkip = False
+ self.canReverse = False
+ self.canDrawTwo = False
+ self.canDrawFour = False
+ self.canValueChange = False
+ self.canZeroChange = False
+ self.legalCards = []
+ self.wildCards = []
+ self.valueChangeCards = []
+ self.zeroCards = []
+ plusFours = []
+ for card in self.hand:
+ if card.isWild():
+ if card.getValue() == '+4':
+ plusFours.append(card)
+ else:
+ self.wildCards.append(card)
+ elif zeroChange and card.isZero():
+ self.canZero = True
+ self.zeroCards.append(card)
+ elif card.getColor() == color or card.getValue() == value:
+ if card.getColor() != color:
+ self.canValueChange = True
+ self.valueChangeCards.append(card)
+ if card.getValue() == "+2":
+ self.canDrawTwo = True
+ elif card.getValue() == 'R':
+ self.canReverse = True
+ elif card.getValue() == 'X':
+ self.canSkip = True
+ self.legalCards.append(card)
+ if len(self.legalCards) == 0 and len(plusFours) > 0:
+ self.canDrawFour = True
+ self.wildCards += plusFours
+
+ def getValidCards(self):
+ return self.legalCards
+
+ def getAllValidCards(self):
+ return self.legalCards + self.wildCards + self.zeroCards
+
+ def hasLegalCard(self):
+ return len(self.legalCards) > 0
+
+ def addPoints(self, amount):
+ if (self.points + amount) <= 999999999999999999999:
+ self.points += amount
+
+ def removeCard(self, index):
+ return self.hand.removeCard(index)
+
+ def assignID(self, identity):
+ self.id = identity
+
+ def getName(self):
+ return self.name
+
+ def getID(self):
+ return self.id
+
+ def getPoints(self):
+ return self.points
+
+ def getType(self):
+ return self.type
+
+ def getCardNum(self):
+ return len(self.hand)
+
+ def getHand(self, scrollNum=0, hide=False):
+ return self.hand.show(scrollNum, hide)
+
+ def getForceDraws(self):
+ return self.forceDraw
+
+ def addForceDraw(self, num):
+ self.forceDraw += num
+
+ def decreaseForceDraw(self):
+ self.forceDraw -= 1
+
+ def removeForceDraw(self):
+ self.forceDraw = 0
+
+ def checkCard(self, index):
+ return self.hand.getCard(int(index))
+
+ def discardHand(self):
+ self.hand.discard()
+
+ def __str__(self):
+ return self.name
+
+ def __repr__(self):
+ return '({},{})'.format(self.name, self.points)
+
+
+class Hand():
+ ''''deck' (Deck) : Card's Color (rgby)
+ 'numberOfCards' (int) : Card's Value (0-9, R, X, W, +2, +4)'''
+
+ def __init__(self, deck=None, numberOfCards=0):
+ self.hand = []
+ if deck != None:
+ self.draw(deck, numberOfCards)
+
+ def __iter__(self):
+ return iter(self.hand)
+
+ def __len__(self):
+ return len(self.hand)
+
+ def __getitem__(self, item):
+ try:
+ return self.hand[item]
+ except:
+ return ''
+
+ def addCard(self, card):
+ self.hand.append(card)
+
+ def removeCard(self, index):
+ index = int(index)
+ if (0 <= index < len(self)):
+ return self.hand.pop(index)
+
+ def discard(self):
+ self.hand = []
+
+ def show(self, scrollNum=0, hide=False):
+ return ''
+
+ def getCard(self, index):
+ return self.hand[index]
+
+ def indexCard(self, card):
+ return self.hand.index(card)
+
+
+class GameSettings():
+ playerIdentities = ('play1', 'play2', 'play3', 'play4')
+ computerNames = ('Watson', 'SkyNet', 'Hal', 'Metal Gear')
+
+ def __init__(self):
+ self.playerStaging = [] # Where Player Objs Are Stored Before Game Starts
+ self.players = {} # ID : Player Obj
+ self.numPlayers = 0
+ self.useColor = True
+ self.displayEffects = True
+ self.hideComputerHands = True
+ self.zeroChange = False
+ self.computerSimulation = False
+ self.mainMenuError = ''
+ self.computerSpeed = 'normal'
+
+ def canAddPlayer(self):
+ return (self.numPlayers < 4)
+
+ def canRemovePlayer(self):
+ return (self.numPlayers > 0)
+
+ def canBegin(self):
+ return (self.numPlayers > 1)
+
+ def addPlayer(self, player):
+ self.playerStaging.append(player)
+ self.numPlayers += 1
+
+ def removePlayer(self, number):
+ number -= 1
+ del self.playerStaging[number]
+ self.numPlayers -= 1
+
+ def clearStaging(self):
+ self.numPlayers = 0
+ self.playerStaging = []
+
+ def finalizePlayers(self):
+ self.players.clear()
+ identity = 0
+ for player in self.playerStaging:
+ playerID = GameSettings.playerIdentities[identity]
+ player.assignID(playerID)
+ self.players[playerID] = player
+ identity += 1
+
+ def getPlayerNum(self):
+ return self.numPlayers
+
+ def getComputerName(self):
+ complete = False
+ index = self.numPlayers
+ while not complete:
+ name = self.computerNames[index]
+ complete = True
+ for player in self.playerStaging:
+ if player.getName() == name:
+ index += 1
+ if index >= len(self.computerNames):
+ index = 0
+ complete = False
+
+ return self.computerNames[index]
+
+ def getRandomIdentity(self):
+ '''For Getting a Random Player for First Turn.'''
+ return random.choice(self.players.keys())
+
+
+ def changeComputerSpeed(self):
+ return
+
+
+
+class Deck():
+ ''''shuffle' (bool) : shuffle deck.'''
+
+ colors = ('red', 'yellow', 'green', 'blue')
+ values = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2')
+
+ def __init__(self, populate):
+ '''Initializes proper deck of 108 Uno Cards.'''
+ self.deck = []
+ if populate:
+ self.populate(True)
+
+ def __getitem__(self, index):
+ return self.deck[index]
+
+ def populate(self, shuffle=True):
+ for color in self.colors:
+ for value in self.values:
+ self.deck.append(Card(color, value))
+ if value != '0':
+ self.deck.append(Card(color, value))
+ for i in range(4):
+ self.deck.append(Card('wild', '+4'))
+ self.deck.append(Card('wild', 'W'))
+ if shuffle:
+ self.shuffle()
+
+ def __iter__(self):
+ return iter(self.deck)
+
+ def __len__(self):
+ return len(self.deck)
+
+ def draw(self):
+ return self.deck.pop()
+
+ def place(self, card):
+ return self.deck.append(card)
+
+ def insert(self, card):
+ self.deck.insert(0, card)
+
+ def shuffle(self):
+ random.shuffle(self.deck)
+
+
+class ComputerPlayer(Player):
+
+ def __init__(self, name):
+ super().__init__(name)
+ self.type = 'Computer'
+ self.begun = False
+ self.colorsInHand = {'red': 0, 'blue': 0, 'green': 0, 'yellow': 0, 'wild': 0}
+ self.colorsOutHand = {}
+ self.currentColor = ""
+
+ def addCard(self, card):
+ Player.addCard(self, card)
+ color = card.getColor()
+ self.colorsInHand[color] += 1
+
+ def indexCard(self, cardColor, cardValue):
+ for card in self.hand:
+ if card.getValue() == cardValue:
+ if cardValue in ('+4', 'W'):
+ return self.hand.indexCard(card)
+ else:
+ if card.getColor() == cardColor:
+ return self.hand.indexCard(card)
+ raise ValueError("Card Cannot Be Found")
+
+ def think(self, match):
+ card = None
+ self.currentColor = match.currentColor
+ currentValue = match.currentValue
+ zeroChangeRule = match.zeroChange
+ twoPlayers = False
+ previousTurnID = match.getNextTurn(True)
+ nextTurnID = match.getNextTurn(False)
+ previousPlayer = match.getPlayer(previousTurnID)
+ # nextPlayer = match.getPlayer(nextTurnID)
+ if previousTurnID == nextTurnID:
+ twoPlayers = True
+ if self.canSkip == False and self.canReverse == True:
+ self.canSkip = True
+ self.canReverse = False
+
+ self.getLegalCards(self.currentColor, currentValue, zeroChangeRule)
+
+ ### DRAW CASE ###
+
+ if len(self.legalCards) == 0 and len(self.wildCards) == 0:
+ return "d"
+
+ else:
+
+ ### NO LEGAL CARD, USE WILD CARD ###
+
+ if len(self.legalCards) == 0:
+
+ if zeroChangeRule and self.canZeroChange:
+ bestZeroColor = self.getBestColor(self.zeroCards)
+ card = self.getCardByColor(self.zeroCards, bestZeroColor)
+
+ else:
+
+ if self.canDrawFour:
+ card = self.getCardByValue(self.wildCards, "+4")
+ # print(card)
+
+ else:
+ card = random.choice(self.wildCards)
+
+ else:
+
+ ### HAS LEGAL CARD ###
+
+ if twoPlayers and self.canSkip: # Always play a skip card in a two player game
+ # print("Shed Skip Strategy")
+ card = self.getCardByValue(self.legalCards, "R", "X")
+
+ if self.canReverse and previousPlayer.didDraw():
+ # print("Reverse Strategy")
+ reverseCards = self.getAllCardsByValue(self.legalCards, "R")
+ for reverseCard in reverseCards:
+ if reverseCard.getColor() == self.currentColor:
+ card = reverseCard
+
+ if self.canValueChange:
+ # Computer Can Value Change, However, Should it?
+ # Computer Checks to See if Value Change Color is Better Than Current
+ currentColorNum = self.colorsInHand[self.currentColor]
+ bestValueChangeColor = self.getBestColor(self.valueChangeCards)
+ if self.colorsInHand[bestValueChangeColor] > currentColorNum or len(self.valueChangeCards) == len(
+ self.legalCards):
+ card = self.getCardByColor(self.valueChangeCards, bestValueChangeColor)
+
+ if card == None:
+ # print("Random Strategy")
+ card = random.choice(list(set(self.legalCards) - set(self.valueChangeCards)))
+
+ color = card.getColor()
+ self.colorsInHand[color] -= 1
+ return str(self.indexCard(card.getColor(), card.getValue()))
+
+ def getWildColor(self):
+ maxKey = max(self.colorsInHand, key=self.colorsInHand.get)
+ if maxKey == 'wild':
+ return random.choice(('r', 'g', 'b', 'y'))
+ else:
+ return maxKey
+
+ def getCardByValue(self, cardList, *values):
+ for card in cardList:
+ if card.getValue() in values:
+ return card
+
+ def getAllCardsByValue(self, cardList, *values):
+ cards = []
+ for card in cardList:
+ if card.getValue() in values:
+ cards.append(card)
+ return cards
+
+ def getCardByColor(self, cardList, *colors):
+ for card in cardList:
+ if card.getColor() in colors:
+ return card
+
+ def getBestColor(self, cardList):
+ bestColor = None
+ bestColorNum = 0
+ for card in cardList:
+ color = card.getColor()
+ if self.colorsInHand[color] > bestColorNum:
+ bestColor = color
+ bestColorNum = self.colorsInHand[color]
+ return bestColor
+
+
+class Card():
+ '''
+ 'suit' (string) : Card's Color (rgby)
+ 'rank' (string) : Card's Value (0-9, R, X, W, +2, +4)
+ '''
+ # 11 = reverse, 12 = +2
+ # 0-9, X, R, W, +2, +4
+ # '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W'
+ green_dict = {'0':g0, '1':g1, '2':g2, '3':g3, '4':g4, '5':g5, '6':g6, '7':g7, '8':g8, '9':g9, 'X':g10, 'R':g11, '+2':g12, '+4':plusfourgreen, 'W':wildgreen}
+ red_dict = {'0':r0, '1':r1, '2':r2, '3':r3, '4':r4, '5':r5, '6':r6, '7':r7, '8':r8, '9':r9, 'X':r10, 'R':r11, '+2':r12, '+4':plusfourred, 'W':wildred}
+ blue_dict = {'0':b0, '1':b1, '2':b2, '3':b3, '4':b4, '5':b5, '6':b6, '7':b7, '8':b8, '9':b9, 'X':b10, 'R':b11, '+2':b12, '+4':plusfourblue, 'W':wildblue}
+ yellow_dict = {'0':y0, '1':y1, '2':y2, '3':y3, '4':y4, '5':y5, '6':y6, '7':y7, '8':y8, '9':y9, 'X':y10, 'R':y11, '+2':y12, '+4':plusfouryellow, 'W':wildyellow}
+ green_cards = [g0, g1, g2, g3, g4, g5, g6, g7, g8, g9, g10, g11, g12 ]
+ red_cards = [r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12 ]
+ blue_cards = [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12 ]
+ yellow_cards = [y0, y1, y2, y3, y4, y5, y6, y7, y8, y9, y10, y11, y12 ]
+ wild_card = wild
+
+
+ colors = {
+ 'red': '\033[91m',
+ 'green': '\033[92m',
+ 'yellow': '\033[93m',
+ 'blue': '\033[94m',
+ 'purple': '\033[95m',
+ 'cyan': '\033[96m',
+ 'white': '\033[97m',
+ 'wild': '',
+ 'dwild': '',
+ 'dred': '\033[31m',
+ 'dgreen': '\033[32m',
+ 'dyellow': '\033[33m',
+ 'dblue': '\033[34m',
+ 'dpurple': '\033[35m',
+ 'dcyan': '\033[36m',
+ 'dwhite': '\033[37m',
+ }
+
+ idMap = {
+ 'red': 'R', 'blue': 'B', 'green': 'G', 'yellow': 'Y', 'wild': 'W',
+ '0': '0', '1': '1', '2': '2', '3': '3', '4': '4', '5': '5', '6': '6', '7': '7', '8': '8', '9': '9',
+ '+2': '+', 'R': 'R', 'W': 'W', '+4': '$', 'X': 'X'
+ }
+
+
+ def __init__(self, color, value):
+ '''Initializes Uno Card w/ Color and Value.'''
+ self.wild = False # Is wild card?
+ self.zero = False
+ self.cardID = '{}{}'.format(self.idMap[color], self.idMap[value])
+ self.setColor(color)
+ self.setValue(value)
+ self.setPoints(value)
+
+ #############################################
+
+ ### -\/- Retrieve Card Information -\/- ###
+
+ def __repr__(self):
+ return "{},{}".format(self.color, self.value)
+
+ def getBigNum(self, reverse, reverseSeed=0):
+ '''Returns list of strings to draw card's value on the pile.'''
+ return ''
+
+ def getColor(self):
+ '''Returns card's color.'''
+ return self.color
+
+ def getColorCode(self):
+ '''Returns card's color code.'''
+ return self.colorCode
+
+ def getValue(self):
+ '''Returns card's value.'''
+ return self.value
+
+ def getPoints(self):
+ '''Returns card's point value.'''
+ return self.points
+
+ def getRow(self, rowNum, hide=False):
+ return
+
+ #############################################
+
+ ### -\/- Set Card Information -\/- ###
+
+ def setColor(self, color):
+ '''Sets Card's color and escape code.'''
+ if color == 'blue':
+ self.color = 'blue'
+ self.colorCode = self.colors['blue']
+ self.colorCodeDark = self.colors['dblue']
+ elif color == 'red':
+ self.color = 'red'
+ self.colorCode = self.colors['red']
+ self.colorCodeDark = self.colors['dred']
+ elif color == 'yellow':
+ self.color = 'yellow'
+ self.colorCode = self.colors['yellow']
+ self.colorCodeDark = self.colors['dyellow']
+ elif color == 'green':
+ self.color = 'green'
+ self.colorCode = self.colors['green']
+ self.colorCodeDark = self.colors['dgreen']
+ elif color == 'wild': # No color modification
+ self.wild = True
+ self.color = 'wild'
+ self.colorCodeDark = self.colors['dwild']
+ self.colorCode = self.colors['wild']
+
+ def setValue(self, value):
+ if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X', 'R', '+2', '+4', 'W'):
+ self.value = value
+ self.displaySpace = ' '
+ if len(value) == 2:
+ self.displaySpace = ''
+ if value == '0':
+ self.zero = True
+
+ def setPoints(self, value):
+ if value in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
+ self.points = int(value)
+ elif value in ("W", "+4"):
+ self.points = 50
+ else:
+ self.points = 20
+
+ #############################################
+
+ ### -\/- Wild Card Methods -\/- ###
+
+ def changeColor(self, color):
+ '''Changes Card's Color, Intended for Wild Cards.'''
+ self.setColor(color)
+
+ def isWild(self):
+ '''Returns if card is a wild card.'''
+ return self.wild
+
+ def isZero(self):
+ return self.zero
+
+
+class Match():
+ elementsInit = {
+ ### Names (final) ###
+ 'P1Name': ' ', 'P2Name': ' ', 'P3Name': ' ', 'P4Name': ' ',
+ ### Card Values ###
+ 'P1Cards': ' ', 'P2Cards': ' ', 'P3Cards': ' ', 'P4Cards': ' ',
+ ### Turn Colors / Hand###
+ 'P1Turn': '', 'P2Turn': '', 'P3Turn': '', 'P4Turn': '',
+ 'HName': '\t\t', 'HVisual': '', 'Hand': '',
+ ### Deck ###
+ 'DNum': '', 'Deck': ['', '', '', '', '', '', '', '', ''],
+ 'PostDNum': '',
+ ### Pile ###
+ 'uHeader': '\t\t\t\t', 'uMiddle': ' ', 'uLower': ' ',
+ 'oHeader': '\t\t\t',
+ 'oMiddle': ['\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t', '\t\t\t'],
+ ### Messages ###
+ 'Console': '', 'Error': ''
+ }
+
+ speeds = {'slow': 2, 'normal': 1, 'fast': 0}
+
+ window = None
+
+ def __init__(self, gs):
+ ### Decks ###
+ self.deck = Deck(True)
+ self.pile = Deck(False)
+
+ ### Player Information ###
+ self.players = gs.players
+ self.turnList = []
+ self.handTitles = {'play1': '', 'play2': '', 'play3': '', 'play4': ''}
+
+ ### Carry Information ###
+ self.displayEffects = gs.displayEffects
+ self.hideComputerHands = gs.hideComputerHands
+ self.zeroChange = gs.zeroChange
+ self.computerSpeed = self.speeds[gs.computerSpeed]
+ self.simulation = gs.computerSimulation
+
+ ### Data ###
+ self.handPosition = 0 # For hand displays
+ self.drawAmount = 0 # Used for force draws
+ self.passes = 0 # Keep track of consecutive passes for emergency color change
+ self.passMax = 0 # Max passes before color change
+ self.turn = '' # Current turn
+ self.event = '' # Wild, Reverse, Skip, etc
+ self.wildColorChange = '' # Specifies color to change wild card to
+ self.currentColor = '' # Current color
+ self.currentValue = '' # Current value
+ self.winnerID = '' # ID of Player who Won
+ self.reverse = False # Is turn order reversed
+ self.turnComplete = False # Is turn complete
+ self.matchComplete = False # Is the Game over?
+ self.matchAbort = False # Did the match conclude without a winner?
+ self.forcedWild = False # Force change wild
+
+ self.max_cards_displayed = 0
+ self.previous_card = None
+ ### Initialize Names / Cards / Deck (Assuming New Game) ###
+ self.elements = dict(self.elementsInit)
+
+ keyStringName = 'P{}Name'
+ keyStringCards = 'P{}Cards'
+
+ for i in self.players:
+ self.elements[keyStringName.format(i[-1])] = self.players[i].getName() + (
+ ' ' * (11 - len(self.players[i].getName())))
+ self.elements[keyStringCards.format(i[-1])] = ' ' + (
+ ' ' * (3 - len(str(self.players[i].getCardNum())))) + str(
+ self.players[i].getCardNum()) + ' Cards'
+
+ self.elements['DNum'] = len(self.deck)
+
+ if len(str(len(self.deck))) < 2:
+ self.elements['PostDNum'] = '\t'
+
+ j = 8
+ for i in range(int(math.ceil(len(self.deck) / 12))):
+ self.elements['Deck'][j] = '='
+ j -= 1
+
+ for key in GameSettings.playerIdentities:
+ try:
+ self.buildHandString(key)
+ self.turnList += [key]
+ except KeyError:
+ pass
+
+ self.passMax = len(self.turnList)
+ # ----------------------------------------- Create the GUI window -----------------------------------------
+ sg.SetOptions(background_color='black', element_background_color='black', text_color='white', border_width=0)
+ Card = lambda image_data, key: sg.Button('', image_data=image_data, image_subsample=4, image_size=(60, 80), button_color=('white', 'black'), key=key)
+ CardBig = lambda image_data: sg.Button(button_text='', image_data=image_data, image_subsample=1, image_size=(200, 300),
+ button_color=('white', 'black'), pad=(0, 0))
+ CardBig2 = lambda image_data: sg.Image(data=image_data, size=(100, 300), pad=(0, 0), background_color='black')
+
+ Elem = lambda key: Match.window.Element(key)
+ T = lambda text, key=None, font='Helvetica 16', **kwargs: sg.T(text, key=key, font=font, **kwargs )
+
+ MyButton = lambda text, size=(6, 1), font='Helvetica 14', **kwargs: sg.Button(text, size=size, font=font, button_color=('white', 'green3'), **kwargs)
+ OvalButton = lambda text, image_data, **kwargs: sg.Button(text, image_data=image_data, font='Helvetica 14', button_color=('white', 'black'), **kwargs)
+
+ col_players = [
+ [OvalButton('Quit', greenbutton, key='_QUIT_', visible=False)],
+ [T('Player', '_P1_', text_color=yellow_color)],
+ [T('Cards', '_C1_', text_color=yellow_color)],
+ [T(' ' * 15)],
+ [T('Player', '_P2_', text_color=red_color)],
+ [T('Cards', '_C2_', text_color=red_color)],
+ [T(' ' * 15,'_S3_', visible=False,)],
+ [T('Player', '_P3_', visible=False)],
+ [T('Cards', '_C3_', visible=False)],
+ [T(' ' * 15, '_S4_', visible=False,)],
+ [T('Player', '_P4_', visible=False)],
+ [T('Cards', '_C4_', visible=False)],]
+
+ col_cards_left = [
+ [OvalButton('Draw', redbutton, key='_DRAW_')],
+ [T(' '), Card(back, '_DRAW_')],
+ [T('0 Cards Left', font='Helvetica 14', key='_CARDS_LEFT_')],
+ [OvalButton('Pass', bluebutton, key='_PASS_')],]
+
+ NUM_COLS = 10 # how many cards shown across bottom in 1 row
+ NUM_ROWS = 4
+ cards = []
+ for j in range(NUM_ROWS):
+ cards.append([sg.T(' ' * 5,font=('Any 5'))] + [Card(None, j*NUM_COLS+i) for i in range(NUM_COLS)])
+
+ layout = [
+ [sg.Column(col_cards_left),
+ sg.Graph((400, 360), (0, 300), (400, 0), key='_GRAPH_', ),
+ sg.Column(col_players)],
+ [T(' ')],
+ [T(' ')],
+ [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES_')],
+ [sg.T('', justification='center', size=(55, 2), font='Helvetica 18', key='_MESSAGES2_')],
+ ]
+ layout += cards
+
+ Match.window = sg.Window('Uno',
+ background_color='black',
+ use_default_focus=False,
+ disable_close=True,
+ ).Layout(layout).Finalize()
+
+ def clearShell(self):
+ os.system('cls' if os.name == 'nt' else 'clear')
+
+ def begin(self):
+ self.elements['Console'] = 'Beginning Game, Click Draw to Deal.'
+ self.drawScreen()
+ self.enterBreak()
+ self.eventDealCards()
+ self.turn = random.choice(self.turnList)
+ self.elements['Console'] = 'First turn will be {}. Click Draw'.format(self.players[self.turn].getName())
+ self.drawScreen(True)
+ self.enterBreak()
+ self.placeCard()
+ self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m'
+ if self.event == 'wild':
+ self.eventWildCard()
+ elif self.event == 'reverse':
+ self.eventReverse()
+
+ def end(self, gs):
+ if not self.matchAbort:
+ points = 0
+ self.elements['P{}Turn'.format(self.turn[-1])] = ''
+ self.elements['Console'] = '{} Wins! Click Draw to Begin Point Tally'.format(
+ self.players[self.winnerID].getName())
+ self.drawScreen()
+ self.enterBreak()
+
+ for identity in self.turnList:
+ if identity != self.winnerID:
+ self.turn = identity
+ self.elements['HName'] = self.handTitles[self.turn]
+ self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m'
+ while self.players[identity].getCardNum() > 0:
+ card = self.players[identity].removeCard(0)
+ points += card.getPoints()
+ self.elements['Console'] = '{} Won {} Points!'.format(self.players[self.winnerID].getName(),
+ points)
+
+ keyStringCards = 'P{}Cards'
+ self.elements[keyStringCards.format(identity[-1])] = ' ' + (
+ ' ' * (3 - len(str(self.players[identity].getCardNum())))) + str(
+ self.players[identity].getCardNum()) + ' Cards'
+ self.players[identity].maxScroll = math.ceil((self.players[identity].getCardNum() / 10) - 1)
+ if self.handPosition > self.players[identity].maxScroll:
+ self.handPosition -= 1
+ self.buildHandVisual(identity)
+
+ if self.displayEffects and not self.simulation:
+ self.drawScreen()
+ time.sleep(.1)
+ self.elements['P{}Turn'.format(self.turn[-1])] = ''
+
+ self.players[self.winnerID].addPoints(points)
+ self.elements['Console'] = '{} Won {} Points! Click Draw'.format(self.players[self.winnerID].getName(),
+ points)
+ self.drawScreen()
+ self.enterBreak()
+
+ gs.clearStaging()
+ for identity in self.turnList:
+ self.players[identity].discardHand()
+ gs.addPlayer(self.players[identity])
+ return gs
+
+ def adjustCardAmount(self, playerID):
+ keyStringCards = 'P{}Cards'
+ self.elements[keyStringCards.format(playerID[-1])] = ' ' + (
+ ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str(
+ self.players[playerID].getCardNum()) + ' Cards'
+ self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1)
+ if self.handPosition > self.players[playerID].maxScroll:
+ self.handPosition -= 1
+ self.buildHandVisual(playerID)
+
+ def buildHandString(self, playerID):
+ playerName = self.players[playerID].getName()
+ if len(playerName) < 9:
+ self.handTitles[playerID] = "{}'s Hand\t".format(self.players[playerID].getName())
+ else:
+ self.handTitles[playerID] = "{}'s Hand".format(self.players[playerID].getName())
+
+ def buildHandVisual(self, playerID):
+ string = '['
+ for i in range(self.players[playerID].maxScroll + 1):
+ if i == self.handPosition:
+ string += '|'
+ else:
+ string += '-'
+ string += ']'
+ self.elements['HVisual'] = string
+
+ def checkInput(self, playerInput):
+ if playerInput == '':
+ return {'valid': False, 'entry': playerInput}
+ if playerInput.isnumeric():
+ if int(playerInput) + (10 * self.handPosition) < self.players[self.turn].getCardNum():
+ return {'valid': True, 'entry': str(int(playerInput) + (10 * self.handPosition)), 'type': 'card'}
+ else:
+ self.elements['Error'] = '{} is not a card.'.format(playerInput)
+ return {'valid': False, 'entry': playerInput}
+ else:
+ playerInput = playerInput.lower()[0]
+ if playerInput in ['<', '>', 'u', 'd', 'p', 'q', 's']:
+ return {'valid': True, 'entry': playerInput}
+ else:
+ self.elements['Error'] = '{} is not a valid selection.'.format(playerInput)
+ return {'valid': False, 'entry': playerInput}
+
+ def checkColorInput(self, playerInput):
+ if playerInput == '':
+ return {'valid': False, 'entry': playerInput}
+ playerInput = str(playerInput).lower()[0]
+ if playerInput[0] == 'b':
+ return {'valid': True, 'entry': 'blue'}
+ elif playerInput[0] == 'r':
+ return {'valid': True, 'entry': 'red'}
+ elif playerInput[0] == 'g':
+ return {'valid': True, 'entry': 'green'}
+ elif playerInput[0] == 'y':
+ return {'valid': True, 'entry': 'yellow'}
+ return {'valid': False, 'entry': playerInput}
+
+ def eventDealCards(self):
+ if self.displayEffects and not self.simulation:
+ self.elements['Console'] = 'Dealing Cards...'
+ for i in ('play1', 'play2', 'play3', 'play4'):
+ if i in self.players:
+ for j in range(7):
+ self.dealCard(i)
+
+ def eventReverse(self):
+ if self.displayEffects and not self.simulation:
+ hide = False
+ if self.players[self.turn].getType() == "Computer":
+ hide = self.hideComputerHands
+ self.elements['Console'] = "Reverse Card Played! Reversing Turn Order.".format(
+ self.players[self.turn].getName())
+ self.drawScreen(hide)
+ time.sleep(1)
+ for i in range(10):
+ cardBigNums = self.pile[0].getBigNum(self.reverse, i)
+ self.elements['oMiddle'] = cardBigNums
+ self.drawScreen(hide)
+ if self.displayEffects and not self.simulation:
+ time.sleep(.1)
+ cardBigNums = self.pile[0].getBigNum(self.reverse, 9)
+ self.elements['oMiddle'] = cardBigNums
+ self.reverse = not self.reverse
+ self.event = ''
+
+ def eventSkip(self):
+ if self.displayEffects and not self.simulation:
+ hide = False
+ if self.players[self.turn].getType() == "Computer":
+ hide = self.hideComputerHands
+ self.elements['Console'] = "Skip Card Placed! Skipping {}'s Turn.".format(self.players[self.turn].getName())
+ self.drawScreen(hide)
+ time.sleep(1)
+ for i in range(2):
+ self.elements['P{}Turn'.format(self.turn[-1])] = '\033[91m'
+ self.drawScreen(hide)
+ time.sleep(.3)
+ self.elements['P{}Turn'.format(self.turn[-1])] = ''
+ self.drawScreen(hide)
+ time.sleep(.3)
+ self.turnComplete = True
+ self.event = ''
+
+ def eventWildCard(self):
+ hide = False
+ if not self.forcedWild:
+ if self.players[self.turn].getType() == 'Human':
+ self.elements['Console'] = 'Wild Card! Specifiy a Color'
+ self.elements['Error'] = 'Specifiy A Color'
+ self.drawScreen()
+ while True:
+ layout=[[sg.T('Wild Card! Specify a Color')],
+ [sg.Combo(('Blue', 'Red', 'Green', 'Yellow'))],
+ [sg.OK()]]
+ window = sg.Window('Wild Card').Layout(layout)
+
+ event, values = window.Read()
+ try:
+ playerInput = values[0].lower()[0]
+ except:
+ playerInput = ' '
+ # playerInput = str(input("Color Change: "))
+ checked = self.checkColorInput(playerInput)
+ if checked['valid']:
+ window.Close()
+ break
+ else:
+ hide = self.hideComputerHands
+ checked = self.checkColorInput(self.players[self.turn].getWildColor())
+ self.wildColorChange = checked['entry']
+ else:
+ self.wildColorChange = self.checkColorInput(random.choice(('r', 'b', 'g', 'y')))['entry']
+ self.forcedWild = False
+ self.currentColor = self.wildColorChange
+ self.elements['Error'] = ""
+ if self.displayEffects and not self.simulation:
+ self.elements['Console'] = 'Wild Card! Changing Color.'
+ seed = 1
+ for i in range(10):
+ if seed > 4:
+ seed = 1
+ self.drawScreen(hide, wildSeed=seed)
+ time.sleep(.1)
+ seed += 1
+ self.pile[0].changeColor(self.wildColorChange)
+ self.wildColorChange = ''
+ cardBigNums = self.pile[0].getBigNum(self.reverse)
+ self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(
+ self.pile[0].getColorCode())
+ self.elements['oMiddle'] = cardBigNums
+ self.event = ''
+
+ def eventDraw(self):
+ self.players[self.turn].addForceDraw(self.drawAmount)
+ self.drawAmount = 0
+ self.event = ''
+
+ def dealCard(self, playerID):
+
+ card = self.deck.draw()
+ self.players[playerID].addCard(card)
+
+ ### Adjust Hand Visual ###
+ self.players[playerID].maxScroll = math.ceil((self.players[playerID].getCardNum() / 10) - 1)
+ self.handPosition = self.players[playerID].maxScroll
+ self.buildHandVisual(playerID)
+
+ ### Adjust Player Tile ###
+ keyStringCards = 'P{}Cards'
+ self.elements[keyStringCards.format(playerID[-1])] = ' ' + (
+ ' ' * (3 - len(str(self.players[playerID].getCardNum())))) + str(
+ self.players[playerID].getCardNum()) + ' Cards'
+
+ ### Adjust Deck ###
+ self.elements['DNum'] = len(self.deck)
+ if len(str(len(self.deck))) < 2:
+ self.elements['PostDNum'] = '\t'
+ j = 8
+ self.elements['Deck'] = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
+ for i in range(math.ceil(len(self.deck) / 12)):
+ self.elements['Deck'][j] = '='
+ j -= 1
+
+ def placeCard(self, card=None):
+ if card == None:
+ ### Used At Beginning For First Card ###
+ card = self.deck.draw()
+ self.elements['DNum'] = len(self.deck)
+
+ cardColor = card.getColorCode()
+ cardBigNums = card.getBigNum(self.reverse)
+
+ self.currentColor = card.getColor()
+ self.currentValue = card.getValue()
+
+ self.pile.insert(card)
+ self.elements['oHeader'] = '{}\u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t'.format(cardColor)
+ self.elements['oMiddle'] = cardBigNums
+
+ if len(self.pile) > 1:
+ previousCard = self.pile[1]
+ previousCardColor = previousCard.getColorCode()
+ self.elements['uHeader'] = '{} \u2666\u2666\u2666=========\u2666\u2666\u2666\033[0m\t\t'.format(
+ previousCardColor)
+ self.elements['uMiddle'] = '{}| |\033[0m'.format(previousCardColor)
+ self.elements['uLower'] = '{}\u2666\u2666\u2666\033[0m'.format(previousCardColor)
+
+ if self.currentColor == 'wild':
+ self.event = 'wild'
+
+ if self.currentValue == 'X':
+ self.event = 'skip'
+ elif self.currentValue == 'R':
+ if len(self.players) > 2:
+ self.event = 'reverse'
+ else:
+ self.event = 'skip'
+ elif self.currentValue == '+4':
+ self.drawAmount = 4
+ elif self.currentValue == '+2':
+ self.drawAmount = 2
+ self.passes = 0
+
+ def extractCard(self, playerID, index):
+ card = self.players[playerID].removeCard(index)
+ if self.players[playerID].getCardNum() == 0:
+ self.matchComplete = True
+ self.winnerID = self.turn
+ self.adjustCardAmount(playerID)
+ return card
+
+ def enterBreak(self):
+ if not self.simulation:
+ while True:
+ if Match.window is None:
+ break
+ event, values = Match.window.Read()
+ if event == '_DRAW_':
+ break
+ if event == '_QUIT_':
+ if sg.PopupYesNo('Do you really want to quit?') == 'Yes':
+ self.matchAbort = True
+ self.matchComplete = True
+
+ def nextTurn(self):
+ self.turnComplete = False
+ self.handPosition = 0
+ turnType = self.players[self.turn].getType()
+ self.players[self.turn].beginTurn()
+ ### Prepare Hand Visuals ###
+
+ self.elements['HName'] = self.handTitles[self.turn]
+ self.buildHandVisual(self.turn)
+
+ if self.event == 'skip':
+ self.eventSkip()
+ elif self.drawAmount > 0:
+ self.eventDraw()
+ #-------------- Main GUI event loop ---------------
+ while not self.turnComplete:
+ if turnType == 'Human':
+ self.players[self.turn].getLegalCards(self.currentColor, self.currentValue, self.zeroChange)
+ if len(self.deck) > 0:
+ self.elements['Console'] = 'Select a card or Draw'
+ else:
+ self.players[self.turn].removeForceDraw()
+ self.elements['Console'] = 'Select a card, Draw, or Pass'
+ if self.players[self.turn].getForceDraws() > 0:
+ self.elements['Error'] = 'Draw Card Played! Draw {} cards.'.format(
+ self.players[self.turn].getForceDraws())
+ self.drawScreen()
+ ## GUI INPUT
+ event, values = Match.window.Read()
+
+ playerInput = str(event)
+ if event == '_DRAW_':
+ playerInput = 'd'
+ elif event == '_PASS_':
+ playerInput = 's'
+ elif event == '_QUIT_':
+ if sg.PopupYesNo('Do you really want to quit?') == 'Yes':
+ self.matchAbort = True
+ self.matchComplete = True
+ break
+
+ if playerInput == '<':
+ self.handPosition -= 1
+ if self.handPosition == -1:
+ self.handPosition = self.players[self.turn].maxScroll
+ self.buildHandVisual(self.turn)
+ elif playerInput == '>':
+ self.handPosition += 1
+ if self.handPosition > self.players[self.turn].maxScroll:
+ self.handPosition = 0
+ self.buildHandVisual(self.turn)
+ elif playerInput == 'd':
+ if len(self.deck) > 0:
+ self.elements['Error'] = ''
+ self.dealCard(self.turn)
+ else:
+ self.elements['Error'] = "Cannot Draw. Deck is Empty"
+ elif playerInput == 'p':
+ pauseOutput = self.pauseScreen()
+ if pauseOutput == 'quit':
+ self.matchComplete = True
+ self.turnComplete = True
+ self.winnerID = 'play1'
+ self.matchAbort = True
+ elif playerInput == 's':
+ if len(self.deck) > 0:
+ self.elements['Error'] = "Cannot pass until Deck is empty."
+ elif len(self.players[self.turn].getAllValidCards()) > 0:
+ self.elements['Error'] = "Cannot pass while having playable cards."
+ else:
+ self.turnComplete = True
+ self.passes += 1
+ if self.passes == self.passMax:
+ self.forcedWild = True
+ self.event = 'wild'
+ self.passes = 0
+ elif playerInput.isnumeric():
+ if self.players[self.turn].getForceDraws() == 0:
+ cardCheck = self.players[self.turn].checkCard(playerInput)
+ if cardCheck in self.players[self.turn].getAllValidCards():
+ card = self.extractCard(self.turn, playerInput)
+ self.placeCard(card)
+ self.elements['Error'] = ""
+ self.turnComplete = True
+ else:
+ self.elements['Error'] = "Card Doesn't Match The Color {} or Value {}!".format(
+ self.currentColor, self.currentValue)
+ else:
+ pass
+
+ elif turnType == 'Computer':
+ event, values = Match.window.Read(timeout=0)
+ if event == '_QUIT_':
+ if sg.PopupYesNo('Do you really want to quit?') == 'Yes':
+ self.matchAbort = True
+ self.matchComplete = True
+ break
+
+ self.elements['Console'] = '{}\'s Turn'.format(self.players[self.turn].getName())
+ self.drawScreen(self.hideComputerHands)
+ if not self.simulation:
+ time.sleep(self.computerSpeed)
+ # str(input())
+ while (True):
+ if self.displayEffects and not self.simulation:
+ time.sleep(.2)
+ if self.players[self.turn].getForceDraws() > 0 and len(self.deck) > 0:
+ cardIndex = 'd'
+ else:
+ cardIndex = self.players[self.turn].think(self)
+ if cardIndex.isnumeric():
+ card = self.extractCard(self.turn, int(cardIndex))
+ if card.getColor() != self.currentColor:
+ self.resetDrawBool()
+ self.placeCard(card)
+ self.turnComplete = True
+ break
+ else:
+ if cardIndex == 'd':
+ if len(self.deck) > 0:
+ self.dealCard(self.turn)
+ self.drawScreen(self.hideComputerHands)
+ else:
+ self.turnComplete = True
+ self.players[self.turn].removeForceDraw()
+ self.passes += 1
+ if self.passes == self.passMax:
+ self.forcedWild = True
+ self.event = 'wild'
+ self.passes = 0
+ break
+
+ ### DECODE INPUT ###
+ if self.event == 'reverse':
+ self.eventReverse()
+ elif self.event == 'wild':
+ self.eventWildCard()
+
+ # Clear Current Turn
+ self.elements['P{}Turn'.format(self.turn[-1])] = ''
+ # Prepare Next Turn
+ self.turn = self.getNextTurn()
+ self.elements['P{}Turn'.format(self.turn[-1])] = '\033[93m'
+
+ # --------------------------------------- drawScreen ---------------------------------------
+ def drawScreen(self, hide=False, wildSeed=0):
+ if Match.window is None:
+ return
+ def get_card_graphic(color, value):
+ dict = Card.red_dict
+ if color == 'red':
+ dict = Card.red_dict
+ if color == 'blue':
+ dict = Card.blue_dict
+ if color == 'green':
+ dict = Card.green_dict
+ if color == 'yellow':
+ dict = Card.yellow_dict
+ card_graphic = dict[value] if value != '' else Card.wild_card
+ return card_graphic
+
+ Update = lambda key, value, **kwargs: Match.window.Element(key).Update(value, **kwargs)
+ elem = lambda key: self.elements[key]
+ if self.simulation:
+ return
+
+ currentTurn = self.turn
+ if currentTurn == '':
+ currentTurn = self.turnList[-1]
+ hide = True
+
+ Update('_MESSAGES_', elem('Console'))
+ Update('_MESSAGES2_', elem('Error'))
+ Update('_P1_', elem('P1Name'))
+ Update('_C1_', elem('P1Cards'))
+ Update('_P2_', elem('P2Name'))
+ Update('_C2_', elem('P2Cards'))
+ if elem('P3Name') != ' ':
+ Update('_P3_', elem('P3Name'), visible=True)
+ Update('_C3_', elem('P3Cards'), visible=True)
+ Update('_S3_', None, visible=True)
+ if elem('P4Name') != ' ':
+ Update('_P4_', elem('P4Name'), visible=True)
+ Update('_C4_', elem('P4Cards'), visible=True)
+ Update('_S4_',None, visible=True)
+ Update('_CARDS_LEFT_', '{} Cards Left'.format(elem('DNum')))
+ # hand = self.players[currentTurn].hand
+ hand = self.players[currentTurn].hand.hand
+ i=0
+ for i, card in enumerate(hand):
+ if card.value == 'W':
+ card_graphic = wild
+ elif card.value == '+4':
+ card_graphic = plusfour
+ else:
+ card_graphic = get_card_graphic(card.color, card.value)
+ if hide:
+ card_graphic = back
+
+ Update(i, '', image_data=card_graphic, image_subsample=4, image_size=(60, 80), visible=True)
+ else:
+ for x in range(i+1, self.max_cards_displayed+1):
+ Update(x, '', image_data=blank, image_subsample=4, image_size=(60, 80), visible=True)
+ self.max_cards_displayed = max(i, self.max_cards_displayed)
+
+ card_graphic = get_card_graphic(self.currentColor, self.currentValue)
+
+ if self.previous_card is not None:
+ Match.window.Element('_GRAPH_').DrawImage(data=self.previous_card, location=(0,0))
+ Match.window.Element('_GRAPH_').DrawImage(data=card_graphic, location=(100,40))
+
+ self.previous_card = card_graphic
+
+ Match.window.Refresh()
+
+ return ''
+
+ def pauseScreen(self):
+ return
+
+ def isComplete(self):
+ return self.matchComplete
+
+ def next(self):
+ self.turn = self.getNextTurn()
+
+ def getNextTurn(self, forceReverse=False):
+ if forceReverse:
+ reverse = not self.reverse
+ else:
+ reverse = self.reverse
+ currentIndex = self.turnList.index(self.turn)
+ if not reverse:
+ if (currentIndex + 1) == len(self.turnList):
+ return self.turnList[0]
+ else:
+ return self.turnList[currentIndex + 1]
+ else:
+ if currentIndex == 0:
+ return self.turnList[len(self.turnList) - 1]
+ else:
+ return self.turnList[currentIndex - 1]
+
+ def getPlayer(self, playerID):
+ return self.players[playerID]
+
+ def resetDrawBool(self):
+ for identity in self.players:
+ self.players[identity].drew = False
+
+def clearShell():
+ os.system('cls' if os.name == 'nt' else 'clear')
+
+def mainMenu():
+ gs = GameSettings()
+
+ PLAYER_TYPE_HUMAN = 'HUMAN'
+ PLAYER_TYPE_COMPUTER = 'COMPUTER'
+ computer_names = ('Watson', 'SkyNet', 'Hal', 'Metal Gear')
+ layout = [
+ [sg.Button('1 - No Player', size=(20,5), key=0, pad=(1,1)),
+ sg.Button('2 - No Player', size=(20, 5), key=1, pad=(1,1), disabled=True)],
+ [sg.Button('3 - No Player', size=(20, 5), key=2, pad=(1,1), disabled=True),
+ sg.Button('4 - No Player', size=(20, 5), key=3, pad=(1,1), disabled=True)],
+ [sg.Text('Enter player 1 (none) name', key='_TXT_'), sg.Input(key='_IN_', do_not_clear=True, size=(22,1)), sg.Button('Set name')],
+ [sg.Button('Begin'), sg.Button('Settings')],]
+
+ Elem = lambda key: window.Element(key)
+
+ button_states = [0] * 4
+ player_names = [''] * 4
+ player_types = [None] * 4
+
+ window = sg.Window('Uno Setup', border_depth=0).Layout(layout)
+
+ current_player = 0
+ while True: # Event Loop
+ event, values = window.Read()
+ # print(event, values)
+ if event is None or event == 'Exit':
+ break
+ if event == 'Begin':
+ window.Hide()
+ gs.finalizePlayers()
+ # ---------------------- START THE MATCH ----------------------
+ gs = playMatch(gs)
+ for i, id in enumerate(gs.players):
+ player = gs.players[id]
+ window.Element(i).Update('{} - {}\n{} points'.format(i+1, player.name, player.points))
+ window.UnHide()
+ window.Refresh()
+ elif event == 'Settings':
+ layout2 = [[sg.Checkbox('Hide computer hands', key='_HIDE_', default=True)],
+ [sg.T('Computer speed')],
+ [sg.Radio('Fast', 1, key='_FAST_')],
+ [sg.Radio('Normal', 1, key='_NORMAL_', default=True)],
+ [sg.Radio('Slow', 1, key='_SLOW_')],
+ [sg.OK(), sg.Cancel()]
+ ]
+ win2 = sg.Window('Settings').Layout(layout2)
+ ev, vals = win2.Read()
+ win2.Close()
+ if ev == 'OK':
+ if vals['_NORMAL_']:
+ gs.computerspeed = 'normal'
+ if vals['_FAST_']:
+ gs.computerspeed = 'slow'
+ if vals['_SLOW_']:
+ gs.computerspeed = 'slow'
+ gs.hideComputerHands = vals['_HIDE_']
+ elif event == 'Set name':
+ if values['_IN_'] in player_names:
+ sg.Popup('Duplicate - Cannot set to same as other players name')
+ else:
+ Elem(current_player).Update(str(current_player+1) + ' - '+values['_IN_'])
+ player_names[current_player] = values['_IN_']
+ Elem(current_player + (current_player < 3)).Update(disabled=False)
+ if player_types[current_player] == PLAYER_TYPE_HUMAN:
+ addPlayer(gs, values['_IN_'])
+ else:
+ addComputer(gs, values['_IN_'])
+ elif 0 <= event <= 3:
+ current_player = event
+ state = button_states[event] = button_states[event]+1 if button_states[event] < 2 else 0
+ Elem('_TXT_').Update('Enter Player %s (%s) Name'%(str(current_player+1), ('human', 'computer', 'none')[state-1]))
+ if state == 1:
+ Elem('_IN_').SetFocus()
+ Elem('_IN_').Update('Player name', select=True)
+ Elem(event).Update(str(event+1) +' - Player')
+ player_types[event] = PLAYER_TYPE_HUMAN
+ elif state == 2:
+ Elem('_IN_').SetFocus()
+ Elem('_IN_').Update(computer_names[event], select=True)
+ Elem(event).Update(str(event+1) + ' - ' + computer_names[event])
+ player_types[event] = PLAYER_TYPE_COMPUTER
+ elif state == 0:
+ Elem(event).Update(str(event+1) +' - No Player')
+ Elem('_IN_').SetFocus()
+ Elem('_IN_').Update('', select=True)
+ for i in range(event):
+ pass
+ player_types[event] = None
+ player_names[event] = ''
+ for i in range(event+1,4):
+ Elem(i).Update(text='%s - No player'%i, disabled=True)
+ player_names[i] = ''
+ try:
+ gs.removePlayer(i)
+ except:
+ pass
+ window.Close()
+ return player_names
+
+
+def playMatch(gs):
+ m = Match(gs)
+ m.begin()
+ Match.window.Element('_QUIT_').Update(visible=True)
+ while (not m.isComplete()):
+ m.nextTurn()
+ gs = m.end(gs)
+ Match.window.Close()
+ Match.window = None
+ return gs
+
+
+def addPlayer(gs, name):
+ p = Player(name)
+ gs.addPlayer(p)
+ gs.mainMenuError = ""
+
+ return gs
+
+
+def addComputer(gs, name):
+ c = ComputerPlayer(name)
+ gs.addPlayer(c)
+
+ return gs
+
+
+
+if __name__ == "__main__":
+ mainMenu()
+
diff --git a/DemoPrograms old/Demo_Window_Disappear.py b/DemoPrograms old/Demo_Window_Disappear.py
new file mode 100644
index 000000000..603fdb0d8
--- /dev/null
+++ b/DemoPrograms old/Demo_Window_Disappear.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+layout = [[ sg.Text('My Window') ],
+ [ sg.Button('Disappear')]]
+
+window = sg.Window('My window').Layout(layout)
+
+while True:
+ event, values = window.Read()
+ if event is None:
+ break
+ if event == 'Disappear':
+ window.Disappear()
+ sg.Popup('Click OK to make window reappear')
+ window.Reappear()
+
diff --git a/DemoPrograms old/Demo_YouTube_Intro.py b/DemoPrograms old/Demo_YouTube_Intro.py
new file mode 100644
index 000000000..88c2690f6
--- /dev/null
+++ b/DemoPrograms old/Demo_YouTube_Intro.py
@@ -0,0 +1,11 @@
+import PySimpleGUI as sg
+
+layout = [[sg.Text('What is your name?')],
+ [sg.InputText()],
+ [sg.Button('Ok')]]
+
+window = sg.Window('Title of Window').Layout(layout)
+
+event, values = window.Read()
+
+sg.Popup('Hello {}'.format(values[0]))
\ No newline at end of file
diff --git a/DemoPrograms old/Demo_Youtube-dl_Frontend.py b/DemoPrograms old/Demo_Youtube-dl_Frontend.py
new file mode 100644
index 000000000..c2503b85e
--- /dev/null
+++ b/DemoPrograms old/Demo_Youtube-dl_Frontend.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import subprocess
+
+"""
+Simple wrapper for youtube-dl.exe.
+Paste the youtube link into the GUI. The GUI link is queried when you click Get List.
+Get List will populate the pulldown list with the language options available for the video.
+Choose the language to download and click Download
+"""
+
+def DownloadSubtitlesGUI():
+ sg.ChangeLookAndFeel('Dark')
+
+ combobox = sg.InputCombo(values=['',], size=(10,1), key='lang')
+ layout = [
+ [sg.Text('Subtitle Grabber', size=(40, 1), font=('Any 15'))],
+ [sg.T('YouTube Link'),sg.In(default_text='',size=(60,1), key='link', do_not_clear=True) ],
+ [sg.Output(size=(90,20), font='Courier 12')],
+ [sg.Button('Get List')],
+ [sg.T('Language Code'), combobox, sg.Button('Download')],
+ [sg.Button('Exit', button_color=('white', 'firebrick3'))]
+ ]
+
+ window = sg.Window('Subtitle Grabber launcher', text_justification='r', default_element_size=(15,1), font=('Any 14')).Layout(layout)
+
+ # ---===--- Loop taking in user input and using it to query HowDoI --- #
+ while True:
+ event, values = window.Read()
+ if event in ('Exit', None):
+ break # exit button clicked
+ link = values['link']
+ if event == 'Get List':
+ print('Getting list of subtitles....')
+ window.Refresh()
+ command = [f'C:\\Python\\Anaconda3\\Scripts\\youtube-dl.exe --list-subs {link}',]
+ output = ExecuteCommandSubprocess(command, wait=True, quiet=True)
+ lang_list = [o[:5].rstrip() for o in output.split('\n') if 'vtt' in o]
+ lang_list = sorted(lang_list)
+ combobox.Update(values=lang_list)
+ print('Done')
+
+ elif event == 'Download':
+ lang = values['lang'] or 'en'
+ print(f'Downloading subtitle for {lang}...')
+ window.Refresh()
+ command = [f'C:\\Python\\Anaconda3\\Scripts\\youtube-dl.exe --sub-lang {lang} --write-sub {link}',]
+ print(ExecuteCommandSubprocess(command, wait=True, quiet=False))
+ print('Done')
+
+
+def ExecuteCommandSubprocess(command, wait=False, quiet=True, *args):
+ try:
+ sp = subprocess.Popen([command,*args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if wait:
+ out, err = sp.communicate()
+ if not quiet:
+ if out:
+ print(out.decode("utf-8"))
+ if err:
+ print(err.decode("utf-8"))
+ except Exception as e:
+ print('Exception encountered running command ', e)
+ return ''
+
+ return (out.decode('utf-8'))
+
+
+if __name__ == '__main__':
+ DownloadSubtitlesGUI()
+
diff --git a/DemoPrograms old/Demo_psutil_Kill_Processes.py b/DemoPrograms old/Demo_psutil_Kill_Processes.py
new file mode 100644
index 000000000..95be70525
--- /dev/null
+++ b/DemoPrograms old/Demo_psutil_Kill_Processes.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+import sys
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import os
+import signal
+import psutil
+import operator
+
+CONFIRM_KILLS = False
+
+"""
+ Utility to show running processes, CPU usage and provides way to kill processes.
+ Based on psutil package that is easily installed using pip
+"""
+
+def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
+ timeout=None, on_terminate=None):
+ """Kill a process tree (including grandchildren) with signal
+ "sig" and return a (gone, still_alive) tuple.
+ "on_terminate", if specified, is a callabck function which is
+ called as soon as a child terminates.
+ """
+ if pid == os.getpid():
+ raise RuntimeError("I refuse to kill myself")
+ parent = psutil.Process(pid)
+ children = parent.children(recursive=True)
+ if include_parent:
+ children.append(parent)
+ for p in children:
+ p.send_signal(sig)
+ gone, alive = psutil.wait_procs(children, timeout=timeout,
+ callback=on_terminate)
+ return (gone, alive)
+
+
+def show_list_by_name(window):
+ psutil.cpu_percent(interval=.1)
+ procs = psutil.process_iter()
+ all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
+ sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(1), reverse=False)
+ display_list = []
+ for process in sorted_by_cpu_procs:
+ display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0] / 10, process[1]))
+ window.FindElement('_processes_').Update(display_list)
+ return display_list
+
+def main():
+
+ # ---------------- Create Form ----------------
+ # sg.ChangeLookAndFeel('Topanga')
+
+ layout = [[sg.Text('Process Killer - Choose one or more processes',
+ size=(45,1), font=('Helvetica', 15), text_color='red')],
+ [sg.Listbox(values=[' '], size=(50, 30), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 12), key='_processes_')],
+ [sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')],
+ [sg.T('Filter by typing name', font='ANY 14'), sg.In(size=(15,1), font='any 14', key='_filter_')],
+ [sg.Button('Sort by Name', ),
+ sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')),
+ sg.Button('Kill', button_color=('white','red'), bind_return_key=True),
+ sg.Exit(button_color=('white', 'sea green'))]]
+
+ window = sg.Window('Process Killer',
+ keep_on_top=True,
+ auto_size_buttons=False,
+ default_button_element_size=(12,1),
+ return_keyboard_events=True,
+ ).Layout(layout).Finalize()
+
+
+ display_list = show_list_by_name(window)
+ # ---------------- main loop ----------------
+ while (True):
+ # --------- Read and update window --------
+ event, values = window.Read()
+ if event is None or event == 'Exit':
+ break
+
+ # skip mouse, control key and shift key events entirely
+ if 'Mouse' in event or 'Control' in event or 'Shift' in event:
+ continue
+
+ # --------- Do Button Operations --------
+ if event == 'Sort by Name':
+ display_list = show_list_by_name(window)
+ # psutil.cpu_percent(interval=.1)
+ # procs = psutil.process_iter()
+ # all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
+ # sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(1), reverse=False)
+ # display_list = []
+ # for process in sorted_by_cpu_procs:
+ # display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
+ # window.FindElement('_processes_').Update(display_list)
+ elif event == 'Kill':
+ processes_to_kill = values['_processes_']
+ for proc in processes_to_kill:
+ pid = int(proc[0:5])
+ # if sg.PopupYesNo('About to kill {} {}'.format(pid, proc[12:]), keep_on_top=True) == 'Yes':
+ try:
+ kill_proc_tree(pid=pid)
+ except:
+ sg.PopupNoWait('Error killing process', auto_close_duration=1, auto_close=True)
+ elif event == 'Sort by % CPU':
+ psutil.cpu_percent(interval=.1)
+ procs = psutil.process_iter()
+ all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
+ sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(0), reverse=True)
+ display_list = []
+ for process in sorted_by_cpu_procs:
+ display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
+ window.FindElement('_processes_').Update(display_list)
+ else: # was a typed character
+ if display_list is not None:
+ new_output = []
+ for line in display_list:
+ if values['_filter_'] in line.lower():
+ new_output.append(line)
+ window.FindElement('_processes_').Update(new_output)
+
+
+if __name__ == "__main__":
+ main()
+ sys.exit(0)
\ No newline at end of file
diff --git a/DemoPrograms old/TutorialCPUUtilization.py b/DemoPrograms old/TutorialCPUUtilization.py
new file mode 100644
index 000000000..003115d72
--- /dev/null
+++ b/DemoPrograms old/TutorialCPUUtilization.py
@@ -0,0 +1,18 @@
+import PySimpleGUI as sg
+import psutil
+
+layout = [ [sg.Text('CPU Utilization')] ,
+ [sg.Text('', size=(8,2), font='Helvetica 20', justification='center', key='_text_')],
+ [sg.Exit()]]
+
+window = sg.Window('CPU Meter').Layout(layout)
+
+while True:
+ button, values = window.ReadNonBlocking()
+
+ if button == 'Exit' or values is None:
+ break
+
+ cpu_percent = psutil.cpu_percent(interval=1)
+
+ window.FindElement('_text_').Update(f'CPU {cpu_percent:02.0f}%')
diff --git a/DemoPrograms old/default_icon.ico b/DemoPrograms old/default_icon.ico
new file mode 100644
index 000000000..1a41525ec
Binary files /dev/null and b/DemoPrograms old/default_icon.ico differ
diff --git a/DemoPrograms old/ping.py b/DemoPrograms old/ping.py
new file mode 100644
index 000000000..3df8635dc
--- /dev/null
+++ b/DemoPrograms old/ping.py
@@ -0,0 +1,572 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+#=============================================================================#
+import argparse
+import os, sys, socket, struct, select, time, signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+#=============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+myStats = MyStats # NOT Used globally anymore.
+
+#=============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string)/2))*2
+ sum = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum = sum + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum = sum + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string)-1]
+ try: # For Python3
+ sum += loByte
+ except: # For Python2
+ sum += ord(loByte)
+
+ sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
+ sum += (sum >> 16) # Add carry from above (if any)
+ answer = ~sum & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+#=============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet = False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime-sentTime)*1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+#=============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ #destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size-8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ #data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+#=============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout/1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ #print (len(recPacket.encode()))
+ return timeReceived, (dataSize+8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+#=============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime/myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+#=============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+#=============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ dump_stats(myStats)
+
+#=============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return False
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+#=============================================================================#
+def main():
+
+ parser = argparse.ArgumentParser(description=__description__)
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='quiet output')
+ parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS,
+ help=('number of packets to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT,
+ help=('time to wait for a response in seoncds '
+ '(default: %(default)s)'))
+ parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE,
+ help=('number of data bytes to be sent '
+ '(default: %(default)s)'))
+ parser. add_argument('destination')
+ # args = parser.parse_args()
+
+ ping = verbose_ping
+ # if args.quiet:
+ # ping = quiet_ping
+ ping('Google.com', timeout=1000)
+ # ping(args.destination, timeout=args.timeout*1000, count=args.count,
+ # packet_size=args.packet_size)
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py b/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py
deleted file mode 100644
index dc4bd6f41..000000000
--- a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py
+++ /dev/null
@@ -1,1106 +0,0 @@
-'''
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
- Licensed under LGPL3
-'''
-
-import os
-import sys
-import mmap, re
-import warnings
-import PySimpleGUI as sg
-
-version = '6.0.1'
-__version__ = version.split()[0]
-
-
-packages_with_weird_names = {'cv2':'opencv-python',
- 'PIL':'pillow',
- 'vlc':'python-vlc',
- }
-
-
-"""
- PySimpleGUI Demo Program Browser
-
- Originaly written for PySimpleGUI Demo Programs, but expanded to
- be a general purpose tool. Enable Advanced Mode in settings for more fun
-
- Use to filter and search your source code tree.
- Then run or edit your files
-
- Filter the list of :
- * Search using filename
- * Searching within the programs' source code (like grep)
-
- The basic file operations are
- * Edit a file in your editor
- * Run a file
- * Filter file list
- * Search in files
- * Run a regular expression search on all files
- * Display the matching line in a file
-
- Additional operations
- * Edit this file in editor
-
- Keeps a "history" of the previously chosen folders to easy switching between projects
-
- Versions:
- 5.0.0 11-Feb-2024 The NEW Demo Browser for use with PySimpleGUI 5!
- 5.1.0 08-Apr-2024 Several new Demo Programs, updated Matplotlib ping demo, license ver 1.1
- 5.2.0 14-Aug-2024 Fixed erronous import error (when import line started with "from")
- Added a new "Path" input so that an arbitrary file can be executed easily (or edited)
- 5.3.0 15-Aug-2024 One last change for the new path input... clear other fields if chars are entered
- 6.0 8-Apr-2026 Major version bump to match the commercial to LGPL3 license change
- 6.0.1 9-Apr-2026 Set the likely location of the demo programs as the initial path in the settings window
-
- Copyright 2018-2026 PySinpleGUI. All rights reserved.
-"""
-
-'''
-MM""""""""`M oo dP
-MM mmmmmmmM 88
-M' MMMM dP 88 .d8888b.
-MM MMMMMMMM 88 88 88ooood8
-MM MMMMMMMM 88 88 88. ...
-MM MMMMMMMM dP dP `88888P'
-MMMMMMMMMMMM
-
-MM""""""""`M
-MM mmmmmmmM
-M' MMMM dP dP 88d888b. .d8888b. .d8888b.
-MM MMMMMMMM 88 88 88' `88 88' `"" Y8ooooo.
-MM MMMMMMMM 88. .88 88 88 88. ... 88
-MM MMMMMMMM `88888P' dP dP `88888P' `88888P'
-MMMMMMMMMMMM
-'''
-
-def get_file_list_dict():
- """
- Returns dictionary of files
- Key is short filename
- Value is the full filename and path
-
- :return: Dictionary of demo files
- :rtype: Dict[str:str]
- """
- python_only = not sg.user_settings_get_entry('-show all files-', False)
- demo_path = get_demo_path()
- demo_files_dict = {}
- for dirname, dirnames, filenames in os.walk(demo_path):
- for filename in filenames:
- if python_only is not True or filename.endswith('.py') or filename.endswith('.pyw'):
- fname_full = os.path.join(dirname, filename)
- if filename not in demo_files_dict.keys():
- demo_files_dict[filename] = fname_full
- else:
- # Allow up to 100 dupicated names. After that, give up
- for i in range(1, 100):
- new_filename = f'{filename}_{i}'
- if new_filename not in demo_files_dict:
- demo_files_dict[new_filename] = fname_full
- break
-
- return demo_files_dict
-
-
-def get_file_list():
- """
- Returns list of filenames of files to display
- No path is shown, only the short filename
-
- :return: List of filenames
- :rtype: List[str]
- """
- return sorted(list(get_file_list_dict().keys()))
-
-
-def get_file_list_full_filename():
- """
- Returns list of filenames of files to display
- No path is shown, only the short filename
-
- :return: List of filenames
- :rtype: List[str]
- """
- return sorted(list(get_file_list_dict().values()))
-
-
-
-def get_demo_path():
- """
- Get the top-level folder path
- :return: Path to list of files using the user settings for this file. Returns folder of this file if not found
- :rtype: str
- """
- demo_path = sg.user_settings_get_entry('-demos folder-', os.path.dirname(__file__))
-
- return demo_path
-
-
-def get_global_editor():
- """
- Get the path to the editor based on user settings or on PySimpleGUI's global settings
-
- :return: Path to the editor
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- return global_editor
-
-
-def get_editor():
- """
- Get the path to the editor based on user settings or on PySimpleGUI's global settings
-
- :return: Path to the editor
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- user_editor = sg.user_settings_get_entry('-editor program-', '')
- if user_editor == '':
- user_editor = global_editor
-
- return user_editor
-
-def using_local_editor():
- user_editor = sg.user_settings_get_entry('-editor program-', None)
- return get_editor() == user_editor
-
-
-def get_explorer():
- """
- Get the path to the file explorer program
-
- :return: Path to the file explorer EXE
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_explorer = sg.pysimplegui_user_settings.get('-explorer program-', '')
- except:
- global_explorer = ''
- explorer = sg.user_settings_get_entry('-explorer program-', '')
- if explorer == '':
- explorer = global_explorer
- return explorer
-
-
-def advanced_mode():
- """
- Returns True is advanced GUI should be shown
-
- :return: True if user indicated wants the advanced GUI to be shown (set in the settings window)
- :rtype: bool
- """
- return sg.user_settings_get_entry('-advanced mode-', True)
-
-
-
-def get_theme():
- """
- Get the theme to use for the program
- Value is in this program's user settings. If none set, then use PySimpleGUI's global default theme
- :return: The theme
- :rtype: str
- """
- # First get the current global theme for PySimpleGUI to use if none has been set for this program
- try:
- global_theme = sg.theme_global()
- except:
- global_theme = sg.theme()
- # Get theme from user settings for this program. Use global theme if no entry found
- user_theme = sg.user_settings_get_entry('-theme-', '')
- if user_theme == '':
- user_theme = global_theme
- return user_theme
-
-# We handle our code properly. But in case the user types in a flag, the flags are now in the middle of a regex. Ignore this warning.
-
-warnings.filterwarnings("ignore", category=DeprecationWarning)
-
-# New function
-def get_line_number(file_path, string, dupe_lines):
- lmn = 0
- with open(file_path, encoding="utf-8") as f:
- for num, line in enumerate(f, 1):
- if string.strip() == line.strip() and num not in dupe_lines:
- lmn = num
- return lmn
-
-def kill_ascii(s):
- return "".join([x if ord(x) < 128 else '?' for x in s])
-
-'''
-MM'""""'YMM dP dP
-M' .mmm. `M 88 88
-M MMMMMooM 88d888b. .d8888b. .d8888b. 88 .dP
-M MMMMMMMM 88' `88 88ooood8 88' `"" 88888"
-M. `MMM' .M 88 88 88. ... 88. ... 88 `8b.
-MM. .dM dP dP `88888P' `88888P' dP `YP
-MMMMMMMMMMM
-
-M""M dP
-M M 88
-M M 88d8b.d8b. 88d888b. .d8888b. 88d888b. d8888P .d8888b.
-M M 88'`88'`88 88' `88 88' `88 88' `88 88 Y8ooooo.
-M M 88 88 88 88. .88 88. .88 88 88 88
-M M dP dP dP 88Y888P' `88888P' dP dP `88888P'
-MMMM 88
- dP
-'''
-
-
-def offer_install(module):
- if sg.popup_yes_no(f'The program failed to import a package. You need to install {module}.', 'Would you like PySimpleGUI to install this package for you?',
- title=f'Package {module} not found') != 'Yes':
- return False
- if module in packages_with_weird_names.keys():
- module = packages_with_weird_names[module]
- try:
- sg.execute_pip_install_package(module)
- sg.cprint(f'Module {module} successfully installed.', colors='white on green')
- sg.popup('Restarting your application to reload the modules...', auto_close_duration=2, auto_close=True)
- sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False)
- exit()
- return True
- except Exception as e:
- sg.popup('Error performing the pip install. You may need a newer version of PySimpleGUI.', e)
- # pip_install_latest(package)
- # sg.popup('Restarting your application...', auto_close_duration=2, auto_close=True)
- # sg.execute_command_subprocess(sys.executable, __file__, pipe_output=False, wait=False)
- return False
-
-def check_module(module):
- try:
- __import__(module)
- # print(f'{module} passed')
- return True
- except ImportError:
- sg.cprint(f'Module {module} not found.', colors='white on red')
- if offer_install(module):
- return True
- return False
-
-
-def check_modules_on_import_line(line:str):
- modules = line.split(' ', 1)[1].split(',')
- # print(f'modules = {modules}')
- for module in modules:
- if ' as ' in module:
- module = module.split('as')[0].strip()
- if '.' in module:
- module = module.split('.')[0].strip()
- # print(f'checking "{module}"')
- if not check_module(module):
- return False
-
- return True
-
-
-
-
-def check_imports_in_file(filename):
- # Check if the file exists
- if not os.path.exists(filename):
- print("File does not exist")
- return False
- all_passed = True
- # Open the file
- file = open(filename, 'r', encoding='utf-8')
- lines = file.readlines()
- # Read the file line by line
- for line in lines:
- # print(line)
- # Check if the line is an import statement
- sline = line.strip() # strip the line in case it's indented
- if sline.startswith('import'):
- # Check if the module exists
- if not check_modules_on_import_line(sline):
- all_passed = False
- elif sline.startswith('from') and 'import' in sline:
- module = re.search(r'from (\w+)', sline).group(1)
- if not check_module(module):
- all_passed = False
- # Close the file
- file.close()
- return all_passed
-
-'''
-MM""""""""`M oo dP
-MM mmmmmmmM 88
-M' MMMM dP 88 .d8888b.
-MM MMMMMMMM 88 88 88ooood8
-MM MMMMMMMM 88 88 88. ...
-MM MMMMMMMM dP dP `88888P'
-MMMMMMMMMMMM
-
-MP""""""`MM dP
-M mmmmm..M 88
-M. `YM .d8888b. .d8888b. 88d888b. .d8888b. 88d888b.
-MMMMMMM. M 88ooood8 88' `88 88' `88 88' `"" 88' `88
-M. .MMM' M 88. ... 88. .88 88 88. ... 88 88
-Mb. .dM `88888P' `88888P8 dP `88888P' dP dP
-MMMMMMMMMMM
-'''
-
-
-
-# def search_files(file_list, search_string):
-# found_list = []
-# for file in file_list:
-# with open(file, 'r') as f:
-# # Memory-map the file
-# try:
-# mmapped_file = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
-# except:
-# continue
-# # Search for the string in the file
-# if mmapped_file.find(bytes(search_string, 'utf-8')) != -1:
-# # print(f"String found in file: {file}")
-# found_list.append(os.path.basename(file))
-# # else:
-# # print(f"String not found in file: {file}")
-# return found_list
-
-def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=None, ignore_case=True, show_first_match=True):
- """
- Search through the demo files for a string.
- The case of the string and the file contents are ignored
-
- :param string: String to search for
- :param verbose: if True print the FIRST match
- :type verbose: bool
- :param find_all_matches: if True, then return all matches in the dictionary
- :type find_all_matches: bool
- :return: List of files containing the string
- :rtype: List[str]
- """
-
-
- # So you face a predicament here. You wish to read files, both small and large; however the bigger the file/bigger the list, the longer to read the file.
- # This probably isn't what you want, right?
- # Well, we can't use a direct command line to run grep and parse. But it is an option. The user may not have it.
- # We could check if grep exists and if not use our method; but it isn't the best way.
- # So using background knowldge, we know that grep is *very* fast.
- #
- # Why?
- # Grep reads a *ton* of files into memory then searches through the memory to find the string or regex/pattern corresponding to the file.
- # (This is useful if you ever accidently delete a file, grep may be able to get you the contents of it again!)
- # How can we load a file into memory on python as fast as grep whilst keeping it universal?
- # memory mapping (mmap).
- # We can't load a lot of files into memory as we may face issues with watchdog on other operating systems. So we load one file at a time and search though there.
- # This will allow the fastest searching and loading of a file without sacrificing read times.
- # 2.8 seconds on the highend for both small and large files in memory.
- # We also don't have to iterate over lines this way.
- file_list = []
- num_files = 0
- matched_dict = {}
- for file in demo_files_dict:
- try:
- full_filename = demo_files_dict[file]
- if not demo_files_dict == get_file_list_dict():
- full_filename = full_filename[0]
- matches = None
-
- with open(full_filename, 'rb', 0) as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as s:
- if regex:
- window['-FIND NUMBER-'].update(f'{num_files} files')
- window.refresh()
- matches = re.finditer(bytes("^.*(" + string + ").*$", 'utf-8'), s, re.MULTILINE)
- if matches:
- for match in matches:
- if match is not None:
- if file not in file_list:
- file_list.append(file)
- num_files += 1
- if verbose:
- sg.cprint(f"{file}:", c = 'white on green')
- sg.cprint(f"{match.group(0).decode('utf-8')}\n")
- else:
- window['-FIND NUMBER-'].update(f'{num_files} files')
- window.refresh()
- matches = None
- if ignore_case:
- if show_first_match:
- matches = re.search(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- matches = re.finditer(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- if show_first_match:
- matches = re.search(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- matches = re.finditer(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE)
- if matches:
- if show_first_match:
- #file_list.append(file)
- #num_files += 1
- match_array = []
-
- matched_str = matches.group(0).decode('utf-8')
- if not all(x in matched_str for x in ("b'", '=')) and len(matched_str) < 500:
- # safe to assume this is not a base64 string as it does not contain the proper ending
- match_array.append(matches.group(0).decode('utf-8'))
- matched_dict[full_filename] = match_array
- file_list.append(file)
- num_files += 1
- else:
- # We need to do this because strings are "falsy" in Python, but empty matches still return True...
- append_file = False
- match_array = []
- for match_ in matches:
- matched_str = match_.group(0).decode('utf-8')
- if matched_str:
- if not all(x in matched_str for x in ("b'", '=')) and len(matched_str) < 500:
- # if len(match_str) < 500 and "=" not in match_str and "b'" not in match_str:
- match_array.append(matched_str)
- append_file = True
- if append_file:
- file_list.append(file)
- num_files += 1
- matched_dict[full_filename] = match_array
-
- # del matches
- except ValueError:
- del matches
- except Exception as e:
- exc_type, exc_obj, exc_tb = sys.exc_info()
- fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
- print(exc_type, fname, exc_tb.tb_lineno)
- print(f'{file}', e, file=sys.stderr)
-
- # Format of the matches dictionary
- # Filename, [num1, num2, num3]
- file_lines_dict = {}
- list_of_matches = []
- if not regex:
- for key in matched_dict:
- head, tail = os.path.split(key)
- # Tails. Don't wanna put Washington in places he doesn't want to be.
- file_array_old = [key]
-
- file_array_new = []
-
- file_match_list = []
-
- if verbose:
- sg.cprint(f"{tail}:", c='white on green')
- try:
- dupe_lines = []
- for _match in matched_dict[key]:
- line_num_match = get_line_number(key, _match, dupe_lines)
- dupe_lines.append(line_num_match)
- file_array_new.append(line_num_match)
- file_match_list.append(_match) # I *really* overthinked this.
- if verbose:
- sg.cprint(f"Line: {line_num_match} ", c='white on purple', end='')
- sg.cprint(f"{_match.strip()}\n")
- # Make a list of the matches found in this file to add to the dictionry
- list_of_matches.append(_match.strip())
- file_array_old.append(file_array_new)
- file_array_old.append(file_match_list)
-
- if tail in file_lines_dict:
- for i in range(1, 100):
- new_tail = f'{tail}_{i}'
- if new_tail not in file_lines_dict:
- file_lines_dict[new_tail] = file_array_old
- break
- else:
- file_lines_dict[tail] = file_array_old
- except Exception as e:
- pass
- find_in_file.file_list_dict = file_lines_dict
-
- file_list = list(set(file_list))
- return file_list
-
-
-def window_choose_line_to_edit(filename, full_filename, line_num_list, match_list):
- # sg.popup('matches previously found for this file:', filename, line_num_list)
- i = 0
- if len(line_num_list) == 1:
- return full_filename, line_num_list[0]
- layout = [[sg.T(f'Choose line from {filename}', font='_ 14')]]
- for line in sorted(set(line_num_list)):
- match_text = match_list[i]
- layout += [[sg.Text(f'Line {line} : {match_text}', key=('-T-', line), enable_events=True, size=(min(len(match_text), 90), None))]]
- i += 1
- layout += [[sg.B('Cancel')]]
-
- window = sg.Window('Open Editor', layout)
-
- line_chosen = line_num_list[0]
- while True:
- event, values = window.read()
- if event in ('Cancel', sg.WIN_CLOSED):
- line_chosen = None
- break
- # At this point we know a line was chosen
- line_chosen = event[1]
- break
-
- window.close()
- return full_filename, line_chosen
-
-'''
-MP""""""`MM dP dP oo
-M mmmmm..M 88 88
-M. `YM .d8888b. d8888P d8888P dP 88d888b. .d8888b. .d8888b.
-MMMMMMM. M 88ooood8 88 88 88 88' `88 88' `88 Y8ooooo.
-M. .MMM' M 88. ... 88 88 88 88 88 88. .88 88
-Mb. .dM `88888P' dP dP dP dP dP `8888P88 `88888P'
-MMMMMMMMMMM .88
- d8888P
-M""MMM""MMM""M oo dP
-M MMM MMM M 88
-M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP
-M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88
-M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88'
-M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P
-MMMMMMMMMMMMMM
-
-'''
-
-
-def settings_window():
- """
- Show the settings window.
- This is where the folder paths and program paths are set.
- Returns True if settings were changed
-
- :return: True if settings were changed
- :rtype: (bool)
- """
-
- try:
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- try:
- global_explorer = sg.pysimplegui_user_settings.get('-explorer program-')
- except:
- global_explorer = ''
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_theme = sg.theme_global()
- except:
- global_theme = ''
-
- # normally the demo programs are located in a folder in the same folder as the demo browser
- default_demo_programs_path = os.path.join(os.path.dirname(__file__), 'demo_programs')
-
- layout = [[sg.T('Program Settings', font='DEFAULT 25')],
- [sg.T('Path to Tree', font='_ 16')],
- [sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', get_demo_path()), size=(50, 1), auto_size_text=False, key='-FOLDERNAME-'),
- sg.FolderBrowse('Folder Browse', target='-FOLDERNAME-', initial_folder=default_demo_programs_path), sg.B('Clear History')],
- [sg.T('Editor Program', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_editor)],
- [ sg.In(sg.user_settings_get_entry('-editor program-', ''),k='-EDITOR PROGRAM-'), sg.FileBrowse()],
- [sg.T('File Explorer Program', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_explorer)],
- [ sg.In(sg.user_settings_get_entry('-explorer program-'), k='-EXPLORER PROGRAM-'), sg.FileBrowse()],
- [sg.T('Theme', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_theme)],
- [sg.Combo(['']+sg.theme_list(),sg.user_settings_get_entry('-theme-', ''), readonly=True, k='-THEME-')],
- [sg.T('Double-click a File Will:'), sg.R('Run', 2, sg.user_settings_get_entry('-dclick runs-', False), k='-DCLICK RUNS-'), sg.R('Edit', 2, sg.user_settings_get_entry('-dclick edits-', False), k='-DCLICK EDITS-'), sg.R('Nothing', 2, sg.user_settings_get_entry('-dclick none-', False), k='-DCLICK NONE-')],
- [sg.CB('Check That Imported Modules Are Installed', sg.user_settings_get_entry('-check imports-', False), k='-CHECK IMPORTS-')],
- [sg.CB('Use Advanced Interface', default=advanced_mode() ,k='-ADVANCED MODE-')],
- [sg.B('Ok', bind_return_key=True), sg.B('Cancel')],
- ]
-
- window = sg.Window('Settings', layout)
-
- settings_changed = False
-
- while True:
- event, values = window.read()
- if event in ('Cancel', sg.WIN_CLOSED):
- break
- if event == 'Ok':
- sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-'])
- sg.user_settings_set_entry('-editor program-', values['-EDITOR PROGRAM-'])
- sg.user_settings_set_entry('-theme-', values['-THEME-'])
- sg.user_settings_set_entry('-folder names-', list(set(sg.user_settings_get_entry('-folder names-', []) + [values['-FOLDERNAME-'], ])))
- sg.user_settings_set_entry('-explorer program-', values['-EXPLORER PROGRAM-'])
- sg.user_settings_set_entry('-advanced mode-', values['-ADVANCED MODE-'])
- sg.user_settings_set_entry('-dclick runs-', values['-DCLICK RUNS-'])
- sg.user_settings_set_entry('-dclick edits-', values['-DCLICK EDITS-'])
- sg.user_settings_set_entry('-dclick nothing-', values['-DCLICK NONE-'])
- sg.user_settings_set_entry('-check imports-', values['-CHECK IMPORTS-'])
- settings_changed = True
- break
- elif event == 'Clear History':
- sg.user_settings_set_entry('-folder names-', [])
- sg.user_settings_set_entry('-last filename-', '')
- window['-FOLDERNAME-'].update(values=[], value='')
-
- window.close()
- return settings_changed
-
-
-
-'''
-M"""""`'"""`YM oo
-M mm. mm. M
-M MMM MMM M .d8888b. dP 88d888b.
-M MMM MMM M 88' `88 88 88' `88
-M MMM MMM M 88. .88 88 88 88
-M MMM MMM M `88888P8 dP dP dP
-MMMMMMMMMMMMMM
-
-M""MMM""MMM""M oo dP
-M MMM MMM M 88
-M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP
-M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88
-M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88'
-M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P
-MMMMMMMMMMMMMM
-'''
-
-ML_KEY = '-ML-' # Multline's key
-
-# --------------------------------- Create the window ---------------------------------
-def make_window():
- """
- Creates the main window
- :return: The main window object
- :rtype: (sg.Window)
- """
- theme = get_theme()
- if not theme:
- theme = sg.OFFICIAL_PYSIMPLEGUI_THEME
- sg.theme(theme)
- # First the window layout...2 columns
-
- find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside."
- filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename."
- find_re_tooltip = "Find in file using Regular Expression\nEnter a string in box to search for string inside of the files.\nSearch is performed after clicking the FindRE button."
- run_tooltip = "Run any python file\nEnter full absolute path and then click RUN button."
-
-
- left_col = sg.Column([
- [sg.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50,20), bind_return_key=True, key='-DEMO LIST-', expand_x=True, expand_y=True)],
- [sg.Text('Filter (F1):', tooltip=filter_tooltip, s=8), sg.Input(size=(25, 1), focus=True, enable_events=True, key='-FILTER-', tooltip=filter_tooltip),
- sg.T(size=(15,1), k='-FILTER NUMBER-')],
- [sg.Button('Run'), sg.B('Edit'), sg.B('Clear'), sg.B('Open Folder'), sg.B('Copy Path')],
- [sg.Text('Find (F2):', tooltip=find_tooltip, s=8), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip),
- sg.T(size=(15,1), k='-FIND NUMBER-')],
- [sg.Text('Path (F3):', tooltip=run_tooltip, s=8), sg.Input(size=(25, 1), enable_events=True, key='-RUN PATH-', tooltip=run_tooltip)],
- ], element_justification='l', expand_x=True, expand_y=True)
-
- lef_col_find_re = sg.pin(sg.Col([
- [sg.Text('Find (F4):', tooltip=find_re_tooltip, s=8), sg.Input(size=(25, 1),key='-FIND RE-', tooltip=find_re_tooltip),sg.B('Find RE')]], k='-RE COL-'))
-
- right_col = [
- [sg.Multiline(size=(70, 21), write_only=True, expand_x=True, expand_y=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True, reroute_cprint=True)],
- [sg.B('Settings'), sg.Button('Exit')],
- [sg.T('Demo Browser Ver ' + version)],
- [sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed, font='Default 8', pad=(0,0))],
- [sg.T('Python ver ' + sys.version, font='Default 8', pad=(0,0))],
- [sg.T('Interpreter ' + sg.execute_py_get_interpreter(), font='Default 8', pad=(0,0))],
- ]
-
- options_at_bottom = sg.pin(sg.Column([[sg.CB('Verbose', enable_events=True, k='-VERBOSE-', tooltip='Enable to see the matches in the right hand column'),
- sg.CB('Show only first match in file', default=True, enable_events=True, k='-FIRST MATCH ONLY-', tooltip='Disable to see ALL matches found in files'),
- sg.CB('Find ignore case', default=True, enable_events=True, k='-IGNORE CASE-'),
- sg.CB('Wait for Runs to Complete', default=False, enable_events=True, k='-WAIT-'),
- sg.CB('Show ALL file types', default=sg.user_settings_get_entry('-show all files-', False), enable_events=True, k='-SHOW ALL FILES-'),
- ]],
- pad=(0,0), k='-OPTIONS BOTTOM-', expand_x=True, expand_y=False), expand_x=True, expand_y=False)
-
- choose_folder_at_top = sg.pin(sg.Column([[sg.T('Click settings to set top of your tree or choose a previously chosen folder'),
- sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', ''), size=(50, 30), key='-FOLDERNAME-', enable_events=True, readonly=True)]], pad=(0,0), k='-FOLDER CHOOSE-'))
- # ----- Full layout -----
-
- layout = [[sg.Text('PySimpleGUI Demo Program & Project Browser', font='Any 20')],
- [choose_folder_at_top],
- # [sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True)],
- [sg.Pane([sg.Column([[left_col],[ lef_col_find_re]], element_justification='l', expand_x=True, expand_y=True), sg.Column(right_col, element_justification='c', expand_x=True, expand_y=True) ], orientation='h', relief=sg.RELIEF_SUNKEN, expand_x=True, expand_y=True, k='-PANE-')],
- [options_at_bottom, sg.Sizegrip()]]
-
- # --------------------------------- Create Window ---------------------------------
- window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, resizable=True, use_default_focus=False, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, auto_save_location=True)
- window.set_min_size(window.size)
-
-
- # window.bind("", 'Exit') # matches the underscore shown on the Exit button (For now disabled this feature until buttons with underscore released to PyPI)
-
- window.bind('', '-FOCUS FILTER-')
- window.bind('', '-FOCUS FIND-')
- window.bind('', '-FOCUS RUN PATH-')
- window.bind('', '-FOCUS RE FIND-')
- if not advanced_mode():
- window['-FOLDER CHOOSE-'].update(visible=False)
- window['-RE COL-'].update(visible=False)
- window['-OPTIONS BOTTOM-'].update(visible=False)
-
- window.bring_to_front()
- return window
-
-
-'''
-M""M dP dP dP
-M M 88 88 88
-M M 88d888b. .d8888b. d8888P .d8888b. 88 88 .d8888b. 88d888b.
-M M 88' `88 Y8ooooo. 88 88' `88 88 88 88ooood8 88' `88
-M M 88 88 88 88 88. .88 88 88 88. ... 88
-M M dP dP `88888P' dP `88888P8 dP dP `88888P' dP
-MMMM
-'''
-
-
-def pip_install_thread(window, sp):
- window.write_event_value('-THREAD-', (sp, 'Install thread started'))
- for line in sp.stdout:
- oline = line.decode().rstrip()
- window.write_event_value('-THREAD-', (sp, oline))
-
-
-
-def pip_install_latest():
-
- pip_command = '-m pip install --upgrade --no-cache-dir PySimpleGUI>=5'
-
- python_command = sys.executable # always use the currently running interpreter to perform the pip!
- if 'pythonw' in python_command:
- python_command = python_command.replace('pythonw', 'python')
-
- layout = [[sg.Text('Installing PySimpleGUI', font='_ 14')],
- [sg.Multiline(s=(90, 15), k='-MLINE-', reroute_cprint=True, reroute_stdout=True, echo_stdout_stderr=True, write_only=True, expand_x=True, expand_y=True)],
- [sg.Push(), sg.Button('Downloading...', k='-EXIT-'), sg.Sizegrip()]]
-
- window = sg.Window('Pip Install PySimpleGUI Utilities', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True, resizable=True)
-
- window.disable_debugger()
-
- sg.cprint('Installing with the Python interpreter =', python_command, c='white on purple')
-
- sp = sg.execute_command_subprocess(python_command, pip_command, pipe_output=True, wait=False)
-
- window.start_thread(lambda: pip_install_thread(window, sp), end_key='-THREAD DONE-')
-
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or (event == '-EXIT-' and window['-EXIT-'].ButtonText == 'Done'):
- break
- elif event == '-THREAD DONE-':
- sg.cprint('\n')
- show_package_version('PySimpleGUI')
- sg.cprint('Done Installing PySimpleGUI. Click Done and the program will restart.', c='white on red', font='default 12 italic')
- window['-EXIT-'].update(text='Done', button_color='white on red')
- elif event == '-THREAD-':
- sg.cprint(values['-THREAD-'][1])
-
- window.close()
-
-
-
-
-def make_str_pre_38(package):
- return f"""
-import warnings
-warnings.filterwarnings("ignore", category=DeprecationWarning)
-import pkg_resources
-try:
- ver=pkg_resources.get_distribution("{package}").version.rstrip()
-except:
- ver=' '
-print(ver, end='')
-"""
-
-def make_str(package):
- return f"""
-import importlib.metadata
-
-try:
- ver = importlib.metadata.version("{package}")
-except importlib.metadata.PackageNotFoundError:
- ver = ' '
-print(ver, end='')
-"""
-
-
-def show_package_version(package):
- """
- Function that shows all versions of a package
- """
- interpreter = sg.execute_py_get_interpreter()
- sg.cprint(f'{package} upgraded to ', end='', c='red')
- # print(f'{interpreter}')
- if sys.version_info.major == 3 and sys.version_info.minor in (6, 7): # if running Python version 3.6 or 3.7
- pstr = make_str_pre_38(package)
- else:
- pstr = make_str(package)
- temp_file = os.path.join(os.path.dirname(__file__), 'temp_py.py')
- with open(temp_file, 'w') as file:
- file.write(pstr)
- sg.execute_py_file(temp_file, interpreter_command=interpreter, pipe_output=True, wait=True)
- os.remove(temp_file)
-
-
-
-
-
-'''
-M"""""`'"""`YM oo
-M mm. mm. M
-M MMM MMM M .d8888b. dP 88d888b.
-M MMM MMM M 88' `88 88 88' `88
-M MMM MMM M 88. .88 88 88 88
-M MMM MMM M `88888P8 dP dP dP
-MMMMMMMMMMMMMM
-'''
-# --------------------------------- Main Program Layout ---------------------------------
-
-def main():
- """
- The main program that contains the event loop.
- It will call the make_window function to create the window.
- """
-
- sg.user_settings_filename(filename='psgdemos.json')
-
- sg.user_settings_filename('psgdemos.json')
- sg.set_options(icon=sg.EMOJI_BASE64_HAPPY_IDEA)
- find_in_file.file_list_dict = None
-
- old_typed_value = None
-
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window = make_window()
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window.force_focus()
- window['-FILTER-'].set_focus()
- counter = 0
- while True:
- event, values = window.read()
- # print(event, values)
-
- counter += 1
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- if event == '-DEMO LIST-': # if double clicked (used the bind return key parm)
- if sg.user_settings_get_entry('-dclick runs-'):
- event = 'Run'
- elif sg.user_settings_get_entry('-dclick edits-'):
- event = 'Edit'
- if event == 'Edit':
- editor_program = get_editor()
- for file in values['-DEMO LIST-']:
- if find_in_file.file_list_dict is not None:
- full_filename, line = window_choose_line_to_edit(file, find_in_file.file_list_dict[file][0], find_in_file.file_list_dict[file][1], find_in_file.file_list_dict[file][2])
- else:
- full_filename, line = get_file_list_dict()[file], 1
- if line is not None:
- sg.cprint(f'Editing using {editor_program}', c='white on red', end='')
- sg.cprint('')
- sg.cprint(f'{full_filename}', c='white on purple')
- if not get_editor():
- sg.popup_error_with_traceback('No editor has been configured', 'You need to configure an editor in order to use this feature', 'You can configure the editor in the Demo Brower Settings or the PySimpleGUI Global Settings')
- else:
- if using_local_editor():
- sg.execute_command_subprocess(editor_program, f'"{full_filename}"')
- else:
- try:
- sg.execute_editor(full_filename, line_number=int(line))
- except:
- sg.execute_command_subprocess(editor_program, f'"{full_filename}"')
- else:
- sg.cprint('Editing canceled')
- elif event == 'Run':
- sg.cprint('Running....', c='white on green', end='')
- sg.cprint('')
- if values['-RUN PATH-']: # if a manual file was entered:
- files_to_run = (values['-RUN PATH-'],)
- else:
- files_to_run = values['-DEMO LIST-']
- # for file in values['-DEMO LIST-']:
- for file in files_to_run:
- try:
- file_to_run = str(file_list_dict[file])
- except:
- file_to_run = file
- # sg.cprint('Checking Imports....', c='white on green')
- if sg.user_settings_get_entry('-check imports-', False) and not check_imports_in_file(file_to_run):
- sg.cprint(f'The demo program {os.path.basename(file_to_run)} depends on modules that are not installed.')
- else:
- sg.cprint(file_to_run,text_color='white', background_color='purple')
- try:
- sp = sg.execute_py_file(file_to_run, pipe_output=values['-WAIT-'])
- except Exception as e:
- sg.cprint(f'Error trying to run python file. Error info:', e, c='white on red')
- try:
- if values['-WAIT-']:
- sg.cprint(f'Waiting on results..', text_color='white', background_color='red', end='')
- while True:
- results = sg.execute_get_results(sp)
- sg.cprint(f'STDOUT:', text_color='white', background_color='green')
- sg.cprint(results[0])
- sg.cprint(f'STDERR:', text_color='white', background_color='green')
- sg.cprint(results[1])
- if not sg.execute_subprocess_still_running(sp):
- break
- except AttributeError:
- sg.cprint('Your version of PySimpleGUI needs to be upgraded to fully use the "WAIT" feature.', c='white on red')
- elif event.startswith('Edit Me'):
- editor_program = get_editor()
- sg.cprint(f'opening using {editor_program}:')
- sg.cprint(f'{__file__}', text_color='white', background_color='red', end='')
- sg.execute_command_subprocess(f'{editor_program}', f'"{__file__}"')
- elif event == '-FILTER-':
- new_list = [i for i in file_list if values['-FILTER-'].lower() in i.lower()]
- window['-DEMO LIST-'].update(new_list)
- window['-FILTER NUMBER-'].update(f'{len(new_list)} files')
- window['-FIND NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-RUN PATH-'].update('')
- window['-FIND RE-'].update('')
- elif event == '-RUN PATH-':
- file_list = get_file_list()
- window['-FILTER-'].update('')
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-FIND-'].update('')
- window['-DEMO LIST-'].update(file_list)
- window['-FIND NUMBER-'].update('')
- window['-FIND RE-'].update('')
- window['-ML-'].update('')
- elif event == '-FOCUS FIND-':
- window['-FIND-'].set_focus()
- elif event == '-FOCUS FILTER-':
- window['-FILTER-'].set_focus()
- elif event == '-FOCUS RE FIND-':
- window['-FIND RE-'].set_focus()
- elif event == '-FOCUS RUN PATH-':
- window['-RUN PATH-'].set_focus()
- elif event == '-FIND-' or event == '-FIRST MATCH ONLY-' or event == '-VERBOSE-' or event == '-FIND RE-':
- # file_list = (search_files(get_file_list_full_filename(), values['-FIND-']))
- # window['-DEMO LIST-'].update(file_list)
- # continue
-
- is_ignore_case = values['-IGNORE CASE-']
- old_ignore_case = False
- current_typed_value = str(values['-FIND-'])
- if len(values['-FIND-']) == 1:
- window[ML_KEY].update('')
- window['-VERBOSE-'].update(False)
- values['-VERBOSE-'] = False
- if values['-VERBOSE-']:
- window[ML_KEY].update('')
- if values['-FIND-']:
- if find_in_file.file_list_dict is None or old_typed_value is None or old_ignore_case is not is_ignore_case:
- # New search.
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- elif current_typed_value.startswith(old_typed_value) and old_ignore_case is is_ignore_case:
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], find_in_file.file_list_dict, verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- else:
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND RE-'].update('')
- window['-FILTER-'].update('')
- window['-RUN PATH-'].update('')
- elif values['-FIND RE-']:
- window['-ML-'].update('')
- file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window)
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FILTER-'].update('')
- window['-RUN PATH-'].update('')
- elif event == 'Find RE':
- window['-ML-'].update('')
- file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window)
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FILTER-'].update('')
- window['-RUN PATH-'].update('')
- sg.cprint('Regular expression find completed')
- elif event == 'Settings':
- if settings_window() is True:
- window.close()
- window = make_window()
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- elif event == 'Clear':
- file_list = get_file_list()
- window['-FILTER-'].update('')
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-FIND-'].update('')
- window['-DEMO LIST-'].update(file_list)
- window['-FIND NUMBER-'].update('')
- window['-FIND RE-'].update('')
- window['-RUN PATH-'].update('')
- window['-ML-'].update('')
- elif event == '-FOLDERNAME-':
- sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-'])
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window['-DEMO LIST-'].update(values=file_list)
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-ML-'].update('')
- window['-FIND NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FIND RE-'].update('')
- window['-FILTER-'].update('')
- window['-RUN PATH-'].update('')
- elif event == 'Open Folder':
- explorer_program = get_explorer()
- if explorer_program:
- sg.cprint(f'Opening Folder using {explorer_program}...', c='white on green', end='')
- sg.cprint('')
- for file in values['-DEMO LIST-']:
- file_selected = str(file_list_dict[file])
- file_path = os.path.dirname(file_selected)
- if sg.running_windows():
- file_path = file_path.replace('/', '\\')
- sg.cprint(file_path, text_color='white', background_color='purple')
- sg.execute_command_subprocess(explorer_program, file_path)
- elif event == 'Copy Path':
- for file in values['-DEMO LIST-']:
- sg.cprint('Copying the last highlighted filename in your list')
- if find_in_file.file_list_dict is not None:
- full_filename, line = window_choose_line_to_edit(file, find_in_file.file_list_dict[file][0], find_in_file.file_list_dict[file][1], find_in_file.file_list_dict[file][2])
- else:
- full_filename, line = get_file_list_dict()[file], 1
- if line is not None:
- sg.cprint(f'Added to Clipboard Full Path {full_filename}', c='white on purple')
- sg.clipboard_set(full_filename)
- elif event == 'Version':
- sg.popup_scrolled(sg.get_versions(), f'This Program: {__file__}' ,keep_on_top=True, non_blocking=True)
- elif event == '-SHOW ALL FILES-':
- sg.user_settings_set_entry('-show all files-', values[event])
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window['-DEMO LIST-'].update(values=file_list)
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-ML-'].update('')
- window['-FIND NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FIND RE-'].update('')
- window['-FILTER-'].update('')
- window['-RUN PATH-'].update('')
- window.close()
-
-
-
-
-
-
-if __name__ == '__main__':
-
- main()
diff --git a/DemoPrograms/ButtonClick.wav b/DemoPrograms/ButtonClick.wav
new file mode 100644
index 000000000..f774f70e4
Binary files /dev/null and b/DemoPrograms/ButtonClick.wav differ
diff --git a/DemoPrograms/Demo_All_Elements.py b/DemoPrograms/Demo_All_Elements.py
deleted file mode 100644
index df179cfd2..000000000
--- a/DemoPrograms/Demo_All_Elements.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/bin/env python
-"""
- Example of (almost) all Elements, that you can use in PySimpleGUI.
- Shows you the basics including:
- Naming convention for keys
- Menubar format
- Right click menu format
- Table format
- Running an async event loop
- Theming your application (requires a window restart)
- Displays the values dictionary entry for each element
- And more!
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-def make_window(theme):
- sg.theme(theme)
- menu_def = [['&Application', ['E&xit']],
- ['&Help', ['&About']] ]
- right_click_menu_def = [[], ['Edit Me', 'Versions', 'Nothing','More Nothing','Exit']]
- graph_right_click_menu_def = [[], ['Erase','Draw Line', 'Draw',['Circle', 'Rectangle', 'Image'], 'Exit']]
-
- # Table Data
- data = [["John", 10], ["Jen", 5]]
- headings = ["Name", "Score"]
-
- input_layout = [
-
- # [sg.Menu(menu_def, key='-MENU-')],
- [sg.Text('Anything that requires user-input is in this tab!')],
- [sg.Input(key='-INPUT-')],
- [sg.Slider(orientation='h', key='-SKIDER-'),
- sg.Image(data=sg.DEFAULT_BASE64_LOADING_GIF, enable_events=True, key='-GIF-IMAGE-'),],
- [sg.Checkbox('Checkbox', default=True, k='-CB-')],
- [sg.Radio('Radio1', "RadioDemo", default=True, size=(10,1), k='-R1-'), sg.Radio('Radio2', "RadioDemo", default=True, size=(10,1), k='-R2-')],
- [sg.Combo(values=('Combo 1', 'Combo 2', 'Combo 3'), default_value='Combo 1', readonly=False, k='-COMBO-'),
- sg.OptionMenu(values=('Option 1', 'Option 2', 'Option 3'), k='-OPTION MENU-'),],
- [sg.Spin([i for i in range(1,11)], initial_value=10, k='-SPIN-'), sg.Text('Spin')],
- [sg.Multiline('Demo of a Multi-Line Text Element!\nLine 2\nLine 3\nLine 4\nLine 5\nLine 6\nLine 7\nYou get the point.', size=(45,5), expand_x=True, expand_y=True, k='-MLINE-')],
- [sg.Button('Button'), sg.Button('Popup'), sg.Button(image_data=sg.DEFAULT_BASE64_ICON, key='-LOGO-')]]
-
- asthetic_layout = [[sg.T('Anything that you would use for asthetics is in this tab!')],
- [sg.Image(data=sg.DEFAULT_BASE64_ICON, k='-IMAGE-')],
- [sg.ProgressBar(100, orientation='h', size=(20, 20), key='-PROGRESS BAR-'), sg.Button('Test Progress bar')]]
-
- logging_layout = [[sg.Text("Anything printed will display here!")],
- [sg.Multiline(size=(60,15), font='Courier 8', expand_x=True, expand_y=True, write_only=True,
- reroute_stdout=True, reroute_stderr=True, echo_stdout_stderr=True, autoscroll=True, auto_refresh=True)]
- # [sg.Output(size=(60,15), font='Courier 8', expand_x=True, expand_y=True)]
- ]
-
- graphing_layout = [[sg.Text("Anything you would use to graph will display here!")],
- [sg.Graph((200,200), (0,0),(200,200),background_color="black", key='-GRAPH-', enable_events=True,
- right_click_menu=graph_right_click_menu_def)],
- [sg.T('Click anywhere on graph to draw a circle')],
- [sg.Table(values=data, headings=headings, max_col_width=25,
- background_color='black',
- auto_size_columns=True,
- display_row_numbers=True,
- justification='right',
- num_rows=2,
- alternating_row_color='black',
- key='-TABLE-',
- row_height=25)]]
-
- popup_layout = [[sg.Text("Popup Testing")],
- [sg.Button("Open Folder")],
- [sg.Button("Open File")]]
-
- theme_layout = [[sg.Text("See how elements look under different themes by choosing a different theme here!")],
- [sg.Listbox(values = sg.theme_list(),
- size =(20, 12),
- key ='-THEME LISTBOX-',
- enable_events = True)],
- [sg.Button("Set Theme")]]
-
- layout = [ [sg.MenubarCustom(menu_def, key='-MENU-', font='Courier 15', tearoff=True)],
- [sg.Text('Demo Of (Almost) All Elements', size=(38, 1), justification='center', font=("Helvetica", 16), relief=sg.RELIEF_RIDGE, k='-TEXT HEADING-', enable_events=True)]]
- layout +=[[sg.TabGroup([[ sg.Tab('Input Elements', input_layout),
- sg.Tab('Asthetic Elements', asthetic_layout),
- sg.Tab('Graphing', graphing_layout),
- sg.Tab('Popups', popup_layout),
- sg.Tab('Theming', theme_layout),
- sg.Tab('Output', logging_layout)]], key='-TAB GROUP-', expand_x=True, expand_y=True),
-
- ]]
- layout[-1].append(sg.Sizegrip())
- window = sg.Window('All Elements Demo', layout, right_click_menu=right_click_menu_def, right_click_menu_tearoff=True, grab_anywhere=True, resizable=True, margins=(0,0), use_custom_titlebar=True, finalize=True, keep_on_top=True)
- window.set_min_size(window.size)
- return window
-
-def main():
- window = make_window(sg.theme())
-
- # This is an Event Loop
- while True:
- event, values = window.read(timeout=100)
- # keep an animation running so show things are happening
- if event not in (sg.TIMEOUT_EVENT, sg.WIN_CLOSED):
- print('============ Event = ', event, ' ==============')
- print('-------- Values Dictionary (key=value) --------')
- for key in values:
- print(key, ' = ',values[key])
- if event in (None, 'Exit'):
- print("[LOG] Clicked Exit!")
- break
-
- window['-GIF-IMAGE-'].update_animation(sg.DEFAULT_BASE64_LOADING_GIF, time_between_frames=100)
- if event == 'About':
- print("[LOG] Clicked About!")
- sg.popup('PySimpleGUI Demo All Elements',
- 'Right click anywhere to see right click menu',
- 'Visit each of the tabs to see available elements',
- 'Output of event and values can be see in Output tab',
- 'The event and values dictionary is printed after every event', keep_on_top=True)
- elif event == 'Popup':
- print("[LOG] Clicked Popup Button!")
- sg.popup("You pressed a button!", keep_on_top=True)
- print("[LOG] Dismissing Popup!")
- elif event == 'Test Progress bar':
- print("[LOG] Clicked Test Progress Bar!")
- progress_bar = window['-PROGRESS BAR-']
- for i in range(100):
- print("[LOG] Updating progress bar by 1 step ("+str(i)+")")
- progress_bar.update(current_count=i + 1)
- print("[LOG] Progress bar complete!")
- elif event == "-GRAPH-":
- graph = window['-GRAPH-'] # type: sg.Graph
- graph.draw_circle(values['-GRAPH-'], fill_color='yellow', radius=20)
- print("[LOG] Circle drawn at: " + str(values['-GRAPH-']))
- elif event == "Open Folder":
- print("[LOG] Clicked Open Folder!")
- folder_or_file = sg.popup_get_folder('Choose your folder', keep_on_top=True)
- sg.popup("You chose: " + str(folder_or_file), keep_on_top=True)
- print("[LOG] User chose folder: " + str(folder_or_file))
- elif event == "Open File":
- print("[LOG] Clicked Open File!")
- folder_or_file = sg.popup_get_file('Choose your file', keep_on_top=True)
- sg.popup("You chose: " + str(folder_or_file), keep_on_top=True)
- print("[LOG] User chose file: " + str(folder_or_file))
- elif event == "Set Theme":
- print("[LOG] Clicked Set Theme!")
- theme_chosen = values['-THEME LISTBOX-'][0]
- print("[LOG] User Chose Theme: " + str(theme_chosen))
- window.close()
- window = make_window(theme_chosen)
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Versions':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True)
-
- window.close()
- exit(0)
-
-if __name__ == '__main__':
- sg.theme('black')
- sg.theme('dark red')
- sg.theme('dark green 7')
- # sg.theme('DefaultNoMoreNagging')
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_All_Elements_Simple.py b/DemoPrograms/Demo_All_Elements_Simple.py
deleted file mode 100644
index e15a28bc4..000000000
--- a/DemoPrograms/Demo_All_Elements_Simple.py
+++ /dev/null
@@ -1,109 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Element List
-
- All elements shown in 1 window as simply as possible.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-use_custom_titlebar = True if sg.running_trinket() else False
-
-def make_window(theme=None):
-
- NAME_SIZE = 23
-
-
- def name(name):
- dots = NAME_SIZE-len(name)-2
- return sg.Text(name + ' ' + '•'*dots, size=(NAME_SIZE,1), justification='r',pad=(0,0), font='Courier 10')
-
- sg.theme(theme)
-
- # NOTE that we're using our own LOCAL Menu element
- if use_custom_titlebar:
- Menu = sg.MenubarCustom
- else:
- Menu = sg.Menu
-
- treedata = sg.TreeData()
-
- treedata.Insert("", '_A_', 'Tree Item 1', [1234], )
- treedata.Insert("", '_B_', 'B', [])
- treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], )
-
- layout_l = [
- [name('Text'), sg.Text('Text')],
- [name('Input'), sg.Input(s=15)],
- [name('Multiline'), sg.Multiline(s=(15,2))],
- [name('Output'), sg.Output(s=(15,2))],
- [name('Combo'), sg.Combo(sg.theme_list(), default_value=sg.theme(), s=(15,22), enable_events=True, readonly=True, k='-COMBO-')],
- [name('OptionMenu'), sg.OptionMenu(['OptionMenu',],s=(15,2))],
- [name('Checkbox'), sg.Checkbox('Checkbox')],
- [name('Radio'), sg.Radio('Radio', 1)],
- [name('Spin'), sg.Spin(['Spin',], s=(15,2))],
- [name('Button'), sg.Button('Button')],
- [name('ButtonMenu'), sg.ButtonMenu('ButtonMenu', sg.MENU_RIGHT_CLICK_EDITME_EXIT)],
- [name('Slider'), sg.Slider((0,10), orientation='h', s=(10,15))],
- [name('Listbox'), sg.Listbox(['Listbox', 'Listbox 2'], no_scrollbar=True, s=(15,2))],
- [name('Image'), sg.Image(sg.EMOJI_BASE64_HAPPY_THUMBS_UP)],
- [name('Graph'), sg.Graph((125, 50), (0,0), (125,50), k='-GRAPH-')] ]
-
- layout_r = [[name('Canvas'), sg.Canvas(background_color=sg.theme_button_color()[1], size=(125,40))],
- [name('ProgressBar'), sg.ProgressBar(100, orientation='h', s=(10,20), k='-PBAR-')],
- [name('Table'), sg.Table([[1,2,3], [4,5,6]], ['Col 1','Col 2','Col 3'], num_rows=2)],
- [name('Tree'), sg.Tree(treedata, ['Heading',], num_rows=3)],
- [name('Horizontal Separator'), sg.HSep()],
- [name('Vertical Separator'), sg.VSep()],
- [name('Frame'), sg.Frame('Frame', [[sg.T(s=15)]])],
- [name('Column'), sg.Column([[sg.T(s=15)]])],
- [name('Tab, TabGroup'), sg.TabGroup([[sg.Tab('Tab1',[[sg.T(s=(15,2))]]), sg.Tab('Tab2', [[]])]])],
- [name('Pane'), sg.Pane([sg.Col([[sg.T('Pane 1')]]), sg.Col([[sg.T('Pane 2')]])])],
- [name('Push'), sg.Push(), sg.T('Pushed over')],
- [name('VPush'), sg.VPush()],
- [name('Sizer'), sg.Sizer(1,1)],
- [name('StatusBar'), sg.StatusBar('StatusBar')],
- [name('Sizegrip'), sg.Sizegrip()] ]
-
- # Note - LOCAL Menu element is used (see about for how that's defined)
- layout = [[Menu([['File', ['Exit']], ['Edit', ['Edit Me', ]]], k='-CUST MENUBAR-',p=0)],
- [sg.T('PySimpleGUI Elements - Use Combo to Change Themes', font='_ 14', justification='c', expand_x=True)],
- [sg.Checkbox('Use Custom Titlebar & Menubar', use_custom_titlebar, enable_events=True, k='-USE CUSTOM TITLEBAR-', p=0)],
- [sg.Col(layout_l, p=0), sg.Col(layout_r, p=0)]]
-
- window = sg.Window('The PySimpleGUI Element List', layout, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, keep_on_top=True, use_custom_titlebar=use_custom_titlebar)
-
- window['-PBAR-'].update(30) # Show 30% complete on ProgressBar
- window['-GRAPH-'].draw_image(data=sg.EMOJI_BASE64_HAPPY_JOY, location=(0,50)) # Draw something in the Graph Element
-
- return window
-
-
-window = make_window()
-
-while True:
- event, values = window.read()
- # sg.Print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if values['-COMBO-'] != sg.theme():
- sg.theme(values['-COMBO-'])
- window.close()
- window = make_window()
- if event == '-USE CUSTOM TITLEBAR-':
- use_custom_titlebar = values['-USE CUSTOM TITLEBAR-']
- sg.set_options(use_custom_titlebar=use_custom_titlebar)
- window.close()
- window = make_window()
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True)
-window.close()
-
-
diff --git a/DemoPrograms/Demo_All_Widgets.py b/DemoPrograms/Demo_All_Widgets.py
new file mode 100644
index 000000000..6ffdf5907
--- /dev/null
+++ b/DemoPrograms/Demo_All_Widgets.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python
+'''
+Example of (almost) all widgets, that you can use in PySimpleGUI.
+'''
+
+import PySimpleGUI as sg
+
+sg.change_look_and_feel('GreenTan')
+
+# ------ Menu Definition ------ #
+menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
+ ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
+ ['&Help', '&About...'], ]
+
+# ------ Column Definition ------ #
+column1 = [[sg.Text('Column 1', background_color='lightblue', justification='center', size=(10, 1))],
+ [sg.Spin(values=('Spin Box 1', '2', '3'),
+ initial_value='Spin Box 1')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'),
+ initial_value='Spin Box 2')],
+ [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]
+
+layout = [
+ [sg.Menu(menu_def, tearoff=True)],
+ [sg.Text('(Almost) All widgets in one Window!', size=(
+ 30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
+ [sg.Text('Here is some text.... and a place to enter text')],
+ [sg.InputText('This is my text')],
+ [sg.Frame(layout=[
+ [sg.CBox('Checkbox', size=(10, 1)),
+ sg.CBox('My second checkbox!', default=True)],
+ [sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10, 1)),
+ sg.Radio('My second Radio!', "RADIO1")]], title='Options',
+ title_color='red',
+ relief=sg.RELIEF_SUNKEN,
+ tooltip='Use these to set flags')],
+ [sg.MLine(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
+ sg.MLine(default_text='A second multi-line', size=(35, 3))],
+ [sg.Combo(('Combobox 1', 'Combobox 2'), size=(20, 1)),
+ sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
+ [sg.OptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
+ [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
+ sg.Frame('Labelled Group', [[
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=25),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),
+ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),
+ sg.Col(column1, background_color='lightblue')]])
+ ],
+ [sg.Text('_' * 80)],
+ [sg.Text('Choose A Folder', size=(35, 1))],
+ [sg.Text('Your Folder', size=(15, 1), justification='right'),
+ sg.InputText('Default Folder'), sg.FolderBrowse()],
+ [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]]
+
+window = sg.Window('Everything bagel', layout,
+ default_element_size=(40, 1), grab_anywhere=False)
+
+event, values = window.read()
+sg.popup('Title',
+ 'The results of the window.',
+ 'The button clicked was "{}"'.format(event),
+ 'The values are', values)
diff --git a/DemoPrograms/Demo_Animated_GIFs.py b/DemoPrograms/Demo_Animated_GIFs.py
index 6857245e7..6e082df42 100644
--- a/DemoPrograms/Demo_Animated_GIFs.py
+++ b/DemoPrograms/Demo_Animated_GIFs.py
@@ -11,10 +11,6 @@
The first image that uses popup_animated will stop after a few seconds on its own.
The remaining images are shown 1 at a time. To move on to the next image, click the current image.
If you want to exit before reaching the final image, right click the image and choose 'exit'
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# ---------------------------- Base 64 GIFs ----------------------------
@@ -33,20 +29,18 @@
gifs = [ring_blue, red_dots_ring, ring_black_dots, ring_gray_segments, ring_lines, blue_dots, red_dots_ring, bar_striped, line_boxes, line_bubbles]
# first show how to use popup_animated using built-in GIF image
-for i in range(1000):
- if not sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, message='Right Click To Exit GIF Windows That Follow\nLeft click to move to next one', no_titlebar=False, time_between_frames=100, text_color='black', background_color='white'):
- break
+for i in range(100000):
+ sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', time_between_frames=100)
sg.popup_animated(None) # close all Animated Popups
# Next demo is to show how to create custom windows with animations
-layout = [[sg.Image(data=gifs[0], enable_events=True, background_color='white', key='-IMAGE-', right_click_menu=['UNUSED', ['Exit']], pad=0)],]
+layout = [[sg.Image(data=gifs[0], enable_events=True, background_color='white', key='-IMAGE-', right_click_menu=['UNUSED', 'Exit'])],]
window = sg.Window('My new window', layout,
no_titlebar=True,
grab_anywhere=True,
keep_on_top=True,
background_color='white',
- # transparent_color='white' if sg.running_windows() else None,
alpha_channel=.8,
margins=(0,0))
@@ -55,13 +49,11 @@
gif = gifs[0]
while True: # Event Loop
event, values = window.read(timeout=10) # loop every 10 ms to show that the 100 ms value below is used for animation
- if event in (sg.WIN_CLOSED, 'Exit', 'Cancel'):
+ if event in (None, 'Exit', 'Cancel'):
break
elif event == '-IMAGE-': # if clicked on the image
- if offset == len(gifs)-1:
- break
offset += (offset < len(gifs)-1) # add 1 until the last one
gif = gifs[offset] # get a new gif image
# update the animation in the window
- window['-IMAGE-'].update_animation(gif, time_between_frames=100)
\ No newline at end of file
+ window['-IMAGE-'].update_animation(gif, time_between_frames=100)
diff --git a/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py b/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py
deleted file mode 100644
index 1db4b042e..000000000
--- a/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from PIL import Image, ImageTk, ImageSequence
-import PySimpleGUI as sg
-
-"""
- Demo_Animated_GIFs_Using_PIL.py
-
- You'll find other animated GIF playback demos for PySimpleGUI that use the tkinter built-in GIF parser.
- That is how the built-in PySimpleGUI Image.update_animation is used.
-
- If you want to do the GIF file parsing yourself using PIL and update your Image element yourself, then
- this is one possible technique.
-
- This particular demo will loop playing the GIF file over and over. To not loop, remove the while True statement.
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-gif_filename = r'ExampleGIF.gif'
-
-layout = [[sg.Text('Happy Thursday!', background_color='#A37A3B', text_color='#FFF000', justification='c', key='-T-', font=("Bodoni MT", 40))],
- [sg.Image(key='-IMAGE-')]]
-
-window = sg.Window('Window Title', layout, element_justification='c', margins=(0,0), element_padding=(0,0), finalize=True)
-
-window['-T-'].expand(True, True, True) # Make the Text element expand to take up all available space
-
-interframe_duration = Image.open(gif_filename).info['duration'] # get how long to delay between frames
-
-while True:
- for frame in ImageSequence.Iterator(Image.open(gif_filename)):
- event, values = window.read(timeout=interframe_duration)
- if event == sg.WIN_CLOSED:
- exit(0)
- window['-IMAGE-'].update(data=ImageTk.PhotoImage(frame) )
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Auto_Save_Window_Position.py b/DemoPrograms/Demo_Auto_Save_Window_Position.py
deleted file mode 100644
index 6cb1d865e..000000000
--- a/DemoPrograms/Demo_Auto_Save_Window_Position.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Simple template window that saves position.
-
- Rather than starting in the middle of the screen, this code will save the position the window was in when it last exited.
-
- To pull this off it's going to be.... super.....?hard?
- No... of course it's going to be... SIMPLE
-
- There is one added line of code. When the user attempts to close the window, that's when the position is saved.
- When the program starts, it reads the previously saved position as part of the window creation. User Settings APIs rock!
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [[sg.Text('Window that Auto-saves position', font='_ 25')],
- [sg.Button('Ok'), sg.Button('Exit')]]
-
-window = sg.Window('Auto-saves Location', layout, enable_close_attempted_event=True, location=sg.user_settings_get_entry('-location-', (None, None)))
-
-while True:
- event, values = window.read()
- print(event, values)
- if event in ('Exit', sg.WINDOW_CLOSE_ATTEMPTED_EVENT):
- sg.user_settings_set_entry('-location-', window.current_location()) # The line of code to save the position before exiting
- break
-
-window.close()
diff --git a/DemoPrograms/Demo_Bar_Chart.py b/DemoPrograms/Demo_Bar_Chart.py
index 620fc004f..5dbf58c8d 100644
--- a/DemoPrograms/Demo_Bar_Chart.py
+++ b/DemoPrograms/Demo_Bar_Chart.py
@@ -1,57 +1,51 @@
import PySimpleGUI as sg
import random
-"""
- Demo - Using a Graph Element to make Bar Charts
-
- The Graph Element is very versatile. Because you can define your own
- coordinate system, it makes producing graphs of many lines (bar, line, etc) very
- straightforward.
-
- In this Demo a "bar" is nothing more than a rectangle drawn in a Graph Element (draw_rectangle).
-
- To make things a little more interesting, this is a barchart with that data values
- placed as labels atop each bar, another Graph element method (draw_text)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-BAR_WIDTH = 50 # width of each bar
-BAR_SPACING = 75 # space between each bar
-EDGE_OFFSET = 3 # offset from the left edge for first bar
-GRAPH_SIZE= DATA_SIZE = (500,500) # size in pixels
-
-sg.theme('Light brown 1')
+# Bars drawing in PySimpleGUI
+#
+# .--.
+# | |
+# .--.| |.--.
+# | || || |
+# | || || |
+# | || || |
+# .--.| || || |
+# .--.| || || || |.--.
+# | || || || || || |
+# | || || || || || |
+# .--.| || || || || || |.--.
+# | || || || || || || || |.--.
+# | || || || || || || || || |
+# '--''--''--''--''--''--''--''--''--'
+
+
+BAR_WIDTH = 50
+BAR_SPACING = 75
+EDGE_OFFSET = 3
+GRAPH_SIZE = (500,500)
+DATA_SIZE = (500,500)
+
+graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
layout = [[sg.Text('Labelled Bar graphs using PySimpleGUI')],
- [sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE, k='-GRAPH-')],
+ [graph],
[sg.Button('OK'), sg.T('Click to display more data'), sg.Exit()]]
-window = sg.Window('Bar Graph', layout, finalize=True)
-
-graph = window['-GRAPH-'] # type: sg.Graph
+window = sg.Window('Window Title', layout)
while True:
+ event, values = window.read()
+ if event in (None, 'Exit'):
+ break
graph.erase()
for i in range(7):
- graph_value = random.randint(0, GRAPH_SIZE[1]-25) # choose an int just short of the max value to give room for the label
+ graph_value = random.randint(0, 400)
graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
- bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0),
- fill_color='green')
- # fill_color=sg.theme_button_color()[1])
-
- graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10), font='_ 14')
-
- # Normally at the top of the loop, but because we're drawing the graph first, making it at the bottom
- event, values = window.read()
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
+ bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue')
+ graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
+window.close()
+# del window
-window.close()
\ No newline at end of file
+while True:
+ pass
diff --git a/DemoPrograms/Demo_Base64_Image_Encoder.py b/DemoPrograms/Demo_Base64_Image_Encoder.py
index e5dfc2f39..6ad4dc68c 100644
--- a/DemoPrograms/Demo_Base64_Image_Encoder.py
+++ b/DemoPrograms/Demo_Base64_Image_Encoder.py
@@ -7,10 +7,6 @@
Make base64 images
input: folder with .png .ico .gif 's
output: output.py file with variables
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
def main():
diff --git a/DemoPrograms/Demo_Base64_Single_Image_Encoder.py b/DemoPrograms/Demo_Base64_Single_Image_Encoder.py
deleted file mode 100644
index b55a82370..000000000
--- a/DemoPrograms/Demo_Base64_Single_Image_Encoder.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import PySimpleGUI as sg
-import base64
-
-"""
- Make base64 image from a file
- This is usually done in order to create a Base64 image for use as an Ucon or a Button image
- To use, either copy and paste the full path to the file or use the browse button to locate the file.
- Once chosen, the conversion will happen automatically with the result placed on the clipboard.
- When complete, a popup window is shown that tells you to paste the image before closing the window. This is because of a
- tkinter problem on Linux. On Windows you can close the Window, but on Linux, you'll need to keep it open until the paste completes
-
- NOTE - if you're replacing your ICO file for your window with a base64 image, you will first need to convert your icon from
- an ICO file into a PNG file. Encode the PNG file and then you'll be able to pass that value in your call to Window:
-
- window = sg.Window('Window Title', layout, icon=icon)
-
- Where icon is a variable you created using the contents of the clipboard folowing running this program.
-
- Input: a single image file
- Output: clipboard will contain the Base64 Byte String of the source image
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def convert_file_to_base64(filename):
- try:
- contents = open(filename, 'rb').read()
- encoded = base64.b64encode(contents)
- sg.clipboard_set(encoded)
- # pyperclip.copy(str(encoded))
- sg.popup('Copied to your clipboard!', 'Keep window open until you have pasted the base64 bytestring')
- except Exception as error:
- sg.popup_error('Cancelled - An error occurred', error)
-
-
-if __name__ == '__main__':
- filename = sg.popup_get_file('Source Image will be encoded and results placed on clipboard', title='Base64 Encoder')
-
- if filename:
- convert_file_to_base64(filename)
- else:
- sg.popup_cancel('Cancelled - No valid file entered')
diff --git a/DemoPrograms/Demo_Borderless_Window.py b/DemoPrograms/Demo_Borderless_Window.py
index 53ed4422a..c330d22b0 100644
--- a/DemoPrograms/Demo_Borderless_Window.py
+++ b/DemoPrograms/Demo_Borderless_Window.py
@@ -1,15 +1,9 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Turn off padding in order to get a really tight looking layout.
-sg.theme('Dark')
+sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [[sg.Text('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)),
@@ -36,5 +30,5 @@
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
diff --git a/DemoPrograms/Demo_Button_Can_Button_Images.py b/DemoPrograms/Demo_Button_Can_Button_Images.py
deleted file mode 100644
index 1ced4efe2..000000000
--- a/DemoPrograms/Demo_Button_Can_Button_Images.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Can Buttons
-
- How to use an Image element to make Can Buttons.
-
- The metadata for the Image Element holds the current button state. In this case the state is an offset into a list of button images.
-
- The technique is much like the toggle buttons except you can have more than 2 states.
-
- A Custom Titlebar was used to make the overall appearance cleaner while still providing the ability to easily exit.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- boost_images = (can_boost_off, can_boost_blue, can_boost_green)
- seat_images = (can_seat_off, can_seat_red)
- sg.theme('black')
- sg.theme_background_color('#222222')
- sg.theme_text_color('#888888')
- sg.set_options(titlebar_background_color=sg.theme_background_color(), titlebar_text_color=sg.theme_text_color(), use_custom_titlebar=True, titlebar_icon=sg.BLANK_BASE64)
-
- layout = [[sg.Im(boost_images[0], k='-BOOST-', enable_events=True, metadata=0), sg.Im(seat_images[0], enable_events=True, k='-SEAT-', metadata=0)]]
-
- window = sg.Window('', layout)
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-SEAT-':
- window[event].metadata = (window[event].metadata + 1) % len(seat_images)
- window[event].update(seat_images[window[event].metadata])
- if event == '-BOOST-':
- window[event].metadata = (window[event].metadata + 1) % len(boost_images)
- window[event].update(boost_images[window[event].metadata])
- window.close()
-
-
-if __name__ == '__main__':
-
- can_boost_off = b'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'
- can_boost_blue = b'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'
- can_boost_green = b'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'
- can_seat_off = b'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'
- can_seat_red = b'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'
- main()
diff --git a/DemoPrograms/Demo_Button_Click.py b/DemoPrograms/Demo_Button_Click.py
index f90d2bfc2..56c68d2a8 100644
--- a/DemoPrograms/Demo_Button_Click.py
+++ b/DemoPrograms/Demo_Button_Click.py
@@ -1,33 +1,37 @@
#!/usr/bin/env python
+import winsound
import sys
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
if not sys.platform.startswith('win'):
sg.popup_error('Sorry, you gotta be on Windows')
- sys.exit()
-import winsound
+ sys.exit(0)
+
+
+# sg.change_look_and_feel('Dark')
+# sg.set_options(element_padding=(0,0))
layout = [
- [sg.Button('Start', button_color=('white', 'black'), key='start'),
- sg.Button('Stop', button_color=('white', 'black'), key='stop'),
- sg.Button('Reset', button_color=('white', 'firebrick3'), key='reset'),
- sg.Button('Submit', button_color=('white', 'springgreen4'), key='submit')]
- ]
+ [sg.Button('Start', button_color=('white', 'black'), key='start'),
+ sg.Button('Stop', button_color=('white', 'black'), key='stop'),
+ sg.Button('Reset', button_color=('white', 'firebrick3'), key='reset'),
+ sg.Button('Submit', button_color=('white', 'springgreen4'), key='submit')]
+]
-window = sg.Window("Button Click", layout, auto_size_buttons=False, default_button_element_size=(12,1), use_default_focus=False, finalize=True)
+window = sg.Window("Button Click", layout, finalize=True,
+ default_element_size=(12, 1), text_justification='r',
+ auto_size_text=False, auto_size_buttons=False,
+ default_button_element_size=(12, 1), use_default_focus=False )
window['submit'].update(disabled=True)
recording = have_data = False
while True:
event, values = window.read(timeout=100)
- if event == sg.WINDOW_CLOSED:
+ if event is None:
break
- winsound.PlaySound("ButtonClick.wav", 1) if event != sg.TIMEOUT_KEY else None
+ if event != sg.TIMEOUT_KEY:
+ winsound.PlaySound("ButtonClick.wav", 1)
+
window.close()
diff --git a/DemoPrograms/Demo_Button_Events_From_Browse.py b/DemoPrograms/Demo_Button_Events_From_Browse.py
deleted file mode 100644
index dd8f8325a..000000000
--- a/DemoPrograms/Demo_Button_Events_From_Browse.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Fill a listbox with list of files FilesBrowse button
-
- This technique can be used to generate events from "Chooser Buttons" like FileBrowse, FilesBrowse
- FolderBrowser, ColorChooserButton, Calendar Button
-
- Any button that uses a "Target" can be used with an invisible Input Element to generate an
- event when the user has made a choice. Enable events for the invisible element and an event will
- be generated when the Chooser Button fills in the element
-
- This particular demo users a list of chosen files to populate a listbox
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-layout = [ [sg.LBox([], size=(20,10), key='-FILESLB-')],
- [sg.Input(visible=False, enable_events=True, key='-IN-'), sg.FilesBrowse()],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-window = sg.Window('Window Title', layout)
-
-while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- # When choice has been made, then fill in the listbox with the choices
- if event == '-IN-':
- window['-FILESLB-'].Update(values['-IN-'].split(';'))
-window.close()
diff --git a/DemoPrograms/Demo_Button_Func_Calls.py b/DemoPrograms/Demo_Button_Func_Calls.py
index 454412c4d..af25aa9a0 100644
--- a/DemoPrograms/Demo_Button_Func_Calls.py
+++ b/DemoPrograms/Demo_Button_Func_Calls.py
@@ -12,10 +12,6 @@
It is quite easy to simulate these callbacks however. The way to do this is to add the calls
to your Event Loop
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -36,7 +32,7 @@ def callback_function2():
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
elif event == 'Button 1':
callback_function1() # call the "Callback" function
diff --git a/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py b/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py
deleted file mode 100644
index 756febe84..000000000
--- a/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Program - Simulated Buttons with Mouseover Highlights
-
- The purpose of this demo is to teach you 5 unique PySimpleGUI constructs that when combined
- create a "Button" that highlights on mouseover regarless of the Operating System.
- Because of how tktiner works, mouseover highlighting is inconsistent across operating systems for Buttons.
- This is one (dare I say "clever") way to get this effect in your program
-
- 1. Binding the Enter and Leave tkinter events
- 2. Using Tuples as keys
- 3. Using List Comprehensions to build a layout
- 4. Using Text Elements to Simulate Buttons
- 5. Using a "User Defined Element" to make what appears to be a new type of Button in the layout
-
- The KEY to making this work simply is these "Buttons" have a tuple as a key.
- The format of the key is ('-B-', button_text)
-
- An element's bind method will make a tuple if the original key is a tuple.
- (('-B-', button_text), 'ENTER') will be the event when the mouse is moved over the "Button"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# sg.theme('dark red')
-
-def TextButton(text):
- """
- A User Defined Element. It looks like a Button, but is a Text element
- :param text: The text that will be put on the "Button"
- :return: A Text element with a tuple as the key
- """
- return sg.Text(text, key=('-B-', text), relief='raised', enable_events=True, font='_ 15',text_color=sg.theme_button_color_text(), background_color=sg.theme_button_color_background())
-
-def do_binds(window, button_text):
- """
- This is magic code that enables the mouseover highlighting to work.
- """
- for btext in button_text:
- window[('-B-', btext)].bind('', 'ENTER')
- window[('-B-', btext)].bind('', 'EXIT')
-
-def main():
- # Defines the text on the 3 buttons we're making
- button_text = ('Button 1', 'Button 2', 'Button 3')
-
- # The window's layout
- layout = [[TextButton(text) for text in button_text],
- [sg.Text(font='_ 14', k='-STATUS-')],
- [sg.Ok(), sg.Exit()]]
-
- window = sg.Window('Custom Mouseover Highlighting Buttons', layout, finalize=True)
-
- # After the window is finalized, then can perform the bindings
- do_binds(window, button_text)
-
- # The Event Looop
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # if the event is a tuple, it's one of our TextButtons
- if isinstance(event, tuple):
- # if second item is one of the bound strings, then do the mouseeover code
- if event[1] in ('ENTER', 'EXIT'):
- button_key = event[0]
- if event[1] == 'ENTER':
- window[button_key].update(text_color=sg.theme_button_color_background(), background_color=sg.theme_button_color_text())
- if event[1] == 'EXIT':
- window[button_key].update(text_color=sg.theme_button_color_text(), background_color=sg.theme_button_color_background())
- else: # a "normal" button click (Text clicked) so print the text which we put into the tuple
- window['-STATUS-'].update(f'Button pressed = {event[1]}')
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Button_States.py b/DemoPrograms/Demo_Button_States.py
index f0516c2ee..2af9d969a 100644
--- a/DemoPrograms/Demo_Button_States.py
+++ b/DemoPrograms/Demo_Button_States.py
@@ -5,13 +5,9 @@
Demonstrates using a "tight" layout with a Dark theme.
Shows how button states can be controlled by a user application. The program manages the disabled/enabled
states for buttons and changes the text color to show greyed-out (disabled) buttons
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-sg.theme('Dark')
+sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [[sg.Text('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)), sg.Text('0', size=(8, 1))],
@@ -40,7 +36,7 @@
while True:
event, values = window.read()
print(event)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event == '-Start-':
for key, state in {'-Start-': True, '-Stop-': False, '-Reset-': False, '-Submit-': True}.items():
diff --git a/DemoPrograms/Demo_Button_Toggle.py b/DemoPrograms/Demo_Button_Toggle.py
index 33fbaa4b4..1d35482a1 100644
--- a/DemoPrograms/Demo_Button_Toggle.py
+++ b/DemoPrograms/Demo_Button_Toggle.py
@@ -6,36 +6,40 @@
Two versions are present... a simple button that changes text and a graphical one
A HUGE thank you to the PySimpleGUI community memeber that donated his time and skill in creating the buttons!
The text of the button toggles between Off and On
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-def main():
- layout = [[sg.Text('A toggle button example')],
- [sg.Text('A graphical version'),
- sg.Button('', image_data=toggle_btn_off, key='-TOGGLE-GRAPHIC-', button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0)],
- [sg.Button('On', size=(3, 1), button_color='white on green', key='-B-'), sg.Button('Exit')]]
+toggle_btn_off = b'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'
+toggle_btn_on = b'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'
- window = sg.Window('Toggle Button Example', layout)
+layout = [[sg.Text('A toggle button example')],
+ [
+ sg.Text('A graphical version'),
+ sg.Button('', image_data=toggle_btn_off,
+ key='-TOGGLE-GRAPHIC-',
+ button_color=sg.COLOR_SYSTEM_DEFAULT,
+ border_width=0)
+],
+ [sg.Button('On', size=(3, 1),
+ button_color=('white', 'green'),
+ key='-B-'),
+ sg.Button('Exit')]]
- down = graphic_off = True
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == '-B-': # if the normal button that changes color and text
- down = not down
- window['-B-'].update(text='On' if down else 'Off', button_color='white on green' if down else 'white on red')
- elif event == '-TOGGLE-GRAPHIC-': # if the graphical button that changes images
- graphic_off = not graphic_off
- window['-TOGGLE-GRAPHIC-'].update(image_data=toggle_btn_off if graphic_off else toggle_btn_on)
+window = sg.Window('Toggle Button Example', layout)
- window.close()
+down = True
+graphic_off = True
+while True: # Event Loop
+ event, values = window.read()
+ print(event, values)
+ if event in (None, 'Exit'):
+ break
+ elif event == '-B-': # if the normal button that changes color and text
+ down = not down
+ window['-B-'].update(('Off', 'On')[down],
+ button_color=(('white', ('red', 'green')[down])))
+ elif event == '-TOGGLE-GRAPHIC-': # if the graphical button that changes images
+ graphic_off = not graphic_off
+ window['-TOGGLE-GRAPHIC-'].update(image_data=(
+ toggle_btn_on, toggle_btn_off)[graphic_off])
-if __name__ == '__main__':
- toggle_btn_off = b'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'
- toggle_btn_on = b'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'
- main()
\ No newline at end of file
+window.close()
diff --git a/DemoPrograms/Demo_Button_Toggle2.py b/DemoPrograms/Demo_Button_Toggle2.py
deleted file mode 100644
index b750ad2d7..000000000
--- a/DemoPrograms/Demo_Button_Toggle2.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""
- Demo - Button Toggle #2
-
-
- Uses the IGNORE BUTTON setting.
- When creating or updating buttons in 4.35.0+, you can use the parameter:
- disabled=BUTTON_DISABLED_MEANS_IGNORE
-
- This will cause the buytton to ignore your clicks but it won't change the button
- with the GUI, which would change the color and gray it out. The button will not
- change appearance at all. It will no longer respond to button clicks.
-
- Another toggle button using Base64 strings
- Of course files could be used instead of Base64 strings
-
- The differences between this toggle button demo and the other one are:
- 1. Different button graphics
- 2. The button state is stored in the metadata for the button
- 3. The metadata for the button is a class instead of a single variable name
-
- For buttons with graphics, it's generally best to set the button's:
- * border width=0
- * color = (background_color, background_color)
-
- Buttons don't normally have explicit keys. However, since this button has
- no text, there is no default key. It's better to be explicit with buttons that
- change text or have graphics.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-import random
-
-# Class holding the button graphic info. At this time only the state is kept
-class BtnInfo:
- def __init__(self, state=True):
- self.state = state # Can have 3 states - True, False, None (disabled)
-
-# Main function that creates the layout, window and has event loop
-def main():
- layout = [[sg.Text('Toggle Button')],
- [sg.T('Disabled with PySimpleGUI Ignore:', text_color='yellow')],
- [sg.Button(image_data=on_image, k='-TOGGLE1-', border_width=0,
- button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled_button_color=(sg.theme_background_color(), sg.theme_background_color()),
- metadata=BtnInfo()),
- sg.T('Disable:'),
- sg.Button(image_data=off_image, k='-DISABLE1-', border_width=0,
- button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled_button_color=(sg.theme_background_color(), sg.theme_background_color()),
- metadata=BtnInfo(False)), sg.T('Disabled button color is\nbetter than other disabled button below')
- ],
- [sg.Button(image_data=on_image, k='-TOGGLE2-', border_width=0,
- button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled_button_color=(sg.theme_background_color(), sg.theme_background_color()),
- metadata=BtnInfo()),
- sg.Image(data=sg.EMOJI_BASE64_HAPPY_THUMBS_UP,enable_events=True, k='-I-')
- ],
- [ sg.T('Disabled with GUI:', text_color='yellow')],
- [sg.Button(image_data=on_image, k='-TOGGLE3-', border_width=0,
- button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled_button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled=True, metadata=BtnInfo()), sg.T('Note color has crosshatching')],
- [ sg.T('Disabled with PySimpleGUI (ignored):', text_color='yellow')],
- [sg.Button(image_data=on_image, k='-TOGGLE4-', border_width=0,
- button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled_button_color=(sg.theme_background_color(), sg.theme_background_color()),
- disabled=sg.BUTTON_DISABLED_MEANS_IGNORE,
- metadata=BtnInfo())],
- [sg.T(size=(40,1), k='-STATUS-')],
- [sg.Button('Exit')]]
-
- window = sg.Window('Window Title', layout, font='_ 14', finalize=True)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- # Where all the magic happens. 2 things happen when button is clicked
- # 1. The state toggles
- # 2. The buton graphic changes
- if 'TOGGLE' in event:
- window[event].metadata.state = not window[event].metadata.state
- window[event].update(image_data=on_image if window[event].metadata.state else off_image)
- elif event == '-DISABLE1-':
- window[event].metadata.state = not window[event].metadata.state
- window[event].update(image_data=on_image if window[event].metadata.state else off_image)
- window['-I-'].update(data=sg.EMOJI_BASE64_HAPPY_GASP if window[event].metadata.state else random.choice(sg.EMOJI_BASE64_HAPPY_LIST))
- # if disabling the button
- if window[event].metadata.state:
- if window['-TOGGLE1-'].metadata.state is True:
- window['-TOGGLE1-'].update(disabled=sg.BUTTON_DISABLED_MEANS_IGNORE, image_data=on_image_disabled)
- elif window['-TOGGLE1-'].metadata.state is False:
- window['-TOGGLE1-'].update(disabled=sg.BUTTON_DISABLED_MEANS_IGNORE, image_data=off_image_disabled)
- else:
- if window['-TOGGLE1-'].metadata.state is True:
- window['-TOGGLE1-'].update(disabled=False, image_data=on_image)
- elif window['-TOGGLE1-'].metadata.state is False:
- window['-TOGGLE1-'].update(disabled=False, image_data=off_image)
- window['-STATUS-'].update(f'event {event} button state = {window[event].metadata.state if window[event].metadata is not None else "Not applicable"}')
- window.close()
-
-# Define the button graphic base 64 strings and then call the main function
-if __name__ == '__main__':
- on_image = b'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'
-
- off_image = b'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'
-
- off_image_disabled = b'iVBORw0KGgoAAAANSUhEUgAAAFoAAAAnCAYAAACPFF8dAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAWJSURBVGhD7ZtLTyxFFMd7Bhgew2OAIXgDxkQWLgYWJsaNiTFxozcuiQs/gR9Bv4crXRuJG2OIiQvj1q25CZC4IQ4wL2B4zPCGwfqVcyaHTs371Xcu/+Sf6q6qnjr1r1PVVYcmtLGx4SmEotHoB7Ozs59GIpG3y3lBxIvj4+N/h4eHH2ZmZsbLeUFAqVgsvjo9Pf3t9vY2Vc6zqAg9Pj7+3srKyvexWOzjkZERz3TC5gcR9/f33t3dnXdycuIdHh56xjG8UChULu0fsGFiYsIbHR29TaVS3yWTyW9LpdKtLUNoI/Lq2tran9PT0wuGgRZZYDzGM57jGQ/ytra2rPj9wuPjY/nqf6ChcVrv8vLyj+3t7Zem/G5ofX09lEgkfp+bm1sx9MLhsH0QmtGoXAeBAjxnaGgIB7ECMwPNUmJtp6xXFPjzbm5uvHw+7y0vL79r7D4rFAp/hc1S8bkZgffNWmcrCURk0iBQbNGCIyx24yDmnWLzdKe7QQ1Xvlwz4/b29hD7G3MbRuhPMBIPEVCZ5QPiLUGg2IO4GmY9tLabfth73flukPaFkqfblWuAVxvb45OTkx+Gx8bG3nkd1uRaQGgGA0iH+0FpX9KHhwe7tBl942ZgwtO25DWH7mC/WAtP5+EAQE/tbrGayP5UY6CE1h3vBRHd1a5AXw+cR/s73Q2KV0t7jWDghO4VtPBadH2t8bx0tEAXquULnj26DdQTV2OghUYIjumcHBcWFmzwiXsN9uCcLl2UutFo9Ek+hyO5blTsgRUaARYXFy0J8ohYkicCITQD4KI50dk6PO8vY/DgGy/0/Py8Z069NpyazWZt3IGUk5p4uQb5mUzmCYkOahCWJT+dTleoYy+1MJBCs/0Sb8zlct7V1ZU9DpNyDyjX3ohg19fXT8ggaRAoIp/onNR5o4Um0AQQyiUW3ovIUg/4lxAJUmkwOFJGKhHDRjCQQounElZ1QbxQezSzQF5wQj9knUdoqAeqHvoqNB1uly6IwHipC3J01gOBl6dSqQpZf/3gjwtSfnBw4F1cXJRL6qMloV0dbpYSxG+XLrCGUkb417+d454BoH2WEQH1udf0g8HQ5dVmjAtPhNYdqMZuCqThesZFF8g/Pz+31+yfme4ITMo9oLza891A00LXg+uZZtnMYFYDW7NCoWCXCV5c7J1JuUfks7Ozcs3eoGmhe8FOgN9hTWUtJWUPTLq/v2//xCTtsBzwyQJ51SCfNchy0oqNFaGlk+2yHbh+rx7rge0dno0HkyKsBrOHlxp77Gpgv0wd9uIajbQvaOll6IJfgF5Rw1XeDfpRLV+jI0tHr16QQYLLbn2v80FHhG4Xrt9slH646nSa4ljSXiNoe+nQBvSDGq7ybhLBXe0K9HVFaI6j/gdqkUb6vWToI7RA7Oomq/XBn2ogdCXqwh5TP1yLnYDrd5uhPmJzL2k/yAC4IM4QNhVGJMIlXyzphztJtkearjqNkg5gL3ayZePYrW3vNQVyTYp9OINhPFwsFvfYiGMsxsu3bHRG/1Ar9IvjqtMK6QBBfcAel9+Wk56rfqdYrT+6XbkG8Xjc1jN78GRoc3Pzq0Qi8SOxVv4qIa4ulYMIsZFZcXR0ZKNpu7u7lahcr+DSSPKIrayurnLcv9zZ2XkrbE5Ev+ZyuT1ORhgtx0w6E1QCsZeYRjKZtPl0spfUkDwGm8CVcV6rZTab/cl4dUG++H+5tLS0GYvF+LrULh299o5mIGs88QeO1UxRGYB+AhskDItd+Xz+n3Q6/ZGx9ajyPyzRaPRLMxI/RCKRaf5EE1Sh8Rpe3qzNdEo+1w0CsA0HwJPNjPs7k8l8Ye4PKKsIDYy481NTU18b0T8zo/LCPz2eURvGo0tm9/PKvPx+MfzZZJW3zp73H5XujC+u8bu1AAAAAElFTkSuQmCC'
- on_image_disabled = b'iVBORw0KGgoAAAANSUhEUgAAAFoAAAAnCAYAAACPFF8dAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAAVLSURBVGhD7Zu7TytHFMbHyxvsJeb9kjCiCihRpJAobaqblFGUJmXqKMofkyZpaKhS5HaJIgUpRZQmoqAhSgEUSBZgsAE/uJhX5ht80LmH8e56fdde7PuTPu0yj/XMt7Nnd2aXxPr6uuKMjIx84LruR47jJGtJbeeVplQqOaOjo+8MDAwk7u7uyrWsWIF2FYvFf3Rbt/HnQ+oDj0Ynk8kPl5eXf9Amf6L7pW5vb9X9/b3Jaye5XE719fWpubk51dPTY/bjijba+KbN3t7d3f324uLir1rWg9HpdPrFysrKy0KhMJTNZtX19XUtu/0sLi6qyclJlUqlcLWpRCJRy4knNzc3ShusKpXKq52dnS/z+fyvSE9sbGxMrq2t/Xd8fJw+PDw0hf1oRWdxNY2Pj6tMJqMmJiZUf3//Y3ocrjQJPOG+nJ2dYWSXt7a23tMRYt+Zn5//rlqteppMB5EHi5rZ2VmEtEeTAUzGJRo3yZOv7ydo94j293v8ndjW6JDxvh7RpoBEGtsKo9FofdNTq6urampqSvX29tZynhcIIUdHR//qUb3iDA4OZnDzs0Gm0khulQCMBs/VZIC2Dw8Pv6v71OvoO7lri3nUYb5tlToRp7Z9Deos37ZanYbVaA7vON/qCU1k6kQC94oMhxFk+FuCU9doPnptkPFRqBN5YjTvKO1LE3iZtwSjMwNiDGnYaD6aEa/1czieFdXQ0JB1wQfPw5C8Cii9Wwg9omHw2NiYmSLDaCz4YNoJ8ScHpGNBCGU4SIe6hVBGY+0BBmOiUy6XzQIKpptY9cOohrESjHg+y+u2ON+w0TAXpgGYfHl5aZYGq9WqMRsLLDDbNnXGyelWQsVoisUwl4OTQGvZPF5TOsxHyOlGQsdogNEroTQZGkqlktkiLnfq7M+LpnpsM4zS5EIVXvFUKhVzAmC2zH+OoA/1JGnYaByEwoN8PONhBXFbgngOw1GvnaNamhJWjdBwb2EmDAP0/EwvTV3XNQbiRNDJ4KBxuIGGQXayGXlhKx9WnFDDCjdBGEZhIJ1Om+dnmI2RXCwWayWfgrpXV1e1v4IhG10P2dEwCoKtnpQkVOgAGNX5fN7c5LCP+IvHOzxT85sk0uUoxt+oh7ygyI7Y5IetTlSSNBUoYSheg8E4mCYf9wDy5asyqlfvFZrE1pFGhd+0pYdRPbzKPTGaF6B9WVEeJGro95uRH7Y6jcqLuiOaKvIDyP2oFBRb3bDywlbeT5LAocPvQFEif5sUBFu9RuVHkDq+RvOK/ECIeW8y7nHZsJULIj9sdRpVEKxGU2W+lftRywtb+bDywlY+qCTGaLkuAagw39pGcBSjWoJJkFe+hJdtRn7Y6kBAznwdZPCVNg5V4gegfS4KI29KgB4VMWVHo7nZtjpcvG1hZTuulK0eID/RdpQDjn7+PcfMrh5UGciDRiVA69w03UfjMdVHw9EB5EUp/IaXbHXQdrwUQTsB2q5nwZc6/T6xubn5WyaT+Wxvb08VCgVTwAtbmIkCNHpmZkYtLCyY76P5iwQ6GXGE/MHMFzPlg4ODP/f39z91Tk9Pfzw/P1dLS0tqenra10h0shUC+JQYbTs5OXltfQRtjKvQdhhMyuVyP5k244t/PXJ+0aPmCywM4dLEohAuD1S0QUa0ApiMD9LxMTrCB1SvXe0GnuHegi1M1m3/I5vNvtBZd8Zo3fCkNvvnZDL5OV41Ic7EqTM48RjReOdo+3QhLmAAwmis4ejQ8bu+Ir/SaWYpk/9XViKVSn3tuu43ujMf67t8975JDYk29UrfAP/WA2NdawNJDzlK/Q9RjPZ1HEiBtwAAAABJRU5ErkJggg=='
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py b/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py
deleted file mode 100644
index 735eed2e3..000000000
--- a/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Toggle Button Demo - Simple Version
-
- A simple graphic that toggles.
- The "State" of on/off is stored in the button's Metadata
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- layout = [[sg.Text('A toggle button example')],
- [sg.Text('Off'),
- sg.Button(image_data=toggle_btn_off, key='-TOGGLE-GRAPHIC-', button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0, metadata=False),
- sg.Text('On')]]
-
- window = sg.Window('Toggle Button Simple Graphic', layout)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == '-TOGGLE-GRAPHIC-': # if the graphical button that changes images
- window['-TOGGLE-GRAPHIC-'].metadata = not window['-TOGGLE-GRAPHIC-'].metadata
- window['-TOGGLE-GRAPHIC-'].update(image_data=toggle_btn_on if window['-TOGGLE-GRAPHIC-'].metadata else toggle_btn_off)
-
- window.close()
-
-
-if __name__ == '__main__':
- # The base64 strings for the button images
- toggle_btn_off = b'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAED0lEQVRYCe1WTWwbRRR+M/vnv9hO7BjHpElMKSlpqBp6gRNHxAFVcKM3qgohQSqoqhQ45YAILUUVDRxAor2VAweohMSBG5ciodJUSVqa/iikaePEP4nj2Ovdnd1l3qqJksZGXscVPaylt7Oe/d6bb9/svO8BeD8vA14GvAx4GXiiM0DqsXv3xBcJU5IO+RXpLQvs5yzTijBmhurh3cyLorBGBVokQG9qVe0HgwiXLowdy9aKsY3g8PA5xYiQEUrsk93JTtjd1x3siIZBkSWQudUK4nZO1w3QuOWXV+HuP/fL85klAJuMCUX7zPj4MW1zvC0Ej4yMp/w++K2rM9b70sHBYCjo34x9bPelsgp/XJksZ7KFuwZjr3732YcL64ttEDw6cq5bVuCvgy/sje7rT0sI8PtkSHSEIRIKgCQKOAUGM6G4VoGlwiqoVd2Za9Vl8u87bGJqpqBqZOj86eEHGNch+M7otwHJNq4NDexJD+59RiCEQG8qzslFgN8ibpvZNsBifgXmFvJg459tiOYmOElzYvr2bbmkD509e1ylGEZk1Y+Ssfan18n1p7vgqVh9cuiDxJPxKPT3dfGXcN4Tp3dsg/27hUQs0qMGpRMYjLz38dcxS7Dm3nztlUAb38p0d4JnLozPGrbFfBFm79c8hA3H2AxcXSvDz7/+XtZE1kMN23hjV7LTRnKBh9/cZnAj94mOCOD32gi2EUw4FIRUMm6LGhyiik86nO5NBdGRpxYH14bbjYfJteN/OKR7UiFZVg5T27QHYu0RBxoONV9W8KQ7QVp0iXdE8fANUGZa0QAvfhhXlkQcmjJZbt631oIBnwKmacYoEJvwiuFgWncWnXAtuVBBEAoVVXWCaQZzxmYuut68b631KmoVBEHMUUrJjQLXRAQVSxUcmrKVHfjWWjC3XOT1FW5QrWpc5IJdQhDKVzOigEqS5dKHMVplnNOqrmsXqUSkn+YzWaHE9RW1FeXL7SKZXBFUrXW6jIV6YTEvMAUu0W/G3kcxPXP5ylQZs4fa6marcWvvZfJu36kuHjlc/nMSuXz+/ejxgqPFpuQ/xVude9eu39Jxu27OLvBGoMjrUN04zrNMbgVmOBZ96iPdPZmYntH5Ls76KuxL9NyoLA/brav7n382emDfHqeooXyhQmARVhSnAwNNMx5bu3V1+habun5nWdXhwJZ2C5mirTesyUR738sv7g88UQ0rEkTDlp+1wwe8Pf0klegUenYlgyg7bby75jUTITs2rhCAXXQ2vwxz84vlB0tZ0wL4NEcLX/04OrrltG1s8aOrHhk51SaK0us+n/K2xexBxljcsm1n6x/Fuv1PCWGiKOaoQCY1Vb9gWPov50+fdEqd21ge3suAlwEvA14G/ucM/AuppqNllLGPKwAAAABJRU5ErkJggg=='
- toggle_btn_on = b'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAD+UlEQVRYCe1XzW8bVRCffbvrtbP+2NhOD7GzLm1VoZaPhvwDnKBUKlVyqAQ3/gAkDlWgPeVQEUCtEOIP4AaHSI0CqBWCQyXOdQuRaEFOk3g3IMWO46+tvZ+PeZs6apq4ipON1MNafrvreTPzfvub92bGAOEnZCBkIGQgZOClZoDrh25y5pdjruleEiX+A+rCaQo05bpuvJ/+IHJCSJtwpAHA/e269g8W5RbuzF6o7OVjF8D3Pr4tSSkyjcqfptPDMDKSleW4DKIggIAD5Yf+Oo4DNg6jbUBlvWLUNutAwZu1GnDjzrcXzGcX2AHw/emFUV6Sfk0pqcKpEydkKSo9q3tkz91uF5aWlo1Gs/mYc+i7tz4//19vsW2AU9O381TiioVCQcnlRsWeQhD3bJyH1/MiFLICyBHiuzQsD1arDvypW7DR9nzZmq47q2W95prm+I9fXfqXCX2AF2d+GhI98Y8xVX0lnxvl2UQQg0csb78ag3NjEeD8lXZ7pRTgftmCu4864OGzrq+5ZU0rCa3m+NzXlzvoAoB3+M+SyWQuaHBTEzKMq/3BMbgM+FuFCDBd9kK5XI5PJBKqLSev+POTV29lKB8rT0yMD0WjUSYLZLxzNgZvIHODOHuATP72Vwc6nQ4Uiw8MUeBU4nHS5HA6TYMEl02wPRcZBJuv+ya+UCZOIBaLwfCwQi1Mc4QXhA+PjWRkXyOgC1uIhW5Qd8yG2TK7kSweLcRGKKVnMNExWWBDTQsH9qVmtmzjiThQDs4Qz/OUSGTwcLwIQTLW58i+yOjpXDLqn1tgmDzXzRCk9eDenjo9yhvBmlizrB3V5dDrNTuY0A7opdndStqmaQLPC1WCGfShYRgHdLe32UrV3ntiH9LliuNrsToNlD4kruN8v75eafnSgC6Luo2+B3fGKskilj5muV6pNhk2Qqg5v7lZ51nBZhNBjGrbxfI1+La5t2JCzfD8RF1HTBGJXyDzs1MblONulEqPDVYXgwDIfNx91IUVbAbY837GMur+/k/XZ75UWmJ77ou5mfM1/0x7vP1ls9XQdF2z9uNsPzosXPNFA5m0/EX72TBSiqsWzN8z/GZB08pWq9VeEZ+0bjKb7RTD2i1P4u6r+bwypo5tZUumEcDAmuC3W8ezIqSGfE6g/sTd1W5p5bKjaWubrmWd29Fu9TD0GlYlmTx+8tTJoZeqYe2BZC1/JEU+wQR5TVEUPptJy3Fs+Vkzgf8lemqHumP1AnYoMZSwsVEz6o26i/G9Lgitb+ZmLu/YZtshfn5FZDPBCcJFQRQ+8ih9DctOFvdLIKHH6uUQnq9yhFu0bec7znZ+xpAGmuqef5/wd8hAyEDIQMjAETHwP7nQl2WnYk4yAAAAAElFTkSuQmCC'
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Buttons_Base64_Shaded.py b/DemoPrograms/Demo_Buttons_Base64_Shaded.py
deleted file mode 100644
index d926e79f9..000000000
--- a/DemoPrograms/Demo_Buttons_Base64_Shaded.py
+++ /dev/null
@@ -1,135 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo of Base64 Buttons (that have gradients)
-
- These button images are all located at the bottom of the souce file.
-
- It's very easy to convert any PNG image into a BASE64 button but running one of these PySimpleGUI Demos:
- Demo_Base64_Image_Encoder.py - Converts an entire folder and writes results to output.py
- Demo_Base64_Single_Image_Encoder.py - Converts a single image and puts result onto the clipboard so you can
- paste into your code
-
- These images are not going to win any awards but they get the point across.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- # sg.theme('Light Green 6')
- # sg.theme('Dark Red')
- sg.theme('Dark Green 7')
- layout = [ [sg.Text('Some Base64 Buttons', font='Default 16')],
- [sg.Text('The size is modified using the image_subsample parameter')],
- [sg.Text("All of these buttons are contained in this program's source code")],
- [sg.Text('These are not super-attractive buttons... better are coming... perhaps with your help.')],
- [sg.Text('The point is that it is not difficult for you to add button graphics to your GUI')],
-
- [
- sg.Button('Rect', image_data=r1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=g1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=grey1, button_color=('white', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=g2, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=o1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=y1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Rect', image_data=p1, image_subsample=3, button_color=('black', sg.theme_background_color()), border_width=0),
- ],
- [sg.Text('These oval buttons are 1/2 of their original size. (image_subsample=2)')],
- [
- sg.Button('Oval', image_data=bo1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=ro1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=go1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=go2, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=oo1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=yo1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=po1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Oval', image_data=greyo1, image_subsample=2, button_color=('white', sg.theme_background_color()), border_width=0, font='Any 15'),],
- [sg.Text('These square buttons are their original size. (image_subsample=1)')],
- [
- sg.Button('Sq', image_data=bs1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=rs1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=gs1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=gs2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=os1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=ys1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=grays1, button_color=('white', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=ps1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'), ],
- [
- sg.Button('Sq', image_data=bs1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=rs1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=gs1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=gs2, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=os1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=ys1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=grays1, image_subsample=2, button_color=('white', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=ps1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'), ],
- [
- sg.Button('Sq', image_data=bs1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Sq', image_data=bs1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 12'),
- sg.Button('Sq', image_data=bs1, image_subsample=3, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 10'),
- ],
- [
- sg.Button('Circle', image_data=bc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=rc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=gc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=gc2, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=oc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=yc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=pc1, button_color=('black', sg.theme_background_color()), border_width=0, font='Any 15'),
- sg.Button('Circle', image_data=grayc1, button_color=('white', sg.theme_background_color()), border_width=0, font='Any 15'),
-
- ],
- [sg.Button(f'Standard Button'),
- sg.Button('Exit', image_data=r1, image_subsample=2, button_color=('black', sg.theme_background_color()), border_width=0),],
-
- ]
-
- window = sg.Window('Base64 Buttons', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- window.close()
-
-
-if __name__ == '__main__':
- b1 = b'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'
- bc1 = b'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'
- bo1 = b'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'
- g1 = b'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'
- g2 = b'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'
- gc1 = b'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'
- gc2 = b'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'
- go1 = b'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'
- go2 = b'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'
- grey1 = b'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'
- greyo1 = b'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'
- o1 = b'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'
- oc1 = b'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'
- oo1 = b'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'
- p1 = b'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'
- pc1 = b'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'
- po1 = b'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'
- r1 = b'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'
- rc1 = b'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'
- ro1 = b'iVBORw0KGgoAAAANSUhEUgAAANAAAAA1CAYAAAAwLWVFAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAC8pSURBVHhexZ1rkGXXVd/vvf2YnvdYb43GkiwhIWzjV/wQL9uxKQLYEJSAKZLwSLCrkhQJ+RCniiJUKh8oihBCHH8hlQRIqEpChQQSOwQIgQIMNsY2emFjSZbGGmk0eo1H8+zpvvd2/r//WmuffXt6ZNmWYfXZe631X4+9z9lrn3Pu7dZovLW1NfqLol++9dZ3Tnfv/oqL4/GVh544fs3KaHxgdWlp39bSZG15aXnPfHl5bWllZTKW75gOkoA8QdQPs7fdJiEdgGwsoQBDtt7J5HRoYtVPxAs3SZgYseJ5hMa8GDBlC+UnviU9c7RcpvJNImTBfjnasmu4LwahLZCAwNTjht5EosMKldQQC/LQ/DkFB4rmaqhwr8aSGis1Xkp5sW3Bx7qati1Jl6/kOQmUc2trPtqazUZb863RPPX5hfXR9Nz5+fjCuY355vT8fDY7P5/Pz6+PRqdOXn/9yZX5/Nm19fWHN5aX7v/ue+59wFP5c6Y/lw30Sy95yZ1ro9HNs2uvefXaZOn2laWl20crKzfuOXhw39qVV4xWdu8Zja6+arRypdq+vZOltd2jpd1qu3bpgi9tK7iBvJ5qrEWdRrmycSgM61p5rZ2dXcf4ZlJ6rgHYlroJXGg/JnaHG1so98sTEyIJuROCPD4/OeHoizxykwceWGQayr02TpynuA1pLSdbI0MHqanzXLbhAnJqYVRBN7spdfsypsbGLyGCWk4b7IgW/k0P77ioQq3CJcShjk01H83ER9pcs42N0XxjYz7TFhqf+txoprZ+6rnR2QsXzs/Pnjk+39h84MJk8sDk+PF7zmxuPvxdR49+iDRfTvqybaD/fMst37z/c597467D179h9/WHb9917bXX7Lnyin3LV18zWXnJodHyvn2TydraaLK8Mud6chmzqHS74grGxXSRRNX5qlqvAMlslLz6Ya/VNEVhmQghVWHl5lCwopBinJDSSdIgB0k3VPYiSTUnaHuYaPCF0rjdzzkEFp58oQi3x0Dps5Opn1fziGMH/8EWNCgDBrFWJWUfh9c0TQs2SwtzSbjOWVpYJccdz5q4trSsfqJ5Q05GUz25Ll6cz9YvjmafOzlfP3VqfePs2ac2nzzx0Nmjn/3Es5sbf/w9D33mf0T8i0sv6gb6d1/ztbdf9alPfucV+/b+1T2vf8ORPa94xaG1665bXd6/fzRZWY43ny09vH0tsrS5u0B5ferpgOpSD6FxyK9KIWXvoJQ7qriMta0c0lanbz+42pBN1Ck95liJhZEnckhIg8+iDDteZwLAM+BytBDb+5bc2SUG2m+h1NJt8A4fF/m2NJCnbp8w8BpXTvTWUmi+8uFJHhsn/O1jqkwDha33QaPDF0n5ggXW/CMg+gWfuafJs1Mba3b69HT9+PFTF//kT44/+/hjv/XYVVf/0rs/8YlP2ONFoBdlA/3Gbbe/a9fePd+79+qr3rzvta89sOerv1qvX2vT0fr6ZL65EU8UFdFYdw2Kqoo1r4YILK4AF96+iVfvmLSFZyxPT9bth1sK+fRyXgs+FuhSPX07ahgwYlLgITGkNY01PAkzznNHTyfO186XoTzXVJ7HF5v8cLVP+uYwjZoN3ypNqXVdhHiDeF4d5l4a9/289iYLYQ/KeIuSJZI7shiSjH8icaQ18jobB3Eei5zpE4cbfeCIXc7siXfTByzX3K5d0y19lp4+8cTk/H33nz1z7Njdpzc3fv4dH/v4zznoS6AvaQP92uHDP7Dvxhu/7dBNN33T3le/as/K4cNxKpub/nQ49odKNQ0BTldbA0KKS2eD164oaocuQD6DhF69KIWmi3oZpfRFH7Qct/VQjGV7H5Dzqk0OkJAXukvVUXl0FKHPT9tzXXZ9dhi0fNPUIi0s2vLTv2QB5VjcFLihwtl4yKWLQkzcouS6JuCJFQ1uIS30aSwf5zJji4z95YLh6uMoLfWaS1jo2UjOsbw8Hy0vj+ZnzozOPfjg9PTjj//e+Uce+Z9P7tn7m9937xf3JcQXtYF+/brr3rp3dfW9B97y5jfuu/0rDy1ffZW2ii7afK46j7uHF0lUxRq8wQOXEB5ByFXAbUOlj6lk2czTQAzuqAk1XuRNSVw5VYDHKSOyqHhPzTfN+cXEjlSD4ck13p6vy3UpXcawAJeSiXu1Cq3G9ZMhHfr1RiyT4fIJFiSlniwQassB13WXPgwbtnKpguZytLDEQoreXF0fF0A+iQJOO/EIMS/kwV4SXmmrGDPx8Vh39/Fka319fuHYsdNnP/bx+08++eRPv+OJJ34Vly+EvqAN9Bu333bHrnPn/97BW29514F3vPOalQP7/bRpm8RFE1RSQcFyG6nr9Sh98QATHSh8kiQMsjxz+sbSUPYeW6DmsIMRSDnL5PSSmydAH9bJTZSw3W3QcyEZQNe+rl1RluJC7CLJN44FallaF4Vd5Hxpa+hg7uIGZqF7LTPr5Oa3XXdcsNSC5Beuwxx21iF8UaI67BFH2iws4gLh1ezkI3GDqac8mkzmotHFT3zi1LP33/9r58aTn/nWBx54wZ+RXvAG+s0bb/z2g/v3/dj+17zmdXvvfNNoNJ3laxqfa4KoiWGhVBqlJ1lOjIZbyfRVtMYslyUoLuXgBzVRYMjyGQKigxPaPTHiHRsq/wxqr2kdkaKHixOass293HEIecfcC2Qvu4UUNOSoDZdapRNfGGf7mqZffF9TWzRDe9dekVx+7lIIlhYriMgo4FDaCsu8Zj1WJjoOnfjCFxXCmQWca9vrOZOIy1jLxsJatW3ZQkapcwa4O2Frq/PNY8cmZ++574HZww/9xJuefPoXcP189II20O8fPPCPVm6++YeveNvbbtx15AjfyfupUwXDhUDsVPfYBwyJ0w9wwAc58PC0WkZN0ZjtcPVMuwrSYIhF9XufSBLnGPMN/0BEFWM3bJmTvvMrt0EIqk3N0XKK7JYYcm8z7QhCBW53qEwd7bR2Deps29MUVbxYq9s+p0SfXxzJ6ZpzMKjxEFzPiAjzKPrmlMwcvNMjf0KyhQmuMfN3UtHSkvGhBQ5mvceJVQpPA53fMYUYGDFLS6P5xfX5xn33nzx5zz2/8MzNN7//rj/88KPhtTN93g30e0du+Km9+w+8+9Bfv+vA8v59eurEJohijOuDEnXKnaI2QGBVYOmeWMop0Ts+ZfMSQOLojNt4OTgozyehrhuYeDtrsAJ8MkDSu41UrKhU7zcEdS2fCVSI88IDjTFCLAhajC0qZ3gX2FML7HwbBm3XRaWbd0a7umt6gDWHYmAcYbMVvNVR2GlhCzx8LAUv/4bDwxamBI0xmiqJJ6iSxtg0H9HsExwKOaR0DRuCcvClonXyiQPjCN8aT+YX7rnn/LOf+tSvvvXoZ78X0+XoeTfQH1x/3S/tvvrq7zz0be8cLa+txRdhIi5MFFnJQcPmGZ408YLHGGP/xUCdAKKbiz6UsStSDmBZzGEIVlQxrs8FPEZuORJrZJku7OGfE4KKlV8/h45VvAlWk+jtkPW8Fv04UCfaVkOVoewV5sWuOzkQM5ch4+pGBctyCKr1TbN1HX16U+IWg0WVFZVov214gxDgUMpcGxs1q2BBzmMheDIVZPrRwasNOk+TEJODEWct8IVwbDTWjCdR+tKHX1zNhuujyWhlZb7x6QdG6x/76Ide+/iJt+C1E112A/3htVf/273XXffuvW9/+2j1wMEJ25+L7guvidQCGCtdHVItJrwVu38QvOyBtKDBz0bLOS9kY6HaPQVe0xZm7y0eDvj4F3pWrGEUpRFJ3Og2PeYS/oNPGVGKq2OThWvDWjGXL7rj0xEZW8UV9bl2pDKSK0UE8i7ki7FCDblRyQ2S0JlbHJ1kp91mD56d/QZ4sKfNcnYcLv6cLKIbMgUcNeIZ+BEhBTLHrkj7BWY9fQ2B4Wrf9BPFR7/Q8SxfY3l5YvOEjc760tJ84+jR+YWP/fEHHzxy43u/+8MfeQhzTztuoD+69pofX7vyin+4/1vfsWd5bVdsHi16FCNBZq4DOuthcqO3bqyQ7IwlOQE8Wqmh97YyiLRJrAnzfWO7bxF2JgZYOH4LPqlWVzbHJfW5GSxPNtDKD4YeqFek4qBOtJxhL4icCx7qjtTySUC2b4GJJcVydxhAZw85AVjqrUx67tgEmogQrMkp4tDqzbpafrHR8kj3mrYNlByGT/lzbsYx8HuehIXz+Sb8A3KzwgbhJzG7pW5bGELWDwCb6LNH10/d/8n/eufDj/wgLj1dsoHuPnTo3asvPfKTu7/x7YeWVld9j6/N4zVSR734dSwx10oWVbR6ogwxZs2BTklKdpOcagi0ArPBdsJ7HVZ6e+nkHIV1T6iicC0blL7bNkWMa4kuqG20xMrUuSyYCq8wqPd9IdTHsnYLOcPYxFDlI6HXGy8BER+SwY0kR+zlZMa24W5ZiFDZGzcYR+ktR4LJAhPlRnLWwu23qPcxzG3xSRVzQve8dT1gfhiC8WMfNh86XzAgxC9v+b3R/JGH188/9NC/fvXDn/1Rxiha2EAfvu2WN+5bXvkve7/u625ePniQdL7fUzyxidCiAVbNxWayZ/iSEqEcMqgVduNyHILd+dszJu9EAfdPGbMW3zXYjri6xmNj+4yRy0ZcTBpLYikmN9DhUOQij5VObt3gL16iR6rhaJKrdpsf68LguT7Ri9KnUW9YkDNhD0O13rBu7T2cMY48D2T7IORcUPEwR0ysGp3l9FnAaZEnbDbYFLaQW00aU5tnjKAxTw0eHbbTunG8I1I2LiFlxvUmsTOu8PrrhsAXNlSIifP3dePR9E//9Oypp5/+/jd95mj7hevCBrrvhmt/Zc+bvubbV266SROdTaog4fUFAAwdkwtQYOyTwIAcl3IAKdshinjACg/e/pua8oEsg8eINjBos0ez1TKSLkLiYQwbzNR44CEng2+z+yqF2ATLATSOe7uiCw6Lap/Py8VkbcuNDSbWLU9Q6XD7i9LJkMV0ghlMDpMvd+eQ6SyKJOgg3jhjDxUVDeqLNG2RJ+RL8dIDC5E5BC9su90yHXvFeBS1/Tqs4d5TZQMP7lsBc+ZIf+O1ofixmZ8yp8yPfZG12TY35hsf/aOP3f3q1971Pf/9V47LhWuJ62j066955XfctjT5+eWvf8uByXSqzQMeS1m/LOXCu57UxQ8eNhirYjMhtqcLivI1e3BU64XTUh18Rbl7P+/GA2w7Xdw+OAT56dZisst5lboYRyd7PUmh3pcO7rGh1IsWVJScY86vtK4TZa7mmnqZoXIpG2T/DIoVNwFZLF/Y9rgyCQ9/OponEIdaYAjdGDR1hrNQCzOpoD3PVFucfNv8Xfwi29Qck5hz0kJ1jDcJDUcwyf3GrtwJDfPqcJhb6HP9sEnwtbsuBLZo8Xaxtbw0nz/66PrTjxz9sTuPHvtXpG4b6DNHrv2/k2/6lrcur6yoXLYmExWiv1YmrRabukRzqyJTaLxyyXd7cUq3hoFVqZiuuRQtF68mi5q/RStdLPz6XIMedjUmyinVvLB7U1mNDu4WMszU40W204U85IYCH+JTgBUGMYf2hEFP7mA4SYs4F5ZLUvnZbMQW0hXSCKUBEpqesnkmzDUv2HopHKV3GD7APhXraXPxww1YDHsKyBS0bRq/4WGD2YjQcsEluZKj+S8UzDUH8iFA9kkust1+EmJ/5WsfuhqAW/mo1bScV5BO0nr6eAOBzbXNxuPp9N577v3MoSt+8Fs+/NG7vYHuv+Ha79x7663vX/qqr7pmPJ1p7yijjvodDtyQYTDx2lFWQvaCp1w6/+kuamCAJaOWXjxEy1ZSzg0QtgGPTZY4hNDPq23ixFh9bejAQg6ePsajwSJ3KLwDg0UntrApM0czdmLlhTrxEv9GytUIGWOPibarWkNOo5FkF0eRRUAYnXJSGMBZeGFLwbK6KkCgykecxMBCb/4ctQkaHjbHY4NDWayDX/KMj82TuOMQDcS8UnTj9zbwZhM3DtSNkzkR2WS9b8/FzCM84kHrC4XZY4+dv/jYYz/6isdO/BtvoE/fcdv71u644+9ODh1cpUxYMtdNFk3czIcCKlvnmLIWshVWYfB4ig06PMQBU+O/pxZQOAWMUuYQwtbizDrc4ytPYrC2EfKpVHj5RKNL1vktbjJwMcfRmK8BYx6nG3uwxQLU5s0o440s94CoVysIQnaiEMwEhnsseKy6nXwUB3bxG0oglCh+ZDUKjHrz3dxm9bYldzFGgxXey30bcFri5IC6wu59Qu+wWY2liTJXxfmXnulvbjy/1sYu5vMtW/oOevrB1bUNgy4jmybCADUFuudOT88//tgHX/HgI3eNP3nbLbevXXnlLy7fdNPrR0u8ubFRdOHF62buloWQipoSmcO0iHIuk4UqQngZOCwzF/nblnj6R66Ay+bmyWBnXBycYdEXEu6nRcZFsYds0HG+FlLJlTaoZLVKVzGDDMtzNxasxZIZH84nw4b4YOVjbjEXGsyudBbEUs4FpLO39cSaTIuCQiw5ChSuwmpFFDo8iilbkxEHfaHglMR5hMdGE8cHDHKeCA2uTjZ/JGg4QtmDx4ZH1MWTPI6iCF1Xie99WdtYf92M1GyzHzj5uZr4Suzn4znlHGvsxJCH8wssT0H+bKDCYqVm09l89NCDJ1ZOPvtt40/d/rI3777qmg9MXnpkny6Gv3lzU7CnZR0hZBugtrtkLxmOsIRDnkY+VWx3IcVknDNlpjhmUdDVmKZtRqRz1hlbNmLKZ+zVkYiexR35CwcSrvkRYZt0rnvprF2sA0LJpUcsatliIcNsguOT40csYo5Z1whKWwG4e3xrOxEZcq4Wdf4BiSQgV4OAGoYy8NgUDKgcKg6KOjD5VJGJDZ8bgoeeeeQXcsZgQ4E7J7nLF0Z8Yvm61V7RHJ/5Ui67c3W2moftYMm5JrII0MKwOPzLQBP+MRptMHHLSyuqy+W0sbj4sV7yyVzDXIrDxPlBxg1d5zA7+tnp/MzJvz3+1Ktf/kP7Dh563/yaaycTnSFl4rXOBaV5IIoDg40anDmI/J38fKaTgE+VXA+52XQ0nm1K52LNsjGJ0O0b01L+kLkK6j0uMt/8uaiQAfOcY1KhFx4XStxzVDbi8iTQwz98m8zR+fAERfWTNO3lB283D8Zp+QBqfmocFVP+tsERCeYsE/ehAsYO1HfwdDWVbiyuVbMbT2P95bNb4nAu/YLOehQfMHhsgvR1XHI1bw7rOIYvfrGk4Ve5W/Ev4CHDvSl3ii+ftPU5PW4ne07G4qnY5kbjwC7M/hSGr20uyLI21NLqaLyszbWyKn1F+0sYGyzH9xcHxMuf3NQwqWdPnpjPnnnm58afuvMvve/Qnj0/tHHgoNdZbcKAXnfvXgZUYybaFFsXL45G043R6OL6aL55cbQ13RyN1WxnVLl6AyjGr1JKQXgkjEaRxatXYtiNl5+Y8ZArpvxsl207xonXtSF2wc6xRKfm+MJDL/+alzcVHJfK3/lGDoyZRw01AsCQec0oGZM6ZKj8aDYCWRlom2riMotYUleFC4OGrADDrH5Ai08DQETkjKNImt7JLSbxxges7FHoxKRuPLBFGw17xvszjTg6Oe07jIEpnlyBt9iMY5OHLz6ca+i22VdAfm6qPJErxkL2jQIZzgWfLI/Gu9ZGo7U9o/GauDYUpraRdHH5r+DmJ58dTZ9++qPjj7/l63/+8Hj0fRt797K2lILeuhQy01PjwvnR1oVzo6319dH44gVvFs6Cdd6iGF2wPB6lwykqCoQsJJKjbXAnpjCJC8xPUvH29MBJnDqYuNjLjm/gxNpXDXs9ORzX4d4A6IonbdgiHz79RokxQwbj3IiJPJnXesR6EzhXt0HAbefcIg6s4nwupdt3wD1m3nRMZulbxOJhoABYUm8WL2jILowsBLosoFZk4BSKcNvLp9kCt46fWP/6FA2XIUcVqQuxj88YZH/9jL1sGdPGti3zqNhbQdMkL84hx6hN0Xzj6dPOFT/HIVd8xFbutsGSVyy5R/qI4yeaFnbMU2rvvtFo957RlmRSETZ97rnR9OSzJ5b+zk0vfdfB+fyVcxwvXBhvfe7kaP7Uk6P5k2rPPjPaOndGm0dPHaJY+GU2jHbFkpL7X5nUxF1wssvsYtAgJQ9Fmzaqomzo4C6skF1k5ZuFZntifVFW7oiBIxKQvkDGE+vzEiMWsfCwLRR+4xOJJCcH9uAl41fNONejdN9o5G+OTp7Ob1k63I0FC8z+krE5N3ZiwNDdYs6WdQzzQ8EWnTmEwNEAKDBIZVSiJd+wknyD6ez2SKVhtfAm7AChW1TCQloMJDC90t5bpQGKbEs5xmLGizTo4ej1tpSbU0R+RHRvHslNtwNz5wsK2fjXUs/r4XFODxK9dXmDcuffuDiaX1ifTNZms/WxlOnxx0fTRz4zmj5xfDR/7vRotLnhC8RnEQdYITvkYbyn2uhQXVGRL0LO2Gj5mmErWWRbJYHSCJXIhfCJ6aTA1ELHpFNtuPJouiy+C8V+EW9ysWWePK3Ik08TZJj8Bpv4hPw1h+AY6klGUGzEsMfGinx1/aK4w6c9wb1xJOfmGa2I01bVdsF1w0IuvG5cXbzHdJPuMZlLjsccPQfpcB1DK11dxg3zrpY2KVzHuMmhurz8E2OEDXf7wnzhE3PLNU7cZDwdYHJxZqsJmMJOqG1WYxyJkQIqHmiI4jFPiUpQGT2NGhvdPVpIvl6crLhf4bSR5s8+O+f1bWtTn/PHo6cmu86cPrn56LHR7Kmn9JlmyoNOMZkiZ8VAmdJ9UMo16o6ET/rtELq4aUTCe7cdiZBLnATUomy3yZ9heIXw+XjXg+scJaLZ1iW2RieqdNvTppcalnDu+2JQ5E9CbKpKxa8WZJFsm7pq3O0s+0gRCWWBJWWOpJDVtRwAXAP6/ozYCqIwBaUZVoXMHH0t02LerWF4XZpjAIpakuYSQue4s7iNLnXyObdJ7hA5nMAwdpL17Px652SxJSid2FBbk/k5fbQ5d5atdXQyPnvmvs3pJh9s+D4vvtOrcSUjDvMpG5oSO58tQR4wyJL1yOGmLmpYgoHYqN6gCEoZIXRJJWcxlR+BzItcYC5SjrkWtukxNgZzIDFsRlCyLXw2KDyxGoOufaj1XOFh9+Uo3Fjp4e8Y3q8T4z078sg2VduEKxiu5djaULso+SKyPo/SwGn4kQuuWOfic4Hza54pV/52Lmr1mcI2HVyL+DYMe5xf+KsDk70+X4D7VK2TJ2zwskdDD5vjxQJ3waBlbpvtaz/ZXagUMGZh9edkUKxrxHjsxOBgCJ6H/3p78PXNCcCB6ZcxkT3mX+dh3CmwBoFFJxZFPNe8PzIR/dlodfUZKZxS5A+/SCA5pprB/Ej0RCNrHMHE6dMuKpfWcoGsOqhrIp9sqlzYGge2mFOdjmEeAx55S1erheyKovH0JY+LQS0WP/L4qjgu5JaDppq2LXl8AF3k1UKn+MWnbAbFsElyQ8Cta6N407hJbrriZA8ftYpzy3GcO8byB+HtY8M9b2GeN3icU5xXcMs62jWD17UQjxbXKfzKt+yJ0elom7KzRZ30etpzvObbfIpny9p052Ajg7lINubl9c3Wz9uhNHdDzvJrZjB6/451a766NZ+uTiZ/sPSel928snThwp3j6fQmP4WUw3cBN6bUywg+rAM5OVg4GeMOYko8tLTZJ5EAUqZravKIcVcGUcOabDFIgFUMcQz2sqmPcLZrITsQd0QL6vNKWvdJu/PCpBgyShVSLpztFAY6l996h7mwacJc3MXV4NXyieNNwUZpm6Wa7OJsilhmYX1OtcDwTT3naQw5Y41JbznKT2zwL7xsySuX5LiZbbOL0VDdpV7XKvC0lX/L1dlKbjnBAo/rHDJYWwdsnWxbMDdsYSdeHHGxeV/pk+nDq5Oln5WyNfr0LUf+6eTChR/Ro2mNj6F8k+XPiXAqzZ+jVEzi7Stdf0i1U7TU24dq6YGLdTGZOPDyS7mPdS7JHiNzldx8jVdM5yfWf20dMdhLr5jwiXGk26d8U4dZVnN85QgM0fPRVbdfiwsOsw5uIBkcSr8me5lyDoiQ5FhMdfVKU3oxIJxSdgAcsYq3cBdjyYE7Fr/mGwXkuzfvbBBx3ixRnP4rhtwsHiNzORCfzIXqgm469vQnp/Tha+Xwc5V2dudN3T6J4bOQu4sd5IrJHAjCau7O2WHOWSZ/nU1YxOM6ns2mW2u7f+G2zz7+Hkpi9NwVV3xIG+e4HOSHY/2hjAGinc0T8gA1EE5hC3tcCPv3NnyLG8enWvgOsYHVWNZ9B81Y7rAsqO+0hSP3fslT90s7vHzE7eMchWXr7/DG5JuYP3v4zg8fWuHm9TmFV7JeztcvML+G8UqGrV7JjPHKFvLcn322y4rhlQ55e2zXYlzy46/5Nj15zR29zV/NT7DE8nqM66lW1wU5r2XTzeWX1zQwXVfpbc3Ac93G3TX3uic3hk4c+Yl13aQ/Pq1F/qidzk/cOraUnVuH64mjYWr2DazlLpNkMUGxH3RVkOdb48mp+dLkdwSxQXEZjY5ed9V/XB+N/obubzyB/OsT7qx1Q40nkUF/K1vywtOjMA7p8bTi7o4cfsS1u33a2iAo+IHZF5m7e/kB4xu2iqu8xsrXfuGDWDH9HBfj8Qm/YX7bfKyHzwLmJgN/90e8dTp4NFSfBzqXHME2uqROdEyKsUKiEnqgxygYMd91eVLl2ppzpI+fYuZZbA2TkrrKOGSK3nGY6dK//NCrGDkSB7ONlvZWpBAcH2NqFV+xjkm/bZzC9muW4sI/44XD4oY52GBx4y87m7TsMQeu2fCwqHRg4SeX0HWrWZ1v/fbRl7/8PW//nd9/tG2gj3ztna85/OlP/p+zq6vXxP+ALzYPG4dC4cMROgvutbcx9FZkydGB4zVKAoULTsfvLUrmSHvlsR+Y9WB0/n2H5cE+jBc+Q3zqvY/xXldnP8TEMq709roKhg3K+ObTydHkaz86SymLcHPCJPurOUnKOxFL1NtiyYIss8opstLlAHMbdK934sjxvt/j6sixDUOs4sqq0qFJ2T90xzgWLHJgc2z6tZzYU6/XJT9lJLQcHOkXupr0enqEX28PeYjBjh6yeeXu8tZ4xe2GbpfYWMh6KM7XNqenTl13+D2vu/+T/h92tQ0E3f3y235831NP/eON5eVl/xUcxaBrxCZiA4WsIARsfcEhV3Eljt5snQ9i//km8iHjxtMsbYXj6w1E03xb3tRThoVP5K18YJEv7Y7LvAvj6Gi2AW/zo6UdEbufrCnjFh08Wzk7B/d1lJxzs7EGiZs/H8mHwu18XYTJA8gGWVbXdBWD9cxB0cA58KkCg1RJFu0P15HFWFgVnVsVou1qWbCIIauh2Kd/ChhKOzocPx2Safbt8sQ5oA9xQ47giznF8LVMzkH2OJJD7bh+ItxPHr1Lz0d7x+NfvvHJk9+taNPCBvrIG19386HHH/sP843Nt+o9LV/jWCaePvEEQqag4smEXV0VpxzQW7FWgixSipOCA24f3NMW9iGuFe2OWMqdDd4wFOfWhXcMrYtDdlMn/wWMOMi+4m7qki9gUM1BXfvTleYf+CCLJR8EUScuUI/XMoEhD8sWJJ0FLznaNh2iMHobhQQ1POSFHBRf+ruYMZeteBYirTZZX+TIvCa1XCk3P+So1sQirl4hw0cnbx5z3TEOWVi8konbFj5smphH+VWewC/dNGFHlzDfWll5YPPQwb/5mj8d/u8NCxsIuu9lN37z8rkz75+OxjerhvhLLa11bRieROg0/j4s6gfARYgSwMLmWLC5MPlcE3mcBJ+yN39w9MBbDnj52x74QgzEOM0fnhhCh8Mqh4kcomE8a8GJD3PomaN8IhcyPAVj6rjMOUbLAVnugEtsosUlCp3mSsDJihfdZC686bRBtuSqENlGCwMFNGAdXv4UbGHJ3Vx1IQ94ctkaln6DHn6otnXjxEYEk24xdR2RM7h9m9+iPT77DHhtMKGWhzD+2rrcYjOho+nNcr4ynz0z2r323juOPfmfQIsu2UDQg0euf9ds/cJPXRyPj+jNSW9v49GSFoSFpwBdp1IaVwo2jAtDnbmNgRto8mBrPtizWJHbZw9hjJcDNZ+S7dNkccvwsqU9fQIf5ADCp202XbCaAwUa4/e+1bCAcfIAImJE7hNqXxxAZai8ReSQXiuBJWS8WM7AisLGnVSolLaHinJNg+EQQ4TqPhRkBbcaELdf6VloHgAbBcdMJEdx58CtQIUTajniHV66ipRibmOAOQ/6IKM0veXWPNsXGoEv5MAPk+XAsXustId/5EYOt+SJx1NHWEu7NV+dzU+N1nb/+Fc9fsL/Ek9PO24g6L6bX/r3l08/9xMXJ5N9KqjJkgtGASqm+DwUuv9OUidH7fCUolqi3mRHaAUdPHQ14tAtg6XuRBmPTmeftDdd89YAjMEZtA2QPr0Oa4VMpzGMSXVenPAXNR/zkIllWtSL7SLnQyhfROcoJVjkSKGwogalYbv9ctSWjOU3W6TUWVunLLs4EfF5AlBWVYklOmohfQzS0LI4s8KCqiBF3ljb/TNXtEsxz62Pc8NPgseImPY5CQLXJoqY9Ovjmpw4WOZBhmG3Wab4vFO6ZP14eONOP1+dTufTQ4f+xaseObbwL5IWXXYDQffedOSfjE+ffu/m0uQKbSBqyPVSG8h1T9NP1CtYFCe+taFg4QyPJMboKGAqjxUcEqoYk6tF8UvI2OCI6iB8K6/1kMunFX6HVQ5Tw7uxbNOc7GtFshY9dknYW4txPY64e+POIEaeLq4jjwkPzb1pm5+dGrHU4XLJ8jU9isAbA5DJmaMnyypphI7BnFnD1fP3hZaxJVOltdxZkQ6zMW0GFFmGZO66GHA+s1DovEoRa7zbFC02KnxRh6NkTlrkyjkZRo4Ngm4upybrp722qc2UYddsuj4/eOjff/XRx35Y6I70vBsI+pMbrnvX8vlz/2xjMrldV5H/UsULx+aIugrujYOWeMlu6Q/HKNEOUcgIdg7e7KWHHL7IpXc+tMxjPyjjAhvkPsa+KTccShkWHTwbXe0FicOTyFCA5tlFlQkuB1EnLlDv87zkFb+UOqyta2GND06ILlyg3g+g6SFbLRymSvNskTt8u48JzMWNmFhU7c6xstmt6YPcP2m2644h1ix0NMYY9hZy2CI0/cCtW56uzmcntvbsed+rjj/1LwVdlj7vBoI+euvL3rZy+rkf29q4+PWzpWW+nfPvUikKN8kLG0jT8GcifqwLt5x1jmBesho+GLtNEj75BMkNUjaHgEHpS6zzQek/6GqIqZtVXMqoXI141krGbBEhZN/IAxSDO8JH+ITNVKKw8FLfx0BW1ZXvF0SZp19DyVHawhiuMwEs/IIVByoLKaG4+6cCR+zU5tiqjcaYg2yOPdWmcwhoT5jyFV/UB//BNmCeX/qygXxOUoBqc7QvBZxCWAtPv8QGm59A88lsNhqvrt49Wlv7idcde+KXZXpeekEbCPrdV7/qlYceO/YP5rPpuzbG40MqlDn/lAcFs7A5mlw4ff3jjLSy6UI2Hw2QtpIFh+xiVrtkY5UNWdlq8wQUDhxqfCFAuL+csK2a4vBJzHnMA2hyACkrj4RARBaYOwtR56LGZU1bcOKCZzoRQjoW1uJ2oO22tnQSUrZLw5NqjdPNBVxA20Cx7ewTxhA62bja4iajDbYQOln5w6auOGT80s3kvNYTy0dH+fA6iRE/MPXB1aWrMTaEmLFhU9k7NlKn4zZTiS5vzc9Plld+69xVV/3kN/zZg3+o0M9LL3gDFd19wzV/bX7m3I9Mt7ZeNVtezq+5q8xDqI3SdP/kxim9/MCdY5sNC0cOABYFHXg6NRl1EUsdFpOIpi58aYlDiNJrQ7FJAsPm2Vj31epwAzbCBz8329IoVlea1ybjabKAXLnK3lNhlaQnYy4EkyMTayBklS4HK5sLKcibr0yMGUIcyGrttQ/VGEZ4J1ssPHjbeOaJq8LjlCNn+2IBKlmNGVpMv7YpGpYbqPMZsJ11pWeE0WQ2n+uV7eHpgUM/84bjJ35WLi+YvuANVPQ7L3vpP9/z7MnvmI3HX6Eca+P4xSsfN8V9L84agdNLFu83VOEEeuGk+EnF08SWftNhDzQ+jwMqyPZ0aDxkbYfAagNBiMLa08VA+jV98AvawQ4xD887gOYO2db5Qttk/zVz74JAvkiK0FFizScRdbUfFgw9R2iyqFStPXPmA3cjDFUT4eQih9erUvNBF0f1PApvPjq43TNp+w+44zK+cJh5/cgeH/ThIPjkJsgYv4q1NN0GkUAkFDa90pFHP54Sf2Y9Gm0sjUaPbu7f/5sPveENP/0Dv/qBow74AuiL3kDQB974+te85Nij79za2LhreX39lbPJ0jLFyo82UUg6uZ57syjWrbDkPlIWu8QeOjh9hzXDYKOALXU2y5C4xVSbj2XUboPRuETbfMzwM08XB9s0cMhyB/Q2EarHC3WgAnZYoh2XbQGT0uuWE8Ck1tKXLc0ByJqDUIwuPSZZftjCHJCan0zW1VOe0oZNkn7RGQsYxapaaOVeTxkULH4tA0cvX34kNBsYMpg9+H8AefPM8WGO+pwzn+/a9dBoeeV/nbv++g/8lXvu+5CDvwj6kjZQ0W/ddssrV86efdvS+vpdSxfW79RTaW22uqLPSHEj1iXkweKOoqtapOAsW2ejhI5GnFji+UTTD9T81CK/Hc0jV5DlSKgCxao87MZwbo61YSzbjkCna5PxbVMFasHj8vsoGcoWg+rIy9pwSIJfDVlIOwV8uRXAfDlbkVPYSYWk3BSIqQv0Gue4hRsihgzMp/PHJ2IkuyJ1sAaSww1Z0fiEqpayX4py5ulffjAXvJWw+QmSujeBp1NPmTDA0dnJ5HaMjfyznMK4/mDhHTZhfBVNqGIn/C97lmezja1du+7d3Lv3V+arq7/+l48ea3+S88XSi7KBevpvX/s1b7zq8WPfv/b0M6/X56Qj86Wlq7SwyzrFuYqQ2ldjg2RB86OLVhzybuOwn0XLttmUdtsqXk0CHCo5bIGWzLgkctGUU4rdzjWFadAXeeGR05sDrXyKev0SY05iOwwVttMSZQFdQobVwdm9FWwWRWa0bFlsJuJcuSjuYhhapRIQTxUc4ZHTfhnjVyQRFqdHRsgw683GD/aIiI3S27GFT+RNHMzDE5MbKPzYUfwXD6zkfGk2O7m0NTp+8cor7z51+PpfvOuPP/7bZHmx6EXfQD198BV3fOP+Y4+/XSdxx3R56ebJbHqd7gnXcBHYJHP/G2mSuLtJkKZNJkhTqsKFu/kHjm7jgJuXTB8JwledrrR90q9s6UbUAg6GDaXflNbFfMUKb0ZRBtrS49AlzkkULXFO+iWQ47sk2/NJjzJEZh4l67CYOmSAogR1txjiQs1sabMvgM7HHJP97GIjV6Zh6vz/3Eln65fYxNPIph3+vz2jiV/vYrPwJYA2FwjltHRSdXViabb1mB6Sn5xed93vPvGVd9z7tz74v7/gzzcvhL6sG6inD95+6+te8swzh8/uWnvl8sbGDePVlTuWzpy9cXk2PbA0Hu8Zzeb7+A8VKaYtNpZFSlE/WiDWz81YKGFNzLoV8SziUDvcDx4Ur4xtNF8CCflUwgU8A0MPMXxRclMaQ02YZrIQsWWjs84YDlYRmAcN0ucncvocMjvlFBmrG8ilFkfqHYHHhMwX95Yjfc7tqYJdin+YO7E++Il5+MBEULk4dyhSQ4fzg93JF/Xg8UNC/pFDXt/0wZ/P0uf15Dm/OR6fnR448Oh4c/rAxurKsf2bm392ev/+R8/ecOTEd33oDx4l7ZeT/tw20PPR//uKW9587sDBwxf27L1ia/Pi8jWPPrq6vLW1X3eQNV02XvvitU6NreWaU4NVZxwRLoEvK7yKdg7yZyk2iZcnittmqRR0jVF2E9XD4sWeTo+g2AQYeImAIgME9/DOjWJYeGbPfC1AlC4m4C7sElsjDNnCJzeSOi9t8aQQ424dc9cnhc6vufKqlece5DI2992/TC0Gu86NOMcGFkb8+RIAOaBo9LnpFBP2QNsY+tEbybpurmeePnx4Y3Pf/unq+XOnDpw+fWLPc6dPfMOTT91P1F8MjUb/HxviaMFsPksnAAAAAElFTkSuQmCC'
- y1 = b'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'
- yc1 = b'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'
- yo1 = b'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'
-
-
-
- bs1 = b'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'
- grays1 = b'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'
- grayc1 = b'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'
- gs1 = b'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'
- gs2 = b'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'
- os1 = b'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'
- ps1 = b'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'
- rs1 = b'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'
- ys1 = b'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'
- main()
diff --git a/DemoPrograms/Demo_Buttons_Base64_Simple.py b/DemoPrograms/Demo_Buttons_Base64_Simple.py
deleted file mode 100644
index a6b5cd2f0..000000000
--- a/DemoPrograms/Demo_Buttons_Base64_Simple.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import PySimpleGUI as sg
-"""
- Demo - Base64 Buttons with Images
-
- This is perhaps the easiest, quickest, and safest way to use buttons with images in PySimpleGUI.
- By putting the button into your code, then you only have to distribute a single file.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# First the button images
-
-play = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAByElEQVRoge3ZMWsUQRjG8Z8RFSKCgoJp0qSJjVpoZ2clkk8g5CtYpU+TD5DSUkvbVCFNYiM2dhZqY6GFQooEISGai8Xu4HgmcnM3c+su+4fj2L2dmedhb+Z95x16enp6hljBxaZF5OAE7/GoaSGTchJ9tnCrWTnjE0zs19+HWMPlJkWNQzAyh2c4rq+/YBnnmpOWRjASuIfX0f0d3GlAVzLDRmBG9Ta+1r8d4wVuTFdaGqcZCVzFOn7Uz+ziKc5PR1oa/zISWMRm9OxbPCisK5lRjASW8Clqs4H5MrLSSTECs1jFQd3ue319KbewVFKNBBbwMmr/EY8z6kpmXCOBh3gX9dNYdjCpEbigWs326r6OVKvdlQn7TSKHkcCcKt4MNJAd5DQSuI83Ud87uJ15jL8oYYTf2cE3f2YH1wuMhXJGAtdU8+WnwtlBaSOBu3gVjZc9O5iWEapJ/wSf6zEHeI6bZzWYmY6u/4v+rzUirZ/snVh+hwPitpYFxNanKJ1IGk9L4xcz6Eom18bqg5ZtrDqx1Y2LDwPVG2lV8aH15aDWF+jOKpkWi8o5GKWIXTwq56BzxwqdOejpxNFbJw5DO3M83dPT02J+AbN50HbYDxzCAAAAAElFTkSuQmCC'
-stop = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAAaklEQVRoge3ZQQqAMAxFwSre/8p6AZFUiXzKzLqLPNJVOwYAvLcVzpztU9Q8zrr/NUW3Y+JsZXsdSjdimY0ISSMkjZA0QtIISSMkjZA0QtIISSMkjZA0QtIISSMkzcxrfMo/ya1lNgIAX1zq+ANHUjXZuAAAAABJRU5ErkJggg=='
-eject = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAAByklEQVRoge3YO2gUURSA4S+JRnyACIGADyxERAsb0UKrWIidWIidlSA2YpFWSauNVtrYiIU2YpFCLGwEEWwsBAsLEbFQFARFfKBZizkyK5pkZvZmZ7PeH05z595z/sPszpxdMplMJpMZbDZFLGsm8CxiomWXxqzBQ3QiHmNdq0YNGMc9RQOvIjqxNt6iVy1GcF0h/h47sR1vY+0mRluzq8ElhfBn7O9a34tPce1KC161OK8Q/Y7D/7h+EF9jz7k+etXilELwJ44vsO8ofsTeM33wqsURpdzZCvtPK5s+toRetZjCF4XYTI1zM3HmGw4lt6rJbnxQCF1tcP5ynP2IPQm9arENb0LkDsYa5BjFrcjxDjuS2VVkI16EwH2s6iHXStxVvjy39GxXkfV4Iu3Y0T3OPMWGBDkXZDUeRMHnmEyY+/eA2cEjrE2Y+w/GcDsKvcbWJaixGS+jxixWpC4wgmvK+WlX6gJddM9lN6J2Mi4q56cDKRPPwz7lXHYhVdJp5W+KtmK61yZOYG4AGpnDyV6byWT+ZxZ7Rnf6YlGdeX2XxZ8AVag6AiR9uzZg0U/G0NyR3MigUfU7MmhPr78YmjuSyWQymUxmmPgFokSdfYSQKDwAAAAASUVORK5CYII='
-
-sg.theme('Light Green 3')
-
-# Define the window's layout
-layout = [[sg.Button(image_data=play, key='-PLAY-', button_color=sg.theme_background_color(), border_width=0),
- sg.Button(image_data=stop, key='-STOP-', button_color=sg.theme_background_color(), border_width=0),
- sg.Button(image_data=eject, key='-EXIT-', button_color=sg.theme_background_color(), border_width=0)] ]
-
-# Create the window
-window = sg.Window('Simple Base64 Buttons', layout)
-
-while True: # Event Loop
- event, values = window.read() # type: str, dict
- print(event, values)
- if event in (sg.WIN_CLOSED, '-EXIT-'): # If the user exits
- break
-window.close() # Exiting so clean up
diff --git a/DemoPrograms/Demo_Buttons_Base64_User_Settings.py b/DemoPrograms/Demo_Buttons_Base64_User_Settings.py
deleted file mode 100644
index 920979e42..000000000
--- a/DemoPrograms/Demo_Buttons_Base64_User_Settings.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Button Images & Theme stored in User Settings
-
- Short demo of some nice buttons obtained from the web.
- These are a good example of higher-end buttons that can be found on the web.
- Often the better buttons are in Photoshop format. These all orignally had text as part of the button.
- Processing the buttons - The text was removed, the Photoshop image saved as PNG, PNG file converted to Base64
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def make_window(theme):
- """
- Sets theme to theme parameter and returns a window
- Creates the layout and the window object
-
- :param theme: (str) the theme used to color the window
- :return: (sg.Window) the Window you'll use in your event loop
- """
- sg.theme(theme)
- layout = [
- [sg.Text('More Buttons from the Web....', font='Default 20')],
- [
- sg.Button('My Text', image_data=image_sunken, font='Helvetica 12 bold italic', button_color=('white', sg.theme_background_color()),
- border_width=0, ),
- sg.Button('More Text', image_data=image_large_rectangle, font='Helvetica 12 bold italic', button_color=('white', sg.theme_background_color()),
- border_width=0, ),
- sg.Button('1/2 size', image_data=image_large_rectangle, image_subsample=2, button_color=('white', sg.theme_background_color()), border_width=0, ),
- ],
- [
- sg.Button(image_data=image_sunken, button_color=('white', sg.theme_background_color()), border_width=0, ),
- sg.Button(image_data=image_large_rectangle, button_color=('white', sg.theme_background_color()), border_width=0, ),
- ],
- [
- sg.Button(image_data=image_grey1, button_color=('black', sg.theme_background_color()), border_width=0),
- sg.Button(image_data=image_grey2, button_color=('black', sg.theme_background_color()), border_width=0),
- ],
- [
- sg.Button('I Like', image_data=image_grey1, font='Helvetica 12 bold italic', button_color=('black', sg.theme_background_color()), border_width=0, ),
- sg.Button('Nice too!', image_data=image_grey2, font='Helvetica 12', button_color=('black', sg.theme_background_color()), border_width=0, ),
- ],
- [sg.Combo(sg.theme_list(), default_value=theme, enable_events=True, key='-THEMES-')],
- ]
-
- return sg.Window('Nice Buttons Buddy', layout, finalize=True, use_default_focus=False)
-
-
-def main():
- """
- main propgram. It's a good practice to encapsulate your main program inside of a function
- """
-
- # Requires version 4.29.0.16+
- try:
- saved_theme = sg.user_settings_get_entry('theme', 'Python')
- except:
- print("Your PySimpleGUI version doesn't have user settings API\n",
- "You need PySimpleGUI version 4.29.0.16 and above")
- saved_theme = 'Python'
-
- window = make_window(saved_theme)
-
- while True: # Event Loop
- event, values = window.read()
- if event == sg.WINDOW_CLOSED:
- break
- if values['-THEMES-']:
- window.close()
- window = make_window(values['-THEMES-'])
- try:
- sg.user_settings_set_entry('theme', values['-THEMES-'])
- except:
- pass # already warned about settings at start
- window.close()
-
-
-if __name__ == '__main__':
- image_sunken = b'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/GMzLdsAAFTiaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0xMC0wM1QxMTowOTowOS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMTAtMDNUMTE6MDk6MDktMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTEwLTAzVDExOjA5OjA5LTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDowNDFhMDAwNy1lMGJlLTk4NGYtODNlMy01ZGQxZTk2NjI5ZWQ8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1YjgyOTQ2Mi0wNThhLTExZWItOTQ3ZC04N2E5Njc3OWZkYzU8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDoxMWMzOWY4MS0xM2VmLWIzNGMtYWNkMy0xZTVjMTI5OWNmMGM8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MTFjMzlmODEtMTNlZi1iMzRjLWFjZDMtMWU1YzEyOTljZjBjPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTEwLTAzVDExOjA5OjA5LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjA0MWEwMDA3LWUwYmUtOTg0Zi04M2UzLTVkZDFlOTY2MjllZDwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0xMC0wM1QxMTowOTowOS0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+CiAgICAgICAgICAgIDxyZGY6QmFnPgogICAgICAgICAgICAgICA8cmRmOmxpPjAwMDE1N0JCNEVDNjZDODMyQ0VBN0Q0OTgxOEYyQkI3PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MEQyMERDMEVCMTBDQkE5Njg5N0M2NzNCRjkwNDI5ODQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4xRDk5RjMzMUY1RkMyOUU0ODU5MkI1OERENENCRkUzMzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjI2QzMwRDNBRTREQjZERTFFN0Y2M0JCQUE4NjBGNEI0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MkFFRkE4NTk0ODJBRTMxMEYwOEYxNEVCQkU3MUEyNTU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4zNDBDQUZCNkZCMzIwRDRGREVEMjc0M0ExRjUwNUI2ODwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjQ4NTVBMzI3NzUwOTIzODkwMzQ5NjIwRkU2NUYzNjkxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+NjZBREMzOThERjcwMDQ1RDgxMkU4OUMwNDIzRkFGNTA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT42QjI5MkM4MDQyRTY1QTcxMkZGMTk4NTdEMjhGQTZCRTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjczNzQ2N0JGQzU2QkFDNTk2Q0M4QkNEOUUzNjk2QUU1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+NzNDMEVENEM3ODE0RTg4RjlBMjQ3NzRFRjdGMTBBODk8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT44MUU0QzY3QjQ5QkFCMzlDNkU5QzExRjQxNUNEMTgyRTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkEzQ0M2RjFEQTFDMTFBMDZDOUExOTEyQURDRDBFRjQ3PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+QTQ3QkZCNkY5NkMxRjBGMjhDMTI5RENCQkZBODRGNkQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5BNTlDQUU4ODNCMzU0RjgyMEQ3OTFEODJCREVGRjE2MDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkFGREUyQkMyMzA1QkUyRTc2Q0RCNTdBNDAwNzM3MEQyPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+Q0Q4RTcxRkQ1REQ3RkM5MjcyNkZFREQ5NDRBREEyMTE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5GM0Y5OURGQjBFMzE5QzUwQzRGNEQ2NUZCM0U1QjU5MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkY4REE4QjZDRUM5MDI5OTgzMzUxQkEzQzUyQTVCNzREPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjMyMjNhYzg2LWVkZTYtMTFkOS1hZGRiLWNiMWQ2NjAxOWMxNzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo2YjM0YmVlZi1mNDg2LTExZDktOWFiYy1mNmY3MDc0YjFkN2E8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NmNjNzJkZDQtYzEyMi0xMWRhLTllYTAtYjQxMDIxN2JjNjA0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjc4ZTg3ZmZlLWY5NWEtMTFkYi1hZmE5LWY3OGRhN2FiODZmZjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5NWFkMzRlOC01MTQwLTExZGEtOGFmNi1iNjQ4NmE1YjIwYjI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6YmViNmY0N2UtMjIzNS0xMWRjLWE0NGUtZjZiOGI4MzA4MWQ1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOmU3ZmI1OGNhLTk2NDItMTFkZC04MWEyLWRkMTQxMDNmNDUxNTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MDFGMUEwRjYxMUVGMTFEQjg4MUVBNkJFMDVFMjc2RDE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjA2MDFFMzM5QkFGMkREMTE5QTlEOTEwOTg5NjI4QzVGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDoxODkyOTc1OTlFNUREQzExOEQxOUJGODREMUU2QjZEQTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MTk1MDE1MDhFMkVGMTFERDhCRUNDQjZCNDU1MkJFQTc8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjJBNTJBMDEwMENGNERDMTFBQTAzRUZBRjc4RDI5ODlDPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDozMEMyMzlCODJFM0JERDExQjY1MUMwNzNDODY5RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MzUwMEIwQ0M2QzUwMTFEQ0E1OEE4MUNDRUFFQjk2N0Q8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjRBMzhCMjREN0NCNkREMTE5ODk5OUZCM0IyMkVFNUNFPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo1MDg1RkUxQzVDRjFEQzExODQ5OTlCMkQ0NzNCNDBDNTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6NTY5OTMxQUNFRTgyREMxMTk4NkVFQTgzNjFGMTQ3MTE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjU3RDRENjNDMDUzN0UwMTFBNjM1RUJFMzgyMzBCODQxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo1RjgzOTA1RDExRUYxMURCODgxRUE2QkUwNUUyNzZEMTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6NjI1OTE1RTFEMEYyREQxMUIyQUVGODg5ODVDQTU4Njg8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjcwNkY4OEYyMzAzQkREMTFCNjUxQzA3M0M4NjlEMjczPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo5MEFERjdENTM5OEExMURGODYxMTk0MzZBMTdDQjIyNzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6QTFFMjhDNEM1NjI5REMxMTlDNzZCNzZDOEFBMDk4NzQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkE5Rjg5MTI5M0IxQzExREFCNTVCQzI1REIzOTc4NjA2PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpCNTdGQjJFRUM4MEJEQzExOURCQThEMjJDNkE3OUM0NzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6QkQ1NkJGM0FGQzM4REIxMUEwNzhFRjBBNDMwOTAyRDU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkJFREZCQTY5MEM2OERCMTE5NEE0RkFCMjk1MERCMjQ1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpDQUQxM0U4ODMwM0JERDExQjY1MUMwNzNDODY5RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6RDlGRkY3NkJDMThBRTAxMTk3RTJFNkIyMDZFQUIzOTU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkU0NUNENDFBNzdEN0REMTE4NkRFREQ1OEI3N0JFMDkxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpGNkFBNkUxMThCNURFMTExOTE0MUJBNTI3OTk1MzhGMDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTg3MUZFNEFENzFFRTI1QzA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE4NzFGRUVCNTZEMUU3NDNCPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMTgwMTE3NDA3MjA2ODExOEY2MkVCMkFERTQ2RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTkxMDlGQTI5N0E3QTU5MDQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMTgwMTE3NDA3MjA2ODExOTdBNURBRjI1ODNBMEE0QjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMUFCMDhFOEU4RUUzRjAyODk8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4OEM2QTI5ODQ0M0YxMEFDPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMjgwMTE3NDA3MjA2ODExOTEwOUM2NUE3MDQwMTM0MDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MEEwOEJDOTI2MUEyREYxMUJCQjVDMUZFMzRDNjY0OEM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjFDOEU5N0FBOEI0QkRGMTE4OTQxQjEwMTZEQkYxRDE0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDoxRjgzQ0M1NjM2RTFFMDExQjc1MzgyQTY2NTdEMjA4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MzE5RTE0NkRCNDM3RTIxMThENjBEQkI0MTU3NjYyQkU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjM2RThEMTc2QkM3QURGMTFBM0M4QzZFMjExRUE4QkJGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo0RDVFODcxRTE1MTFFMjExOTU1M0RENDcyOUEyMzZDRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NTE0MDRGNDMzOTQ0RTIxMUEyMzlDMDRBRkQ0NDQ4MUU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjUxNTQ2RkREMTMyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo1NDU0NkZERDEzMjA2ODExOTJCMEJBQTkwNERFMEY4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NjM4ODgwRTgwOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjY0ODg4MEU4MDkyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo2NERGNTM3NjM1RTFFMDExQjc1MzgyQTY2NTdEMjA4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NjY4ODgwRTgwOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjY3ODg4MEU4MDkyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo2RUQ1RTlDRDZGQzRERjExQjc1QzlCRTFENUIxNkVBMzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NzNGREFEODU3RUNCRTExMUI1MUVCRkE3RDIwMUNDNEI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjk2MkFGRDIxNjgzOUUyMTE4NzA1ODUzNjA1RUY2MEJBPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpBMzQ3Q0E3MUNFRENFMTExOUJFN0Y0NzJGQzQyQzU4NTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6QTY1Q0FDMUZDOTM3RTIxMThENjBEQkI0MTU3NjYyQkU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkE5Q0NBNkFGRkI0M0UxMTE5RURCRjYzRTA1ODA0MzA0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpCMjQwMUYyQjk2MzhFMjExQTY2MkI0N0U5QjhENzE0RTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6QkIzNTY1RTgxNTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkMyMzU2NUU4MTUyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpDMzczQ0VDMDM2MjA2ODExOEY2MkQwRjcwMTBBQzAyRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6Q0I1NzY4QzhGQjNBRTIxMUFBNDNGMUNGRTNEMkUyNTM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkNGMEY3NzJFOUY5MkUwMTFCMDBBQjc4N0Y4ODIyQjQ2PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpEMDczREU4OURFM0VFMjExQkM2QUZERjZBNEZEMTc1RjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6RDQwNTRFQzExOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkRBQTQ4QUM0NzYzRkUyMTE4M0EyQkZEMTQ2NjBDQTJGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpFMEE0OEFDNDc2M0ZFMjExODNBMkJGRDE0NjYwQ0EyRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6Rjc1RDkxOEExMTIwNjgxMTkyQjA4QkVFMjlDNzVERDI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkY3N0YxMTc0MDcyMDY4MTE4MDgzRUI4M0M2MkJEN0MxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpGNzdGMTE3NDA3MjA2ODExOTEwOUY4RkUyNzcxOEQ1QTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6RkJDNEQyMDQwQTIwNjgxMTkxMDlDQzY0MkM0NEVDMEM8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QmFnPgogICAgICAgICA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTA5PC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjM4PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz4BWge9AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAHGSURBVHja7Nu9ihNRHIbx5/xnJpOZaAKbXWIjwUULkTU2rqgoYqM2FnaWfqAXYGWpjbjVegFiue028aPbzgURFuxUtNMNYkSLOJsx59joPZzA+1zC++PMnOa4EAKA3Xq0ceLd59HaZDo746FARVHiqIos2V451Lv39P71HcC7EII9ePbq+Obr91sha3aSrIEz01qRFLxnVk+hrn5eXT188eHtKzsp0Hrzcfexa+7rNIoSS1JwTmtFoxbwsz/UVdp5+2m0BlwzoPfjtz+bFSWWZgKLLeewNCNrlown/jTQM6BbzVzLJakGitkuSZliJbBgQO6SBKcTFvmBczhLAHIDdOuYr3RNnEs1TSA0JTQlNKEpoSmhCU0JTQlNaEpoSmhKaEJTQlNCE5oSmhKa0JTQlNCEpuYIzbfLfKop4m9/0agBb8DeoN/98u9xoYq0EAIr/e5XYM+A73cuD4bt3GaaJt7aufm7lwZDYGzA6OjBxedPbp5/sbrcrZqpfnMxlafGyeXFav3GuZfH+ktDYORCCAYsAaeAC8ARoAXo7VMEX0VgAnwAtoBt4Jv7/1AeaAMHgAUgE1o0aDUwBnaBX4D/CwAA//8DAOgHcZ21310BAAAAAElFTkSuQmCC'
- image_large_rectangle = b'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/GMzLdsAAFTiaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0xMC0wM1QxMToxNjo1MC0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMTAtMDNUMTE6MTY6NTAtMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTEwLTAzVDExOjE2OjUwLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDo3OTNkNzlhNS0zZTAzLTcwNDMtYmEzMS0wNGZhNTk0MTA1NWM8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo2Y2M2NTVmZC0wNThiLTExZWItOTQ3ZC04N2E5Njc3OWZkYzU8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDplZjg4OTAwZC04M2FiLTA5NDAtOGIwNC02NmZmY2Y4YjBmMDQ8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6ZWY4ODkwMGQtODNhYi0wOTQwLThiMDQtNjZmZmNmOGIwZjA0PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTEwLTAzVDExOjE2OjUwLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjc5M2Q3OWE1LTNlMDMtNzA0My1iYTMxLTA0ZmE1OTQxMDU1Yzwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0xMC0wM1QxMToxNjo1MC0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+CiAgICAgICAgICAgIDxyZGY6QmFnPgogICAgICAgICAgICAgICA8cmRmOmxpPjAwMDE1N0JCNEVDNjZDODMyQ0VBN0Q0OTgxOEYyQkI3PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MEQyMERDMEVCMTBDQkE5Njg5N0M2NzNCRjkwNDI5ODQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4xRDk5RjMzMUY1RkMyOUU0ODU5MkI1OERENENCRkUzMzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjI2QzMwRDNBRTREQjZERTFFN0Y2M0JCQUE4NjBGNEI0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+MkFFRkE4NTk0ODJBRTMxMEYwOEYxNEVCQkU3MUEyNTU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT4zNDBDQUZCNkZCMzIwRDRGREVEMjc0M0ExRjUwNUI2ODwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjQ4NTVBMzI3NzUwOTIzODkwMzQ5NjIwRkU2NUYzNjkxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+NjZBREMzOThERjcwMDQ1RDgxMkU4OUMwNDIzRkFGNTA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT42QjI5MkM4MDQyRTY1QTcxMkZGMTk4NTdEMjhGQTZCRTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPjczNzQ2N0JGQzU2QkFDNTk2Q0M4QkNEOUUzNjk2QUU1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+NzNDMEVENEM3ODE0RTg4RjlBMjQ3NzRFRjdGMTBBODk8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT44MUU0QzY3QjQ5QkFCMzlDNkU5QzExRjQxNUNEMTgyRTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkEzQ0M2RjFEQTFDMTFBMDZDOUExOTEyQURDRDBFRjQ3PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+QTQ3QkZCNkY5NkMxRjBGMjhDMTI5RENCQkZBODRGNkQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5BNTlDQUU4ODNCMzU0RjgyMEQ3OTFEODJCREVGRjE2MDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkFGREUyQkMyMzA1QkUyRTc2Q0RCNTdBNDAwNzM3MEQyPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+Q0Q4RTcxRkQ1REQ3RkM5MjcyNkZFREQ5NDRBREEyMTE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5GM0Y5OURGQjBFMzE5QzUwQzRGNEQ2NUZCM0U1QjU5MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPkY4REE4QjZDRUM5MDI5OTgzMzUxQkEzQzUyQTVCNzREPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjMyMjNhYzg2LWVkZTYtMTFkOS1hZGRiLWNiMWQ2NjAxOWMxNzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo2YjM0YmVlZi1mNDg2LTExZDktOWFiYy1mNmY3MDc0YjFkN2E8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6NmNjNzJkZDQtYzEyMi0xMWRhLTllYTAtYjQxMDIxN2JjNjA0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjc4ZTg3ZmZlLWY5NWEtMTFkYi1hZmE5LWY3OGRhN2FiODZmZjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5NWFkMzRlOC01MTQwLTExZGEtOGFmNi1iNjQ4NmE1YjIwYjI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6YmViNmY0N2UtMjIzNS0xMWRjLWE0NGUtZjZiOGI4MzA4MWQ1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOmU3ZmI1OGNhLTk2NDItMTFkZC04MWEyLWRkMTQxMDNmNDUxNTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MDFGMUEwRjYxMUVGMTFEQjg4MUVBNkJFMDVFMjc2RDE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjA2MDFFMzM5QkFGMkREMTE5QTlEOTEwOTg5NjI4QzVGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDoxODkyOTc1OTlFNUREQzExOEQxOUJGODREMUU2QjZEQTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MTk1MDE1MDhFMkVGMTFERDhCRUNDQjZCNDU1MkJFQTc8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjJBNTJBMDEwMENGNERDMTFBQTAzRUZBRjc4RDI5ODlDPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDozMEMyMzlCODJFM0JERDExQjY1MUMwNzNDODY5RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6MzUwMEIwQ0M2QzUwMTFEQ0E1OEE4MUNDRUFFQjk2N0Q8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjRBMzhCMjREN0NCNkREMTE5ODk5OUZCM0IyMkVFNUNFPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo1MDg1RkUxQzVDRjFEQzExODQ5OTlCMkQ0NzNCNDBDNTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6NTY5OTMxQUNFRTgyREMxMTk4NkVFQTgzNjFGMTQ3MTE8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjU3RDRENjNDMDUzN0UwMTFBNjM1RUJFMzgyMzBCODQxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo1RjgzOTA1RDExRUYxMURCODgxRUE2QkUwNUUyNzZEMTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6NjI1OTE1RTFEMEYyREQxMUIyQUVGODg5ODVDQTU4Njg8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOjcwNkY4OEYyMzAzQkREMTFCNjUxQzA3M0M4NjlEMjczPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDo5MEFERjdENTM5OEExMURGODYxMTk0MzZBMTdDQjIyNzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6QTFFMjhDNEM1NjI5REMxMTlDNzZCNzZDOEFBMDk4NzQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkE5Rjg5MTI5M0IxQzExREFCNTVCQzI1REIzOTc4NjA2PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpCNTdGQjJFRUM4MEJEQzExOURCQThEMjJDNkE3OUM0NzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6QkQ1NkJGM0FGQzM4REIxMUEwNzhFRjBBNDMwOTAyRDU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkJFREZCQTY5MEM2OERCMTE5NEE0RkFCMjk1MERCMjQ1PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpDQUQxM0U4ODMwM0JERDExQjY1MUMwNzNDODY5RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnV1aWQ6RDlGRkY3NkJDMThBRTAxMTk3RTJFNkIyMDZFQUIzOTU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT51dWlkOkU0NUNENDFBNzdEN0REMTE4NkRFREQ1OEI3N0JFMDkxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+dXVpZDpGNkFBNkUxMThCNURFMTExOTE0MUJBNTI3OTk1MzhGMDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTg3MUZFNEFENzFFRTI1QzA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE4NzFGRUVCNTZEMUU3NDNCPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMTgwMTE3NDA3MjA2ODExOEY2MkVCMkFERTQ2RDI3MzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTkxMDlGQTI5N0E3QTU5MDQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAxODAxMTc0MDcyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMTgwMTE3NDA3MjA2ODExOTdBNURBRjI1ODNBMEE0QjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMUFCMDhFOEU4RUUzRjAyODk8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjAyODAxMTc0MDcyMDY4MTE4OEM2QTI5ODQ0M0YxMEFDPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDowMjgwMTE3NDA3MjA2ODExOTEwOUM2NUE3MDQwMTM0MDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MEEwOEJDOTI2MUEyREYxMUJCQjVDMUZFMzRDNjY0OEM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjFDOEU5N0FBOEI0QkRGMTE4OTQxQjEwMTZEQkYxRDE0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDoxRjgzQ0M1NjM2RTFFMDExQjc1MzgyQTY2NTdEMjA4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MzE5RTE0NkRCNDM3RTIxMThENjBEQkI0MTU3NjYyQkU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjM2RThEMTc2QkM3QURGMTFBM0M4QzZFMjExRUE4QkJGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo0RDVFODcxRTE1MTFFMjExOTU1M0RENDcyOUEyMzZDRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NTE0MDRGNDMzOTQ0RTIxMUEyMzlDMDRBRkQ0NDQ4MUU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjUxNTQ2RkREMTMyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo1NDU0NkZERDEzMjA2ODExOTJCMEJBQTkwNERFMEY4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NjM4ODgwRTgwOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjY0ODg4MEU4MDkyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo2NERGNTM3NjM1RTFFMDExQjc1MzgyQTY2NTdEMjA4RDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NjY4ODgwRTgwOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjY3ODg4MEU4MDkyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDo2RUQ1RTlDRDZGQzRERjExQjc1QzlCRTFENUIxNkVBMzwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6NzNGREFEODU3RUNCRTExMUI1MUVCRkE3RDIwMUNDNEI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOjk2MkFGRDIxNjgzOUUyMTE4NzA1ODUzNjA1RUY2MEJBPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpBMzQ3Q0E3MUNFRENFMTExOUJFN0Y0NzJGQzQyQzU4NTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6QTY1Q0FDMUZDOTM3RTIxMThENjBEQkI0MTU3NjYyQkU8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkE5Q0NBNkFGRkI0M0UxMTE5RURCRjYzRTA1ODA0MzA0PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpCMjQwMUYyQjk2MzhFMjExQTY2MkI0N0U5QjhENzE0RTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6QkIzNTY1RTgxNTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkMyMzU2NUU4MTUyMDY4MTE5MkIwQkFBOTA0REUwRjhEPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpDMzczQ0VDMDM2MjA2ODExOEY2MkQwRjcwMTBBQzAyRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6Q0I1NzY4QzhGQjNBRTIxMUFBNDNGMUNGRTNEMkUyNTM8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkNGMEY3NzJFOUY5MkUwMTFCMDBBQjc4N0Y4ODIyQjQ2PC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpEMDczREU4OURFM0VFMjExQkM2QUZERjZBNEZEMTc1RjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6RDQwNTRFQzExOTIwNjgxMTkyQjBCQUE5MDRERTBGOEQ8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkRBQTQ4QUM0NzYzRkUyMTE4M0EyQkZEMTQ2NjBDQTJGPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpFMEE0OEFDNDc2M0ZFMjExODNBMkJGRDE0NjYwQ0EyRjwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6Rjc1RDkxOEExMTIwNjgxMTkyQjA4QkVFMjlDNzVERDI8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaT54bXAuZGlkOkY3N0YxMTc0MDcyMDY4MTE4MDgzRUI4M0M2MkJEN0MxPC9yZGY6bGk+CiAgICAgICAgICAgICAgIDxyZGY6bGk+eG1wLmRpZDpGNzdGMTE3NDA3MjA2ODExOTEwOUY4RkUyNzcxOEQ1QTwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6RkJDNEQyMDQwQTIwNjgxMTkxMDlDQzY0MkM0NEVDMEM8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QmFnPgogICAgICAgICA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTgyPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjU4PC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgCjw/eHBhY2tldCBlbmQ9InciPz48XvJIAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAR0SURBVHja7J2/bxNnHIef93z+EeB62KhqTNRABzeQNUMZytChHVpU/oEydkgkBMrkLcp/AGLI0o3NGy1dqo4sDKxJ1AwVVOCqKHGikGD77Pt28Lmx3ABSFs7H5zl5ucTLq48/et7v+XzOzBinVqsVd3Z2Pj44ODjV6XSmAIcQ6cGCIGjn8/mDSqXycmtrqzP+D24s2K5cLl/Y3d0NgAOgDXSBPmBaT5ECHOABRaAEnDp79uyrVqv1dDSjo8F2pVLp806n0wH2klD3klDHWk+RIjwgB/hJuMNisVhst9t//BduM8PMXLVanQVmgKnkjUJMSsingJlqtTprZs7M8AGWl5dLzWbTA14CbTOz2Wu3LwGLwA9AResnUkQLuA+sPXt4Z9M51wZ2ms3mJ/fu3SvcvHmz48zMzc/PT29sbLQTBYk//e7WnMvlNs99c52gehEv9sCk2CINhu2IPWO/+Sfbvz3A+v2Lf/1692nS3OHly5dL6+vrf/uAF0VRLnHqoUsvnvv6e8JgGp41odfT1lGkZuvo+T5hZRr76lu2f/9lEagn2W1HUXQa8HzAvXjxop9sFIfcCKqfDUId9bSYIj0Y0O3BdouPZmtsw49JsAF6SZadD3iHh4dRMv0YUnGxw3qRFlKkk16Eix1j+79+kmXPH55gfKRnMcTyD5Hi5rb/TaHjYUH7A2s5xqANbRhF+sN9/Fnnv/k9hnaMYhKTPWzst1S9gi0mMtdvC7Yp2CLlwT5BY9u7PhJCpBj/rT2vxhZybCEmwLFNji2y6NgDFdHXsEXGVMSkIiKLKqJxn8ikigwcWyoiMufYUhExuWgqIj6wxpaKiEw6tlREZFFFBtFWY4tUV7YcW0hFBsQGsRpbpJhY4z4hx5aKiCyriMZ9IovB1h00IpMqosYWGW1sObZIfbJP0tgo2GJSc62vrYoPTEV0l7rIpIro1jCRSRXRVERkUkV05VFk1LGlImJy0V3q4gNTkXfZuRBqbCHS4tga94nUB/sEja1HdYhJTvabG9u5d9a9EO8N544y+oZgWxiGbm9vb/T8juWLFecXoNvWIor0kS9i+RLAzujpMAwdYB7A1atXcwyeRT3kfme/hU3PYoUi5gZqokPHez8cg0xWL9De/Qfgp5HcekmW8YH4/PnzADmOfkhk7fDRz7f48jqF+S9wUVd3rIt04HlYvkD31R6vHz0AWBv5ay7JcuzMLPf48ePTV65ciYDXA602Zq/dvgQsAjeAslZUpIgWcB9Ye/bwzqY7cu2pzc1Nf25u7hAzc2ZWqtfr5TEdEWKiurxer5fNrGRmDjPDzHwzC5aWls4weAS1EBM1I1laWjpjZkGSZYbBdmZWMLOw0WiEam4xSU3daDRCMwuTDDszw9nRnNoBeaD4/PnzwtbWVn9/f7/75MmT7urqak/rJ9LCysqKv7CwUAiCoFCr1XIzMzNdoANEJFdtRoM9DHcumZYMX570RKSM4U8B90ZefUYuRY4HezTg3lioFW6RllCPhjvmmGvr/w4AJ8NnvMG503MAAAAASUVORK5CYII'
- image_grey1 = b'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/GMzLdsAADsHaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0xMC0wM1QxMToyOTozMi0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMTAtMDNUMTE6Mjk6MzItMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTEwLTAzVDExOjI5OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDo2Y2Q5MjZlZS0xYWE3LTBlNDEtYTI2ZS04MmMwMGYyN2E2Nzg8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDozMzlhMjcxYS0wNThkLTExZWItOTQ3ZC04N2E5Njc3OWZkYzU8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpjZDY3N2JmMi02YjVjLWU4NDgtYTI0OC1kOGRkNGNkZTBkMzM8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6Y2Q2NzdiZjItNmI1Yy1lODQ4LWEyNDgtZDhkZDRjZGUwZDMzPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTEwLTAzVDExOjI5OjMyLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjZjZDkyNmVlLTFhYTctMGU0MS1hMjZlLTgyYzAwZjI3YTY3ODwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0xMC0wM1QxMToyOTozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+CiAgICAgICAgICAgIDxyZGY6QmFnPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTg3MUZEQjdDNzNFQzdBRjQ8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QmFnPgogICAgICAgICA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+ODI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PkjKk0kAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAgtJREFUeNrsmi1vFFEUhp97Z6b7PYtuNyQYQkIwBNNgoAKBA4FAIJAIdP/BViOQCAQCgUQSBB+GYDZtCGnShKAIgp3dndl05p6L2G2ABrrscgXivGbEuCfvc8+ZyTXM8/Dx03ONZmvHWrtljOmg+WO89yMReVHkk+17d259ADAADx49OZ92T70+c7rXTdMuePB4JfabGAwYyLIhB58+D7Pht8v3797ejYGo0Wz1exvr3XitznCUI14hnhRrDMland7GevegLPvAjRhIrI2uJrUaxWGplP4i4j3VoZDUalgbbQFJDERAuyoFr01cKlUpAC0gigEr3uMU4tJx3h8dgzYGEBFERMmsovmcWzwf52ghV16FfoAU8YjXRq7WyF9ACl60kv+stnjR3XHlVUiOq60gg6gtqnYAtXX9CQVS1Va1/7ep7VTtQFNbGxlGbadfNqGmtjYyzNTWMzKA2l5w2sgQw0YX8mBqayMDqO29npGr5tiPXVU7iNpOZFxVrm2sVTLLtFEEJ5IfgZRpkb/Jx9m1RjtVOkukGGdMi/wVIDHg9vcG/bWktpk612m0UrSZi5tYTDKyr19G+3uDPuAMswsCnSvXb146e+Hidr3e2DTWNhXXiSDz6bR4+3Hwfufl82fvgJFhdpEqZnZjoA3UAa3kghkDTIExMAEq89PLCEjmTwW5GKQDyvmT7wMAzpNJbp+doKQAAAAASUVORK5CYII='
- image_grey2 = b'iVBORw0KGgoAAAANSUhEUgAAAFIAAAAgCAYAAACBxi9RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAADsHaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAyMC0xMC0wM1QxMTozMDoyMi0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMjAtMTAtMDNUMTE6MzA6MjItMDQ6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDIwLTEwLTAzVDExOjMwOjIyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpiZTM1YzVhMi02NDQ3LWY2NGEtYTJkNi04NTM1NGJkYjQ1MWE8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDo1MjZjNTY3NS0wNThkLTExZWItOTQ3ZC04N2E5Njc3OWZkYzU8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDo1NWI1YjZiOC0zZmM1LTU1NGMtYTNjMi01NDI2NjlkYWRlZGY8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6NTViNWI2YjgtM2ZjNS01NTRjLWEzYzItNTQyNjY5ZGFkZWRmPC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDIwLTEwLTAzVDExOjMwOjIyLTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOmJlMzVjNWEyLTY0NDctZjY0YS1hMmQ2LTg1MzU0YmRiNDUxYTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAyMC0xMC0wM1QxMTozMDoyMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDxwaG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+CiAgICAgICAgICAgIDxyZGY6QmFnPgogICAgICAgICAgICAgICA8cmRmOmxpPnhtcC5kaWQ6MDE4MDExNzQwNzIwNjgxMTg3MUZEQjdDNzNFQzdBRjQ8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6QmFnPgogICAgICAgICA8L3Bob3Rvc2hvcDpEb2N1bWVudEFuY2VzdG9ycz4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHRpZmY6T3JpZW50YXRpb24+MTwvdGlmZjpPcmllbnRhdGlvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+ODI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvOojhoAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAdNJREFUeNrsmj9rFEEYh5+ZufV2725zCRG/QI4QYmFjI4JgilQ24sfQwka4QhBByIGNhR/FysJC/NPYCHpuzkLBkD+QEOKd2dtk9x2LvYAgF70DQcj7FLvFdg/v/H4z7BhGPHj8dCmMoo4xdsUYE6OMxXvf915eDNO0/fDenQTAANzvPLnYiGdeLy8tNufmz+OB8qH8himl7e/t0k16B4P+96uP2nc/VgAXRrW1VmuhWYlidg8GiKjF07DWUI1iWq2FZpKsrwE3K0BgrbtercWk2ZFa+gtEPGl2RFifwVq3AgQWcAYauYgampDjosBAHXAWsB6vy3nKyfRlmVg7aiG1Mn2Dl7mpIlXk/ydSVOT0OakT+S+Wtjb29CJFJ1LLRkVqayva2rq0dftzdrc/mpGakZqRKlJRkSpSRZ61I6LIoMhztTIhRVEgIocnIiXL0jc721tqZkJ2tjbJsvQVIA5ws/MXvmLdrSA4V6036tjy56IydhJzNjc2WE8+9T93P9z+0ut+M4AD4murNy4vLl9qV6PwijG2prpOy0U5zNLh2173fefl82fvgL6hvBNUobwx0ADCk+xUxp8MgSEwAH4AufnlowOC0VtF/llkARyP3vwcAJizBUPv/gPvAAAAAElFTkSuQmCC'
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Buttons_Mac.py b/DemoPrograms/Demo_Buttons_Mac.py
index 201746036..90908f6c2 100644
--- a/DemoPrograms/Demo_Buttons_Mac.py
+++ b/DemoPrograms/Demo_Buttons_Mac.py
@@ -3,23 +3,17 @@
import time
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
def show_win():
sg.set_options(border_width=0, margins=(0, 0), element_padding=(5, 3))
frame_layout = [
- [sg.Button(image_data=mac_red,
- button_color=(sg.theme_background_color(),sg.theme_background_color()), key='-exit-'),
+ [sg.Button('', image_data=mac_red,
+ button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='-exit-'),
sg.Button('', image_data=mac_orange,
- button_color=(sg.theme_background_color(),sg.theme_background_color())),
+ button_color=('white', sg.COLOR_SYSTEM_DEFAULT)),
sg.Button('', image_data=mac_green,
- button_color=(sg.theme_background_color(),sg.theme_background_color()), key='-minimize-'),
+ button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='-minimize-'),
sg.Text(' '*40)], ]
layout = [[sg.Frame('', frame_layout)],
@@ -31,12 +25,12 @@ def show_win():
alpha_channel=0, finalize=True)
for i in range(100):
- window.set_alpha(i/100)
+ window.eet_alpha(i/100)
time.sleep(.01)
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED or event == '-exit-':
+ if event is None or event == '-exit-':
break
if event == '-minimize-':
# window.Minimize() # cannot minimize a window with no titlebar
diff --git a/DemoPrograms/Demo_Buttons_Nice_Graphics.py b/DemoPrograms/Demo_Buttons_Nice_Graphics.py
index a7e69cabb..300c9c50d 100644
--- a/DemoPrograms/Demo_Buttons_Nice_Graphics.py
+++ b/DemoPrograms/Demo_Buttons_Nice_Graphics.py
@@ -11,10 +11,6 @@
using the tkinter version of PySimpleGUI (except for crude "Scaling")
The PIL code resizes the button images prior to creating the sg.B
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -30,7 +26,7 @@ def resize_base64_image(image64, size):
'''
image_file = io.BytesIO(base64.b64decode(image64))
img = Image.open(image_file)
- img.thumbnail(size, Image.LANCZOS)
+ img.thumbnail(size, Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format='PNG')
imgbytes = bio.getvalue()
@@ -54,7 +50,7 @@ def GraphicButton(text, key, image_data, color=DEF_BUTTON_COLOR, size=(100, 50))
def ShowMeTheButtons():
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
frame_layout = [[sg.Text('Who says Windows have to be ugly when using tkinter?', size=(45, 3))],
[sg.Text(
diff --git a/DemoPrograms/Demo_Buttons_Realtime.py b/DemoPrograms/Demo_Buttons_Realtime.py
deleted file mode 100644
index 9e02040d3..000000000
--- a/DemoPrograms/Demo_Buttons_Realtime.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-"""
- Demo - Realtime Buttons
-
- Realtime buttons provide a way for you to get a continuous stream of button
- events for as long as a button is held down.
-
- This demo is using a timeout to determine that a button has been released.
- If your application doesn't care when a button is released and only needs to know
- that it's being held down, then you can remove the timeout on the window read call.
-
- Note that your reaction latency will be the same as your timeout value. In this demo
- the timeout is 100, so there will be 100ms between releasing a button and your program detecting
- this has happened.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-def main():
- # The Quit button is being placed in the bottom right corner and the colors are inverted, just for fun
- layout = [[sg.Text('Robotics Remote Control')],
- [sg.Text('Hold Down Button To Move')],
- [sg.Text()],
- [sg.Text(' '),
- sg.RealtimeButton(sg.SYMBOL_UP, key='-FORWARD-')],
- [sg.RealtimeButton(sg.SYMBOL_LEFT, key='-LEFT-'),
- sg.Text(size=(10,1), key='-STATUS-', justification='c', pad=(0,0)),
- sg.RealtimeButton(sg.SYMBOL_RIGHT, key='-RIGHT-')],
- [sg.Text(' '),
- sg.RealtimeButton(sg.SYMBOL_DOWN, key='-DOWN-')],
- [sg.Text()],
- [sg.Column([[sg.Quit(button_color=(sg.theme_button_color()[1], sg.theme_button_color()[0]), focus=True)]], justification='r')]]
-
- window = sg.Window('Robotics Remote Control', layout)
-
- while True:
- # This is the code that reads and updates your window
- event, values = window.read(timeout=100)
- if event in (sg.WIN_CLOSED, 'Quit'):
- break
- if event != sg.TIMEOUT_EVENT:
- # if not a timeout event, then it's a button that's being held down
- window['-STATUS-'].update(event)
- else:
- # A timeout signals that all buttons have been released so clear the status display
- window['-STATUS-'].update('')
-
- window.close()
-
-if __name__ == '__main__':
- sg.theme('dark red')
- main()
diff --git a/DemoPrograms/Demo_CLI_or_GUI.py b/DemoPrograms/Demo_CLI_or_GUI.py
deleted file mode 100644
index 4b2eda521..000000000
--- a/DemoPrograms/Demo_CLI_or_GUI.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
- Demo Command Line Application or GUI Application
-
- If your program is run with arguments, then a command line version is used.
- If no arguments are given, then a GUI is shown that asks for a filename.
-
- http://www.PySimpleGUI.org
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-import sys
-
-def main_cli(filename):
- print(f'Your filename = {filename}')
-
-
-def main_gui():
- filename = sg.popup_get_file('Please enter a filename:')
- main_cli(filename)
-
-if __name__ == '__main__':
- if len(sys.argv) < 2:
- main_gui()
- else:
- main_cli(sys.argv[1])
diff --git a/DemoPrograms/Demo_Calendar.py b/DemoPrograms/Demo_Calendar.py
index 039e5e23c..5d1d6e551 100644
--- a/DemoPrograms/Demo_Calendar.py
+++ b/DemoPrograms/Demo_Calendar.py
@@ -1,28 +1,13 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Simple test harness to demonstate how to use the CalendarButton and the get date popup
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-# sg.theme('Dark Red')
-layout = [[sg.Text('Date Chooser Test Harness', key='-TXT-')],
- [sg.Input(key='-IN-', size=(20,1)), sg.CalendarButton('Cal US No Buttons Location (0,0)', close_when_date_chosen=True, target='-IN-', location=(0,0), no_titlebar=False, )],
- [sg.Input(key='-IN3-', size=(20,1)), sg.CalendarButton('Cal Monday', title='Pick a date any date', no_titlebar=True, close_when_date_chosen=False, target='-IN3-', begin_at_sunday_plus=1, month_names=('студзень', 'люты', 'сакавік', 'красавік', 'май', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'), day_abbreviations=('Дш', 'Шш', 'Шр', 'Бш', 'Жм', 'Иш', 'Жш'))],
- [sg.Input(key='-IN2-', size=(20,1)), sg.CalendarButton('Cal German Feb 2020', target='-IN2-', default_date_m_d_y=(2,None,2020), locale='de_DE', begin_at_sunday_plus=1 )],
- [sg.Input(key='-IN4-', size=(20,1)), sg.CalendarButton('Cal Format %m-%d Jan 2020', target='-IN4-', format='%m-%d', default_date_m_d_y=(1,None,2020), )],
- [sg.Button('Read'), sg.Button('Date Popup'), sg.Exit()]]
-window = sg.Window('window', layout)
+layout = [[sg.Text('Calendar Test')],
+ [sg.Input('', size=(20, 1), key='input')],
+ [sg.CalendarButton('Choose Date', target='input', key='date')],
+ [sg.Ok(key=1)]]
-while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Date Popup':
- sg.popup('You chose:', sg.popup_get_date())
-window.close()
\ No newline at end of file
+window = sg.Window('Calendar', layout, grab_anywhere=False)
+event, values = window.read()
+sg.popup(values['input'])
+windowclose()
diff --git a/DemoPrograms/Demo_Canvas.py b/DemoPrograms/Demo_Canvas.py
index 518cf6b7d..74b63a065 100644
--- a/DemoPrograms/Demo_Canvas.py
+++ b/DemoPrograms/Demo_Canvas.py
@@ -1,12 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
layout = [
[sg.Canvas(size=(150, 150), background_color='red', key='canvas')],
[sg.Text('Change circle color to:'), sg.Button('Red'), sg.Button('Blue')]
@@ -18,7 +12,7 @@
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event in ('Blue', 'Red'):
window['canvas'].TKCanvas.itemconfig(cir, fill=event)
diff --git a/DemoPrograms/Demo_Change_Submits_InputText.py b/DemoPrograms/Demo_Change_Submits_InputText.py
new file mode 100644
index 000000000..f64914c0a
--- /dev/null
+++ b/DemoPrograms/Demo_Change_Submits_InputText.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+"""
+ Demonstrates the new change_submits parameter for inputtext elements
+ It ONLY submits when a button changes the field, not normal user input
+ Be careful on persistent forms to not clear the input
+"""
+layout = [[sg.Text('Test of reading input field')],
+ [sg.Text('This input is normal'), sg.Input()],
+ [sg.Text('This input change submits'),
+ sg.Input(change_submits=True)],
+ [sg.Text('This multiline input change submits'),
+ sg.ML('', change_submits=True)],
+ [sg.Text('This input is normal'),
+ sg.Input(), sg.FileBrowse()],
+ [sg.Text('File Browse submits'),
+ sg.Input(change_submits=True,
+ key='-in1-'), sg.FileBrowse()],
+ [sg.Text('Color Chooser submits'),
+ sg.Input(change_submits=True,
+ key='-in2-'), sg.ColorChooserButton('Color...', target=(sg.ThisRow, -1))],
+ [sg.Text('Folder Browse submits'),
+ sg.Input(change_submits=True,
+ key='-in3-'), sg.FolderBrowse()],
+ [sg.Text('Calendar Chooser submits'),
+ sg.Input(change_submits=True,
+ key='-in4-'), sg.CalendarButton('Date...', target=(sg.ThisRow, -1))],
+ [sg.Text('Disabled input submits'),
+ sg.Input(change_submits=True,
+ disabled=True,
+ key='_in5'), sg.FileBrowse()],
+ [sg.Text('This input clears after submit'),
+ sg.Input(change_submits=True, key='-in6-'), sg.FileBrowse()],
+ [sg.Button('Read')]]
+
+window = sg.Window('Demonstration of InputText with change_submits',
+ layout, auto_size_text=False, default_element_size=(22, 1),
+ text_justification='right')
+
+while True: # Event Loop
+ event, values = window.read()
+ print(event, values)
+ if event is None:
+ break
+
+window.close()
diff --git a/DemoPrograms/Demo_Chat.py b/DemoPrograms/Demo_Chat.py
index deee6e12f..9bfadfa82 100644
--- a/DemoPrograms/Demo_Chat.py
+++ b/DemoPrograms/Demo_Chat.py
@@ -4,14 +4,9 @@
'''
A simple send/response chat window. Add call to your send-routine and print the response
If async responses can come in, then will need to use a different design that uses PySimpleGUI async design pattern
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
'''
-sg.theme('GreenTan') # give our window a spiffy set of colors
+sg.change_look_and_feel('GreenTan') # give our window a spiffy set of colors
layout = [[sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(110, 20), font=('Helvetica 10'))],
@@ -19,15 +14,15 @@
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
-window = sg.Window('Chat window', layout, font=('Helvetica', ' 13'), default_button_element_size=(8,2), use_default_focus=False)
+window = sg.Window('Chat window', layout, font=('Helvetica', ' 13'), default_button_element_size=(8,2))
while True: # The Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'EXIT'): # quit if exit button or X
+ event, value = window.read()
+ if event in (None, 'EXIT'): # quit if exit button or X
break
if event == 'SEND':
- query = values['-QUERY-'].rstrip()
+ query = value['-QUERY-'].rstrip()
# EXECUTE YOUR COMMAND HERE
- print('The command you entered was {}'.format(query), flush=True)
+ print('The command you entered was {}'.format(query))
window.close()
diff --git a/DemoPrograms/Demo_Chat_With_History.py b/DemoPrograms/Demo_Chat_With_History.py
index 6ed8108a3..cd24a6923 100644
--- a/DemoPrograms/Demo_Chat_With_History.py
+++ b/DemoPrograms/Demo_Chat_With_History.py
@@ -9,17 +9,13 @@
Down arrow - scroll down in commands
Escape - clear current command
Control C - exit form
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
def ChatBotWithHistory():
# ------- Make a new Window ------- #
# give our form a spiffy set of colors
- sg.theme('GreenTan')
+ sg.change_look_and_feel('GreenTan')
layout = [[sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(127, 30), font=('Helvetica 10'))],
@@ -52,7 +48,7 @@ def ChatBotWithHistory():
window['query'].update('')
window['history'].update('\n'.join(command_history[-3:]))
- elif event in (sg.WIN_CLOSED, 'EXIT'): # quit if exit event or X
+ elif event in (None, 'EXIT'): # quit if exit event or X
break
elif 'Up' in event and len(command_history):
diff --git a/DemoPrograms/Demo_Chatterbot.py b/DemoPrograms/Demo_Chatterbot.py
index 88444e5de..2a80fa95f 100644
--- a/DemoPrograms/Demo_Chatterbot.py
+++ b/DemoPrograms/Demo_Chatterbot.py
@@ -1,29 +1,19 @@
#!/usr/bin/env python
import PySimpleGUI as sg
+from chatterbot import ChatBot
import chatterbot.utils
'''
Demo_Chatterbot.py
-
-Note - this code was written using version 0.8.7 of Chatterbot... to install:
-
-python -m pip install chatterbot==0.8.7
-
-It still runs fine with the old version.
-
-A GUI wrapped around the Chatterbot package.
+A GUI wrapped arouind the Chatterbot package.
The GUI is used to show progress bars during the training process and
to collect user input that is sent to the chatbot. The reply is displayed in the GUI window
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
# Create the 'Trainer GUI'
# The Trainer GUI consists of a lot of progress bars stacked on top of each other
-sg.theme('GreenTan')
+sg.change_look_and_feel('GreenTan')
# sg.DebugWin()
MAX_PROG_BARS = 20 # number of training sessions
bars = []
@@ -60,32 +50,15 @@ def print_progress_bar(description, iteration_counter, total_items, progress_bar
# redefine the chatbot text based progress bar with a graphical one
chatterbot.utils.print_progress_bar = print_progress_bar
-
-from chatterbot import ChatBot
-from chatterbot.trainers import ChatterBotCorpusTrainer
-
-chatbot = ChatBot('Ron Obvious')
-
-# Create a new trainer for the chatbot
-trainer = ChatterBotCorpusTrainer(chatbot)
-
-# Train based on the english corpus
-trainer.train("chatterbot.corpus.english")
-
-# Train based on english greetings corpus
-trainer.train("chatterbot.corpus.english.greetings")
-
-# Train based on the english conversations corpus
-trainer.train("chatterbot.corpus.english.conversations")
chatbot = ChatBot('Ron Obvious', trainer='chatterbot.trainers.ChatterBotCorpusTrainer')
# Train based on the english corpus
-# chatbot.train("chatterbot.corpus.english")
+chatbot.train("chatterbot.corpus.english")
################# GUI #################
-layout = [[sg.Multiline(size=(80, 20), reroute_stdout=True, echo_stdout_stderr=True)],
- [sg.MLine(size=(70, 5), key='-MLINE IN-', enter_submits=True, do_not_clear=False),
+layout = [[sg.Output(size=(80, 20))],
+ [sg.MLine(size=(70, 5), enter_submits=True),
sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
window = sg.Window('Chat Window', layout,
@@ -93,11 +66,11 @@ def print_progress_bar(description, iteration_counter, total_items, progress_bar
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
while True:
- event, values = window.read()
+ event, (value,) = window.read()
if event != 'SEND':
break
- string = values['-MLINE IN-'].rstrip()
+ string = value.rstrip()
print(' ' + string)
# send the user input to chatbot to get a response
- response = chatbot.get_response(values['-MLINE IN-'].rstrip())
+ response = chatbot.get_response(value.rstrip())
print(response)
diff --git a/DemoPrograms/Demo_Chatterbot_With_TTS.py b/DemoPrograms/Demo_Chatterbot_With_TTS.py
index adffd49c8..c650e8403 100644
--- a/DemoPrograms/Demo_Chatterbot_With_TTS.py
+++ b/DemoPrograms/Demo_Chatterbot_With_TTS.py
@@ -9,26 +9,14 @@
'''
Demo_Chatterbot.py
-
-
-Note - this code was written using version 0.8.7 of Chatterbot... to install:
-
-python -m pip install chatterbot==0.8.7
-
-It still runs fine with the old version.
-
-A GUI wrapped around the Chatterbot package.
+A GUI wrapped arouind the Chatterbot package.
The GUI is used to show progress bars during the training process and
to collect user input that is sent to the chatbot. The reply is displayed in the GUI window
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
# Create the 'Trainer GUI'
# The Trainer GUI consists of a lot of progress bars stacked on top of each other
-sg.theme('NeutralBlue')
+sg.change_look_and_feel('NeutralBlue')
# sg.DebugWin()
MAX_PROG_BARS = 20 # number of training sessions
bars = []
@@ -84,22 +72,22 @@ def speak(text):
################# GUI #################
-layout = [[sg.Multiline(size=(80, 20), reroute_stdout=True, echo_stdout_stderr=True)],
- [sg.MLine(size=(70, 5), key='-MLINE IN-', enter_submits=True, do_not_clear=False),
+layout = [[sg.Output(size=(80, 20))],
+ [sg.MLine(size=(70, 5), enter_submits=True),
sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
-window = sg.Window('Chat Window', layout,
- default_element_size=(30, 2))
+window = sg.Window('Chat Window', layout, default_element_size=(30, 2))
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
while True:
- event, values = window.read()
+ event, (value,) = window.read()
if event != 'SEND':
break
- string = values['-MLINE IN-'].rstrip()
- print(' ' + string)
+ string = value.rstrip()
+ print(' '+string)
# send the user input to chatbot to get a response
- response = chatbot.get_response(values['-MLINE IN-'].rstrip())
+ response = chatbot.get_response(value.rstrip())
print(response)
+ speak(str(response))
window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Checkboxes_Custom.py b/DemoPrograms/Demo_Checkboxes_Custom.py
deleted file mode 100644
index de7e1568c..000000000
--- a/DemoPrograms/Demo_Checkboxes_Custom.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Custom Checkboxes done simply
-
- The Base64 Image encoding feature of PySimpleGUI makes it possible to create beautiful GUIs very simply
-
- These 2 checkboxes required 3 extra lines of code than a normal checkbox.
- 1. Keep track of the current value using the Image Element's Metadata
- 2. Changle / Update the image when clicked
- 3. The Base64 image definition
-
- Enable the event on the Image with the checkbox so that you can take action (flip the value)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- layout = [[sg.Text('Fancy Checkboxes... Simply')],
- [sg.Image(checked, key=('-IMAGE-', 1), metadata=True, enable_events=True), sg.Text(True, enable_events=True, k=('-TEXT-', 1))],
- [sg.Image(unchecked, key=('-IMAGE-', 2), metadata=False, enable_events=True), sg.Text(False, enable_events=True, k=('-TEXT-', 2))],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- window = sg.Window('Custom Checkboxes', layout, font="_ 14")
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # if a checkbox is clicked, flip the vale and the image
- if event[0] in ('-IMAGE-', '-TEXT-'):
- cbox_key = ('-IMAGE-', event[1])
- text_key = ('-TEXT-', event[1])
- window[cbox_key].metadata = not window[cbox_key].metadata
- window[cbox_key].update(checked if window[cbox_key].metadata else unchecked)
- # Update the string next to the checkbox
- window[text_key].update(window[cbox_key].metadata)
-
- window.close()
-
-
-if __name__ == '__main__':
- checked = b'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'
- unchecked = b'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'
- main()
diff --git a/DemoPrograms/Demo_Class_Wrapper.py b/DemoPrograms/Demo_Class_Wrapper.py
deleted file mode 100644
index b5e64b7f2..000000000
--- a/DemoPrograms/Demo_Class_Wrapper.py
+++ /dev/null
@@ -1,109 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Class wrapper
-
- Using a class to encapsulate PySimpleGUI Window creation & event loop
-
- This is NOT a recommended design pattern. It mimics the object oriented design that many OO-based
- GUI frameworks use, but there is no advantage to structuring you code in his manner. It adds
- confusion, not clarity.
-
- The class version is 18 lines of code. The plain version is 13 lines of code.
-
- Two things about the class wrapper jump out as adding confusion:
- 1. Unneccessary fragmentation of the event loop - the button click code is pulled out of the loop entirely
- 2. "self" clutters the code without adding value
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-'''
- MM'""""'YMM dP
- M' .mmm. `M 88
- M MMMMMooM 88 .d8888b. .d8888b. .d8888b.
- M MMMMMMMM 88 88' `88 Y8ooooo. Y8ooooo.
- M. `MMM' .M 88 88. .88 88 88
- MM. .dM dP `88888P8 `88888P' `88888P'
- MMMMMMMMMMM
-
- M""MMMMM""M oo
- M MMMMM M
- M MMMMP M .d8888b. 88d888b. .d8888b. dP .d8888b. 88d888b.
- M MMMM' .M 88ooood8 88' `88 Y8ooooo. 88 88' `88 88' `88
- M MMP' .MM 88. ... 88 88 88 88. .88 88 88
- M .dMMM `88888P' dP `88888P' dP `88888P' dP dP
- MMMMMMMMMMM
-'''
-
-
-class SampleGUI():
-
- def __init__(self):
- self.layout = [[sg.Text('My layout')],
- [sg.Input(key='-IN-')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- self.window = sg.Window('My new window', self.layout)
-
- def run(self):
- while True: # Event Loop
- self.event, self.values = self.window.read()
- if self.event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- if self.event == 'Go':
- self.button_go()
-
- self.window.close()
-
- def button_go(self):
- sg.popup('Go button clicked', 'Input value:', self.values['-IN-'])
-
-
-# Create the class
-my_gui = SampleGUI()
-# run the event loop
-my_gui.run()
-
-'''
- M"""""""`YM dP
- M mmmm. M 88
- M MMMMM M .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88
- M MMMMM M 88' `88 88' `88 88'`88'`88 88' `88 88
- M MMMMM M 88. .88 88 88 88 88 88. .88 88
- M MMMMM M `88888P' dP dP dP dP `88888P8 dP
- MMMMMMMMMMM
-
- M""MMMMM""M oo
- M MMMMM M
- M MMMMP M .d8888b. 88d888b. .d8888b. dP .d8888b. 88d888b.
- M MMMM' .M 88ooood8 88' `88 Y8ooooo. 88 88' `88 88' `88
- M MMP' .MM 88. ... 88 88 88 88. .88 88 88
- M .dMMM `88888P' dP `88888P' dP `88888P' dP dP
- MMMMMMMMMMM
-'''
-
-
-def gui_function():
- layout = [[sg.Text('My layout')],
- [sg.Input(key='-IN-')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- window = sg.Window('My new window', layout)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- if event == 'Go':
- sg.popup('Go button clicked', 'Input value:', values['-IN-'])
-
- window.close()
-
-
-gui_function()
diff --git a/DemoPrograms/Demo_Close_Attempted_Event.py b/DemoPrograms/Demo_Close_Attempted_Event.py
deleted file mode 100644
index c510f9356..000000000
--- a/DemoPrograms/Demo_Close_Attempted_Event.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
- Demo_Close_Attempted_Event
-
- Catches if a window close was tried by user (click "X") and confirms with a popup.
- Requires PySimpleGUI 4.33.0 and later
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-layout = [[sg.Text('Close confirmation demo')],
- [sg.Text('Try closing window with the "X"')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
-window = sg.Window('Window Title', layout, enable_close_attempted_event=True)
-
-while True:
- event, values = window.read()
- print(event, values)
- if (event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT or event == 'Exit') and sg.popup_yes_no('Do you really want to exit?') == 'Yes':
- break
-
-window.close()
diff --git a/DemoPrograms/Demo_Color.py b/DemoPrograms/Demo_Color.py
new file mode 100644
index 000000000..e4382307d
--- /dev/null
+++ b/DemoPrograms/Demo_Color.py
@@ -0,0 +1,1725 @@
+#!/usr/bin/env python
+import sys
+import PySimpleGUI as sg
+
+reverse = {}
+colorhex = {}
+
+colors = {
+ "abbey" : ( 76, 79, 86),
+ "acadia" : ( 27, 20, 4),
+ "acapulco" : (124, 176, 161),
+ "aero blue" : (201, 255, 229),
+ "affair" : (113, 70, 147),
+ "akaroa" : (212, 196, 168),
+ "alabaster" : (250, 250, 250),
+ "albescent white" : (245, 233, 211),
+ "algae green" : (147, 223, 184),
+ "alice blue" : (240, 248, 255),
+ "alizarin crimson" : (227, 38, 54),
+ "allports" : ( 0, 118, 163),
+ "almond" : (238, 217, 196),
+ "almond frost" : (144, 123, 113),
+ "alpine" : (175, 143, 44),
+ "alto" : (219, 219, 219),
+ "aluminium" : (169, 172, 182),
+ "amaranth" : (229, 43, 80),
+ "amazon" : ( 59, 122, 87),
+ "amber" : (255, 191, 0),
+ "americano" : (135, 117, 110),
+ "amethyst" : (153, 102, 204),
+ "amethyst smoke" : (163, 151, 180),
+ "amour" : (249, 234, 243),
+ "amulet" : (123, 159, 128),
+ "anakiwa" : (157, 229, 255),
+ "antique brass" : (200, 138, 101),
+ "antique bronze" : (112, 74, 7),
+ "anzac" : (224, 182, 70),
+ "apache" : (223, 190, 111),
+ "apple" : ( 79, 168, 61),
+ "apple blossom" : (175, 77, 67),
+ "apple green" : (226, 243, 236),
+ "apricot" : (235, 147, 115),
+ "apricot peach" : (251, 206, 177),
+ "apricot white" : (255, 254, 236),
+ "aqua deep" : ( 1, 75, 67),
+ "aqua forest" : ( 95, 167, 119),
+ "aqua haze" : (237, 245, 245),
+ "aqua island" : (161, 218, 215),
+ "aqua spring" : (234, 249, 245),
+ "aqua squeeze" : (232, 245, 242),
+ "aquamarine" : (127, 255, 212),
+ "aquamarine blue" : (113, 217, 226),
+ "arapawa" : ( 17, 12, 108),
+ "armadillo" : ( 67, 62, 55),
+ "arrowtown" : (148, 135, 113),
+ "ash" : (198, 195, 181),
+ "asparagus" : (123, 160, 91),
+ "asphalt" : ( 19, 10, 6),
+ "astra" : (250, 234, 185),
+ "astral" : ( 50, 125, 160),
+ "astronaut" : ( 40, 58, 119),
+ "astronaut blue" : ( 1, 62, 98),
+ "athens gray" : (238, 240, 243),
+ "aths special" : (236, 235, 206),
+ "atlantis" : (151, 205, 45),
+ "atoll" : ( 10, 111, 117),
+ "atomic tangerine" : (255, 153, 102),
+ "au chico" : (151, 96, 93),
+ "aubergine" : ( 59, 9, 16),
+ "australian mint" : (245, 255, 190),
+ "avocado" : (136, 141, 101),
+ "axolotl" : ( 78, 102, 73),
+ "azalea" : (247, 200, 218),
+ "aztec" : ( 13, 28, 25),
+ "azure" : ( 49, 91, 161),
+ "azure radiance" : ( 0, 127, 255),
+ "baby blue" : (224, 255, 255),
+ "bahama blue" : ( 2, 99, 149),
+ "bahia" : (165, 203, 12),
+ "baja white" : (255, 248, 209),
+ "bali hai" : (133, 159, 175),
+ "baltic sea" : ( 42, 38, 48),
+ "bamboo" : (218, 99, 4),
+ "banana mania" : (251, 231, 178),
+ "bandicoot" : (133, 132, 112),
+ "barberry" : (222, 215, 23),
+ "barley corn" : (166, 139, 91),
+ "barley white" : (255, 244, 206),
+ "barossa" : ( 68, 1, 45),
+ "bastille" : ( 41, 33, 48),
+ "battleship gray" : (130, 143, 114),
+ "bay leaf" : (125, 169, 141),
+ "bay of many" : ( 39, 58, 129),
+ "bazaar" : (152, 119, 123),
+ "bean " : ( 61, 12, 2),
+ "beauty bush" : (238, 193, 190),
+ "beaver" : (146, 111, 91),
+ "beeswax" : (254, 242, 199),
+ "beige" : (245, 245, 220),
+ "bermuda" : (125, 216, 198),
+ "bermuda gray" : (107, 139, 162),
+ "beryl green" : (222, 229, 192),
+ "bianca" : (252, 251, 243),
+ "big stone" : ( 22, 42, 64),
+ "bilbao" : ( 50, 124, 20),
+ "biloba flower" : (178, 161, 234),
+ "birch" : ( 55, 48, 33),
+ "bird flower" : (212, 205, 22),
+ "biscay" : ( 27, 49, 98),
+ "bismark" : ( 73, 113, 131),
+ "bison hide" : (193, 183, 164),
+ "bistre" : ( 61, 43, 31),
+ "bitter" : (134, 137, 116),
+ "bitter lemon" : (202, 224, 13),
+ "bittersweet" : (254, 111, 94),
+ "bizarre" : (238, 222, 218),
+ "black" : ( 0, 0, 0),
+ "black bean" : ( 8, 25, 16),
+ "black forest" : ( 11, 19, 4),
+ "black haze" : (246, 247, 247),
+ "black marlin" : ( 62, 44, 28),
+ "black olive" : ( 36, 46, 22),
+ "black pearl" : ( 4, 19, 34),
+ "black rock" : ( 13, 3, 50),
+ "black rose" : (103, 3, 45),
+ "black russian" : ( 10, 0, 28),
+ "black squeeze" : (242, 250, 250),
+ "black white" : (255, 254, 246),
+ "blackberry" : ( 77, 1, 53),
+ "blackcurrant" : ( 50, 41, 58),
+ "blaze orange" : (255, 102, 0),
+ "bleach white" : (254, 243, 216),
+ "bleached cedar" : ( 44, 33, 51),
+ "blizzard blue" : (163, 227, 237),
+ "blossom" : (220, 180, 188),
+ "blue" : ( 0, 0, 255),
+ "blue bayoux" : ( 73, 102, 121),
+ "blue bell" : (153, 153, 204),
+ "blue chalk" : (241, 233, 255),
+ "blue charcoal" : ( 1, 13, 26),
+ "blue chill" : ( 12, 137, 144),
+ "blue diamond" : ( 56, 4, 116),
+ "blue dianne" : ( 32, 72, 82),
+ "blue gem" : ( 44, 14, 140),
+ "blue haze" : (191, 190, 216),
+ "blue lagoon" : ( 1, 121, 135),
+ "blue marguerite" : (118, 102, 198),
+ "blue ribbon" : ( 0, 102, 255),
+ "blue romance" : (210, 246, 222),
+ "blue smoke" : (116, 136, 129),
+ "blue stone" : ( 1, 97, 98),
+ "blue violet" : (100, 86, 183),
+ "blue whale" : ( 4, 46, 76),
+ "blue zodiac" : ( 19, 38, 77),
+ "blumine" : ( 24, 88, 122),
+ "blush" : (180, 70, 104),
+ "blush pink" : (255, 111, 255),
+ "bombay" : (175, 177, 184),
+ "bon jour" : (229, 224, 225),
+ "bondi blue" : ( 0, 149, 182),
+ "bone" : (228, 209, 192),
+ "bordeaux" : ( 92, 1, 32),
+ "bossanova" : ( 78, 42, 90),
+ "boston blue" : ( 59, 145, 180),
+ "botticelli" : (199, 221, 229),
+ "bottle green" : ( 9, 54, 36),
+ "boulder" : (122, 122, 122),
+ "bouquet" : (174, 128, 158),
+ "bourbon" : (186, 111, 30),
+ "bracken" : ( 74, 42, 4),
+ "brandy" : (222, 193, 150),
+ "brandy punch" : (205, 132, 41),
+ "brandy rose" : (187, 137, 131),
+ "breaker bay" : ( 93, 161, 159),
+ "brick red" : (198, 45, 66),
+ "bridal heath" : (255, 250, 244),
+ "bridesmaid" : (254, 240, 236),
+ "bright gray" : ( 60, 65, 81),
+ "bright green" : (102, 255, 0),
+ "bright red" : (177, 0, 0),
+ "bright sun" : (254, 211, 60),
+ "bright turquoise" : ( 8, 232, 222),
+ "brilliant rose" : (246, 83, 166),
+ "brink pink" : (251, 96, 127),
+ "bronco" : (171, 161, 150),
+ "bronze" : ( 63, 33, 9),
+ "bronze olive" : ( 78, 66, 12),
+ "bronzetone" : ( 77, 64, 15),
+ "broom" : (255, 236, 19),
+ "brown" : (150, 75, 0),
+ "brown bramble" : ( 89, 40, 4),
+ "brown derby" : ( 73, 38, 21),
+ "brown pod" : ( 64, 24, 1),
+ "brown rust" : (175, 89, 62),
+ "brown tumbleweed" : ( 55, 41, 14),
+ "bubbles" : (231, 254, 255),
+ "buccaneer" : ( 98, 47, 48),
+ "bud" : (168, 174, 156),
+ "buddha gold" : (193, 160, 4),
+ "buff" : (240, 220, 130),
+ "bulgarian rose" : ( 72, 6, 7),
+ "bull shot" : (134, 77, 30),
+ "bunker" : ( 13, 17, 23),
+ "bunting" : ( 21, 31, 76),
+ "burgundy" : (144, 0, 32),
+ "burnham" : ( 0, 46, 32),
+ "burning orange" : (255, 112, 52),
+ "burning sand" : (217, 147, 118),
+ "burnt maroon" : ( 66, 3, 3),
+ "burnt orange" : (204, 85, 0),
+ "burnt sienna" : (233, 116, 81),
+ "burnt umber" : (138, 51, 36),
+ "bush" : ( 13, 46, 28),
+ "buttercup" : (243, 173, 22),
+ "buttered rum" : (161, 117, 13),
+ "butterfly bush" : ( 98, 78, 154),
+ "buttermilk" : (255, 241, 181),
+ "buttery white" : (255, 252, 234),
+ "cab sav" : ( 77, 10, 24),
+ "cabaret" : (217, 73, 114),
+ "cabbage pont" : ( 63, 76, 58),
+ "cactus" : ( 88, 113, 86),
+ "cadet blue" : (169, 178, 195),
+ "cadillac" : (176, 76, 106),
+ "cafe royale" : (111, 68, 12),
+ "calico" : (224, 192, 149),
+ "california" : (254, 157, 4),
+ "calypso" : ( 49, 114, 141),
+ "camarone" : ( 0, 88, 26),
+ "camelot" : (137, 52, 86),
+ "cameo" : (217, 185, 155),
+ "camouflage" : ( 60, 57, 16),
+ "camouflage green" : (120, 134, 107),
+ "can can" : (213, 145, 164),
+ "canary" : (243, 251, 98),
+ "candlelight" : (252, 217, 23),
+ "candy corn" : (251, 236, 93),
+ "cannon black" : ( 37, 23, 6),
+ "cannon pink" : (137, 67, 103),
+ "cape cod" : ( 60, 68, 67),
+ "cape honey" : (254, 229, 172),
+ "cape palliser" : (162, 102, 69),
+ "caper" : (220, 237, 180),
+ "caramel" : (255, 221, 175),
+ "cararra" : (238, 238, 232),
+ "cardin green" : ( 1, 54, 28),
+ "cardinal" : (196, 30, 58),
+ "cardinal pink" : (140, 5, 94),
+ "careys pink" : (210, 158, 170),
+ "caribbean green" : ( 0, 204, 153),
+ "carissma" : (234, 136, 168),
+ "carla" : (243, 255, 216),
+ "carmine" : (150, 0, 24),
+ "carnaby tan" : ( 92, 46, 1),
+ "carnation" : (249, 90, 97),
+ "carnation pink" : (255, 166, 201),
+ "carousel pink" : (249, 224, 237),
+ "carrot orange" : (237, 145, 33),
+ "casablanca" : (248, 184, 83),
+ "casal" : ( 47, 97, 104),
+ "cascade" : (139, 169, 165),
+ "cashmere" : (230, 190, 165),
+ "casper" : (173, 190, 209),
+ "castro" : ( 82, 0, 31),
+ "catalina blue" : ( 6, 42, 120),
+ "catskill white" : (238, 246, 247),
+ "cavern pink" : (227, 190, 190),
+ "cedar" : ( 62, 28, 20),
+ "cedar wood finish" : (113, 26, 0),
+ "celadon" : (172, 225, 175),
+ "celery" : (184, 194, 93),
+ "celeste" : (209, 210, 202),
+ "cello" : ( 30, 56, 91),
+ "celtic" : ( 22, 50, 34),
+ "cement" : (141, 118, 98),
+ "ceramic" : (252, 255, 249),
+ "cerise" : (218, 50, 135),
+ "cerise red" : (222, 49, 99),
+ "cerulean" : ( 2, 164, 211),
+ "cerulean blue" : ( 42, 82, 190),
+ "chablis" : (255, 244, 243),
+ "chalet green" : ( 81, 110, 61),
+ "chalky" : (238, 215, 148),
+ "chambray" : ( 53, 78, 140),
+ "chamois" : (237, 220, 177),
+ "champagne" : (250, 236, 204),
+ "chantilly" : (248, 195, 223),
+ "charade" : ( 41, 41, 55),
+ "chardon" : (255, 243, 241),
+ "chardonnay" : (255, 205, 140),
+ "charlotte" : (186, 238, 249),
+ "charm" : (212, 116, 148),
+ "chartreuse" : (127, 255, 0),
+ "chartreuse yellow" : (223, 255, 0),
+ "chateau green" : ( 64, 168, 96),
+ "chatelle" : (189, 179, 199),
+ "chathams blue" : ( 23, 85, 121),
+ "chelsea cucumber" : (131, 170, 93),
+ "chelsea gem" : (158, 83, 2),
+ "chenin" : (223, 205, 111),
+ "cherokee" : (252, 218, 152),
+ "cherry pie" : ( 42, 3, 89),
+ "cherrywood" : (101, 26, 20),
+ "cherub" : (248, 217, 233),
+ "chestnut" : (185, 78, 72),
+ "chestnut rose" : (205, 92, 92),
+ "chetwode blue" : (133, 129, 217),
+ "chicago" : ( 93, 92, 88),
+ "chiffon" : (241, 255, 200),
+ "chilean fire" : (247, 119, 3),
+ "chilean heath" : (255, 253, 230),
+ "china ivory" : (252, 255, 231),
+ "chino" : (206, 199, 167),
+ "chinook" : (168, 227, 189),
+ "chocolate" : ( 55, 2, 2),
+ "christalle" : ( 51, 3, 107),
+ "christi" : (103, 167, 18),
+ "christine" : (231, 115, 10),
+ "chrome white" : (232, 241, 212),
+ "cinder" : ( 14, 14, 24),
+ "cinderella" : (253, 225, 220),
+ "cinnabar" : (227, 66, 52),
+ "cinnamon" : (123, 63, 0),
+ "cioccolato" : ( 85, 40, 12),
+ "citrine white" : (250, 247, 214),
+ "citron" : (158, 169, 31),
+ "citrus" : (161, 197, 10),
+ "clairvoyant" : ( 72, 6, 86),
+ "clam shell" : (212, 182, 175),
+ "claret" : (127, 23, 52),
+ "classic rose" : (251, 204, 231),
+ "clay ash" : (189, 200, 179),
+ "clay creek" : (138, 131, 96),
+ "clear day" : (233, 255, 253),
+ "clementine" : (233, 110, 0),
+ "clinker" : ( 55, 29, 9),
+ "cloud" : (199, 196, 191),
+ "cloud burst" : ( 32, 46, 84),
+ "cloudy" : (172, 165, 159),
+ "clover" : ( 56, 73, 16),
+ "cobalt" : ( 0, 71, 171),
+ "cocoa bean" : ( 72, 28, 28),
+ "cocoa brown" : ( 48, 31, 30),
+ "coconut cream" : (248, 247, 220),
+ "cod gray" : ( 11, 11, 11),
+ "coffee" : (112, 101, 85),
+ "coffee bean" : ( 42, 20, 14),
+ "cognac" : (159, 56, 29),
+ "cola" : ( 63, 37, 0),
+ "cold purple" : (171, 160, 217),
+ "cold turkey" : (206, 186, 186),
+ "colonial white" : (255, 237, 188),
+ "comet" : ( 92, 93, 117),
+ "como" : ( 81, 124, 102),
+ "conch" : (201, 217, 210),
+ "concord" : (124, 123, 122),
+ "concrete" : (242, 242, 242),
+ "confetti" : (233, 215, 90),
+ "congo brown" : ( 89, 55, 55),
+ "congress blue" : ( 2, 71, 142),
+ "conifer" : (172, 221, 77),
+ "contessa" : (198, 114, 107),
+ "copper" : (184, 115, 51),
+ "copper canyon" : (126, 58, 21),
+ "copper rose" : (153, 102, 102),
+ "copper rust" : (148, 71, 71),
+ "copperfield" : (218, 138, 103),
+ "coral" : (255, 127, 80),
+ "coral red" : (255, 64, 64),
+ "coral reef" : (199, 188, 162),
+ "coral tree" : (168, 107, 107),
+ "corduroy" : ( 96, 110, 104),
+ "coriander" : (196, 208, 176),
+ "cork" : ( 64, 41, 29),
+ "corn" : (231, 191, 5),
+ "corn field" : (248, 250, 205),
+ "corn harvest" : (139, 107, 11),
+ "cornflower" : (147, 204, 234),
+ "cornflower blue" : (100, 149, 237),
+ "cornflower lilac" : (255, 176, 172),
+ "corvette" : (250, 211, 162),
+ "cosmic" : (118, 57, 93),
+ "cosmos" : (255, 216, 217),
+ "costa del sol" : ( 97, 93, 48),
+ "cotton candy" : (255, 183, 213),
+ "cotton seed" : (194, 189, 182),
+ "county green" : ( 1, 55, 26),
+ "cowboy" : ( 77, 40, 45),
+ "crail" : (185, 81, 64),
+ "cranberry" : (219, 80, 121),
+ "crater brown" : ( 70, 36, 37),
+ "cream" : (255, 253, 208),
+ "cream brulee" : (255, 229, 160),
+ "cream can" : (245, 200, 92),
+ "creole" : ( 30, 15, 4),
+ "crete" : (115, 120, 41),
+ "crimson" : (220, 20, 60),
+ "crocodile" : (115, 109, 88),
+ "crown of thorns" : (119, 31, 31),
+ "crowshead" : ( 28, 18, 8),
+ "cruise" : (181, 236, 223),
+ "crusoe" : ( 0, 72, 22),
+ "crusta" : (253, 123, 51),
+ "cumin" : (146, 67, 33),
+ "cumulus" : (253, 255, 213),
+ "cupid" : (251, 190, 218),
+ "curious blue" : ( 37, 150, 209),
+ "cutty sark" : ( 80, 118, 114),
+ "cyan / aqua" : ( 0, 255, 255),
+ "cyprus" : ( 0, 62, 64),
+ "daintree" : ( 1, 39, 49),
+ "dairy cream" : (249, 228, 188),
+ "daisy bush" : ( 79, 35, 152),
+ "dallas" : (110, 75, 38),
+ "dandelion" : (254, 216, 93),
+ "danube" : ( 96, 147, 209),
+ "dark blue" : ( 0, 0, 200),
+ "dark burgundy" : (119, 15, 5),
+ "dark ebony" : ( 60, 32, 5),
+ "dark fern" : ( 10, 72, 13),
+ "dark tan" : (102, 16, 16),
+ "dawn" : (166, 162, 154),
+ "dawn pink" : (243, 233, 229),
+ "de york" : (122, 196, 136),
+ "deco" : (210, 218, 151),
+ "deep blue" : ( 34, 8, 120),
+ "deep blush" : (228, 118, 152),
+ "deep bronze" : ( 74, 48, 4),
+ "deep cerulean" : ( 0, 123, 167),
+ "deep cove" : ( 5, 16, 64),
+ "deep fir" : ( 0, 41, 0),
+ "deep forest green" : ( 24, 45, 9),
+ "deep koamaru" : ( 27, 18, 123),
+ "deep oak" : ( 65, 32, 16),
+ "deep sapphire" : ( 8, 37, 103),
+ "deep sea" : ( 1, 130, 107),
+ "deep sea green" : ( 9, 88, 89),
+ "deep teal" : ( 0, 53, 50),
+ "del rio" : (176, 154, 149),
+ "dell" : ( 57, 100, 19),
+ "delta" : (164, 164, 157),
+ "deluge" : (117, 99, 168),
+ "denim" : ( 21, 96, 189),
+ "derby" : (255, 238, 216),
+ "desert" : (174, 96, 32),
+ "desert sand" : (237, 201, 175),
+ "desert storm" : (248, 248, 247),
+ "dew" : (234, 255, 254),
+ "di serria" : (219, 153, 94),
+ "diesel" : ( 19, 0, 0),
+ "dingley" : ( 93, 119, 71),
+ "disco" : (135, 21, 80),
+ "dixie" : (226, 148, 24),
+ "dodger blue" : ( 30, 144, 255),
+ "dolly" : (249, 255, 139),
+ "dolphin" : (100, 96, 119),
+ "domino" : (142, 119, 94),
+ "don juan" : ( 93, 76, 81),
+ "donkey brown" : (166, 146, 121),
+ "dorado" : (107, 87, 85),
+ "double colonial white" : (238, 227, 173),
+ "double pearl lusta" : (252, 244, 208),
+ "double spanish white" : (230, 215, 185),
+ "dove gray" : (109, 108, 108),
+ "downriver" : ( 9, 34, 86),
+ "downy" : (111, 208, 197),
+ "driftwood" : (175, 135, 81),
+ "drover" : (253, 247, 173),
+ "dull lavender" : (168, 153, 230),
+ "dune" : ( 56, 53, 51),
+ "dust storm" : (229, 204, 201),
+ "dusty gray" : (168, 152, 155),
+ "eagle" : (182, 186, 164),
+ "earls green" : (201, 185, 59),
+ "early dawn" : (255, 249, 230),
+ "east bay" : ( 65, 76, 125),
+ "east side" : (172, 145, 206),
+ "eastern blue" : ( 30, 154, 176),
+ "ebb" : (233, 227, 227),
+ "ebony" : ( 12, 11, 29),
+ "ebony clay" : ( 38, 40, 59),
+ "eclipse" : ( 49, 28, 23),
+ "ecru white" : (245, 243, 229),
+ "ecstasy" : (250, 120, 20),
+ "eden" : ( 16, 88, 82),
+ "edgewater" : (200, 227, 215),
+ "edward" : (162, 174, 171),
+ "egg sour" : (255, 244, 221),
+ "egg white" : (255, 239, 193),
+ "eggplant" : ( 97, 64, 81),
+ "el paso" : ( 30, 23, 8),
+ "el salva" : (143, 62, 51),
+ "electric lime" : (204, 255, 0),
+ "electric violet" : (139, 0, 255),
+ "elephant" : ( 18, 52, 71),
+ "elf green" : ( 8, 131, 112),
+ "elm" : ( 28, 124, 125),
+ "emerald" : ( 80, 200, 120),
+ "eminence" : (108, 48, 130),
+ "emperor" : ( 81, 70, 73),
+ "empress" : (129, 115, 119),
+ "endeavour" : ( 0, 86, 167),
+ "energy yellow" : (248, 221, 92),
+ "english holly" : ( 2, 45, 21),
+ "english walnut" : ( 62, 43, 35),
+ "envy" : (139, 166, 144),
+ "equator" : (225, 188, 100),
+ "espresso" : ( 97, 39, 24),
+ "eternity" : ( 33, 26, 14),
+ "eucalyptus" : ( 39, 138, 91),
+ "eunry" : (207, 163, 157),
+ "evening sea" : ( 2, 78, 70),
+ "everglade" : ( 28, 64, 46),
+ "faded jade" : ( 66, 121, 119),
+ "fair pink" : (255, 239, 236),
+ "falcon" : (127, 98, 109),
+ "fall green" : (236, 235, 189),
+ "falu red" : (128, 24, 24),
+ "fantasy" : (250, 243, 240),
+ "fedora" : (121, 106, 120),
+ "feijoa" : (159, 221, 140),
+ "fern" : ( 99, 183, 108),
+ "fern frond" : (101, 114, 32),
+ "fern green" : ( 79, 121, 66),
+ "ferra" : (112, 79, 80),
+ "festival" : (251, 233, 108),
+ "feta" : (240, 252, 234),
+ "fiery orange" : (179, 82, 19),
+ "finch" : ( 98, 102, 73),
+ "finlandia" : ( 85, 109, 86),
+ "finn" : (105, 45, 84),
+ "fiord" : ( 64, 81, 105),
+ "fire" : (170, 66, 3),
+ "fire bush" : (232, 153, 40),
+ "firefly" : ( 14, 42, 48),
+ "flame pea" : (218, 91, 56),
+ "flamenco" : (255, 125, 7),
+ "flamingo" : (242, 85, 42),
+ "flax" : (238, 220, 130),
+ "flax smoke" : (123, 130, 101),
+ "flesh" : (255, 203, 164),
+ "flint" : (111, 106, 97),
+ "flirt" : (162, 0, 109),
+ "flush mahogany" : (202, 52, 53),
+ "flush orange" : (255, 127, 0),
+ "foam" : (216, 252, 250),
+ "fog" : (215, 208, 255),
+ "foggy gray" : (203, 202, 182),
+ "forest green" : ( 34, 139, 34),
+ "forget me not" : (255, 241, 238),
+ "fountain blue" : ( 86, 180, 190),
+ "frangipani" : (255, 222, 179),
+ "french gray" : (189, 189, 198),
+ "french lilac" : (236, 199, 238),
+ "french pass" : (189, 237, 253),
+ "french rose" : (246, 74, 138),
+ "fresh eggplant" : (153, 0, 102),
+ "friar gray" : (128, 126, 121),
+ "fringy flower" : (177, 226, 193),
+ "froly" : (245, 117, 132),
+ "frost" : (237, 245, 221),
+ "frosted mint" : (219, 255, 248),
+ "frostee" : (228, 246, 231),
+ "fruit salad" : ( 79, 157, 93),
+ "fuchsia blue" : (122, 88, 193),
+ "fuchsia pink" : (193, 84, 193),
+ "fuego" : (190, 222, 13),
+ "fuel yellow" : (236, 169, 39),
+ "fun blue" : ( 25, 89, 168),
+ "fun green" : ( 1, 109, 57),
+ "fuscous gray" : ( 84, 83, 77),
+ "fuzzy wuzzy brown" : (196, 86, 85),
+ "gable green" : ( 22, 53, 49),
+ "gallery" : (239, 239, 239),
+ "galliano" : (220, 178, 12),
+ "gamboge" : (228, 155, 15),
+ "geebung" : (209, 143, 27),
+ "genoa" : ( 21, 115, 107),
+ "geraldine" : (251, 137, 137),
+ "geyser" : (212, 223, 226),
+ "ghost" : (199, 201, 213),
+ "gigas" : ( 82, 60, 148),
+ "gimblet" : (184, 181, 106),
+ "gin" : (232, 242, 235),
+ "gin fizz" : (255, 249, 226),
+ "givry" : (248, 228, 191),
+ "glacier" : (128, 179, 196),
+ "glade green" : ( 97, 132, 95),
+ "go ben" : (114, 109, 78),
+ "goblin" : ( 61, 125, 82),
+ "gold" : (255, 215, 0),
+ "gold drop" : (241, 130, 0),
+ "gold sand" : (230, 190, 138),
+ "gold tips" : (222, 186, 19),
+ "golden bell" : (226, 137, 19),
+ "golden dream" : (240, 213, 45),
+ "golden fizz" : (245, 251, 61),
+ "golden glow" : (253, 226, 149),
+ "golden grass" : (218, 165, 32),
+ "golden sand" : (240, 219, 125),
+ "golden tainoi" : (255, 204, 92),
+ "goldenrod" : (252, 214, 103),
+ "gondola" : ( 38, 20, 20),
+ "gordons green" : ( 11, 17, 7),
+ "gorse" : (255, 241, 79),
+ "gossamer" : ( 6, 155, 129),
+ "gossip" : (210, 248, 176),
+ "gothic" : (109, 146, 161),
+ "governor bay" : ( 47, 60, 179),
+ "grain brown" : (228, 213, 183),
+ "grandis" : (255, 211, 140),
+ "granite green" : (141, 137, 116),
+ "granny apple" : (213, 246, 227),
+ "granny smith" : (132, 160, 160),
+ "granny smith apple" : (157, 224, 147),
+ "grape" : ( 56, 26, 81),
+ "graphite" : ( 37, 22, 7),
+ "gravel" : ( 74, 68, 75),
+ "gray" : (128, 128, 128),
+ "gray asparagus" : ( 70, 89, 69),
+ "gray chateau" : (162, 170, 179),
+ "gray nickel" : (195, 195, 189),
+ "gray nurse" : (231, 236, 230),
+ "gray olive" : (169, 164, 145),
+ "gray suit" : (193, 190, 205),
+ "green" : ( 0, 255, 0),
+ "green haze" : ( 1, 163, 104),
+ "green house" : ( 36, 80, 15),
+ "green kelp" : ( 37, 49, 28),
+ "green leaf" : ( 67, 106, 13),
+ "green mist" : (203, 211, 176),
+ "green pea" : ( 29, 97, 66),
+ "green smoke" : (164, 175, 110),
+ "green spring" : (184, 193, 177),
+ "green vogue" : ( 3, 43, 82),
+ "green waterloo" : ( 16, 20, 5),
+ "green white" : (232, 235, 224),
+ "green yellow" : (173, 255, 47),
+ "grenadier" : (213, 70, 0),
+ "guardsman red" : (186, 1, 1),
+ "gulf blue" : ( 5, 22, 87),
+ "gulf stream" : (128, 179, 174),
+ "gull gray" : (157, 172, 183),
+ "gum leaf" : (182, 211, 191),
+ "gumbo" : (124, 161, 166),
+ "gun powder" : ( 65, 66, 87),
+ "gunsmoke" : (130, 134, 133),
+ "gurkha" : (154, 149, 119),
+ "hacienda" : (152, 129, 27),
+ "hairy heath" : (107, 42, 20),
+ "haiti" : ( 27, 16, 53),
+ "half baked" : (133, 196, 204),
+ "half colonial white" : (253, 246, 211),
+ "half dutch white" : (254, 247, 222),
+ "half spanish white" : (254, 244, 219),
+ "half and half" : (255, 254, 225),
+ "hampton" : (229, 216, 175),
+ "harlequin" : ( 63, 255, 0),
+ "harp" : (230, 242, 234),
+ "harvest gold" : (224, 185, 116),
+ "havelock blue" : ( 85, 144, 217),
+ "hawaiian tan" : (157, 86, 22),
+ "hawkes blue" : (212, 226, 252),
+ "heath" : ( 84, 16, 18),
+ "heather" : (183, 195, 208),
+ "heathered gray" : (182, 176, 149),
+ "heavy metal" : ( 43, 50, 40),
+ "heliotrope" : (223, 115, 255),
+ "hemlock" : ( 94, 93, 59),
+ "hemp" : (144, 120, 116),
+ "hibiscus" : (182, 49, 108),
+ "highland" : (111, 142, 99),
+ "hillary" : (172, 165, 134),
+ "himalaya" : (106, 93, 27),
+ "hint of green" : (230, 255, 233),
+ "hint of red" : (251, 249, 249),
+ "hint of yellow" : (250, 253, 228),
+ "hippie blue" : ( 88, 154, 175),
+ "hippie green" : ( 83, 130, 75),
+ "hippie pink" : (174, 69, 96),
+ "hit gray" : (161, 173, 181),
+ "hit pink" : (255, 171, 129),
+ "hokey pokey" : (200, 165, 40),
+ "hoki" : (101, 134, 159),
+ "holly" : ( 1, 29, 19),
+ "hollywood cerise" : (244, 0, 161),
+ "honey flower" : ( 79, 28, 112),
+ "honeysuckle" : (237, 252, 132),
+ "hopbush" : (208, 109, 161),
+ "horizon" : ( 90, 135, 160),
+ "horses neck" : ( 96, 73, 19),
+ "hot cinnamon" : (210, 105, 30),
+ "hot pink" : (255, 105, 180),
+ "hot toddy" : (179, 128, 7),
+ "humming bird" : (207, 249, 243),
+ "hunter green" : ( 22, 29, 16),
+ "hurricane" : (135, 124, 123),
+ "husk" : (183, 164, 88),
+ "ice cold" : (177, 244, 231),
+ "iceberg" : (218, 244, 240),
+ "illusion" : (246, 164, 201),
+ "inch worm" : (176, 227, 19),
+ "indian khaki" : (195, 176, 145),
+ "indian tan" : ( 77, 30, 1),
+ "indigo" : ( 79, 105, 198),
+ "indochine" : (194, 107, 3),
+ "international klein blue" : ( 0, 47, 167),
+ "international orange" : (255, 79, 0),
+ "irish coffee" : ( 95, 61, 38),
+ "iroko" : ( 67, 49, 32),
+ "iron" : (212, 215, 217),
+ "ironside gray" : (103, 102, 98),
+ "ironstone" : (134, 72, 60),
+ "island spice" : (255, 252, 238),
+ "ivory" : (255, 255, 240),
+ "jacaranda" : ( 46, 3, 41),
+ "jacarta" : ( 58, 42, 106),
+ "jacko bean" : ( 46, 25, 5),
+ "jacksons purple" : ( 32, 32, 141),
+ "jade" : ( 0, 168, 107),
+ "jaffa" : (239, 134, 63),
+ "jagged ice" : (194, 232, 229),
+ "jagger" : ( 53, 14, 87),
+ "jaguar" : ( 8, 1, 16),
+ "jambalaya" : ( 91, 48, 19),
+ "janna" : (244, 235, 211),
+ "japanese laurel" : ( 10, 105, 6),
+ "japanese maple" : (120, 1, 9),
+ "japonica" : (216, 124, 99),
+ "java" : ( 31, 194, 194),
+ "jazzberry jam" : (165, 11, 94),
+ "jelly bean" : ( 41, 123, 154),
+ "jet stream" : (181, 210, 206),
+ "jewel" : ( 18, 107, 64),
+ "jon" : ( 59, 31, 31),
+ "jonquil" : (238, 255, 154),
+ "jordy blue" : (138, 185, 241),
+ "judge gray" : ( 84, 67, 51),
+ "jumbo" : (124, 123, 130),
+ "jungle green" : ( 41, 171, 135),
+ "jungle mist" : (180, 207, 211),
+ "juniper" : (109, 146, 146),
+ "just right" : (236, 205, 185),
+ "kabul" : ( 94, 72, 62),
+ "kaitoke green" : ( 0, 70, 32),
+ "kangaroo" : (198, 200, 189),
+ "karaka" : ( 30, 22, 9),
+ "karry" : (255, 234, 212),
+ "kashmir blue" : ( 80, 112, 150),
+ "kelp" : ( 69, 73, 54),
+ "kenyan copper" : (124, 28, 5),
+ "keppel" : ( 58, 176, 158),
+ "key lime pie" : (191, 201, 33),
+ "khaki" : (240, 230, 140),
+ "kidnapper" : (225, 234, 212),
+ "kilamanjaro" : ( 36, 12, 2),
+ "killarney" : ( 58, 106, 71),
+ "kimberly" : (115, 108, 159),
+ "kingfisher daisy" : ( 62, 4, 128),
+ "kobi" : (231, 159, 196),
+ "kokoda" : (110, 109, 87),
+ "korma" : (143, 75, 14),
+ "koromiko" : (255, 189, 95),
+ "kournikova" : (255, 231, 114),
+ "kumera" : (136, 98, 33),
+ "la palma" : ( 54, 135, 22),
+ "la rioja" : (179, 193, 16),
+ "las palmas" : (198, 230, 16),
+ "laser" : (200, 181, 104),
+ "laser lemon" : (255, 255, 102),
+ "laurel" : (116, 147, 120),
+ "lavender" : (181, 126, 220),
+ "lavender gray" : (189, 187, 215),
+ "lavender magenta" : (238, 130, 238),
+ "lavender pink" : (251, 174, 210),
+ "lavender purple" : (150, 123, 182),
+ "lavender rose" : (251, 160, 227),
+ "lavender blush" : (255, 240, 245),
+ "leather" : (150, 112, 89),
+ "lemon" : (253, 233, 16),
+ "lemon chiffon" : (255, 250, 205),
+ "lemon ginger" : (172, 158, 34),
+ "lemon grass" : (155, 158, 143),
+ "light apricot" : (253, 213, 177),
+ "light orchid" : (226, 156, 210),
+ "light wisteria" : (201, 160, 220),
+ "lightning yellow" : (252, 192, 30),
+ "lilac" : (200, 162, 200),
+ "lilac bush" : (152, 116, 211),
+ "lily" : (200, 170, 191),
+ "lily white" : (231, 248, 255),
+ "lima" : (118, 189, 23),
+ "lime" : (191, 255, 0),
+ "limeade" : (111, 157, 2),
+ "limed ash" : (116, 125, 99),
+ "limed oak" : (172, 138, 86),
+ "limed spruce" : ( 57, 72, 81),
+ "linen" : (250, 240, 230),
+ "link water" : (217, 228, 245),
+ "lipstick" : (171, 5, 99),
+ "lisbon brown" : ( 66, 57, 33),
+ "livid brown" : ( 77, 40, 46),
+ "loafer" : (238, 244, 222),
+ "loblolly" : (189, 201, 206),
+ "lochinvar" : ( 44, 140, 132),
+ "lochmara" : ( 0, 126, 199),
+ "locust" : (168, 175, 142),
+ "log cabin" : ( 36, 42, 29),
+ "logan" : (170, 169, 205),
+ "lola" : (223, 207, 219),
+ "london hue" : (190, 166, 195),
+ "lonestar" : (109, 1, 1),
+ "lotus" : (134, 60, 60),
+ "loulou" : ( 70, 11, 65),
+ "lucky" : (175, 159, 28),
+ "lucky point" : ( 26, 26, 104),
+ "lunar green" : ( 60, 73, 58),
+ "luxor gold" : (167, 136, 44),
+ "lynch" : (105, 126, 154),
+ "mabel" : (217, 247, 255),
+ "macaroni and cheese" : (255, 185, 123),
+ "madang" : (183, 240, 190),
+ "madison" : ( 9, 37, 93),
+ "madras" : ( 63, 48, 2),
+ "magenta / fuchsia" : (255, 0, 255),
+ "magic mint" : (170, 240, 209),
+ "magnolia" : (248, 244, 255),
+ "mahogany" : ( 78, 6, 6),
+ "mai tai" : (176, 102, 8),
+ "maize" : (245, 213, 160),
+ "makara" : (137, 125, 109),
+ "mako" : ( 68, 73, 84),
+ "malachite" : ( 11, 218, 81),
+ "malibu" : (125, 200, 247),
+ "mallard" : ( 35, 52, 24),
+ "malta" : (189, 178, 161),
+ "mamba" : (142, 129, 144),
+ "manatee" : (141, 144, 161),
+ "mandalay" : (173, 120, 27),
+ "mandy" : (226, 84, 101),
+ "mandys pink" : (242, 195, 178),
+ "mango tango" : (231, 114, 0),
+ "manhattan" : (245, 201, 153),
+ "mantis" : (116, 195, 101),
+ "mantle" : (139, 156, 144),
+ "manz" : (238, 239, 120),
+ "mardi gras" : ( 53, 0, 54),
+ "marigold" : (185, 141, 40),
+ "marigold yellow" : (251, 232, 112),
+ "mariner" : ( 40, 106, 205),
+ "maroon" : (128, 0, 0),
+ "maroon flush" : (195, 33, 72),
+ "maroon oak" : ( 82, 12, 23),
+ "marshland" : ( 11, 15, 8),
+ "martini" : (175, 160, 158),
+ "martinique" : ( 54, 48, 80),
+ "marzipan" : (248, 219, 157),
+ "masala" : ( 64, 59, 56),
+ "matisse" : ( 27, 101, 157),
+ "matrix" : (176, 93, 84),
+ "matterhorn" : ( 78, 59, 65),
+ "mauve" : (224, 176, 255),
+ "mauvelous" : (240, 145, 169),
+ "maverick" : (216, 194, 213),
+ "medium carmine" : (175, 64, 53),
+ "medium purple" : (147, 112, 219),
+ "medium red violet" : (187, 51, 133),
+ "melanie" : (228, 194, 213),
+ "melanzane" : ( 48, 5, 41),
+ "melon" : (254, 186, 173),
+ "melrose" : (199, 193, 255),
+ "mercury" : (229, 229, 229),
+ "merino" : (246, 240, 230),
+ "merlin" : ( 65, 60, 55),
+ "merlot" : (131, 25, 35),
+ "metallic bronze" : ( 73, 55, 27),
+ "metallic copper" : (113, 41, 29),
+ "meteor" : (208, 125, 18),
+ "meteorite" : ( 60, 31, 118),
+ "mexican red" : (167, 37, 37),
+ "mid gray" : ( 95, 95, 110),
+ "midnight" : ( 1, 22, 53),
+ "midnight blue" : ( 0, 51, 102),
+ "midnight moss" : ( 4, 16, 4),
+ "mikado" : ( 45, 37, 16),
+ "milan" : (250, 255, 164),
+ "milano red" : (184, 17, 4),
+ "milk punch" : (255, 246, 212),
+ "millbrook" : ( 89, 68, 51),
+ "mimosa" : (248, 253, 211),
+ "mindaro" : (227, 249, 136),
+ "mine shaft" : ( 50, 50, 50),
+ "mineral green" : ( 63, 93, 83),
+ "ming" : ( 54, 116, 125),
+ "minsk" : ( 63, 48, 127),
+ "mint green" : (152, 255, 152),
+ "mint julep" : (241, 238, 193),
+ "mint tulip" : (196, 244, 235),
+ "mirage" : ( 22, 25, 40),
+ "mischka" : (209, 210, 221),
+ "mist gray" : (196, 196, 188),
+ "mobster" : (127, 117, 137),
+ "moccaccino" : (110, 29, 20),
+ "mocha" : (120, 45, 25),
+ "mojo" : (192, 71, 55),
+ "mona lisa" : (255, 161, 148),
+ "monarch" : (139, 7, 35),
+ "mondo" : ( 74, 60, 48),
+ "mongoose" : (181, 162, 127),
+ "monsoon" : (138, 131, 137),
+ "monte carlo" : (131, 208, 198),
+ "monza" : (199, 3, 30),
+ "moody blue" : (127, 118, 211),
+ "moon glow" : (252, 254, 218),
+ "moon mist" : (220, 221, 204),
+ "moon raker" : (214, 206, 246),
+ "morning glory" : (158, 222, 224),
+ "morocco brown" : ( 68, 29, 0),
+ "mortar" : ( 80, 67, 81),
+ "mosque" : ( 3, 106, 110),
+ "moss green" : (173, 223, 173),
+ "mountain meadow" : ( 26, 179, 133),
+ "mountain mist" : (149, 147, 150),
+ "mountbatten pink" : (153, 122, 141),
+ "muddy waters" : (183, 142, 92),
+ "muesli" : (170, 139, 91),
+ "mulberry" : (197, 75, 140),
+ "mulberry wood" : ( 92, 5, 54),
+ "mule fawn" : (140, 71, 47),
+ "mulled wine" : ( 78, 69, 98),
+ "mustard" : (255, 219, 88),
+ "my pink" : (214, 145, 136),
+ "my sin" : (255, 179, 31),
+ "mystic" : (226, 235, 237),
+ "nandor" : ( 75, 93, 82),
+ "napa" : (172, 164, 148),
+ "narvik" : (237, 249, 241),
+ "natural gray" : (139, 134, 128),
+ "navajo white" : (255, 222, 173),
+ "navy blue" : ( 0, 0, 128),
+ "nebula" : (203, 219, 214),
+ "negroni" : (255, 226, 197),
+ "neon carrot" : (255, 153, 51),
+ "nepal" : (142, 171, 193),
+ "neptune" : (124, 183, 187),
+ "nero" : ( 20, 6, 0),
+ "nevada" : (100, 110, 117),
+ "new orleans" : (243, 214, 157),
+ "new york pink" : (215, 131, 127),
+ "niagara" : ( 6, 161, 137),
+ "night rider" : ( 31, 18, 15),
+ "night shadz" : (170, 55, 90),
+ "nile blue" : ( 25, 55, 81),
+ "nobel" : (183, 177, 177),
+ "nomad" : (186, 177, 162),
+ "norway" : (168, 189, 159),
+ "nugget" : (197, 153, 34),
+ "nutmeg" : (129, 66, 44),
+ "nutmeg wood finish" : (104, 54, 0),
+ "oasis" : (254, 239, 206),
+ "observatory" : ( 2, 134, 111),
+ "ocean green" : ( 65, 170, 120),
+ "ochre" : (204, 119, 34),
+ "off green" : (230, 248, 243),
+ "off yellow" : (254, 249, 227),
+ "oil" : ( 40, 30, 21),
+ "old brick" : (144, 30, 30),
+ "old copper" : (114, 74, 47),
+ "old gold" : (207, 181, 59),
+ "old lace" : (253, 245, 230),
+ "old lavender" : (121, 104, 120),
+ "old rose" : (192, 128, 129),
+ "olive" : (128, 128, 0),
+ "olive drab" : (107, 142, 35),
+ "olive green" : (181, 179, 92),
+ "olive haze" : (139, 132, 112),
+ "olivetone" : (113, 110, 16),
+ "olivine" : (154, 185, 115),
+ "onahau" : (205, 244, 255),
+ "onion" : ( 47, 39, 14),
+ "opal" : (169, 198, 194),
+ "opium" : (142, 111, 112),
+ "oracle" : ( 55, 116, 117),
+ "orange" : (255, 104, 31),
+ "orange peel" : (255, 160, 0),
+ "orange roughy" : (196, 87, 25),
+ "orange white" : (254, 252, 237),
+ "orchid" : (218, 112, 214),
+ "orchid white" : (255, 253, 243),
+ "oregon" : (155, 71, 3),
+ "orient" : ( 1, 94, 133),
+ "oriental pink" : (198, 145, 145),
+ "orinoco" : (243, 251, 212),
+ "oslo gray" : (135, 141, 145),
+ "ottoman" : (233, 248, 237),
+ "outer space" : ( 45, 56, 58),
+ "outrageous orange" : (255, 96, 55),
+ "oxford blue" : ( 56, 69, 85),
+ "oxley" : (119, 158, 134),
+ "oyster bay" : (218, 250, 255),
+ "oyster pink" : (233, 206, 205),
+ "paarl" : (166, 85, 41),
+ "pablo" : (119, 111, 97),
+ "pacific blue" : ( 0, 157, 196),
+ "pacifika" : (119, 129, 32),
+ "paco" : ( 65, 31, 16),
+ "padua" : (173, 230, 196),
+ "pale canary" : (255, 255, 153),
+ "pale leaf" : (192, 211, 185),
+ "pale oyster" : (152, 141, 119),
+ "pale prim" : (253, 254, 184),
+ "pale rose" : (255, 225, 242),
+ "pale sky" : (110, 119, 131),
+ "pale slate" : (195, 191, 193),
+ "palm green" : ( 9, 35, 15),
+ "palm leaf" : ( 25, 51, 14),
+ "pampas" : (244, 242, 238),
+ "panache" : (234, 246, 238),
+ "pancho" : (237, 205, 171),
+ "papaya whip" : (255, 239, 213),
+ "paprika" : (141, 2, 38),
+ "paradiso" : ( 49, 125, 130),
+ "parchment" : (241, 233, 210),
+ "paris daisy" : (255, 244, 110),
+ "paris m" : ( 38, 5, 106),
+ "paris white" : (202, 220, 212),
+ "parsley" : ( 19, 79, 25),
+ "pastel green" : (119, 221, 119),
+ "pastel pink" : (255, 209, 220),
+ "patina" : ( 99, 154, 143),
+ "pattens blue" : (222, 245, 255),
+ "paua" : ( 38, 3, 104),
+ "pavlova" : (215, 196, 152),
+ "peach" : (255, 229, 180),
+ "peach cream" : (255, 240, 219),
+ "peach orange" : (255, 204, 153),
+ "peach schnapps" : (255, 220, 214),
+ "peach yellow" : (250, 223, 173),
+ "peanut" : (120, 47, 22),
+ "pear" : (209, 226, 49),
+ "pearl bush" : (232, 224, 213),
+ "pearl lusta" : (252, 244, 220),
+ "peat" : (113, 107, 86),
+ "pelorous" : ( 62, 171, 191),
+ "peppermint" : (227, 245, 225),
+ "perano" : (169, 190, 242),
+ "perfume" : (208, 190, 248),
+ "periglacial blue" : (225, 230, 214),
+ "periwinkle" : (204, 204, 255),
+ "periwinkle gray" : (195, 205, 230),
+ "persian blue" : ( 28, 57, 187),
+ "persian green" : ( 0, 166, 147),
+ "persian indigo" : ( 50, 18, 122),
+ "persian pink" : (247, 127, 190),
+ "persian plum" : (112, 28, 28),
+ "persian red" : (204, 51, 51),
+ "persian rose" : (254, 40, 162),
+ "persimmon" : (255, 107, 83),
+ "peru tan" : (127, 58, 2),
+ "pesto" : (124, 118, 49),
+ "petite orchid" : (219, 150, 144),
+ "pewter" : (150, 168, 161),
+ "pharlap" : (163, 128, 123),
+ "picasso" : (255, 243, 157),
+ "pickled bean" : (110, 72, 38),
+ "pickled bluewood" : ( 49, 68, 89),
+ "picton blue" : ( 69, 177, 232),
+ "pig pink" : (253, 215, 228),
+ "pigeon post" : (175, 189, 217),
+ "pigment indigo" : ( 75, 0, 130),
+ "pine cone" : (109, 94, 84),
+ "pine glade" : (199, 205, 144),
+ "pine green" : ( 1, 121, 111),
+ "pine tree" : ( 23, 31, 4),
+ "pink" : (255, 192, 203),
+ "pink flamingo" : (255, 102, 255),
+ "pink flare" : (225, 192, 200),
+ "pink lace" : (255, 221, 244),
+ "pink lady" : (255, 241, 216),
+ "pink salmon" : (255, 145, 164),
+ "pink swan" : (190, 181, 183),
+ "piper" : (201, 99, 35),
+ "pipi" : (254, 244, 204),
+ "pippin" : (255, 225, 223),
+ "pirate gold" : (186, 127, 3),
+ "pistachio" : (157, 194, 9),
+ "pixie green" : (192, 216, 182),
+ "pizazz" : (255, 144, 0),
+ "pizza" : (201, 148, 21),
+ "plantation" : ( 39, 80, 75),
+ "plum" : (132, 49, 121),
+ "pohutukawa" : (143, 2, 28),
+ "polar" : (229, 249, 246),
+ "polo blue" : (141, 168, 204),
+ "pomegranate" : (243, 71, 35),
+ "pompadour" : (102, 0, 69),
+ "porcelain" : (239, 242, 243),
+ "porsche" : (234, 174, 105),
+ "port gore" : ( 37, 31, 79),
+ "portafino" : (255, 255, 180),
+ "portage" : (139, 159, 238),
+ "portica" : (249, 230, 99),
+ "pot pourri" : (245, 231, 226),
+ "potters clay" : (140, 87, 56),
+ "powder ash" : (188, 201, 194),
+ "powder blue" : (176, 224, 230),
+ "prairie sand" : (154, 56, 32),
+ "prelude" : (208, 192, 229),
+ "prim" : (240, 226, 236),
+ "primrose" : (237, 234, 153),
+ "provincial pink" : (254, 245, 241),
+ "prussian blue" : ( 0, 49, 83),
+ "puce" : (204, 136, 153),
+ "pueblo" : (125, 44, 20),
+ "puerto rico" : ( 63, 193, 170),
+ "pumice" : (194, 202, 196),
+ "pumpkin" : (255, 117, 24),
+ "pumpkin skin" : (177, 97, 11),
+ "punch" : (220, 67, 51),
+ "punga" : ( 77, 61, 20),
+ "purple" : (102, 0, 153),
+ "purple heart" : (101, 45, 193),
+ "purple mountain's majesty" : (150, 120, 182),
+ "purple pizzazz" : (255, 0, 204),
+ "putty" : (231, 205, 140),
+ "quarter pearl lusta" : (255, 253, 244),
+ "quarter spanish white" : (247, 242, 225),
+ "quicksand" : (189, 151, 142),
+ "quill gray" : (214, 214, 209),
+ "quincy" : ( 98, 63, 45),
+ "racing green" : ( 12, 25, 17),
+ "radical red" : (255, 53, 94),
+ "raffia" : (234, 218, 184),
+ "rainee" : (185, 200, 172),
+ "rajah" : (247, 182, 104),
+ "rangitoto" : ( 46, 50, 34),
+ "rangoon green" : ( 28, 30, 19),
+ "raven" : (114, 123, 137),
+ "raw sienna" : (210, 125, 70),
+ "raw umber" : (115, 74, 18),
+ "razzle dazzle rose" : (255, 51, 204),
+ "razzmatazz" : (227, 11, 92),
+ "rebel" : ( 60, 18, 6),
+ "red" : (255, 0, 0),
+ "red beech" : (123, 56, 1),
+ "red berry" : (142, 0, 0),
+ "red damask" : (218, 106, 65),
+ "red devil" : (134, 1, 17),
+ "red orange" : (255, 63, 52),
+ "red oxide" : (110, 9, 2),
+ "red ribbon" : (237, 10, 63),
+ "red robin" : (128, 52, 31),
+ "red stage" : (208, 95, 4),
+ "red violet" : (199, 21, 133),
+ "redwood" : ( 93, 30, 15),
+ "reef" : (201, 255, 162),
+ "reef gold" : (159, 130, 28),
+ "regal blue" : ( 1, 63, 106),
+ "regent gray" : (134, 148, 159),
+ "regent st blue" : (170, 214, 230),
+ "remy" : (254, 235, 243),
+ "reno sand" : (168, 101, 21),
+ "resolution blue" : ( 0, 35, 135),
+ "revolver" : ( 44, 22, 50),
+ "rhino" : ( 46, 63, 98),
+ "rice cake" : (255, 254, 240),
+ "rice flower" : (238, 255, 226),
+ "rich gold" : (168, 83, 7),
+ "rio grande" : (187, 208, 9),
+ "ripe lemon" : (244, 216, 28),
+ "ripe plum" : ( 65, 0, 86),
+ "riptide" : (139, 230, 216),
+ "river bed" : ( 67, 76, 89),
+ "rob roy" : (234, 198, 116),
+ "robin's egg blue" : ( 0, 204, 204),
+ "rock" : ( 77, 56, 51),
+ "rock blue" : (158, 177, 205),
+ "rock spray" : (186, 69, 12),
+ "rodeo dust" : (201, 178, 155),
+ "rolling stone" : (116, 125, 131),
+ "roman" : (222, 99, 96),
+ "roman coffee" : (121, 93, 76),
+ "romance" : (255, 254, 253),
+ "romantic" : (255, 210, 183),
+ "ronchi" : (236, 197, 78),
+ "roof terracotta" : (166, 47, 32),
+ "rope" : (142, 77, 30),
+ "rose" : (255, 0, 127),
+ "rose bud" : (251, 178, 163),
+ "rose bud cherry" : (128, 11, 71),
+ "rose fog" : (231, 188, 180),
+ "rose white" : (255, 246, 245),
+ "rose of sharon" : (191, 85, 0),
+ "rosewood" : (101, 0, 11),
+ "roti" : (198, 168, 75),
+ "rouge" : (162, 59, 108),
+ "royal blue" : ( 65, 105, 225),
+ "royal heath" : (171, 52, 114),
+ "royal purple" : (107, 63, 160),
+ "rum" : (121, 105, 137),
+ "rum swizzle" : (249, 248, 228),
+ "russet" : (128, 70, 27),
+ "russett" : (117, 90, 87),
+ "rust" : (183, 65, 14),
+ "rustic red" : ( 72, 4, 4),
+ "rusty nail" : (134, 86, 10),
+ "saddle" : ( 76, 48, 36),
+ "saddle brown" : ( 88, 52, 1),
+ "saffron" : (244, 196, 48),
+ "saffron mango" : (249, 191, 88),
+ "sage" : (158, 165, 135),
+ "sahara" : (183, 162, 20),
+ "sahara sand" : (241, 231, 136),
+ "sail" : (184, 224, 249),
+ "salem" : ( 9, 127, 75),
+ "salmon" : (255, 140, 105),
+ "salomie" : (254, 219, 141),
+ "salt box" : (104, 94, 110),
+ "saltpan" : (241, 247, 242),
+ "sambuca" : ( 58, 32, 16),
+ "san felix" : ( 11, 98, 7),
+ "san juan" : ( 48, 75, 106),
+ "san marino" : ( 69, 108, 172),
+ "sand dune" : (130, 111, 101),
+ "sandal" : (170, 141, 111),
+ "sandrift" : (171, 145, 122),
+ "sandstone" : (121, 109, 98),
+ "sandwisp" : (245, 231, 162),
+ "sandy beach" : (255, 234, 200),
+ "sandy brown" : (244, 164, 96),
+ "sangria" : (146, 0, 10),
+ "sanguine brown" : (141, 61, 56),
+ "santa fe" : (177, 109, 82),
+ "santas gray" : (159, 160, 177),
+ "sapling" : (222, 212, 164),
+ "sapphire" : ( 47, 81, 158),
+ "saratoga" : ( 85, 91, 16),
+ "satin linen" : (230, 228, 212),
+ "sauvignon" : (255, 245, 243),
+ "sazerac" : (255, 244, 224),
+ "scampi" : (103, 95, 166),
+ "scandal" : (207, 250, 244),
+ "scarlet" : (255, 36, 0),
+ "scarlet gum" : ( 67, 21, 96),
+ "scarlett" : (149, 0, 21),
+ "scarpa flow" : ( 88, 85, 98),
+ "schist" : (169, 180, 151),
+ "school bus yellow" : (255, 216, 0),
+ "schooner" : (139, 132, 126),
+ "science blue" : ( 0, 102, 204),
+ "scooter" : ( 46, 191, 212),
+ "scorpion" : (105, 95, 98),
+ "scotch mist" : (255, 251, 220),
+ "screamin' green" : (102, 255, 102),
+ "sea buckthorn" : (251, 161, 41),
+ "sea green" : ( 46, 139, 87),
+ "sea mist" : (197, 219, 202),
+ "sea nymph" : (120, 163, 156),
+ "sea pink" : (237, 152, 158),
+ "seagull" : (128, 204, 234),
+ "seance" : (115, 30, 143),
+ "seashell" : (241, 241, 241),
+ "seashell peach" : (255, 245, 238),
+ "seaweed" : ( 27, 47, 17),
+ "selago" : (240, 238, 253),
+ "selective yellow" : (255, 186, 0),
+ "sepia" : (112, 66, 20),
+ "sepia black" : ( 43, 2, 2),
+ "sepia skin" : (158, 91, 64),
+ "serenade" : (255, 244, 232),
+ "shadow" : (131, 112, 80),
+ "shadow green" : (154, 194, 184),
+ "shady lady" : (170, 165, 169),
+ "shakespeare" : ( 78, 171, 209),
+ "shalimar" : (251, 255, 186),
+ "shamrock" : ( 51, 204, 153),
+ "shark" : ( 37, 39, 44),
+ "sherpa blue" : ( 0, 73, 80),
+ "sherwood green" : ( 2, 64, 44),
+ "shilo" : (232, 185, 179),
+ "shingle fawn" : (107, 78, 49),
+ "ship cove" : (120, 139, 186),
+ "ship gray" : ( 62, 58, 68),
+ "shiraz" : (178, 9, 49),
+ "shocking" : (226, 146, 192),
+ "shocking pink" : (252, 15, 192),
+ "shuttle gray" : ( 95, 102, 114),
+ "siam" : (100, 106, 84),
+ "sidecar" : (243, 231, 187),
+ "silk" : (189, 177, 168),
+ "silver" : (192, 192, 192),
+ "silver chalice" : (172, 172, 172),
+ "silver rust" : (201, 192, 187),
+ "silver sand" : (191, 193, 194),
+ "silver tree" : (102, 181, 143),
+ "sinbad" : (159, 215, 211),
+ "siren" : (122, 1, 58),
+ "sirocco" : (113, 128, 128),
+ "sisal" : (211, 203, 186),
+ "skeptic" : (202, 230, 218),
+ "sky blue" : (118, 215, 234),
+ "slate gray" : (112, 128, 144),
+ "smalt" : ( 0, 51, 153),
+ "smalt blue" : ( 81, 128, 143),
+ "smoky" : ( 96, 91, 115),
+ "snow drift" : (247, 250, 247),
+ "snow flurry" : (228, 255, 209),
+ "snowy mint" : (214, 255, 219),
+ "snuff" : (226, 216, 237),
+ "soapstone" : (255, 251, 249),
+ "soft amber" : (209, 198, 180),
+ "soft peach" : (245, 237, 239),
+ "solid pink" : (137, 56, 67),
+ "solitaire" : (254, 248, 226),
+ "solitude" : (234, 246, 255),
+ "sorbus" : (253, 124, 7),
+ "sorrell brown" : (206, 185, 143),
+ "soya bean" : (106, 96, 81),
+ "spanish green" : (129, 152, 133),
+ "spectra" : ( 47, 90, 87),
+ "spice" : (106, 68, 46),
+ "spicy mix" : (136, 83, 66),
+ "spicy mustard" : (116, 100, 13),
+ "spicy pink" : (129, 110, 113),
+ "spindle" : (182, 209, 234),
+ "spray" : (121, 222, 236),
+ "spring green" : ( 0, 255, 127),
+ "spring leaves" : ( 87, 131, 99),
+ "spring rain" : (172, 203, 177),
+ "spring sun" : (246, 255, 220),
+ "spring wood" : (248, 246, 241),
+ "sprout" : (193, 215, 176),
+ "spun pearl" : (170, 171, 183),
+ "squirrel" : (143, 129, 118),
+ "st tropaz" : ( 45, 86, 155),
+ "stack" : (138, 143, 138),
+ "star dust" : (159, 159, 156),
+ "stark white" : (229, 215, 189),
+ "starship" : (236, 242, 69),
+ "steel blue" : ( 70, 130, 180),
+ "steel gray" : ( 38, 35, 53),
+ "stiletto" : (156, 51, 54),
+ "stonewall" : (146, 133, 115),
+ "storm dust" : (100, 100, 99),
+ "storm gray" : (113, 116, 134),
+ "stratos" : ( 0, 7, 65),
+ "straw" : (212, 191, 141),
+ "strikemaster" : (149, 99, 135),
+ "stromboli" : ( 50, 93, 82),
+ "studio" : (113, 74, 178),
+ "submarine" : (186, 199, 201),
+ "sugar cane" : (249, 255, 246),
+ "sulu" : (193, 240, 124),
+ "summer green" : (150, 187, 171),
+ "sun" : (251, 172, 19),
+ "sundance" : (201, 179, 91),
+ "sundown" : (255, 177, 179),
+ "sunflower" : (228, 212, 34),
+ "sunglo" : (225, 104, 101),
+ "sunglow" : (255, 204, 51),
+ "sunset orange" : (254, 76, 64),
+ "sunshade" : (255, 158, 44),
+ "supernova" : (255, 201, 1),
+ "surf" : (187, 215, 193),
+ "surf crest" : (207, 229, 210),
+ "surfie green" : ( 12, 122, 121),
+ "sushi" : (135, 171, 57),
+ "suva gray" : (136, 131, 135),
+ "swamp" : ( 0, 27, 28),
+ "swamp green" : (172, 183, 142),
+ "swans down" : (220, 240, 234),
+ "sweet corn" : (251, 234, 140),
+ "sweet pink" : (253, 159, 162),
+ "swirl" : (211, 205, 197),
+ "swiss coffee" : (221, 214, 213),
+ "sycamore" : (144, 141, 57),
+ "tabasco" : (160, 39, 18),
+ "tacao" : (237, 179, 129),
+ "tacha" : (214, 197, 98),
+ "tahiti gold" : (233, 124, 7),
+ "tahuna sands" : (238, 240, 200),
+ "tall poppy" : (179, 45, 41),
+ "tallow" : (168, 165, 137),
+ "tamarillo" : (153, 22, 19),
+ "tamarind" : ( 52, 21, 21),
+ "tan" : (210, 180, 140),
+ "tan hide" : (250, 157, 90),
+ "tana" : (217, 220, 193),
+ "tangaroa" : ( 3, 22, 60),
+ "tangerine" : (242, 133, 0),
+ "tango" : (237, 122, 28),
+ "tapa" : (123, 120, 116),
+ "tapestry" : (176, 94, 129),
+ "tara" : (225, 246, 232),
+ "tarawera" : ( 7, 58, 80),
+ "tasman" : (207, 220, 207),
+ "taupe" : ( 72, 60, 50),
+ "taupe gray" : (179, 175, 149),
+ "tawny port" : (105, 37, 69),
+ "te papa green" : ( 30, 67, 60),
+ "tea" : (193, 186, 176),
+ "tea green" : (208, 240, 192),
+ "teak" : (177, 148, 97),
+ "teal" : ( 0, 128, 128),
+ "teal blue" : ( 4, 66, 89),
+ "temptress" : ( 59, 0, 11),
+ "tenn" : (205, 87, 0),
+ "tequila" : (255, 230, 199),
+ "terracotta" : (226, 114, 91),
+ "texas" : (248, 249, 156),
+ "texas rose" : (255, 181, 85),
+ "thatch" : (182, 157, 152),
+ "thatch green" : ( 64, 61, 25),
+ "thistle" : (216, 191, 216),
+ "thistle green" : (204, 202, 168),
+ "thunder" : ( 51, 41, 47),
+ "thunderbird" : (192, 43, 24),
+ "tia maria" : (193, 68, 14),
+ "tiara" : (195, 209, 209),
+ "tiber" : ( 6, 53, 55),
+ "tickle me pink" : (252, 128, 165),
+ "tidal" : (241, 255, 173),
+ "tide" : (191, 184, 176),
+ "timber green" : ( 22, 50, 44),
+ "timberwolf" : (217, 214, 207),
+ "titan white" : (240, 238, 255),
+ "toast" : (154, 110, 97),
+ "tobacco brown" : (113, 93, 71),
+ "toledo" : ( 58, 0, 32),
+ "tolopea" : ( 27, 2, 69),
+ "tom thumb" : ( 63, 88, 59),
+ "tonys pink" : (231, 159, 140),
+ "topaz" : (124, 119, 138),
+ "torch red" : (253, 14, 53),
+ "torea bay" : ( 15, 45, 158),
+ "tory blue" : ( 20, 80, 170),
+ "tosca" : (141, 63, 63),
+ "totem pole" : (153, 27, 7),
+ "tower gray" : (169, 189, 191),
+ "tradewind" : ( 95, 179, 172),
+ "tranquil" : (230, 255, 255),
+ "travertine" : (255, 253, 232),
+ "tree poppy" : (252, 156, 29),
+ "treehouse" : ( 59, 40, 32),
+ "trendy green" : (124, 136, 26),
+ "trendy pink" : (140, 100, 149),
+ "trinidad" : (230, 78, 3),
+ "tropical blue" : (195, 221, 249),
+ "tropical rain forest" : ( 0, 117, 94),
+ "trout" : ( 74, 78, 90),
+ "true v" : (138, 115, 214),
+ "tuatara" : ( 54, 53, 52),
+ "tuft bush" : (255, 221, 205),
+ "tulip tree" : (234, 179, 59),
+ "tumbleweed" : (222, 166, 129),
+ "tuna" : ( 53, 53, 66),
+ "tundora" : ( 74, 66, 68),
+ "turbo" : (250, 230, 0),
+ "turkish rose" : (181, 114, 129),
+ "turmeric" : (202, 187, 72),
+ "turquoise" : ( 48, 213, 200),
+ "turquoise blue" : (108, 218, 231),
+ "turtle green" : ( 42, 56, 11),
+ "tuscany" : (189, 94, 46),
+ "tusk" : (238, 243, 195),
+ "tussock" : (197, 153, 75),
+ "tutu" : (255, 241, 249),
+ "twilight" : (228, 207, 222),
+ "twilight blue" : (238, 253, 255),
+ "twine" : (194, 149, 93),
+ "tyrian purple" : (102, 2, 60),
+ "ultramarine" : ( 18, 10, 143),
+ "valencia" : (216, 68, 55),
+ "valentino" : ( 53, 14, 66),
+ "valhalla" : ( 43, 25, 79),
+ "van cleef" : ( 73, 23, 12),
+ "vanilla" : (209, 190, 168),
+ "vanilla ice" : (243, 217, 223),
+ "varden" : (255, 246, 223),
+ "venetian red" : (114, 1, 15),
+ "venice blue" : ( 5, 89, 137),
+ "venus" : (146, 133, 144),
+ "verdigris" : ( 93, 94, 55),
+ "verdun green" : ( 73, 84, 0),
+ "vermilion" : (255, 77, 0),
+ "vesuvius" : (177, 74, 11),
+ "victoria" : ( 83, 68, 145),
+ "vida loca" : ( 84, 144, 25),
+ "viking" : (100, 204, 219),
+ "vin rouge" : (152, 61, 97),
+ "viola" : (203, 143, 169),
+ "violent violet" : ( 41, 12, 94),
+ "violet" : ( 36, 10, 64),
+ "violet eggplant" : (153, 17, 153),
+ "violet red" : (247, 70, 138),
+ "viridian" : ( 64, 130, 109),
+ "viridian green" : (103, 137, 117),
+ "vis vis" : (255, 239, 161),
+ "vista blue" : (143, 214, 180),
+ "vista white" : (252, 248, 247),
+ "vivid tangerine" : (255, 153, 128),
+ "vivid violet" : (128, 55, 144),
+ "voodoo" : ( 83, 52, 85),
+ "vulcan" : ( 16, 18, 29),
+ "wafer" : (222, 203, 198),
+ "waikawa gray" : ( 90, 110, 156),
+ "waiouru" : ( 54, 60, 13),
+ "walnut" : (119, 63, 26),
+ "wasabi" : (120, 138, 37),
+ "water leaf" : (161, 233, 222),
+ "watercourse" : ( 5, 111, 87),
+ "waterloo " : (123, 124, 148),
+ "wattle" : (220, 215, 71),
+ "watusi" : (255, 221, 207),
+ "wax flower" : (255, 192, 168),
+ "we peep" : (247, 219, 230),
+ "web orange" : (255, 165, 0),
+ "wedgewood" : ( 78, 127, 158),
+ "well read" : (180, 51, 50),
+ "west coast" : ( 98, 81, 25),
+ "west side" : (255, 145, 15),
+ "westar" : (220, 217, 210),
+ "wewak" : (241, 155, 171),
+ "wheat" : (245, 222, 179),
+ "wheatfield" : (243, 237, 207),
+ "whiskey" : (213, 154, 111),
+ "whisper" : (247, 245, 250),
+ "white" : (255, 255, 255),
+ "white ice" : (221, 249, 241),
+ "white lilac" : (248, 247, 252),
+ "white linen" : (248, 240, 232),
+ "white pointer" : (254, 248, 255),
+ "white rock" : (234, 232, 212),
+ "wild blue yonder" : (122, 137, 184),
+ "wild rice" : (236, 224, 144),
+ "wild sand" : (244, 244, 244),
+ "wild strawberry" : (255, 51, 153),
+ "wild watermelon" : (253, 91, 120),
+ "wild willow" : (185, 196, 106),
+ "william" : ( 58, 104, 108),
+ "willow brook" : (223, 236, 218),
+ "willow grove" : (101, 116, 93),
+ "windsor" : ( 60, 8, 120),
+ "wine berry" : ( 89, 29, 53),
+ "winter hazel" : (213, 209, 149),
+ "wisp pink" : (254, 244, 248),
+ "wisteria" : (151, 113, 181),
+ "wistful" : (164, 166, 211),
+ "witch haze" : (255, 252, 153),
+ "wood bark" : ( 38, 17, 5),
+ "woodland" : ( 77, 83, 40),
+ "woodrush" : ( 48, 42, 15),
+ "woodsmoke" : ( 12, 13, 15),
+ "woody brown" : ( 72, 49, 49),
+ "xanadu" : (115, 134, 120),
+ "yellow" : (255, 255, 0),
+ "yellow green" : (197, 225, 122),
+ "yellow metal" : (113, 99, 56),
+ "yellow orange" : (255, 174, 66),
+ "yellow sea" : (254, 169, 4),
+ "your pink" : (255, 195, 192),
+ "yukon gold" : (123, 102, 8),
+ "yuma" : (206, 194, 145),
+ "zambezi" : (104, 85, 88),
+ "zanah" : (218, 236, 214),
+ "zest" : (229, 132, 27),
+ "zeus" : ( 41, 35, 25),
+ "ziggurat" : (191, 219, 226),
+ "zinnwaldite" : (235, 194, 175),
+ "zircon" : (244, 248, 255),
+ "zombie" : (228, 214, 155),
+ "zorba" : (165, 155, 145),
+ "zuccini" : ( 4, 64, 34),
+ "zumthor" : (237, 246, 255)}
+
+def build_reverse_dict():
+ global reverse
+ global colorhex
+ global colors
+ for color in colors:
+ rgb = colors[color]
+ hex_val = '#%02X%02X%02X' % (rgb)
+ reverse[hex_val] = color
+ colorhex[color] = hex_val
+ return
+
+
+def get_complementary_hex(color):
+ # strip the # from the beginning
+ color = color[1:]
+ # convert the string into hex
+ color = int(color, 16)
+ # invert the three bytes
+ # as good as substracting each of RGB component by 255(FF)
+ comp_color = 0xFFFFFF ^ color
+ # convert the color back to hex by prefixing a #
+ comp_color = "#%06X" % comp_color
+ # return the result
+ return comp_color
+
+def get_complementary_rgb(red, green, blue):
+ color_string = '#%02X%02X%02X' % (red, green, blue)
+ # strip the # from the beginning
+ color = color_string[1:]
+ # convert the string into hex
+ color = int(color, 16)
+ # invert the three bytes
+ # as good as substracting each of RGB component by 255(FF)
+ comp_color = 0xFFFFFF ^ color
+ # convert the color back to hex by prefixing a #
+ comp_color = "#%06X" % comp_color
+ # return the result
+ return comp_color
+
+def get_name_from_hex(hex):
+ global reverse
+ global colorhex
+ global colors
+
+ hex_val = hex.upper()
+ try:
+ name = reverse[hex_val]
+ except:
+ name = 'No Hex For Name'
+ return name
+
+def get_hex_from_name(name):
+ global reverse
+ global colorhex
+ global colors
+
+ name = name.lower()
+ try:
+ hex_val = colorhex[name]
+ except:
+ hex_val = '#000000'
+ return hex_val
+
+def show_all_colors_on_buttons():
+ global reverse
+ global colorhex
+ global colors
+ window = sg.Window('Colors on Buttons Demo', default_element_size=(3, 1), location=(0, 0), font=("Helvetica", 7))
+ row = []
+ row_len = 20
+ for i, c in enumerate(colors):
+ hex_val = get_hex_from_name(c)
+ button1 = sg.CButton(button_text=c, button_color=(get_complementary_hex(hex_val), hex_val), size=(8, 1))
+ button2 = sg.CButton(button_text=c, button_color=(hex_val, get_complementary_hex(hex_val)), size=(8, 1))
+ row.append(button1)
+ row.append(button2)
+ if (i+1) % row_len == 0:
+ window.AddRow(*row)
+ row = []
+ if row != []:
+ window.AddRow(*row)
+ window.Show()
+
+
+GoodColors = [('#0e6251', sg.RGB(255, 246, 122)),
+ ('white', sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 210, 124), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 210, 87), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 164, 73), sg.RGB(0, 74, 60)),
+ (sg.RGB(0, 74, 60), sg.RGB(0, 74, 60)),
+ ]
+
+
+def main():
+ global colors
+ global reverse
+
+ build_reverse_dict()
+ list_of_colors = [c for c in colors]
+ printable = '\n'.join(map(str, list_of_colors))
+ # show_all_colors_on_buttons()
+ sg.set_options(element_padding=(0,0))
+ while True:
+ # ------- Form show ------- #
+ layout = [[sg.Text('Find color')],
+ [sg.Text('Demonstration of colors')],
+ [sg.Text('Enter a color name in text or hex #RRGGBB format')],
+ [sg.InputText(key='hex')],
+ [sg.Listbox(list_of_colors, size=(20, 30), bind_return_key=True, key='listbox'), sg.Text('Or choose from list')],
+ [sg.Submit(), sg.Button('Many buttons', button_color=('white', '#0e6251'), key='Many buttons'), sg.ColorChooserButton( 'Chooser', target=(3,0), key='Chooser'), sg.Quit(),],
+ ]
+ # [g.Multiline(DefaultText=str(printable), Size=(30,20))]]
+ event, values = sg.Window('Color Demo', layout, auto_size_buttons=False).read()
+
+ # ------- OUTPUT results portion ------- #
+ if event == 'Quit' or event is None:
+ exit(0)
+ elif event == 'Many buttons':
+ show_all_colors_on_buttons()
+
+ drop_down_value = values['listbox']
+ hex_input = values['hex']
+ if hex_input == '' and len(drop_down_value) == 0:
+ continue
+
+ if len(hex_input) != 0:
+ if hex_input[0] == '#':
+ color_hex = hex_input.upper()
+ color_name = get_name_from_hex(hex_input)
+ else:
+ color_name = hex_input
+ color_hex = get_hex_from_name(color_name)
+ elif drop_down_value is not None and len(drop_down_value) != 0:
+ color_name = drop_down_value[0]
+ color_hex = get_hex_from_name(color_name)
+
+ complementary_hex = get_complementary_hex(color_hex)
+ complementary_color = get_name_from_hex(complementary_hex)
+
+ layout = [[sg.Text('That color and it\'s compliment are shown on these buttons. This form auto-closes')],
+ [sg.CloseButton(button_text=color_name, button_color=(color_hex, complementary_hex))],
+ [sg.CloseButton(button_text=complementary_hex + ' ' + complementary_color, button_color=(complementary_hex , color_hex), size=(30, 1))],
+ ]
+ sg.Window('Color demo', layout, default_element_size=(100, 1),
+ auto_close=True, auto_close_duration=5).read()
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms/Demo_Color_Chooser_Custom.py b/DemoPrograms/Demo_Color_Chooser_Custom.py
deleted file mode 100644
index 3c041f2ff..000000000
--- a/DemoPrograms/Demo_Color_Chooser_Custom.py
+++ /dev/null
@@ -1,724 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def popup_color_chooser(look_and_feel=None):
- """
- :return: Any(str, None) Returns hex string of color chosen or None if nothing was chosen
- """
- color_map = {
- 'alice blue': '#F0F8FF',
- 'AliceBlue': '#F0F8FF',
- 'antique white': '#FAEBD7',
- 'AntiqueWhite': '#FAEBD7',
- 'AntiqueWhite1': '#FFEFDB',
- 'AntiqueWhite2': '#EEDFCC',
- 'AntiqueWhite3': '#CDC0B0',
- 'AntiqueWhite4': '#8B8378',
- 'aquamarine': '#7FFFD4',
- 'aquamarine1': '#7FFFD4',
- 'aquamarine2': '#76EEC6',
- 'aquamarine3': '#66CDAA',
- 'aquamarine4': '#458B74',
- 'azure': '#F0FFFF',
- 'azure1': '#F0FFFF',
- 'azure2': '#E0EEEE',
- 'azure3': '#C1CDCD',
- 'azure4': '#838B8B',
- 'beige': '#F5F5DC',
- 'bisque': '#FFE4C4',
- 'bisque1': '#FFE4C4',
- 'bisque2': '#EED5B7',
- 'bisque3': '#CDB79E',
- 'bisque4': '#8B7D6B',
- 'black': '#000000',
- 'blanched almond': '#FFEBCD',
- 'BlanchedAlmond': '#FFEBCD',
- 'blue': '#0000FF',
- 'blue violet': '#8A2BE2',
- 'blue1': '#0000FF',
- 'blue2': '#0000EE',
- 'blue3': '#0000CD',
- 'blue4': '#00008B',
- 'BlueViolet': '#8A2BE2',
- 'brown': '#A52A2A',
- 'brown1': '#FF4040',
- 'brown2': '#EE3B3B',
- 'brown3': '#CD3333',
- 'brown4': '#8B2323',
- 'burlywood': '#DEB887',
- 'burlywood1': '#FFD39B',
- 'burlywood2': '#EEC591',
- 'burlywood3': '#CDAA7D',
- 'burlywood4': '#8B7355',
- 'cadet blue': '#5F9EA0',
- 'CadetBlue': '#5F9EA0',
- 'CadetBlue1': '#98F5FF',
- 'CadetBlue2': '#8EE5EE',
- 'CadetBlue3': '#7AC5CD',
- 'CadetBlue4': '#53868B',
- 'chartreuse': '#7FFF00',
- 'chartreuse1': '#7FFF00',
- 'chartreuse2': '#76EE00',
- 'chartreuse3': '#66CD00',
- 'chartreuse4': '#458B00',
- 'chocolate': '#D2691E',
- 'chocolate1': '#FF7F24',
- 'chocolate2': '#EE7621',
- 'chocolate3': '#CD661D',
- 'chocolate4': '#8B4513',
- 'coral': '#FF7F50',
- 'coral1': '#FF7256',
- 'coral2': '#EE6A50',
- 'coral3': '#CD5B45',
- 'coral4': '#8B3E2F',
- 'cornflower blue': '#6495ED',
- 'CornflowerBlue': '#6495ED',
- 'cornsilk': '#FFF8DC',
- 'cornsilk1': '#FFF8DC',
- 'cornsilk2': '#EEE8CD',
- 'cornsilk3': '#CDC8B1',
- 'cornsilk4': '#8B8878',
- 'cyan': '#00FFFF',
- 'cyan1': '#00FFFF',
- 'cyan2': '#00EEEE',
- 'cyan3': '#00CDCD',
- 'cyan4': '#008B8B',
- 'dark blue': '#00008B',
- 'dark cyan': '#008B8B',
- 'dark goldenrod': '#B8860B',
- 'dark gray': '#A9A9A9',
- 'dark green': '#006400',
- 'dark grey': '#A9A9A9',
- 'dark khaki': '#BDB76B',
- 'dark magenta': '#8B008B',
- 'dark olive green': '#556B2F',
- 'dark orange': '#FF8C00',
- 'dark orchid': '#9932CC',
- 'dark red': '#8B0000',
- 'dark salmon': '#E9967A',
- 'dark sea green': '#8FBC8F',
- 'dark slate blue': '#483D8B',
- 'dark slate gray': '#2F4F4F',
- 'dark slate grey': '#2F4F4F',
- 'dark turquoise': '#00CED1',
- 'dark violet': '#9400D3',
- 'DarkBlue': '#00008B',
- 'DarkCyan': '#008B8B',
- 'DarkGoldenrod': '#B8860B',
- 'DarkGoldenrod1': '#FFB90F',
- 'DarkGoldenrod2': '#EEAD0E',
- 'DarkGoldenrod3': '#CD950C',
- 'DarkGoldenrod4': '#8B6508',
- 'DarkGray': '#A9A9A9',
- 'DarkGreen': '#006400',
- 'DarkGrey': '#A9A9A9',
- 'DarkKhaki': '#BDB76B',
- 'DarkMagenta': '#8B008B',
- 'DarkOliveGreen': '#556B2F',
- 'DarkOliveGreen1': '#CAFF70',
- 'DarkOliveGreen2': '#BCEE68',
- 'DarkOliveGreen3': '#A2CD5A',
- 'DarkOliveGreen4': '#6E8B3D',
- 'DarkOrange': '#FF8C00',
- 'DarkOrange1': '#FF7F00',
- 'DarkOrange2': '#EE7600',
- 'DarkOrange3': '#CD6600',
- 'DarkOrange4': '#8B4500',
- 'DarkOrchid': '#9932CC',
- 'DarkOrchid1': '#BF3EFF',
- 'DarkOrchid2': '#B23AEE',
- 'DarkOrchid3': '#9A32CD',
- 'DarkOrchid4': '#68228B',
- 'DarkRed': '#8B0000',
- 'DarkSalmon': '#E9967A',
- 'DarkSeaGreen': '#8FBC8F',
- 'DarkSeaGreen1': '#C1FFC1',
- 'DarkSeaGreen2': '#B4EEB4',
- 'DarkSeaGreen3': '#9BCD9B',
- 'DarkSeaGreen4': '#698B69',
- 'DarkSlateBlue': '#483D8B',
- 'DarkSlateGray': '#2F4F4F',
- 'DarkSlateGray1': '#97FFFF',
- 'DarkSlateGray2': '#8DEEEE',
- 'DarkSlateGray3': '#79CDCD',
- 'DarkSlateGray4': '#528B8B',
- 'DarkSlateGrey': '#2F4F4F',
- 'DarkTurquoise': '#00CED1',
- 'DarkViolet': '#9400D3',
- 'deep pink': '#FF1493',
- 'deep sky blue': '#00BFFF',
- 'DeepPink': '#FF1493',
- 'DeepPink1': '#FF1493',
- 'DeepPink2': '#EE1289',
- 'DeepPink3': '#CD1076',
- 'DeepPink4': '#8B0A50',
- 'DeepSkyBlue': '#00BFFF',
- 'DeepSkyBlue1': '#00BFFF',
- 'DeepSkyBlue2': '#00B2EE',
- 'DeepSkyBlue3': '#009ACD',
- 'DeepSkyBlue4': '#00688B',
- 'dim gray': '#696969',
- 'dim grey': '#696969',
- 'DimGray': '#696969',
- 'DimGrey': '#696969',
- 'dodger blue': '#1E90FF',
- 'DodgerBlue': '#1E90FF',
- 'DodgerBlue1': '#1E90FF',
- 'DodgerBlue2': '#1C86EE',
- 'DodgerBlue3': '#1874CD',
- 'DodgerBlue4': '#104E8B',
- 'firebrick': '#B22222',
- 'firebrick1': '#FF3030',
- 'firebrick2': '#EE2C2C',
- 'firebrick3': '#CD2626',
- 'firebrick4': '#8B1A1A',
- 'floral white': '#FFFAF0',
- 'FloralWhite': '#FFFAF0',
- 'forest green': '#228B22',
- 'ForestGreen': '#228B22',
- 'gainsboro': '#DCDCDC',
- 'ghost white': '#F8F8FF',
- 'GhostWhite': '#F8F8FF',
- 'gold': '#FFD700',
- 'gold1': '#FFD700',
- 'gold2': '#EEC900',
- 'gold3': '#CDAD00',
- 'gold4': '#8B7500',
- 'goldenrod': '#DAA520',
- 'goldenrod1': '#FFC125',
- 'goldenrod2': '#EEB422',
- 'goldenrod3': '#CD9B1D',
- 'goldenrod4': '#8B6914',
- 'green': '#00FF00',
- 'green yellow': '#ADFF2F',
- 'green1': '#00FF00',
- 'green2': '#00EE00',
- 'green3': '#00CD00',
- 'green4': '#008B00',
- 'GreenYellow': '#ADFF2F',
- 'grey': '#BEBEBE',
- 'grey0': '#000000',
- 'grey1': '#030303',
- 'grey2': '#050505',
- 'grey3': '#080808',
- 'grey4': '#0A0A0A',
- 'grey5': '#0D0D0D',
- 'grey6': '#0F0F0F',
- 'grey7': '#121212',
- 'grey8': '#141414',
- 'grey9': '#171717',
- 'grey10': '#1A1A1A',
- 'grey11': '#1C1C1C',
- 'grey12': '#1F1F1F',
- 'grey13': '#212121',
- 'grey14': '#242424',
- 'grey15': '#262626',
- 'grey16': '#292929',
- 'grey17': '#2B2B2B',
- 'grey18': '#2E2E2E',
- 'grey19': '#303030',
- 'grey20': '#333333',
- 'grey21': '#363636',
- 'grey22': '#383838',
- 'grey23': '#3B3B3B',
- 'grey24': '#3D3D3D',
- 'grey25': '#404040',
- 'grey26': '#424242',
- 'grey27': '#454545',
- 'grey28': '#474747',
- 'grey29': '#4A4A4A',
- 'grey30': '#4D4D4D',
- 'grey31': '#4F4F4F',
- 'grey32': '#525252',
- 'grey33': '#545454',
- 'grey34': '#575757',
- 'grey35': '#595959',
- 'grey36': '#5C5C5C',
- 'grey37': '#5E5E5E',
- 'grey38': '#616161',
- 'grey39': '#636363',
- 'grey40': '#666666',
- 'grey41': '#696969',
- 'grey42': '#6B6B6B',
- 'grey43': '#6E6E6E',
- 'grey44': '#707070',
- 'grey45': '#737373',
- 'grey46': '#757575',
- 'grey47': '#787878',
- 'grey48': '#7A7A7A',
- 'grey49': '#7D7D7D',
- 'grey50': '#7F7F7F',
- 'grey51': '#828282',
- 'grey52': '#858585',
- 'grey53': '#878787',
- 'grey54': '#8A8A8A',
- 'grey55': '#8C8C8C',
- 'grey56': '#8F8F8F',
- 'grey57': '#919191',
- 'grey58': '#949494',
- 'grey59': '#969696',
- 'grey60': '#999999',
- 'grey61': '#9C9C9C',
- 'grey62': '#9E9E9E',
- 'grey63': '#A1A1A1',
- 'grey64': '#A3A3A3',
- 'grey65': '#A6A6A6',
- 'grey66': '#A8A8A8',
- 'grey67': '#ABABAB',
- 'grey68': '#ADADAD',
- 'grey69': '#B0B0B0',
- 'grey70': '#B3B3B3',
- 'grey71': '#B5B5B5',
- 'grey72': '#B8B8B8',
- 'grey73': '#BABABA',
- 'grey74': '#BDBDBD',
- 'grey75': '#BFBFBF',
- 'grey76': '#C2C2C2',
- 'grey77': '#C4C4C4',
- 'grey78': '#C7C7C7',
- 'grey79': '#C9C9C9',
- 'grey80': '#CCCCCC',
- 'grey81': '#CFCFCF',
- 'grey82': '#D1D1D1',
- 'grey83': '#D4D4D4',
- 'grey84': '#D6D6D6',
- 'grey85': '#D9D9D9',
- 'grey86': '#DBDBDB',
- 'grey87': '#DEDEDE',
- 'grey88': '#E0E0E0',
- 'grey89': '#E3E3E3',
- 'grey90': '#E5E5E5',
- 'grey91': '#E8E8E8',
- 'grey92': '#EBEBEB',
- 'grey93': '#EDEDED',
- 'grey94': '#F0F0F0',
- 'grey95': '#F2F2F2',
- 'grey96': '#F5F5F5',
- 'grey97': '#F7F7F7',
- 'grey98': '#FAFAFA',
- 'grey99': '#FCFCFC',
- 'grey100': '#FFFFFF',
- 'honeydew': '#F0FFF0',
- 'honeydew1': '#F0FFF0',
- 'honeydew2': '#E0EEE0',
- 'honeydew3': '#C1CDC1',
- 'honeydew4': '#838B83',
- 'hot pink': '#FF69B4',
- 'HotPink': '#FF69B4',
- 'HotPink1': '#FF6EB4',
- 'HotPink2': '#EE6AA7',
- 'HotPink3': '#CD6090',
- 'HotPink4': '#8B3A62',
- 'indian red': '#CD5C5C',
- 'IndianRed': '#CD5C5C',
- 'IndianRed1': '#FF6A6A',
- 'IndianRed2': '#EE6363',
- 'IndianRed3': '#CD5555',
- 'IndianRed4': '#8B3A3A',
- 'ivory': '#FFFFF0',
- 'ivory1': '#FFFFF0',
- 'ivory2': '#EEEEE0',
- 'ivory3': '#CDCDC1',
- 'ivory4': '#8B8B83',
- 'khaki': '#F0E68C',
- 'khaki1': '#FFF68F',
- 'khaki2': '#EEE685',
- 'khaki3': '#CDC673',
- 'khaki4': '#8B864E',
- 'lavender': '#E6E6FA',
- 'lavender blush': '#FFF0F5',
- 'LavenderBlush': '#FFF0F5',
- 'LavenderBlush1': '#FFF0F5',
- 'LavenderBlush2': '#EEE0E5',
- 'LavenderBlush3': '#CDC1C5',
- 'LavenderBlush4': '#8B8386',
- 'lawn green': '#7CFC00',
- 'LawnGreen': '#7CFC00',
- 'lemon chiffon': '#FFFACD',
- 'LemonChiffon': '#FFFACD',
- 'LemonChiffon1': '#FFFACD',
- 'LemonChiffon2': '#EEE9BF',
- 'LemonChiffon3': '#CDC9A5',
- 'LemonChiffon4': '#8B8970',
- 'light blue': '#ADD8E6',
- 'light coral': '#F08080',
- 'light cyan': '#E0FFFF',
- 'light goldenrod': '#EEDD82',
- 'light goldenrod yellow': '#FAFAD2',
- 'light gray': '#D3D3D3',
- 'light green': '#90EE90',
- 'light grey': '#D3D3D3',
- 'light pink': '#FFB6C1',
- 'light salmon': '#FFA07A',
- 'light sea green': '#20B2AA',
- 'light sky blue': '#87CEFA',
- 'light slate blue': '#8470FF',
- 'light slate gray': '#778899',
- 'light slate grey': '#778899',
- 'light steel blue': '#B0C4DE',
- 'light yellow': '#FFFFE0',
- 'LightBlue': '#ADD8E6',
- 'LightBlue1': '#BFEFFF',
- 'LightBlue2': '#B2DFEE',
- 'LightBlue3': '#9AC0CD',
- 'LightBlue4': '#68838B',
- 'LightCoral': '#F08080',
- 'LightCyan': '#E0FFFF',
- 'LightCyan1': '#E0FFFF',
- 'LightCyan2': '#D1EEEE',
- 'LightCyan3': '#B4CDCD',
- 'LightCyan4': '#7A8B8B',
- 'LightGoldenrod': '#EEDD82',
- 'LightGoldenrod1': '#FFEC8B',
- 'LightGoldenrod2': '#EEDC82',
- 'LightGoldenrod3': '#CDBE70',
- 'LightGoldenrod4': '#8B814C',
- 'LightGoldenrodYellow': '#FAFAD2',
- 'LightGray': '#D3D3D3',
- 'LightGreen': '#90EE90',
- 'LightGrey': '#D3D3D3',
- 'LightPink': '#FFB6C1',
- 'LightPink1': '#FFAEB9',
- 'LightPink2': '#EEA2AD',
- 'LightPink3': '#CD8C95',
- 'LightPink4': '#8B5F65',
- 'LightSalmon': '#FFA07A',
- 'LightSalmon1': '#FFA07A',
- 'LightSalmon2': '#EE9572',
- 'LightSalmon3': '#CD8162',
- 'LightSalmon4': '#8B5742',
- 'LightSeaGreen': '#20B2AA',
- 'LightSkyBlue': '#87CEFA',
- 'LightSkyBlue1': '#B0E2FF',
- 'LightSkyBlue2': '#A4D3EE',
- 'LightSkyBlue3': '#8DB6CD',
- 'LightSkyBlue4': '#607B8B',
- 'LightSlateBlue': '#8470FF',
- 'LightSlateGray': '#778899',
- 'LightSlateGrey': '#778899',
- 'LightSteelBlue': '#B0C4DE',
- 'LightSteelBlue1': '#CAE1FF',
- 'LightSteelBlue2': '#BCD2EE',
- 'LightSteelBlue3': '#A2B5CD',
- 'LightSteelBlue4': '#6E7B8B',
- 'LightYellow': '#FFFFE0',
- 'LightYellow1': '#FFFFE0',
- 'LightYellow2': '#EEEED1',
- 'LightYellow3': '#CDCDB4',
- 'LightYellow4': '#8B8B7A',
- 'lime green': '#32CD32',
- 'LimeGreen': '#32CD32',
- 'linen': '#FAF0E6',
- 'magenta': '#FF00FF',
- 'magenta1': '#FF00FF',
- 'magenta2': '#EE00EE',
- 'magenta3': '#CD00CD',
- 'magenta4': '#8B008B',
- 'maroon': '#B03060',
- 'maroon1': '#FF34B3',
- 'maroon2': '#EE30A7',
- 'maroon3': '#CD2990',
- 'maroon4': '#8B1C62',
- 'medium aquamarine': '#66CDAA',
- 'medium blue': '#0000CD',
- 'medium orchid': '#BA55D3',
- 'medium purple': '#9370DB',
- 'medium sea green': '#3CB371',
- 'medium slate blue': '#7B68EE',
- 'medium spring green': '#00FA9A',
- 'medium turquoise': '#48D1CC',
- 'medium violet red': '#C71585',
- 'MediumAquamarine': '#66CDAA',
- 'MediumBlue': '#0000CD',
- 'MediumOrchid': '#BA55D3',
- 'MediumOrchid1': '#E066FF',
- 'MediumOrchid2': '#D15FEE',
- 'MediumOrchid3': '#B452CD',
- 'MediumOrchid4': '#7A378B',
- 'MediumPurple': '#9370DB',
- 'MediumPurple1': '#AB82FF',
- 'MediumPurple2': '#9F79EE',
- 'MediumPurple3': '#8968CD',
- 'MediumPurple4': '#5D478B',
- 'MediumSeaGreen': '#3CB371',
- 'MediumSlateBlue': '#7B68EE',
- 'MediumSpringGreen': '#00FA9A',
- 'MediumTurquoise': '#48D1CC',
- 'MediumVioletRed': '#C71585',
- 'midnight blue': '#191970',
- 'MidnightBlue': '#191970',
- 'mint cream': '#F5FFFA',
- 'MintCream': '#F5FFFA',
- 'misty rose': '#FFE4E1',
- 'MistyRose': '#FFE4E1',
- 'MistyRose1': '#FFE4E1',
- 'MistyRose2': '#EED5D2',
- 'MistyRose3': '#CDB7B5',
- 'MistyRose4': '#8B7D7B',
- 'moccasin': '#FFE4B5',
- 'navajo white': '#FFDEAD',
- 'NavajoWhite': '#FFDEAD',
- 'NavajoWhite1': '#FFDEAD',
- 'NavajoWhite2': '#EECFA1',
- 'NavajoWhite3': '#CDB38B',
- 'NavajoWhite4': '#8B795E',
- 'navy': '#000080',
- 'navy blue': '#000080',
- 'NavyBlue': '#000080',
- 'old lace': '#FDF5E6',
- 'OldLace': '#FDF5E6',
- 'olive drab': '#6B8E23',
- 'OliveDrab': '#6B8E23',
- 'OliveDrab1': '#C0FF3E',
- 'OliveDrab2': '#B3EE3A',
- 'OliveDrab3': '#9ACD32',
- 'OliveDrab4': '#698B22',
- 'orange': '#FFA500',
- 'orange red': '#FF4500',
- 'orange1': '#FFA500',
- 'orange2': '#EE9A00',
- 'orange3': '#CD8500',
- 'orange4': '#8B5A00',
- 'OrangeRed': '#FF4500',
- 'OrangeRed1': '#FF4500',
- 'OrangeRed2': '#EE4000',
- 'OrangeRed3': '#CD3700',
- 'OrangeRed4': '#8B2500',
- 'orchid': '#DA70D6',
- 'orchid1': '#FF83FA',
- 'orchid2': '#EE7AE9',
- 'orchid3': '#CD69C9',
- 'orchid4': '#8B4789',
- 'pale goldenrod': '#EEE8AA',
- 'pale green': '#98FB98',
- 'pale turquoise': '#AFEEEE',
- 'pale violet red': '#DB7093',
- 'PaleGoldenrod': '#EEE8AA',
- 'PaleGreen': '#98FB98',
- 'PaleGreen1': '#9AFF9A',
- 'PaleGreen2': '#90EE90',
- 'PaleGreen3': '#7CCD7C',
- 'PaleGreen4': '#548B54',
- 'PaleTurquoise': '#AFEEEE',
- 'PaleTurquoise1': '#BBFFFF',
- 'PaleTurquoise2': '#AEEEEE',
- 'PaleTurquoise3': '#96CDCD',
- 'PaleTurquoise4': '#668B8B',
- 'PaleVioletRed': '#DB7093',
- 'PaleVioletRed1': '#FF82AB',
- 'PaleVioletRed2': '#EE799F',
- 'PaleVioletRed3': '#CD687F',
- 'PaleVioletRed4': '#8B475D',
- 'papaya whip': '#FFEFD5',
- 'PapayaWhip': '#FFEFD5',
- 'peach puff': '#FFDAB9',
- 'PeachPuff': '#FFDAB9',
- 'PeachPuff1': '#FFDAB9',
- 'PeachPuff2': '#EECBAD',
- 'PeachPuff3': '#CDAF95',
- 'PeachPuff4': '#8B7765',
- 'peru': '#CD853F',
- 'pink': '#FFC0CB',
- 'pink1': '#FFB5C5',
- 'pink2': '#EEA9B8',
- 'pink3': '#CD919E',
- 'pink4': '#8B636C',
- 'plum': '#DDA0DD',
- 'plum1': '#FFBBFF',
- 'plum2': '#EEAEEE',
- 'plum3': '#CD96CD',
- 'plum4': '#8B668B',
- 'powder blue': '#B0E0E6',
- 'PowderBlue': '#B0E0E6',
- 'purple': '#A020F0',
- 'purple1': '#9B30FF',
- 'purple2': '#912CEE',
- 'purple3': '#7D26CD',
- 'purple4': '#551A8B',
- 'red': '#FF0000',
- 'red1': '#FF0000',
- 'red2': '#EE0000',
- 'red3': '#CD0000',
- 'red4': '#8B0000',
- 'rosy brown': '#BC8F8F',
- 'RosyBrown': '#BC8F8F',
- 'RosyBrown1': '#FFC1C1',
- 'RosyBrown2': '#EEB4B4',
- 'RosyBrown3': '#CD9B9B',
- 'RosyBrown4': '#8B6969',
- 'royal blue': '#4169E1',
- 'RoyalBlue': '#4169E1',
- 'RoyalBlue1': '#4876FF',
- 'RoyalBlue2': '#436EEE',
- 'RoyalBlue3': '#3A5FCD',
- 'RoyalBlue4': '#27408B',
- 'saddle brown': '#8B4513',
- 'SaddleBrown': '#8B4513',
- 'salmon': '#FA8072',
- 'salmon1': '#FF8C69',
- 'salmon2': '#EE8262',
- 'salmon3': '#CD7054',
- 'salmon4': '#8B4C39',
- 'sandy brown': '#F4A460',
- 'SandyBrown': '#F4A460',
- 'sea green': '#2E8B57',
- 'SeaGreen': '#2E8B57',
- 'SeaGreen1': '#54FF9F',
- 'SeaGreen2': '#4EEE94',
- 'SeaGreen3': '#43CD80',
- 'SeaGreen4': '#2E8B57',
- 'seashell': '#FFF5EE',
- 'seashell1': '#FFF5EE',
- 'seashell2': '#EEE5DE',
- 'seashell3': '#CDC5BF',
- 'seashell4': '#8B8682',
- 'sienna': '#A0522D',
- 'sienna1': '#FF8247',
- 'sienna2': '#EE7942',
- 'sienna3': '#CD6839',
- 'sienna4': '#8B4726',
- 'sky blue': '#87CEEB',
- 'SkyBlue': '#87CEEB',
- 'SkyBlue1': '#87CEFF',
- 'SkyBlue2': '#7EC0EE',
- 'SkyBlue3': '#6CA6CD',
- 'SkyBlue4': '#4A708B',
- 'slate blue': '#6A5ACD',
- 'slate gray': '#708090',
- 'slate grey': '#708090',
- 'SlateBlue': '#6A5ACD',
- 'SlateBlue1': '#836FFF',
- 'SlateBlue2': '#7A67EE',
- 'SlateBlue3': '#6959CD',
- 'SlateBlue4': '#473C8B',
- 'SlateGray': '#708090',
- 'SlateGray1': '#C6E2FF',
- 'SlateGray2': '#B9D3EE',
- 'SlateGray3': '#9FB6CD',
- 'SlateGray4': '#6C7B8B',
- 'SlateGrey': '#708090',
- 'snow': '#FFFAFA',
- 'snow1': '#FFFAFA',
- 'snow2': '#EEE9E9',
- 'snow3': '#CDC9C9',
- 'snow4': '#8B8989',
- 'spring green': '#00FF7F',
- 'SpringGreen': '#00FF7F',
- 'SpringGreen1': '#00FF7F',
- 'SpringGreen2': '#00EE76',
- 'SpringGreen3': '#00CD66',
- 'SpringGreen4': '#008B45',
- 'steel blue': '#4682B4',
- 'SteelBlue': '#4682B4',
- 'SteelBlue1': '#63B8FF',
- 'SteelBlue2': '#5CACEE',
- 'SteelBlue3': '#4F94CD',
- 'SteelBlue4': '#36648B',
- 'tan': '#D2B48C',
- 'tan1': '#FFA54F',
- 'tan2': '#EE9A49',
- 'tan3': '#CD853F',
- 'tan4': '#8B5A2B',
- 'thistle': '#D8BFD8',
- 'thistle1': '#FFE1FF',
- 'thistle2': '#EED2EE',
- 'thistle3': '#CDB5CD',
- 'thistle4': '#8B7B8B',
- 'tomato': '#FF6347',
- 'tomato1': '#FF6347',
- 'tomato2': '#EE5C42',
- 'tomato3': '#CD4F39',
- 'tomato4': '#8B3626',
- 'turquoise': '#40E0D0',
- 'turquoise1': '#00F5FF',
- 'turquoise2': '#00E5EE',
- 'turquoise3': '#00C5CD',
- 'turquoise4': '#00868B',
- 'violet': '#EE82EE',
- 'violet red': '#D02090',
- 'VioletRed': '#D02090',
- 'VioletRed1': '#FF3E96',
- 'VioletRed2': '#EE3A8C',
- 'VioletRed3': '#CD3278',
- 'VioletRed4': '#8B2252',
- 'wheat': '#F5DEB3',
- 'wheat1': '#FFE7BA',
- 'wheat2': '#EED8AE',
- 'wheat3': '#CDBA96',
- 'wheat4': '#8B7E66',
- 'white': '#FFFFFF',
- 'white smoke': '#F5F5F5',
- 'WhiteSmoke': '#F5F5F5',
- 'yellow': '#FFFF00',
- 'yellow green': '#9ACD32',
- 'yellow1': '#FFFF00',
- 'yellow2': '#EEEE00',
- 'yellow3': '#CDCD00',
- 'yellow4': '#8B8B00',
- 'YellowGreen': '#9ACD32',
- }
-
- old_look_and_feel = None
- if look_and_feel is not None:
- old_look_and_feel = sg.CURRENT_LOOK_AND_FEEL
- sg.theme(look_and_feel)
-
- button_size = (1, 1)
-
- # button_size = (None,None) # for very compact buttons
-
- def ColorButton(color):
- """
- A User Defined Element - returns a Button that configured in a certain way.
- :param color: Tuple[str, str] ( color name, hex string)
- :return: sg.Button object
- """
- return sg.B(button_color=('white', color[1]), pad=(0, 0), size=button_size, key=color, tooltip=f'{color[0]}:{color[1]}', border_width=0)
-
- num_colors = len(list(color_map.keys()))
- row_len = 40
-
- grid = [[ColorButton(list(color_map.items())[c + j * row_len]) for c in range(0, row_len)] for j in range(0, num_colors // row_len)]
- grid += [[ColorButton(list(color_map.items())[c + num_colors - num_colors % row_len]) for c in range(0, num_colors % row_len)]]
-
- layout = [[sg.Text('Pick a color', font='Def 18')]] + grid + \
- [[sg.Button('OK'), sg.T(size=(30, 1), key='-OUT-')]]
-
- window = sg.Window('Window Title', layout, no_titlebar=True, grab_anywhere=True, keep_on_top=True, use_ttk_buttons=True)
- color_chosen = None
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'OK'):
- if event == sg.WIN_CLOSED:
- color_chosen = None
- break
- window['-OUT-'](f'You chose {event[0]} : {event[1]}')
- color_chosen = event[1]
- window.close()
- if old_look_and_feel is not None:
- sg.theme(old_look_and_feel)
- return color_chosen
-
-
-if __name__ == '__main__':
- sg.theme('Light Brown 4')
- layout = [[sg.In(key='-CHOICE-'), sg.B('Color Picker')],
- [sg.Ok(), sg.Cancel()]]
- window = sg.Window('My application', layout)
- while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Cancel'):
- break
- if event.startswith('Color'):
- window.hide()
- color_chosen = popup_color_chooser('Dark Blue 3')
- window['-CHOICE-'].update(color_chosen)
- window.un_hide()
- else:
- print(f'The current look and feel = {sg.CURRENT_LOOK_AND_FEEL}')
diff --git a/DemoPrograms/Demo_Color_Names.py b/DemoPrograms/Demo_Color_Names.py
index 21242c056..60bd7574c 100644
--- a/DemoPrograms/Demo_Color_Names.py
+++ b/DemoPrograms/Demo_Color_Names.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-import PySimpleGUI as sg
+import PySimpleGUIQt as sg
"""
@@ -10,9 +10,6 @@
You will find the list of tkinter colors here:
http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
color_map = {
@@ -668,42 +665,47 @@
'YellowGreen': '#9ACD32',
}
-sg.popup_quick_message('Building your table... one moment please...', background_color='red', text_color='white', font='_ 20')
-sg.set_options(button_element_size=(11, 1),
+sg.set_options(button_element_size=(12, 1),
element_padding=(0, 0),
auto_size_buttons=False,
- border_width=0, tooltip_time=100)
+ border_width=1, tooltip_time=100)
# start layout with the tittle
-# layout = [[sg.Text('Hover mouse to see RGB value, click for popup with buttons',
-# justification='center', font='Default 20')]]
+layout = [
+ [sg.Text('Hover mouse to see RGB value, click for white & black text',
+ justification='center',
+ text_color='blue', background_color='light green',
+ size=(100, 1), pad=(0, (0, 20)))]
+]
# -- Create primary color viewer window --
-color_list = list(color_map.keys())
-num_colors = len(color_list)
-colors_per_row = 15
-total_rows = num_colors//colors_per_row
-# for row_num in range(total_rows):
-# row = []
-# for i in range(colors_per_row):
-# color = color_list[row_num + i * total_rows]
-# row.append(sg.Button(color, button_color=('black', color), key=color, tooltip=color_map[color], border_width=0))
-# layout.append(row)
+color_list = [key for key in color_map]
+for rows in range(40):
+ row = []
+ for i in range(12):
+ try:
+ color = color_list[rows+40*i]
+ row.append(sg.Button(color, button_color=('black', color),
+ key=color, tooltip=color_map[color], border_width=0))
+ except:
+ pass
+ layout.append(row)
-# layout = [[sg.Text('Hover mouse to see RGB value, click for popup with buttons',
-# justification='center', font='Default 20')]] + [[sg.Button(color_list[row_num + i * total_rows], button_color=('black', color_list[row_num + i * total_rows]), key=color_list[row_num + i * total_rows], tooltip=color_map[color_list[row_num + i * total_rows]], border_width=0) for i in range(colors_per_row)] for row_num in range(total_rows)]
-window = sg.Window('Color Viewer',
- [[sg.Text('Hover mouse to see RGB value, click for popup with buttons', justification='center', font='Default 15')]] +
- [[sg.Button(color_list[row_num + i * total_rows], button_color=('black', color_list[row_num + i * total_rows]), key=color_list[row_num + i * total_rows], tooltip=color_map[color_list[row_num + i * total_rows]], border_width=0) for i in range(colors_per_row)] for row_num in range(total_rows)], font='Default 7', element_justification='c', use_default_focus=False)
+window = sg.Window('Color Viewer', layout, grab_anywhere=False, font=('any 9'), element_padding=(0,0), border_depth=0)
# -- Event loop --
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
# -- Create a secondary window that shows white and black text on chosen color
- layout2 = [[sg.DummyButton(event, button_color=('white', event), tooltip=color_map[event]), sg.DummyButton(event, button_color=('black', event), tooltip=color_map[event])]]
- sg.Window('Buttons with white and black text', layout2, keep_on_top=True, use_default_focus=False).read(timeout=0)
+ layout2 = [[
+ sg.DummyButton(event, button_color=(
+ 'white', event), tooltip=color_map[event]),
+ sg.DummyButton(event, button_color=('black', event), tooltip=color_map[event])
+ ]]
+ sg.Window('Buttons with white and black text',
+ layout2, keep_on_top=True).read(timeout=0)
diff --git a/DemoPrograms/Demo_Color_Names_Smaller_List.py b/DemoPrograms/Demo_Color_Names_Smaller_List.py
index 0bdad6812..12f86376c 100644
--- a/DemoPrograms/Demo_Color_Names_Smaller_List.py
+++ b/DemoPrograms/Demo_Color_Names_Smaller_List.py
@@ -8,10 +8,6 @@
Shows a big chart of colors... give it a few seconds to create it
Once large window is shown, you can click on any color and another window will popup
showing both white and black text on that color
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -118,7 +114,7 @@
# -- Event loop --
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
# -- Create a secondary window that shows white and black text on chosen color
layout2 = [[sg.DummyButton(event, button_color=('white', event)),
diff --git a/DemoPrograms/Demo_Color_Swatches.py b/DemoPrograms/Demo_Color_Swatches.py
deleted file mode 100644
index 2e23a0d13..000000000
--- a/DemoPrograms/Demo_Color_Swatches.py
+++ /dev/null
@@ -1,740 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import sys
-
-"""
- Big chart of tkinter colors shown as swatches.
-
- Hover over a swatch to get the color "name"
- Click on a swatch to:
- * preview the color as 2 buttons
- * see the hex value
- * get hex value copied onto clipboard
-
- You will find the list of tkinter colors here:
- http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-color_map = {
- 'alice blue': '#F0F8FF',
- 'AliceBlue': '#F0F8FF',
- 'antique white': '#FAEBD7',
- 'AntiqueWhite': '#FAEBD7',
- 'AntiqueWhite1': '#FFEFDB',
- 'AntiqueWhite2': '#EEDFCC',
- 'AntiqueWhite3': '#CDC0B0',
- 'AntiqueWhite4': '#8B8378',
- 'aquamarine': '#7FFFD4',
- 'aquamarine1': '#7FFFD4',
- 'aquamarine2': '#76EEC6',
- 'aquamarine3': '#66CDAA',
- 'aquamarine4': '#458B74',
- 'azure': '#F0FFFF',
- 'azure1': '#F0FFFF',
- 'azure2': '#E0EEEE',
- 'azure3': '#C1CDCD',
- 'azure4': '#838B8B',
- 'beige': '#F5F5DC',
- 'bisque': '#FFE4C4',
- 'bisque1': '#FFE4C4',
- 'bisque2': '#EED5B7',
- 'bisque3': '#CDB79E',
- 'bisque4': '#8B7D6B',
- 'black': '#000000',
- 'blanched almond': '#FFEBCD',
- 'BlanchedAlmond': '#FFEBCD',
- 'blue': '#0000FF',
- 'blue violet': '#8A2BE2',
- 'blue1': '#0000FF',
- 'blue2': '#0000EE',
- 'blue3': '#0000CD',
- 'blue4': '#00008B',
- 'BlueViolet': '#8A2BE2',
- 'brown': '#A52A2A',
- 'brown1': '#FF4040',
- 'brown2': '#EE3B3B',
- 'brown3': '#CD3333',
- 'brown4': '#8B2323',
- 'burlywood': '#DEB887',
- 'burlywood1': '#FFD39B',
- 'burlywood2': '#EEC591',
- 'burlywood3': '#CDAA7D',
- 'burlywood4': '#8B7355',
- 'cadet blue': '#5F9EA0',
- 'CadetBlue': '#5F9EA0',
- 'CadetBlue1': '#98F5FF',
- 'CadetBlue2': '#8EE5EE',
- 'CadetBlue3': '#7AC5CD',
- 'CadetBlue4': '#53868B',
- 'chartreuse': '#7FFF00',
- 'chartreuse1': '#7FFF00',
- 'chartreuse2': '#76EE00',
- 'chartreuse3': '#66CD00',
- 'chartreuse4': '#458B00',
- 'chocolate': '#D2691E',
- 'chocolate1': '#FF7F24',
- 'chocolate2': '#EE7621',
- 'chocolate3': '#CD661D',
- 'chocolate4': '#8B4513',
- 'coral': '#FF7F50',
- 'coral1': '#FF7256',
- 'coral2': '#EE6A50',
- 'coral3': '#CD5B45',
- 'coral4': '#8B3E2F',
- 'cornflower blue': '#6495ED',
- 'CornflowerBlue': '#6495ED',
- 'cornsilk': '#FFF8DC',
- 'cornsilk1': '#FFF8DC',
- 'cornsilk2': '#EEE8CD',
- 'cornsilk3': '#CDC8B1',
- 'cornsilk4': '#8B8878',
- 'cyan': '#00FFFF',
- 'cyan1': '#00FFFF',
- 'cyan2': '#00EEEE',
- 'cyan3': '#00CDCD',
- 'cyan4': '#008B8B',
- 'dark blue': '#00008B',
- 'dark cyan': '#008B8B',
- 'dark goldenrod': '#B8860B',
- 'dark gray': '#A9A9A9',
- 'dark green': '#006400',
- 'dark grey': '#A9A9A9',
- 'dark khaki': '#BDB76B',
- 'dark magenta': '#8B008B',
- 'dark olive green': '#556B2F',
- 'dark orange': '#FF8C00',
- 'dark orchid': '#9932CC',
- 'dark red': '#8B0000',
- 'dark salmon': '#E9967A',
- 'dark sea green': '#8FBC8F',
- 'dark slate blue': '#483D8B',
- 'dark slate gray': '#2F4F4F',
- 'dark slate grey': '#2F4F4F',
- 'dark turquoise': '#00CED1',
- 'dark violet': '#9400D3',
- 'DarkBlue': '#00008B',
- 'DarkCyan': '#008B8B',
- 'DarkGoldenrod': '#B8860B',
- 'DarkGoldenrod1': '#FFB90F',
- 'DarkGoldenrod2': '#EEAD0E',
- 'DarkGoldenrod3': '#CD950C',
- 'DarkGoldenrod4': '#8B6508',
- 'DarkGray': '#A9A9A9',
- 'DarkGreen': '#006400',
- 'DarkGrey': '#A9A9A9',
- 'DarkKhaki': '#BDB76B',
- 'DarkMagenta': '#8B008B',
- 'DarkOliveGreen': '#556B2F',
- 'DarkOliveGreen1': '#CAFF70',
- 'DarkOliveGreen2': '#BCEE68',
- 'DarkOliveGreen3': '#A2CD5A',
- 'DarkOliveGreen4': '#6E8B3D',
- 'DarkOrange': '#FF8C00',
- 'DarkOrange1': '#FF7F00',
- 'DarkOrange2': '#EE7600',
- 'DarkOrange3': '#CD6600',
- 'DarkOrange4': '#8B4500',
- 'DarkOrchid': '#9932CC',
- 'DarkOrchid1': '#BF3EFF',
- 'DarkOrchid2': '#B23AEE',
- 'DarkOrchid3': '#9A32CD',
- 'DarkOrchid4': '#68228B',
- 'DarkRed': '#8B0000',
- 'DarkSalmon': '#E9967A',
- 'DarkSeaGreen': '#8FBC8F',
- 'DarkSeaGreen1': '#C1FFC1',
- 'DarkSeaGreen2': '#B4EEB4',
- 'DarkSeaGreen3': '#9BCD9B',
- 'DarkSeaGreen4': '#698B69',
- 'DarkSlateBlue': '#483D8B',
- 'DarkSlateGray': '#2F4F4F',
- 'DarkSlateGray1': '#97FFFF',
- 'DarkSlateGray2': '#8DEEEE',
- 'DarkSlateGray3': '#79CDCD',
- 'DarkSlateGray4': '#528B8B',
- 'DarkSlateGrey': '#2F4F4F',
- 'DarkTurquoise': '#00CED1',
- 'DarkViolet': '#9400D3',
- 'deep pink': '#FF1493',
- 'deep sky blue': '#00BFFF',
- 'DeepPink': '#FF1493',
- 'DeepPink1': '#FF1493',
- 'DeepPink2': '#EE1289',
- 'DeepPink3': '#CD1076',
- 'DeepPink4': '#8B0A50',
- 'DeepSkyBlue': '#00BFFF',
- 'DeepSkyBlue1': '#00BFFF',
- 'DeepSkyBlue2': '#00B2EE',
- 'DeepSkyBlue3': '#009ACD',
- 'DeepSkyBlue4': '#00688B',
- 'dim gray': '#696969',
- 'dim grey': '#696969',
- 'DimGray': '#696969',
- 'DimGrey': '#696969',
- 'dodger blue': '#1E90FF',
- 'DodgerBlue': '#1E90FF',
- 'DodgerBlue1': '#1E90FF',
- 'DodgerBlue2': '#1C86EE',
- 'DodgerBlue3': '#1874CD',
- 'DodgerBlue4': '#104E8B',
- 'firebrick': '#B22222',
- 'firebrick1': '#FF3030',
- 'firebrick2': '#EE2C2C',
- 'firebrick3': '#CD2626',
- 'firebrick4': '#8B1A1A',
- 'floral white': '#FFFAF0',
- 'FloralWhite': '#FFFAF0',
- 'forest green': '#228B22',
- 'ForestGreen': '#228B22',
- 'gainsboro': '#DCDCDC',
- 'ghost white': '#F8F8FF',
- 'GhostWhite': '#F8F8FF',
- 'gold': '#FFD700',
- 'gold1': '#FFD700',
- 'gold2': '#EEC900',
- 'gold3': '#CDAD00',
- 'gold4': '#8B7500',
- 'goldenrod': '#DAA520',
- 'goldenrod1': '#FFC125',
- 'goldenrod2': '#EEB422',
- 'goldenrod3': '#CD9B1D',
- 'goldenrod4': '#8B6914',
- 'green': '#00FF00',
- 'green yellow': '#ADFF2F',
- 'green1': '#00FF00',
- 'green2': '#00EE00',
- 'green3': '#00CD00',
- 'green4': '#008B00',
- 'GreenYellow': '#ADFF2F',
- 'grey': '#BEBEBE',
- 'grey0': '#000000',
- 'grey1': '#030303',
- 'grey2': '#050505',
- 'grey3': '#080808',
- 'grey4': '#0A0A0A',
- 'grey5': '#0D0D0D',
- 'grey6': '#0F0F0F',
- 'grey7': '#121212',
- 'grey8': '#141414',
- 'grey9': '#171717',
- 'grey10': '#1A1A1A',
- 'grey11': '#1C1C1C',
- 'grey12': '#1F1F1F',
- 'grey13': '#212121',
- 'grey14': '#242424',
- 'grey15': '#262626',
- 'grey16': '#292929',
- 'grey17': '#2B2B2B',
- 'grey18': '#2E2E2E',
- 'grey19': '#303030',
- 'grey20': '#333333',
- 'grey21': '#363636',
- 'grey22': '#383838',
- 'grey23': '#3B3B3B',
- 'grey24': '#3D3D3D',
- 'grey25': '#404040',
- 'grey26': '#424242',
- 'grey27': '#454545',
- 'grey28': '#474747',
- 'grey29': '#4A4A4A',
- 'grey30': '#4D4D4D',
- 'grey31': '#4F4F4F',
- 'grey32': '#525252',
- 'grey33': '#545454',
- 'grey34': '#575757',
- 'grey35': '#595959',
- 'grey36': '#5C5C5C',
- 'grey37': '#5E5E5E',
- 'grey38': '#616161',
- 'grey39': '#636363',
- 'grey40': '#666666',
- 'grey41': '#696969',
- 'grey42': '#6B6B6B',
- 'grey43': '#6E6E6E',
- 'grey44': '#707070',
- 'grey45': '#737373',
- 'grey46': '#757575',
- 'grey47': '#787878',
- 'grey48': '#7A7A7A',
- 'grey49': '#7D7D7D',
- 'grey50': '#7F7F7F',
- 'grey51': '#828282',
- 'grey52': '#858585',
- 'grey53': '#878787',
- 'grey54': '#8A8A8A',
- 'grey55': '#8C8C8C',
- 'grey56': '#8F8F8F',
- 'grey57': '#919191',
- 'grey58': '#949494',
- 'grey59': '#969696',
- 'grey60': '#999999',
- 'grey61': '#9C9C9C',
- 'grey62': '#9E9E9E',
- 'grey63': '#A1A1A1',
- 'grey64': '#A3A3A3',
- 'grey65': '#A6A6A6',
- 'grey66': '#A8A8A8',
- 'grey67': '#ABABAB',
- 'grey68': '#ADADAD',
- 'grey69': '#B0B0B0',
- 'grey70': '#B3B3B3',
- 'grey71': '#B5B5B5',
- 'grey72': '#B8B8B8',
- 'grey73': '#BABABA',
- 'grey74': '#BDBDBD',
- 'grey75': '#BFBFBF',
- 'grey76': '#C2C2C2',
- 'grey77': '#C4C4C4',
- 'grey78': '#C7C7C7',
- 'grey79': '#C9C9C9',
- 'grey80': '#CCCCCC',
- 'grey81': '#CFCFCF',
- 'grey82': '#D1D1D1',
- 'grey83': '#D4D4D4',
- 'grey84': '#D6D6D6',
- 'grey85': '#D9D9D9',
- 'grey86': '#DBDBDB',
- 'grey87': '#DEDEDE',
- 'grey88': '#E0E0E0',
- 'grey89': '#E3E3E3',
- 'grey90': '#E5E5E5',
- 'grey91': '#E8E8E8',
- 'grey92': '#EBEBEB',
- 'grey93': '#EDEDED',
- 'grey94': '#F0F0F0',
- 'grey95': '#F2F2F2',
- 'grey96': '#F5F5F5',
- 'grey97': '#F7F7F7',
- 'grey98': '#FAFAFA',
- 'grey99': '#FCFCFC',
- 'grey100': '#FFFFFF',
- 'honeydew': '#F0FFF0',
- 'honeydew1': '#F0FFF0',
- 'honeydew2': '#E0EEE0',
- 'honeydew3': '#C1CDC1',
- 'honeydew4': '#838B83',
- 'hot pink': '#FF69B4',
- 'HotPink': '#FF69B4',
- 'HotPink1': '#FF6EB4',
- 'HotPink2': '#EE6AA7',
- 'HotPink3': '#CD6090',
- 'HotPink4': '#8B3A62',
- 'indian red': '#CD5C5C',
- 'IndianRed': '#CD5C5C',
- 'IndianRed1': '#FF6A6A',
- 'IndianRed2': '#EE6363',
- 'IndianRed3': '#CD5555',
- 'IndianRed4': '#8B3A3A',
- 'ivory': '#FFFFF0',
- 'ivory1': '#FFFFF0',
- 'ivory2': '#EEEEE0',
- 'ivory3': '#CDCDC1',
- 'ivory4': '#8B8B83',
- 'khaki': '#F0E68C',
- 'khaki1': '#FFF68F',
- 'khaki2': '#EEE685',
- 'khaki3': '#CDC673',
- 'khaki4': '#8B864E',
- 'lavender': '#E6E6FA',
- 'lavender blush': '#FFF0F5',
- 'LavenderBlush': '#FFF0F5',
- 'LavenderBlush1': '#FFF0F5',
- 'LavenderBlush2': '#EEE0E5',
- 'LavenderBlush3': '#CDC1C5',
- 'LavenderBlush4': '#8B8386',
- 'lawn green': '#7CFC00',
- 'LawnGreen': '#7CFC00',
- 'lemon chiffon': '#FFFACD',
- 'LemonChiffon': '#FFFACD',
- 'LemonChiffon1': '#FFFACD',
- 'LemonChiffon2': '#EEE9BF',
- 'LemonChiffon3': '#CDC9A5',
- 'LemonChiffon4': '#8B8970',
- 'light blue': '#ADD8E6',
- 'light coral': '#F08080',
- 'light cyan': '#E0FFFF',
- 'light goldenrod': '#EEDD82',
- 'light goldenrod yellow': '#FAFAD2',
- 'light gray': '#D3D3D3',
- 'light green': '#90EE90',
- 'light grey': '#D3D3D3',
- 'light pink': '#FFB6C1',
- 'light salmon': '#FFA07A',
- 'light sea green': '#20B2AA',
- 'light sky blue': '#87CEFA',
- 'light slate blue': '#8470FF',
- 'light slate gray': '#778899',
- 'light slate grey': '#778899',
- 'light steel blue': '#B0C4DE',
- 'light yellow': '#FFFFE0',
- 'LightBlue': '#ADD8E6',
- 'LightBlue1': '#BFEFFF',
- 'LightBlue2': '#B2DFEE',
- 'LightBlue3': '#9AC0CD',
- 'LightBlue4': '#68838B',
- 'LightCoral': '#F08080',
- 'LightCyan': '#E0FFFF',
- 'LightCyan1': '#E0FFFF',
- 'LightCyan2': '#D1EEEE',
- 'LightCyan3': '#B4CDCD',
- 'LightCyan4': '#7A8B8B',
- 'LightGoldenrod': '#EEDD82',
- 'LightGoldenrod1': '#FFEC8B',
- 'LightGoldenrod2': '#EEDC82',
- 'LightGoldenrod3': '#CDBE70',
- 'LightGoldenrod4': '#8B814C',
- 'LightGoldenrodYellow': '#FAFAD2',
- 'LightGray': '#D3D3D3',
- 'LightGreen': '#90EE90',
- 'LightGrey': '#D3D3D3',
- 'LightPink': '#FFB6C1',
- 'LightPink1': '#FFAEB9',
- 'LightPink2': '#EEA2AD',
- 'LightPink3': '#CD8C95',
- 'LightPink4': '#8B5F65',
- 'LightSalmon': '#FFA07A',
- 'LightSalmon1': '#FFA07A',
- 'LightSalmon2': '#EE9572',
- 'LightSalmon3': '#CD8162',
- 'LightSalmon4': '#8B5742',
- 'LightSeaGreen': '#20B2AA',
- 'LightSkyBlue': '#87CEFA',
- 'LightSkyBlue1': '#B0E2FF',
- 'LightSkyBlue2': '#A4D3EE',
- 'LightSkyBlue3': '#8DB6CD',
- 'LightSkyBlue4': '#607B8B',
- 'LightSlateBlue': '#8470FF',
- 'LightSlateGray': '#778899',
- 'LightSlateGrey': '#778899',
- 'LightSteelBlue': '#B0C4DE',
- 'LightSteelBlue1': '#CAE1FF',
- 'LightSteelBlue2': '#BCD2EE',
- 'LightSteelBlue3': '#A2B5CD',
- 'LightSteelBlue4': '#6E7B8B',
- 'LightYellow': '#FFFFE0',
- 'LightYellow1': '#FFFFE0',
- 'LightYellow2': '#EEEED1',
- 'LightYellow3': '#CDCDB4',
- 'LightYellow4': '#8B8B7A',
- 'lime green': '#32CD32',
- 'LimeGreen': '#32CD32',
- 'linen': '#FAF0E6',
- 'magenta': '#FF00FF',
- 'magenta1': '#FF00FF',
- 'magenta2': '#EE00EE',
- 'magenta3': '#CD00CD',
- 'magenta4': '#8B008B',
- 'maroon': '#B03060',
- 'maroon1': '#FF34B3',
- 'maroon2': '#EE30A7',
- 'maroon3': '#CD2990',
- 'maroon4': '#8B1C62',
- 'medium aquamarine': '#66CDAA',
- 'medium blue': '#0000CD',
- 'medium orchid': '#BA55D3',
- 'medium purple': '#9370DB',
- 'medium sea green': '#3CB371',
- 'medium slate blue': '#7B68EE',
- 'medium spring green': '#00FA9A',
- 'medium turquoise': '#48D1CC',
- 'medium violet red': '#C71585',
- 'MediumAquamarine': '#66CDAA',
- 'MediumBlue': '#0000CD',
- 'MediumOrchid': '#BA55D3',
- 'MediumOrchid1': '#E066FF',
- 'MediumOrchid2': '#D15FEE',
- 'MediumOrchid3': '#B452CD',
- 'MediumOrchid4': '#7A378B',
- 'MediumPurple': '#9370DB',
- 'MediumPurple1': '#AB82FF',
- 'MediumPurple2': '#9F79EE',
- 'MediumPurple3': '#8968CD',
- 'MediumPurple4': '#5D478B',
- 'MediumSeaGreen': '#3CB371',
- 'MediumSlateBlue': '#7B68EE',
- 'MediumSpringGreen': '#00FA9A',
- 'MediumTurquoise': '#48D1CC',
- 'MediumVioletRed': '#C71585',
- 'midnight blue': '#191970',
- 'MidnightBlue': '#191970',
- 'mint cream': '#F5FFFA',
- 'MintCream': '#F5FFFA',
- 'misty rose': '#FFE4E1',
- 'MistyRose': '#FFE4E1',
- 'MistyRose1': '#FFE4E1',
- 'MistyRose2': '#EED5D2',
- 'MistyRose3': '#CDB7B5',
- 'MistyRose4': '#8B7D7B',
- 'moccasin': '#FFE4B5',
- 'navajo white': '#FFDEAD',
- 'NavajoWhite': '#FFDEAD',
- 'NavajoWhite1': '#FFDEAD',
- 'NavajoWhite2': '#EECFA1',
- 'NavajoWhite3': '#CDB38B',
- 'NavajoWhite4': '#8B795E',
- 'navy': '#000080',
- 'navy blue': '#000080',
- 'NavyBlue': '#000080',
- 'old lace': '#FDF5E6',
- 'OldLace': '#FDF5E6',
- 'olive drab': '#6B8E23',
- 'OliveDrab': '#6B8E23',
- 'OliveDrab1': '#C0FF3E',
- 'OliveDrab2': '#B3EE3A',
- 'OliveDrab3': '#9ACD32',
- 'OliveDrab4': '#698B22',
- 'orange': '#FFA500',
- 'orange red': '#FF4500',
- 'orange1': '#FFA500',
- 'orange2': '#EE9A00',
- 'orange3': '#CD8500',
- 'orange4': '#8B5A00',
- 'OrangeRed': '#FF4500',
- 'OrangeRed1': '#FF4500',
- 'OrangeRed2': '#EE4000',
- 'OrangeRed3': '#CD3700',
- 'OrangeRed4': '#8B2500',
- 'orchid': '#DA70D6',
- 'orchid1': '#FF83FA',
- 'orchid2': '#EE7AE9',
- 'orchid3': '#CD69C9',
- 'orchid4': '#8B4789',
- 'pale goldenrod': '#EEE8AA',
- 'pale green': '#98FB98',
- 'pale turquoise': '#AFEEEE',
- 'pale violet red': '#DB7093',
- 'PaleGoldenrod': '#EEE8AA',
- 'PaleGreen': '#98FB98',
- 'PaleGreen1': '#9AFF9A',
- 'PaleGreen2': '#90EE90',
- 'PaleGreen3': '#7CCD7C',
- 'PaleGreen4': '#548B54',
- 'PaleTurquoise': '#AFEEEE',
- 'PaleTurquoise1': '#BBFFFF',
- 'PaleTurquoise2': '#AEEEEE',
- 'PaleTurquoise3': '#96CDCD',
- 'PaleTurquoise4': '#668B8B',
- 'PaleVioletRed': '#DB7093',
- 'PaleVioletRed1': '#FF82AB',
- 'PaleVioletRed2': '#EE799F',
- 'PaleVioletRed3': '#CD687F',
- 'PaleVioletRed4': '#8B475D',
- 'papaya whip': '#FFEFD5',
- 'PapayaWhip': '#FFEFD5',
- 'peach puff': '#FFDAB9',
- 'PeachPuff': '#FFDAB9',
- 'PeachPuff1': '#FFDAB9',
- 'PeachPuff2': '#EECBAD',
- 'PeachPuff3': '#CDAF95',
- 'PeachPuff4': '#8B7765',
- 'peru': '#CD853F',
- 'pink': '#FFC0CB',
- 'pink1': '#FFB5C5',
- 'pink2': '#EEA9B8',
- 'pink3': '#CD919E',
- 'pink4': '#8B636C',
- 'plum': '#DDA0DD',
- 'plum1': '#FFBBFF',
- 'plum2': '#EEAEEE',
- 'plum3': '#CD96CD',
- 'plum4': '#8B668B',
- 'powder blue': '#B0E0E6',
- 'PowderBlue': '#B0E0E6',
- 'purple': '#A020F0',
- 'purple1': '#9B30FF',
- 'purple2': '#912CEE',
- 'purple3': '#7D26CD',
- 'purple4': '#551A8B',
- 'red': '#FF0000',
- 'red1': '#FF0000',
- 'red2': '#EE0000',
- 'red3': '#CD0000',
- 'red4': '#8B0000',
- 'rosy brown': '#BC8F8F',
- 'RosyBrown': '#BC8F8F',
- 'RosyBrown1': '#FFC1C1',
- 'RosyBrown2': '#EEB4B4',
- 'RosyBrown3': '#CD9B9B',
- 'RosyBrown4': '#8B6969',
- 'royal blue': '#4169E1',
- 'RoyalBlue': '#4169E1',
- 'RoyalBlue1': '#4876FF',
- 'RoyalBlue2': '#436EEE',
- 'RoyalBlue3': '#3A5FCD',
- 'RoyalBlue4': '#27408B',
- 'saddle brown': '#8B4513',
- 'SaddleBrown': '#8B4513',
- 'salmon': '#FA8072',
- 'salmon1': '#FF8C69',
- 'salmon2': '#EE8262',
- 'salmon3': '#CD7054',
- 'salmon4': '#8B4C39',
- 'sandy brown': '#F4A460',
- 'SandyBrown': '#F4A460',
- 'sea green': '#2E8B57',
- 'SeaGreen': '#2E8B57',
- 'SeaGreen1': '#54FF9F',
- 'SeaGreen2': '#4EEE94',
- 'SeaGreen3': '#43CD80',
- 'SeaGreen4': '#2E8B57',
- 'seashell': '#FFF5EE',
- 'seashell1': '#FFF5EE',
- 'seashell2': '#EEE5DE',
- 'seashell3': '#CDC5BF',
- 'seashell4': '#8B8682',
- 'sienna': '#A0522D',
- 'sienna1': '#FF8247',
- 'sienna2': '#EE7942',
- 'sienna3': '#CD6839',
- 'sienna4': '#8B4726',
- 'sky blue': '#87CEEB',
- 'SkyBlue': '#87CEEB',
- 'SkyBlue1': '#87CEFF',
- 'SkyBlue2': '#7EC0EE',
- 'SkyBlue3': '#6CA6CD',
- 'SkyBlue4': '#4A708B',
- 'slate blue': '#6A5ACD',
- 'slate gray': '#708090',
- 'slate grey': '#708090',
- 'SlateBlue': '#6A5ACD',
- 'SlateBlue1': '#836FFF',
- 'SlateBlue2': '#7A67EE',
- 'SlateBlue3': '#6959CD',
- 'SlateBlue4': '#473C8B',
- 'SlateGray': '#708090',
- 'SlateGray1': '#C6E2FF',
- 'SlateGray2': '#B9D3EE',
- 'SlateGray3': '#9FB6CD',
- 'SlateGray4': '#6C7B8B',
- 'SlateGrey': '#708090',
- 'snow': '#FFFAFA',
- 'snow1': '#FFFAFA',
- 'snow2': '#EEE9E9',
- 'snow3': '#CDC9C9',
- 'snow4': '#8B8989',
- 'spring green': '#00FF7F',
- 'SpringGreen': '#00FF7F',
- 'SpringGreen1': '#00FF7F',
- 'SpringGreen2': '#00EE76',
- 'SpringGreen3': '#00CD66',
- 'SpringGreen4': '#008B45',
- 'steel blue': '#4682B4',
- 'SteelBlue': '#4682B4',
- 'SteelBlue1': '#63B8FF',
- 'SteelBlue2': '#5CACEE',
- 'SteelBlue3': '#4F94CD',
- 'SteelBlue4': '#36648B',
- 'tan': '#D2B48C',
- 'tan1': '#FFA54F',
- 'tan2': '#EE9A49',
- 'tan3': '#CD853F',
- 'tan4': '#8B5A2B',
- 'thistle': '#D8BFD8',
- 'thistle1': '#FFE1FF',
- 'thistle2': '#EED2EE',
- 'thistle3': '#CDB5CD',
- 'thistle4': '#8B7B8B',
- 'tomato': '#FF6347',
- 'tomato1': '#FF6347',
- 'tomato2': '#EE5C42',
- 'tomato3': '#CD4F39',
- 'tomato4': '#8B3626',
- 'turquoise': '#40E0D0',
- 'turquoise1': '#00F5FF',
- 'turquoise2': '#00E5EE',
- 'turquoise3': '#00C5CD',
- 'turquoise4': '#00868B',
- 'violet': '#EE82EE',
- 'violet red': '#D02090',
- 'VioletRed': '#D02090',
- 'VioletRed1': '#FF3E96',
- 'VioletRed2': '#EE3A8C',
- 'VioletRed3': '#CD3278',
- 'VioletRed4': '#8B2252',
- 'wheat': '#F5DEB3',
- 'wheat1': '#FFE7BA',
- 'wheat2': '#EED8AE',
- 'wheat3': '#CDBA96',
- 'wheat4': '#8B7E66',
- 'white': '#FFFFFF',
- 'white smoke': '#F5F5F5',
- 'WhiteSmoke': '#F5F5F5',
- 'yellow': '#FFFF00',
- 'yellow green': '#9ACD32',
- 'yellow1': '#FFFF00',
- 'yellow2': '#EEEE00',
- 'yellow3': '#CDCD00',
- 'yellow4': '#8B8B00',
- 'YellowGreen': '#9ACD32',
-}
-
-
-def make_window():
- layout = [[sg.Text(f'Swatches for {len(color_list)} Colors', font='Default 14'),],
- [sg.Text(f'Hover - see color "name"\nRight click - see hex value\nClick - see buttons & hex value copied to clipboard', font='Default 12')],
- [sg.Text(f'PySimpleGUI version: {sg.ver}', font='_ 12')],
- [sg.Text(f'Python version: {sys.version}', font='_ 12')],
- [sg.Text(f'tkinter version: {sg.tclversion_detailed}', font='_ 12')],
- ]
-
-
- for rows in range(len(color_list)//COLORS_PER_ROW+1):
- row = []
- for i in range(COLORS_PER_ROW):
- try:
- color = color_list[rows*COLORS_PER_ROW+i]
- row.append(sg.T(' ', s=1, background_color=color, text_color=color, font=('Default', font_size), right_click_menu=['_', color_map[color]],
- tooltip=color, enable_events=True, key=(color, color_map[color])))
- except IndexError as e:
- break
- except Exception as e:
- sg.popup_error(f'Error while creating color window. Something with the Text elements perhaps....', e,
- f'rows = {rows} i = {i}')
- break
- layout.append(row)
-
- return sg.Window('Color Swatches Viewer', layout, font='Any 9', element_padding=(1,1), border_depth=0, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, use_ttk_buttons=True)
-
-def main():
- sg.theme('black')
- window = make_window()
- # -- Event loop --
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- continue
- elif isinstance(event, tuple):
- color, color_hex = event[0], event[1]
- else:
- color, color_hex = hex_to_color[event], event
- # -- Create a secondary window that shows white and black text on chosen color
- layout2 = [[sg.Text(color_hex + ' on clipboard')],
- [sg.DummyButton(color, button_color=('white',color), tooltip=color_hex),
- sg.DummyButton(color, button_color=('black',color), tooltip=color_hex)]]
- window2 = sg.Window('Buttons with white and black text', layout2, keep_on_top=True, finalize=True)
- sg.clipboard_set(color_hex)
-
- window.close()
-
-if __name__ == '__main__':
- sg.popup_quick_message('Building your color window... one moment please...', background_color='red', text_color='white', font='Any 14')
-
- sg.set_options(button_element_size=(12, 1),
- element_padding=(0, 0),
- auto_size_buttons=False,
- border_width=1, tooltip_time=100)
-
- # -- Create primary color viewer window --
- hex_to_color = {v: k for k, v in color_map.items()}
- color_list = list(color_map.keys())
- # [key for key in color_map]
- COLORS_PER_ROW = 40
- font_size = 18
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Column_And_Frames.py b/DemoPrograms/Demo_Column_And_Frames.py
index ec3b94d20..3b6c8d79e 100644
--- a/DemoPrograms/Demo_Column_And_Frames.py
+++ b/DemoPrograms/Demo_Column_And_Frames.py
@@ -1,71 +1,63 @@
+# this one long import has the effect of making the code more compact as there is no 'sg.' prefix required for Elements
import PySimpleGUI as sg
+from PySimpleGUI import InputCombo, Combo, Multiline, ML,
+ MLine, Checkbox, CB, Check,
+ Button, B, Btn, ButtonMenu,
+ Canvas, Column, Col, Combo,
+ Frame, Graph, Image, InputText,
+ Input, In, Listbox, LBox, Menu,
+ Multiline, ML, MLine, OptionMenu,
+ Output, Pane, ProgressBar, Radio,
+ Slider, Spin, StatusBar, Tab,
+ TabGroup, Table, Text, Txt, T,
+ Tree, TreeData, VerticalSeparator, Window, Sizer
"""
- Demo sg.Columns and sg.Frames
- Demonstrates using mixture of sg.Column and sg.Frame elements to create a nice window layout.
+ Demo Columns and Frames
+ Demonstrates using mixture of Column and Frame elements to create a nice window layout.
A couple of the concepts shown here include:
- * Using sg.Columns and sg.Frames with specific sizes on them
- * Buttons that have the same text on them that arew differentiated using explicit keys
- * One way to hard-code the size of a Frame is to hard-code the size of a Column inside the frame
-
- CAUTION:
- Using explicit sizes on Column and Frame elements may not have the same effect on
- all computers. Hard coding parts of layouts can sometimes not have the same result on all computers.
-
- There are 3 sg.Columns. Two are side by side at the top and the third is along the bottom
-
- When there are multiple Columns on a row, be aware that the default is for those Columns to be
- aligned along their center. If you want them to be top-aligned, then you need to use the
- vtop helper function to make that happen.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
+ * Using Columns and Frames with specific sizes on them
+ * Importing all required classes so that "sg." is not required on any objects. This makes the code more compact and readable
+ There are 3 columns. Two are side by side at the top and the third is along the bottom
"""
-col2 = sg.Column([[sg.Frame('Accounts:', [[sg.Column([[sg.Listbox(['Account '+str(i) for i in range(1,16)],
- key='-ACCT-LIST-',size=(15,20)),]],size=(150,400))]])]],pad=(0,0))
-
-col1 = sg.Column([
- # Categories sg.Frame
- [sg.Frame('Categories:',[[ sg.Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10,1)),
- sg.Radio('Software', 'radio1', key='-SOFTWARE-', size=(10,1))]],)],
- # Information sg.Frame
- [sg.Frame('Information:', [[sg.Text(), sg.Column([[sg.Text('Account:')],
- [sg.Input(key='-ACCOUNT-IN-', size=(19,1))],
- [sg.Text('User Id:')],
- [sg.Input(key='-USERID-IN-', size=(19,1)),
- sg.Button('Copy', key='-USERID-')],
- [sg.Text('Password:')],
- [sg.Input(key='-PW-IN-', size=(19,1)),
- sg.Button('Copy', key='-PASS-')],
- [sg.Text('Location:')],
- [sg.Input(key='-LOC-IN-', size=(19,1)),
- sg.Button('Copy', key='-LOC-')],
- [sg.Text('Notes:')],
- [sg.Multiline(key='-NOTES-', size=(25,5))],
- ], size=(235,350), pad=(0,0))]])], ], pad=(0,0))
-
-col3 = sg.Column([[sg.Frame('Actions:',
- [[sg.Column([[sg.Button('Save'), sg.Button('Clear'), sg.Button('Delete'), ]],
- size=(450,45), pad=(0,0))]])]], pad=(0,0))
-
-# The final layout is a simple one
-layout = [[col1, col2],
- [col3]]
-
-# A perhaps better layout would have been to use the vtop layout helpful function.
-# This would allow the col2 column to have a different height and still be top aligned
-# layout = [sg.vtop([col1, col2]),
-# [col3]]
-
-
-window = sg.Window('Columns and Frames', layout)
+sg.change_look_and_feel('GreenTan')
+
+col2 = Column([[Frame('Accounts:', [[Column([[Listbox(['Account '+str(i) for i in range(1, 16)],
+ key='-ACCT-LIST-', size=(15, 20)), ]], size=(150, 400))]])]], pad=(0, 0))
+
+col1 = Column([
+ # Categories frame
+ [Frame('Categories:', [[Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10, 1)),
+ Radio('Software', 'radio1', key='-SOFTWARE-', size=(10, 1))]],)],
+ # Information frame
+ [Frame('Information:', [[Column([[Text('Account:')],
+ [Input(key='-ACCOUNT-IN-', size=(19, 1))],
+ [Text('User Id:')],
+ [Input(key='-USERID-IN-', size=(19, 1)),
+ Button('Copy', key='-USERID-')],
+ [Text('Password:')],
+ [Input(key='-PW-IN-', size=(19, 1)),
+ Button('Copy', key='-PASS-')],
+ [Text('Location:')],
+ [Input(key='-LOC-IN-', size=(19, 1)),
+ Button('Copy', key='-LOC')],
+ [Text('Notes:')],
+ [Multiline(key='-NOTES-', size=(25, 5))],
+ ], size=(235, 350), pad=(0, 0))]])], ], pad=(0, 0))
+
+col3 = Column([[Frame('Actions:', [[Column([[Button('Save'), Button(
+ 'Clear'), Button('Delete'), ]], size=(450, 45), pad=(0, 0))]])]], pad=(0, 0))
+
+layout = [[col1, col2], [col3]]
+
+window = Window('Passwords', layout)
while True:
event, values = window.read()
print(event, values)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
-window.close()
\ No newline at end of file
+window.close()
diff --git a/DemoPrograms/Demo_Column_Collapsible_Sections.py b/DemoPrograms/Demo_Column_Collapsible_Sections.py
deleted file mode 100644
index 0cfa196ee..000000000
--- a/DemoPrograms/Demo_Column_Collapsible_Sections.py
+++ /dev/null
@@ -1,77 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - "Collapsible" sections of windows
-
- This demo shows one techinique for creating a collapsible section (Column) within your window.
-
- To open/close a section, click on the arrow or name of the section.
- Section 2 can also be controlled using the checkbox at the top of the window just to
- show that there are multiple way to trigger events such as these.
-
- Feel free to modify to use the fonts and sizes of your choosing. It's 1 line of code to make the section.
- It could have been done directly in the layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def Collapsible(layout, key, title='', arrows=(sg.SYMBOL_DOWN, sg.SYMBOL_UP), collapsed=False):
- """
- User Defined Element
- A "collapsable section" element. Like a container element that can be collapsed and brought back
- :param layout:Tuple[List[sg.Element]]: The layout for the section
- :param key:Any: Key used to make this section visible / invisible
- :param title:str: Title to show next to arrow
- :param arrows:Tuple[str, str]: The strings to use to show the section is (Open, Closed).
- :param collapsed:bool: If True, then the section begins in a collapsed state
- :return:sg.Column: Column including the arrows, title and the layout that is pinned
- """
- return sg.Column([[sg.T((arrows[1] if collapsed else arrows[0]), enable_events=True, k=key+'-BUTTON-'),
- sg.T(title, enable_events=True, key=key+'-TITLE-')],
- [sg.pin(sg.Column(layout, key=key, visible=not collapsed, metadata=arrows))]], pad=(0,0))
-
-
-SEC1_KEY = '-SECTION1-'
-SEC2_KEY = '-SECTION2-'
-
-section1 = [[sg.Input('Input sec 1', key='-IN1-')],
- [sg.Input(key='-IN11-')],
- [sg.Button('Button section 1', button_color='yellow on green'),
- sg.Button('Button2 section 1', button_color='yellow on green'),
- sg.Button('Button3 section 1', button_color='yellow on green')]]
-
-section2 = [[sg.I('Input sec 2', k='-IN2-')],
- [sg.I(k='-IN21-')],
- [sg.B('Button section 2', button_color=('yellow', 'purple')),
- sg.B('Button2 section 2', button_color=('yellow', 'purple')),
- sg.B('Button3 section 2', button_color=('yellow', 'purple'))]]
-
-layout = [[sg.Text('Window with 2 collapsible sections')],
- [sg.Checkbox('Blank checkbox'), sg.Checkbox('Hide Section 2', enable_events=True, key='-OPEN SEC2-CHECKBOX-')],
- #### Section 1 part ####
- [Collapsible(section1, SEC1_KEY, 'Section 1', collapsed=True)],
- #### Section 2 part ####
- [Collapsible(section2, SEC2_KEY, 'Section 2', arrows=( sg.SYMBOL_TITLEBAR_MINIMIZE, sg.SYMBOL_TITLEBAR_MAXIMIZE))],
- [sg.Button('Button1'),sg.Button('Button2'), sg.Button('Exit')]]
-
-window = sg.Window('Visible / Invisible Element Demo', layout)
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if event.startswith(SEC1_KEY):
- window[SEC1_KEY].update(visible=not window[SEC1_KEY].visible)
- window[SEC1_KEY+'-BUTTON-'].update(window[SEC1_KEY].metadata[0] if window[SEC1_KEY].visible else window[SEC1_KEY].metadata[1])
-
- if event.startswith(SEC2_KEY) or event == '-OPEN SEC2-CHECKBOX-':
- window[SEC2_KEY].update(visible=not window[SEC2_KEY].visible)
- window[SEC2_KEY+'-BUTTON-'].update(window[SEC2_KEY].metadata[0] if window[SEC2_KEY].visible else window[SEC2_KEY].metadata[1])
- window['-OPEN SEC2-CHECKBOX-'].update(not window[SEC2_KEY].visible)
-
-window.close()
diff --git a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py b/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py
deleted file mode 100644
index f3bec7c7b..000000000
--- a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIQt as sg
-
-"""
- Demo - Multiple layouts in a single window that are swapped in and out
-
- If you've ever wanted to replace the contents of a window with another layout then perhaps
- this demo is for you. You cannot actually change the layout of a window dynamically, but what
- you can do is make elements visible and invisible.
-
- To "swap out" a portion of a window, use a Column element for that portion. Add multiple Columns
- on the same row and make only 1 of them active at a time
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ----------- Create the 3 layouts this Window will display -----------
-layout1 = [[sg.Text('This is layout 1 - It is all Checkboxes')],
- *[[sg.CB(f'Checkbox {i}')] for i in range(5)]]
-
-layout2 = [[sg.Text('This is layout 2')],
- [sg.Input(key='-IN-')],
- [sg.Input(key='-IN2-')]]
-
-layout3 = [[sg.Text('This is layout 3 - It is all Radio Buttons')],
- *[[sg.Radio(f'Radio {i}', 1)] for i in range(8)]]
-
-# ----------- Create actual layout using Columns and a row of Buttons
-layout = [[sg.Column(layout1, key='-COL1-'), sg.Column(layout2, visible=False, key='-COL2-'), sg.Column(layout3, visible=False, key='-COL3-')],
- [sg.Button('Cycle Layout'), sg.Button('1'), sg.Button('2'), sg.Button('3'), sg.Button('Exit')]]
-
-window = sg.Window('Swapping the contents of a window', layout)
-
-layout = 1 # The currently visible layout
-while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == 'Cycle Layout':
- window[f'-COL{layout}-'].update(visible=False)
- layout = layout + 1 if layout < 3 else 1
- window[f'-COL{layout}-'].update(visible=True)
- elif event in '123':
- window[f'-COL{layout}-'].update(visible=False)
- layout = int(event)
- window[f'-COL{layout}-'].update(visible=True)
-window.close()
diff --git a/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py b/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py
deleted file mode 100644
index 0de63c1ae..000000000
--- a/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py
+++ /dev/null
@@ -1,79 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Columns with a hard coded size that can have elements justified within it.
-
- The Column element can have the size set to a fixed size, but when doing so, PySimpleGUI has
- a limitation that the contents can't be justified using the normal element_justification parameter.
-
- What to do?
-
- The Sizer Element to the rescue.
-
- PySimpleGUI likes to have layouts that size themselves rather than hard coded using a size parameter. The
- Sizer Element enables you to create columns with fixed size by making the contents of your column a fixed size.
- It is an invisible "padding" type of element. It has a width and a height parameter.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-'''
-M#"""""""'M dP
-## mmmm. `M 88
-#' .M 88d888b. .d8888b. 88 .dP .d8888b. 88d888b.
-M# MMMb.'YM 88' `88 88' `88 88888" 88ooood8 88' `88
-M# MMMM' M 88 88. .88 88 `8b. 88. ... 88 88
-M# .;M dP `88888P' dP `YP `88888P' dP dP
-M#########M
-'''
-
-
-# Let's say this is your layout and you want to center it in a 500 x 300 pixel Column Element.
-col_interior = [[sg.Text('My Window')],
- [sg.In()],
- [sg.In()],
- [sg.Button('Go'), sg.Button('Exit'), sg.Cancel(), sg.Ok()]]
-
-# Intuition would be to write it as this:
-layout = [[sg.Text('This layout is broken. The size of the Column is correct, but the elements are not justified')],
- [sg.Column(col_interior, element_justification='c', size=(500, 300), background_color='red')]]
-
-# But when you run it, you'll see that your interior is not centered.
-
-window = sg.Window('Window Title', layout)
-
-window.read(close=True)
-
-
-'''
-M""MMM""MMM""M dP
-M MMM MMM M 88
-M MMP MMP M .d8888b. 88d888b. 88 .dP .d8888b.
-M MM' MM' .M 88' `88 88' `88 88888" Y8ooooo.
-M `' . '' .MM 88. .88 88 88 `8b. 88
-M .d .dMMM `88888P' dP dP `YP `88888P'
-MMMMMMMMMMMMMM
-'''
-
-def ColumnFixedSize(layout, size=(None, None), *args, **kwargs):
- # An addition column is needed to wrap the column with the Sizers because the colors will not be set on the space the sizers take
- return sg.Column([[sg.Column([[sg.Sizer(0,size[1]-1), sg.Column([[sg.Sizer(size[0]-2,0)]] + layout, *args, **kwargs, pad=(0,0))]], *args, **kwargs)]],pad=(0,0))
-
-col_interior = [[sg.Text('My Window')],
- [sg.In()],
- [sg.In()],
- [sg.Button('Go'), sg.Button('Exit'), sg.Cancel(), sg.Ok()]]
-
-
-layout = [[sg.Text('Below is a column that is 500 x 300')],
- [sg.Text('With the interior centered')],
- [ColumnFixedSize(col_interior, size=(500, 300), background_color='red', element_justification='c', vertical_alignment='t')]]
-
-window = sg.Window('Window Title', layout)
-
-window.read(close=True)
-
diff --git a/DemoPrograms/Demo_Columns.py b/DemoPrograms/Demo_Columns.py
index d26dcfeae..d4489d066 100644
--- a/DemoPrograms/Demo_Columns.py
+++ b/DemoPrograms/Demo_Columns.py
@@ -3,29 +3,24 @@
'''
Usage of Column Element
-
- How to embed a layout in a layout
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-sg.theme('BlueMono')
+sg.change_look_and_feel('BlueMono')
+css = {'text_color': 'white', 'background_color': 'blue'}
# Column layout
-col = [[sg.Text('col Row 1', text_color='white', background_color='blue')],
- [sg.Text('col Row 2', text_color='white', background_color='blue', pad=(0,(25,0))),sg.T('Another item'), sg.T('another'), sg.Input('col input 1')],
- [sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]]
+col = [[sg.Text('col Row 1', **css)],
+ [sg.Text('col Row 2', **css), sg.Input('col input 1')],
+ [sg.Text('col Row 3', **css), sg.Input('col input 2')]]
# Window layout
layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'),
select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20, 3)),
- sg.Column(col, background_color='blue')],
+ sg.Col(col, background_color='blue')],
[sg.Input('Last input')],
[sg.OK()]]
# Display the window and get values
-window = sg.Window('Column Element', layout, margins=(0,0), element_padding=(0,0))
+window = sg.Window('Compact 1-line form with column', layout)
event, values = window.read()
sg.popup(event, values, line_width=200)
diff --git a/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py b/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py
deleted file mode 100644
index 7bb56333e..000000000
--- a/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Combo File Chooser - with clearable history
-
- This is a design pattern that is very useful for programs that you run often that requires
- a filename be entered. You've got 4 options to use to get your filename with this pattern:
- 1. Copy and paste a filename into the combo element
- 2. Use the last used item which will be visible when you create the window
- 3. Choose an item from the list of previously used items
- 4. Browse for a new name
-
- To clear the list of previous entries, click the "Clear History" button.
-
- The history is stored in a json file using the PySimpleGUI User Settings APIs
-
- The code is as sparse as possible to enable easy integration into your code.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-layout = [[sg.Combo(sorted(sg.user_settings_get_entry('-filenames-', [])), default_value=sg.user_settings_get_entry('-last filename-', ''), size=(50, 1), key='-FILENAME-'), sg.FileBrowse(), sg.B('Clear History')],
- [sg.Button('Ok', bind_return_key=True), sg.Button('Cancel')]]
-
-window = sg.Window('Filename Chooser With History', layout)
-
-while True:
- event, values = window.read()
-
- if event in (sg.WIN_CLOSED, 'Cancel'):
- break
- if event == 'Ok':
- # If OK, then need to add the filename to the list of files and also set as the last used filename
- 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-'])
- break
- elif event == 'Clear History':
- sg.user_settings_set_entry('-filenames-', [])
- sg.user_settings_set_entry('-last filename-', '')
- window['-FILENAME-'].update(values=[], value='')
-
-window.close()
diff --git a/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py b/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py
index 7f4607c85..4bebce3e9 100644
--- a/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py
+++ b/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py
@@ -28,11 +28,7 @@
PLEASE OH PLEASE OH PLEASE NEVER EVER EVER do this:
from PySimpleGUI import *
There is a bot scanning GitHub for this statement. If found in your code, a squad of assassins will be dispatched
- from the PySimpleGUI headquarters and you will be hunted down and forced to change your code.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ from the PySimpleGUI headquarters and you will be hunted down and forced to change your code.
"""
# A user created shortcut....
@@ -45,7 +41,7 @@
layout = [[M(size=(30, 3))],
[B('OK')]]
-window = sg.Window('Shortcuts', layout)
+window = sg.Window('Shortcuts', layout).read()
event, values = window.read()
sg.popup_scrolled(event, values)
window.close()
diff --git a/DemoPrograms/Demo_Compare_Files.py b/DemoPrograms/Demo_Compare_Files.py
index b3ce8a7c7..a57698773 100644
--- a/DemoPrograms/Demo_Compare_Files.py
+++ b/DemoPrograms/Demo_Compare_Files.py
@@ -3,20 +3,14 @@
'''
Simple "diff" in PySimpleGUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-sg.theme('Dark Blue 3')
-
def GetFilesToCompare():
form_rows = [[sg.Text('Enter 2 files to comare')],
[sg.Text('File 1', size=(15, 1)),
sg.InputText(key='-file1-'), sg.FileBrowse()],
[sg.Text('File 2', size=(15, 1)), sg.InputText(key='-file2-'),
- sg.FileBrowse(target='-file2-')],
+ sg.FileBrowse(target='file2')],
[sg.Submit(), sg.Cancel()]]
window = sg.Window('File Compare', form_rows)
diff --git a/DemoPrograms/Demo_Control_Panel_Button_Grid.py b/DemoPrograms/Demo_Control_Panel_Button_Grid.py
deleted file mode 100644
index 343ef2e07..000000000
--- a/DemoPrograms/Demo_Control_Panel_Button_Grid.py
+++ /dev/null
@@ -1,127 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Creates a grid of buttons include of a column for scrolling
- This window looks much like a control panel
-
- NOTE - The SCROLLING using the mousewheel is known to have a bug in the tkinter port. You will need to have your mouse over the scrollbar to scroll with the mousewheel
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def GraphicButton(text:str, key:str, image_data):
- text = text.replace('_', ' ')
- button = sg.Button('', image_data=image_data, button_color=('white', '#9FB8AD'), font='Any 15', key=key, border_width=0)
- text = sg.Text(text, font='Any 10', size=(15,1), justification='center',)
- return sg.Column([[button],[text]], element_justification='c')
-
-def main():
- sg.ChangeLookAndFeel('GreenTan')
-
- layout = [ [sg.Text('Control Panel. Click Abort to exit.')]]
- layout += [[sg.Column([[GraphicButton(png_names[i+j*5], png_names[i+j*5] , png_images[i+j*5]) for i in range(2)] for j in range(7)], scrollable=True, size=(400,400))]]
-
- window = sg.Window('Control Panel', layout, font='any 15', finalize=True)
- while True: # ---===--- The event loop --- #
- event, values = window.read()
- print(event)
- if event in ('Exit','Abort', None): # Exit button or X
- break
- window.close()
-
-
-Abort = b'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'
-Add_event = b'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'
-Alarm_clock = b'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'
-Alarm = b'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'
-Atomic = b'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'
-Bomb = b'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'
-Calendar = b'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'
-Call = b'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'
-Circulation = b'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'
-Clock_face = b'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'
-Clock = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAPPklEQVR42s1aCVRU1xn+3syw75vgsCkgKItRgkSljda2kqgQT2Nq3UhOmpgmFVM9WYhGNO5L0ihxiXs0eqxK3G2Mu2iMERTESNxBQEAUkE22Gej/X+YNMwyQGDXpPeedWbjz3vf991++/14kPMHR1NSkbGhocFCpVOUKhUL7JJ4hPa4bVVVV9bpz587w+/fv966trVVXV1d7VFZWetTX16vozxozM7MiIlJkYWFR4OLikt61a9ddbm5uGb8pAQLd5+7du3GFhYXDCbxXXV0dyNJseRBYcUmSBI1GA1oJEDEQKdTU1Ig51tbW+QEBAbt69uy5Ua1Wp/5qBAhIYG5u7pycnJwR5eXlMDc3h4ODA6ysrAQ4WgUwGQZMKyAuBszkaCXEfP6O55SWlgqCgYGBydHR0VNpVa4+MQL0IOf8/PxZ2dnZ4+nBKkdHR9jb24PcBffu3RNg+D2Dq6iowIMHDwRIchtYWlqKi1eEBxPiwaR5Ds/VarWaiIiIVUOHDp1mY2NT+lgJkGWDL1++vJcs78dAnJychLXz8vJAboQbN27g6tWruHXrFgE2h6OjE5ydnWBra4damsdz68mNGDhZGa6urmLVZCL8SgQEGbr/zfj4+BhPT8+sx0KAXGJYVlbWlqKiIlvyVfEgWgncvn0bR48eRWZmJroHBSE4NAw9+kTBys0LCktrKC2sYUavUqMGjXVkYboaqsqRe+k8cq5kobSsDBTQwhg8GhsbBRGde1W98cYbo8LDw/c9EoHi4uIJly5dSqLgkzw8PISLXLlyBcePH8fJkycR1b8//hA7Aja+IbDo5AVLchcblQRzJV1098p7RbB2cIRkZgk2dp2WLM0giUhVwU1knvgGebeyYWdnJ1yMSfBgI9HKNo0dO3YiudTSX0SALB9z/vz53WQNiZec/fzHH3/EmjVroO7cGcP+OgZOYVGw6eQNVysFHMwVsCDg7OYK3T0unT4K3x494eDsJr7nBzKJGk0jqjUEtKEedy6n4+LJQygrKxUBziT4YhJkwKZ33nnnhb59++59KALksyEE/kxJSYltZwJLqRLnzp3DunVrMfjPg9H/pVdh498bdtpqeLnaw0ypbL6hDjy/ssVTj+yHT3BvOHTqLP5O/KBSSLBQNLMpKi1HvcICTfU1uHh4J25czhLAZRKcoYhE1eLFi/tS7bj0swjQj1wuXLiQRmmyi7e3N1mmDN9++y1Wr16NV159FUHPjYa9uiu62qtQffc2SvJvITAiSoBuJNDVbN0GsjJdGSkH0S2MCLi4iYcxbgVNVNIbZZMWe5bPw2vvJqKivkkE+bXvDuPqhTTxTAbPMcEJgLwgZ9WqVREU+CU/SeDmzZvLicCb7POcFdLS0rBkyWKMi3sFQcNfh6tbJ3jbKoUleVw8cQD+4f1QZ26H+3VkOXqokkDyXzW11WKOlbWNHrzuZ9i2dD7CfzcIoU/3haWKgxgiPm6kpeDS2VNseVEAmQSn6MjIyBUffPDBWx0SILbdzpw5k0XAVZzmMjIysHTpUvTr1xdRcZPRyccPvnZKAUS+QWnlA1zJzoWbr7/OTZpBsittWjgVryTM0X+v+xn9rQnZWZkICuulvw+vikJqTquZR/Yi52oWyAv0qfb69euaTZs2Bfv6+l5rlwDl8u0EekSXLl1ETv/qq6+IfQlGTpoO56Bw+DuQRJBaflZS24iyWq0+QGULK3VTNi2YipeJgAzeyI2kFhD8ngq1KHT8ubGhDue+2YkrWT+IOsNxwVWfwCcnJSW91CYB0jYRKSkpqVzuuXp+//33WLZsGSYlfAiPQaMQ6GQmsow8Cqu15OuN7YKXdCsQ9/4c4W5tgZdXyhC8fI+yonykH/tauDC7Egc1Z8ENGzb0If2UZkKAlmhJamrqRD8/P36PrVu3wtbGBs9PSIQ7xYNZRRHcfQME4GICX17fAl7vNq2AbVzwIca9P1t8Z6mUjGJABiruoQPPnxvqanEgeTNejHsNmSnf4OL5NFF75FiglJo0c+bMt00InDhxIpeWy9vd3V1Yf+XKlZg8bRbco2LRzVGFvKx0lBbkwevpgahQWOtTpqIN8HIQf0EuNO69ZgLWKoUJeIXuC4Xuu5uXf8DaT2bjw09WwMHJGdVl93CBMtmBAwf0tYG0WB6ldB8jAiS+etGkdC7rXG0PHTqE69euYezUj+ETEAQ3KlQMuLamFmezrkHt371D8PLnL+ZPxVgdAVszRYfg+TqwfROGjRxn4G4U0CmHcPTwQZCUEQQ4sezYsaN3WFhYhp7AtWvXpn/33Xcz/P39QaJNuE9oaAj6vZ6IAFcbWKmaLVr0QEs5u1EPXu8CBv6tJ0PXeiIwRkfAzkyhByWDV0oGQSwZx4FsjOwfM3H+dIqQLqRShWiMjY2dMWXKlI/0BChQdpPmiWX/Z/dZv349Jn4wHeqoGOE+sgTIrdI2V1qgQ/AysHVEYPS7s9sFrw9iyTSI5VRddb8UWWdPglIo2L05PknG76FVeEFPgMRZKinMCGdnZ6Snp2PPnj1466NP4B0aAU8bpQB6h6xfSRVTfqgheMMcLz+c56yZNwWjdATMlND3A0rJIIhhHMQKA/DynMxvj1BGXA6SE+wtoA6QbJ7WR09g165dhdRBecjpk/0sLmEefAOD4WZNUKiW5FRqdVW2Vf7uIMevnjsF46fMFe/NVa3dwwCowfetwfNrxqmjoqByfeLeg4xcQMNTzKToVn755Zf15F8K1uJUiYXWH/nuXHTp2gWOFgrUa4H8Ks1DgZd0BF4nAg8LvmUlmu+VfvIwPvtsKUJCQkT/cfDgQYpnrUr8mWSDC/nXPZYO3HQzAe6iYifPhrOFhHtXL+BGdg7qLB3Rf8iLBn4rGdSBVgGsm7N3YSKGlhTBxs5eL7Hl38jvZbJ6d5j5byxIeFt89lB7Iv6dBKSeOIikpM8QFRXF6Z4JtPycV2Dt2rViBaga4+LFi0I+/GXSLHirO8NSW4PiigeobFTCnlpFOce31AFT8Ezo+L6vEBoeCbW3D9oaVqr225H7hbnNc8ilPUjOnz91DAsXLcKAAQNEM3XkyJGWFeBB5bmQKp0Hl2y5t33pX4no4h8IF0sFimuaZYOyVZpsF/x+At87Eh5ePkZuYxrELaLQqDIb1Bj+Lis9FTNmzEB/6gBJ7oBa3JYY4LFt27ZU0uAR3BFxlPMqjJs0jZqRp9DJSom7RKBG02QC3lSkmYLvKMcbxxPa1VV51y9j9uzZLOZA9YqLrXEW2rdv324SSrHcA3Aho34AI8fHwzt8AHypcSkj1VnV0Niq+LQPvjO5zU8VKMNYaQ1e/h0PraYet7Ovk5dsFNsvpNdAOCnT72mpA8RqOkmJGRzlXAd4uyQkrCeeGR0PHzsz0cOW1TUa5XijOkBfHNvXAr6tAtVejpcM7tWWKLxbWIBTKcdB7a3YBWEDjx49mjxqRkslpsLQa8WKFeksJViysvbmEfOP99G5swfM6U6lpPv54U3aBqhUZkY6Xgbv6eNjtEqSjmxHOb7FJSVUV1bAwcHeYI6EvJybWE+9OHtHcnIy+z8OHz7cm0aLFuJBjXMuRbY31wJuIvgaNubv8OrZD+5UzArKa7B12UJEDhyM4PBnTMDLln+YAmUInj8vWTAbPXs/jcHPPS++a9RqcO9OIZYvXy56ZPZ/Ct486tSM1SiP/fv3L6EcO5EbeeqLhSr18vLGwLET4GCppNw8EUPGvoHuT4XrmxAZvNrbxxQojLOPZEQGupWSTHTVF6tWwNrGGmOpB7+dl4sTx48J8IRPuM/gwYOpKUsy7QfI7yM+/fTTVN5GYenKK8EjKjoWfhHPwob0DMeC/LD//mcD+vx+UJvgDVVmR+Db0lV8j5K7xWLftYKE3Lp16wQBlvg69+lDw7Qj09WD7ZSBRrCo470g7oLcPdwxcOR42Du7iM2etnR8WzleAVOFKbUCbyg7WqflooJ8YXXepmff5wafegB6m9x2T8yjuLi4G0V3FrFXcVVm5tbW1vAP7I7IYX+DuaWliXs8ao5vS1cVFxUIA7LPc1Hl4kXuo6FOLDgwMLD9XQkeGzduXH7q1Kk3GTjv8cs7yoGhT6HnH2OoQVcYAbt1/SrOHD+MMeP/+bPBa+prMW/6h5i54GMTXVVextv0VcLq3IHt3r1biMshQ4ZQolzR8b4QD7K8S2JiYhoJuy78mXtRXkaWsn7BYQjpPwgqpUoA0dIKvffaKCRtTDbJNAysgYCyRG8uTsY5PuPcWRw/dBDvTZmmB3+/rES8ckPFBuRtHY5H3pk7e/ZshKur60/vzOkCOiQhIeEMSQtb+TuWGQEBAXD39EKvZ6NhZWuHQ7u2IzLqWbhRp9RWgVowPQEjRsehe4+QNnvnfbt3oE/kM/Ak1XmH3IZdli1va2sr/J/dhxqtKnKhvqGhoT9vb1QexDhm/vz5uykeJHYjXgk+JurRowfUXl7oGhIOL79uHeb4BYkJeGnMy0QguN3Gv46kezlZvoB8nvdgebVZLrPbUPvYtHnz5heoB3643Wl5kP9N+Pzzz5OcnJwkDlT5EIJFFR9q2Du5oCsLPrWXSZpkF9q8diX+FP08vGm+YZrk14aGeipSReJcYO/evSLeWOt8/fXXYv8nOzu7ae7cuRPj4+N/2fmAPE6fPj1s5syZW8gnbXnXTo4LXg3WTr16PQWlyhy2Ts5w81DDpZOHUaAb5viG+jqUUoVvatSIHYZjx46J0x7O+ZzjuZ1lGUPSpopS+qiYmJhHO6GRB1Xm4MmTJ+8lK/nxaYq8f88Xr4wXuRSlNwQH9xDnYpKkQBPdXUWEzUg3WZipxAklF0eW6lzpufdgfcM9rgycBRvNu0krH0PGeTxnZPKgBzhTCZ+1Y8eO8VToVBxovArsAgyOXYtdgEHy37hF5ZNMDkze42eyfMbGoBksuYjYImHQfDRLVteMGzdu1axZs6a5uLg83lPKVqsRuGjRojnU2o3gQzpeER6cLnnfRibEaZDdRD5G5Yt7bg5OJsA5ng8y+BwgOjo6ec6cOVODgoKe3Dlx60F9Q58tW7bEUdANJ0BebG22PKdbXhkGyKsiX7wSHKh8hsxBSn6fT9llV1xc3MbIyMhf76S+rZGRkdFr586dw4lUb5K7arKqmqzrTvGhJPBaIneHVqeAXKiAdHz68OHDd7Gef9TnPjYCbQ2yuJJWhkLBoZxy+//3f6v8VuN/5YCWmuAs4iIAAAAASUVORK5CYII='
-Coffee_Time = b'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'
-Credit = b'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'
-Cycle = b'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'
-Date_and_time = b'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'
-Day = b'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'
-Delete_event = b'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'
-Disaster = b'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'
-Done_event = b'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'
-Earth = b'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'
-Emergency_off = b'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'
-Emergency_on = b'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'
-Enlarge_time = b'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'
-Event_info = b'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'
-Event_manager = b'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'
-Event_status = b'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'
-Event = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFVklEQVR42tWZf0xbVRTHz+t7/QErBbqxgBCGY0gQKAuUkYBKGJgQSabGzBDmtjgT2R/+4YI6E/Gv+cdMNuMfRlniZqIbLhozp1kUBtMSCVGK/BBhEQYECswwobaldO374bm3r6ULNdGEvva95HDee3257/u595xz77swsM1H2gsXiatHa0FrQDOiedB60DrRep2XX9q29zHbLJ4IvnG0vkhXW5IN6SkG+gIJbc3tA9v4InzWO+nHyyaE6EkoABR/ttGad/rFJx8FLavZ8rske14Q4ZObE/C9fe5dhHgzIQBQfMexhuLW43WFwLEMOJw+kCTpwYfka0n+c3N4Hj7t+f0CQpyMKwCKb2ms3HvlrcPlYOBYqnN82QWiKEV5WgoDEMCvfpqCLvvsEYTojAsAik9BN/ZxW2NecZaJ3nM4N+BP1/2t0iNGhJwSFAJ56sPeObxlQQh3PADOtR4qbyvIMcPuFD14/QKs3+ex1SjNSlI4DwhM0ABmlp1w4ZtfzyPAa4oCoHgW3fLrRx/PSDVogdEwcoNM9FalcACBJEr0nAA4vX54r7N/BW9nIYSgJECdKcN865UmC7Ah8djztPP/bQSkzVAS5WQgVemj78bBtbJ6EAF+UBLgTMaeh9qba/IhWccGxQcp6PlW/VI4jMi5KBIvwkZAgKv9M/DXwvI7CPC2kgCD+8oKrTX7dkJ2WhIw8giQQxMFQAyV0RAEEpBbJOn7/rgH8xPTdgSoVBLAUVRZkp1pMkBFbipo4L+HkEiACADG0ZDDBUsIMT08uYgAOUoCBCzV+zkOZ92STCPs3KGVwygEESl+s3RSgOAFrHj8MLroAgFhbg+O8wigVXQErLUV2SRcdFoWCnclg1HPyTkAD+RBqGSCLF7E2Pf4eLi94gU/5gBJ5N8GRhUfgcGahiorEcqyLJoGskw6SDOwUZM4CAIgoNhVLw/LLh8EeIH2PgG024YUz4EzB54ob99hTKbiNVhK6WjgciJFz0KSVgOcJliZSK8HBIlOdC6c6Py8SEGI8YIA3vUNGBkYU7wK1RWW5N/ak5+D84CGQpD5gGE2bbPnpbAJmLhUPPY8WUrwOAqOuSWYnpxVfB6gM3HTcwczODoCsqFwjWYrABFL458KF2nc8/Io9Hzbp/xMLEOcq2040LZrt5mOAieHUrichgE2IXi59wUhmLxupxtsPb8ovxaSAehqtPlYUx4Rz7IMHQVahSKaJtdJHAN6RqJ3SQ6seQPgxny4drV7DuK1GpUhWkrLCq5Yq4pp+NA8ACncsB6hTPpgaAlicCRo+GDs9w1MwODwVPy+ByIgOmoes7SWlObjjCyFAXQoPt3A0mdCd7EY0VAaHJ6G7h9H4v9FFgFxtrT44dM11fhNjKWUyDWjeC0bnJaJeLKE8PlF6LaNgX30TuJ8E0dA0F2JqooCXcHeTHgk1ww6DClSWpbuusA+sQA/D00l5q5EBARxdF8IE/oEiXlSlbB0XoJE3xeKAsNLWsyEQEBwXj7BxeIdMQMoe/WLkSU/ZLs966ZUk2ktkxPujr7//H5VAKx6fOlmo2Ht8LNPk0vbl9eu147O3rPkZqTMpxv1zoQHCB0IQCa6DxDgeKzeEWuAInRPIcB5tQI8g24DAbrUCtCO7nMEuKNWAFL3X0YAj+oAIitQrN4Ra4BkdJcQoFmtAGSH4SQCtKsVwIKuGgE61ApA/8GHAF+rFYDMAX8jwP/eaUgUgCPoZhBgQK0ApPosIEC/WgEOofMiwLZ8ecUDwIquDAEuqhUgC90pBHhDlQAyhA1dPULwagUgez4kkW+oFcCAriuWC7qYAihx/AO7uMpPbzCjJgAAAABJRU5ErkJggg=='
-Events = b'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'
-Execute = b'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'
-Fast = b'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'
-Filmclapper = b'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'
-Fire = b'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'
-Gauge = b'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'
-Global_time = b'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'
-Globe = b'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'
-Go = b'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'
-History = b'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'
-Holidays = b'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'
-Hourglass = b'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'
-Income = b'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'
-Medium_speed = b'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'
-Modify_time = b'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'
-Moon = b'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'
-Navigator = b'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'
-Network_time = b'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'
-New = b'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'
-Next_event = b'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'
-Period_end = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAKEUlEQVR42tVYB1BUWRa9DYiCOBJWaBExjDqOu6bZsdRBHV21LDPqYMKc15kVYzllHkXMAXXU0gFlzDmUoVxddWXNCRUTCgaMNEnoJjTQ7DsX3+c3tIAyKvOKX7//f+//d8579557Phr6kzdNQZ2RkZEDDxw4MMjX13e8m5vb9ZLWXyiBhg0bZl6/ft3az8/vQWBgYK2S1l8ggezsbKulS5dm7d69m76uU4eCg4I0Jak/HwE8IE4Oqj79tWvXsgICAqi8oyO/QIz5oqT0azSaJHHtoxDoGPi/bCsrK/UK0C9eZUi+IKb+EKN4yPY9+jNEfylVPyalAvoLe96s3xQTk3h4jreT8samAadS6v7Vw05eO9hak69rggLQ8YeppDdmUUnpj7p8N+GEfxdnhUDj+f9N+aqmu0KAMozkVzNNeUFp7ylkMJqopPQ/CrufEDqnUy6BbxeEpnxZXasQSLsbRtPaV6X58+fzC1Jaj6fsUsoOfvb+qLCI+MtzO7ooBL5ZdNbg6elqb8zKJhwOLx5S7yrJJJSARv7zJzpu35juJmSQKVvEn4j/mslP8/WHxxvJWsS5jZWGKic8ztf/JpPI1tqKxB+ZHkXk6zdqcnOwsP6Imw/jwv3b/0UhUCPgrMHR1dleXlcuq6HqGXH0pZMN3Uqxo1grO3oEBH9AP5LZQ8yUt9+QmUMeoKxMGfn6jaZcAnduPYx74N8ul8DXiy/qtVqXslQCGggKHjlENLnXOfdyIIfdfBgb7d+2gkKg/opr+iruJYNAUdqFG5G6mDn/cM1N4rXh+q88nP80BP59LUqnm9Esl0CjteGZtTycrT83sKK2k2GP0l9O8yqjELh9+3Z6nTp1bIvz0oKayWSirKycQoQzjszMTLNrjEHDfXlPfS3HY9zly5cNw4YNc/gkBP5o8LgWPunTEPgY4NGuXr1qGD58eMEEgn9bR0OGjTADdOrkfyg5KYm6eHdT7iW9eUMhG4NpwMDBXDVlS01JoYMH9lP3H3wUYGlpqfTrikDq1sOHtBUrKuBDQ0MpJiaG2rdvr5CLiIigffv2UadOnahatWoKeDwjvhMKJpAiJvf/ZSYFLFhkRiDm9Wv6feMGmjj5Z7NVDgkOojbt2lHlyp7KvS2bfiedAPXjGD9lJZ89i6aNQb9R3379qaJ7JQXs1KlTqUGDBtSlSxezndq6dSv5+PjwODhgSbhQAmi/rgykH//lZ0Zg+pSfyU2rpZ/GjFXuxcXF0ppVq6iDWKlv/v4tT4Jj+9bNFHrmDC1bsYrBAECsTieIhZBX8xb0t7r1FLDr1q2j1NRUGjVqlAIe4zdt2kR9+vQxA19kAh/SMBEAyAnVcS6vcZb9Ms7lc+rx6nfJ46MSKA549XVh4ItE4N69e3TkyBEaN26c2ZfU4cOH+dyxY0cF9PLly2nEiBG0cuVKDgF7e3tKT0/nsOjWrRudOHGCevTowQBxD79DQkKod+/e5CiSPjIykqKiouiNEIPy5ctT06ZNGfyWLVs4fPbv308dOnSgUqVKFZ3AoUOHaMOGDbRt2zaytc3dmLlz54pEfEZr1qzha4PBwCT79+8PbSbxDmrWrBm9ePGCAgMD+T6UZOzYsaTX62nWrFk0ffp02rFjBzVp0oSqV69OYWFhKEzUqlUrOnbsGA0YMIDJrF69mkkuXLiQFi1aRGXKlCk6gV27dtHp06dzvojEqsiGiV++fMmA5A6AlK+vL82cOZOmTJlCHh4evIJLliwhPz8/9vRjxozhscuWLaM2bdowiXnz5lGlSpVY8bBQ2Lm4uDgaPHgwjw0KCmKSwcHBvLM1atR4vxxALKo/9CVgGVIydmXMIkRkrKuTUsZw3hhXF67CYj5vE7tW/Er8saqsWi4tNSwqdmDo0KEfTuBzgre2tmYrMWTIEMsE0tLSOIG///57jnnEdenSpenJkyd4kFxcXOj58+dcIQEC6oO4RtXs2rUr1a5dm1UFSgZgCLmWLVsqcQ27gMTu27cvK8upU6dYtZCkEIxGjRoxpp07d7Io4F1IcOQiwOOAGxW5YpnA06dPae3atdS4cWO6ePEiKwdeLMawpCGJMUmvXr0oSfiiyZMns5RCIvv168erdOfOHZZPKA+ukcRQlgULFjCBgwcPUufOnalevXrsgfAvxLJlc76noFwge/PmTV40EIAyubm5MXgsCAgMGjTo3SEE9QHrPXv2sGKAPbYX96EWAAPg2IHFixezlEJaRVzy8xkZGSyDWFlMKC0CxsDvrF+/nsdiN2fPnk2enp5MFAvVs2dPfl6oDI0ePZpeC//VvHlzJoAxksDAgQMLzwGpOmq1sVRF1TGe1xLIs/Q374p5tcLJhmsZNhK8jY0NXbhwwSB2pWhJ/CktQmHg5fX58+cNItQsE0BpRwK1bduWE0wWLVRJnXCTWAEkNfpRiREWsAxXrlwhLy8vKleuHJ08eZLjH6CNRiNbAYzdvHkztW7dmoskfL6TkxOdEY4VYxITE/mM5E5OTubwhZCcPXuWcwA5InMAOyCKp2UCiO9Vwh5DZWBnJ02axAoB5UFciwLCioPEhAVGQoIUEtHf358qVKhAr1694mdB1NnZmby9vVnd4K8SEhI4rgHK1dWVkxiqhNy4f/8+KxZyAL4LoHGGncBYGUJiAfQiB8pZJHD8+HEu+VAL7AASDok7ceJEXt2qVavS48ePafz48Uxq5MiRrBxQHaweFArS6+7uzpOCDOxBdHQ0CwJ+Ywdg6iC5IF2lShWeAySwWFAf3MfO3rhxg+fAGMgudkHIe+KECROcLBLIaxHUSam2AHJsQRZB/R51zFtKWDQZ4zjU1xgrwWMhxI7Fil2pYJHA+1RZsVRkJQqW4bvvKFu83EY40nTxxZb21gC+T5W1BB7hggbw8fHxnFfnzp1D2OmEWXTNRwCTIA737t3LCSQ8B8cq2tGjRznmEZcYB212nDCBshwcKFO4ylThFrUi4Z+KomZo2PCDLIJcbVwDPOZXN7wPYS1COT8BEY+2GIAkhj0Aa1RUeHE7OzuKjY3laisJoNBgvHv37hQrCplRJOsX27dTkvi4T65fv9jg8RvfGOpxUCSombDsuhkzZuQSCA8Pz65Vq5ay0rASSDbIIZIJIKAUIITqCZVAv+2DB2QS0ldeJHq0qNJaYRUShS9Kqlu32ODfeh5lLH7DuuArTiyiZQJy22XVVFdTNOn5ZU64TJtGNiIP4oVaJIqVB4EEofN6sQOFgX9XlZWkJGg0hBJywPHt/53Eh5BOyLg5AXzxqMEXZBHM1En4HZOYNK/d+FDwchfwbhCADMNIAjzG4SwkWidy05yA/O/X57AIlsDDEcAZX7p0ic0kxqFyg4BWq9UJ625OAI7wc/obCR6/Af7WrVt8qMFLAsKZ6oRKmhHIpBLShN/SCLGwkuDRYEdUq6/HvRYtWpTTFGumEtD+D2wpKxmKxCM6AAAAAElFTkSuQmCC'
-Play = b'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'
-Previous_event = b'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'
-Reduce_time = b'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'
-Remove_event = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFi0lEQVR42tWZbUxbVRiA39vbL6AU6MYCQtgcQ4JAWaCMBFTkYwlKMjVmhjC3xZnIfvjDBXUm4q/5Yyab8YdRlriZ6IbLjG5qFgcrmyUSoi3yIcIiCITPGSbUFgpr74fvOb0tXegSdfS29yQv772Xm3Pe55z349xTBja5Jb94lqgalEaUWhQDyjKKFaUNpdN5/uVNG4/ZZOOJwVcP1uRpKwsyICVRTwcQUZbca2AbmoXPO0e8eFuPENaYAkDjT9ZZdhx/ae+joGFVG/4vSprjBfj0+jBcc0y+hxBvxQQAGt96qDa/6XBVLqhZBmacayCK4r0vSfei9Od63xR8Zv3tDEIcjSoAGt9YV7rzwtv7i0GvZqmdQ/MuEAQxzNtiEIAAfvXjKLQ7Jg4gRFtUAND4RFSDnzTX7chPN9JnM85V+NN1d6PpIStCLgkKgTz2UeckPjIjhDsaAKea9hU352SaYFuiDjxeHlbucthrmG5FMRgHBMYvAOPzTjjz7S+nEeB1WQHQeBbV/BsHH09N0muAUTFSh0z4XsWgA4EoiPSaADg9Xni/rXsBH6cjBC8nQJUx1XTj1XozsAHjcebp5N9vBcR1VxKkYCBZ6ePvh8C1sFiNADflBDiRuv2hloaKbIjXsn7j/RT0eqP9YtCNyLUgEC3Aqo+Hi93j8Nf0/LsI8I6cAPZdRbmWil1bICM5DhhpBUhThQEQAmk0AIEE5BEJ+q7f78DU8JgDAUrlBJjJKy3ISDPqoSQrCVTw711IIEAEAP2od8YFcwgx1jcyiwCZcgL4zOW71WqsugVpBtiSoJHcKAARavx66qQA/htYWPbCwKwLeIS5ZR/iEEAj6wpYKksyiLtoNSzkbo0Hg04txQDcEweBlAmS8QL6/vIaB7cWPODFGCCB/GvPgOwrYK+oLbMQQ1mWRVFBulELyXo2bBD7QQB4NHbRw8G8aw18HE9nnwA6bL2yx8CJPU8UtyQY4qnxKkyldDVwO5GoYyFOowK1yp+ZyKz7eJEWOhcWOi8nUBAiHM+DZ2UV+nsGZc9CVbkF2Te2Z2diHVBRCFIPGGZd1mdeDAqPgUuNx5knWwkOV2Fmcg7GRiZkrwO0Etc/X52qpisgCRquUm0EIMZS/6eGC9TvOWkVrN91yV+JJYhTlbV7mrduM9FVUEuuFEynQYB1CE6afZ73B6/b6Qab9Wf590ISAN2NNhyq30GMZ1mGrgLNQiFdk/s4NQM6RqRPSQwseXzgxni4fLFjEqK1G5UgGguLci5YyvKp+9A4ADHYsQ6hjDq/a/GCfyWo+6Dvd/UMg71vNHrfAyEQrRWPmZsKCrOxIotBAC0an6Jn6TuBp5iMqCvZ+8ag44f+6H+RhUCcLMx/+HhFOX4TYyol5prQeA3rL8vEeLKFWPMK0GEbBMfAH7HzTRwCQU8lykpytDk70+CRLBNo0aVIapm77QLH8DT81Dsam6cSIRBE0XMhDOgjxOdJVsLUeQ5i/VwoDAwnajASfD7eef6IOhJjRAyg6LVL/XNeyHAvrxiTjMalNDV/e+CDF3YrAmBxeS3FZNAv7X/uGXJr+/LyN5UDE3fMWamJUykGnTPmAQINAUih+xABDkdqjEgD5KF6GgFOKxXgWVSrCNCuVIAWVF9c+vrKGHg8APHxD9TfU3urE65Zb3rkBCB5/xUEcAPzgENhPUGAJ/HKHgoRMYDQDCT6q5niAIi/nEOABqUCkBOGowjQolQAM6pyBGgVN/za8f+a3AD0Bz4EuFJXW0Xc6T8fmdynyQZAasDfCEBPGiSITWlyARxANY4APZEaI9IADaimEaBbqQD7UHkQYFO+vKIBYEFVhABnlQqQjuoYArypSAAJwoaqBiE4pQKQMx8SyFeVCqBH1U42dIoEkKP9A7w8Cl4mHEaMAAAAAElFTkSuQmCC'
-Rocket = b'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'
-Run_application = b'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'
-Run = b'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'
-Schedule = b'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'
-Scheduled = b'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'
-Search_event = b'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'
-Select_date = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAACyUlEQVR42u2YX0hTURzHvzPxYRKL/TEo/6CtnsrKh/ShCBGWJOageogeqpeKCIoeil56KgiLLLGogW5modOKBRHlS8H+4PoDWiCLGbTKGlK5gm1mc+ueI6tc27r7c3Y2ut+n+zvnt3u+n/vdvedyZShwyXgbkAB4G5AAeBuQAHgbkAB4G8gYwO+PRHibSEcRwbZ58PY8wOTHD3QwGAyK+nFYJHORjF3AxMOdobu/AYinQDBAJ58/dcDrnURL604mdbYUAxARAOYTMHV3wWq1ottkZlIzA9hmeUMnmt8P0QX9uzqZ1ANblrIDKFMpUTd2jS5YevgGbUyl/vojgsZxA61DB/ro/J/192/T+QsQzzAXAPXkCFRBL15p9bQxUf2sWo9wOIIVU05aP6lqo/PJ6pwAsNTU5y/sAOz2x9i3ZzdTAGPvTayvq2cLYLh6hYn5/QcP5Q6ALEaU7eNYgNfucezY3vZPs+c7LqOpSZcYgGzNDk4JPHxwDydPHKMXMZHsI6OQy0vFA4i9ogHnMF6ePQLV9DvhBWUOn9TVqD1+AfKGZlEJRHVrsB9nTp/6a7ymRoue3n4oFEuS/4XSSaBq9D4WhWbxtlaHUImcjhXPBlD5YhhzxSXwrNsqKoGojD0GdF4896tetrwcputmaDRlcfszTqCx7yhW2mfj9rgbivBob5foBKK6JACYBBC1WiP0DqC8ojJhb94lQETuA5JCS6seWu2qpOvn1T2QjhYCCK8EDkcB7wOxAKk841NRXiWQCoDNZoPT6cRihQob6jeyBci2LBYL3G43JiYmsHrNWmzarMv8pLkC8Pl8MBqNcLlcwnO9Akqlki1AtiVDGB6Phx4T80SMAMIIzsxkHYClFgCEQqG4ADKR33bE9jEBaG/voAMkhVwpFWDSG9tPdmzit/C/jfI2IAHwNiAB8DYgAfA2IAHwNvDfA/wEhbFoxUS/KkIAAAAASUVORK5CYII='
-Simple_clock = b'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'
-Slow = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAJZElEQVR42u2YCYzU9RXHv/9jZv5zX7sze7CwwLIcu7gU5fCCSMGW4lGvQkrSeDTaxFrTgjVpa03TtKmtWg9sUpu0NJVWQ1qrhSpgVVC0oCys4u7KMrvsNcvu3PfM/+z7/1eGrrBc0mxN9pf8MzO//+94n/fe7733Gwaf88ZMtACTABMtwCTARAswCTDRAkwCTLQAkwBnG6DmO2drqTeu0Qofz9akuA+sWWRMlRHGsbCVdV39FmOuGr5YwmiaxlDTLgqAEt+2Rh18/Eeakl7KCA0A7wFDD8BCkyJEVgTEQYUR6newgdt/wbqXvfVZhT/w9MZ/Lrz3kRtYjpcuGEBTcjbl6F1/UAvdX2M9K40hpH16OukJQVMLoxMZFuDcBOYFI4+A8d+6mZ/x5P0M705fKET7879+qmbJtVs805v2XRCAJqed0uFrd8LkXco6l0DLd0JNvEr9Scgyh0LRTAAMzGYZJpMMjlPHLMY6Fhwyzdu+hrHUhi8EILR98084izVVv3Lt4+cyvpSOB8sAGkkmd659QRMHb2NdV0GJvUj+34VUyoFYwglJMo2ZbLMXIVhEeFw5AjppcUaY1mtqemU1a5vXcb4A/Xteuid5tO2G+Xf+eM3p3itiyRo/cnB5rOO9VZnB7vn26mkdZQAluvVWuft7Wzn/TVAiW5DPZBAeqiDBeaTStlENs6phAe0Tw7ldedhsRfrMGU8ZwuSLm5p2fIl1Lnr/fACGD+35au+O5zYtfvDZKSeFLtr0/vC+XevzkcGZlc1LXwkuWPait2H+XoblFGZU+worHZjXDusMijh7kM/KGAhXIE6a5/gi8nKWtFwit1GRIA+3W8zI5wV4bDZyLZMBUlmRhN+XHgvRvGsV67i09VwBIh+++5Vj//jd9pb7HgvoGg7v37l+uHX3zd6GS96etuLWp/1zF+36dJQyANTU7mVS+/W7aVeoYgzdx6oRjbkgM2nU1BYwc+5SMOZqQI5RBIqSWjIQS0ns2pOAjfNA4BxngHhtJetYePBMgmuqyg4f3H1z7yt/3OzwBe39H7yjRyXULbvxt9PpPNiDU4+MN9cAkEP3PyGHn7xf/x6PO9HVXQuzkEZzixVCcDW05Gt6Pji93w7Z0D/oBwf76SF4d8o0+/l1rG/1q5+eq8qSeeCd7Xf07PzLRlZVGgIzmvTwhnh/F3LpRHzFr16uOltINQDEw6t2qoldq/TvvX0BRAmiviGHQP0VUOPbkEiYcHzYh2LJBAtFoOqqODzubHmRj45Uoph3wm6Tjd+nQDCsSrliM1//8x/oiU+RSsLA3u139uzY8qBSyE711EyH3VuJxGA3OJMZrkAdwh3vYc66766vWXztn88KUHp/5lGK8TP170dDNUjmVCxe4oJW7EI6LeBIdwAli4CKCoFyQS/yKTum16XKECUCaz1cBVYbtcIJCJ83g/92WdZ3y9/Cw+t2k+DfhyLX+mpnQnB5kU9GET3WCVkswmx1oKqxBblkBJKG1it/+PtLzwigaRIv7rUWNE3m9Y6e3iDC8QKuWpjVQytZJIhEgcGcOQ7aKASfW0M6x6O7pxoLmvvLCx04HKTz4YTDLhq/9ehk5mU4nBSprCXEonMGDr1e6eZl1ekO1sE/bbbuQoj1HUEmOmTMSaZkUgpfXlPwVAwu/9nWGSxvEscHkOLe0r998RMd3f0eNVeQ2PmNo2Gxrz+ASFpCXU0KQyM2zJ0pkmAi2tprMLchUs4BR3sqEE3YwajWshU+gdBa3wygGHUzXs9oLvHVNUDMZ5FLjOgH2OjLZGT0h0uor7Nq1XPnHfDNatkzbcVtT1n9Vb1nsYDCinvNIn1yekc6I2B/O4eVS0YB9ATW3uWDpMiQVAlXLPGTa/Xg3dZqXLagCBObMMYNDvkQ6rfBwo5GJI5TcDxk1T54y8nU1trgdoxfN1JeRyiUoVOtYvWGDQ/MXrP+UZxjGz3EB5oOq/mPmk50/us9K7646JOah7WAsTaSAwsUFgNQM/uQjuew/7ATK6+xEsyogjq7AkhlrCSEFX5vGn0fmtB5MIDa6UG4+OS4AqisFX0DJSNxLr5uxbarNz52/bkKXwaQQvduUsLP3HuiMzTAIZvn0dJYOjmQcgSdFySSDnT3+sE70/hCcxWFV6oY6Jy+01oLCyeAo0Pb9poVmYQZwanV8LpZcNLpASSTDyMjRSSHI6iptso3/ebFGVZfsP9sQp8CoGbev1Q8dFk57TOk7Y5jDGVjG6ZUsHDadT/VkEiZcTyhwufPYNHSa6jQ20lQshFiewYcBMDi4KtOFLI83MEgLEocVk8FrDZOP2y0AiVKyhiKoqGYy1MwIN+PRsnleKz8zoYN01etO6ci7hQAQxvtN/5dib10Y/mFOUhJyI+Oj/sQHpZRpDhQG1TQ0jyDqs6FlL3fgCYeRy4nkPtMQTpbRNebPohFDrzFQm5EFpNLp9/U4qCzpqCQTlO+MOHK2+/+6awb7nr4fC8zYwC0Uv8U8dDi/Zo4VH3SEmYwzsvJ9yuNCw0RGQdY04VXRaNWClE4zRXy6Njlp9DOGvMqp9aCyY+cZje6DFkrEBs8ThurmDW/vueK+x7+hq+h5e3zFfwUAMOVcm2X5A+u2cFrA1VnmqTfC/oHKHMmneDpgvPuy97yUgzLIhCgwy2PDd2MxUlWIq2nUrDbTcqKb337ocbr1v9SrygvVPhTAPQmZ0MNA3vu3qpkPlggCCUIgkjlg0R+yyJfsFCt5DLuB3ppXYjJaHvTPWYZu9cLO5cdu6itErHwCFlIhtttkdc+86fLXHWz2j6L4OMCnGiRthe+efT1hzYxvGjRTa9qLFhGgSqpVEqw+Hi/A4Ucf8o8u9cHO5813IWxuMhalLkjEeMdzzFYdc8djzatve+BiyH8uAAd27ZsfOOZJx4pFmVWHXtrBM8zZBG6VppYKKoGUdQflQBPjuF43iiHCZssRValqKOH2im1Fqx5fGujPVjX9T8DEFOxKUf+uunZbLjnErmYs5eyOWexUKIi0SzZfb6I4K0cpBolzPJmUcol/fnIUEMpFa3LZ7JMLlciGIUuPixdN1kD9sQmJrOA6su//Oy8r2+852IJP64FPt1UWbSQwKXx3sv5rDfWvu+WwnBfs1TIuaV8xisXMh4yC8/bHTHBE+irWLD8OdfUxnP+t+GiAvw/t0mAiW6TABPdJgEmuk0CTHSbBJjo9rkH+A9nCyz9QWC14wAAAABJRU5ErkJggg=='
-Speed = b'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'
-Start = b'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'
-Stop = b'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'
-Sun = b'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'
-Task_list = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAEh0lEQVR42tXZW2wUVRgA4H8v3W5bqH1ugvFFg22khS1dUDHbG/RCoaUtpRYvC8WQFrwkPmmigFFffBFRsY0B1FouLbSUIkJLS5FELkXxRaM+aWLiW+lDd3du6/kHO5e9THd+9tDyJ83M7p7M/N/MOec/M3XAQx6OZD90fzwWfRAJhMNidEXxsvcCGwrfTTugLfg0LFnq5ZW4uj12+Iq6XV6Qf4CCsARse3ktN0AkImmAJ5Y/Cr//9hcJYQ14aS3kcAIIgg4oeOoxkESFhLAEtCJgSSYXgCjKGsDnfxxCsyJDyAzxty2EJWDri/wAkmQGYMQg9jPEvvsErIGcHE4AWdEAzwQKIBwSSQhrwAtrIJsTAENWFBVQWVukJm5EYBf7IwWEJaBlOwI83ABKNKoC6ptKIMSST4oozN8XWF+4nwTI4giI/g9IJXa/UZUwV0tA83Y/ZGXzA8zVgn//mbZux4rej1f/hFdeq4jL1xrQbgYoyvyrC6fTMW8buxGaFaC/97p9QFN7KWRl6QBRkOHo4YmE7RHXsbccXC5n+gEhAQZ6bxAAz5eC1whgg+oYA3TsrUjQfhR27kkdgP0/UTgc8SmFEfAtAbClDQEZJsBXX1xRE71fgJ3Amel0HxGQ6U0N0HNwFHZ06YCjn0+QEw52BsB4g3AQ0wDbVscDuidhZ1dZPOCTMdjRWcblDqiA4zftAxpjAWwQf92THBDkCDhDATQgINNtOlDfkWtJT9TesQ4yMlzpB7B6MUgCtK4GjwGwUCEg4AQBsHnr4gEMnSQBSsDj0QHqxBCJJJ/DvV5Ifx2+9/Q2dPIWAdBSAhlGQCSsbqWez8C9qxPXDViCQfjoffC8+TawAcMOmH6CiIBTBMCmFh8blIYuxK688KH+pOd56wAIH7xj+swjRFGCs6emCIBmH7iNAOxE7IrPvr4LnKy7RCVJ/cPIPvjlfIckh4SAfgKgXgUYpkXs+oKg7s6+GmTJi/hwCzndx9nl92hHxG7Ud+QHcsJtwWfZqfRxho+Yw2SAWwdE2QDGmGmuimuf23+JIdgY4DCK8QUACbCxaZUJAOEwTFf7wZmbB8rMNOSNTsF0pU/7OW/8Do8epALODdwmALasApc7prIyxN0aPzyCyWLIEtxlCO0zh5ARcJoAqEMAh7WNbYCswAgJ0LiIAGdIgJWsVqUG6LpVBp+WjHMBKAoCfrIPqG1IDbBnSl9eH/KlH4GA84MEQE1DsQmA8/tzo9UwWXlB+273zUaIyDOQ6cqFQysH2KBP/zSEgO8GfyYANheDwwAIjNVo+4hovVYHbvazpAD0+ofVGuDg8FolioAhKsBQmXARWjZeq+7nZy/Vvv+m9IRWwOa2WHiogQXUBGAnJgGqNxUnfM0xh5AUB0yWj3CpvrGAC2eJgGRNyidq4XLgPN/MdQINsKG+yNQk2YOM6YBcbkcUvh++Yx+wfmMRcFncEAAXz1EBD+S/xfMEy5IMSKHX8M+fCqiqW7FoAJdGfqEBFGWh07/37oAEWFfx5ELnrsXVsV/tAxY66diwBXhY4j/wQM5Pf2bZNgAAAABJRU5ErkJggg=='
-Temporary_tooth = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAQtElEQVR42s1aB3RU55W+04tGvSHUMRJNNkWAFyJcWNbxyo4LRWDCEhvv2iE2DmA7xPGCsSAhJ+dgUeJCW6xwYA1LJEoERoAECIEKAoR616gXRnV63Xv/mTeaUcE+wCb7znl672nevPd99363/RIPHmEbNJgjyrvV75itNs8AuSh/UoDi2KM872E23sN8SW00h16o7f5eLhKMD5CJfLVGM88GoNdZoSbUU/L1U8FeX/+/JVCj0qypVmk+T4jwDbvR2A0qjcH5mUIiggh/RXOX2pj2YkzQ+n8oAb3Z4qc2WkI1Rst4Hg/MeJxY16t9K0QhiZvgI/PIrusEtDy7VyTggxh3D7EQgj2lIBYJB5r6dBd/GhO09O9OQGM0h5woa99ns8F0iYAnFfJ5Uj6fLwz1ksgn+StAh6Dzmu6D3mRhgEUO4ERAIbFfB8gl0GcwW5HwVSHPduBfJgb/99+FQHpFh0ePzlSvEECQyWwecTMfXSHg85yAnUeJg4CDEB3pybU9Gmgd0Pe2DRrUXhJhWmJsULJUKOj5PyFwrKRtMcomRQrWCKvV6naTq5U5gGIhfwQR8oDBYsUgt4LRaoNBowVMeG21WKBHZzA1Dxg6fCSC3z8TFZDpLRU1PDYCWpMlKPVuS5avRDDNbDI5QXPgXEE7z12A2/ApRosN1CYrI0DA6ZqOBjyakMxEBY/eA3e7NLoYH0noMxOCex8bgQNFTRtFfN5WCR88pXwYVdeKUTzgBGpyBUwErOy6ddDISClEAM+GyADrBejMFqhQaauT4kIXYBrueiwEvi5UZijEgkQfsQD8pGPrmkAPl4irxT3xHk8x3/5gLAwyIQ+sVrwHQdswK6BEGYmqHl33s1EBS0K9pDmPhcCfCxqV+PIILEowyV/+QF27AibrWhBYh9qMn1vghSgviPQSAw+D3WgmL9C9JhjUm8EGdgKYnKBdbTThZ79OejLskQsez2y1yr651VTtJRaGSRDwzBAE4S0boWstHjEBsSwkRoDoMZAK7FmJ7NA0aICbbWp4PtwLIpAEWZ0IEBGV1ghWGz4DSWpQbj1ICNPwphXTw//0yAQogP/rdnMRprkwEYETCmA8FiOJSMBACgksnqN6mLvIuoSZUipd8/GC57hGB8GFhj546QlfMGPmoaDV4a42mMCCH1Lh0+gN0KvWgUGv/S4h0v+oVCptk8lktHfhs60PReAQEkCwYTIhAeWh5nkQ5CFhmvbBmJAhAR5wBBzgicgwAnTs1JhQLAB+GAtEQIuAe3pU0NfVCarONjAZjSweaDdjrbEgUY1GQ9eaqKioszExMekTJkz4XiKRDPwoAqhJr31FylKUULgEzUwkPNDyHggaiw5EeEsZWBhOwOENIuz8veO8VW0CP8w8zc3NUF9TBRYEihZm++DgIGi1WjAiEdqxyoNAIGDnarUa9Ho96HQ6TUJCwvYFCxbsFolEugcSQOa8PfmNTd4oISJAoH2lIiA5BXqIwQ8D+0EEuLhgcnJ4oef+fbh37x4YDAbw8/OD3t5euI+/a2xsZKTI4gSUgBMphULB7hMKMXGIxYzUwMAAHbuXLFny7syZM9PHJEA/duc1lKNMppDWKfNgPCARPpORv1zEgDm/4CDAB0469odwJJqUjVBZUcEAEdDa2lrIysoCpVIJ44KD4cmnfwJ+48JA4RvADKAb7AVND5KrKEHPaBgZX19foG6A5EXeWrRo0dbXX389Ge+3jUXgOBJIsgcrj+X9QLkYmzIxI8BzgAXgAA/JhnYB/rBhlqmtrISWlmYICAiAhoYGOHPmDFRXV8NLS5ZD9D8tAnlwBHh5yAGbRLDp0QuaAfAOCsFshRmP4qWrGVrLb0FJXg5gDADKh8UKGQJj4+SGDRtWoNcsoxH4DDFsRssLPERCJh8Cj5USwrykdg84LM1Jh8eRcXiksbYara8EHx8fKC0thYMHD8Kc+QkQ/8pq8I+MgWA5xRXP7j2SWXsL7s0QGz/P/nwqdJi2+424d3dAxbVzoKyuYO/iAn3u3Lkpa9eu3TiCQMuA7rm0io4TqP1A8gAFst36uDtjwOamfbIMyYas393RBqX3iiEwMBBu3boFB/bvh6S33oEJi1aAv8AA1r4OCJ/8FMtaiBG0WBvqa6qhsaoM5rzwGj4DULo8tve3NsBArwrGTZ4JdQVZUIre6O/vZyT6+vrgTdwSExNT3QhQMfuqUFmFmSecrM4R8MFgpkB2yoULAgRPVIiAUa+FgtwcJhuSy65du2Dlux9A9PNLIdpXzORSX1wAYk8fEAU/ARozfdcu5Yy9W2Hx+s+ZbGkzqAfhy0/fgy1fHWExaMB7m+7lQcHlc5iKexiJtrY2Y2pq6oSgoKBWJwHa9uQ3XMMstICqsQ+OhhTIlE6jfOROd/Fdpge7FHhQVXIXBvp6WVbZs2cPzF3wPMxY9h7EBsmZFImsSm+Bjl4NyORyZ+DTdnbPVkjamMzOyQtWkxGPNhBLpPbEwDIcQMX1TLhzMwe6urpYZsN4OJycnLzGjcDe/Ia1KI1dWLzEVLzI+lSJw7xk7npziQPtQC8U3rgOISEhcOHCBcgvyIdV2w/A5PBg1siRzDq19u5U4IwXe9DTdmr3Z4wAA+rYufgi4HQtZB43Q37GSbh+NZsVP8xoNoyxuNjY2HIngU61IR5HyVNo9TAqYkEoHZISecJX5shE6HquJpD1q9H6/ahXKk47d+6E1et/B+Fxc0Cq6YKw2GkI3gIDCJ4PXLayf09ob1jhZMpn8MaHdgKcjOzVnYDbiZbfLQAN1oToqEjIyUiDSsx05O0ZM2Z8sXnz5g/dRkosaM2eSMCEkRbpI3NUYz5rJai4cTmfWQnz9NXMDAjG3H7lyhUoLCiAn//hIEwJ8YXO2nJoaGqB4NkLGThOIgI2kg4VwuNfbIFVHyW7gecsT/FVnH8d7ty4BmvWb8JYEsCdK+cg7X9OMC+0t7e35OTkhLsR2JvfeAM9MI8IkHyoK3UlMJQ6edCn6oI7eTfA29sbvv32W4ibMx/mLvsPCFMISfZQ2dkHEpmHG3jWEHISwR/Hdm6BN3+zzXkPn2e3PLUkdG42GkCK9YAj3lheDGnH/gLd3d3ME0ePHo1zI4BzwREsBatIu/QgqsTjFPamjgi5dqLN9ZgGMRWSOw8dOgSrN22HKdPjwRvHOpXOCr0Ge70h6/LZ0R08pcxv/7SZEeCCVcBVdK66O2KA75CcWtUNmenfQVlZGdTU1MDbb7+9xo3AlwWNO5DAb9kvkQRlIT+ZGEKwvfbFwOZ6HXpe5b3b0IMdZkdHB5w5fRr+betueDJmAtBA1jhgZpOXvU4MBSff4UGhQ0ZE4O1N2xh4ocM4HHguBjjw9DnPZoFLSODmzZuMwMKFCz91I4C1YB32QnvoZqwNzq6UAjlIIcWjgFmJwBRcuYQkrexB2dlZ8Obv90NcRBCQ/JoGzU7wbvp2WJrrrYjAO59sY+AEDqBD9/GG+izH5/T7G5l/g4sXL7Iea+LEiV+6EahWaZZfbVQdRS8I9Cazk4D9KGTjJQY5y07ZGadBgX3N3bt3oaTkHqxK/gasjXeg8GYuBE1PgGmz5zumtSFQrjIqunYRph7bB+OEImd+5loVrm2hTXTwOHywagk7P/BdGhRkfQ9Xr15l3S4Wz6NuBGpUmqWX6u8fxmqssK+8uRNwvc7PvsiCrAI7zzLsfVb8ZwpMDQ+EPixagyZwghc4JOcKXllVClmnj8OvNn3utDyzuksM8DnL4/tsVns8SbDdzr10Dq5duwYFmPVmzZqV4kaAeqJzNd1/RQJ+gzgGDoEXsCHf9bqkIBdjoIt1nWVlpbB04zaY9kQUgrfiHG1zyT7uMdCI4LMJ/O+2O/XtDFau2DmIcJmJiwE+TpxZ584y8JS6Fy9e/Bs3AlTMTlV1ZuBwE9yDg/iDPFBaVIhgylmDRVnhZ2s+gClPzWDNWr/BsQAwLAaclv90uxMYB97pCbCnUQ68awyo+3vh3Ol0aG1thbS0NNi0adPP3Qj06kwxWI2vYCsx/r5mOAF3L9yprOsvyzrr7enpyfQ4bfY8mP/aKpBj+uhFGXGBOBZ4Z68zDDwXvHxnNrJnIrq3tUkJx46k4szRwlqXvLy8MDcCNOAfvtNyO9BDFIreGBM8LXJdV/ZU1585HIr9v0d9fT2LvJfXbYHxPh6Qk3MNqu4UQNIvN7IXN1bawb+H4HljgOckJHCRUW72Zehsb4WVq3/B7mnA+YBSNk14OHKWFBYWPuVGAHO3ZN8tZV2wQhLaNqAfRmBIRiarzaw1WX+pvH7+n5uamt5QqVRsIE9IXAxhMVPgQtp38OqadQyMuk8FJ/btcgM/Wo5n6RVGxkDGqb+CVCqF+Nmz4cK5DGb9U6dOQVJS0qe4/WHE3wewmDUEeEiiOgZHJ0CptL5Xq3w20u/5ge4Ov5SUlFs0hVGr6+3jDT99az14enqzFTsCtX/HZnjfAf6HcvxYMUBHZX0t/O3sWbh8+TJJVn/79u1I7MO6RhDAYlYY4CGe3Y4ekLEldHcCXtgTVXSrc5dNC0lgufnAgRM4yCyj4ZsyTdys2RD/YhLOswI3ifDBvc8ZC/yIGMCTjtYWnK9Ps4WB8+fPw/Llyz/bsmVLMlc73DaU0DEfmfgN8oBUMJKAwWrTYG+0bE6o93m6Hxur6E8++aRKLBaLqEuk5m7WT56FuIQXnODblQ2QlrofPvr8j245nu8CnmT0/dl0nPB0sHTFSufc0IXj6uVLl5iH09PTqQvtxpk7WqFQaEYlcKyk9X2Mhb19ehObqFxl5C+XQE2PtnHlk+OjXb+Tm5u7ct++fUdpFYGWQ8LCwiAufi5Mnb8Q2pT1cPPSBfjFr37tpu+muhpoqK2CRf/6slsM5N3IYRZPQhKdbS2AgcrWks6ifDBdmzF9PjN//vyb3LtHEOhQG57OqO7K1JutXjTAcOBJ+wFyqbFDrT/ycmzQvw//3uHDh/+IqW0TLUxRN0skpmFdmBw/D/yDQ+wDjYu+b+ffgEKcpdd99Ft3GeFRp9HAIOZ8SpU0LGVmZrJas337dprpU13fO4KAzmTxP3KvtRitFKo3DrUT0X5yKO9Wt6yeHhYOo2xoef7evXu/ys7OfpcWp2gApxoxffp0iI6dDOMjJ0Igjp4C1A3Jo7ujHbra22AWZhcO/CDN1ho11NfXsdpCmY1IYJq2ffzxxx9u2LAhZfh7R/0z6ze3lGX+cvFULhNF4HSmNlhUeHxpVoh3PjxgO3ny5FoM7D97eXnxudU1mtomTZrEdp+AQBCLJCBCTwkxpmiyI6+oBwegCocUas8pGRQVFbGhBa+1OP8uTUxMPD/a+0YlcOh28wE/uehFbHvDqPts7tdbpgYqls4J9TkFP2IrLi6etzV5W6qquyuGlgkpNmin1TaSGJ3T0iOd06IuASZv0RoqrZ/W1dWxdiEuLu7i7t2730fi1WO9a8w/dP+luOU4ts1Pm1AaEd6yddMCPStxuK/6MQRoo0Xj42mnl+/84osjRnW/kLKTh4cHW8ylIxUnihWSCe1UDGlBl9Z/oqKiinbs2PHhc889d/WH3vPAfzXAgvUznIWrEHj1Dz1orO2+1hhXX1UZmp15Ph5z+GttbW3RGo3Gj48bSQx3M1pfFRERUfnqq6+efOWVV85ERkY2/djnP9Q/ezzqhvVCgHk9CKVk8vf3VyEX28M+6x9C4HFu/wsVuKciaCa0qwAAAABJRU5ErkJggg=='
-Terminate = b'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'
-Time_machine = b'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'
-Time_management = b'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'
-Time_report = b'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'
-Time_settings = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAPNElEQVR42tVYCVSTZ7p+EkISAglh33cQKy5jtdbqKNpRsepY5457q/bWOlbb2/HWOqd16mnnTscFdzvXZUYdz1wVlzoic61LUQFRERSQsogg+xogCQESQrZ5v58kBKtVWzud+c75Sfi3PM/7Pu/28fBvvng/NoAflUB3d3e4QqGYqVar43Q6XWBXV1egRqPxd3JyUovF4gahUNggkUgqQkJCzvn5+eXweDzLj07AYDB4NzU1rayvr59LR5zJZAIBBp/Ph7OzM/ed7oFer4dWq0VnZyeIHLvWEh0dfWrEiBF7/P39C/7pBAiopLGxcVVZWdna9vZ2V7IwZDIZ8wJUKhU6Ojq47+xg4Bkh8gBEIhHI8ux5kIdAz1oGDx58eMqUKR97enrW/FMIkCwmFRQUHFUqlT7u7u4cMLI+WlpaQKRApOyWZkDZdTc3N7i6usLb2xtSqRQWi4XzECPDiNC9hoSEhE+mTp268ftI67EEmpub38vPz99B0uAxIPQ/7t+/jytXrnCfgYGB+MnIUfCPGACphzfEMneYSUK6DjW06jZU3f0ajUTWxcUFFAccCbPZzB2M8MCBA08uW7bsDfKU9pkSIIvxq6ur9xYWFi5jUmGSKC4uxoULF3D37l0kzPg5BsdPg9A3DG4ePpAIeBA58dDT1Q4noRgCoQhGM+gwQ9taD1VVKfIyvoKWrM+8yDzCFpMbeerO2rVrp8jlcsUzI1BXV/c/ubm563x9fTmX3759G4cOHcJPx43Hi6++BmnUUHhJRPAQ8eFC4EkZ3MvK8rLg6RcI36Aw7pyRgHYbLegyWMgrGtTcuY78zMuclNhinmBxQySyEhMT48lDPd+bQFtb29zs7OzjTDLMzampqUhOTsbiX61A+M/mQ+oMyPkGePv5cy+wge8xWXD9Ygq8gyMRHBvHnXPm93pGTMfdoq8hD4tFh6IeN1KSoFK2wWg0cnHDYmjYsGEH16xZs9SGo6y0YUxVZfPzpXfrx6lVXQFOAkHPshWT3/T2ltU8kgABjr1x40YBWUjIZJOeno5jx45hxW/WwffFVxDu4QI3Zz7yL6VgyLgpnFxUejNZ2AyTmSzdroSLRAKR2AWEHU7EjrCjICsDbTXlmL34LehNQJdGhVtffoHqynLOw2yxpLBkyZJls2bN2n/4UNr+FkXHRHo6XCQS8mVurnAS8Dp7jLqkxUsn/uqRBEpKSs6Ul5fP9PLywq1bt7Bn924sfe8DhE2ahygPEUT8XrkYenqQfvFLRIybwQKGA+lE19JO/RWT5yzm3sW3gmcySd6/A/Pefp8jJKD7WAT0dLbjxt+TcL/sHicj5omGhgbl/NlrUnlm4S969AZnC0GUSSVQqTW6sRNi5g8bHpHySAlRuhyblpaWyVJfTU0Ndu3ahQmTEzBk9juI8ZPBxakXvImCs0Fr5LTNAPLRC55dS/nzdswnoKQmzgPgrvV6gu8gN9u5dpJT9oVkFBUWcgWwu0uGcWNe6RIJJa7GHhMkrmK0KpVNH6ydGfDYGKCgvUHBO5plnXPnziErKwtLP9uDyKgoLlg5y5NM6jpNlF2sVmfAeL3AGMAzRIBZ2pbYbUCdrL/E7uHzHZ6j/+/nZyE77StQ1oOQF4dpUyehtlYBMcnTaDIaFrwxOtLTS1rniPX82dz3XSRCjZ0AaT/y7Nmz9wMCAlBRUYFt27Zh8dv/hcjJC6D/+gpinh8NZ4kUNR1GDrxd3/w+YAxkMhGYs/z93nMPAc/u51vBF+floLKkEDPmLMTt1BRcSv0Kzpah+Pn0l9HQ1AaLkQehyMk8dGTQ4hdejD5iw7r3jxeyggMCXmhta82wEyD2qyh4twcFBXG5/ubNm1j8+92IDQ+FVEhBe+UsLAED4eYf2iubh4BnYP/2p21YuHI1SchijwFYr9tIM29lXb6AkvxbWP7Bx9z1mpJ8XPnyDJrrvDDjlQkUD2ZUVTXDQy6ld5l0Y+KjF7hJRZVZmeUb3CRu07hsqW77i51AZmZmRmtr6zj2/ciRI4iIicWYtz5CrFzI/aCmx4w6lZbrbTj38x2AoQ/YKUZgxWprEPfdw2LEMQZ0He2Qucu57+xdOo0aWZSCs662Y1rCBK5OqNWsvzJQKyKhe1gLojP6+XkIBM5OKC6p6lyweOwL3E9QlnA+ceJENwUvv6qqCgcOHMDSNZ8getQE+Ls6sSSDao2RsyoHxBGYQ3Cy86f2bcN8IvAg+H4xYPWgLZhtnrmdlopLZyswMX50b4CyvqlTBwNlJzEZzpmAs0PToaXAbs1YtWZmPM+q/2DK9bWRkZGcdM6fP4+3frcTsbGxlPN56CDrK7Qmzgq2wHPM8bD/D5zct92aLq3nHgDvxOsFxuPZDNBLhq3TB/8fFr0Yzk7O4BMzL28pted87n7WevA4z/Nw7cYdxabtS/zsWYi6zFFffPHFzQEDBiAjIwM52dlY9Oku0n8wlzqbCbzWaOlLgTz00zef1+eN43u34fWVtiB+IAbwaPCatg4c+eNZBFESCQ33QbeuB4pmNfwDPLhnlEoNZTaz8n5lXef6zYsi6JzZTqC2tnYWpc3TYWFhuHz5MtWAasz+7Q5Ee7mCZzKgXKmDm9zTDt6WAm1p0jEGTuzeioXvrMaTLkt7M/eupD3pCA0IRFikL3e+vLweMjcJDEb6/Yq69qiYgMygYI9rM159YcM36gBloDmUQk8EBwdzHmilkv6Lj7ZBrKxEY1U5sovK8R/LV9tl86gCxT4vHtiFifk3Iff0suqY/UhfubF5kR2aT3fi84/eoV7pOQyKGYagEE8IBE40yelxr7QWeoNWHxMbdGzh4vHLnZ0F+kcWMurxxyYlJWWGh4eDmjhUUyDP/TARsSF+oJSPhk6j3d32GHhIjt/w30vx6083w4PaEMc46e8pq4ys39PO3oKiqp30LqOOVEwysSAvtxza7nbwhU1HE7ese+3bPMi9nVqIiL1791awGGBt8717pViw5g+IjgjjbmABbJMIj/eQGLCCX0Xg5Vbwjvru9ZRDDFjPlRfVIvNcAXy8PCD3cOXeXVhYSR2qAXlfZyJhetyv33135a7HEqCWVkyVVxcaGkovKGQNHea9+yGi44bClTrP5i5TP/D9ZESf61c9HrzNE7ZWokujxaEdZxFA84aPr4wjVlXVBH13Dxrb8nEhNQmbN2+mxnTWmccSYOvgwYMF1A0OYbMuqwUjx03EiGnz4SdxQj1JiO9QSR3Bb1jVKxsG/sEcz38IeFve37T2MMIDg+DlI+WmPZWqA62tGmi66lFcdh45OTkWGmUDqbVpeiICFLyfXLt27VM2kLOmilXc6Ss/RrCHBAqdGcrGOljMJgSEhNn1zcCv+t1muHt6PTTH94sBXl+63ZOYDA9Xd6qwLlzQGqlQVdxvIPAqBEV04MyZM0wVOdTajHpcFrMTaGxsHEbtcz5r5pgH1Go1pr2+DFFDRqAsPwfJRw/h7Y83wNVN2iebbwHfT0a8viA+fTQDOqURLmIhDT002lGSKCuvQ7deB3efeihamnHp0iUsWrToQ1qbnpgAW5s2bSqnihdFhY2bkvwpL09c9C7qinIRPWIMdzObuI7v24GVa3/fZ1lrcPIdrPwgeOaJ7KslKL5VQ22ykAwh5shWVTfBVSKGWdAGN1kXTp48yeLQQtaPiY6Ovv9UBEhzsykWTrKBRqFQkHsFeGnSdMSMirfOvpZvxIBd3w6ysceAA/j6mlakHM2EzEVKQ4qIq9KtrWr0GEyIinVHZW0WK6i4evUqRo8efWD//v1vPQ78NwiQ9Xnr16/PUalUI2ybVIzMuJnzuH2ffnWA/nR3dXKS4jvIxjHH22oFjYbY9YeTCPDyo9gSgEcPdFO2Uas70aFrR2SsHj00oh4/fpxtkunz8vKiqKjWPzUBtu7duzdu48aN6WKxmMd2DNhGVERkFMZMn0Ma9bODO38qidsHnfbLed8sUPz+Mjp2IBU97WbSvJCzPOv1G5tayfrdeP4lmndVbUhJSUFpaSkWLlz4Ga11TwL+oQTYOn369G+Tk5M/s+2isS3C6JgY/GT8FPiHRqLwdjbysjLx5nur+8cAfV6j0TAsPAJR0THcuzavO4pgvwCYCbRA0NtZ1je0wEy92IiXZGhqqubal4KCArZzl3Hx4sVJlAkN34sAk9KWLVuSKCbmsThgrSzb64yLi0PU4OGIjBsOgbPgoTl+/66tGDhoOJQKAYrzqxBNE52RdM5jWYg01dqmpkHGFY2KKpIOtcbXrnHgSbLVFLgjSLJtTwr+kQTY0uv1LpTGLtKQ/1O2E808wcgMGjQI4RGRCIp5DmFRsXbLM/DZGUW4kJwJobMEvl6ecHd3I/0buWe54USr4z7rmmrw3FAeyNrc/E2tTAvNIBPIQMVPA/5bCbBlMBiEW7du3ZOenv4m289kQc28IZfLMXLkSISEhEJCY6GHty9K7jSjolgBuVTa+2Je36uZZEwUT6w4tijpHt96XL9+ndvhlslkd0iuM0JCQurwHdYTba8fPnx41b59+7YQcCdWqW0AGSHWwcrdYmhu8MaAAeFwkQih7dJDreqyW56RNpksaGlrRUlZGsorb5L2mxAfH3+C0vZ/Uox9p53pJybAFrUX0YmJiRuoR5nNUivLQCy4mVWFGI6XJ7wEqczFPgIyB1RWNMFA4yif2/Ti4VZePi5lfA4PT3khFc3VCQkJF78r8KcmYFu5ubkv7ty58yOSwFSJRCIKDhyGyePnIyTUj9JhOwqoagf4hWHw4Fgu65QU10Bk9VpObq7hZ68EvEmp8igZwPx9wX8nAral1WolqampU1L+VrJvwtjxvu0aDTbtXEEFScvtOM+eudYyNeFlnpYCt5aqsJurC6rr6+vWb349ihq4p9pC/0EI2Nb1zNJlGZdLPpv72uhXQ8O8c6iP8qTA1AiFIsOfPr+k9fP1FBUVVUEuk6KmsaE6cfuS8GcF/pkQYKuttSPEy1ta63gu40rRsqoy9W6RyFlw924NpK4SDBjis/bBofxfgsCD6//+knZIp7HMJ/AiRYuaqrCFCpdCtWXXG/7PUj4/CIGtG1OyXASSUWwfSqXWcMWPLzCXzn19zCIfH1k5tdGqf1kC6ZeLll+7cm9nt76H19Nj0Josxq74l+P+91nL5gcjQKBd6mrb4pTKzmBPD7f68EjfXOp/TD8U+GdO4MdY//YE/gHhh6F7BGlt9gAAAABJRU5ErkJggg=='
-Time_tracker = b'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'
-Time_zone = b'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'
-Time = b'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'
-Timer = b'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'
-Timetable = b'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'
-To_do_list = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAEeUlEQVR42tXZX0xTVxwH8F9pKRTQJXvYA9mmL1sQojCLArZsOFTGfxAL7UCgQsyic4tLttfplmWPy7YHnc6JblCnoCjiv0GGK5vs/5+XLbqnmSzZi3EuoXBve+v53Ul7b2976f3RA/jjobftyeH7yb3nnHtuTfCQlynRF0feHw8vRoCZGTG8ruiJtyuqCt5MOcDj3QQ5KzJ5BZdfTxy+Lr/m5ee+RUHoAtzdZdwAs7PBCODpvCfh5h9/kRD6gK4yyOYEEIQoIH/tagiKEgmhC2hDQE4GF4AohiIAe8lTEJgWGSLEELcNIXQBrZ38AMGgGoAVgzjIEAcWCCiF7GxOgJAUATgq8mEmIJIQ+oCdpZDFCYAVkiQZsKWmUA6uROAldisJhC7A1YEAKzeAFA7LgPqWYgiw8AkRBbkHKrYVHCQBbBwB4QeAZOql/VvjZtUF7OgoAVsWP8DcWvDP33f127FFb8r/J+x+tVKTVx/QrgZI0vx3F2lppnnbGK3AtACD/d8aB7S0bwSbLQoQhRD0HZ6I2x5xvfueB7M5LfWAgABD/d8RAC9uhEwlgA2qEwzQu68yTvsx6Hk5eQBe//HKZNJGmkHAAAGw3YOAdBXg5EfX5aALBRgpnJnO+oiAjMzkAEc/GINde6OAvkMT5MDePRWgPEE4iGkA9wYt4MhX0LN3sxbw4Tjs2rOZyxmQAae+Nw5ojgWwQfzp0cQAL0fAOQqgCQEZFlVHvuNfJ/xH7b3lkJ5uTj2ArRfDJEDbBrAqAEtVAgI+JwAaW5cP4PxpEqAYrNbkAD1+Jxwrn+QDEBDwAwHgKob0JAC9k87I8cfO1CNEBJwhABpcdjYoFYNYmoZnLzXARPUw2Mw58mdefz3Mhu5BhnklvGM/BLlZj6ceIAbhwpkfCYAddrAoAKWjWyLHkzWXwfVlHVjYrBlkm6t37e9B3iP5ke99x+lnwuN1qt4HETBIANTLgOi0KLE/x2iVfJybtSLy+WsFr4PjsTJFpwu/Iw1DdCnGLeYIGWBRz+uCJMBzV2r/71gywRtrXwHXqroFB9YrfABAAtS1rNcAsP4V/4PqsRZwrW6H/Wu6uIafA1wc+okA2L4ezJb4K+sd4R48al3JPTxWCAFnCYBaBHC4tzEMCEkwSgI0LyPAORLgGbbHjQJwYzHkmwKIt5liPbk6ypJeuY2UJCHgZ+OAmiY1APcDg5/dgNbOTZr2p/omwdNdDmnm1G/qEXBpmACobipSAYIPAO6YhQZr4Jgf3N1OboDLw78QAI1FYIoF9N+Qg2oAnzBAVxQwwu5d5h7gGq1mT4nqfRgB56kAxVMCGTAwxYI6tAB26+DudHA5A/gEgwR4oUELwEHc1qkF+NgYaNvJD3DlAhGgbILX4umT37B9cvyZptFVwgWA0x4JUFVfqGqS6GGUqkMTH8DVkV+NA7bVFeo1WcQKw7WLVMCi/Fo8T7GUZEASVw3//FTA1tp1ywbwxehvNIAkLXV8/M2BCCivXLPU2SPlH//dOGCpQ8eWIcDDUvcBZ2nMT+uGWNMAAAAASUVORK5CYII='
-Tower = b'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'
-Turnaround_time = b'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAOqklEQVR42u1ZCVhU19l+594ZZgaGTQKMrOIuYsRfE6hVoyFS8Y8xLjG1f6LGNPTPozUGSdTEpi5pNTUxRKnRPknQEE1rjUtMahDUqKgIgoIKirIIsu8MwzJrv3NgYAZGo03atM/T+zz3udczl3Pe9/vebzlHCf7DL8mPDeA/hoDBYFDpdDp3uVxeI4pi+781Aa1WG1JbW/sU3VPo3U+j0fh0dHS4GI1GEAmzIAh1Dg4O5SqVqtjX1/fogAEDvqT38h+VAFnYo7y8PKa0tHQ+AQ8ioCCgkMlk/JZKpfy7trY2SCQStLS0gIihubkZer0earU6Kzg4ePfYsWN30rcd/zICZFXH6urq5fn5+avr6upUCoUCLi4u/LfGxkbQGAfd3t7OrM/HzWYzJ0Re4E+TycQMwL9VKpV3IiMj3xwzZsxnZADTP5UAWW/q9evXEysqKrwdHR3h6uoKsj6qqqq4ZYuKilBZWckJMPAkIzg5OYHkwp/u7u5gf8eBkFcoPpj8OFkPD48rixcvnuvt7Z3/TyFAIJddu3YtjkBJaDEO+Pbt26AxZGVlEZEaDBkyBIOHjUA/tR9cPDyhULlC19oCbWMdNA21uH0rn8uIEWdzUHBz77CLeYSk1RwdHT03JCQk+QcjQAtIS0pK/pibmxvNLMYsWFhYiKtXryI5ORluBGbK9KfgE/w/kHkGQOnmCQcBcBAlEOlpMpnBMJppaWOHFtrK26guyEVO2mn+GyPDvMECnkmrqanJNG/evFeioqLifxACBD4+Ozt7CXM/W4gkhAMHDqCmuhoz5/0cfmGRcPYdBFe5AFdC7iiVQJB0LpSZcgShkyLhQHHCWLQazGgzmtFuADqaalGY8S1uXMqAiX5jczMCzCP19fUgOS2KiIjY/b0IULC+fPHixe3Ozs7cQkQEiYmJGDRwICIX/hrOQ8bgIbkZXio5gZYQCECwWijt6AGMnhwFqULJ/8084sDYkUfq2/RERgJNVQnSv/4LGiig2RqMAJNTTU2Nfv369Y+NHDny/D9EgLQ6OT09/Ti9CizTMJ1/uH07IqdNQ+jTi+ERMBgBziLyUpMwZMx4OFImYpNr9WRpvQltZO3Thz9HeNQsClYF9wojKaUXJrGD2zZgUcwaaA0CtJpG5CQfQmlxAY8t5gmWaklO+qVLlwZPmTLl1gMRoAlkBPgGZZsgT09P5OXlYceOHeg3bSjGT16I8EET0N9J4G7Xt7Ui9/wJDJk4HTVtJi4HgVub5JZ5FsNCH+V1QZR0SotdZ778C/fWE0/Ph1yk1Exjho52ZB79K4pu3uASYp4oKytDRkZGPKXbXz8QAUqFS8+dO7fNx8eHxQC2nNqNypE6zA73xKUST8RPepdPxG49BWL+nSqIKnfISCMWoAzgthUvYsX7n/A5LeApttFQXQkvdf/ucXaz8Q6tBplJX+DmjRvM+lxSZ86cYfUljEik3xcB+iPn1NTUIsrPHlnGInxa+TdMGFqDQFcRvopQbMuuxd6pe7mVWVBWtBp5NukE0Zl5LAtti30RsV0EJN1gJRysBbzYRYB5kw03V5fjIskpOzuHy4jViVOnTl0gAuH3RYBag9j403s3JyMTYwPL4K8yY5DTZHgofJFV+zdk1huxIGgr/FQDUKY18uwiWoBZgWdjH6zoIdAbPPtWgC149pvZoMdNkl7m+TM8XbPr/PnzzCMjiMT1exI4UnR25urU9/eFDahyCHA2YLDTlG7gOXXHSS7t6O8WCjfTmwj3fpLrXeyyvCD0WJXHAI1tiVmMlXEWAj0xwMCLXanWAv5OYT4Stvwer7y1kSq3E66mHsOxpCRe0Skb4vLly58TgV/YJXD0dtr032ft2DLcuzjA36ldOdBxMtzl/ZFdl0zAUzhwy+Xr5ofMW9OxKjyuUwJCDzCLjAR0xsCWVxdj1QcJtjEgoNtjfJx7zIxt61YiesWbcHZ148ZgXjiZdJS3JywWTp8+TbnFJNoQSCnNiHw7c8f7gzyLAv2dtE5cKnI/Ap2M7Ppk6IxtNkSZrRTUkGVVzMS74btoob7gu/VN93vkgdVdBHgM2AFviQHLGJcWvdaWlSDj22M4ceIEbwDPnj3L4mEE/6pUUxWw8MSarwI9CoMCVRpVkOMkeCoCkVOfwsF3GFut3Ns5seWdt8aGSMzy/4DiwNd+cHaNbSYPvLE1oTv72ACV9BCQWIqgpIegkYrZ9QunsHPnDt43ZWZmsoz4Gv/rp48uT1W7F4xWiJdUPrJHSOf+OFn2CTpM2m6Q1s9uAl169XUPRV39y5g3eF6PbKzSpKQrBt5Z/gLWbOuRkDV4CwF74C3f5F+6gLj3NsPf358XUtYJd0voq+KzM+Kyd7+tdisJVKsKXM06OZRSFxRrskiR5h4PSGw9wBZQu/ji8p05WDH6N33AC1YxsIkI/LaLgKQXeLF7XlvwPR4Fiq5dxqbfbeAEWNebk5OT3ieIRyU+o3vU77ggoRo0e+BbuNZwHFfptvGEjQckcHRQIKVgCuInJnQ3bvZy/MZXiED8rp4YsAPeWlrW4Nl4cX4e1q1ZjREjRvA+jGTUZI9ACxFQKOUqMcr/FYqDJBQ0p/UQkPSOgc5gLm6agEWDtkLt6HXXApUUG42nGmt4328hYZFkr0dn8/d/v8Tejz/k75u3f0R7CQ1WrXgVYWFhSEtLY21FbR8Coz+bVz/ON8Wln5OX+Jh6MS7Xf4U7rVftBzGXR+dTlA6Hs34VIv0n98nxTEIbli5E7KZtcHZx7dG8JfsIvWLAJsgt80hQeusGVsbGIDw8nFVjJqFCGwIhiXOpOxSrHh+Y7iXQDI/1f4kklEwErth4wJqM5dlPpUZm8ZN4bfTqPjl+/ZJO8C4EXrgLeNEqlQpW4DvTbac3S4jAG6tWYtSoUTh+/Dhu3bqVY88DDRGDMtxMog5TfZbhpiYVt1su2s1CStK+UuaIprZGOMqVOHBlHP702Mc2OX7D0kVYsXErB987dd4PeEthZHd5cSE2/+Edvgtk9YC64w/7EBi39xep44NO/0QqNQmT1b9CRVsebmnO2s1CSpkC+66OwFhfE0LVlUi66Y/lwfHwUrrzBXuD753jBSvwPem2M5glVumY3WxTU3wjF4cPH8YN6k67CtnP+xAI3fPse5MGXYpxlHVgtMdT0Jlacb35LlmIZv76xsN4efhvsK/wUwjSOox0icJzQ2d1g2d73HsVKJuiBvvg2VVbWYEUaiXYicX+/fvZHpzt/of2IUBxEBEWUJsc7KORKOEHH0UwLjXu59s+e1noWsUABGtewPTxM5FenYXa1hpkb/m8G/z9FCjLmCVjsde1K2OwYvUaXnXZtxWlxdiVkMA3Nkz/+fn5WnYOZY+AnB4XFoRpRpoNddJg12ko0J6BRl9lNwuJghp3KufjheHP8cXXk+VjmWxcXR8ox/ek207L3y4qwJaNb2PNurfhStvTwlv5PHXSxgoXLlxgW823iMAGu90okUh6JrQ5UhRLMcw5Aq3GOpS3XbGbhZwoeP+UNhi7Hv8IX3yyHc+8uMTKqrbgu2VkBzwPVosHrNoPs9GA+ppqJH6WyK1/5MgRZn12YhdEBEruRiCCHhNWTm5cq9FL4KccjYKWUzDBYKeZoxLfMBDDFcvxU/U4uzneJgbukuN79gM94NlYHYHPy8vlxzdJtB9gFVij0SQS+AXWhc8eibzpIfBRqwpdAhwfQbupEXW6AruFzEnuiO3nApEwZSdflAXcQ95qansFmxjonSYt4CvLSnl/05NKO8FrW5rR1NiIgwcPsmMVHDt2DMXFxUbyhC8RqPouAhEUuBNen9qwtl0HqOUhqOjIhtHc0auQdbYDV6pd8bjHOnh3eOHDd9bht3E77rtAffnFPtrv6vDs/Oe6Y0Cv64CmuQl79uzhG5hDhw6hoKCApdM3CPxGC857bilDPp174PlxmlluqhaoRE+opN6o0eVyLVo3czyYqb85eE0FlyMPYeEvX8fAgIF9wB/6cyKenD2XnUD3SZMvzn8GH+3eA6VCThJpIgI67Nu3j//GTv7YfrilpSWZPPEzQRDM90vAmVrpylVTRVFnqJS7yvwgE5So1xfYtNMWEjJRijNFXpjk8f8I93qkO01adB8TvRDr3o1DP/d+tjLi8jLzZ3VVBd/3soLF5vzmm2+YbPg++Pnnn/eOi4urtsZ4TwLsGvnpnJ/S463XJjZFCgozXKS+9E8TtMYq24zURURKnkgrUcDdHIUFQxZaxQDw+pKXsHbTu3B3c4PECjz7pqmhDgaSUU7OFV5pc3WlOFyZAbevq9jxfHlqamoYxcmd3vi+k0AXiSgyUEzsxKYnlCoRcsEVDoITWk3MGGabRo8FNTNtrVaKhAwTHn1oImYFzUCIx0CrzY6Ze661RYPmxgbIZVJ2fIMDZ79Bjms58k130FrfBulfy+An65dBQTzTx8enwh62+yLASeye8zOS02tLHm2OUHuxw1sZEXGhoG4lf+j7BDUnQ3dzh4jj+cC5Yj385N4IcvKBt9wTjlIlyhsqUFBXjDJDDYxKPR72FdGqN+JkRiPEP+Zj2hORiTt37oymmLnrfwreNwF2Be+ePYqMd2xeiF79yFAZP4GTCjKahDYoEhP9ZOyz8eleiB+Xi9DoSH46MwxUihxlAlRyuh2oYJkFfHayASm7iiGkN5etX79+9YIFCxK/C9MDEeAkds2WkSe2UiZyj4lwmjPAwyBlWUnoOsmy/A9L5+SSXsHOmdg0g6KEPHRZg/gj5Wg7WdX25v9Gr122bNnWe1n9exGwXMMTnh5KJt9EgE2rpznOCegnPNBktRojUq62YH9aAwKr3LNeHffs+zNmzDji5ubW9CA4/mEClmvYxzMHE4n5dP+K7rRF45Vz1C4iPJwEKBwkXGYGI9CmN+F2rR65ZR1Iymm5aTKZLppN5riaVWfSv8/635uA9RXx55f8ipvKhxGREQTuYXr60K2l9zaT2dRAT3YemEVjdypjvzX+EGv+oAR+jOu/BH7s6+/rWnbYMe/i9AAAAABJRU5ErkJggg=='
-Wait = b'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'
-Wall_clock = b'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'
-Week = b'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'
-Wrist_watch = b'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'
-
-vars = dir()
-png_images = []
-png_names = []
-for var in vars:
- png_images.append(eval(var))
- png_names.append(var)
-
-main()
diff --git a/DemoPrograms/Demo_Conways_Game_of_Life.py b/DemoPrograms/Demo_Conways_Game_of_Life.py
new file mode 100644
index 000000000..cd100e9d1
--- /dev/null
+++ b/DemoPrograms/Demo_Conways_Game_of_Life.py
@@ -0,0 +1,188 @@
+#!/usr/bin/env python
+
+# John Conway's "Game of Life" using a GUI.
+# Copyright (C) 2018 PySimpleGUI.org
+# GUI provided by PySimpleGUI.
+# Core game engine provied by Christian Jacobs
+
+# An implementation of Conway's Game of Life in Python.
+
+# Copyright (C) 2013 Christian Jacobs.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import numpy
+import PySimpleGUI as sg
+
+BOX_SIZE = 15
+
+
+class GameOfLife:
+
+ def __init__(self, N=20, T=200):
+ """ Set up Conway's Game of Life. """
+ # Here we create two grids to hold the old and new configurations.
+ # This assumes an N*N grid of points.
+ # Each point is either alive or dead, represented by integer values of 1 and 0, respectively.
+ self.N = N
+ self.old_grid = numpy.zeros(N * N, dtype='i').reshape(N, N)
+ self.new_grid = numpy.zeros(N * N, dtype='i').reshape(N, N)
+ self.T = T # The maximum number of generations
+
+ # Set up a random initial configuration for the grid.
+ for i in range(0, self.N):
+ for j in range(0, self.N):
+ self.old_grid[i][j] = 0
+ self.init_graphics()
+ self.manual_board_setup()
+
+ def live_neighbours(self, i, j):
+ """ Count the number of live neighbours around point (i, j). """
+ s = 0 # The total number of live neighbours.
+ # Loop over all the neighbours.
+ for x in [i - 1, i, i + 1]:
+ for y in [j - 1, j, j + 1]:
+ if (x == i and y == j):
+ continue # Skip the current point itself - we only want to count the neighbours!
+ if (x != self.N and y != self.N):
+ s += self.old_grid[x][y]
+ # The remaining branches handle the case where the neighbour is off the end of the grid.
+ # In this case, we loop back round such that the grid becomes a "toroidal array".
+ elif (x == self.N and y != self.N):
+ s += self.old_grid[0][y]
+ elif (x != self.N and y == self.N):
+ s += self.old_grid[x][0]
+ else:
+ s += self.old_grid[0][0]
+ return s
+
+ def play(self):
+ """ Play Conway's Game of Life. """
+
+ # Write the initial configuration to file.
+
+ self.t = 1 # Current time level
+ while self.t <= self.T: # Evolve!
+ # print( "At time level %d" % t)
+
+ # Loop over each cell of the grid and apply Conway's rules.
+ for i in range(self.N):
+ for j in range(self.N):
+ live = self.live_neighbours(i, j)
+ if (self.old_grid[i][j] == 1 and live < 2):
+ self.new_grid[i][j] = 0 # Dead from starvation.
+ elif (self.old_grid[i][j] == 1 and (live == 2 or live == 3)):
+ self.new_grid[i][j] = 1 # Continue living.
+ elif (self.old_grid[i][j] == 1 and live > 3):
+ self.new_grid[i][j] = 0 # Dead from overcrowding.
+ elif (self.old_grid[i][j] == 0 and live == 3):
+ self.new_grid[i][j] = 1 # Alive from reproduction.
+
+ # Output the new configuration.
+
+ # The new configuration becomes the old configuration for the next generation.
+ self.old_grid = self.new_grid.copy()
+ self.draw_board()
+ # Move on to the next time level
+ self.t += 1
+
+ def init_graphics(self):
+ self.graph = sg.Graph((600, 600), (0, 0), (450, 450),
+ key='-GRAPH-',
+ change_submits=True,
+ drag_submits=False,
+ background_color='lightblue')
+ layout = [
+ [sg.Text('Game of Life', font='ANY 15'),
+ sg.Text('', key='-OUTPUT-', size=(30, 1), font='ANY 15')],
+ [self.graph],
+ [sg.Button('Go!', key='-DONE-'),
+ sg.Text(' Delay (ms)'),
+ sg.Slider([0, 800],
+ orientation='h',
+ key='-SLIDER-',
+ enable_events=True,
+ size=(15, 15)),
+ sg.Text('', size=(3, 1), key='-S1-OUT-'),
+ sg.Text(' Num Generations'), sg.Slider([0, 20000],
+ default_value=4000,
+ orientation='h',
+ size=(15, 15),
+ enable_events=True,
+ key='-SLIDER2-'),
+ sg.Text('', size=(3, 1), key='-S2-OUT-')]
+ ]
+
+ self.window = sg.Window('Window Title', layout, finalize=True)
+ event, values = self.window.read(timeout=0)
+ self.delay = values['-SLIDER-']
+ self.window['-S1-OUT-'].update(values['-SLIDER-'])
+ self.window['-S2-OUT-'].update(values['-SLIDER2-'])
+
+ def draw_board(self):
+ BOX_SIZE = 15
+ self.graph.erase()
+ for i in range(self.N):
+ for j in range(self.N):
+ if self.old_grid[i][j]:
+ self.graph.draw_rectangle((i * BOX_SIZE, j * BOX_SIZE),
+ (i * BOX_SIZE + BOX_SIZE,
+ j * (BOX_SIZE) + BOX_SIZE),
+ line_color='black', fill_color='yellow')
+ event, values = self.window.read(timeout=self.delay)
+ if event in (None, '-DONE-'):
+ return
+ self.delay = values['-SLIDER-']
+ self.T = int(values['-SLIDER2-'])
+ self.window['-S1-OUT-'].update(values['-SLIDER-'])
+ self.window['-S2-OUT-'].update(values['-SLIDER2-'])
+ self.window['-OUTPUT-'].update('Generation {}'.format(self.t))
+
+ def manual_board_setup(self):
+ ids = []
+ for i in range(self.N):
+ ids.append([])
+ for j in range(self.N):
+ ids[i].append(0)
+ while True: # Event Loop
+ event, values = self.window.read()
+ if event is None or event == '-DONE-':
+ break
+ self.window['-S1-OUT-'].update(values['-SLIDER-'])
+ self.window['-S2-OUT-'].update(values['-SLIDER2-'])
+ mouse = values['-GRAPH-']
+
+ if event == '-GRAPH-':
+ if mouse == (None, None):
+ continue
+ box_x = mouse[0] // BOX_SIZE
+ box_y = mouse[1] // BOX_SIZE
+ if self.old_grid[box_x][box_y] == 1:
+ id_val = ids[box_x][box_y]
+ self.graph.delete_figure(id_val)
+ self.old_grid[box_x][box_y] = 0
+ else:
+ id_val = self.graph.draw_rectangle((box_x * BOX_SIZE, box_y * BOX_SIZE),
+ (box_x * BOX_SIZE + BOX_SIZE,
+ box_y * (BOX_SIZE) + BOX_SIZE),
+ line_color='black', fill_color='yellow')
+ ids[box_x][box_y] = id_val
+ self.old_grid[box_x][box_y] = 1
+ self.window['-DONE-'].update(text='Exit')
+
+
+if (__name__ == "__main__"):
+ game = GameOfLife(N=35, T=200)
+ game.play()
+ game.window.close()
diff --git a/DemoPrograms/Demo_Crossword_Puzzle.py b/DemoPrograms/Demo_Crossword_Puzzle.py
index 9c791a0b9..c01d78e47 100644
--- a/DemoPrograms/Demo_Crossword_Puzzle.py
+++ b/DemoPrograms/Demo_Crossword_Puzzle.py
@@ -6,10 +6,6 @@
Demo application to show how to draw rectangles and letters on a Graph Element
This demo mocks up a crossword puzzle board
It will place a letter where you click on the puzzle
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -39,7 +35,7 @@
while True: # Event Loop
event, values = window.read()
print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
mouse = values['-GRAPH-']
diff --git a/DemoPrograms/Demo_Cursor_Previewer.py b/DemoPrograms/Demo_Cursor_Previewer.py
deleted file mode 100644
index 9d66fa4c7..000000000
--- a/DemoPrograms/Demo_Cursor_Previewer.py
+++ /dev/null
@@ -1,50 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Preview tkinter cursors
-
- Shows the standard tkinter cursors using Buttons
-
- The name of the cursor is on the Button. Mouse over the Button and you'll see
- what that cursor looks like.
- This list of cursors is a constant defined in PySimpleGUI. The constant name is:
- sg.TKINTER_CURSORS
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-cursors = sg.TKINTER_CURSORS
-# Make a layout that's 10 buttons across
-NUM_BUTTONS_PER_ROW = 10
-layout = [[]]
-row = []
-for i, c in enumerate(cursors):
- # print(i, c)
- row.append(sg.Button(c, size=(14,3), k=c))
- if ((i+1) % NUM_BUTTONS_PER_ROW) == 0:
- layout.append(row)
- row = []
- # print(row)
-# Add on the last, partial row
-start = len(cursors)//NUM_BUTTONS_PER_ROW * NUM_BUTTONS_PER_ROW
-row = []
-for i in range(start, len(cursors)):
- row.append(sg.Button(cursors[i], size=(14,3), k=cursors[i]))
-layout.append(row)
-
-window = sg.Window('Cursor Previewer',layout, finalize=True)
-
-# set the cursor on each of the buttons that has the name of the cursor as the text
-for c in cursors:
- window[c].set_cursor(c)
-
-# The ubiquitous event loop...
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Cursors.py b/DemoPrograms/Demo_Cursors.py
deleted file mode 100644
index 20ebf0291..000000000
--- a/DemoPrograms/Demo_Cursors.py
+++ /dev/null
@@ -1,55 +0,0 @@
-import PySimpleGUI as sg
-import webbrowser
-
-"""
- Demo Cursors
-
- Demonstration of setting an Element's Cursor to use a different cursor than the standard arrow.
- Can also change Cursor at the Window level.
-
- If you want no cursor, set the cursor to the string 'none'.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Here is a more complete list of cursors you can choose from
-cursors = sg.TKINTER_CURSORS
-
-sg.theme('Light Blue 2')
-
-layout = [ [sg.Text('Here is a clickable link for you')],
- [sg.Text('Notice how the cursor switches to a "hand" when hover over the link')],
- [sg.Text('www.PySimpleGUI.org', font='default 12 underline', text_color='blue', enable_events=True, key='-LINK-')],
- [sg.Text('Try out these additional cursors')],
- [sg.Text('watch - This makes the spinning-donut-of-death cursor on Windows', key='-WATCH-')],
- [sg.Text('fleur - The "Move" cursor', key='-FLEUR-')],
- [sg.Text('trek - Beam me up Scotty!', key='-TREK-')],
- [sg.Text('none - No cursor at all', key='-NONE-')],
- [sg.Text('For touchscreen applications, you may want to turn off the cursor entirely for the windw')],
- [sg.Text('Click the Hide Cursor button to turn off at the Window level.')],
- [sg.Text('Elements that have specific cursors set will continue to show those cursors')],
- [sg.Button('Hide Cursor'), sg.Button('Exit')] ]
-
-window = sg.Window('Cursor Demo', layout, finalize=True)
-
-# Make sure window is finalized first. Then set the cursor
-window['-LINK-'].set_cursor(cursor='hand1')
-window['-WATCH-'].set_cursor(cursor='watch')
-window['-FLEUR-'].set_cursor(cursor='fleur')
-window['-TREK-'].set_cursor(cursor='trek')
-window['Exit'].set_cursor(cursor='no')
-window['-NONE-'].set_cursor(cursor='none')
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Hide Cursor':
- window.set_cursor('none') # special value that hides the cursor entirely
- elif event == '-LINK-':
- # if the text was clicked, open a browser using the text as the address
- webbrowser.open(window['-LINK-'].DisplayText) # accessing DisplayText isn't something you'll see often
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_DOC_Viewer_PIL.py b/DemoPrograms/Demo_DOC_Viewer_PIL.py
new file mode 100644
index 000000000..ae24bad55
--- /dev/null
+++ b/DemoPrograms/Demo_DOC_Viewer_PIL.py
@@ -0,0 +1,237 @@
+"""
+@created: 2018-08-19 18:00:00
+@author: (c) 2018 Jorj X. McKie
+Display a PyMuPDF Document using Tkinter
+-------------------------------------------------------------------------------
+Dependencies:
+-------------
+PyMuPDF, PySimpleGUI (requires Python 3), Tkinter, PIL
+License:
+--------
+GNU GPL V3+
+Description
+------------
+Get filename and start displaying page 1. Please note that all file types
+of MuPDF are supported (including EPUB e-books and HTML files for example).
+Pages can be directly jumped to, or buttons can be used for paging.
+
+This version contains enhancements:
+* Use of PIL improves response times by a factor 3 or more.
+* Zooming is now flexible: only one button serves as a toggle. Arrow keys can
+ be used for moving the window when zooming.
+
+We also interpret keyboard events (PageDown / PageUp) and mouse wheel actions
+to support paging as if a button was clicked. Similarly, we do not include
+a 'Quit' button. Instead, the ESCAPE key can be used, or cancelling the window.
+To improve paging performance, we are not directly creating pixmaps from
+pages, but instead from the fitz.DisplayList of the page. A display list
+will be stored in a list and looked up by page number. This way, zooming
+pixmaps and page re-visits will re-use a once-created display list.
+
+"""
+import sys
+import fitz
+import sys
+import PySimpleGUI as sg
+
+import tkinter as tk
+from PIL import Image, ImageTk
+import time
+
+if len(sys.argv) == 1:
+ fname = sg.popup_get_file('Document Browser', 'Document file to open',
+ no_window=True,
+ file_types=(
+ ("PDF Files", "*.pdf"),
+ ("XPS Files", "*.*xps"),
+ ("Epub Files", "*.epub"),
+ ("Fiction Books", "*.fb2"),
+ ("Comic Books", "*.cbz"),
+ ("HTML", "*.htm*")
+ # add more document types here
+ )
+ )
+else:
+ fname = sys.argv[1]
+
+if not fname:
+ sg.popup("Cancelling:", "No filename supplied")
+ raise SystemExit("Cancelled: no filename supplied")
+
+doc = fitz.open(fname)
+page_count = len(doc)
+
+# used for response time statistics only
+fitz_img_time = 0.0
+tk_img_time = 0.0
+img_count = 1
+
+# allocate storage for page display lists
+dlist_tab = [None] * page_count
+
+title = "PyMuPDF display of '%s', pages: %i" % (fname, page_count)
+
+
+def get_page(pno, zoom=False, max_size=None, first=False):
+ """Return a PNG image for a document page number.
+ """
+ dlist = dlist_tab[pno] # get display list of page number
+ if not dlist: # create if not yet there
+ dlist_tab[pno] = doc[pno].getDisplayList()
+ dlist = dlist_tab[pno]
+ r = dlist.rect # the page rectangle
+ clip = r
+ # ensure image fits screen:
+ # exploit, but do not exceed width or height
+ zoom_0 = 1
+ if max_size:
+ zoom_0 = min(1, max_size[0] / r.width, max_size[1] / r.height)
+ if zoom_0 == 1:
+ zoom_0 = min(max_size[0] / r.width, max_size[1] / r.height)
+ mat_0 = fitz.Matrix(zoom_0, zoom_0)
+
+ if not zoom: # show total page
+ pix = dlist.getPixmap(matrix=mat_0, alpha=False)
+ else:
+ mp = r.tl + (r.br - r.tl) * 0.5 # page rect center
+ w2 = r.width / 2
+ h2 = r.height / 2
+ clip = r * 0.5
+ tl = zoom[0] # old top-left
+ tl.x += zoom[1] * (w2 / 2)
+ tl.x = max(0, tl.x)
+ tl.x = min(w2, tl.x)
+ tl.y += zoom[2] * (h2 / 2)
+ tl.y = max(0, tl.y)
+ tl.y = min(h2, tl.y)
+ clip = fitz.Rect(tl, tl.x + w2, tl.y + h2)
+
+ mat = mat_0 * fitz.Matrix(2, 2) # zoom matrix
+ pix = dlist.getPixmap(alpha=False, matrix=mat, clip=clip)
+
+ if first: # first call: tkinter still inactive
+ img = pix.getPNGData() # so use fitz png output
+ else: # else take tk photo image
+ pilimg = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
+ img = ImageTk.PhotoImage(pilimg)
+
+ return img, clip.tl # return image, clip position
+
+
+root = tk.Tk()
+max_width = root.winfo_screenwidth() - 20
+max_height = root.winfo_screenheight() - 135
+max_size = (max_width, max_height)
+root.destroy()
+del root
+
+
+cur_page = 0
+data, clip_pos = get_page(cur_page, zoom=False, max_size=max_size, first=True)
+
+image_elem = sg.Image(data=data)
+
+goto = sg.InputText(str(cur_page + 1), size=(5, 1), key="-PageNumber-")
+
+layout = [[
+ sg.ReadButton('Next'),
+ sg.ReadButton('Prev'),
+ sg.Text('Page:'),
+ goto,
+ sg.Text('(%i)' % page_count),
+ sg.ReadButton('Zoom'),
+ sg.Text('(toggle on/off, use arrows to navigate while zooming)'),
+ ],
+ [image_elem],
+]
+
+window = sg.Window(title, layout, return_keyboard_events=True,
+ location=(0, 0), use_default_focus=False, no_titlebar=False)
+
+# now define the buttons / events we want to handle
+enter_buttons = [chr(13), "Return:13"]
+quit_buttons = ["Escape:27", chr(27)]
+next_buttons = ["Next", "Next:34", "MouseWheel:Down"]
+prev_buttons = ["Prev", "Prior:33", "MouseWheel:Up"]
+Up = "Up:38"
+Left = "Left:37"
+Right = "Right:39"
+Down = "Down:40"
+zoom_buttons = ["Zoom", Up, Down, Left, Right]
+
+# all the buttons we will handle
+my_keys = enter_buttons + next_buttons + prev_buttons + zoom_buttons
+
+# old page store and zoom toggle
+old_page = 0
+old_zoom = False
+
+while True:
+ event, value = window.read()
+ if event is None and (value is None or value['-PageNumber-'] is None):
+ break
+ if event in quit_buttons:
+ break
+
+ zoom_pressed = False
+ zoom = False
+
+ if event in enter_buttons:
+ try:
+ cur_page = int(value['-PageNumber-']) - 1 # check if valid
+ while cur_page < 0:
+ cur_page += page_count
+ except:
+ cur_page = 0 # this guy's trying to fool me
+
+ elif event in next_buttons:
+ cur_page += 1
+ elif event in prev_buttons:
+ cur_page -= 1
+ elif event == Up:
+ zoom = (clip_pos, 0, -1)
+ elif event == Down:
+ zoom = (clip_pos, 0, 1)
+ elif event == Left:
+ zoom = (clip_pos, -1, 0)
+ elif event == Right:
+ zoom = (clip_pos, 1, 0)
+ elif event == "Zoom":
+ zoom_pressed = True
+ zoom = (clip_pos, 0, 0)
+
+ # sanitize page number
+ if cur_page >= page_count: # wrap around
+ cur_page = 0
+ while cur_page < 0: # pages > 0 look nicer
+ cur_page += page_count
+
+ if zoom_pressed and old_zoom:
+ zoom = zoom_pressed = old_zoom = False
+
+ t0 = time.perf_counter()
+ data, clip_pos = get_page(cur_page, zoom=zoom, max_size=max_size,
+ first=False)
+ t1 = time.perf_counter()
+ image_elem.update(data=data)
+ t2 = time.perf_counter()
+ fitz_img_time += t1 - t0
+ tk_img_time += t2 - t1
+ img_count += 1
+ old_page = cur_page
+ old_zoom = zoom_pressed or zoom
+
+ # update page number field
+ if event in my_keys:
+ goto.update(str(cur_page + 1))
+
+window.close()
+
+# print some response time statistics
+if img_count > 0:
+ print("response times for '%s'" % doc.name)
+ print("%.4f" % (fitz_img_time/img_count), "sec fitz avg. image time")
+ print("%.4f" % (tk_img_time/img_count), "sec tk avg. image time")
+ print("%.4f" % ((fitz_img_time + tk_img_time)/img_count), "sec avg. total time")
+ print(img_count, "images read")
+ print(page_count, "pages")
diff --git a/DemoPrograms/Demo_Dashboard.py b/DemoPrograms/Demo_Dashboard.py
deleted file mode 100644
index 0c38a1382..000000000
--- a/DemoPrograms/Demo_Dashboard.py
+++ /dev/null
@@ -1,66 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Dashboard using blocks of information.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-theme_dict = {'BACKGROUND': '#2B475D',
- 'TEXT': '#FFFFFF',
- 'INPUT': '#F2EFE8',
- 'TEXT_INPUT': '#000000',
- 'SCROLL': '#F2EFE8',
- 'BUTTON': ('#000000', '#C2D4D8'),
- 'PROGRESS': ('#FFFFFF', '#C7D5E0'),
- 'BORDER': 1,'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0}
-
-# sg.theme_add_new('Dashboard', theme_dict) # if using 4.20.0.1+
-sg.LOOK_AND_FEEL_TABLE['Dashboard'] = theme_dict
-sg.theme('Dashboard')
-
-BORDER_COLOR = '#C7D5E0'
-DARK_HEADER_COLOR = '#1B2838'
-BPAD_TOP = ((20,20), (20, 10))
-BPAD_LEFT = ((20,10), (0, 10))
-BPAD_LEFT_INSIDE = (0, 10)
-BPAD_RIGHT = ((10,20), (10, 20))
-
-top_banner = [[sg.Text('Dashboard'+ ' '*64, font='Any 20', background_color=DARK_HEADER_COLOR),
- sg.Text('Tuesday 9 June 2020', font='Any 20', background_color=DARK_HEADER_COLOR)]]
-
-top = [[sg.Text('The Weather Will Go Here', size=(50,1), justification='c', pad=BPAD_TOP, font='Any 20')],
- [sg.T(f'{i*25}-{i*34}') for i in range(7)],]
-
-block_3 = [[sg.Text('Block 3', font='Any 20')],
- [sg.Input(), sg.Text('Some Text')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-
-block_2 = [[sg.Text('Block 2', font='Any 20')],
- [sg.T('This is some random text')],
- [sg.Image(data=sg.DEFAULT_BASE64_ICON)] ]
-
-block_4 = [[sg.Text('Block 4', font='Any 20')],
- [sg.T('This is some random text')],
- [sg.T('This is some random text')],
- [sg.T('This is some random text')],
- [sg.T('This is some random text')]]
-
-
-layout = [[sg.Column(top_banner, size=(960, 60), pad=(0,0), background_color=DARK_HEADER_COLOR)],
- [sg.Column(top, size=(920, 90), pad=BPAD_TOP)],
- [sg.Column([[sg.Column(block_2, size=(450,150), pad=BPAD_LEFT_INSIDE)],
- [sg.Column(block_3, size=(450,150), pad=BPAD_LEFT_INSIDE)]], pad=BPAD_LEFT, background_color=BORDER_COLOR),
- sg.Column(block_4, size=(450, 320), pad=BPAD_RIGHT)]]
-
-window = sg.Window('Dashboard PySimpleGUI-Style', layout, margins=(0,0), background_color=BORDER_COLOR, no_titlebar=True, grab_anywhere=True)
-
-while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-window.close()
diff --git a/DemoPrograms/Demo_Date_Chooser.py b/DemoPrograms/Demo_Date_Chooser.py
deleted file mode 100644
index 7303248ab..000000000
--- a/DemoPrograms/Demo_Date_Chooser.py
+++ /dev/null
@@ -1,166 +0,0 @@
-import PySimpleGUI as sg
-import datetime
-import calendar
-import itertools
-
-"""
- Demo_Date_Chooser
-
- This is the same code that is now used internally in PySimpleGUI as the 'date chooser'
- It is shown here in a demo program form to demonstrate to you that PySimpleGUI is being used
- to implement user features. The underlying GUI framework is no longer being used like it was previously
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sunday_plus=0, no_titlebar=True, title='Choose Date', keep_on_top=True, location=(None, None), close_when_chosen=False, icon=None, locale=None, month_names=None, day_abbreviations=None):
- """
- Display a calendar window, get the user's choice, return as a tuple (mon, day, year)
-
- :param start_mon: The starting month
- :type start_mon: int
- :param start_day: The starting day - optional. Set to None or 0 if no date to be chosen at start
- :type start_day: int or None
- :param start_year: The starting year
- :type start_year: int
- :param begin_at_sunday_plus: Determines the left-most day in the display. 0=sunday, 1=monday, etc
- :type begin_at_sunday_plus: int
- :param icon: Same as Window icon parameter. Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO
- :type icon: str
- :param locale: locale used to get the day names
- :type locale: str
- :param month_names: optional list of month names to use (should be 12 items)
- :type month_names: List[str]
- :param day_abbreviations: optional list of abbreviations to display as the day of week
- :type day_abbreviations: List[str]
- :return: Tuple containing (month, day, year) of chosen date or None if was cancelled
- :rtype: None or (int, int, int)
- """
-
- if month_names is not None and len(month_names) != 12:
- sg.popup_error('Incorrect month names list specified. Must have 12 entries.', 'Your list:', month_names)
-
- if day_abbreviations is not None and len(day_abbreviations) != 7:
- sg.popup_error('Incorrect day abbreviation list. Must have 7 entries.', 'Your list:', day_abbreviations)
-
- day_font = 'TkFixedFont 9'
- mon_year_font = 'TkFixedFont 10'
- arrow_font = 'TkFixedFont 7'
-
- now = datetime.datetime.now()
- cur_month, cur_day, cur_year = now.month, now.day, now.year
- cur_month = start_mon or cur_month
- if start_mon is not None:
- cur_day = start_day
- else:
- cur_day = cur_day
- cur_year = start_year or cur_year
-
-
- def update_days(window, month, year, begin_at_sunday_plus):
- [window[(week, day)].update('') for day in range(7) for week in range(6)]
- weeks = calendar.monthcalendar(year, month)
- month_days = list(itertools.chain.from_iterable([[0 for _ in range(8 - begin_at_sunday_plus)]] + weeks))
- if month_days[6] == 0:
- month_days = month_days[7:]
- if month_days[6] == 0:
- month_days = month_days[7:]
- for i, day in enumerate(month_days):
- offset = i
- if offset >= 6 * 7:
- break
- window[(offset // 7, offset % 7)].update(str(day) if day else '')
-
- def make_days_layout():
- days_layout = []
- for week in range(6):
- row = []
- for day in range(7):
- row.append(sg.T('', size=(4, 1), justification='c', font=day_font, key=(week, day), enable_events=True, pad=(0, 0)))
- days_layout.append(row)
- return days_layout
-
-
- # Create table of month names and week day abbreviations
-
- if day_abbreviations is None or len(day_abbreviations) != 7:
- fwday = calendar.SUNDAY
- try:
- if locale is not None:
- _cal = calendar.LocaleTextCalendar(fwday, locale)
- else:
- _cal = calendar.TextCalendar(fwday)
- day_names = _cal.formatweekheader(3).split()
- except Exception as e:
- print('Exception building day names from locale', locale, e)
- day_names = ('Sun', 'Mon', 'Tue', 'Wed', 'Th', 'Fri', 'Sat')
- else:
- day_names = day_abbreviations
-
- mon_names = month_names if month_names is not None and len(month_names) == 12 else [calendar.month_name[i] for i in range(1,13)]
- days_layout = make_days_layout()
-
- layout = [[sg.B('◄◄', font=arrow_font, border_width=0, key='-YEAR-DOWN-', pad=((10,2),2)),
- sg.B('◄', font=arrow_font, border_width=0, key='-MON-DOWN-', pad=(0,2)),
- sg.Text('{} {}'.format(mon_names[cur_month - 1], cur_year), size=(16, 1), justification='c', font=mon_year_font, key='-MON-YEAR-', pad=(0,2)),
- sg.B('►', font=arrow_font,border_width=0, key='-MON-UP-', pad=(0,2)),
- sg.B('►►', font=arrow_font,border_width=0, key='-YEAR-UP-', pad=(2,2))]]
- layout += [[sg.Col([[sg.T(day_names[i - (7 - begin_at_sunday_plus) % 7], size=(4,1), font=day_font, background_color=sg.theme_text_color(), text_color=sg.theme_background_color(), pad=(0,0)) for i in range(7)]], background_color=sg.theme_text_color(), pad=(0,0))]]
- layout += days_layout
- if not close_when_chosen:
- layout += [[sg.Button('Ok', border_width=0,font='TkFixedFont 8'), sg.Button('Cancel',border_width=0, font='TkFixedFont 8')]]
-
- window = sg.Window(title, layout, no_titlebar=no_titlebar, grab_anywhere=True, keep_on_top=keep_on_top, font='TkFixedFont 12', use_default_focus=False, location=location, finalize=True, icon=icon)
-
- update_days(window, cur_month, cur_year, begin_at_sunday_plus)
-
- prev_choice = chosen_mon_day_year = None
-
- if cur_day:
- chosen_mon_day_year = cur_month, cur_day, cur_year
- for week in range(6):
- for day in range(7):
- if window[(week,day)].DisplayText == str(cur_day):
- window[(week,day)].update(background_color=sg.theme_text_color(), text_color=sg.theme_background_color())
- prev_choice = (week,day)
- break
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Cancel'):
- chosen_mon_day_year = None
- break
- if event == 'Ok':
- break
- if event in ('-MON-UP-', '-MON-DOWN-', '-YEAR-UP-','-YEAR-DOWN-'):
- cur_month += (event == '-MON-UP-')
- cur_month -= (event == '-MON-DOWN-')
- cur_year += (event == '-YEAR-UP-')
- cur_year -= (event == '-YEAR-DOWN-')
- if cur_month > 12:
- cur_month = 1
- cur_year += 1
- elif cur_month < 1:
- cur_month = 12
- cur_year -= 1
- window['-MON-YEAR-'].update('{} {}'.format(mon_names[cur_month - 1], cur_year))
- update_days(window, cur_month, cur_year, begin_at_sunday_plus)
- if prev_choice:
- window[prev_choice].update(background_color=sg.theme_background_color(), text_color=sg.theme_text_color())
- elif type(event) is tuple:
- if window[event].DisplayText != "":
- chosen_mon_day_year = cur_month, int(window[event].DisplayText), cur_year
- if prev_choice:
- window[prev_choice].update(background_color=sg.theme_background_color(), text_color=sg.theme_text_color())
- window[event].update(background_color=sg.theme_text_color(), text_color=sg.theme_background_color())
- prev_choice = event
- if close_when_chosen:
- break
- window.close()
- return chosen_mon_day_year
-
-
-print(popup_get_date())
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py
index 58987f9bc..79764b3ce 100644
--- a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py
+++ b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py
@@ -16,10 +16,6 @@
3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
In this loop add this call:
imwatchingyou.refresh()
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
layout = [
@@ -44,7 +40,7 @@
while True: # Your Event Loop
event, values = window.read(timeout=100)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event == 'Enable':
window.enable_debugger()
diff --git a/DemoPrograms/Demo_Debugger_Button.py b/DemoPrograms/Demo_Debugger_Button.py
index bd8a30506..2f56ec438 100644
--- a/DemoPrograms/Demo_Debugger_Button.py
+++ b/DemoPrograms/Demo_Debugger_Button.py
@@ -17,10 +17,6 @@
3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
In this loop add this call:
imwatchingyou.refresh()
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
layout = [
@@ -41,7 +37,7 @@
while True: # Your Event Loop
event, values = window.read(timeout=100)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event == 'Enable':
window.enable_debugger()
diff --git a/DemoPrograms/Demo_Debugger_ImWatchingYou.py b/DemoPrograms/Demo_Debugger_ImWatchingYou.py
index 8e740869d..ce59c1df8 100644
--- a/DemoPrograms/Demo_Debugger_ImWatchingYou.py
+++ b/DemoPrograms/Demo_Debugger_ImWatchingYou.py
@@ -17,10 +17,6 @@
3. You must find a location in your code to "refresh" the debugger. Some loop that's executed often.
In this loop add this call:
imwatchingyou.refresh()
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
layout = [
@@ -43,7 +39,7 @@
while True: # Your Event Loop
event, values = window.read(timeout=100)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event == 'Ok':
print('You clicked Ok.... this is where print output goes')
diff --git a/DemoPrograms/Demo_Demo_Programs_Browser.py b/DemoPrograms/Demo_Demo_Programs_Browser.py
deleted file mode 100644
index 21db7e950..000000000
--- a/DemoPrograms/Demo_Demo_Programs_Browser.py
+++ /dev/null
@@ -1,613 +0,0 @@
-import os.path
-import subprocess
-import sys
-import mmap, re
-import warnings
-import PySimpleGUI as sg
-
-"""
- PySimpleGUI Demo Program Browser
-
- Originaly written for PySimpleGUI Demo Programs, but expanded to
- be a general purpose tool. Enable Advanced Mode in settings for more fun
-
- Use to filter and search your source code tree.
- Then run or edit your files
-
- Filter the list of :
- * Search using filename
- * Searching within the programs' source code (like grep)
-
- The basic file operations are
- * Edit a file in your editor
- * Run a file
- * Filter file list
- * Search in files
- * Run a regular expression search on all files
- * Display the matching line in a file
-
- Additional operations
- * Edit this file in editor
-
- Keeps a "history" of the previously chosen folders to easy switching between projects
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def running_linux():
- return sys.platform.startswith('linux')
-
-def running_windows():
- return sys.platform.startswith('win')
-
-def get_file_list_dict():
- """
- Returns dictionary of files
- Key is short filename
- Value is the full filename and path
-
- :return: Dictionary of demo files
- :rtype: Dict[str:str]
- """
-
- demo_path = get_demo_path()
- demo_files_dict = {}
- for dirname, dirnames, filenames in os.walk(demo_path):
- for filename in filenames:
- if filename.endswith('.py') or filename.endswith('.pyw'):
- fname_full = os.path.join(dirname, filename)
- if filename not in demo_files_dict.keys():
- demo_files_dict[filename] = fname_full
- else:
- # Allow up to 100 dupicated names. After that, give up
- for i in range(1, 100):
- new_filename = f'{filename}_{i}'
- if new_filename not in demo_files_dict:
- demo_files_dict[new_filename] = fname_full
- break
-
- return demo_files_dict
-
-
-def get_file_list():
- """
- Returns list of filenames of files to display
- No path is shown, only the short filename
-
- :return: List of filenames
- :rtype: List[str]
- """
- return sorted(list(get_file_list_dict().keys()))
-
-
-def get_demo_path():
- """
- Get the top-level folder path
- :return: Path to list of files using the user settings for this file. Returns folder of this file if not found
- :rtype: str
- """
- demo_path = sg.user_settings_get_entry('-demos folder-', os.path.dirname(__file__))
-
- return demo_path
-
-
-def get_global_editor():
- """
- Get the path to the editor based on user settings or on PySimpleGUI's global settings
-
- :return: Path to the editor
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- return global_editor
-
-
-def get_editor():
- """
- Get the path to the editor based on user settings or on PySimpleGUI's global settings
-
- :return: Path to the editor
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- user_editor = sg.user_settings_get_entry('-editor program-', '')
- if user_editor == '':
- user_editor = global_editor
-
- return user_editor
-
-
-def get_explorer():
- """
- Get the path to the file explorer program
-
- :return: Path to the file explorer EXE
- :rtype: str
- """
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_explorer = sg.pysimplegui_user_settings.get('-explorer program-', '')
- except:
- global_explorer = ''
- explorer = sg.user_settings_get_entry('-explorer program-', '')
- if explorer == '':
- explorer = global_explorer
- return explorer
-
-
-def advanced_mode():
- """
- Returns True is advanced GUI should be shown
-
- :return: True if user indicated wants the advanced GUI to be shown (set in the settings window)
- :rtype: bool
- """
- return sg.user_settings_get_entry('-advanced mode-', False)
-
-
-
-def get_theme():
- """
- Get the theme to use for the program
- Value is in this program's user settings. If none set, then use PySimpleGUI's global default theme
- :return: The theme
- :rtype: str
- """
- # First get the current global theme for PySimpleGUI to use if none has been set for this program
- try:
- global_theme = sg.theme_global()
- except:
- global_theme = sg.theme()
- # Get theme from user settings for this program. Use global theme if no entry found
- user_theme = sg.user_settings_get_entry('-theme-', '')
- if user_theme == '':
- user_theme = global_theme
- return user_theme
-
-# We handle our code properly. But in case the user types in a flag, the flags are now in the middle of a regex. Ignore this warning.
-
-warnings.filterwarnings("ignore", category=DeprecationWarning)
-
-# New function
-def get_line_number(file_path, string):
- lmn = 0
- with open(file_path) as f:
- for num, line in enumerate(f, 1):
- if string.strip() == line.strip():
- lmn = num
- return lmn
-
-def find_in_file(string, demo_files_dict, regex=False, verbose=False, window=None, ignore_case=True, show_first_match=True):
- """
- Search through the demo files for a string.
- The case of the string and the file contents are ignored
-
- :param string: String to search for
- :param verbose: if True print the FIRST match
- :type verbose: bool
- :param find_all_matches: if True, then return all matches in the dictionary
- :type find_all_matches: bool
- :return: List of files containing the string
- :rtype: List[str]
- """
-
-
- # So you face a prediciment here. You wish to read files, both small and large; however the bigger the file/bigger the list, the longer to read the file.
- # This probably isn't what you want, right?
- # Well, we can't use a direct command line to run grep and parse. But it is an option. The user may not have it.
- # We could check if grep exists and if not use our method; but it isn't the best way.
- # So using background knowldge, we know that grep is *very* fast.
- #
- # Why?
- # Grep reads a *ton* of files into memory then searches through the memory to find the string or regex/pattern corresponding to the file.
- # How can we load a file into memory on python as fast as grep whilst keeping it universal?
- # memory mapping (mmap).
- # We can't load a lot of files into memory as we may face issues with watchdog on other operating systems. So we load one file at a time and search though there.
- # This will allow the fastest searching and loading of a file without sacrificing read times.
- # 2.8 seconds on the highend for both small and large files in memory.
- # We also don't have to iterate over lines this way.
- file_list = []
- num_files = 0
-
- matched_dict = {}
- for file in demo_files_dict:
- try:
- full_filename = demo_files_dict[file]
- if not demo_files_dict == get_file_list_dict():
- full_filename = full_filename[0]
- matches = None
-
- with open(full_filename, 'rb', 0) as f, mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as s:
- if (regex):
- window['-FIND NUMBER-'].update(f'{num_files} files')
- window.refresh()
- matches = re.finditer(bytes("^.*(" + string + ").*$", 'utf-8'), s, re.MULTILINE)
- if matches:
- for match in matches:
- if match is not None:
- if file not in file_list:
- file_list.append(file)
- num_files += 1
- if verbose:
- sg.cprint(f"{file}:", c = 'white on green')
- sg.cprint(f"{match.group(0).decode('utf-8')}\n")
- else:
- window['-FIND NUMBER-'].update(f'{num_files} files')
- window.refresh()
- matches = None
- if (ignore_case):
- if (show_first_match):
- matches = re.search(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- matches = re.finditer(br'(?i)^' + bytes(".*("+re.escape(string.lower()) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- if (show_first_match):
- matches = re.search(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE)
- else:
- matches = re.finditer(br'^' + bytes(".*("+re.escape(string) + ").*$", 'utf-8'), s, re.MULTILINE)
- if matches:
- if show_first_match:
- file_list.append(file)
- num_files += 1
- match_array = []
- match_array.append(matches.group(0).decode('utf-8'))
- matched_dict[full_filename] = match_array
- else:
- # We need to do this because strings are "falsy" in Python, but empty matches still return True...
- append_file = False
- match_array = []
- for match_ in matches:
- match_str = match_.group(0).decode('utf-8')
- if match_str:
- match_array.append(match_str)
- if append_file == False:
- append_file = True
- if append_file:
- file_list.append(file)
- num_files += 1
- matched_dict[full_filename] = match_array
-
- # del matches
- except ValueError:
- del matches
- except Exception as e:
- exc_type, exc_obj, exc_tb = sys.exc_info()
- fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
- print(exc_type, fname, exc_tb.tb_lineno)
- print(f'{file}', e, file=sys.stderr)
-
-
- file_lines_dict = {}
- if not regex:
- for key in matched_dict:
- head, tail = os.path.split(key)
- # Tails. Don't wanna put Washington in places he doesn't want to be.
- file_array_old = [key]
- file_array_new = []
-
- if (verbose):
- sg.cprint(f"{tail}:", c = 'white on green')
- try:
- for _match in matched_dict[key]:
- line_num_match = get_line_number(key, _match)
- file_array_new.append(line_num_match)
- if (verbose):
- sg.cprint(f"Line: {line_num_match} | {_match.strip()}\n")
- file_array_old.append(file_array_new)
- file_lines_dict[tail] = file_array_old
- except:
- pass
-
- find_in_file.old_file_list = file_lines_dict
-
- file_list = list(set(file_list))
- return file_list
-
-
-
-def settings_window():
- """
- Show the settings window.
- This is where the folder paths and program paths are set.
- Returns True if settings were changed
-
- :return: True if settings were changed
- :rtype: (bool)
- """
-
- try:
- global_editor = sg.pysimplegui_user_settings.get('-editor program-')
- except:
- global_editor = ''
- try:
- global_explorer = sg.pysimplegui_user_settings.get('-explorer program-')
- except:
- global_explorer = ''
- try: # in case running with old version of PySimpleGUI that doesn't have a global PSG settings path
- global_theme = sg.theme_global()
- except:
- global_theme = ''
-
- layout = [[sg.T('Program Settings', font='DEFAULT 25')],
- [sg.T('Path to Tree', font='_ 16')],
- [sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', get_demo_path()), size=(50, 1), key='-FOLDERNAME-'),
- sg.FolderBrowse('Folder Browse', target='-FOLDERNAME-'), sg.B('Clear History')],
- [sg.T('Editor Program', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_editor)],
- [ sg.In(sg.user_settings_get_entry('-editor program-', ''),k='-EDITOR PROGRAM-'), sg.FileBrowse()],
- [sg.T('File Explorer Program', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_explorer)],
- [ sg.In(sg.user_settings_get_entry('-explorer program-'), k='-EXPLORER PROGRAM-'), sg.FileBrowse()],
- [sg.T('Theme', font='_ 16')],
- [sg.T('Leave blank to use global default'), sg.T(global_theme)],
- [sg.Combo(['']+sg.theme_list(),sg.user_settings_get_entry('-theme-', ''), readonly=True, k='-THEME-')],
- [sg.CB('Use Advanced Interface', default=advanced_mode() ,k='-ADVANCED MODE-')],
- [sg.B('Ok', bind_return_key=True), sg.B('Cancel')],
- ]
-
- window = sg.Window('Settings', layout)
-
- settings_changed = False
-
- while True:
- event, values = window.read()
- if event in ('Cancel', sg.WIN_CLOSED):
- break
- if event == 'Ok':
- sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-'])
- sg.user_settings_set_entry('-editor program-', values['-EDITOR PROGRAM-'])
- sg.user_settings_set_entry('-theme-', values['-THEME-'])
- sg.user_settings_set_entry('-folder names-', list(set(sg.user_settings_get_entry('-folder names-', []) + [values['-FOLDERNAME-'], ])))
- sg.user_settings_set_entry('-explorer program-', values['-EXPLORER PROGRAM-'])
- sg.user_settings_set_entry('-advanced mode-', values['-ADVANCED MODE-'])
- settings_changed = True
- break
- elif event == 'Clear History':
- sg.user_settings_set_entry('-folder names-', [])
- sg.user_settings_set_entry('-last filename-', '')
- window['-FOLDERNAME-'].update(values=[], value='')
-
- window.close()
- return settings_changed
-
-ML_KEY = '-ML-' # Multline's key
-
-# --------------------------------- Create the window ---------------------------------
-def make_window():
- """
- Creates the main window
- :return: The main window object
- :rtype: (Window)
- """
- theme = get_theme()
- if not theme:
- theme = sg.OFFICIAL_PYSIMPLEGUI_THEME
- sg.theme(theme)
- # First the window layout...2 columns
-
- find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside."
- filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename."
- find_re_tooltip = "Find in file using Regular Expression\nEnter a string in box to search for string inside of the files.\nSearch is performed after clicking the FindRE button."
-
-
- left_col = sg.Col([
- [sg.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50, 20), key='-DEMO LIST-')],
- [sg.Text('Filter:', tooltip=filter_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FILTER-', tooltip=filter_tooltip),
- sg.T(size=(15,1), k='-FILTER NUMBER-')],
- [sg.Button('Run'), sg.B('Edit'), sg.B('Clear'), sg.B('Open Folder')],
- [sg.Text('Find:', tooltip=find_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip),
- sg.T(size=(15,1), k='-FIND NUMBER-')],
- ], element_justification='l')
-
- lef_col_find_re = sg.pin(sg.Col([
- [sg.Text('Find:', tooltip=find_re_tooltip), sg.Input(size=(25, 1),key='-FIND RE-', tooltip=find_re_tooltip),sg.B('Find RE')]], k='-RE COL-'))
-
- right_col = [
- [sg.Multiline(size=(70, 21), write_only=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True)],
- [sg.Button('Edit Me (this program)'), sg.B('Settings'), sg.Button('Exit')],
- [sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed, font='Default 8', pad=(0,0))],
- ]
-
- options_at_bottom = sg.pin(sg.Column([[sg.CB('Verbose', enable_events=True, k='-VERBOSE-'),
- sg.CB('Show only first match in file', default=True, enable_events=True, k='-FIRST MATCH ONLY-'),
- sg.CB('Find ignore case', default=True, enable_events=True, k='-IGNORE CASE-'),
- sg.T('<---- NOTE: Only the "Verbose" setting is implemented at this time')]], pad=(0,0), k='-OPTIONS BOTTOM-'))
-
- choose_folder_at_top = sg.pin(sg.Column([[sg.T('Click settings to set top of your tree or choose a previously chosen folder'),
- sg.Combo(sorted(sg.user_settings_get_entry('-folder names-', [])), default_value=sg.user_settings_get_entry('-demos folder-', ''), size=(50, 1), key='-FOLDERNAME-', enable_events=True, readonly=True)]], pad=(0,0), k='-FOLDER CHOOSE-'))
- # ----- Full layout -----
-
- layout = [[sg.Text('PySimpleGUI Demo Program & Project Browser', font='Any 20')],
- [choose_folder_at_top],
- sg.vtop([sg.Column([[left_col],[ lef_col_find_re]], element_justification='l'), sg.Col(right_col, element_justification='c') ]),
- [options_at_bottom]
- ]
-
- # --------------------------------- Create Window ---------------------------------
- window = sg.Window('PSG Demo & Project Browser', layout, finalize=True, icon=icon)
-
- if not advanced_mode():
- window['-FOLDER CHOOSE-'].update(visible=False)
- window['-RE COL-'].update(visible=False)
- window['-OPTIONS BOTTOM-'].update(visible=False)
-
- sg.cprint_set_output_destination(window, ML_KEY)
- return window
-
-
-# --------------------------------- Main Program Layout ---------------------------------
-
-def main():
- """
- The main program that contains the event loop.
- It will call the make_window function to create the window.
- """
-
- find_in_file.old_file_list = None
-
- old_typed_value = None
-
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window = make_window()
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- counter = 0
- while True:
- event, values = window.read()
- counter += 1
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- if event == 'Edit':
- editor_program = get_editor()
- for file in values['-DEMO LIST-']:
- sg.cprint(f'Editing using {editor_program}', text_color='white', background_color='red', end='')
- sg.cprint('')
- sg.cprint(f'{file_list_dict[file]}', text_color='white', background_color='purple')
- execute_command_subprocess(f'{editor_program}', f'"{file_list_dict[file]}"')
- elif event == 'Run':
- sg.cprint('Running....', c='white on green', end='')
- sg.cprint('')
- for file in values['-DEMO LIST-']:
- file_to_run = str(file_list_dict[file])
- sg.cprint(file_to_run,text_color='white', background_color='purple')
- execute_py_file(f'{file_to_run}')
- elif event.startswith('Edit Me'):
- editor_program = get_editor()
- sg.cprint(f'opening using {editor_program}:')
- sg.cprint(f'{__file__}', text_color='white', background_color='red', end='')
- execute_command_subprocess(f'{editor_program}', f'"{__file__}"')
- elif event == '-FILTER-':
- new_list = [i for i in file_list if values['-FILTER-'].lower() in i.lower()]
- window['-DEMO LIST-'].update(new_list)
- window['-FILTER NUMBER-'].update(f'{len(new_list)} files')
- window['-FIND NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FIND RE-'].update('')
- elif event == '-FIND-' or event == '-FIRST MATCH ONLY-' or event == '-VERBOSE-' or event == '-FIND RE-':
- is_ignore_case = values['-IGNORE CASE-']
- old_ignore_case = False
- current_typed_value = str(values['-FIND-'])
- if len(values['-FIND-']) == 1:
- window[ML_KEY].update('')
- window['-VERBOSE-'].update(False)
- values['-VERBOSE-'] = False
- if values['-VERBOSE-']:
- window[ML_KEY].update('')
- if values['-FIND-']:
- if find_in_file.old_file_list is None or old_typed_value is None or old_ignore_case is not is_ignore_case:
- # New search.
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- elif current_typed_value.startswith(old_typed_value) and old_ignore_case is is_ignore_case:
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], find_in_file.old_file_list, verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- else:
- old_typed_value = current_typed_value
- file_list = find_in_file(values['-FIND-'], get_file_list_dict(), verbose=values['-VERBOSE-'], window=window, ignore_case=is_ignore_case, show_first_match=values['-FIRST MATCH ONLY-'])
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND RE-'].update('')
- window['-FILTER-'].update('')
- elif values['-FIND RE-']:
- window['-ML-'].update('')
- file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window)
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FILTER-'].update('')
- elif event == 'Find RE':
- window['-ML-'].update('')
- file_list = find_in_file(values['-FIND RE-'], get_file_list_dict(), regex=True, verbose=values['-VERBOSE-'],window=window)
- window['-DEMO LIST-'].update(sorted(file_list))
- window['-FIND NUMBER-'].update(f'{len(file_list)} files')
- window['-FILTER NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FILTER-'].update('')
- sg.cprint('Regular expression find completed')
- elif event == 'Settings':
- if settings_window() is True:
- window.close()
- window = make_window()
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- elif event == 'Clear':
- file_list = get_file_list()
- window['-FILTER-'].update('')
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-FIND-'].update('')
- window['-DEMO LIST-'].update(file_list)
- window['-FIND NUMBER-'].update('')
- window['-FIND RE-'].update('')
- window['-ML-'].update('')
- elif event == '-FOLDERNAME-':
- sg.user_settings_set_entry('-demos folder-', values['-FOLDERNAME-'])
- file_list_dict = get_file_list_dict()
- file_list = get_file_list()
- window['-DEMO LIST-'].update(values=file_list)
- window['-FILTER NUMBER-'].update(f'{len(file_list)} files')
- window['-ML-'].update('')
- window['-FIND NUMBER-'].update('')
- window['-FIND-'].update('')
- window['-FIND RE-'].update('')
- window['-FILTER-'].update('')
- elif event == 'Open Folder':
- explorer_program = get_explorer()
- if explorer_program:
- sg.cprint(f'Opening Folder using {explorer_program}...', c='white on green', end='')
- sg.cprint('')
- for file in values['-DEMO LIST-']:
- file_selected = str(file_list_dict[file])
- file_path = os.path.dirname(file_selected)
- if running_windows():
- file_path = file_path.replace('/', '\\')
- sg.cprint(file_path, text_color='white', background_color='purple')
- execute_command_subprocess(explorer_program, file_path)
-
- window.close()
-
-try:
- execute_py_file = sg.execute_py_file
-except:
- def execute_py_file(pyfile, parms=None, cwd=None):
- if parms is not None:
- execute_command_subprocess('python' if running_windows() else 'python3', pyfile, parms, wait=False, cwd=cwd)
- else:
- execute_command_subprocess('python' if running_windows() else 'python3', pyfile, wait=False, cwd=cwd)
-
-try:
- execute_command_subprocess = sg.execute_command_subprocess
-except:
- def execute_command_subprocess(command, *args, wait=False, cwd=None):
- if running_linux():
- arg_string = ''
- for arg in args:
- arg_string += ' ' + str(arg)
- sp = subprocess.Popen(str(command) + arg_string, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
- else:
- expanded_args = ' '.join(args)
- sp = subprocess.Popen([command, *args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
- if wait:
- out, err = sp.communicate()
- if out:
- print(out.decode("utf-8"))
- if err:
- print(err.decode("utf-8"))
-
-
-if __name__ == '__main__':
- # https://www.vecteezy.com/free-vector/idea-bulb is where I got the icon
-
- icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAAK/2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4NCjx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDA3IDEuMTM2ODgxLCAyMDEwLzA2LzEwLTE4OjExOjM1ICAgICAgICAiPg0KICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPg0KICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0iRUM4REZFNUEyMEM0QjcwMzFBMjNBRDA4NENCNzZCODAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIGRjOmZvcm1hdD0iaW1hZ2UvanBlZyIgeG1wOlJhdGluZz0iNSIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wNC0xOVQxMjoxMTozOSswNDozMCI+DQogICAgICA8eG1wTU06SGlzdG9yeT4NCiAgICAgICAgPHJkZjpTZXE+DQogICAgICAgICAgPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOkYwNjRBQzcwNzY2MkU5MTFBNkU1QzYwODhFRTUxMzM5IiBzdEV2dDp3aGVuPSIyMDE5LTA0LTE5VDEyOjExOjM5KzA0OjMwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ2FtZXJhIFJhdyA3LjAiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgICA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6OUVBNkIyNzA3NjYyRTkxMThDQzNFODdFN0ZEQTgwNTEiIHN0RXZ0OndoZW49IjIwMTktMDQtMTlUMTI6MTE6MzkrMDQ6MzAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDYW1lcmEgUmF3IDcuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii9tZXRhZGF0YSIgLz4NCiAgICAgICAgPC9yZGY6U2VxPg0KICAgICAgPC94bXBNTTpIaXN0b3J5Pg0KICAgICAgPGRjOnRpdGxlPg0KICAgICAgICA8cmRmOkFsdD4NCiAgICAgICAgICA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPkJ1bGIgSWNvbiBEZXNpZ248L3JkZjpsaT4NCiAgICAgICAgPC9yZGY6QWx0Pg0KICAgICAgPC9kYzp0aXRsZT4NCiAgICAgIDxkYzpjcmVhdG9yPg0KICAgICAgICA8cmRmOlNlcT4NCiAgICAgICAgICA8cmRmOmxpPklZSUtPTjwvcmRmOmxpPg0KICAgICAgICA8L3JkZjpTZXE+DQogICAgICA8L2RjOmNyZWF0b3I+DQogICAgICA8ZGM6ZGVzY3JpcHRpb24+DQogICAgICAgIDxyZGY6QWx0Pg0KICAgICAgICAgIDxyZGY6bGkgeG1sOmxhbmc9IngtZGVmYXVsdCI+QnVsYiBJY29uIERlc2lnbg0KPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkFsdD4NCiAgICAgIDwvZGM6ZGVzY3JpcHRpb24+DQogICAgICA8ZGM6c3ViamVjdD4NCiAgICAgICAgPHJkZjpCYWc+DQogICAgICAgICAgPHJkZjpsaT5idWxiPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5lbmVyZ3k8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWE8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpZ2h0PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5saWdodGJ1bGI8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmJ1bGIgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZW5lcmd5IGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlkZWEgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHQgaWNvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bGlnaHRidWxiIGljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmljb248L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmlsbHVzdHJhdGlvbjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZGVzaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zaWduPC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5zeW1ib2w8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYXBoaWM8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmxpbmVhcjwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+b3V0bGluZTwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+ZmxhdDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+Z2x5cGg8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPmdyYWRpZW50PC9yZGY6bGk+DQogICAgICAgICAgPHJkZjpsaT5jaXJjbGU8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnNoYWRvdzwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+bG93IHBvbHk8L3JkZjpsaT4NCiAgICAgICAgICA8cmRmOmxpPnBvbHlnb25hbDwvcmRmOmxpPg0KICAgICAgICAgIDxyZGY6bGk+c3F1YXJlPC9yZGY6bGk+DQogICAgICAgIDwvcmRmOkJhZz4NCiAgICAgIDwvZGM6c3ViamVjdD4NCiAgICA8L3JkZjpEZXNjcmlwdGlvbj4NCiAgPC9yZGY6UkRGPg0KPC94OnhtcG1ldGE+DQo8P3hwYWNrZXQgZW5kPSJyIj8+ncdlNwAABG5JREFUWMPtV2tMk1cYfr6vINBRKpVLpVIuGZfOjiARochYO/EyMWHDjOIYYSyQ6MaignEkEgJLyNxMRthmJBkalKmgUacsjMiCBRFWqKsBFJEwtkILLYxBuQi0/c5+sE5mJmvBxR/zJO+fc877vE/ey5NzKEIInuWi8YzXcwIrInCtuirlWnVVykowHGy9qFYqo+bn5pyj4uIarXtBope6H7+nbGp6dZWT0+yGqCjlUyUQEBTUW15SkiOOiLj9/eXLu1sVN6Q6jUYIAD5CoUYilSleT0q6dLO+fmvmwYOfP/UScN3df+cLBIPvbN92fWpijJedtk5XWQT6TM5PkR9Izrw72ZpRkRrr/yvfhz/MXe02aSsuZYsOMAxDH87MPMlfJxjcn7OnitWReg7GjrDH75ktQGkVMDz/csdnFReSWZzgnmVnwGwyOSbLpI1davWGY/n5xaFhYR2HPko/zWrb0vBPwQHAgQXkpgKhvM6wY+/HNXU1X0xOlkkbzSaT4xMZEEKeaDPT02xVy62YrKQ3rxDGQltubmq31NDEFsuUUKTthPjezNQkZ6kYS/aAC5s9U1lWti+36OMCMvxtEsZVG22tbU4qhW8u3hU5G69vX3YTMgxDD/T3B4SIxZ1EVyW3Z75D/IABPcBoq+XLJjA0MOArDAj4GQAwcSfCXpERegO6PnXEsglMTU1xXN3cjAtdaXSz7s/MAl19gHZKqNGOAF0634GZOQcz3GNaF/u7soHpyUd+dhPw8PQ06HVDPgAA57W6v2aXAgrKCBrazKyGzrVDBSfmHSn/vWXU6si2xf6GMWCN9yM/u5VwjZeXYdSg9559+JDt5LWzlvw5fi5OQFoChS+qtAK88GLv/rzs4+zASBVpkd2w+s7OASPjgEfQztoVCdH5k+WZo3q994e5WV8zivXdMI3xFsYX2H2YAC4C7ZXbGl/SvqsWhrodVr+vLgAeXryxt4vviuDkZVi2FMsz3julutWyuV31IJgKr0gHxbJYyyDfRkH+ik6AcWX04uDt9wDVfdoiP1SRvlRwmwjQNM2UVlamfZKXd7T3t4B+SvxltvWMRS8YmDkn616vBvj0NFB66ng2i5/w3b+OylIqtdi0Go0wMUbSOjQ4KGB6CossNTSpPrBgzKhCaqmhibaCJokiigw2FxbZimszAUIIutTq8D3xW36wmE0OFmVC7WICpqs0SQmnSOf5hFpCGMpWTAd7hGV9ePgdiVSmyNu7r8zPx3egU7XQwCOl51J/URJItr5xVZxYcgCgbH9q25MBQgiM4+NcmUjUrair23FJFtt81hnkrDPIZhZIf37eUXvx7H4TcrjcCZ6nx0hsfHx9nEzWsJEGImiAC8B1leP8f/Ym/JvEctwm5a/JFMyQzsc0T4EBwIuK/pGbkVVuN5i9KSOE4C2ZVMFYLPRI4ZHiHjbIfTbILhbISOGRYnuxqOV8zaL9/TR+gYF98w96Qs3DQ3wA0HO4xmalctOq4JAee7Co53/D/z2BPwAlMRlLdQS6SQAAAABJRU5ErkJggg=='
-
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py
index 50fd2724a..57da54ca0 100644
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py
+++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py
@@ -1,54 +1,53 @@
import PySimpleGUI as sg
"""
- Demo - 2 simultaneous windows using read_all_window
-
- Window 1 launches window 2
- BOTH remain active in parallel
-
- Both windows have buttons to launch popups. The popups are "modal" and thus no other windows will be active
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ Demo - Running 2 windows with both being active at the same time
+ Three important things to note about this design patter:
+ 1. The layout for window 2 is inside of the while loop, just before the call to window2=sg.Window
+ 2. The read calls have timeout values of 100 and 0. You can change the 100 to whatever interval you wish
+ but must keep the second window's timeout at 0
+ 3. There is a safeguard to stop from launching multiple copies of window2. Only 1 window2 is visible at a time
"""
-def make_win1():
- layout = [[sg.Text('This is the FIRST WINDOW'), sg.Text(' ', k='-OUTPUT-')],
- [sg.Text('Click Popup anytime to see a modal popup')],
- [sg.Button('Launch 2nd Window'), sg.Button('Popup'), sg.Button('Exit')]]
- return sg.Window('Window Title', layout, location=(800,600), finalize=True)
-
-
-def make_win2():
- layout = [[sg.Text('The second window')],
- [sg.Input(key='-IN-', enable_events=True)],
- [sg.Text(size=(25,1), k='-OUTPUT-')],
- [sg.Button('Erase'), sg.Button('Popup'), sg.Button('Exit')]]
- return sg.Window('Second Window', layout, finalize=True)
-
-
-
-def main():
- window1, window2 = make_win1(), None # start off with 1 window open
-
- while True: # Event Loop
- window, event, values = sg.read_all_windows()
- if event == sg.WIN_CLOSED or event == 'Exit':
- window.close()
- if window == window2: # if closing win 2, mark as closed
- window2 = None
- elif window == window1: # if closing win 1, exit program
- break
- elif event == 'Popup':
- sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active')
- elif event == 'Launch 2nd Window' and not window2:
- window2 = make_win2()
- elif event == '-IN-':
- window['-OUTPUT-'].update(f'You enetered {values["-IN-"]}')
- elif event == 'Erase':
- window['-OUTPUT-'].update('')
- window['-IN-'].update('')
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
+# Window 1 layout
+layout = [
+ [sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='-OUTPUT-')],
+ [sg.Text('')],
+ [sg.Button('Launch 2nd Window'), sg.Button('Popup'), sg.Button('Exit')]
+ ]
+
+window = sg.Window('Window Title', layout, location=(800,600))
+win2_active = False
+i=0
+while True: # Event Loop
+ event, values = window.read(timeout=100)
+ if event != sg.TIMEOUT_KEY:
+ print(i, event, values)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Popup':
+ sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active')
+ i+=1
+ if event == 'Launch 2nd Window' and not win2_active: # only run if not already showing a window2
+ win2_active = True
+ # window 2 layout - note - must be "new" every time a window is created
+ layout2 = [
+ [sg.Text('The second window'), sg.Text('', key='-OUTPUT-')],
+ [sg.Input('', key='-IN-')],
+ [sg.Button('Show'), sg.Button('Exit')]
+ ]
+ window2 = sg.Window('Second Window', layout2)
+ # Read window 2's events. Must use timeout of 0
+ if win2_active:
+ # print("reading 2")
+ event, values = window2.read(timeout=100)
+ # print("win2 ", event)
+ if event != sg.TIMEOUT_KEY:
+ print("win2 ", event)
+ if event == 'Exit' or event is None:
+ # print("Closing window 2", event)
+ win2_active = False
+ window2.close()
+ if event == 'Show':
+ sg.popup('You entered ', values['-IN-'])
+
+window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py
index dbca0ca41..030d2d9e1 100644
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py
+++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py
@@ -1,59 +1,39 @@
import PySimpleGUI as sg
-
"""
- Design pattern multiple windows
- Using read_all_windows()
-
- Only 1 window at a time is visible/active on the screen.
-
- Window1 opens Window2
- When Window2 closes, Window1 reappears
- Program exits when Window1 is closed
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ PySimpleGUI The Complete Course
+ Lesson 7 - Multiple Windows
+ 1-lvl nested window
"""
+# Design pattern 1 - First window does not remain active
+
+layout = [[ sg.Text('Window 1'),],
+ [sg.Input()],
+ [sg.Text('', size=(20,1), key='-OUTPUT-')],
+ [sg.Button('Launch 2')]]
+
+window1 = sg.Window('Window 1', layout)
+window2_active=False
+
+while True:
+ event1, values1 = window1.read(timeout=100)
+ if event1 is None:
+ break
+ window1['-OUTPUT-'].update(values1[0])
+
+ if event1 == 'Launch 2' and not window2_active:
+ window2_active = True
+ window1.hide()
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('Exit')]]
+
+ window2 = sg.Window('Window 2', layout2)
+ while True:
+ ev2, vals2 = window2.read()
+ if ev2 is None or ev2 == 'Exit':
+ window2.close()
+ window2_active = False
+ window1.un_hide()
+ break
+window1.close()
-def make_window1():
- layout = [[sg.Text('Window 1'), ],
- [sg.Input(key='-IN-')],
- [sg.Text(size=(20, 1), key='-OUTPUT-')],
- [sg.Button('Launch 2'), sg.Button('Output')]]
-
- return sg.Window('Window 1', layout, finalize=True)
-
-def make_window2():
- layout = [[sg.Text('Window 2')],
- [sg.Button('Exit')]]
-
- return sg.Window('Window 2', layout, finalize=True)
-
-
-def main():
- # Design pattern 1 - First window does not remain active
- window2 = None
- window1 = make_window1()
-
- while True:
- window, event, values = sg.read_all_windows()
- if event == sg.WIN_CLOSED and window == window1:
- break
-
- if window == window1:
- window1['-OUTPUT-'].update(values['-IN-'])
-
- if event == 'Launch 2' and not window2:
- window1.hide()
- window2 = make_window2()
-
- if window == window2 and (event in (sg.WIN_CLOSED, 'Exit')):
- window2.close()
- window2 = None
- window1.un_hide()
- window1.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py
index b157ebd02..1cca3dc12 100644
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py
+++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py
@@ -1,56 +1,37 @@
import PySimpleGUI as sg
"""
- Multiple Window Design Pattern
-
- Two windows - both remain active and visible
- Window 1 launches Window 2
- Window 1 remains visible and active while Window 2 is active
- Closing Window 1 exits application
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ PySimpleGUI The Complete Course
+ Lesson 7
+ Multiple Independent Windows
"""
+# Design pattern 2 - First window remains active
+layout = [[ sg.Text('Window 1'),],
+ [sg.Input('')],
+ [sg.Text('', size=(20,1), key='-OUTPUT-')],
+ [sg.Button('Launch 2'), sg.Button('Exit')]]
-def make_window1():
- layout = [[ sg.Text('Window 1'),],
- [sg.Input(enable_events=True, k='-IN-')],
- [sg.Text(size=(20,1), k='-OUTPUT-')],
- [sg.Button('Launch 2'), sg.Button('Exit')]]
+window1 = sg.Window('Window 1', layout)
- return sg.Window('Window 1', layout, finalize=True)
+window2_active = False
+while True:
+ event1, values1 = window1.read(timeout=100)
+ window1['-OUTPUT-'].update(values1[0])
+ if event1 is None or event1 == 'Exit':
+ break
+ if not window2_active and event1 == 'Launch 2':
+ window2_active = True
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('Exit')]]
-def make_window2():
- layout = [[sg.Text('Window 2')],
- [sg.Button('Exit')]]
+ window2 = sg.Window('Window 2', layout2)
- return sg.Window('Window 2', layout, finalize=True)
-
-
-def main():
- window1, window2 = make_window1(), None
- while True:
- window, event, values = sg.read_all_windows()
- if window == window1 and event in (sg.WIN_CLOSED, 'Exit'):
- break
- # Window 1 stuff
- if event == '-IN-':
- window['-OUTPUT-'].update(values['-IN-'])
- elif event == 'Launch 2' and not window2:
- window2 = make_window2()
-
- # Window 2 stuff
- if window == window2 and event in(sg.WIN_CLOSED, 'Exit'):
+ if window2_active:
+ ev2, vals2 = window2.read(timeout=100)
+ if ev2 is None or ev2 == 'Exit':
+ window2_active = False
window2.close()
- window2 = None
-
- window1.close()
- if window2 is not None:
- window2.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
+window1.close()
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py
index d9f564536..c19b2425d 100644
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py
+++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py
@@ -2,58 +2,53 @@
'''
Example of wizard-like PySimpleGUI windows
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-def make_window1():
- layout = [[sg.Text('Window 1'), ],
- [sg.Input(k='-IN-', enable_events=True)],
- [sg.Text(size=(20,1), k='-OUTPUT-')],
- [sg.Button('Next >'), sg.Button('Exit')]]
+layout = [[sg.Text('Window 1'), ],
+ [sg.Input('')],
+ [sg.Text('',size=(20,1), key='-OUTPUT-')],
+ [sg.Button('Next >'), sg.Button('Exit')]]
- return sg.Window('Window 1', layout, finalize=True)
-
-
-def make_window2():
- layout = [[sg.Text('Window 2')],
- [sg.Button('< Prev'), sg.Button('Next >')]]
-
- return sg.Window('Window 2', layout, finalize=True)
-
-
-def make_window3():
- layout = [[sg.Text('Window 3')],
- [sg.Button('< Prev'), sg.Button('Exit')]]
- return sg.Window('Window 3', layout, finalize=True)
-
-
-
-window1, window2, window3 = make_window1(), None, None
+window = sg.Window('Window 1', layout)
+window3_active = window2_active = False
while True:
- window, event, values = sg.read_all_windows()
- if window == window1 and event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- if window == window1:
- if event == 'Next >':
- window1.hide()
- window2 = make_window2()
- window1['-OUTPUT-'].update(values['-IN-'])
-
- if window == window2:
- if event == 'Next >':
- window2.hide()
- window3 = make_window3()
- elif event in (sg.WIN_CLOSED, '< Prev'):
+ if not window2_active:
+ event1, values1 = window.read()
+ if event1 is None or event1 == 'Exit':
+ break
+ window['-OUTPUT-'].update(values1[0])
+
+ if not window2_active and event1 == 'Next >':
+ window2_active = True
+ window.hide()
+ layout2 = [[sg.Text('Window 2')],
+ [sg.Button('< Prev'), sg.Button('Next >')]]
+
+ window2 = sg.Window('Window 2', layout2)
+
+ if window2_active:
+ event2 = window2.read()[0]
+ if event2 in (None, 'Exit', '< Prev'):
+ window2_active = False
window2.close()
- window1.un_hide()
-
- if window == window3:
- window3.close()
- window2.un_hide()
+ window.un_hide()
+ elif event2 == 'Next >':
+ window3_active = True
+ window2_active = False
+ window2.hide()
+ layout3 = [[sg.Text('Window 3')],
+ [sg.Button('< Prev'), sg.Button('Exit')]]
+ window3 = sg.Window('Window 3', layout3)
+
+ if window3_active:
+ ev3, vals3 = window3.read()
+ if ev3 == '< Prev':
+ window3.close()
+ window3_active = False
+ window2_active = True
+ window2.un_hide()
+ elif ev3 in (None, 'Exit'):
+ break
window.close()
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py
deleted file mode 100644
index fe16e74b9..000000000
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import PySimpleGUI as sg
-"""
- Demo - 2 simultaneous windows using read_all_window
-
- Both windows are immediately visible. Each window updates the other.
-
- There's an added capability to "re-open" window 2 should it be closed. This is done by simply calling the make_win2 function
- again when the button is pressed in window 1.
-
- The program exits when both windows have been closed
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def make_win1():
- layout = [[sg.Text('Window 1')],
- [sg.Text('Enter something to output to Window 2')],
- [sg.Input(key='-IN-', enable_events=True)],
- [sg.Text(size=(25,1), key='-OUTPUT-')],
- [sg.Button('Reopen')],
- [sg.Button('Exit')]]
- return sg.Window('Window Title', layout, finalize=True)
-
-
-def make_win2():
- layout = [[sg.Text('Window 2')],
- [sg.Text('Enter something to output to Window 1')],
- [sg.Input(key='-IN-', enable_events=True)],
- [sg.Text(size=(25,1), key='-OUTPUT-')],
- [sg.Button('Exit')]]
- return sg.Window('Window Title', layout, finalize=True)
-
-
-def main():
- window1, window2 = make_win1(), make_win2()
-
- window2.move(window1.current_location()[0], window1.current_location()[1]+220)
-
- while True: # Event Loop
- window, event, values = sg.read_all_windows()
-
- if window == sg.WIN_CLOSED: # if all windows were closed
- break
- if event == sg.WIN_CLOSED or event == 'Exit':
- window.close()
- if window == window2: # if closing win 2, mark as closed
- window2 = None
- elif window == window1: # if closing win 1, mark as closed
- window1 = None
- elif event == 'Reopen':
- if not window2:
- window2 = make_win2()
- window2.move(window1.current_location()[0], window1.current_location()[1] + 220)
- elif event == '-IN-':
- output_window = window2 if window == window1 else window1
- if output_window: # if a valid window, then output to it
- output_window['-OUTPUT-'].update(values['-IN-'])
- else:
- window['-OUTPUT-'].update('Other window is closed')
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py
deleted file mode 100644
index 97d49b3de..000000000
--- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_OLD METHOD.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import PySimpleGUI as sg
-"""
- Demo - Running 2 windows with both being active at the same time
- Three important things to note about this design patter:
- 1. The layout for window 2 is inside of the while loop, just before the call to window2=sg.Window
- 2. The read calls have timeout values of 100 and 0. You can change the 100 to whatever interval you wish
- but must keep the second window's timeout at 0
- 3. There is a safeguard to stop from launching multiple copies of window2. Only 1 window2 is visible at a time
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('Dark Blue 3')
-# Window 1 layout
-layout = [
- [sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='-OUTPUT-')],
- [sg.Text()],
- [sg.Button('Launch 2nd Window'), sg.Button('Popup'), sg.Button('Exit')]
- ]
-
-window = sg.Window('Window Title', layout, location=(800,600))
-
-win2_active = False
-i=0
-while True: # Event Loop
- event, values = window.read(timeout=100)
- if event != sg.TIMEOUT_KEY:
- print(i, event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Popup':
- sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active')
- i+=1
- if event == 'Launch 2nd Window' and not win2_active: # only run if not already showing a window2
- win2_active = True
- # window 2 layout - note - must be "new" every time a window is created
- layout2 = [
- [sg.Text('The second window')],
- [sg.Input(key='-IN-')],
- [sg.Button('Show'), sg.Button('Exit')]
- ]
- window2 = sg.Window('Second Window', layout2)
- # Read window 2's events. Must use timeout of 0
- if win2_active:
- # print("reading 2")
- event, values = window2.read(timeout=100)
- # print("win2 ", event)
- if event != sg.TIMEOUT_KEY:
- print("win2 ", event)
- if event == 'Exit' or event == sg.WIN_CLOSED:
- # print("Closing window 2", event)
- win2_active = False
- window2.close()
- if event == 'Show':
- sg.popup('You entered ', values['-IN-'])
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py
index 9f34ff964..45fa657d6 100644
--- a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py
+++ b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py
@@ -1,11 +1,5 @@
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
layout = [
[sg.Text('Your typed chars appear here:'),
sg.Text(size=(20, 1), key='-OUTPUT-')],
@@ -18,7 +12,7 @@
while True:
event, values = window.read()
print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
if event == 'Show':
# change the "output" element to be the value of "input" element
diff --git a/DemoPrograms/Demo_Design_Pattern_Save_Theme.py b/DemoPrograms/Demo_Design_Pattern_Save_Theme.py
deleted file mode 100644
index 3d9fe7f5d..000000000
--- a/DemoPrograms/Demo_Design_Pattern_Save_Theme.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Basic window design pattern
- * Creates window in a separate function for easy "restart"
- * Saves theme as a user variable
- * Puts main code into a main function so that multiprocessing works if you later convert to use
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# ------------------- Create the window -------------------
-def make_window():
- # Set theme based on previously saved
- sg.theme(sg.user_settings_get_entry('theme', None))
-
- # ----- Layout & Window Create -----
- layout = [[sg.T('This is your layout')],
- [sg.OK(), sg.Button('Theme', key='-THEME-'), sg.Button('Exit')]]
-
- return sg.Window('Pattern for theme saving', layout)
-
-
-# ------------------- Main Program and Event Loop -------------------
-
-def main():
- window = make_window()
-
- while True:
- event, values = window.read()
- if event == sg.WINDOW_CLOSED or event == 'Exit':
- break
- if event == '-THEME-': # Theme button clicked, so get new theme and restart window
- ev, vals = sg.Window('Choose Theme', [[sg.Combo(sg.theme_list(), k='-THEME LIST-'), sg.OK(), sg.Cancel()]]).read(close=True)
- if ev == 'OK':
- window.close()
- sg.user_settings_set_entry('theme', vals['-THEME LIST-'])
- window = make_window()
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_Design_Patterns.py b/DemoPrograms/Demo_Design_Patterns.py
index 534775f5a..70cb77195 100644
--- a/DemoPrograms/Demo_Design_Patterns.py
+++ b/DemoPrograms/Demo_Design_Patterns.py
@@ -1,75 +1,52 @@
+import PySimpleGUI as sg
"""
When creating a new PySimpleGUI program from scratch, start here.
These are the accepted design patterns that cover the two primary use cases
1. A "One Shot" window
-2. A "One Shot" window in 1 line of code
-3. A persistent window that stays open after button clicks (uses an event loop)
-4. A persistent window that need to perform update of an element before the window.read
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+2. A persistent window that stays open after button clicks (uses an event loop)
+3. A persistent window that need to perform update of an element before the window.read
"""
-# -----------------------------------#
-# DESIGN PATTERN 1 - One-shot Window #
-# -----------------------------------#
-import PySimpleGUI as sg
+# ---------------------------------#
+# DESIGN PATTERN 1 - Simple Window #
+# ---------------------------------#
layout = [[ sg.Text('My Oneshot') ],
- [ sg.Input(key='-IN-') ],
[ sg.Button('OK') ]]
-window = sg.Window('Design Pattern 1', layout)
+window = sg.Window('My Oneshot', layout)
event, values = window.read()
window.close()
-# ---------------------------------------------#
-# DESIGN PATTERN 2 - One-shot Window in 1 line #
-# ---------------------------------------------#
-import PySimpleGUI as sg
-
-event, values = sg.Window('Design Pattern 2', [[sg.Text('My Oneshot')],[sg.Input(key='-IN-')], [ sg.Button('OK') ]]).read(close=True)
-
-
-
# -------------------------------------#
-# DESIGN PATTERN 3 - Persistent Window #
+# DESIGN PATTERN 2 - Persistent Window #
# -------------------------------------#
-import PySimpleGUI as sg
-layout = [[sg.Text('My layout')],
- [sg.Input(key='-INPUT-')],
- [sg.Button('OK'), sg.Button('Cancel')] ]
+layout = [[ sg.Text('My layout') ],
+ [ sg.Button('OK'), sg.Button('Cancel') ]]
-window = sg.Window('Design Pattern 3 - Persistent Window', layout)
+window = sg.Window('Design Pattern 2', layout)
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Cancel':
+ if event in (None, 'Cancel'):
break
window.close()
# ------------------------------------------------------------------#
-# DESIGN PATTERN 4 - Persistent Window with "early update" required #
+# DESIGN PATTERN 3 - Persistent Window with "early update" required #
# ------------------------------------------------------------------#
-import PySimpleGUI as sg
-layout = [[ sg.Text('My layout') ],
- [sg.Input(key='-INPUT-')],
- [sg.Text('Some text will be output here', key='-TEXT-KEY-')],
+layout = [[ sg.Text('My layout', key='-TEXT-KEY-') ],
[ sg.Button('OK'), sg.Button('Cancel') ]]
-window = sg.Window('Design Pattern 4', layout, finalize=True)
+window = sg.Window('Design Pattern 3', layout, finalize=True)
-# Change the text field. Finalize allows us to do this
-window['-TEXT-KEY-'].update('Modified before event loop')
+window['-TEXT-KEY-'].update('NEW Text') # Change the text field. Finalize allows us to do this
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Cancel':
+ if event in (None, 'Cancel'):
break
- if event == 'OK':
- window['-TEXT-KEY-'].update(values['-INPUT-'])
window.close()
diff --git a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py
index b6e1a4d4a..261bcbaae 100644
--- a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py
+++ b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py
@@ -12,10 +12,6 @@
You can setup a specific program to launch when a button is clicked, or use the
Combobox to select a .py file found in the root folder, and run that file.
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
"""
ROOT_PATH = './'
@@ -23,7 +19,7 @@
def Launcher():
- sg.theme('Dark')
+ sg.change_look_and_feel('Dark')
namesonly = [f for f in os.listdir(ROOT_PATH) if f.endswith('.py')]
@@ -50,7 +46,7 @@ def Launcher():
# ---===--- Loop taking in user input and executing appropriate program --- #
while True:
event, values = window.read()
- if event == 'EXIT' or event == sg.WIN_CLOSED:
+ if event == 'EXIT' or event is None:
break # exit button clicked
if event == 'Program 1':
print('Run your program 1 here!')
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py
index bf64dfa3a..cf5874775 100644
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py
@@ -1,30 +1,19 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-import sys
import psutil
"""
Desktop floating widget - CPU Cores
Uses psutil to display:
- CPU usage of each individual core
- CPU utilization is updated every 500 ms by default
- Utiliziation is shown as a scrolling area graph
- To achieve a "rainmeter-style" of window, these featurees were used:
- An alpha-channel setting of 0.8 to give a little transparency
- No titlebar
- Grab anywhere, making window easy to move around
- Note that the keys are tuples, with a tuple as the second item
- ('-KEY-', (row, col))
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ CPU usage on each individual core
+ Information is updated once a second and is shown as an area graph that scrolls
"""
GRAPH_WIDTH = 120 # each individual graph size in pixels
GRAPH_HEIGHT = 40
TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window
NUM_COLS = 4
-POLL_FREQUENCY = 1500 # how often to update graphs in milliseconds
+POLL_FREQUENCY = 500 # how often to update graphs in milliseconds
colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
@@ -32,102 +21,89 @@
class DashGraph(object):
def __init__(self, graph_elem, text_elem, starting_count, color):
self.graph_current_item = 0
- self.graph_elem = graph_elem # type: sg.Graph
+ self.graph_elem = graph_elem
self.text_elem = text_elem
self.prev_value = starting_count
self.max_sent = 1
self.color = color
- self.line_list = [] # list of currently visible lines. Used to delete oild figures
def graph_percentage_abs(self, value):
- self.line_list.append(self.graph_elem.draw_line( # draw a line and add to list of lines
- (self.graph_current_item, 0),
- (self.graph_current_item, value),
- color=self.color))
+ self.graph_elem.draw_line(
+ (self.graph_current_item, 0),
+ (self.graph_current_item, value),
+ color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
self.graph_elem.move(-1,0)
- self.graph_elem.delete_figure(self.line_list[0]) # delete the oldest line
- self.line_list = self.line_list[1:] # remove line id from list of lines
else:
self.graph_current_item += 1
def text_display(self, text):
self.text_elem.update(text)
-def main(location):
- # A couple of "User defined elements" that combine several elements and enable bulk edits
+def main():
+ # A couple of "Uber Elements" that combine several elements and enable bulk edits
def Txt(text, **kwargs):
return(sg.Text(text, font=('Helvetica 8'), **kwargs))
def GraphColumn(name, key):
- return sg.Column([[Txt(name, size=(10,1), key=('-TXT-', key))],
- [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black', key=('-GRAPH-', key))]], pad=(2, 2))
+ col = sg.Col([[Txt(name, key=key+'_TXT_'), ],
+ [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black',
+ key=key+'_GRAPH_')]], pad=(2, 2))
+ return col
+
num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
+ sg.set_options(element_padding=(0,0), margins=(1,1), border_width=0)
- layout = [[sg.Text('CPU Core Usage', justification='c', expand_x=True)] ]
+ # 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'),
+ sg.Text(' CPU Core Usage')] ]
# add on the graphs
for rows in range(num_cores//NUM_COLS+1):
- # for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)):
- layout += [[GraphColumn('CPU '+str(rows*NUM_COLS+cols), (rows, cols)) for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS))]]
+ row = []
+ for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)):
+ row.append(GraphColumn('CPU '+str(rows*NUM_COLS+cols), '_CPU_'+str(rows*NUM_COLS+cols)))
+ layout.append(row)
# ---------------- Create Window ----------------
- window = sg.Window('CPU Cores Usage Widget', layout,
+ window = sg.Window('PSG System Dashboard', layout,
keep_on_top=True,
+ auto_size_buttons=False,
grab_anywhere=True,
no_titlebar=True,
+ default_button_element_size=(12, 1),
return_keyboard_events=True,
alpha_channel=TRANSPARENCY,
use_default_focus=False,
- finalize=True,
- margins=(1,1),
- element_padding=(0,0),
- border_depth=0,
- location=location,
- enable_close_attempted_event=True,
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
+ finalize=True)
+ # setup graphs & initial values
graphs = []
- for rows in range(num_cores//NUM_COLS+1):
- for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)):
- graphs += [DashGraph(window[('-GRAPH-', (rows, cols))],
- window[('-TXT-', (rows, cols))],
- 0, colors[(rows*NUM_COLS+cols)%len(colors)])]
-
+ for i in range(num_cores):
+ graphs.append(DashGraph(window['_CPU_'+str(i)+'_GRAPH_'],
+ window['_CPU_'+str(i) + '_TXT_'],
+ 0, colors[i%6]))
# ---------------- main loop ----------------
while True :
# --------- Read and update window once every Polling Frequency --------
event, values = window.read(timeout=POLL_FREQUENCY)
- if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'): # Be nice and give an exit
- sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting
+ if event in (None, 'Exit'): # Be nice and give an exit
break
- elif event == sg.WIN_CLOSED:
- break
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location())
# read CPU for each core
stats = psutil.cpu_percent(percpu=True)
# update each graph
- for i, util in enumerate(stats):
- graphs[i].graph_percentage_abs(util)
- graphs[i].text_display('{} CPU {:2.0f}'.format(i, util))
+ for i in range(num_cores):
+ graphs[i].graph_percentage_abs(stats[i])
+ graphs[i].text_display('{} CPU {:2.0f}'.format(i, stats[i]))
window.close()
if __name__ == "__main__":
- # when invoking this program, if a location is set on the command line, then the window will be created there. Use x,y with no ( )
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
-
- main(location)
\ No newline at end of file
+
+ main()
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py
deleted file mode 100644
index 07ff2db41..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py
+++ /dev/null
@@ -1,315 +0,0 @@
-import PySimpleGUI as sg
-import psutil
-import sys
-import math
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- This time a CPU Usage indicator using a custom Gauge element
-
- The Gauge class was developed by the brilliant PySimpleGUI user and support-helper @jason990420
- It has been hacked on a bit, had classes and functions moved around. It could be cleaned up some
- but it's "good enough" at this point to release as a demo.
-
- This is a good example of how you can use Graph Elements to create your own custom elements.
- This Gauge element is created from a Graph element.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-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 + number2
-
- 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)
-
- def new(self, degree=0):
- """
- 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
- 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, 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.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):
- """
- 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)
- return False
- else:
- self.pointer.new(degree=self.pointer.stop_degree)
- return True
-
-ALPHA = 0.5
-THEME = 'Dark purple 6 '
-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):
- sg.theme(THEME)
- gsize = (100, 55)
- layout = [
- [sg.T('CPU', font='Any 20', background_color='black')],
- [sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key='-Graph-')],
- [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_VER_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,
- 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=window['-Graph-'])
-
- gauge.change(degree=0)
-
- while True: # Event Loop
- cpu_percent = psutil.cpu_percent(interval=1)
-
- if gauge.change():
- new_angle = cpu_percent*180/100
- window['-gauge VALUE-'].update(f'{int(cpu_percent)}%')
- gauge.change(degree=new_angle, step=180)
- gauge.change()
- # ----------- 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 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__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- window.close()
-
-
-if __name__ == '__main__':
-
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
- main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py
index e2b368bf6..ee7bb3777 100644
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py
@@ -1,15 +1,10 @@
#!/usr/bin/env python
import PySimpleGUI as sg
+import time
import random
import psutil
from threading import Thread
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
STEP_SIZE = 3
SAMPLES = 300
@@ -38,7 +33,7 @@ def main():
global g_exit, g_response_time
# start ping measurement thread
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [
@@ -62,7 +57,8 @@ def main():
last_cpu = i = 0
prev_x, prev_y = 0, 0
while True: # the Event Loop
- event, values = window.read(timeout=500)
+ time.sleep(.5)
+ event, values = window.read(timeout=0)
if event in ('Quit', None): # always give ths user a way out
break
# do CPU measurement and graph it
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py
deleted file mode 100644
index 0c2bcac92..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py
+++ /dev/null
@@ -1,384 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import sys
-import psutil
-import math
-
-"""
- Desktop floating widget - CPU Cores as Gauges
- Uses psutil to display:
- CPU usage of each individual core
- CPU utilization is updated every 2000 ms by default
- Utiliziation is shown as a gauge
- Pointer turns red when usage > 50%
- To achieve a "rainmeter-style" of window, these featurees were used:
- An alpha-channel setting of 0.8 to give a little transparency
- No titlebar
- Grab anywhere, making window easy to move around
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# 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 = 1500 # how often to update graphs in milliseconds
-
-colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
-
-
-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 + number2
-
- 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
-
-# ------------------------------ BEGINNING OF CPU WIDGET GUI CODE ------------------------------
-
-# DashGraph does the drawing of each graph
-class DashGraph(object):
- 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
- self.prev_value = starting_count
- self.max_sent = 1
- 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=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(pointer_color='red' if value > 50 else None):
- new_angle = value*180/100
- 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):
- # 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))
-
- 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 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
-
- sg.theme('black')
- sg.set_options(element_padding=(0,0), margins=(1,1), border_width=0)
-
- 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
- for rows in range(num_cores//NUM_COLS+1):
- # for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)):
- layout += [[GraphColumn('CPU '+str(rows*NUM_COLS+cols), '-CPU-'+str(rows*NUM_COLS+cols)) for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS))]]
-
- # ---------------- Create Window ----------------
- window = sg.Window('CPU Cores Usage Widget', layout,
- keep_on_top=True,
- auto_size_buttons=False,
- grab_anywhere=True,
- no_titlebar=True,
- default_button_element_size=(12, 1),
- return_keyboard_events=True,
- alpha_channel=TRANSPARENCY,
- use_default_focus=False,
- finalize=True,
- location=location,
- right_click_menu=[[''], 'Exit'],
- # transparent_color='black',
- )
-
- # setup graphs & initial values
- graphs = [DashGraph(gsize, window['-CPU-'+str(i)+'-GRAPH-'],
- window['-CPU-'+str(i) + '-GAUGE VALUE-'],
- 0, colors[i%6]) for i in range(num_cores) ]
-
- # ---------------- main loop ----------------
- while True :
- # --------- Read and update window once every Polling Frequency --------
- event, values = window.read(timeout=POLL_FREQUENCY/2)
- if event in (sg.WIN_CLOSED, 'Exit'): # Be nice and give an exit
- break
- # read CPU for each core
- stats = psutil.cpu_percent(interval=POLL_FREQUENCY/2/1000, percpu=True)
-
- # update each graph
- for i, util in enumerate(stats):
- graphs[i].graph_percentage_abs(util)
- graphs[i].text_display('{:2.0f}'.format(util))
-
- window.close()
-
-if __name__ == "__main__":
- # when invoking this program, if a location is set on the command line, then the window will be created there. Use x,y with no ( )
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = (None, None)
- main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py
deleted file mode 100644
index 13a0ae74f..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import PySimpleGUI as sg
-import psutil
-import sys
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- 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.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.5
-THEME = 'Dark purple 6'
-GSIZE = (160, 160)
-UPDATE_FREQUENCY_MILLISECONDS = 2 * 1000
-
-
-def main(location):
- 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_VER_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])
-
-
- while True: # Event Loop
- # ----------- update the graphics and text in the window ------------
- cpu_percent = psutil.cpu_percent(interval=1)
- # Draw the filled rectangle
- rect_height = int(GSIZE[1] * float(cpu_percent) / 100)
- rect_id = graph.draw_rectangle((0, rect_height), (GSIZE[0], 0), fill_color=sg.theme_button_color()[1], line_width=0)
- # Draw the % used text and the close "X" on bottom
- text_id1 = graph.draw_text(f'{int(cpu_percent)}%', (GSIZE[0] // 2, GSIZE[1] // 2), font='Any 40', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0])
- # put the bar behind everything else
- graph.send_figure_to_back(rect_id)
-
- # update the window, wait for a while, then check for exit
- event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
- 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__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- # erase figures so they can be redrawn
- graph.delete_figure(rect_id)
- graph.delete_figure(text_id1)
- window.close()
-
-
-if __name__ == '__main__':
- sg.theme(THEME)
-
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
- main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py
deleted file mode 100644
index 1ea9a2e96..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import psutil
-import operator
-
-"""
- PSUTIL "Top" CPU Processes - Desktop Widget
-
- Creates a floating CPU utilization window running something similar to a "top" command.
-
- Use the spinner to adjust the number of seconds between readings of the CPU utilizaiton
- Rather than calling the threading module this program uses the PySimpleGUI perform_long_operation method.
- The result is similar. The function is run as a thread... the call is simply wrapped.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# global used to communicate with thread.
-g_interval = 1 # how often to poll for CPU usage
-
-def CPU_thread(window:sg.Window):
-
- while True:
- cpu_percent = psutil.cpu_percent(interval=g_interval)
- procs = psutil.process_iter()
- window.write_event_value('-CPU UPDATE FROM THREAD-', (cpu_percent, procs))
-
-
-def main():
- global g_interval
-
- location = sg.user_settings_get_entry('-location-', (None, None))
-
- # ---------------- Create Form ----------------
- sg.theme('Black')
-
- layout = [[sg.Text(font=('Helvetica', 20), text_color=sg.YELLOWS[0], key='-CPU PERCENT-')],
- [sg.Text(size=(35, 12), font=('Courier New', 12), key='-PROCESSES-')], # size will determine how many processes shown
- [sg.Text('Update every '), sg.Spin([x+1 for x in range(10)], 3, key='-SPIN-'), sg.T('seconds')]]
-
- 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_VER_EXIT, enable_close_attempted_event=True)
-
- # start cpu measurement thread
- # using the PySimpleGUI call to start and manage the thread
- window.start_thread(lambda: CPU_thread(window), '-THREAD FINISHED-')
- g_interval = 1
- # Unusual construct of a Try around entire event loop... something is crashing, we need to find out what...
- try:
- # ---------------- main loop ----------------
- while True:
- # --------- Read and update window --------
- event, values = window.read()
- # print(event, values)
- # --------- Do Button Operations --------
- if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
- sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting
- break
- if event == 'Edit Me':
- sp = sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location())
- elif event == '-CPU UPDATE FROM THREAD-': # 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 = {}
- for proc in procs:
- try:
- top[proc.name()] = proc.cpu_percent()
- except Exception as e:
- pass # it's OK to get an exception here because processes come and go... one may have gone...
- # sg.Print('*** GOT Exception looping through procs ***', c='white on red', font='_ 18')
- # sg.Print('Exception = ', e, 'procs=', procs, 'proc', proc)
-
- 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:23}' for proc, cpu in top_sorted])
- # --------- Display timer and proceses in window --------
- window['-CPU PERCENT-'].update(f'CPU {cpu_percent}')
- window['-PROCESSES-'].update(display_string)
- # get the timeout from the spinner
- g_interval = int(values['-SPIN-'])
- except Exception as e:
- sg.Print('*** GOT Exception in event loop ***', c='white on red', font='_ 18')
- sg.Print('Exception = ', e, wait=True) # IMPORTANT to add a wait/blocking so that the print pauses execution. Otherwise program continue and exits
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py
new file mode 100644
index 000000000..8ea6d4c2b
--- /dev/null
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import psutil
+import time
+from threading import Thread
+import operator
+
+
+"""
+ PSUTIL 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
+ 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.
+ It will look something like:
+ invalid command name "1616802625480StopMove"
+"""
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_interval = 1
+g_cpu_percent = 0
+g_procs = None
+g_exit = False
+
+
+def CPU_thread(args):
+ global g_interval, g_cpu_percent, g_procs, g_exit
+
+ while not g_exit:
+ try:
+ g_cpu_percent = psutil.cpu_percent(interval=g_interval)
+ g_procs = psutil.process_iter()
+ except:
+ pass
+
+
+def main():
+ global g_interval, g_procs, g_exit
+
+ # ---------------- Create Form ----------------
+ sg.change_look_and_feel('Black')
+ layout = [
+ [sg.Text('', size=(8, 1), font=('Helvetica', 20),
+ text_color=sg.YELLOWS[0], justification='center', key='text')],
+ [sg.Text('', size=(30, 8), font=('Courier New', 12),
+ text_color='white', justification='left', key='processes')],
+ [sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9, 1)),
+ sg.Spin([x+1 for x in range(10)], 3, key='spin')]
+ ]
+
+ window = sg.Window('CPU Utilization', layout
+ no_titlebar=True, keep_on_top=True, alpha_channel=.8, grab_anywhere=True)
+
+ # start cpu measurement thread
+ thread = Thread(target=CPU_thread, args=(None,))
+ thread.start()
+ timeout_value = 1 # make first read really quick
+ g_interval = 1
+ # ---------------- main loop ----------------
+ while True:
+ # --------- Read and update window --------
+ event, values = window.read(timeout=timeout_value, timeout_key='Timeout')
+ # --------- Do Button Operations --------
+ if event in (None, 'Exit'):
+ break
+
+ timeout_value = int(values['spin']) * 1000
+
+ 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()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py
index ce2edb7bd..b143ce41c 100644
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py
@@ -2,16 +2,10 @@
import PySimpleGUI as sg
import psutil
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Yet another usage of CPU data
# ---------------- Create Form ----------------
-sg.theme('Black')
+sg.change_look_and_feel('Black')
layout = [[sg.Text('CPU Utilization')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20),
@@ -32,7 +26,7 @@
# --------- Read and update window --------
event, values = window.read(timeout=interval)
# --------- Do Button Operations --------
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
interval = int(values['-spin-'])*1000
@@ -44,4 +38,4 @@
window['-text-'].update(f'CPU {cpu_percent:02.0f}%')
# Broke out of main loop. Close the window.
-window.close()
+window.CloseNonBlocking()
diff --git a/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py b/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py
deleted file mode 100644
index 09976b6d6..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py
+++ /dev/null
@@ -1,432 +0,0 @@
-import PySimpleGUI as sg
-import math
-"""
- Another simple Desktop Widget using PySimpleGUI
-
- A Counter Widget... X out of Y
-
- Maybe you're counting the number of classes left in a course you're
- working your way through, or the number of pokemons left to capture.
-
- Whatever it is, sometimes knowing your progress helps. This widget shows
- you the current count and the total along with your % complete via a gauge.
- (Again, thank you to Jason for the gauge!)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.9 # Initial alpha until user changes
-THEME = 'Dark green 3' # Initial theme until user changes
-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')
-main_info_size = (3,1)
-
-
-
-
-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 + number2
-
- 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)
-
- def new(self, degree=0):
- """
- 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
- 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, 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.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):
- """
- 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)
- return False
- else:
- self.pointer.new(degree=self.pointer.stop_degree)
- return True
-
-GSIZE = (160, 160)
-
-def choose_theme(location):
- layout = [[sg.Text(f'Current theme {sg.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, keep_on_top=True)
- 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])
- test_window=make_window(location=(location[0]-200, location[1]), test_window=True)
- test_window.read(close=True)
- window.close()
-
- 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):
- title_font = sg.user_settings_get_entry('-title font-', 'Courier 8')
- title = sg.user_settings_get_entry('-title-', '')
- main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70')
-
- if not test_window:
- theme = sg.user_settings_get_entry('-theme-', THEME)
- sg.theme(theme)
-
- alpha = sg.user_settings_get_entry('-alpha-', ALPHA)
-
- # ------------------- Window Layout -------------------
- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info
- # and also enables events for the elements to make the window easy to close
- if test_window:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-', enable_events=True)],
- [sg.Text('Click to close', font=title_font, enable_events=True)],
- [sg.Text('This is theme', font=title_font, enable_events=True)],
- [sg.Text(sg.theme(), font=title_font, enable_events=True)]]
- right_click_menu = [[''], ['Exit',]]
- else:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-')]]
- right_click_menu = [[''], ['Set Count','Set Goal','Choose Title', 'Edit Me', 'Change Theme', 'Save Location', 'Refresh', 'Set Title Font', 'Set Main Font','Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
-
- gsize = (100, 55)
-
-
- layout = top_elements + \
- [[sg.Text('0', size=main_info_size, font=main_number_font, k='-MAIN INFO-', justification='c', enable_events=test_window)],
- sg.vbottom([sg.Text(0, size=(3, 1), justification='r', font='courier 20'),
- sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key='-Graph-'),
- sg.Text(0, size=(3, 1), font='courier 20', k='-GOAL-')]),
- ]
-
-
-
- try:
- window = sg.Window('Counter Widget', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_justification='c', element_padding=(0, 0), alpha_channel=alpha, finalize=True, right_click_menu=right_click_menu, right_click_menu_tearoff=False, keep_on_top=True)
- except Exception as e:
- if sg.popup_yes_no('Error creating your window', e, 'These are your current settings:', sg.user_settings(), 'Do you want to delete your settings file?') == 'Yes':
- sg.user_settings_delete_filename()
- sg.popup('Settings deleted.','Please restart your program')
- exit()
- window = None
-
- window.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,
- 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=window['-Graph-'])
-
- window.gauge.change(degree=0)
-
- return window
-
-def main():
- loc = sg.user_settings_get_entry('-location-', (None, None))
- window = make_window(loc)
- try:
- current_count = int(sg.user_settings_get_entry('-current count-', 0))
- current_goal = int(sg.user_settings_get_entry('-goal-', 100))
- current_goal = current_goal if current_goal != 0 else 100
- except:
- if sg.popup_yes_no('Your count or goal number is not good. Do you want to delete your settings file?', location=window.current_location()) == 'Yes':
- sg.user_settings_delete_filename()
- sg.popup('Settings deleted.','Please restart your program', location=window.current_location())
- exit()
-
- window['-MAIN INFO-'].update(current_count)
- window['-GOAL-'].update(current_goal)
-
- while True: # Event Loop
- window.gauge.change()
- new_angle = current_count / current_goal * 180
- window.gauge.change(degree=new_angle, step=180)
- window.gauge.change()
- window['-GOAL-'].update(current_goal)
- window['-MAIN INFO-'].update(current_count)
-
- # -------------- Start of normal event loop --------------
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Set Count':
- new_count = sg.popup_get_text('Enter current count', default_text=current_count, location=window.current_location(), keep_on_top=True)
- if new_count is not None:
- try:
- current_count = int(new_count)
- except:
- sg.popup_error('Your count is not good. Ignoring input.', location=window.current_location())
- continue
- sg.user_settings_set_entry('-current count-', current_count)
- elif event == 'Set Goal':
- new_goal = sg.popup_get_text('Enter Goal', default_text=current_goal, location=window.current_location(), keep_on_top=True)
- if new_goal is not None:
- try:
- current_goal = int(new_goal)
- except:
- sg.popup_error('Your goal number is not good. Ignoring input.', location=window.current_location())
- continue
- current_goal = current_goal if current_goal != 0 else 100
- sg.user_settings_set_entry('-goal-', current_goal)
- elif event == 'Choose Title':
- new_title = sg.popup_get_text('Choose a title for your date', default_text=sg.user_settings_get_entry('-title-', '') , location=window.current_location(), keep_on_top=True)
- if new_title is not None:
- window['-TITLE-'].update(new_title)
- sg.user_settings_set_entry('-title-', new_title)
- elif event == 'Save Location':
- sg.user_settings_set_entry('-location-', window.current_location())
- elif event in [str(x) for x in range(1,11)]:
- window.set_alpha(int(event)/10)
- sg.user_settings_set_entry('-alpha-', int(event)/10)
- elif event == 'Change Theme':
- loc = window.current_location()
- if choose_theme(loc) is not None:
- # 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-', main_number_font),location=window.current_location(), keep_on_top=True)
- if font:
- loc = window.current_location()
- sg.user_settings_set_entry('-main number font-', font)
- _, window = window.close(), make_window(loc)
- elif event == 'Set Title Font':
- font = sg.popup_get_text('Title Font and Size (e.g. courier 8)', default_text=sg.user_settings_get_entry('-title font-', title_font), location=window.current_location(), keep_on_top=True)
- if font:
- loc = window.current_location()
- sg.user_settings_set_entry('-title font-', font)
- _, window = window.close(), make_window(loc)
-
-
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Date.py b/DemoPrograms/Demo_Desktop_Widget_Date.py
deleted file mode 100644
index 7c2cbcb24..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Date.py
+++ /dev/null
@@ -1,200 +0,0 @@
-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 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-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)
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py b/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py
deleted file mode 100644
index a82305106..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py
+++ /dev/null
@@ -1,167 +0,0 @@
-import PySimpleGUI as sg
-import sys
-import datetime
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- The "Days Since _______" Widget
-
- This widget counts the number of days since some date of your choosing.
- Maybe you want to track the number of days since the start of the year.
- Or perhaps when you got married.... or divorced.... or stopped some activity
- Or started some activity.... you get the idea. It tracks a time delta in days
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.9 # Initial alpha until user changes
-THEME = 'Dark green 3' # Initial theme until user changes
-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')
-main_info_size = (3,1)
-
-# May add ability to change theme from the user interface. For now forcing to constant
-
-GSIZE = (160, 160)
-UPDATE_FREQUENCY_MILLISECONDS = 1000*60*60 # update every hour
-
-def choose_theme(location):
- layout = [[sg.Text(f'Current theme {sg.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, keep_on_top=True)
- 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])
- test_window=make_window(location=(location[0]-200, location[1]), test_window=True)
- test_window.read(close=True)
- window.close()
-
- 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):
- title_font = sg.user_settings_get_entry('-title font-', 'Courier 8')
- title = sg.user_settings_get_entry('-title-', '')
- main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70')
-
- if not test_window:
- theme = sg.user_settings_get_entry('-theme-', THEME)
- sg.theme(theme)
-
- alpha = sg.user_settings_get_entry('-alpha-', ALPHA)
-
- # ------------------- Window Layout -------------------
- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info
- # and also enables events for the elements to make the window easy to close
- if test_window:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-', enable_events=True)],
- [sg.Text('Click to close', font=title_font, enable_events=True)],
- [sg.Text('This is theme', font=title_font, enable_events=True)],
- [sg.Text(sg.theme(), font=title_font, enable_events=True)]]
- right_click_menu = [[''], ['Exit',]]
- else:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-')]]
- right_click_menu = [[''], ['Choose Date','Choose Title', 'Edit Me', 'Change Theme', 'Save Location', 'Refresh', 'Show Refresh Info', 'Hide Refresh Info', 'Set Title Font', 'Set Main Font','Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
-
-
- layout = top_elements + \
- [[sg.Text('0', size=main_info_size, font=main_number_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)))]]
-
- try:
- window = sg.Window('Day Number', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_justification='c', element_padding=(0, 0), alpha_channel=alpha, finalize=True, right_click_menu=right_click_menu, right_click_menu_tearoff=False, keep_on_top=True)
- except Exception as e:
- if sg.popup_yes_no('Error creating your window', e, 'These are your current settings:', sg.user_settings(), 'Do you want to delete your settings file?') == 'Yes':
- sg.user_settings_delete_filename()
- sg.popup('Settings deleted.','Please restart your program')
- exit()
- window = None
-
- return window
-
-def main(location):
- loc = sg.user_settings_get_entry('-location-', location)
- window = make_window(loc)
-
- saved_date = sg.user_settings_get_entry('-start date-', (1,1,2021))
- start_date = datetime.datetime(saved_date[2], saved_date[0], saved_date[1])
-
- while True: # Event Loop
- # First update the status information
- delta = datetime.datetime.now() - start_date
- window['-MAIN INFO-'].update(f'{delta.days}')
-
- # for debugging show the last update date time
- window['-REFRESHED-'].update(datetime.datetime.now().strftime("%m/%d/%Y\n%I:%M:%S %p"))
-
- # -------------- Start of normal event loop --------------
- event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Choose Date':
- new_start = sg.popup_get_date(location=window.current_location(), keep_on_top=True)
- if new_start is not None:
- start_date = datetime.datetime(new_start[2], new_start[0], new_start[1])
- sg.user_settings_set_entry('-start date-', new_start)
- elif event == 'Choose Title':
- new_title = sg.popup_get_text('Choose a title for your date', location=window.current_location(), keep_on_top=True)
- if new_title is not None:
- window['-TITLE-'].update(new_title)
- 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())
- 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)]:
- window.set_alpha(int(event)/10)
- sg.user_settings_set_entry('-alpha-', int(event)/10)
- elif event == 'Change Theme':
- loc = window.current_location()
- if choose_theme(loc) is not None:
- # 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)
- if font:
- sg.user_settings_set_entry('-main number font-', font)
- _, window = window.close(), make_window(loc)
- elif event == 'Set Title Font':
- font = sg.popup_get_text('Title Font and Size (e.g. courier 8)', default_text=sg.user_settings_get_entry('-title font-'), keep_on_top=True)
- if font:
- sg.user_settings_set_entry('-title font-', font)
- _, 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
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = (None, None)
- main(location)
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py b/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py
deleted file mode 100644
index fa76120f1..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py
+++ /dev/null
@@ -1,292 +0,0 @@
-import PySimpleGUI as sg
-import datetime
-import PIL
-from PIL import Image
-import random
-import os
-import io
-import base64
-
-"""
- Another simple Desktop Widget using PySimpleGUI
-
- This one shows images from a folder of your choosing.
- You can change the new "Standard Desktop Widget Settings"
- * Theme, location, alpha channel, refresh info,
-
- Specific to this Widget are
- * Image size
- * How long to show the image and if you wnt this time to vary semi-randomly
- * Folder containing your images
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.9 # Initial alpha until user changes
-refresh_font = sg.user_settings_get_entry('-refresh font-', 'Courier 8')
-
-
-def make_square(im, fill_color=(0, 0, 0, 0)):
- x, y = im.size
- size = max(x, y)
- new_im = Image.new('RGBA', (size, size), fill_color)
- new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
- return new_im
-
-
-def get_image_size(source):
- if isinstance(source, str):
- image = PIL.Image.open(source)
- elif isinstance(source, bytes):
- image = PIL.Image.open(io.BytesIO(base64.b64decode(source)))
- else:
- image = PIL.Image.open(io.BytesIO(source))
-
- width, height = image.size
- return (width, height)
-
-
-def convert_to_bytes(source, size=(None, None), subsample=None, zoom=None, fill=False):
- """
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param source: either a string filename or a bytes base64 image object
- :type source: (Union[str, bytes])
- :param size: optional new size (width, height)
- :type size: (Tuple[int, int] or None)
- :param subsample: change the size by multiplying width and height by 1/subsample
- :type subsample: (int)
- :param zoom: change the size by multiplying width and height by zoom
- :type zoom: (int)
- :param fill: If True then the image is filled/padded so that the image is square
- :type fill: (bool)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- """
- # print(f'converting {source} {size}')
- if isinstance(source, str):
- image = PIL.Image.open(source)
- elif isinstance(source, bytes):
- image = PIL.Image.open(io.BytesIO(base64.b64decode(source)))
- else:
- image = PIL.Image.open(io.BytesIO(source))
-
- width, height = image.size
-
- scale = None
- if size != (None, None):
- new_width, new_height = size
- scale = min(new_height / height, new_width / width)
- elif subsample is not None:
- scale = 1 / subsample
- elif zoom is not None:
- scale = zoom
-
- resized_image = image.resize((int(width * scale), int(height * scale)),
- Image.LANCZOS) if scale is not None else image
- if fill and scale is not None:
- resized_image = make_square(resized_image)
- # encode a PNG formatted version of image into BASE64
- with io.BytesIO() as bio:
- resized_image.save(bio, format="PNG")
- contents = bio.getvalue()
- encoded = base64.b64encode(contents)
- return encoded
-
-
-def choose_theme(location):
- layout = [[sg.Text(f'Current theme {sg.theme()}')],
- [sg.Listbox(values=sg.theme_list(), size=(20, 20), key='-LIST-')],
- [sg.OK(), sg.Cancel()]]
-
- event, values = sg.Window('Look and Feel Browser', layout, location=location, keep_on_top=True).read(close=True)
-
- 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:
- return None
-
-
-def reset_settings():
- sg.user_settings_set_entry('-time per image-', 60)
- sg.user_settings_set_entry('-random time-', False)
- sg.user_settings_set_entry('-image size-', (None, None))
- sg.user_settings_set_entry('-image_folder-', None)
- sg.user_settings_set_entry('-location-', (None, None))
- sg.user_settings_set_entry('-single image-', None)
- sg.user_settings_set_entry('-alpha-', ALPHA)
-
-
-def make_window(location):
- alpha = sg.user_settings_get_entry('-alpha-', ALPHA)
-
- # ------------------- Window Layout -------------------
- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info
- # and also enables events for the elements to make the window easy to close
- right_click_menu = [[''],
- ['Choose Image Folder', 'Choose Single Image', 'Edit Me', 'Change Theme', 'Set Image Size',
- 'Set Time Per Image', 'Save Location', 'Refresh', 'Show Refresh Info', 'Hide Refresh Info',
- 'Alpha',
- [str(x) for x in range(1, 11)], 'Exit', ]]
-
- refresh_info = [[sg.T(size=(25, 1), font=refresh_font, k='-REFRESHED-', justification='c')],
- [sg.T(size=(40, 1), justification='c', font=refresh_font, k='-FOLDER-')],
- [sg.T(size=(40, 1), justification='c', font=refresh_font, k='-FILENAME-')]]
-
- layout = [[sg.Image(k='-IMAGE-', enable_events=True)],
- [sg.pin(sg.Column(refresh_info, key='-REFRESH INFO-', element_justification='c',
- visible=sg.user_settings_get_entry('-show refresh-', True)))]]
-
- window = sg.Window('Photo Frame', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0),
- element_justification='c', element_padding=(0, 0), alpha_channel=alpha, finalize=True,
- right_click_menu=right_click_menu, keep_on_top=True, enable_close_attempted_event=True,
- enable_window_config_events=True)
-
- return window
-
-
-def main():
- loc = sg.user_settings_get_entry('-location-', (None, None))
- sg.theme(sg.user_settings_get_entry('-theme-', None))
-
- time_per_image = sg.user_settings_get_entry('-time per image-', 60)
- vary_randomly = sg.user_settings_get_entry('-random time-', False)
- width, height = sg.user_settings_get_entry('-image size-', (None, None))
- image_folder = sg.user_settings_get_entry('-image_folder-', None)
-
- try:
- os.listdir(image_folder) # Try reading the folder to check to see if it is read
- except:
- image_folder = None
- sg.user_settings_set_entry('-image_folder-', None)
-
- image_name = single_image = sg.user_settings_get_entry('-single image-', None)
-
- if image_folder is None and single_image is None:
- image_name = single_image = sg.popup_get_file('Choose a starting image', keep_on_top=True)
- if not single_image:
- if sg.popup_yes_no('No folder entered', 'Go you want to exit the program entirely?',
- keep_on_top=True) == 'Yes':
- exit()
- if image_folder is not None and single_image is None:
- images = os.listdir(image_folder)
- images = [i for i in images if i.lower().endswith(('.png', '.jpg', '.gif'))]
- image_name = os.path.join(image_folder, random.choice(images))
- else: # means single image is not none
- images = None
- image_name = single_image
- window = make_window(loc)
-
- window_size = window.size
- image_data = convert_to_bytes(image_name, (width, height))
-
- while True: # Event Loop
- # -------------- Start of normal event loop --------------
- timeout = time_per_image * 1000 + (random.randint(int(-time_per_image * 500),
- int(time_per_image * 500)) if vary_randomly else 0) if single_image is None else None
- event, values = window.read(timeout=timeout)
- if event == sg.WIN_CLOSED:
- break
- elif 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
- # First update the status information
- # for debugging show the last update date time
- if event == sg.TIMEOUT_EVENT:
- if single_image is None:
- image_name = random.choice(images)
- image_data = convert_to_bytes(os.path.join(image_folder, image_name))
- window['-FOLDER-'].update(image_folder)
- else:
- image_name = single_image
- image_data = convert_to_bytes(single_image, (width, height))
- window['-FILENAME-'].update(image_name)
- window['-IMAGE-'].update(data=image_data)
- window['-REFRESHED-'].update(datetime.datetime.now().strftime("%m/%d/%Y %I:%M:%S %p"))
- if event == sg.WINDOW_CONFIG_EVENT:
- new_size = window.size
- if new_size != window_size:
- print(f'resizing {new_size}')
- (width, height) = new_size
- image_data = convert_to_bytes(image_data, (width, height))
- window['-IMAGE-'].update(data=image_data)
- window.size = get_image_size(image_data)
- window_size = window.size
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Choose Image Folder':
- folder = sg.popup_get_folder('Choose location of your images', default_path=image_folder,
- location=window.current_location(), keep_on_top=True)
- if folder is not None:
- image_folder = folder
- window['-FOLDER-'].update(image_folder)
- sg.user_settings_set_entry('-image_folder-', image_folder)
- images = os.listdir(image_folder)
- images = [i for i in images if i.lower().endswith(('.png', '.jpg', '.gif'))]
- sg.user_settings_set_entry('-single image-', None)
- single_image = None
- elif event == 'Set Time Per Image':
- layout = [[sg.T('Enter number of seconds each image should be displayed')],
- [sg.I(time_per_image, size=(5, 1), k='-TIME PER IMAGE-')],
- [sg.CB('Use some randomness', vary_randomly, k='-RANDOM TIME-')],
- [sg.Ok(), sg.Cancel()]]
- event, values = sg.Window('Display duration', layout, location=window.current_location(), keep_on_top=True,
- no_titlebar=True).read(close=True)
- if event == 'Ok':
- try:
- time_per_image = int(values['-TIME PER IMAGE-'])
- vary_randomly = values['-RANDOM TIME-']
- sg.user_settings_set_entry('-time per image-', time_per_image)
- sg.user_settings_set_entry('-random time-', values['-RANDOM TIME-'])
- except:
- sg.popup_error('Bad number of seconds entered', location=window.current_location(),
- keep_on_top=True)
- elif event == 'Set Image Size':
- layout = [[sg.T('Enter size should be shown at in pixels (width, height)')],
- [sg.I(width, size=(4, 1), k='-W-'), sg.I(height, size=(4, 1), k='-H-')],
- [sg.Ok(), sg.Cancel()]]
- event, values = sg.Window('Image Dimensions', layout, location=window.current_location(), keep_on_top=True,
- no_titlebar=True).read(close=True)
- if event == 'Ok':
- try:
- w, h = int(values['-W-']), int(values['-H-'])
- sg.user_settings_set_entry('-image size-', (w, h))
- width, height = w, h
- except:
- sg.popup_error('Bad size specified. Use integers only', location=window.current_location(),
- keep_on_top=True)
- elif event == 'Show Refresh Info':
- window['-REFRESH INFO-'].update(visible=True)
- sg.user_settings_set_entry('-show refresh-', True)
- elif event == 'Save Location':
- sg.user_settings_set_entry('-location-', window.current_location())
- elif event == 'Hide Refresh Info':
- window['-REFRESH INFO-'].update(visible=False)
- sg.user_settings_set_entry('-show refresh-', False)
- elif event in [str(x) for x in range(1, 11)]:
- window.set_alpha(int(event) / 10)
- sg.user_settings_set_entry('-alpha-', int(event) / 10)
- elif event == 'Change Theme':
- loc = window.current_location()
- if choose_theme(loc) is not None:
- window.close()
- window = make_window(loc)
- elif event == 'Choose Single Image':
- image_name = single_image = sg.popup_get_file('Choose single image to show', history=True)
- sg.user_settings_set_entry('-single image-', single_image)
- (width, height) = get_image_size(single_image)
- sg.user_settings_set_entry('-image size-', (width, height))
- image_data = convert_to_bytes(image_name, (width, height))
- window['-IMAGE-'].update(data=image_data)
- window.size = window_size = (width, height)
- window.close()
-
-
-if __name__ == '__main__':
- # reset_settings() # if get corrupted problems, uncomment this
- main()
diff --git a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py b/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py
deleted file mode 100644
index 58ba3ba2c..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import psutil
-import sys
-
-"""
- Desktop "Rainmeter" style widget - Drive usage
- Requires: psutil
- Shows a bar graph of space used for each drive partician that psutil finds
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.7
-THEME = 'black'
-UPDATE_FREQUENCY_MILLISECONDS = 20 * 1000
-
-BAR_COLORS = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')
-
-
-class Globals():
- drive_list = None
- def __init__(self):
- return
-
-
-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):
- drive_list = []
- particians = psutil.disk_partitions()
- all_ok = True
- 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')
- drive_list.append(str(mount))
- except KeyError as e: # A key error means a new drive was added
- all_ok = False
- except Exception as e:
- pass
- all_ok = Globals.drive_list == drive_list and all_ok
- Globals.drive_list = drive_list
-
- return all_ok
-
-
- # ---------------- Create Layout ----------------
-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=(5, 1), key=('-NAME-', mount)),
- 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)]]
-
- # ---------------- 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,right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT,
- finalize=True, enable_close_attempted_event=True)
-
- return window
-
-def main(location):
- # we rely on a key error to tell us if a drive was added. So.... we don't want pesky popups or other key erros to be shown
- 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
- try:
- # ---------------- Event Loop ----------------
- while True:
- event, values = window.read(timeout=UPDATE_FREQUENCY_MILLISECONDS)
- if event in (sg.WIN_CLOSED, sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
- 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
-
- if event == 'Edit Me':
- sp = sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location())
-
- if not update_window(window): # update the window.. if not True then something changed and need to make a new window
- window.close()
- window = create_window(location)
- update_window(window)
-
-
- except Exception as e:
- sg.Print('ERROR in event loop', e)
- sg.popup_error_with_traceback('Crashed', e)
-
- sg.popup('Check the error!')
-
-
-
-
-if __name__ == '__main__':
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
- main(location)
-
diff --git a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py b/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py
deleted file mode 100644
index 6a6a26f1e..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py
+++ /dev/null
@@ -1,363 +0,0 @@
-#!/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
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-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)
-
diff --git a/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py b/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py
index a8f175df5..037f09721 100644
--- a/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py
+++ b/DemoPrograms/Demo_Desktop_Widget_Email_Notification.py
@@ -7,10 +7,6 @@
'''
Usage of Notification in PSG
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
IMAP_SERVER_GMAIL = 'imap.gmail.com' # gmail server address
@@ -24,7 +20,7 @@
def gui():
- sg.theme('Topanga')
+ sg.change_look_and_feel('Topanga')
sg.set_options(border_width=0, margins=(0, 0), element_padding=(4, 0))
color = ('#282923', '#282923')
layout = [[sg.Text('Email New Mail Notification' + 48 * ' '),
diff --git a/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py b/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py
deleted file mode 100644
index 76338f7fd..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py
+++ /dev/null
@@ -1,126 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Launcher Bar
-
- A 2021 version of a PySimpleGUI based launcher.
- Once making the GUI leap, it's hard to go back.... at least for some people.
- This tool will perhaps help make for a more GUI-like environment for your Python activities
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-excel_icon = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAAsSAAALEgHS3X78AAAFB0lEQVRIx51We0xTZxQ/X3t5lZY+QLwgLYgg4MSJOAQCOgED23SgMjedr2mY2UQhwblHNpK5xCxTM+Nkf+Dc2NTMZJCpEF3YsqU6y5ZsGpextSD0AcKlBeVR+rrt/fbHhcv1tlTGSdN8j3O/33mfgxiGAR4hhDDG7D/MTgghAGA5+efcCbdAAgA+jGDLYDzuspuGByZck7JwSZYmw/9dARgAEEHE9Hhp08iAftBooEx6ytg1ZB4YtblpDwCsVKe11ZzlC8sJxNmA3c4A0D7vg0fWbqtZP2gyUCYDZTIO97tozyw2mhGce4t9mv86QggxDNOobW69p+219U+4HQEt5k8xMsXGFWv9zzEGDBghFCImSjJyC1KzCISQrufeXYse/g+FikNTYjVBGMac9vorDb8cPU8Ej5ZZNZAqXiuo4Ftf4I/BMds3utYnODkIDYxa6680AEBRek5GfHLDz5fxtGvyU1aWPpUPABgwxnieAMP20fO3vgcAZaSclMd8+esVzhKEWMwCIEDz10ASGp5GJgEAGRUdERqWpU7HMAWwSBE7HUKAECL8U0ytIqVhEqOt30m7AWBLdkmiitR2/XnH/C/HlhKraT38Gbe9dviMf54DIIwxIchABKhxd31mQurbzacvdrQlL0g4ta3O46MvdLTx2fSUMf/4LkBQtbZyXVr2rnPvcRrsWPP8oeIdAAgBIIREgihiMNOobcYYb88pA4CdeRtDiZCLHW3D9lFBklseUpYRasw5QXu97Jr9PXKMY4wBMCAI7OTWv7R1pXsyE5ZmJy17afUGu8vRqG0R8JDy6N15LwJA7pIVMTLlW2V7AYDVYVViOj+TAwDQXu8Xt1o+qqj+eGuNUhJ17mbL0PiIgCcqQlq6PJ9NaVmYhA0bllSRcn49CRxFzX/8VFuyMyMu2eFxNd5s9mfooszFJ6sA4EjpnucyC0pOvc6Z+sC6yg82HeAKqmiWcg8+zCCExCJROBH2xMYgqIOPmSgAB8Ce/PKFUdF3zP9kaTLeWL/t6HefChiWkomf73wfAC+QKmXhkT/WNcKUE5AqMoorfQAQQAN5hLRq7ZZJt7P28gmnx7U1uyQxOk7AM+6cbO/UtXd29Nj67W5He6eO3bZ36rqGzFOKYAjsg32Fm6Oliku/Xe+x9l27p335mdKDRa8IlKDGhj+58RUAHCnbK5dIT/zQNOODZysLU1cBYBzQBwqJbH/BZi/j+1p3FQCabl/1MUzl6g1qFflYuSZC1CpSrSLlEZEhIkKtWshu1SpSESHjcwo1cNGe8rM1YpGoe8gCAH8/uP9Oy+lFytikmPi+hxTHlk4uvl7bwG11716YLQT8Adw91j5+4/729xv+X963WjadOQQAr+a9kL/k6epLx7mCsHlV0f7CLTMazK/hODwutgkWL8t10u67FgP3Ts7i5Xz5AofpXDpaedZ6AMjSpCklUfsKKrirNcmZ/Flmnv0gXhH7YfmbXKIdqzjoNx1NddB5AozYR5tuXw3e9OUS6VQURYSEiUUi39wGFpbcPrrH1j+TsXhqUoLp1kyIiGPlBxE7AdA+78CotXvIwk5wBsrUa+t3etxBAASTnWCg4wcOgTEOERMaVZxGFVeyLJe9o31e88iggTLqB416ytQ1ZH7wyOqi3YLJzn9uFIBhjINN0ZxEDGYmnJPGkQH9YK+BMjs8TrWSrC7ePhdjBgYPuAgyu8/I63f1H5J3l/PVeWn1AAAAAElFTkSuQmCC'
-
-# This is your master table.... keys are what will be shown on the bar. The item is what you want to happen.
-launcher_buttons = {
- sg.SYMBOL_DOWN_ARROWHEAD : None,
- 'PSG Main': sg.main,
- 'Word': r"C:\Program Files\Microsoft Office\root\Office16\WINWORD.EXE",
- excel_icon: r"C:\Program Files\Microsoft Office\root\Office16\excel.EXE",
- 'Notepad++': r"C:\Program Files\NotePad++\notepad++.exe",
- sg.EMOJI_BASE64_HAPPY_IDEA: sg.main_sdk_help,
- 'All Elements' : r'C:\Python\PycharmProjects\PSG\DemoPrograms\Demo_All_Elements.py',
- 'Exit': None}
-
-MINIMIZED_IMAGE = sg.EMOJI_BASE64_HAPPY_THUMBS_UP
-
-DEFAULT_SCREEN_BACKGROUND_COLOR = 'black'
-DEFAULT_BUTTON_SIZE = (None, None)
-
-def settings(window:sg.Window):
- layout = [[sg.T(f'Screen size = {sg.Window.get_screen_size()}')],
- [sg.T(f'Your launcher is currently located at {window.current_location()}')],
- [sg.T('Enable autosave and position your window where you want it to appear next time you run.')],
- [sg.T('Your Screen Background Color'), sg.In(sg.user_settings_get_entry('-screen color-', DEFAULT_SCREEN_BACKGROUND_COLOR), s=15,k='-SCREEN COLOR-')],
- [sg.CBox('Autosave Location on Exit', default=sg.user_settings_get_entry('-auto save location-', True), k='-AUTO SAVE LOCATION-')],
- [sg.CBox('Keep launcher on top', default=sg.user_settings_get_entry('-keep on top-', True), k='-KEEP ON TOP-')],
- [sg.OK(), sg.Cancel()]]
- event, values = sg.Window('Settings', layout).read(close=True)
- if event == 'OK':
- sg.user_settings_set_entry('-auto save location-', values['-AUTO SAVE LOCATION-'])
- sg.user_settings_set_entry('-keep on top-', values['-KEEP ON TOP-'])
- sg.user_settings_set_entry('-screen color-', values['-SCREEN COLOR-'])
- if values['-KEEP ON TOP-']:
- window.keep_on_top_set()
- else:
- window.keep_on_top_clear()
-
-
-def make_window():
-
- screen_background_color = sg.user_settings_get_entry('-screen color-', DEFAULT_SCREEN_BACKGROUND_COLOR)
- old_bg = sg.theme_background_color()
- sg.theme_background_color(screen_background_color)
- button_row = []
- for item in launcher_buttons.keys():
- tip = 'Grab anywhere to move the launcher\nClick an item to launch something\nRight Click to get to settings'
- if isinstance(item, bytes):
- button = sg.Button(image_data=item, key=item, metadata=launcher_buttons[item], button_color=screen_background_color,tooltip=tip, border_width=0)
- else:
- button = sg.Button(item, key=item, metadata=launcher_buttons[item], tooltip=tip, border_width=0)
- button_row.append(button)
-
- col_buttons = sg.Column([button_row], p=0, k='-BUTTON COL-')
- col_minimized = sg.Column([[sg.Button(image_data=MINIMIZED_IMAGE, k='-MINIMIZED IMAGE-', button_color=sg.theme_background_color(), border_width=0)]], visible=False, k='-MINIMIZED COL-')
-
- layout = [[sg.pin(col_minimized), sg.pin(col_buttons)]]
-
- screen_size = sg.Window.get_screen_size()
- location = screen_size[0] // 2, screen_size[1] - 200 # set a default location centered and near the bottom of the screen
- location = sg.user_settings_get_entry('-window location-', location)
- keep_on_top = sg.user_settings_get_entry('-keep on top-', True)
-
-
-
- window = sg.Window('Window Title', layout, location=location,
- keep_on_top=keep_on_top, no_titlebar=True, grab_anywhere=True, background_color=screen_background_color,
- auto_size_buttons=False, default_button_element_size=DEFAULT_BUTTON_SIZE, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_SETTINGS_EXIT,
- enable_close_attempted_event=True, use_default_focus=False)
- sg.theme_background_color(old_bg)
-
- return window
-
-
-def main():
- window = make_window()
-
- while True:
- event, values = window.read(timeout=1000) # Not needed but handy while debugging
- # print(event, values)
- if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit', sg.WIN_CLOSED):
- if event != sg.WIN_CLOSED:
- if sg.user_settings_get_entry('-auto save location-', True):
- print('saving locatoin', window.current_location())
- sg.user_settings_set_entry('-window location-', window.current_location())
- break
- if event in launcher_buttons:
- action = window[event].metadata
- if isinstance(action, str):
- if action.endswith(('.py', '.pyw')):
- sg.execute_py_file(action)
- else:
- sg.execute_command_subprocess(action)
- elif callable(action):
- action()
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(sg.get_versions())
- elif event == 'Settings':
- settings(window)
- window.close()
- window = make_window()
- elif event == sg.SYMBOL_DOWN_ARROWHEAD:
- window['-BUTTON COL-'].update(visible=False)
- window['-MINIMIZED COL-'].update(visible=True)
- elif event == '-MINIMIZED IMAGE-':
- window['-BUTTON COL-'].update(visible=True)
- window['-MINIMIZED COL-'].update(visible=False)
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py b/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py
deleted file mode 100644
index 1e222c8af..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py
+++ /dev/null
@@ -1,178 +0,0 @@
-import PySimpleGUI as sg
-import winsound
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- This one is a manual counter. Click +/- to add and subtract to the counter
- Dedicated to @SuperScienceGirl for having the original analog clicker that spawned this digital one.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.9 # Initial alpha until user changes
-THEME = 'Dark green 3' # Initial theme until user changes
-title_font = sg.user_settings_get_entry('-title font-', 'Courier 8')
-main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70')
-main_info_size = (None, None)
-# May add ability to change theme from the user interface. For now forcing to constant
-
-def choose_theme(location):
- layout = [[sg.Text(f'Current theme {sg.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, keep_on_top=True)
- 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])
- test_window = make_window(location=(location[0] - 200, location[1]), test_window=True)
- test_window.read(close=True)
- window.close()
-
- 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):
- title_font = sg.user_settings_get_entry('-title font-', 'Courier 8')
- button_font = sg.user_settings_get_entry('-button font-', 'Courier 20')
- sg.user_settings_set_entry('-button font-', button_font)
- title = sg.user_settings_get_entry('-title-', '')
- main_number_font = sg.user_settings_get_entry('-main number font-', 'Courier 70')
- sg.user_settings_set_entry('-main number font-', main_number_font)
-
- if not test_window:
- theme = sg.user_settings_get_entry('-theme-', THEME)
- sg.theme(theme)
-
- alpha = sg.user_settings_get_entry('-alpha-', ALPHA)
-
- # ------------------- Window Layout -------------------
- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info
- # and also enables events for the elements to make the window easy to close
- if test_window:
- top_elements = [[sg.Text(title, font=title_font, k='-TITLE-', enable_events=True)],
- [sg.Text('Click to close', font=title_font, enable_events=True)],
- [sg.Text('This is theme', font=title_font, enable_events=True)],
- [sg.Text(sg.theme(), font=title_font, enable_events=True)]]
- right_click_menu = [[''], ['Exit', ]]
- else:
- top_elements = [[sg.Stretch(), sg.Text(title, font=title_font, k='-TITLE-'), sg.Stretch()]]
-
- right_click_menu = [[''],
- ['Set Counter', 'Choose Title', 'Edit Me', 'Change Theme', 'Set Button Font',
- 'Set Title Font', 'Set Main Font', 'Set Click Sound', 'Show Settings', 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
-
- layout = top_elements + \
- [[sg.Column([[sg.pin(sg.Text('0', font=main_number_font, k='-MAIN INFO NUM-', justification='c', enable_events=test_window, pad=(0, 0)))]],justification='c', element_justification='c', pad=0)]] + \
- [[sg.T('+', font=button_font, enable_events=True, pad=0), sg.Stretch(), sg.T('-', font=button_font, enable_events=True, pad=0)]]
-
- try:
- window = sg.Window('Clicky Counter', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=0, alpha_channel=alpha, finalize=True, right_click_menu=right_click_menu, right_click_menu_tearoff=False,
- enable_close_attempted_event=True, keep_on_top=True)
- except Exception as e:
- if sg.popup_yes_no('Error creating your window', e, 'These are your current settings:', sg.user_settings(),
- 'Do you want to delete your settings file?') == 'Yes':
- sg.user_settings_delete_filename()
- sg.popup('Settings deleted.', 'Please restart your program')
- exit()
- window = None
-
- return window
-
-
-def main():
- loc = sg.user_settings_get_entry('-location-', (None, None))
- window = make_window(loc)
-
- counter = sg.user_settings_get_entry('-counter-', 0)
- sound_file = sg.user_settings_get_entry('-sound file-', None)
-
- while True: # Event Loop
- # First update the status information
- window['-MAIN INFO NUM-'].update(counter)
- # for debugging show the last update date time
-
- # -------------- Start of normal event loop --------------
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED:
- break
- elif event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
- sg.user_settings_set_entry('-location-', window.current_location())
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Set Counter':
- new_count = sg.popup_get_text('What value do you want to set the counter to?', location=window.current_location(), keep_on_top=True)
- try:
- new_count = int(new_count)
- except Exception as e:
- sg.popup_error('Counter must be a valid int')
- continue
- 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(), )
- if new_title is not None:
- window['-TITLE-'].update(new_title)
- sg.user_settings_set_entry('-title-', new_title)
- elif event in [str(x) for x in range(1, 11)]:
- window.set_alpha(int(event) / 10)
- sg.user_settings_set_entry('-alpha-', int(event) / 10)
- elif event == 'Change Theme':
- loc = window.current_location()
- if choose_theme(loc) is not None:
- # 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=False, location=window.current_location())
- if font:
- sg.user_settings_set_entry('-main number font-', font)
- _, window = window.close(), make_window(loc)
- elif event == 'Set Button Font':
- font = sg.popup_get_text('Font for the +/- symbols (e.g. courier 70)', default_text=sg.user_settings_get_entry('-button font-'), keep_on_top=True, location=window.current_location())
- if font:
- sg.user_settings_set_entry('-button font-', font)
- _, window = window.close(), make_window(loc)
- elif event == 'Set Title Font':
- font = sg.popup_get_text('Title Font and Size (e.g. courier 8)', default_text=sg.user_settings_get_entry('-title font-'), keep_on_top=True, location=window.current_location())
- if font:
- sg.user_settings_set_entry('-title font-', font)
- _, window = window.close(), make_window(loc)
- elif event == '+':
- counter += 1
- if sound_file:
- winsound.PlaySound(sound_file, 1)
- elif event == '-':
- counter -= 1
- if sound_file:
- winsound.PlaySound(sound_file, 1)
- elif event == 'Set Click Sound':
- if not sg.running_windows():
- sg.popup_error('I am terribly sorry to inform you that you are not running Windows and thus, no clicky sound for you.', keep_on_top=True, location=window.current_location())
- else:
- sound_file = sg.popup_get_file('Choose the file to play when changing counter', file_types=(('WAV', '*.wav'),), keep_on_top=True, location=window.current_location(), default_path=sg.user_settings_get_entry('-sound file-', ''))
- if sound_file is not None:
- sg.user_settings_set_entry('-sound file-', sound_file)
- elif event =='Show Settings':
- sg.popup_scrolled(sg.UserSettings._default_for_function_interface, location=window.current_location())
-
- sg.user_settings_set_entry('-counter-', counter)
-
- window.close()
-
-
-if __name__ == '__main__':
- sg.set_options(keep_on_top=True)
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Postit.py b/DemoPrograms/Demo_Desktop_Widget_Postit.py
deleted file mode 100644
index 577270f01..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Postit.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Desktop Widget Postit
-
- This is the longer version as it adds a lot to the right click menu to make it like
- the other more complete desktop widgets.
-
- Note that while the window has no scrollbar, you can still use the mousewheel to scroll
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ----- Make the window -----
-def make_window(loc):
- text_font = sg.user_settings_get_entry('-font-', '_ 20')
- text = sg.user_settings_get_entry('-text-', '')
- alpha = sg.user_settings_get_entry('-alpha-', 1.0)
- title = sg.user_settings_get_entry('-title-', 'Postit')
-
- layout = [[sg.T(title, text_color='black', background_color='#FFFF88', k='-TITLE-')],
- [sg.ML(text, size=(30, 5), background_color='#FFFF88', no_scrollbar=True, k='-ML-', border_width=0, expand_y=True, expand_x=True, font=text_font),
- sg.Sizegrip(background_color='#FFFF88')]]
- window = sg.Window('Postit',layout,
- no_titlebar=True, grab_anywhere=True, margins=(0, 0), background_color='#FFFF88', element_padding=(0, 0), location=loc,
- right_click_menu=[[''], ['Edit Me', 'Change Font', 'Alpha', [str(x) for x in range(1, 11)], 'Choose Title', 'Exit', ]], keep_on_top=True,
- font='_ 20', right_click_menu_font=text_font, resizable=True, finalize=True, alpha_channel=alpha)
- window.set_min_size(window.size)
-
- return window
-
-# ----- Make sure it doesn't get any smaller than it is initially -----
-
-def main():
- loc = sg.user_settings_get_entry('-location-', (None, None))
- window = make_window(loc)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- if event == 'Exit':
- sg.user_settings_set_entry('-location-', window.current_location())
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Change Font':
- font = sg.popup_get_text('Main Information Font and Size (e.g. courier 70)', default_text=sg.user_settings_get_entry('-font-'), keep_on_top=True, location=window.current_location())
- if font:
- sg.user_settings_set_entry('-font-', font)
- loc = window.current_location()
- window.close()
- window = make_window(loc)
- elif event in [str(x) for x in range(1,11)]:
- window.set_alpha(int(event)/10)
- sg.user_settings_set_entry('-alpha-', int(event)/10)
- elif event == 'Choose Title':
- new_title = sg.popup_get_text('Choose a title for your date', default_text=sg.user_settings_get_entry('-title-', 'Postit'), location=window.current_location(), keep_on_top=True)
- if new_title is not None:
- window['-TITLE-'].update(new_title)
- sg.user_settings_set_entry('-title-', new_title)
- sg.user_settings_set_entry('-text-', window['-ML-'].get().rstrip())
-
- 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
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py b/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py
deleted file mode 100644
index 14c69f706..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Desktop Widget Postit
-
- Sizegrip Element is used to make a window without a titlebar be resizable.
-
- There are 3 lines
- 1. Make the window
- 2. Set initial size of window as the minimum
- 3. Read any event from the window which will close the window and return
-
- Note that while the window has no scrollbar, you can still use the mousewheel to scroll
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ----- Make the window -----
-window = sg.Window('Postit', [[sg.T('Postit Note', text_color='black', background_color='#FFFF88')],
- [sg.ML(size=(30, 5), background_color='#FFFF88', no_scrollbar=True, k='-ML-', border_width=0, expand_y=True, expand_x=True),
- sg.Sizegrip(background_color='#FFFF88')]],
- no_titlebar=True, grab_anywhere=True, margins=(0, 0), background_color='#FFFF88', element_padding=(0, 0),
- right_click_menu=sg.MENU_RIGHT_CLICK_EXIT, keep_on_top=True, font='_ 20', resizable=True, finalize=True)
-
-# ----- Make sure it doesn't get any smaller than it is initially -----
-window.set_min_size(window.size)
-
-# ----- Read the window and wait for any event.
-# ----- Any event will cause the read to return
-# ----- Has a right click menu that can be used to choose exit
-window.read(close=True)
diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py
deleted file mode 100644
index 6c117ab16..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py
+++ /dev/null
@@ -1,320 +0,0 @@
-import PySimpleGUI as sg
-import psutil
-import sys
-import math
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- This time a RAM Usage indicator using a custom Gauge element
-
- The Gauge class was developed by the brilliant PySimpleGUI user and support-helper @jason990420
- It has been hacked on a bit, had classes and functions moved around. It could be cleaned up some
- but it's "good enough" at this point to release as a demo.
-
- This is a good example of how you can use Graph Elements to create your own custom elements.
- This Gauge element is created from a Graph element.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.5
-THEME = 'Dark Green 5'
-UPDATE_FREQUENCY_MILLISECONDS = 2 * 1000
-
-
-
-
-
-
-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 + number2
-
- 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)
-
- def new(self, degree=0):
- """
- 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
- 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, 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.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):
- """
- 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)
- return False
- else:
- self.pointer.new(degree=self.pointer.stop_degree)
- 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 main(location):
- sg.theme(THEME)
- gsize = (100, 55)
- layout = [
- [sg.T('RAM', font='Any 20', background_color='black')],
- [sg.Graph(gsize, (-gsize[0] // 2, 0), (gsize[0] // 2, gsize[1]), key='-Graph-')],
- [sg.T(size=(5, 1), font='Any 20', justification='c', background_color='black', k='-gauge VALUE-')],
- [sg.T(size=(8, 1), font='Any 14', justification='c', background_color='black', k='-RAM USED-')],
- ]
-
- 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_VER_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,
- 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=window['-Graph-'])
-
- gauge.change(degree=0)
-
- while True: # Event Loop
- ram = psutil.virtual_memory()
- ram_percent = ram.percent
-
- if gauge.change():
- new_angle = ram_percent*180/100
- window['-gauge VALUE-'].update(f'{ram_percent}%')
- window['-RAM USED-'].update(f'{human_size(ram.used)}')
- gauge.change(degree=new_angle, step=180)
- gauge.change()
- # ----------- 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 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__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- window.close()
-
-
-if __name__ == '__main__':
-
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
- main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py
deleted file mode 100644
index ff6c4f1eb..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import PySimpleGUI as sg
-import psutil
-import sys
-
-"""
- Another simple Desktop Widget using PySimpleGUI
- This time a RAM indicator. The Widget is square. The bottom section will be shaded to
- represent the total amount of RAM currently in use.
- The % and number of bytes in use is shown on top in text.
- Uses the theme's button color for colors.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ALPHA = 0.5
-THEME = 'Dark Green 5'
-GSIZE = (160, 160)
-UPDATE_FREQUENCY_MILLISECONDS = 10 * 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:])
-
-
-sg.theme(THEME)
-
-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_VER_EXIT, enable_close_attempted_event=True, keep_on_top=True)
-
-
- while True: # Event Loop
- # ----------- update the graphics and text in the window ------------
- ram = psutil.virtual_memory()
- rect_height = int(GSIZE[1] * float(ram.percent) / 100)
- rect_id = graph.draw_rectangle((0, rect_height), (GSIZE[0], 0), fill_color=sg.theme_button_color()[1], line_width=0)
- text_id1 = graph.draw_text(f'{int(ram.percent)}%', (GSIZE[0] // 2, GSIZE[1] // 2), font='Any 40', text_location=sg.TEXT_LOCATION_CENTER,
- color=sg.theme_button_color()[0])
- 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 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
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
-
- graph.delete_figure(rect_id)
- graph.delete_figure(text_id1)
- graph.delete_figure(text_id2)
- window.close()
-
-if __name__ == '__main__':
-
- if len(sys.argv) > 1:
- location = sys.argv[1].split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = sg.user_settings_get_entry('-location-', (None, None))
- main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_Template.py b/DemoPrograms/Demo_Desktop_Widget_Template.py
deleted file mode 100644
index 7f516365c..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Template.py
+++ /dev/null
@@ -1,194 +0,0 @@
-import PySimpleGUI as sg
-import sys
-import datetime
-
-"""
- Desktop Widget - Template to start with
- This "template" is meant to give you a starting point towards making your own Desktop Widget
- Note - the term "Widget" here means a "Desktop Widget", not a GUI Widget
-
- It has many of the features that a Rainmeter-style Desktop Widget would have
- * Save position of window
- * Set Alpha channel
- * "Edit Me" which will launch your editor to edit the code
- * Right click menu to access all setup
- * Theme selection
- * Preview of window using a different theme
- * A command line parm to set the intial position of the window in case one hasn't been saved
- * A status section of the window that can be hidden / restored (currently shows last refresh time)
- * A title
- * A main display area
-
- The contents of your widget may be significantly different than this example. Change the function
- make_window to create your own custom layout and window.
-
- There are several important design patterns provided including:
- Using a function to define and create your window
- Using User Settings APIs to save program settings
- A Theme Selection window with previewing capability
-
- The standard PySimpleGUI Coding Conventions are used throughout including
- * Naming layout keys in format '-KEY-'
- * Naming User Settings keys in the format '-key-'
- * Using standard layout, window, event, values variable names
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-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 ='Courier 20'
-main_info_size = (10,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, keep_on_top=True)
- 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)
-
- # ------------------- Window Layout -------------------
- # If this is a test window (for choosing theme), then uses some extra Text Elements to display theme info
- # and also enables events for the elements to make the window easy to close
- if test_window:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-', enable_events=True)],
- [sg.Text('Click to close', font=title_font, enable_events=True)],
- [sg.Text('This is theme', font=title_font, enable_events=True)],
- [sg.Text(sg.theme(), font=title_font, enable_events=True)]]
- right_click_menu = [[''], ['Exit',]]
- else:
- top_elements = [[sg.Text(title, size=(20, 1), font=title_font, justification='c', k='-TITLE-')]]
- right_click_menu = [[''], ['Choose Title', 'Edit Me', 'New Theme', 'Save Location', 'Refresh', 'Set Refresh Rate', 'Show Refresh Info', 'Hide Refresh Info', 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
-
- layout = top_elements + \
- [[sg.Text('0', size=main_info_size, 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 -------------------
- return 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, keep_on_top=True)
-
-
-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('Your Info')
- # for debugging show the last update date time
- window['-REFRESHED-'].update(datetime.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', location=window.current_location(), keep_on_top=True)
- if new_title is not None:
- window['-TITLE-'].update(new_title)
- 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())
- 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(), keep_on_top=True)
- 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(), keep_on_top=True)
- 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
-
- 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)
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py b/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py
deleted file mode 100644
index 36140be88..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py
+++ /dev/null
@@ -1,89 +0,0 @@
-import PySimpleGUI as sg
-import datetime
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.SYMBOL_CHECK_SMALL = '✓' # can remove line if using later PySimpleGUI version that has this symbol defined
-
-menu_sizes_original = ['Large::Large', 'Medium::Medium', 'Small::Small']
-menu_sizes = menu_sizes_original
-max_digits = 8
-
-
-def right_click_meny_new_size(window, new_size):
- current_size = window.metadata # Window's metadata has the subsample value
- menu = window.RightClickMenu # Dangerous operation... directly accessing the right click menu with assumption same for entire window
- menu_sizes[current_size - 1] = menu_sizes[current_size - 1][1:] # Remove checkmark from previous item
- menu_sizes[new_size - 1] = sg.SYMBOL_CHECK_SMALL + menu_sizes[new_size - 1] # Add checkmark to new item
- sg.user_settings_set_entry('-subsample-', new_size)
- [window[('-IMAGE-', i)].set_right_click_menu(menu) for i in range(max_digits)] # Set right click menu for all image elements
- window.metadata = new_size # Store the new subsample value as the Window's metadata
-
-def main():
-
- base64_digits = {'0':i0, '1':i1, '2':i2, '3':i3, '4':i4, '5':i5, '6':i6, '7':i7, '8':i8, '9':i9, ':':colon, ' ':blank, '.':dot}
-
- subsample = sg.user_settings_get_entry('-subsample-', 2)
- location =sg.user_settings_get_entry('-location-', (None, None))
- alpha = sg.user_settings_get_entry('-alpha-', 0.9)
- menu_sizes[subsample-1] = sg.SYMBOL_CHECK_SMALL + menu_sizes[subsample-1]
- right_click_menu = [[''], ['Version', 'Edit Me', 'Save Location', 'Size', menu_sizes, 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
-
- layout = [[sg.Image(blank, key=('-IMAGE-', i), p=0, subsample=subsample) for i in range(max_digits)]]
-
- window = sg.Window('', layout, background_color='black', no_titlebar=True, grab_anywhere=True, right_click_menu=right_click_menu, location=location, keep_on_top=True, enable_close_attempted_event=True, alpha_channel=alpha, metadata=subsample)
-
- while True:
- event, values = window.read(timeout=300)
- 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())
- break
- # Update the Image Elements with current time
- date = datetime.datetime.now()
- time_string = f'{date:%I}:{date:%M}:{date:%S}'
- subsample = window.metadata
- for i, c in enumerate(time_string):
- window[('-IMAGE-', i)].update(base64_digits[c], subsample=subsample)
-
- # Process the event
- if event == sg.TIMEOUT_EVENT: # if a timeout, then do nothing (saves a TINY amount of time not checking all the if statements...)
- pass
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event.startswith('Version'):
- sg.popup_scrolled(sg.get_versions(), non_blocking=True, keep_on_top=True, grab_anywhere=False, location=window.current_location())
- elif event in [str(x) for x in range(1,11)]: # Alpha channel selected
- window.set_alpha(int(event)/10)
- sg.user_settings_set_entry('-alpha-', int(event)/10)
- elif event.endswith('Small'): # Size changed to Small
- right_click_meny_new_size(window, 3)
- elif event.endswith('Medium'): # Size changed to Medium
- right_click_meny_new_size(window, 2)
- elif event.endswith('Large'): # Size changed to Large
- right_click_meny_new_size(window, 1)
- elif event == 'Save Location': # Gernally not neeeded since save on exit, but may make user feel better
- sg.user_settings_set_entry('-location-', window.current_location())
-
- window.close()
-
-if __name__ == '__main__':
-
- i0 = b'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'
- i1 = b'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'
- i2 = b'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'
- i3 = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAACXBIWXMAAAsSAAALEgHS3X78AAAPSklEQVRo3u1a23Icy3GsrO657BW7WAAESFHnKML+/y/xo8OyLMuWjkniDuxlZufSXemHmV0AOgBI4JkTQQIMxkx1VVdlV2Y15LUHAhGIAIgkRQAKRb3XYDGKiACACoQUAgITI0SUJIW//6R/1R4gIkIhQIoItPtpkWbd16CqQlIAEdIIEqpqZnzGnrhXDSpUhOz/9P8WERGy/5xziVdaVHUONKMY1HsPedbe6x5Kt2zZhwYKCIVisvseoGpCEgoaSREC6mjPf/E7BikikJ3FbkP7vwSEdFE0M9JMd1Ek9wF4o0F2Pjz4CAEfJ5QILYBGIU36bRV2S3h7SCkUBUDuMgR9Hu3dpBi76PKRCVq0F1z8rocEsItoVyDYe9ttb78YGvrc6uL85pCCooAT9hmZQBPvMq9J4tLMRQa2VV23TayJCIr0ldoXCAXPZap/zTs458zMRCDOO5+nST7Kx6PBcJw3oWmK5XpVbiuxGE33qawQsS4gfKuHPknaYEahuCRJB3k+OJgfzg6ms+m2rqqby+vrYonaARYpFIpAu3IEFGR80x4C6rxZHxeXDkaD0ejDyenxyeHRoiyKzdfpKL1i2Jp1NbHLKwEpAIR4U0hJs2hmAqeYTQ8m0/F0Mj9czGbjzLlkIIcxHSyW93eb+80qWIh9vkCMxD5ObymL2DIEirpER/OTxXw6n00mk9F4kLmU0Kij6XqzWl9cXIampfWrRJ8qz1biq3vIyGhGgUv8ZPHp9Gh+tMizPEuSBF7g3aA9XRfr6q9JWCoCepgBKRAS8qYsFRETU6PA+TQ9WJx9/nD04chpoj1qc2iwuixryOpCogME1tnb4cJbPGRvE46D0Xh8/OHobHaQu9A2rSGoJpqqJEgGcEe3Z8XdDQsg4hH+vv08JAgHh8FkdnB6dnY2HA18VSw3ga2Mh/kgcYkXaDI/KZok1OjASLj78Y7TQmgqLp8cLg6PPpwmSarV8vwmsrXx4aFzTrwmiR0sKmNxZ+IecK9DOb4VSyHeJX4wmR+fnZ2dighDefu1aZt4xiRVpUJTmdf05VWKHl3wAP1v91CCCE00cTButnXx29ffvkYzK26uZ7ODg1maJakbzHg9n2QUsvMNL9n7jkGICKMYfOo9pLy5vf6/8y9faeTk6ny8OF4cTSZj1QHS8+kot2gRBF+w9UMegoxm4jKvYHn1j39cnH/7BoJ5ng8/nH0oDxvkOhhMv8zGmbWR7I9rvscgBMJoZnCJd7Dy5re/XJyfX6h4cc6lZ6uiDW544AeZLmbjQUsCQtJeNum+25c684MEYbve3Pz5r3//drcqakANIDPP6PLJzClweXdXw7UVd88Ln/yeQYEKHJuyWN3e/Pffv1wUZR0gIIRUtvVkMl8IVG+Wm4pxuzVSXjb3A2Vh6l3cNMvLUTbeFMVm2waVSAZRLVFvDo4qiLRMJh8KtLexx9P3Jg3FQ1luzJJMsza0wQsgoMBiCJXznzaNiJj54fykuEuMeP2L3y0LUhWAWAAtGoIqCNIEmuRJ6hFb59Sng/FslCciFEjfLr89SyFQGs0ooJIkAQHRwYlL8sHASyuWaJoNpoPM7U99e1fhdw0RRQRmEs1orjspRUDx2XAy8BKcCZLBuB2lfk8J5Jl+5gdCCuz6aViUR4BMgcBn+Sh3bJw5n+ajMMw8hEIIVCLe4SFJEddhsuuKGeJETSkibLeCVVMLxKTZrC7XZdt1y0KLFLwdvGkQKACAZjvfBFCCZKjNyjqSFMbt3eVdGXX3Ht/FLUA6daqqGmKIu+ZRAEYTa6jbZdFSADTF3dVyG7QPjL0rS4XoCKBzSmrX4KBLX0eRaIKqNqGRdbm8WW0DupR6GWv895BNaF2/oA5mwYSkdM04kKgOBoM8cWBbLq/uiwZkR90e88o3ZSloVDWFeFowdrzMaCbweZpOx6Oh97CqXN2uty078gZCIG/rvEXQMWyjqsJ5D5NooIE0QkmXZMPRIM+gbKrN8rbctg/sH+/xUKBGo6nCwbkYVbnLCRHx2XA6GY8GQrF2u7xu6lZ2/wd5V1nQCBVAFUFjNGiW5RnUlIE2nS2mvxwPpWq3zfVd2YSO+ILoAvpWgxSxjvQ6VTCKiWIyno2dFx9CjLPDw/nn46E0m9XmZlk0IXZUC9B3NsJCKFSdOrXQRlHR9ODkOEldWrfb9ujkw8n0MGe9vrm7ui+bGDtqr6qwd/alFEBVVY0hOOf89OjjpzRLsrrZNCcfTk8HeYpmfXN+tSqDRbPd3vM9Hu7kLBGxaEQyyPKjD2ef0zRJt2HbHM1nI6ub7fXF19/O7za/Uy7enDRQoOvbACORjkaT0z98/tUlLtnGuj0Yj/PYtsXt+W9/u73bPrJHk3fIJoAqxDo8g1CT0fzw+OzTL3BwMYRmkOeDdVuUNxdf/74qt3smKnwpoN9XE9Wk2xcHQTI8WHz4+PkXUSJGtomq27Je3Zz/9j8hhIjuSMLLzOI7ZUGDkVAKJXpabKqqXK9XziUqhDNBJElajGYE1bBTHt+ltZEGdvoaQVpoqm1VFqskyVMzVQEtdvAajd3RC4LCd54WYoQAEKPQKDE029Vqvc5z57xKL7MBYjHECOtFKKEYdhTq7eJeJ2ZRKBLbuqzLzdLEe1N4E7INkUYztb3yKPIKe3Lf44cCgOxURe/EYE1xv9qUdUQGKElgU2yrRBH0sZTwWHl8i8FeHhDAOdUYrCmX63VRRE3HADRSsNnWrZdYQx4UN2AvV7/RQ+lENGiisKZuytXdpixLzUYHEFWKum0dA0JdgPoENJ4L7Q8Y7N5y6tXaqi7Xt1frYltlo9mRKkTh06qNsa3LDXpZumuhtReH3ryHuuubSCPVEYkyOAntJlhmFFZNkLZe3wPUThWCKoTPHYnuB3JGH3CcJEyUobXY1DXSkYigobiiWK0gZp1Mo/oS7/6uQYXqzpaZiCogodpKW26YTg9Bk1ZcUq6ur2OPoFB1u71/s2winf65iw6MIoHU7f3VtU4/GhwwcsngfDrMaLYfD0knCz/n4bPl8rSc+qlHfxYDFOZO42Q4yJqWzkTd/WpdOMQWO9L1Aro5wSvS3261vXeiTtF/SSEcD7M0IMkBuPv1phS2DfqgvISmrgNLvGSq64X7l1W961gKRMViPnCOfjh00GS92ZYMdUVBJ7e8JJvgJQ/7oU8X0k6TVOdcjzsiFtokc95n47FzSVoUVWn1ZtO/9Nrx9Mh9yG5E2DMDCkHQlC4mlufDHKqy3ZQlxGJzP0qTSWGgI0nGuGt/rTupnm2i+OAf8GR1nYplAjhAvJfReDzK8jy9ubpuRSxul4lNj8u241TWnYLdGl8lM3zC6bs920+R0JEJ8RDNDw4PR+PR+H9R3UahVUur5ydlAARiFmMveXWig2I/1fx9HWI3SIMoBCa9bNB1iQ5wSCQZTubHh7P5zLV3DhG2tWrzcbUNcAZyN1AD99oJngtpP8/ATiugYBeb7m1onqd5PkpHi8PFItrV5d/OS2u70rRAqqqANLMOAPFomPSshw8TFIoQumdHIhAHan4wOZjOR/PpdHZwfnVxfXm5Dj6KqDCq84l3KjSLxo7892IAyOcGJZ2K06l1IpRuwMpHU2f6ydHJ8fHiZDicjMLl1b9Xq9KCOfb5qCIGYYxG0f2QpKfez5UFCGHnJnvY3EELANAPZyd/+Pjx08c8y7Mv8fI/0Kg5OIKMUO+7X3chlZ2Dz9fhbubGLp79QKUrI++RjPJx/vHk08nR8SSvl9v6P79sBM57dcrpcDz5vBgK2yDFZltWbWPCXQY+35v6h9786bIIUZ/5dHF4Mj9dfDgeTYbJ3eXl1X99WVFTr0y8P5rNF5+Px64NdSzKoqybyEcjrldafe57gX3yqADOJ/nhH3/9dHgwO0yzNA+Xf/nz9dUagGieOD87+/jp4/FAYrNtttuyrNpg6AfTFMFzAO53eMB/IllUqM/y0fHnf/nX2cF0LLRYfPnLv9VlZch8plmSLT7++sviaKwMbbkuirJqItkPifGKh/ucfIhmN4Kdzabzz2dHh5m3IFGYH/1pXddNlQ78ME2T5OzD6dHIW7W6X95f3iw3Vd0SnTa2m5k8l6WdboR+Mr+7c5FkPpufHJ/84XQ+9qkXRgl+/rFp66YejPOx+tTPD+YHacK6uL++Or9ZFW0TH+lxL2DpAxXvzkXrmxKfpIPp8afPp6eLicKZBWmyBYZtFavJZDJJkGKQ57mR1frm4su3q/uNhbi/3QCo0J4F74ciR3/9AKqaZPl4fvrHP82P5lMGCTFImy4GJ6FmfTCdTbzkAhGp6qra3F58ubxdbsAetdA3Cj/Annb3WKCqzAbjw0nmo2j0TGIicG1sYzscJE7Q+kqadrsuVl++fLm4LbYuSmesg0v7MboGgJ2z6tLR7CjPvRCAB1QTCyFYyPNERRibZlvf3q/uv51/u1wVocuCfQvxgorxkEfozsJd9+uAJB/PEgczByVcpzBECUnXacSqXJe315fXF1cXV2VTW48b6LsIvsoPgaetDUWTwWS2CDCoiqqjEEqJbD3ExWChKdebL5ffLq9ub27NIp/ef3lZEcau8NkvjDRhaMq7iy+HqdNUEjghYCJsm1h7hauqeru6v1/eXp/f3hd1NMoDPeTLwxnPbo60swhSCBOrYbK8/joZDEcjJyqiCoshbqtqm/jEr1br5fp+uVze36yKbW3YX+t5GbifHMDE/rKP0Ci+UV3ffEvnM3oXkSTiIaFutpuiSNMsvb26vlov1/erYlU0obV9Te2tvSCb9NJtX/7YHx7BJN5fJqxanyapU4BgbOrVerVO80F69e3rt+X9+r6qy7pr/BQQ4EH7f8HDvkAfVWlnNGqL4ta168vLqVfvnfcu1lVTlutas8zf3F/ebop13bSRe91hd8o/Gjw/m6WQJzjbbamZbNCur4fToYcqnIOFJjb1NsAnWhSroqq2dRv6Wzs7iHxk7jnNu9PvbM/lsG9gnWiWplnuswRdKESMFmIwUaAJTdu2TTCLREeo9oW+A26+eBcDD23ojg1KEGlE1Dquvm9ytA9aIgAtslOAOoN8rHsSxPMM+OlRuU9v7ZpMfUS9Ol7TNUr7K2UP2spjzHpR3nMPx9ajy3I7VHq44iVPSpoiqjvttptS2O+1lmdNut3S+GQsKjsU3mHV/nc8kkSFD+T5nz/+2uWBVydBT2pFntwV/Pn8fH4+P5+fz8/n5/PO5/8BfvwgqFy+yvAAAAAASUVORK5CYII='
- i4 = b'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'
- i5 = b'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'
- i6 = b'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'
- i7 = b'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'
- i8 = b'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'
- i9 = b'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'
- blank = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwBAMAAAA0zul4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJUExURQAAAAsLCwEBASarxPMAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAAnSURBVFjD7c0hAQAACAOwV6AB/VOiSIDAbAUWAAC4qn5IAQAAYCUD5JkAMsfpUwIAAAAASUVORK5CYII='
- colon = b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAMAAADxPgR5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJhUExURQAAAAEBAQICAgMDAwQEBAUFBQYGBggICAoKCgkJCQwMDA8PDwcHBw4ODhEREQ0NDQsLCxsbGyUlJSoqKjQ0NDMzMyYmJh0dHRcXFy4uLkFBQVlZWXd3d4+Pj5qamlJSUisrKzg4OG9vb5GRkbGxsdHR0ejo6NjY2MDAwJaWlltbWyEhIWFhYYKCgqGhob+/v97e3vr6+vb29uvr69nZ2bS0tGZmZiQkJElJSW1tbZOTk66ursjIyOPj4/7+/u7u7tPT05SUlEVFRSkpKVNTU3t7e6Wlpbu7u/Hx8dXV1cbGxpWVlU5OTi0tLVpaWoeHh/39/erq6tfX18XFxbKyskpKSjAwMGJiYtLS0t/f3+3t7fv7+8zMzJ2dnXZ2dkJCQmpqaqCgoPn5+d3d3cHBwaSkpImJiTs7OxAQEHNzc6mpqeTk5La2tnR0dFZWVjY2NnBwcK+vr+Xl5enp6fLy8vf3962trUZGRiwsLBYWFlhYWKurq+/v7/Pz8/T09G5ubj8/PycnJxUVFYuLi+Dg4ISEhEhISDk5Obi4uOfn5xMTE46OjhwcHBQUFCAgIEdHR1xcXF1dXVBQUBISEhgYGDExMbm5uV5eXh4eHj4+PmxsbM3Nzdzc3MTExGdnZ0tLS6Ojo/Dw8NTU1MfHx2BgYC8vL4WFhdbW1v///+Hh4dDQ0MLCwmNjY9ra2uzs7MvLy7q6uo2NjV9fXzIyMiIiIkNDQ4GBgYaGhk1NTaqqqoCAgFVVVZ+fn8PDw4ODg1dXV76+viMjI3V1debm5hkZGaysrL29vRoaGigoKDU1NVRUVKDZ5uMAAAAJcEhZcwAACxEAAAsRAX9kX5EAAAXESURBVGhD7Zn7WxRVGMfnvrvsIloIoXgh4paW5ooauYLXwEIETPMCFl6yIEwhkjLILqakZWllF81McrO7ZVmU3a9/Ve97zjswe2F3ztmVpx/mw/M4887Me77znvO+Z85ZlVSomm7omjpqaJqKaHDZgBtwNC04QfCWgrcY6AIGXBLDKQjntiAqoqHpls/vswyuwW6wF4ETpgfPCCpiA07BsWhZKLoZyAnmBAymhWiGFTIN/pDGxIUFYyOkl2docMHy507KA0G0UU83Qz7L1Ph93TBNCUHsRuc5wm0UDOQFJ/t0slHQCkEPc1szTPEIsedGfZjFs4NbumH5AiE7IhxYCMqOCu8LjyG+dowLNAJ/JMhyh3c5GTx5yQN9RfWQWEEdUhLSnxsUKwcDwgoRDiqRmPfESGwhFhfvYhW7FPuQj7JUaDYJ3qhCpwyuADjPAX5XGGFPHjYgqSj+pqAFYyk3mOAj4UYxSnnKjQS4seQh0z3oR6dioBpCplvAI4OqklOUTzUOmW7JRJDPAGS6JQNBzFJxxQwEsQ4lIgRJOhUDPoZMkEz32B8GUbggGROCbk6soKrbaykZZBxV6FKpQQQgw8X9VNCTm79Bz7H6dg9UFPv+kykArPYQ4SFBQSwNMl2C7wmCFq7+YpYV6QBHLki2S1DOhvm6TgPwY6MoKsh3R+DHXTFcXFjjIj51W4YFK3DxLHVuThBmw8o+OOWGG/OnFhTmmuO1aPhCuOUQFYR1L+0P4GXhAAkEexVDualo2vTiGTNnFs+aHUzepk57DMEY7ZLAFMA44RsA+rpSWDLr5tJbysorKqtuncP3MnFoMBRiWhwaOzvFEU3RlDnT5t52+7z5dywIL6xelFwRHGQEQYv9g9sUKir8gCxecmfNXUsjyxbURuqWrwjgI/HgF59OJYCxREGyFGXlqtVr7i4rX1YfaVh7z715dDUWVhTCmtiHeNBjp5rGdU3VayvC65tbWjc03ZdLV+OQmhIpWaAcLOduduOmmtb7N2/ZGtlW3da+PUhX44DtqvCWG7OFCeIE4PDNf+DBhs3l9R07du7aveihPXQ1Ds0c3X67BwRZn8KKYUxPD5U8/Mj8znB9R0VX1aPde7MoiOXARh6KYQzVanxs3/6e2t7H6/qa5j5xYJwuZYKObnGDXfhxqP1PPhU+2Pv0wLa2wWcOPRuiy3HIC5LhwCx67vna3oGBnS8cnpKTtO4ByDSJ32nwZxIynIRenHGkrvPomu5Cg64kApkm9TtN8uLVh4q6V780/dj4ejg9idchVj6dJaD5hyanTMIUvv83JvZFJTY05EATsSgqDD6dusP+ho6fcamBUhSboGh5wA9ygrhuEoBtRrmgeFmwycYUmaFAiC3xQU+uDmHCYGtRt/DAUFCm8GHkIcCYj286MhNkEeJ6RqxPUUdaUNjRFsRQhfUQasAN0JHsHVk12EcJuF96Z3g1h2BGsEbStkKLXzePpoGNh4YN0oXkwGN0ZIcMwMTRdEWFOSdlW5krEVgbuDkx/Xk5x4M+oalVED4ePEJV8U869vIrJ1597cBJk+5nG9QDRVYZMIa5pw69vqn0jZau3W9OPZliOSMNTxYcGKar7Dm98a23297ZuuXdM7vO7j0uMv+4AwTZzM8NRRlaXPJe8bmy9e93nv9g+YXhkMTUlRoI0CGoaqeGV5z4sO9i9OBHlz6u+STfzLaeLciaxcSBvf1gTden0c92fP7Fl5e/EvyxyAVc0G5VNb6+cuEb2NtHmxe2bvh23TD7r72sgoJjmaEZBVcHa/qWRqLlDZXffT8yO9sdCoIx2zRFPb2k/Ycjl/ZHm1t+7Lv2U6PUGik1cQ1aBWfP/XyxJxquOLPv2sjKrCdpIvovv1af/62jp6K1r33779dfD0LuHyn9Y96flV1VV/8SWzxKY/T//c+Vfy8f7r+eU3gChm+cfbaHh4eHh4eHh4eHh4eHhweiKP8BrAuWtSVSEvUAAAAASUVORK5CYII='
- dot = b'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'
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_Timer.py b/DemoPrograms/Demo_Desktop_Widget_Timer.py
index 805d7156f..d8edf544b 100644
--- a/DemoPrograms/Demo_Desktop_Widget_Timer.py
+++ b/DemoPrograms/Demo_Desktop_Widget_Timer.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-
import PySimpleGUI as sg
import time
@@ -13,9 +12,6 @@
this design were not used, then the time value displayed would slowly drift by the amount of time
it takes to execute the PySimpleGUI read and update calls (not good!)
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -24,7 +20,7 @@ def time_as_int():
# ---------------- Create Form ----------------
-sg.theme('Black')
+sg.change_look_and_feel('Black')
layout = [[sg.Text('')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20),
@@ -38,10 +34,7 @@ def time_as_int():
auto_size_buttons=False,
keep_on_top=True,
grab_anywhere=True,
- element_padding=(0, 0),
- finalize=True,
- element_justification='c',
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
+ element_padding=(0, 0))
current_time, paused_time, paused = 0, 0, False
start_time = time_as_int()
@@ -54,7 +47,7 @@ def time_as_int():
else:
event, values = window.read()
# --------- Do Button Operations --------
- if event in (sg.WIN_CLOSED, 'Exit'): # ALWAYS give a way out of program
+ if event in (None, 'Exit'): # ALWAYS give a way out of program
break
if event == '-RESET-':
paused_time = start_time = time_as_int()
@@ -67,8 +60,7 @@ def time_as_int():
start_time = start_time + time_as_int() - paused_time
# Change button's text
window['-RUN-PAUSE-'].update('Run' if paused else 'Pause')
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
+
# --------- Display timer in window --------
window['text'].update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
(current_time // 100) % 60,
diff --git a/DemoPrograms/Demo_Desktop_Widget_Weather.py b/DemoPrograms/Demo_Desktop_Widget_Weather.py
deleted file mode 100644
index 0cd74e6b4..000000000
--- a/DemoPrograms/Demo_Desktop_Widget_Weather.py
+++ /dev/null
@@ -1,323 +0,0 @@
-import PySimpleGUI as sg
-import datetime
-import base64
-from urllib import request
-import json
-import sys
-import webbrowser
-
-"""
- A Current Weather Widget
-
- Adapted from the weather widget originally created and published by Israel Dryer that you'll find here:
- https://github.com/israel-dryer/Weather-App
-
- BIG THANKS goes out for creating a good starting point for other widgets to be build from.
-
- A true "Template" is being developed that is a little more abstracted to make creating your own
- widgets easy. Things like the settings window is being standardized, the settings file format too.
-
- You will need a key (APPID) from OpenWeathermap.org in order to run this widget. It's free, it's easy:
- https://home.openweathermap.org/
-
- Your initial location is determined using your IP address and will be used if no settings file is found
-
- This widget is an early version of a PSG Widget so it may not share the same names / constructs as the templates.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-SETTINGS_PATH = None # use the default settings path (OS settings foloder)
-
-API_KEY = '' # Set using the "Settings" window and saved in your config file
-
-sg.theme('Light Green 6')
-ALPHA = 0.8
-
-BG_COLOR = sg.theme_text_color()
-TXT_COLOR = sg.theme_background_color()
-
-APP_DATA = {
- 'City': 'New York',
- 'Country': 'US',
- 'Postal': 10001,
- 'Description': 'clear skys',
- 'Temp': 101.0,
- 'Feels Like': 72.0,
- 'Wind': 0.0,
- 'Humidity': 0,
- 'Precip 1hr': 0.0,
- 'Pressure': 0,
- 'Updated': 'Not yet updated',
- 'Icon': None,
- 'Units': 'Imperial'
-}
-
-
-def load_settings():
- global API_KEY
- settings = sg.UserSettings(path=SETTINGS_PATH)
- API_KEY = settings['-api key-']
- if not API_KEY:
- sg.popup_quick_message('No valid API key found... opening setup window...', keep_on_top=True, background_color='red', text_color='white', auto_close_duration=3, non_blocking=False, location=win_location)
- change_settings(settings)
- return settings
-
-
-def change_settings(settings, window_location=(None, None)):
- global APP_DATA, API_KEY
-
- try:
- nearest_postal = json.loads(request.urlopen('http://ipapi.co/json').read())['postal']
- except Exception as e:
- print('Error getting nearest postal', e)
- nearest_postal = ''
-
- layout = [[sg.T('Enter Zipcode or City for your location')],
- [sg.I(settings.get('-location-', nearest_postal), size=(15, 1), key='-LOCATION-'), sg.T('City')],
- [sg.I(settings.get('-country-', 'US'), size=(15, 1), key='-COUNTRY-'), sg.T('Country')],
- [sg.I(settings.get('-friends name-', ''), size=(15, 1), key='-FRIENDS NAME-'), sg.T('Who')],
- [sg.I(settings.get('-api key-', ''), size=(32, 1), key='-API KEY-')],
- [sg.CBox('Use Metric For Temperatures', default=settings.get('-celsius-', False),key='-CELSIUS-')],
- [sg.B('Ok', border_width=0, bind_return_key=True), sg.B('Register For a Key', border_width=0, k='-REGISTER-'), sg.B('Cancel', border_width=0)], ]
-
- window = sg.Window('Settings', layout, location=window_location, no_titlebar=True, keep_on_top=True, border_depth=0)
- event, values = window.read()
- window.close()
-
- if event == '-REGISTER-':
- sg.popup('Launching browser so you can signup for the "Current Weather" service from OpenWeatherMap.org to get a Free API Key', 'Click OK and your browser will open', r'Visit https://home.openweathermap.org/ for more information', location=window_location)
- # Register to get a free key
- webbrowser.open(r'https://home.openweathermap.org/users/sign_up')
-
-
- if event == 'Ok':
- user_location = settings['-location-'] = values['-LOCATION-']
- settings['-country-'] = values['-COUNTRY-']
- API_KEY = settings['-api key-'] = values['-API KEY-']
- settings['-celsius-'] = values['-CELSIUS-']
- settings['-friends name-'] = values['-FRIENDS NAME-']
- else:
- API_KEY = settings['-api key-']
- user_location = settings['-location-']
-
- if user_location is not None:
- if user_location.isnumeric() and len(user_location) == 5 and user_location is not None:
- APP_DATA['Postal'] = user_location
- APP_DATA['City'] = ''
- else:
- APP_DATA['City'] = user_location
- APP_DATA['Postal'] = ''
- APP_DATA['Country'] = settings['-country-']
- if settings['-celsius-']:
- APP_DATA['Units'] = 'metric'
- else:
- APP_DATA['Units'] = 'imperial'
-
- return settings
-
-
-def update_weather():
- if APP_DATA['City']:
- request_weather_data(create_endpoint(2))
- elif APP_DATA['Postal']:
- request_weather_data(create_endpoint(1))
-
-
-def create_endpoint(endpoint_type=0):
- """ Create the api request endpoint
- {0: default, 1: zipcode, 2: city_name}"""
- if endpoint_type == 1:
- try:
- endpoint = f"http://api.openweathermap.org/data/2.5/weather?zip={APP_DATA['Postal']},{APP_DATA['Country']}&appid={API_KEY}&units={APP_DATA['Units']}"
- return endpoint
- except ConnectionError:
- return
- elif endpoint_type == 2:
- try:
- # endpoint = f"http://api.openweathermap.org/data/2.5/weather?q={APP_DATA['City'].replace(' ', '%20')},us&APPID={API_KEY}&units={APP_DATA['Units']}"
- endpoint = f"http://api.openweathermap.org/data/2.5/weather?q={APP_DATA['City'].replace(' ', '%20')},{APP_DATA['Country']}&APPID={API_KEY}&units={APP_DATA['Units']}"
- return endpoint
- except ConnectionError:
- return
- else:
- return
-
-
-def request_weather_data(endpoint):
- """ Send request for updated weather data """
- global APP_DATA
-
- if endpoint is None:
- sg.popup_error('Could not connect to api. endpoint is None', keep_on_top=True, location=win_location)
- return
- else:
- try:
- response = request.urlopen(endpoint)
- except request.HTTPError:
- sg.popup_error('ERROR Obtaining Weather Data',
- 'Is your API Key set correctly?',
- API_KEY, keep_on_top=True, location=win_location)
- return
- if APP_DATA['Units'] == 'metric':
- temp_units, speed_units = '°C', 'm/sec'
- else:
- temp_units, speed_units = '°F', 'miles/hr'
- if response.reason == 'OK':
- weather = json.loads(response.read())
- APP_DATA['City'] = weather['name'].title()
- APP_DATA['Description'] = weather['weather'][0]['description']
- APP_DATA['Temp'] = "{:,.0f}{}".format(weather['main']['temp'], temp_units)
- APP_DATA['Humidity'] = "{:,d}%".format(weather['main']['humidity'])
- APP_DATA['Pressure'] = "{:,d} hPa".format(weather['main']['pressure'])
- APP_DATA['Feels Like'] = "{:,.0f}{}".format(weather['main']['feels_like'], temp_units)
- APP_DATA['Wind'] = "{:,.1f}{}".format(weather['wind']['speed'], speed_units)
- APP_DATA['Precip 1hr'] = None if not weather.get('rain') else "{:2} mm".format(weather['rain']['1h'])
- APP_DATA['Updated'] = 'Updated: ' + datetime.datetime.now().strftime("%B %d %I:%M:%S %p")
- APP_DATA['Lon'] = weather['coord']['lon']
- APP_DATA['Lat'] = weather['coord']['lat']
-
- icon_url = "http://openweathermap.org/img/wn/{}@2x.png".format(weather['weather'][0]['icon'])
- APP_DATA['Icon'] = base64.b64encode(request.urlopen(icon_url).read())
-
-
-def metric_row(metric):
- """ Return a pair of labels for each metric """
- return [sg.Text(metric, font=('Arial', 10), pad=(15, 0), size=(9, 1)),
- sg.Text(APP_DATA[metric], font=('Arial', 10, 'bold'), pad=(0, 0), size=(9, 1), key=metric)]
-
-
-def create_window(win_location, settings):
- """ Create the application window """
- friends_name = settings.get('-friends name-', '')
- col1 = sg.Column(
- [[sg.Text(APP_DATA['City'], font=('Arial Rounded MT Bold', 18), background_color=BG_COLOR, text_color=TXT_COLOR, key='City'),
- sg.Text(f' - {friends_name}' if friends_name else '', background_color=BG_COLOR, text_color=TXT_COLOR, font=('Arial Rounded MT Bold', 18),)],
- [sg.Text(APP_DATA['Description'], font=('Arial', 12), pad=(10, 0), background_color=BG_COLOR, text_color=TXT_COLOR, key='Description')]],
- background_color=BG_COLOR, key='COL1')
-
- col2 = sg.Column([[sg.Image(data=APP_DATA['Icon'], size=(100, 100), background_color=BG_COLOR, key='Icon')]],
- element_justification='center', background_color=BG_COLOR, key='COL2')
-
- col3 = sg.Column([[sg.Text(APP_DATA['Updated'], font=('Arial', 8), background_color=BG_COLOR, text_color=TXT_COLOR, key='Updated')]],
- pad=(10, 5), element_justification='left', background_color=BG_COLOR, key='COL3')
-
- col4 = sg.Column(
- [[sg.Text('Settings', font=('Arial', 8, 'italic'), background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-CHANGE-'),
- sg.Text('Refresh', font=('Arial', 8, 'italic'), background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-REFRESH-')]],
- pad=(10, 5), element_justification='right', background_color=BG_COLOR, key='COL4')
-
- top_col = sg.Column([[col1, sg.Push(background_color=BG_COLOR), col2, sg.Text('×', font=('Arial Black', 16), pad=(0, 0), justification='right', background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-QUIT-')]], pad=(0, 0), background_color=BG_COLOR, key='TopCOL')
-
- bot_col = sg.Column([[col3, col4]],
- pad=(0, 0), background_color=BG_COLOR, key='BotCOL')
-
- lf_col = sg.Column(
- [[sg.Text(APP_DATA['Temp'], font=('Haettenschweiler', 90), pad=((10, 0), (0, 0)), justification='center', key='Temp')]],
- pad=(10, 0), element_justification='center', key='LfCOL')
-
- rt_col = sg.Column([metric_row('Feels Like'), metric_row('Wind'), metric_row('Humidity'), metric_row('Precip 1hr'), metric_row('Pressure')],
- pad=((15, 0), (25, 5)), key='RtCOL')
-
- layout = [[top_col],
- [lf_col, rt_col],
- [bot_col],
- [sg.Text(f'PSG: {sg.ver} Tk:{sg.framework_version} Py:{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}', font=('Arial', 8), justification='c', background_color=BG_COLOR, text_color=TXT_COLOR, pad=(0,0), expand_x=True)]]
-
- 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=[[''], ['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)
-
- for col in ['COL3', 'COL4', 'LfCOL', 'RtCOL']:
- window[col].expand(expand_x=True)
-
- window['-CHANGE-'].set_cursor('hand2')
- window['-QUIT-'].set_cursor('hand2')
- window['-REFRESH-'].set_cursor('hand2')
-
- return window
-
-
-def update_metrics(window):
- """ Adjust the GUI to reflect the current weather metrics """
- metrics = ['City', 'Temp', 'Feels Like', 'Wind', 'Humidity', 'Precip 1hr',
- 'Description', 'Icon', 'Pressure', 'Updated']
- for metric in metrics:
- if metric == 'Icon':
- window[metric].update(data=APP_DATA[metric])
- else:
- window[metric].update(APP_DATA[metric])
-
-
-def main(refresh_rate, win_location):
- """ The main program routine """
- refresh_in_milliseconds = refresh_rate * 60 * 1000
-
- # Load settings from config file. If none found will create one
- settings = load_settings()
- location = settings['-location-']
- APP_DATA['Country'] = settings.get('-country-', 'US')
- if settings.get('-celsius-'):
- APP_DATA['Units'] = 'metric'
- else:
- APP_DATA['Units'] = 'imperial'
-
- if location is not None:
- if location.isnumeric() and len(location) == 5 and location is not None:
- APP_DATA['Postal'] = location
- APP_DATA['City'] = ''
- else:
- APP_DATA['City'] = location
- APP_DATA['Postal'] = ''
- update_weather()
- else:
- sg.popup_error('Having trouble with location. Your location: ', location)
- exit()
-
- window = create_window(win_location, settings)
-
-
- while True: # Event Loop
- event, values = window.read(timeout=refresh_in_milliseconds)
- 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
- try:
- if event == '-CHANGE-':
- x, y = window.current_location()
- settings = change_settings(settings, (x + 200, y+50))
- window.close()
- window = create_window(win_location, settings)
- 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=(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)
-
- update_weather()
- update_metrics(window)
- except Exception as e:
- sg.Print('*** GOT Exception in event loop ***', c='white on red', location=window.current_location(), keep_on_top=True)
- sg.Print('File = ', __file__, f'Window title: {window.Title}')
- sg.Print('Exception = ', e, wait=True) # IMPORTANT to add a wait/blocking so that the print pauses execution. Otherwise program continue and exits
- window.close()
-
-
-if __name__ == '__main__':
- if len(sys.argv) > 1:
- win_location = sys.argv[1].split(',')
- win_location = (int(win_location[0]), int(win_location[1]))
- else:
- win_location = sg.user_settings_get_entry('-win location-', (None, None))
-
- main(refresh_rate=1, win_location=win_location)
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py
index bfd232dfc..e34bdf8d7 100644
--- a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py
+++ b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py
@@ -10,60 +10,58 @@
CPU Used
Mem Used
Information is updated once a second and is shown as an area graph that scrolls
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-GRAPH_WIDTH, GRAPH_HEIGHT = 120, 40 # each individual graph size in pixels
+GRAPH_WIDTH = 120 # each individual graph size in pixels
+GRAPH_HEIGHT = 40
ALPHA = .7
class DashGraph(object):
def __init__(self, graph_elem, starting_count, color):
self.graph_current_item = 0
- self.graph_elem = graph_elem # type:sg.Graph
+ self.graph_elem = graph_elem
self.prev_value = starting_count
self.max_sent = 1
self.color = color
- self.graph_lines = []
def graph_value(self, current_value):
delta = current_value - self.prev_value
self.prev_value = current_value
self.max_sent = max(self.max_sent, delta)
percent_sent = 100 * delta / self.max_sent
- line_id = self.graph_elem.draw_line((self.graph_current_item, 0), (self.graph_current_item, percent_sent), color=self.color)
- self.graph_lines.append(line_id)
+ self.graph_elem.draw_line((self.graph_current_item, 0),
+ (self.graph_current_item, percent_sent),
+ color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
- self.graph_elem.delete_figure(self.graph_lines.pop(0))
self.graph_elem.move(-1, 0)
else:
self.graph_current_item += 1
return delta
def graph_percentage_abs(self, value):
- self.graph_elem.draw_line((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color)
+ self.graph_elem.draw_line((self.graph_current_item, 0),
+ (self.graph_current_item, value),
+ color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
self.graph_elem.move(-1, 0)
else:
self.graph_current_item += 1
-def human_size(bytes, units=(' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB')):
+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():
# ---------------- Create Window ----------------
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0), margins=(1, 1), border_width=0)
- location = sg.user_settings_get_entry('-location-', (None, None))
def GraphColumn(name, key):
layout = [
- [sg.Text(name, size=(18,1), font=('Helvetica 8'), key=key+'TXT_')],
+ [sg.Text(name, font=('Helvetica 8'), key=key+'TXT_')],
[sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT),
(0, 0),
(GRAPH_WIDTH, 100),
@@ -71,8 +69,14 @@ def GraphColumn(name, key):
key=key+'GRAPH_')]]
return sg.Col(layout, pad=(2, 2))
+ red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
layout = [
- [sg.Text('System Status Dashboard'+' '*18)],
+ [sg.Text('System Status Dashboard'+' '*18),
+ sg.Button('',
+ image_data=red_x,
+ button_color=('black', 'black'),
+ key='Exit',
+ tooltip='Closes window')],
[GraphColumn('Net Out', '_NET_OUT_'),
GraphColumn('Net In', '_NET_IN_')],
[GraphColumn('Disk Read', '_DISK_READ_'),
@@ -81,50 +85,54 @@ def GraphColumn(name, key):
GraphColumn('Memory Usage', '_MEM_')], ]
window = sg.Window('PSG System Dashboard', layout,
- keep_on_top=True,
+ keep_on_top=True, auto_size_buttons=False,
grab_anywhere=True, no_titlebar=True,
- return_keyboard_events=True, alpha_channel=ALPHA, enable_close_attempted_event=True,
- use_default_focus=False, finalize=True, location=location,right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT,)
+ default_button_element_size=(12, 1),
+ return_keyboard_events=True, alpha_channel=ALPHA,
+ use_default_focus=False, finalize=True)
# setup graphs & initial values
netio = psutil.net_io_counters()
net_in = window['_NET_IN_GRAPH_']
- net_graph_in = DashGraph(net_in, netio.bytes_recv, '#23a0a0')
+ net_graph_in = DashGraph(net_in,
+ netio.bytes_recv, '#23a0a0')
net_out = window['_NET_OUT_GRAPH_']
- net_graph_out = DashGraph(net_out, netio.bytes_sent, '#56d856')
+ net_graph_out = DashGraph(net_out,
+ netio.bytes_sent, '#56d856')
diskio = psutil.disk_io_counters()
- disk_graph_write = DashGraph(window['_DISK_WRITE_GRAPH_'], diskio.write_bytes, '#be45be')
- disk_graph_read = DashGraph(window['_DISK_READ_GRAPH_'], diskio.read_bytes, '#5681d8')
+ disk_graph_write = DashGraph(
+ window['_DISK_WRITE_GRAPH_'], diskio.write_bytes, '#be45be')
+ disk_graph_read = DashGraph(
+ window['_DISK_READ_GRAPH_'], diskio.read_bytes, '#5681d8')
cpu_usage_graph = DashGraph(window['_CPU_GRAPH_'], 0, '#d34545')
mem_usage_graph = DashGraph(window['_MEM_GRAPH_'], 0, '#BE7C29')
- # print(psutil.cpu_percent(percpu=True))
+ print(psutil.cpu_percent(percpu=True))
# ---------------- main loop ----------------
while True :
# --------- Read and update window once a second--------
event, values = window.read(timeout=1000)
- if event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
- sg.user_settings_set_entry('-location-', window.current_location()) # save window location before exiting
+ # Be nice and give an exit, expecially since there is no titlebar
+ if event in (None, 'Exit'):
break
- elif event == 'Edit Me':
- sp = sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location())
-
# ----- Network Graphs -----
netio = psutil.net_io_counters()
write_bytes = net_graph_out.graph_value(netio.bytes_sent)
read_bytes = net_graph_in.graph_value(netio.bytes_recv)
- window['_NET_OUT_TXT_'].update('Net out {}'.format(human_size(write_bytes)))
- window['_NET_IN_TXT_'].update('Net In {}'.format(human_size(read_bytes)))
+ window['_NET_OUT_TXT_'].update(
+ 'Net out {}'.format(human_size(write_bytes)))
+ window['_NET_IN_TXT_'].update(
+ 'Net In {}'.format(human_size(read_bytes)))
# ----- Disk Graphs -----
diskio = psutil.disk_io_counters()
write_bytes = disk_graph_write.graph_value(diskio.write_bytes)
read_bytes = disk_graph_read.graph_value(diskio.read_bytes)
- window['_DISK_WRITE_TXT_'].update('Disk Write {}'.format(human_size(write_bytes)))
- window['_DISK_READ_TXT_'].update('Disk Read {}'.format(human_size(read_bytes)))
+ window['_DISK_WRITE_TXT_'].update(
+ 'Disk Write {}'.format(human_size(write_bytes)))
+ window['_DISK_READ_TXT_'].update(
+ 'Disk Read {}'.format(human_size(read_bytes)))
# ----- CPU Graph -----
cpu = psutil.cpu_percent(0)
cpu_usage_graph.graph_percentage_abs(cpu)
@@ -134,6 +142,6 @@ def GraphColumn(name, key):
mem_usage_graph.graph_percentage_abs(mem_used)
window['_MEM_TXT_'].update('{}% Memory Used'.format(mem_used))
-if __name__ == '__main__':
- main()
+if __name__ == "__main__":
+ main()
diff --git a/DemoPrograms/Demo_Disable_Elements.py b/DemoPrograms/Demo_Disable_Elements.py
index acd02cb2a..97a6ad400 100644
--- a/DemoPrograms/Demo_Disable_Elements.py
+++ b/DemoPrograms/Demo_Disable_Elements.py
@@ -3,13 +3,9 @@
'''
Usage of Disable elements
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-sg.theme('Dark')
+sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [
@@ -56,7 +52,7 @@
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'exit'):
+ if event in (None, 'exit'):
break
elif event == 'Disable':
for key in key_list:
diff --git a/DemoPrograms/Demo_Dispatchers.py b/DemoPrograms/Demo_Dispatchers.py
deleted file mode 100644
index 59f1b169d..000000000
--- a/DemoPrograms/Demo_Dispatchers.py
+++ /dev/null
@@ -1,111 +0,0 @@
-"""
- Demo Dispatchers
-
- Alternative to if/else event processing
-
- Adapted from "The Official Python GUI Programming with PySimpleGUI Course"
-
- Most PySimpleGUI demos follow the simple if-else event processing, but there are
- other ways to process or dispatch events.
-
- Event Dispatchers:
- * If-Else
- * Dictionaries
- * Functions as keys
- * Lambda as key (callable like functions are)
-
- The handlers in this demo are all functions that are called once the event is detected
-
- The dispatch dictionary maps from an event to a function. It's more compact than a series
- of if/else statements if you have a lot of different events and are handling events in functions
-
- Keep it SIMPLE. Add complexity as you need it. If it is clearer to do the event processing in the
- event loop rather than functions, then do it in the event loop.
-
- http://www.PySimpleGUI.org
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-SYMBOL_X = '❎'
-SYMBOL_CHECK = '✅'
-
-
-## ## ## # # #### # ###### ##### ####
-## ## # # ## # # # # # # # # #
-## ## # # # # # # # # # # # #
-####### ###### # # # # # # #### ##### ####
-## ## # # # ## # # # # # # #
-## ## # # # # # # # # # # # #
-## ## # # # # #### ###### ###### # # ####
-
-def do_go(window):
- window['-STATUS-'].update(SYMBOL_CHECK, text_color='pink')
-
-def do_stop(window):
- window['-STATUS-'].update(SYMBOL_CHECK, text_color='pink')
-
-def do_tuple(window):
- window['-STATUS-'].update(SYMBOL_CHECK, text_color='pink')
-
-def do_other(window):
- window['-STATUS-'].update(SYMBOL_CHECK, text_color='yellow')
-
-def do_simple(window):
- window['-STATUS-'].update(SYMBOL_CHECK, text_color='yellow')
-
-def do_not_found(window):
- window['-STATUS-'].update(SYMBOL_X, text_color='red')
-
-
-# # ## ### # #
-## ## # # # ## #
-# ## # # # # # # #
-# ## # ###### # # # #
-# # # # # # ##
-# # # # # # #
-# # # # ### # #
-
-def main():
- # --------- A Dispatch Dictionary -------
- dispatch_dict = {'Go':do_go, 'Stop':do_stop, (1,2):do_tuple}
-
- # --------- Define layout and create Window -------
-
- layout = [[sg.Text('Dispatching Approaches')],
- [sg.Text('Status:'), sg.Text(size=(3, 1), key='-STATUS-')],
- [sg.Text(size=(50, 1), key='-OUT-')],
- [sg.Button('Simple'), sg.Button('Go'), sg.Button('Stop'), sg.Button('Other', key=do_other),
- sg.Button('Tuple', key=(1,2)), sg.Button('Lambda', key= lambda window: do_other(window)), sg.Button('Bad')]]
-
- window = sg.Window('Dispatchers', layout, font='Default 16', keep_on_top=True)
-
- # --------- Event Loop -------
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED: # Test for window closed (always do this one)
- break
-
- window['-OUT-'].update(f'Event = {event}')
-
- # --------- Dispatching of events ---------
- # Event processing.... a minimal if-else to show 3 dispatchers
- if event == 'Simple': # Dispatch using direct string compare
- do_simple(window)
- elif callable(event): # Dispatch when event is a function
- event(window)
- elif event in dispatch_dict: # Dispatch using a dispatch dictionary
- func = dispatch_dict.get(event)
- func(window)
- else: # None of the above
- do_not_found(window)
-
- # --------- After event loop ---------
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_DuplicateFileFinder.py b/DemoPrograms/Demo_DuplicateFileFinder.py
index a6e79bf11..9ec425771 100644
--- a/DemoPrograms/Demo_DuplicateFileFinder.py
+++ b/DemoPrograms/Demo_DuplicateFileFinder.py
@@ -5,10 +5,6 @@
'''
Find dups with PySimpleGUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
# ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== #
diff --git a/DemoPrograms/Demo_EXE_Maker.py b/DemoPrograms/Demo_EXE_Maker.py
index d46688694..14fd09421 100644
--- a/DemoPrograms/Demo_EXE_Maker.py
+++ b/DemoPrograms/Demo_EXE_Maker.py
@@ -1,18 +1,15 @@
import PySimpleGUI as sg
import subprocess
+from shutil import copyfile
import shutil
import os
-import sys
+
'''
Make a "Windows os" executable with PyInstaller
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-def main():
- sg.theme('LightGreen')
+def Launcher():
+ sg.change_look_and_feel('LightGreen')
layout = [[sg.Text('PyInstaller EXE Creator', font='Any 15')],
[sg.Text('Source Python File'), sg.Input(key='-sourcefile-', size=(45, 1)),
@@ -21,11 +18,16 @@ def main():
sg.FileBrowse(file_types=(("Icon Files", "*.ico"),))],
[sg.Frame('Output', font='Any 15', layout=[
[sg.Output(size=(65, 15), font='Courier 10')]])],
- [sg.Button('Make EXE', bind_return_key=True),
- sg.Button('Quit', button_color=('white', 'firebrick3')) ],
- [sg.Text('Made with PySimpleGUI (www.PySimpleGUI.org)', auto_size_text=True, font='Courier 8')]]
+ [sg.ReadFormButton('Make EXE', bind_return_key=True),
+ sg.SimpleButton('Quit', button_color=('white', 'firebrick3')), ]]
+
+ window = sg.Window('PySimpleGUI EXE Maker',
+ layout,
+ auto_size_text=False,
+ auto_size_buttons=False,
+ default_element_size=(20, 1,),
+ text_justification='right')
- window = sg.Window('PySimpleGUI EXE Maker', layout, auto_size_text=False, auto_size_buttons=False, default_element_size=(20,1), text_justification='right')
# ---===--- Loop taking in user input --- #
while True:
@@ -42,47 +44,39 @@ def main():
dispath_option = '--distpath "{}"'.format(source_path)
specpath_option = '--specpath "{}"'.format(source_path)
folder_to_remove = os.path.join(source_path, source_filename[:-3])
- file_to_remove = os.path.join(source_path, source_filename[:-3]+'.spec')
- command_line = 'pyinstaller -wF --clean "{}" {} {} {} {}'.format(source_file, icon_option, workpath_option, dispath_option, specpath_option)
+ file_to_remove = os.path.join(
+ source_path, source_filename[:-3]+'.spec')
+ command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format(
+ source_file, icon_option, workpath_option, dispath_option, specpath_option)
if event == 'Make EXE':
try:
print(command_line)
- print('Making EXE...the program has NOT locked up...')
+ print(
+ 'Making EXE...the program has NOT locked up...')
window.refresh()
# print('Running command {}'.format(command_line))
- out, err = runCommand(command_line, window=window)
+ runCommand(command_line)
shutil.rmtree(folder_to_remove)
os.remove(file_to_remove)
print('**** DONE ****')
except:
- sg.PopupError('Something went wrong', 'close this window and copy command line from text printed out in main window','Here is the output from the run', out)
- print('Copy and paste this line into the command prompt to manually run PyInstaller:\n\n', command_line)
-
+ sg.popup_error('Something went wrong')
-def runCommand(cmd, timeout=None, window=None):
- """ run shell command
- @param cmd: command to execute
- @param timeout: timeout for command execution
+def runCommand(cmd, timeout=None):
+ """
+ run shell command
- @return: (return code from command, command output)
- """
+ @param cmd: command to execute
+ @param timeout: timeout for command execution
+ @return: (return code from command, command output)
+ """
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- output = ''
- for line in p.stdout:
- line = line.decode(errors='replace' if (sys.version_info) < (3, 5)
- else 'backslashreplace').rstrip()
- output += line
- print(line)
- if window:
- window.Refresh()
-
- retval = p.wait(timeout)
-
- return (retval, output)
-
+ out, err = p.communicate()
+ p.wait(timeout)
+ return (out, err)
if __name__ == '__main__':
- main()
+ Launcher()
diff --git a/DemoPrograms/Demo_Edit_Me_Option.py b/DemoPrograms/Demo_Edit_Me_Option.py
deleted file mode 100644
index ab497dfda..000000000
--- a/DemoPrograms/Demo_Edit_Me_Option.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo "Edit Me" (and Version)
-
- More and more of these Demos are getting an "Edit me" option added.
-
- It's a big time saver to be able to right click and choose "Edit me" to edit a program you're developing.
- It's maybe an even bigger time saver if you've not worked on it for some time and have forgotten where
- the source code is located on your computer.
-
- You can add this capability to your program by adding a right click menu to your window and calling the
- editor that you set up in the global PySimpleGUI options.
-
- A constant MENU_RIGHT_CLICK_EDITME_VER_EXIT, when set at the right click menu shows a "Version" and "Edit Me" meny item.
-
- You will need to have first set up your editor by using the menu in sg.main()
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-layout = [[sg.Text('Edit this program by right clicking and choosing "Edit me"')],
- [sg.Button('Exit')]]
-
-window = sg.Window('Edit Me Right Click Menu Demo', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
-while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
-
-window.close()
diff --git a/DemoPrograms/Demo_Email_Send.py b/DemoPrograms/Demo_Email_Send.py
deleted file mode 100644
index ccc3d912e..000000000
--- a/DemoPrograms/Demo_Email_Send.py
+++ /dev/null
@@ -1,113 +0,0 @@
-import PySimpleGUI as sg
-
-'''
- Learn how to send emails from PySimpleGUI using the smtplib and email modules
-
- The GUI portion is simple
-
- Based on a send-email script originally written by by Israel Dryer
- (Thank you Israel for figuring out the hard part of the stmp and email module calls!)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-'''
-
-# If you are using a mail service that's not gmail, hotmail, live or yahoo:
-# then you can enter the smtp server address here so you don't have to keep typing it into the GUI
-smtp_host_default = ''
-
-# used for sending the email
-import smtplib as smtp
-# used to build the email
-from email.message import EmailMessage
-
-# create and send email
-def send_an_email(from_address, to_address, subject, message_text, user, password, smtp_host, smtp_port):
- server = smtp.SMTP(host=smtp_host, port=smtp_port)
- server.starttls()
- try:
- server.login(user=user, password=password)
- except Exception as e:
- sg.popup_error('Error authenticaing your email credentials', e, image=sg.EMOJI_BASE64_WEARY)
- server.close()
- return
-
- # create the email message headers and set the payload
- msg = EmailMessage()
- msg['From'] = from_address
- msg['To'] = to_address
- msg['Subject'] = subject
- msg.set_payload(message_text)
-
- # open the email server and send the message
- try:
- server.send_message(msg)
- except Exception as e:
- sg.popup_error('Error sending your email', e, image=sg.EMOJI_BASE64_WEARY)
- server.close()
- return
-
- server.close()
- sg.popup('Email sent successfully!', image=sg.EMOJI_BASE64_HAPPY_JOY)
-
-'''
- important notes about using gmail
-
- - Gmail has locked things down pretty good with what it considers less secure apps. That
- would include access your Gmail account from the smtplib library in Python. However, there
- is a work around. You can enable access from "Less Secure Apps" by going to your Gmail
- account and enabling that feature. However, you should do this at your own peril, and after
- carefully reading the warnings: https://support.google.com/accounts/answer/6010255.
-
- smtplib | https://docs.python.org/3/library/smtplib.html?#module-smtplib
- email.message | https://docs.python.org/3/library/email.message.html?#module-email.message
- email examples in Python | https://docs.python.org/3.7/library/email.examples.html
-'''
-
-def main():
- smtp_server_dict = {'gmail.com':'smtp.gmail.com','hotmail.com':'smtp.office365.com', 'live.com': 'smtp.office365.com', 'yahoo.com':'smtp.mail.yahoo.com'}
-
- sg.theme('Dark Blue 3')
- layout = [[sg.Text('Send an Email', font='Default 18')],
- [sg.T('From:', size=(8,1)), sg.Input(key='-EMAIL FROM-', size=(35,1))],
- [sg.T('To:', size=(8,1)), sg.Input(key='-EMAIL TO-', size=(35,1))],
- [sg.T('Subject:', size=(8,1)), sg.Input(key='-EMAIL SUBJECT-', size=(35,1))],
- [sg.T('Mail login information', font='Default 18')],
- [sg.T('User:', size=(8,1)), sg.Input(key='-USER-', size=(35,1), enable_events=True)],
- [sg.T('Password:', size=(8,1)), sg.Input(password_char='*', key='-PASSWORD-', size=(35,1))],
- [sg.T('SMTP Server Info', font='_ 14')],
- [sg.T('SMTP Hostname'), sg.Input(smtp_host_default, s=20, key='-SMTP HOST-'), sg.T('SMTP Port'), sg.In(587, s=4, key='-SMTP PORT-') ],
- [sg.Multiline('Type your message here', size=(60,10), key='-EMAIL TEXT-')],
- [sg.Button('Send'), sg.Button('Exit')]]
-
- window = sg.Window('Send An Email', layout)
-
- while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == 'Send':
- if values['-SMTP HOST-']:
- sg.popup_quick_message('Sending your message... this will take a moment...', background_color='red')
- send_an_email(from_address=values['-EMAIL FROM-'],
- to_address=values['-EMAIL TO-'],
- subject=values['-EMAIL SUBJECT-'],
- message_text=values['-EMAIL TEXT-'],
- user=values['-USER-'],
- password=values['-PASSWORD-'],
- smtp_host=values['-SMTP HOST-'],
- smtp_port = values['-SMTP PORT-'])
- else:
- sg.popup_error('Missing SMTP Hostname... you have to supply a hostname (gmail, hotmail, live, yahoo are autofilled)')
- elif event == '-USER-': # as the email sender is typed in, try to fill in the smtp hostname automatically
- for service in smtp_server_dict.keys():
- if service in values[event].lower():
- window['-SMTP HOST-'].update(smtp_server_dict[service])
- break
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py b/DemoPrograms/Demo_Emoji_Toolbar_PIL.py
deleted file mode 100644
index 8cd97c006..000000000
--- a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py
+++ /dev/null
@@ -1,408 +0,0 @@
-import PySimpleGUI as sg
-import PIL
-import PIL.Image
-import io
-import base64
-import win32clipboard
-import win32con
-import sys
-
-"""
- Demo_Emoji_Toolbar
-
- Shows a toolbar of emoji icons and radio buttons to choose size.
- When an emoji is clicked, the image is placed on the clipboard.
-
- If this program is invoked with a location on the command line, then it will
- show the window at the indicated x,y location, get a SINGLE image click, and then close the window.
- The idea here is to emulate the Window+. behavior like on Windows that enables emojis to be added
- easily while typing in text.
-
- This program currently integrates with PySimpleHotkey to create this popup, single choice behavior.
-
- You can replace the emojis with your own version of emojis. Use one of the many PySimpleGUI Base64 encoder demos
- to create your Base64 strings based on PNG files. PNG is what enables a transparent background.
-
- 6-Feb-2022
- The design took a turn and is kinda weird now... sorry about that but wanted to work in more emojis
- and the pre-rendering approach from before got replaced with a resizing of a single starting image.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-EMOJI_SIZES = (28, 56, 112)
-NUM_ROWS = 3 # Number of rows of Emojis. Note, may be 1 more than this if there is an incomplete row
-
-'''
-MM"""""""`YM M""M M""MMMMMMMM M""MMMMM""MM dP
-MM mmmmm M M M M MMMMMMMM M MMMMM MM 88
-M' .M M M M MMMMMMMM M `M .d8888b. 88 88d888b. .d8888b. 88d888b. .d8888b.
-MM MMMMMMMM M M M MMMMMMMM M MMMMM MM 88ooood8 88 88' `88 88ooood8 88' `88 Y8ooooo.
-MM MMMMMMMM M M M MMMMMMMM M MMMMM MM 88. ... 88 88. .88 88. ... 88 88
-MM MMMMMMMM M M M M M MMMMM MM `88888P' dP 88Y888P' `88888P' dP `88888P'
-MMMMMMMMMMMM MMMM MMMMMMMMMMM MMMMMMMMMMMM 88
- dP
-'''
-
-
-def make_square(im, min_size=256, fill_color=(0, 0, 0, 0)):
- """
-
- :param im:
- :type im:
- :param min_size:
- :type min_size:
- :param fill_color:
- :type fill_color:
- :return:
- :rtype:
- """
-
- x, y = im.size
- size = max(min_size, x, y)
- new_im = PIL.Image.new('RGBA', (size, size), fill_color)
- new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
- return new_im
-
-
-def convert_to_bytes(file_or_bytes, resize=None, fill=False):
- """
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (Union[str, bytes])
- :param resize: optional new size
- :type resize: (Tuple[int, int] or None)
- :param fill: If True then the image is filled/padded so that the image is not distorted
- :type fill: (bool)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- """
-
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- try:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
- except Exception as e:
- dataBytesIO = io.BytesIO(file_or_bytes)
- img = PIL.Image.open(dataBytesIO)
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height / cur_height, new_width / cur_width)
- img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS)
- if fill:
- if resize is not None:
- img = make_square(img, resize[0])
- with io.BytesIO() as bio:
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-
-
-'''
-M"""""`'"""`YM dP
-M mm. mm. M 88
-M MMM MMM M .d8888b. 88 .dP .d8888b.
-M MMM MMM M 88' `88 88888" 88ooood8
-M MMM MMM M 88. .88 88 `8b. 88. ...
-M MMM MMM M `88888P8 dP `YP `88888P'
-MMMMMMMMMMMMMM
-
-M""MMM""MMM""M oo dP
-M MMM MMM M 88
-M MMP MMP M dP 88d888b. .d888b88 .d8888b. dP dP dP
-M MM' MM' .M 88 88' `88 88' `88 88' `88 88 88 88
-M `' . '' .MM 88 88 88 88. .88 88. .88 88.88b.88'
-M .d .dMMM dP dP dP `88888P8 `88888P' 8888P Y8P
-MMMMMMMMMMMMMM
-'''
-
-
-def make_toolbar(location=(None, None)):
- buttons_per_row = len(all_emojis)//NUM_ROWS
- button_rows = []
- for row_num in range(NUM_ROWS+1):
- row = []
- for i in range(buttons_per_row*row_num, buttons_per_row*(row_num+1)):
- try: # The final row may be partial, so avoid crashing when overflowing beyond the total length
- row.append(sg.Button(image_data=all_emojis[i][2], border_width=0, tooltip=all_emojis[i][0], key=all_emojis[i]))
- except:
- pass
- button_rows.append(row)
-
- size_col = [sg.Col([[sg.Radio(s, 1, default=True if s == EMOJI_SIZES[1] else False, font='_ 6', k=i, pad=(0, 0))] for i, s in enumerate(EMOJI_SIZES)], pad=(0, 0))]
- layout = []
- for i, row in enumerate(button_rows):
- if i == 0:
- layout.append(sg.vtop(row+size_col))
- else:
- layout.append(row)
-
- return sg.Window('', layout, element_padding=(0, 0), margins=(0, 0), finalize=True, no_titlebar=True, grab_anywhere=True,
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, keep_on_top=True, button_color='black', location=location)
-
-
-'''
-M"""""`'"""`YM oo
-M mm. mm. M
-M MMM MMM M .d8888b. dP 88d888b.
-M MMM MMM M 88' `88 88 88' `88
-M MMM MMM M 88. .88 88 88 88
-M MMM MMM M `88888P8 dP dP dP
-MMMMMMMMMMMMMM
-'''
-
-
-def main(location=(None, None)):
- sg.theme('dark black')
- window = make_toolbar(location)
-
- while True:
- event, values = window.read()
- # print(event, values)
- if event in ('Exit', sg.WIN_CLOSED):
- break
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- elif event != sg.TIMEOUT_EVENT:
- emoji_data = None
- for e in all_emojis:
- if event == e:
- print(f'you clicked {e[0]}')
- emoji_data = e
- break
- if emoji_data is None:
- continue
- size_index = [key for key in values.keys() if values[key]][0]
- size = EMOJI_SIZES[size_index]
- decoded = emoji_data[size_index + 1]
-
- output = io.BytesIO()
- image = PIL.Image.new("RGBA", (size, size))
-
- win32clipboard.OpenClipboard()
- win32clipboard.EmptyClipboard()
-
- image.save(output, "PNG")
- fmt = win32clipboard.RegisterClipboardFormat("PNG")
- win32clipboard.SetClipboardData(fmt, decoded)
-
- background = PIL.Image.new("RGB", image.size, (255, 255, 255))
- background.paste(image, mask=image.split()[3])
- output = io.BytesIO()
- background.save(output, 'BMP')
- data = output.getvalue()[14:]
- win32clipboard.SetClipboardData(win32con.CF_DIB, data)
-
- win32clipboard.CloseClipboard()
- break
- # If started in a specific location, then assume should get ONE selection then close
- if location != (None, None):
- break
- window.close()
-
-
-if __name__ == '__main__':
- '''
- MM""""""""`M oo oo
- MM mmmmmmmM
- M` MMMM 88d8b.d8b. .d8888b. dP dP .d8888b.
- MM MMMMMMMM 88'`88'`88 88' `88 88 88 Y8ooooo.
- MM MMMMMMMM 88 88 88 88. .88 88 88 88
- MM .M dP dP dP `88888P' 88 dP `88888P'
- MMMMMMMMMMMM 88
- dP
- '''
- # This is where the emoji images are defined
- # Each emoji is a tuple with (description, starting image)
- # Each image is the size found in the EMOJI_SIZES tuple
- # These are the starting images that will be resized. They are LARGER than the version that is already in PySimpleGUI.
- e_cry = ('Cry',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODNCRDlCMUM3NjZBMTFFQ0FGNjFERkIyMDI1NzQwQjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODNCRDlCMUQ3NjZBMTFFQ0FGNjFERkIyMDI1NzQwQjkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4M0JEOUIxQTc2NkExMUVDQUY2MURGQjIwMjU3NDBCOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4M0JEOUIxQjc2NkExMUVDQUY2MURGQjIwMjU3NDBCOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Phe2EXkAACMVSURBVHja7F0HdFzVmf7e9KLRqMuSbFm23AvNGMeYZsAGTA2EkAC7S/FCSCOBPbvJhuXsIQnJbrJJNsmmQsISeggkS4lD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')
-
- e_dead = ('Dead',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEY3OTlCMkE3NjZBMTFFQzk1NUE5RTAzQkExMDE3QTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEY3OTlCMkI3NjZBMTFFQzk1NUE5RTAzQkExMDE3QTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Rjc5OUIyODc2NkExMUVDOTU1QTlFMDNCQTEwMTdBMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Rjc5OUIyOTc2NkExMUVDOTU1QTlFMDNCQTEwMTdBMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvXRfC0AACE2SURBVHja7F0JeFvVlT7vaZcl73a8JXEWnH0hBAKBBEIgKRC2Dk0ppVAK06aUUKDMB22H+fq1ZaCdMi3TdkpLYWAopR1K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')
-
- e_dream = ('Dream',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzUxRkExNTQ2Q0U5MTFFQjhCMEJDMzEzNTZENkFERTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzUxRkExNTU2Q0U5MTFFQjhCMEJDMzEzNTZENkFERTYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozNTFGQTE1MjZDRTkxMUVCOEIwQkMzMTM1NkQ2QURFNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozNTFGQTE1MzZDRTkxMUVCOEIwQkMzMTM1NkQ2QURFNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnhA2k0AACysSURBVHja7H0JfFxV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')
-
- e_eyebrow = ('Eyebrow',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Mjg0NDU0QTY2Q0U5MTFFQjk2RDlFRjIxRUU4QjUzNzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Mjg0NDU0QTc2Q0U5MTFFQjk2RDlFRjIxRUU4QjUzNzgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyODQ0NTRBNDZDRTkxMUVCOTZEOUVGMjFFRThCNTM3OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyODQ0NTRBNTZDRTkxMUVCOTZEOUVGMjFFRThCNTM3OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvF2CX8AACWtSURBVHja7H0JeBzV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')
-
- e_fingers_crossed = ('Fingers Crossed',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTFCRTVBQjk3NjZBMTFFQzgxMEZDQzE5RUVFMDZGMEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTFCRTVBQkE3NjZBMTFFQzgxMEZDQzE5RUVFMDZGMEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUJFNUFCNzc2NkExMUVDODEwRkNDMTlFRUUwNkYwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUJFNUFCODc2NkExMUVDODEwRkNDMTlFRUUwNkYwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjAxkeUAACr5SURBVHja7H0HmBzVle5f1bmnu6dnepImaWY0ygkUQCJIBAVAgG0MZnF+67zALvCcd41562d/++z9jHftt2t77X3gtb0O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')
-
- e_frust = ('Frustrated',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Q0IzRjc4RkY2Q0U4MTFFQkE1NTlGNDQ1RUJGOTQ2QTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Q0IzRjc5MDA2Q0U4MTFFQkE1NTlGNDQ1RUJGOTQ2QTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDQjNGNzhGRDZDRTgxMUVCQTU1OUY0NDVFQkY5NDZBNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDQjNGNzhGRTZDRTgxMUVCQTU1OUY0NDVFQkY5NDZBNyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pn5lfqsAAC32SURBVHja7H0HmFRF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')
-
- e_gasp = ('Gasp',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjQ5NDlCQUE3NkRGMTFFQjg3Rjc5NkVCRUQ5RDNEODMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjQ5NDlCQUI3NkRGMTFFQjg3Rjc5NkVCRUQ5RDNEODMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCNDk0OUJBODc2REYxMUVCODdGNzk2RUJFRDlEM0Q4MyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCNDk0OUJBOTc2REYxMUVCODdGNzk2RUJFRDlEM0Q4MyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrRdjb4AACb8SURBVHja7H0JnFTVme//1tbdVb3vNNDQ0OwCDQoqEME9xiU6aghGo8ZnEifJaPJeMknQaBKj5mXemBkzRk000WQclxg3FFwQRAQR2ddmbxroptdaurr2e9/3nXtr6669q6BJcn6/01VdVXc7//Pt33eOpCgK/tHO3GZI9gNJkk7rDV5agRJ6GaP10dRrqVdRr6ReRr1I62a6Vb5ZHfXi4O1T5xnqo95Pc1XWPrdSd2i9l/pJ6p3U26i3UD/Kr+91w3+6njtVwpKS/fBUAUhA8YUmUJ9DfS71s+jSU+j2RsQ7xmQESgkqi4VQI9jKy1TEjCZCtDA4EkBPr/rW4wXsDh4cKN29kPqc4n2c50aAvmumt9y3UN9I/VMCtecfAIZBY4r6PL+ly1xCt1IW/K4gH5g+FZgyERhXD1RXqWAVFAB5JhWw8L0pQxgowE905vYADGgv0eZxosMDR4Dtu4DDRIuyHAXsbjrmXXr7PvUPCFDX3xWABFoNvSymfhP1c7VBwZxZwEULgEmNxB8riLpM9KGR3xAB5lE3Eec0EL6GUvVEroOAcyd1GmXFl0NKIGD7CdQTwDa61FvvQWnvEITO981s+TV6+wL15dlkucMOQALuPHr5Dp3uS3RJQzFJrRuvAT53Pgm1aqIoPZGWeRKR2Hi15xPZScbwCXxdJLE2Uydu5j48JKobamNWvI/mz7J3gNXrVJDpuU7Q62/p66cIyI6/GQAJOJZnD1O/iP9vHAdceQmwiKjNUkJUVdhEfSYBNpYupos+OEA8zbGJBNcnRHGHTito8VrrCRXI9z6EQiyYh8tDQ/of9NUjBGTvGQsgAcfa4mPUb+D/z51NFPdFYMZ00jiKiXOWzCPWODr2wc69gG0N8a6t9CSBM0KdZxn6zirg5TegdHSKYbPT0N5PX/0nASmfUQASeLfRYY/SqUtZCfnGrcDUacQnyy8m8Ihn6vIGHxRwE6V9TAr+h4D35Blrlx0l5vkWqTfvvAOlv1/IyrXU7yQQ9w57AAk4M738nvoS0iKVf74d0mWXlkKquloFTtIPPshPen0vKXXWj0jdc+FMbzIN527SYG19wNtvk+3xmZCPLhrmOwjE/xm2ABJ4VfTTFXS62VNJF/nh3TrUTiSxV3VttDISSXG9K6h/QE/t+ZvyjvTSnDzUpr7fQ3T34stQPG5BjT8jEO8fdgASeKPoZ6voVI2XXwjc/a1KoP6b8OdPgBcm+GAUPQA9fARmm+0wDnZtQ1cgD27kwy3lk/5tQB9U67ufCJmPU10mqtnglUzi85izHjrYQ86XZK4nP12lL+73pYpVdRLQHZjpitz493ycjq5UTFfiVqzYkQcPLHCK7/n3/FkBmYV8XOdxO3QuGwoDNvT0KPjjs1C6ugSIjxKI3xs2ALKri37yMZ1mGh78N/TN+RoW1xajQD+YXdpJH/kDibfd/X9f/kqz3IciXzfmPLYYnrUbkAolnhIACTxGaRl7U6T7HoRt0VLcVqM6Iwe2FuKSjxNbsfrxd9vMATsWPHihomzZzIO6hEB8YagA6oZ4Tz9k8PJuuRmH5i/FV6vjg/fo8b9v8IRo0Bdj8w9fl5TqWoXo4mkigAlDPWfGANLF2dn8U/2kicraG57C19jTFYNY3WQB/a6d7HAZ/2jUuvJGoe3nz0kKJBbof9Sc+KceQGq/pZvQt977rLSovAAVcQJTb/cCnb5/ABfZdtVcCuVrX+e386jfNpRzZSQDadZcRS9vFtx6C96//jk8PBbIj5gKEhShdzp9HvxXy0mYFCfpklahnZmVfqG15av6Z5RWWKLYxLGs2fHxkZogtwLFJTS/WC2oKSZlYxEa7sDmkIqEphxsQQ3YSXfEWrSHru6SCsRvHCIECaH98nf8f59UKM7PnY/tJyJzygXo1xUOulaJrwvn3DEBeof1GGvvJA89mchAQ4bA/4j/fGlOK+4ruh+jMRt5ZMuZxNB4wwPZ9Ty+5fvwzCGNHLhaD56giUDz06EvRZ+uRH2l7tCVou3Ccmx73TqKfnYz9aczOX/aABL1zWLSbzoL+EoNgVPM4bwYri+/DbCty8oguMjmD2guUa8X8PmDs5SoI0OTxECElp8f/p/jjzqNi+Tn0feG7ACYrxF7UcAq+ghfS5jCJwLbJBGE/s4pAxDqxXDtF/ipGwFjWexfWVdHxem89HbrDmDPfiLMHhp4pxoo5SBqQFZB8vlUgNz03k+A9bviR8xPRTMa1ah/EFCLWQXZXKD+z5+bOPpvAUaOAJqmA+PGRJ8jzxj//KXEoWfSMdu2YyYRxgJio2tzCiBdJI9E4g0V5cB5Z7M7Ym4cVuRVfZtQo91/eRN4hbrNcWYpGzyhuKdD5RyQvvMWYMbU5ABymztHAAiNja7NNQVeRhRRtPB8jd1YpsX+lX0TkZVDUNpPfgkcOJSBONIZ1FC9uBCpNpGeHZ0eiNS+6XeKTp+yoJMCA0JUiqx2Vasj1qB9T79jpSr0fwqt+QDwf+4HvnwdcPsSNf0jURtDCqCZKNvlwvVEIN8iKgzkEsAb+c8F57OzsEZNeYjVbB/BZge+/4CaXxLyWRaQlldcCSXPrA64pKdXnQaUXgPKMDzJkQCWZDkEtsSgamBLAR90/Q7obR3iPbcXXlWpl0Np/HjxRIGeHr+pCVi3TmTZLaT+QU4AZIOTbuQKTiyazP4D8+TYP/ScEPkqjz4RAR6B462bgEBR5RlruykEnsCAswboeSS9Kaz1MLHSs/mq6mE8eRgGa7v47JVlamJWSRXJdW/8c0+ZJAAUHC5nAFKbRrOocsY0dUYhf1wc6luDLaSsrNsYZG86eOrPEtR3Rjdip/7uzkEpalJePvSFReKVgfWNaBSfG3rV2fvks8CPf5D41KPr1XlBhH1RLmXgIv4ze0ZQ7x4TY5oSz7BtwOvLI6yJilFJwVP0RnQ0XYKeKfPhrhgt2FNBZwsqdq5G5a6PQvLplCowhWU4ec6VsI4/W7zX+bwobNmJ8pV/RuHBrSE7RnG74KeuM1ugLy0X4PlqGqB39kLyutFGFlbzPtJS6+Nfi+VkA8nCQ4dwNkd3SA7acgEgu30ESxApESwDYygvzr5+fLolPEP95XUJT2prmIn9Ny6Fuyw6f7ePWG7nzEtgaT+EiS/+jF4PnjLwTsy7Hi2XfxMBU360p2b0FLQtuBHln76Fhj/8CAZneJzlfifNswAMFdWCnPzlI2HU7nnTlsQAcmscLwBknsyq/XtZ94USFmezsTuSU5U4VzPWofZ1WP+ZajoIrmMpS6iUdDZdip13/HoQeJHNWTsO2+96gihhdu6Ro4c8+MXv4dDV9wwCL7L1zL0Su+5/DT4WbpGchAxY2WELycRg27xNVWgStRHhIWhK55ZTApDI2sL+uvENmvwzxRhwXzdZ3vuwZn2E2CiOr7TYx0zHvht+nJLWyYO59+aH4KoclVP8ji28GW3nXZfSb900sZq/9wxkY3SCVqDPLuSkYjBCtqi+VI8H2Lcv8fmqwnNhdtYBpCYYZ2OD9l9M9vkpUZ6CLdvDs1kuKo95Mn7ofYvvS8tk8OdbsO/Ge7UZlP3mJOWj5dI70jumYQZOfPE7Ax5Ogezq16gwbGY1JwGQ6zpYD6LHm5ELACfyn7raIIBVMQBcj13NatayavMVq8Z4TBlzQ0K2Ga856qehc8ZFOQHw8BX/nIYzINzavvANeCui5bzscqoAFobdjAcOJuXeqKkWb8enEyNMFUBhM4wMjvlAA951RORyhqhPyL/SOBqnASfmfynjgT5+wU05oL4JsE6Yk9GxssGE9ktvG+BJ9AizQzHmi86ttxfoTlLXVFkpFFvmySOzDeD4KAANA1ij4xNV24oAUI4DoLXxHHjjsNZUWl/dRPTXjMsqgB2zLx/S8V3zrosuC2AHjcc1aCIfTEKF1VXR451NAAWPqAyOu74w2o9o/0wI6v2Hwp4XuaAwLoBDbdnWSNnWG5LNWFoNV934QRrpwIl8+HDi8xSFMyNHZBvAWg6lcGhFJOlGZliT5smO6wOHw04K1XCPzcbt9WcNecAdWThHiNXnmYWpMuR7mhjNgmWPO2IsNC33WOJzWMJprzVZBZAEbG1ZcCLpBthHDtVn1hzBHhJ5Xljby4bGmK0m2LGkG/p5yMiPRpBMCa+XZGAemRRqSKKrWzUp4rXCMNOqzSqAJFgrSoPkHVmYwpVDfarbpaU14t7zLHFmu2WQ3ZRJG4oMHXSuwtLsuN5KqmJ4Fr2DxuNkgrodDhQH9ZmsAUgqLZOcrqAgBoDOPWoNHwMYwR44XBQbwIIssT1L1gD0Z8nJHmtiBgGMHI+TCUo/DeHgryWbFCiunh+8v8hCFcfGsHofGfczxQZK58tOEYvOn71iGH2W7kmS/QkADI9Hd3f8c5iM0WOeLQAF8wwlAAUVGE6b6NsWchXZ7NrHPBPjeEv0nv6sRBYMrr6sAWhwZSfPI9KxHQbQp1FnWG/oTVCzmxcm4pJsa6EwGgYA2LcrVM/X0RVx0wlkHIeJ8nvbhzxY+d3HsgZgfldrVs6T19ESU3kQykwEgFZragSddQBDuR1BFur4LPRdZLJSUOOKa+u07h7yYBUd3ZU9AGlCGft6h3yewgNb4iiAqmM7pDYkSZAyGtMUJ5lJbHeIfQq2YI10lSW+g+Ij24Y8WMUtO7JqyA/1fFLAj8KDW+Kq8CLfRzNVnM6knE7JPYDO3VE5ny53pKBLHGGo2L1WTQ7KVNa4nSg9sDGrAFbuXD2k40t2rIHeHQcZWdEmtjoubncSDVvOEQX2BUlfMqnrtUQ0T0TCjpIk3GOydxGIH2U8WDUb3yQtNLvVMpU7VsPkyHwFrZqVzyWyokPekBBICRIHSSGUsg1gf+R9gNMWndujjdjI8dQlj/HVv/90RlTIWuyoNc8j241TAUevejYzeXxkO0q3rUroBREvEeMSLzofMSSObALojRK+vATIEBclMJ88jFGr/5T2cQ1v/SYrCkesVrvhNZKFO9O0R71o/MsjKaqVyUWbOzys/mwC6Ig6ebI1XFLMYq5f+QzK93yc1gDXEvvMVWOOMPn5+5BnS3GVLNIuJ778EMxtB5KcWBo0Lro4ox4hGWxZA5BTvXnVIUcC2znCiw5JM9SVQCCFAfsJqra+m/QmR659EePfeBS5biyfpz/5raQZcHqvG5P/5wFUbl8ZnSea6nVMSSmwO2WlLsXfdRGAcdfxKIgMUARU6hcLo5gtSVnQpBd/jopdH+HYwq+gb9TkKNlRQibH6JV/QOnBzThVje3Cmf91p8gaaDv/n+ApqY6638odq1D/3u9DDgklGYCa+RBMuTclMJPd4XWOerIKII1lt9WGuEGz4qJom0gcQ/xA8fshpVBox2o8d44yuMtHCo3J3HkUhn47TkdjLXfUh/8tFCa+H09JlTATzJ0tg/25AX9yFspcSQPanMDLGWGOZZ0C25i8XS51wdWBrSzCcyf5vdrE00N2OqAvKUudtZAqnydmthTlvUi5cdEJDbCOWBy/gma9JLpflUGsEXLX072ZS+Evq0nstaLfstsuketO8fuTEKAUGhPhsSmM/1t7WPdsyzaA4gk6ibDrY6TbRORy0MBp04gHyWGFvqgkvtSOlCukXRpPHoLkVfkIB4W9IybEDU2Fj+uBnmSXzmUXqewpmyR8jNshrjGUpiSyScUK3npIEQ7z0gThR4c9eryzCaDw+HZ0xgaQZWBJkeoTlTiEQjNXsE5ZEYmu+uLEQVO9owumY82CdepMeUKu6Oih80kGesbMgJw/WJbq+m0idV3n6Y/gVjrozYWiG6hLxjzo8wrEOSW9gbrqiPf398G+eyP01pP02xIEIuRceugpoZBRTPw074sUwXbLE8SiI1ySWQeQV3FHewINmzPWVKc2geDth2wyixko9zmgsxSGHiam/+/kEdVTMGkOqhomCtW4d+sauNtbCdg98DQ0hZOAiRWaCDi9pu7rCyywjJ0MU0UtdIUl8PsD1P0IcDURdS9NBlnrwdJJc9kIFE+dA9uOT0Q5mFxYnlFdIitqicw7yahqLJGTrKoigabYJUSm590unMw2gM1iWpyI/wNOu9+tZR9L7BfMsxAVGkVMLGDthaGiKulFfIYCOPr6iM2Uomz2QnSvWwGvtUsMMtcXMtWZTuwTM1oitlw4YQYKxk6B1WZHZ68Dcndq5pPT6URdXT1MZQfh7e2EoatVVBSl22R34tCCpKmczKpD9myCbJf2dkHU+3LhCxUnPZ5AtDZGPL9O4/mSSY0NcgkWV+/EdeBqqXfGgBd2uz2kBJXO+pxQw/W2kzCSwZzXslOAZywuR+XnroJcPRatx47DZrOpFJZG66LpXjxNrfHnWr5IRSNV9im7Eq9vKmoGBYDOkAEfD0CHM+Tozj6AZMw7iLTbjySIfU4aHwmgPeoBBEjWnrjyQtZS0CVSSHxEsW7tSQyWYhQ2qNleatWrgsLxZ6F47iU4aXMKEOQMIxterxdunQn5taOF9mpIM0gsa0Us8UdWJ1iozt0X8sJwBVI8q6o3bPntSec+DGlMuG0nO1HLPlFLDMWwYUxYkeEZJ+rG8wuEGyeovvu7OmCorA7JhtBgaIlFSg+BVFQNh4MUGC2Hg9mks6VZsMzSpgVwmQpx/ERb1EpGOvrOaDSKbqAR4s6fBbuYQCQPPR6POHdA8xL19vaibkKTkLUGUmj8lfUpyUKeiAFHYhuVn128OsOaybgE6aftYam3IycAUmN3yOWcfd10Vmx7lddJ+VBb24dvPFBcJR4kWK3DM9bfeVJopazYBP2EIorPQc9+lfX2kRysrKwURfk6AruIQDTW1KOb+IxM8quQjCkTyZdgN6S4Kg8fx/L1+PHjgtJZ2XHrjMirHAFPVxtppe2iojg+2clC7gVs1qQL2OgK1FmujwCwMUHC/ImwfrElVwCKE8cDkNvZM8MAsp3FAAp3mqs/ipQDtl6awVboiMUKaqTOkXxJdkPHZWk0UC6SL2bNbVHYOF2wvBGFxUPeBkFPpsQI4mXHjh0T17FaragaN1UAaOhth4+3QiCWJ3y5nM/CTgACWvUs+VJbjkuvE+KDHQiseImBNqhl1HHV/KNiPjtoeA7kQonh9in/2ZVg7fX5c4X9HjLMeSAYJMRYvVeto3MhYLch0E0mgaZEBMenv79/gAPYlLVNSJjVVlRUhGQhmxFsjggnxPFDgksEerqE3JaJVTIHERlmKSY76Mwqd9E5ukOUOmlS/HwXflSSCvzTDaRv5Calgk7cQvd0dOfe+NyDN5yaNT3s1tJzlJsO0lsKE547z2MXUQypcmRItrlcuV3Bvri4OCRnWfM1j1L5m8E/xPWgeckb7XkN9s7Qx9MTlHMQRw869NJeqSmtnBga2zXsr0ukjS6cF8GfrardobMUxXWnGX1OAtAmzAVf7fgoLTHXexsGqZCp3VQzWgPQPaRz6piS2evjdYUUGDYHp0yOf0zL0dDbD3MKILRFaD7bGv8HiwjAQkvQ3WWHzuMU4BnKKgYl/Bp9/ShwdavO68nnwheR0cOyKtdb3xUUFAg5yxOF6xd44HWyPxTTTJv4CKmg8z64Tgy3WU2Jw0i79qgeGHq7IdcA8gowyiebBlFmmB2S7X7ZhRFUqCXOSqSNGqprQ7Yhz3QVPDp+0hy4ES0ny8rKkOt2zjnnYOzYsGah08ybtAFkeVdUTCZSjWr/+TzCLAm2889L7P9sV+Xfyky2sksLQLoAW9ObWJGJjNDzMlL7jqkbXjCY11we5pisjZpadwkFgV1rbAcay8pR4O5WVZaJ5wiDOrJZLBaUlJTkFDw2PRobGzFv3jwhC3UEWkBU1ZIWnGKtPDvsdcUlMNbWqQ57lvekuORx7qtmvLPtV5Og2u9AWOdclhHLzuCYV9kB8eG6SNWcAO1XdyvZdpAAJVyuvzrie9JI8w9ugqltv/BMmGxtIs1eGj0JLn3+IPBqampyTn0MXh6xi/r6elRXV0O2qxpjgNdAixcjlFQ2KaitqgaGmjo1XMbAkcKSd3ircL4H3XKsI119ZRLbbGtI+X49o4mYwTGc1/eL99cAV10WMnvCLjNZpcTZZFJ46P3y5doKuzQ4InwTZC0kb9zFNVHuKNYMq6qqcg4ey9epU6dq3E8SToPDW9VcVZ+xIAwWKyOs+7NLjENSpryoJCWmNo5H6gj8gdVJHCO9aUli6uvuDZVdryLuduKUAEgXOnJpBdbubsYCjk6MqlMB5D4wq5h5/8QJwLvvATt2RstKafTkKD8my7zy8nKcisbUx5OFG7vXbN2dcHeovlC5chQMeWYVuAglShjlpFWyYS6UM/ZxxpCVrMB9bgGINSdftnl7uMrgzxmLggyPe5L6Al5O8e6vazdOE9fmjKWqA0u+DFxOJuFvX9Sj75gqG7yW8hD1MXCnQmkJyr4ZM8Jr6WzcuBH2/TtU9llUIRatk7weSC6b0KAl6sK3myRaoS/UYRrZwDdcLqdUoMJLS6/9WCSy8z6DL51qAF+iCz/8zgcYtfhadQvVYktsAIOtlPDxazuDSLVj4dfAYwXiVIHHbebMmULOcmttbcW+3TvhPLJX81v2Qr8vNU2eQTKXSXDn62EsJc3TJKFwRIA+T02D3bBReGB4QH5DXM2Zsd2ZyUF0QS/Nmnt5YfLfaGutlyZ2tsDlkeA9qVJfIMJhHGRlp6KxZjtt2rSQ8f7xxx/DvneL6u/UnNXxGs+xaSQ2P08a9jeJ69x/H7DwCh1M1XoBHjenJzW71WqjMXxPUB8Hkf5tSBxlCMdyRcedn27G/OUrgSsuBorMqjYaz1kru0gIWkqFchPp4zwVjZWV+fPni/ASy95Vq1bBevQA+o/ui2Cv6pplDBaLY1ZAOABbWxNVPRsG1RLtKdKlgB/PkVf+Kuoj+Nc/IGKwnhYA2emqbbW69bHfwzxuDKTqmvgAbt6sPeyo6CwwnU53SgCcPn26MBfY6/LRRx/h+P496N2keq7mksZ8yUU0AdNc76BgwNxLBcD3VoZsP7b7nhnqcw1p9AjEAzQeN3Nq5NKHoHBUOdYy+7w3xJ7dqungGWD3yXLuV+Nln2dTU5MAb926dWjeshHdn7wrWGfTTODaa9IHL6aDvCCx7/bjT4DVq4VyyxB+Nd3IQ9YB1EB8jV7utjsg/eCnUOwxioc2b1Jr4qSRjZAHOKj9/tzuSccsetGiRQI8Zpu7Nq5XwfP7hIP5huszX8HS4Y4+sKY0Nh78yHRpLHtTXKuN/r9iKFuUZxVADUTebvwuAlF58P9C2bQ5bPPx66daQa2/aLCR7vHkbv9clnsLFy4UpsOKFSuwf/MGdK9/JwTeV26KHapMtXXZowFsqBrMTTjW9yIZCe++L8A7SuNxAXOurJlF2ToR3dQTJBNbyZj/019eQdkuYpnXXA10d6nLLEollfDKg2doLuN+c0m4MQUuW7YMXQd2w7pljUgaZrbJlDcU8Ljtbw/P/9EVMorN0c+3l/SjV16B0tcnFJbVBN6XaZyyusd6VnfZoJt7i0DkkO4f9+zBJfsPQCkrVR2LyojYCSGcgcZs1GDI7oYfbKyzgrR8+XIy1LfDvmdTyDt09VVDX/j3eI8OnREUeN7EcDkde6jITBDLLNN1+It7qf+KxifrAj/r26TQTR4nENlLuoR0hF91dqJObPxBRqMkKVrRSvTocUQ8m260hoYGkSu6betWkX3d37pffH7ZpcCFi7JzjdW7wuQ7vkbG+GpZLKu8fgPQHE47WUZU930ak705ExPZ2kd+YNPWWGNv38QBJxQL33AqoWwuRqCwnAzhfIwZMyYrJgV7dTjjzNbVgd7NH8Lb0yG8JswyZ0zPzqB9ekCP93eoc7+UNM8xkg/btyoKzcPgYK2g/ggBl/HmibneADKV9jiDxzmkvBY05wSxQO+x0o15XdBzt9HgQl1fu8ttRdXEGaEClEwb53p6utsJvDVi1Vwu5/rqLSSjsrDgPfsvm49K2H1IQhWxl/bDstJqVaRWdV6ybHuZnzuXFHdKKJCoj7dS+xPP/P94EGiMSGjlJUlajwG7iN1s2qbuqeDVKrR0xjxYGqagcNxUEfzNpPUd2AF78xah/hInxZLF6dl4vGchd87bdTjUxem46IQTbzlzbIDlxtYtb9LBxfur0915LBsUmHUACbxqOmQvnbbsnm8AX7gkiY/UrQaH33gnvE0dx96KJjbBMmZSytpGwN0P69a1Ir+T27ixRP6N6ngPXFyHLRevxhH4O842DwIXL5uCbqOLnomzpjm9kjWitQRYW64o63QCyAHfJZz8+8ufpKftbd4OPENH79PWGOAiltKm+eI14SQ4fgi2nZ9CzmDpSLo/tmP6aBh4yT7O8+C6NU4dadU6h1z3ZMvwHtYAEnjzeWbyupdP/XvEPhNp3TjwwUfA08+rSxRzTQRTIxe1DJwNLOOsO9aL2gbxPylFvuoGUd8QuZBQcPNIg60Thk6xqiBHMV8eqiN5OACYbSXmF/zngsVjUVvLyY5yJhSBiy8A5s0FnvgjsHylDPvezYI1ls2+gNhrvkDZeXQfHHs2Q1YDrWyj6LmaNzQAMc4dsaqubjiDd1qUGKI+trBW6etG4IPHj4i94C+Q1+BCZRWuU15FvXI0LSrcc1SNMR6j1189plY9cfp78eSz4Ty8WxR+am0N9XqisrGehlkJz6vvs8LYLrxYD1H/XeQlqfdwGd2ZRoHZBPBterlC9/C/450p3x30/dnKJtwg/wVfUf4bo5XEi6weZ61Pq5ezEMEVEeE8/GhYNuaw8VU5vZ3zX1/PpZIyrAAk8DjI16yUVUjrnmlBvxR/gR8dsdUvKG/jTvl3uEpeJv6PUkg8KvVF3hbv+T66Evj1E8Ann6nZYua6sUI+ZjQ4Oj38kQuni8UKPAj0diBg7QxenP/wWmCcr/JX9jD9LcvAOxnrvNtvTwiekEME2TLpKizTX4VG3QH8b/n/4Vb5WRRoScmtnYOLZzh1o6VD3XySAcwrq0T13KFtgsVOdK7wDUQuCVZWBz1vnxrwQu5slXzHDy0gu2IBffOfNEk3aIY6Kz9HhwurHTIF0oPpNXV7RPNL+3HUlP6mHLWktS8N/AI32p7CsbY42V9+4IGHVBuuZt7lMI8YM+SH52ByN1nqzjjL6HKtokH2Qek6Du+x/SIfQlNo6UPIAVlsVMVKbj+NkhMS+unzHppwDPZTBPTWYc9CCcCL6eV9w7lzsfxHG4Y0oCP8R/Gd9h/gUttLUcszMgt99a/AOjKhGTgGMJuNK4J7enriZwe4+iA1fwJzgYIpkxSUlqhLZpmIf+Ubww4JXqiAFzXfvhuy2yO2pL+TQHx6uLPQa/nP+HPrhObpROabcrQZ6vHjUS/gpfJvY+mJr6PBo9b793Sq4OlI9lU0zc86G+LSa05vZJbqjrEmstLbLgpe7vkXTv0Pf15RDIyNYes6+6H7xaPCMfEYTfC3tJqSnDRdtgC8q+Y1HPGNxb/KvxRADqVtNS/ATeO34pmqpTDmGfDqG+rnJZOaxApMuWgcj6ytrRXRjIFch5c8YYIIZqZx3k9NGSlWcRZ4Ygf+v9wpbFqOyHw3lzJwSADS7OKyxVHMUqZM4A1/uvBI4IcCyHvlB1GOzNeh9kkmPF79IP7V/AT2kvjR5xegeELseBAzGyuNlTsLDIVzR7mG3hiZXp1nFgBatXWExtfRQ1dF14QMkusE7qL5QlH+No1T6XClQKEKzpwW7eViIH8euA8tvjF4NPDdpHZfQuP7jZfFa+nk2dDFiFB0wowXcBbp+tPwHGaSEVdPgA6W21wzs2iRWrNQmWRrKU7DqKurE6w1CCA3m+a7STXideM1Qu/hg+8YrgAuDAIYU7agD/fIv8Yh/zj8KXALZijb0zr5JNsGeFe8A0NBIYoapgz6voOY9VuYCAfCWbe7UYVVGBsF4pw5pME+ACxZAtx6K/DggwBZPFHyLJbyxlVLok5R2/uopzeovaZ2/+NIUZ4xlcxOHe4mKtQNRwDFrofTpyTTlPy4Wf4ztvlnYrV/Ef5J/ivZHslDZxNe+qkm+2YOMtoZvLcxAV4MJocDxLyDIJ57Lk3/O6IrhZhbnHcesHQpscIkgV4uw+Z8Vj0Jvm7Ne+dJY9eDL14h/OpcgH/1sAKQZhTHeBo48jCqLg2SVT7EK4HrcdRfjwe8S1Hnjb0v6RjXHnjeXiGWiywaOyll8AaCeP758UNaXDn1/e+TMjI6/v0GZaGSV4gTmi7Zn8Y6CPPmiHR9mebfXcONAmcKNjE2s/S8OuUEbut4CK/vH4/fHb4A1/c8gdJAeBetsz54VLhkihunRS1VmQp4kSAufnwsmpvj/4araL/97fhRey4G5S7nF+HYMXUmuNJYF4/H5oqLoSMqvIwm/ZjhBKAgizGjM/U0qJW8bLDP6v8IP2q7C+821+KZw/Pw9Y6fwfPcn4X6XtQwNXRMNwpSBi/YdngrcONvxqKlJf5veBXdW25JTIUSyWGXSxHLIvenuRLJ5y8SXIDRv304ASiqVEaOyOxga9/gil6dEsBM13rMeuN+SB4XLKPHEwsN11KsJ1HC4NWSclSWxoIODOIjzycuY5tJ/GT8+ARsNF/VSDk/hmWgN42KgJoqdQEkosb/RVQoDRcAxePWZbgeQU+cyFshKZQr16jvi8dNjfquizTyUrL2rkEzrsNegjI8A8qTALr6SBmSZfHPmpUAQHORSGdt1+Sg3Zk+FQYC4AWrFwwXAOuCsyvdxhn28ap5Dx5UdwM1FpUirzza1cHg9cMojHa2/wLa7c/FcdJ0E+v2ZQZPUlkdTw4KAImd681mtGomrSPNFbnOnyP2YOSbvHm4ACiYZ0UG1dE8e2P5anmXUC7BEoM5QPMUg4BWGgFJGO1vqiJYgHeEoO1I4IO1wIdbz+lMuujAgQOJNdFAfhkOHVE5oD1NAHkDzQXn0TTQYwmxUeNwAFCQRyYV0tY42/joFTVXlCV+Yf3g7QBq4MTnSbcMUluq4H23YQ9uXZLY7txG1/344/h+UjbsJUsJ7DZFuNQ4RtmXZl3ORZ8TbLQo6AA5bQDSDGKJbuKdrU0ZzKV47HP7TrWOsKBmFPT55jh82yFAPDcN8Jbe4wtv4hzrutuBp55K7GERVFikspvjWmy+N80MGlZkCvKF6/ba002BwndlMad/IKdM+GMQA3v412vhxKL6iQnPUUmS8HAWwXvySbGma8KmaqIW4ZHRFudBb5qbaXNcc84ssULXracbwCKVtWQg/+LIDl7oiKMOXBtRMKI+7vF+uuUVaMwaeB0dwOLFyROQg3JQtlRg9x71x7wCVbrKzHnniMlSSFzsymwA+P8FGAAftXydC9CXGgAAAABJRU5ErkJggg==')
-
- e_grimace = ('Grimace',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDAxMTY2MUM2Q0U5MTFFQkI0NTI5NDc3NjMxNDc0NDciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDAxMTY2MUQ2Q0U5MTFFQkI0NTI5NDc3NjMxNDc0NDciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MDExNjYxQTZDRTkxMUVCQjQ1Mjk0Nzc2MzE0NzQ0NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MDExNjYxQjZDRTkxMUVCQjQ1Mjk0Nzc2MzE0NzQ0NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnHJL3EAACP8SURBVHja7F0JnBTV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')
-
- e_guess = ('Gruess',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM1QTE5NzI3NjZBMTFFQ0EwNjdCNzEwQkM3NzcxMUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM1QTE5NzM3NjZBMTFFQ0EwNjdCNzEwQkM3NzcxMUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzVBMTk3MDc2NkExMUVDQTA2N0I3MTBCQzc3NzExRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzVBMTk3MTc2NkExMUVDQTA2N0I3MTBCQzc3NzExRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiscrbsAACzoSURBVHja7H0HfBzVtfd/tkir3VXvspolWS5ytzE22LTEQAwO8CBOAwIJhHRI8l56f8n7knyQvBAIhJCEFCAJhAAJzZgS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')
-
- e_happy = ('Happy',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDc4QTIzQTU3OTk2MTFFQjk4QzJENkY0Q0Q0MUFDODQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDc4QTIzQTY3OTk2MTFFQjk4QzJENkY0Q0Q0MUFDODQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NzhBMjNBMzc5OTYxMUVCOThDMkQ2RjRDRDQxQUM4NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NzhBMjNBNDc5OTYxMUVCOThDMkQ2RjRDRDQxQUM4NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv80eF8AACEwSURBVHja7F0JeFzV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')
-
- e_clap = ('Clap',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUM2RjJGQzM3NjZBMTFFQ0E0M0VFMkNBNDBDNTI2MzAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUM2RjJGQzQ3NjZBMTFFQ0E0M0VFMkNBNDBDNTI2MzAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QzZGMkZDMTc2NkExMUVDQTQzRUUyQ0E0MEM1MjYzMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QzZGMkZDMjc2NkExMUVDQTQzRUUyQ0E0MEM1MjYzMCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk/GOPYAACMNSURBVHja7F0HfFzFmf+/t1276pJVrWbZci8YN3ymm4CNgSP9wiVcSCAJcIGQXI5ckkvu6IQLSShJIBcOchcOCEeHAMYF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')
-
- e_idea = ('Idea',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RUJCN0VCMjY3NkRGMTFFQkI3RDFBN0ExNDRFOUZBNDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RUJCN0VCMjc3NkRGMTFFQkI3RDFBN0ExNDRFOUZBNDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFQkI3RUIyNDc2REYxMUVCQjdEMUE3QTE0NEU5RkE0NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFQkI3RUIyNTc2REYxMUVCQjdEMUE3QTE0NEU5RkE0NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PglD/LAAAChqSURBVHja7H0HfFzV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')
-
- e_joy = ('Joy',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjBFNkMzQUY3NkRGMTFFQjk1NzE5NkM4MjcxQ0E0N0IiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjBFNkMzQjA3NkRGMTFFQjk1NzE5NkM4MjcxQ0E0N0IiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MEU2QzNBRDc2REYxMUVCOTU3MTk2QzgyNzFDQTQ3QiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2MEU2QzNBRTc2REYxMUVCOTU3MTk2QzgyNzFDQTQ3QiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ph9nEOgAAC77SURBVHja7H0HmFzF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')
-
- e_laugh = ('Laugh',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjdFQzYzOTk3NkRFMTFFQjhBMjhDNURDRDc2MUNCMDEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjdFQzYzOUE3NkRFMTFFQjhBMjhDNURDRDc2MUNCMDEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCN0VDNjM5Nzc2REUxMUVCOEEyOEM1RENENzYxQ0IwMSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCN0VDNjM5ODc2REUxMUVCOEEyOEM1RENENzYxQ0IwMSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgUBlpQAACOLSURBVHja7F0JeBzF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')
-
- e_love = ('Love',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NUJFREZGQjQ3OTk2MTFFQjg2MjRFRUI2RThFQzhBOUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NUJFREZGQjU3OTk2MTFFQjg2MjRFRUI2RThFQzhBOUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1QkVERkZCMjc5OTYxMUVCODYyNEVFQjZFOEVDOEE5RSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1QkVERkZCMzc5OTYxMUVCODYyNEVFQjZFOEVDOEE5RSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pp4lEjUAACvlSURBVHja7H0HnBzF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')
-
- e_no_hear = ('No Hear',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDc2N0E4QkY3NjZBMTFFQzhDQjRFMzU5OTQ3OUYxQ0UiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDc2N0E4QzA3NjZBMTFFQzhDQjRFMzU5OTQ3OUYxQ0UiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0NzY3QThCRDc2NkExMUVDOENCNEUzNTk5NDc5RjFDRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0NzY3QThCRTc2NkExMUVDOENCNEUzNTk5NDc5RjFDRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnMOIAoAACkuSURBVHja7H0JdBzVsfbXPTOaTftqLZYseV9kDF4xxjZgAyYQgyEQw4OEQxKWlz8bgfOSvKzvD++QvB8eCUlYAoQABgzB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')
-
- e_no_see = ('No See',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0FCNEQzMEU3NjZBMTFFQ0E2MjBGQTQ0MzU3OUM0RTgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0FCNEQzMEY3NjZBMTFFQ0E2MjBGQTQ0MzU3OUM0RTgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozQUI0RDMwQzc2NkExMUVDQTYyMEZBNDQzNTc5QzRFOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozQUI0RDMwRDc2NkExMUVDQTYyMEZBNDQzNTc5QzRFOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Ppi+AJIAACjOSURBVHja7H0JnFxVlf73Xu3V1Xt39ZqlO53Ovu8ECAkJQf5AosiiDDDggqCMjjijo6ijf3VkXPjpOKAiOsoQRWSTECASEZKQtbOnu9Pp9Jbeq5faumt/b865r3pN713dSST397v9qrpevXrvfvec8517zz1XUlUVV8rlW+QrTXAFwCvlCoBXyhUArwB4pVwB8Eq5AuCVcgXAD1SR/h4falMqbHTQR9+aqFp6feymqkRf+//SCv8VACcPmHQ6zKFaSHVqtNplGamyhDRFRZKqIpGqbsQNICFI33fSy7ZIBC18pNpAtZpqDdUSqmUEtPcKgKMDK44O11K9ihp5JVdFQVK37iflb0+Fmp8HZGdCSk0GEuK1qqPPjEaqhqgImrTzQyEgHNb+1+kjMSQ5DAZJJAkapwtobQcqq6HU1EGi933ahr5fQ+fvp5eHqb5LtYhAjVwBsC9oLFG3E1hb6LiGJElvIBCWLICyainkmflABsmgjRSkwcioUJWM0UpCp3QQSoQCxj++y0PEAQaXFG5dI4lhGbD3IJTySsj8GQHqIUD/Qqe+QHX7xZJQ6RIAjVoft1GDPEINsobAA4Gl3rQJ0pyZQGIimTLTFLJi+drRlEmiRVUmsxYh89VxHPAeo2MxATjx5oyltpkU7bFTwJ9eI2mthcxqmEB9kT5+koDc84EAkIBjYvEQAfdv1ChpKUlQbr0R8ub1QKoQs0VA3DzASihKhl6iQXrQQ4C5D5IePE3vL54WY0msJCv5yg7gr7uhBEMCzGP0/28SkH/+uwWQwLuXgHucgMsktajesQXS1VfFQ5e8iozYGsCce+GXfBVkqHaTtBWRGAQuOZvtJe39OinUl3dAaWsnDSvjED3fwwTk4b8bANnGUQ99mnroDblZUD99L6TVawms5E0E3HK6G32/Lk5GyEW8wUmcIVB7WTDlOgeB+Cbw1k6SyICQ0h/Rv78xUe6KNIng3UTg/Z5q/D23Q7rrTjt09i0acP0L2zYXgdZGXTriuaz8MlarpaRWHeSMvPY6cPy4cFVO0v+3EIiVlyWABN6D9BBPpaVA/daXdXLB8huBlJuIiAwgcW27qO4kNdk5vNoifz0M/eCfSwN/blb9MA8hEBb4yPsfu5r20K2XRRXG8ZNEU18ABz44SaXeSCAevKwAJPC+QIcnktcvx9YHF6Cw4BYYiUkGiXxyjZDPzY1c0enHXxyNaAiZ0EEuYAiGboBUuk2XlCiux9/x9RlYmdgSDw9kKHSXEcSrnj4AW9EpniJJdYr3/H8+n48hlxv6gBtxETcCzU4ceeawgrraTgJyI4F44LIAkMD7GB22GbfcisqHX8QnM/WI6zdGEiGV82IrsThnLLy3S7ekBuqw6MvXqYaacpbElQRi+SUNIIG3gNTmIcPVa41nvvY36Qs5ehj6/VqYEPslOcnHO/CBKFmd5Zj78CpV52orJUlcRiD6xntNeYLAMzJhiSSnG4998WXpkxkXgsdlm+ODAx6XBmsBGr63TSKTwOO534/FNSdqOumL1MPmeb73tLQ2PR3JhgtPKCZDv9eND1wpzt4M5YHP8MtHqKMvu+RUKN1UKklfpe6GzfHvP/ImvjcN0Ed/hYmAnmkJsc1nahrgCZKRJ8qSqLoEIWAiwCSAz2OWyFWnRsT/uCTALQjFYCyRP0tQR9crmER5pPgBP+siU0ycOukOe5MpD90Vf9cfvVMmXD7JIr7jQqI4v5Pu1KkkoFO2QZF6jL8t3I6VnyhQ9e62d3e2YP142ls/AZ3sYZK++H9cW42f2L6CdHUpTGpAsDVd1+C99xju7nzqEnLeJs4nPFquHRlEry4RXjkJHl0Szq01SId24Drq8CvH41roYyx9BlnGZ6fkQL1j7lkJiXb6r/PCE9veGloqCGcfuWmhsDbd4w9o00A+MvkRhSSjn91UVG16aKBrDFZscf1UEWmJuH7eiY6ExmwGeEbEZKTXJmowajGrRZueirMOo97ommb6no/u36p4RbWjTnw2fQFw6A3qOioeobf3XCoSuJUocsaHyUeHley0znbhGZ1ntXFNZqHUyHvJI3pvH3CukqB2XwjEpV66gExNAebNok68Dpg7q+dzk0EDsH9JTACWLIZ07Bjuoo7/RZJCx6UA4F3UW9X1V5OxiB/EPvMoC7T5tR/8N1BbP1JrLWm6aKJL/98Z5nd5esnj1WpVjTagvYoe/YsPAcmJGoCDleV03tGjAoPbqP78ogLIcSj0rDevWgrJYo5KYP8SIo+94yT2Hwa+/aOe2XFuJMWSANVggspdWtLIsa7DCSmgDalZk1ORkJsPo9UmxqX8rla4z1ci0KERHNVkQSTBjogtpQ9FU+ULoyukiGaLpRCRJFczdN52OlGBRDozMWsq4tIzobfYEKbf7mxxwFVXAYVvVmdAJC4JqtEizhffUSICRb5POaDp9gNFRDG/Avzo25oKHaxMI4JnJW5EpuGOiw4glY3UrsZrVtMrYxYZjuQLz3Dtwfk6Fd99oge8cHIWwulToep6uqrO5YCxsZzan7zdm2/HqptvgzEuAU1NTXA6nWQDOwSIemrwoLsdzWdOoObIPvgd1ZA9rQhmFxKggxsoVa/CQOfq2+oEDc+euxgZc5ciaUoewoombUajEfHx8bDb7Uik45nD7+Od3z0Fd0szIvGpCGXPpM7Rt/kYQENjBeROl5j0/Tp5et//5uANxqEfixZB2r8f60gA4kmNei4mgBv4z9KFLC4FA7Qa9VTnHvzsGS1UQQhk5gwBYO8iGrblPOzTZuCWf/oavGEF7x86IsAbtCRkIuXaW+E+cwzeitMwVx1HIHcOlLikAXWeqbYYMkm3ITEVifNXQk22o9EXRmPZ2QEvbyUxycvLwz/8x1M4suMlHHhlG6TyInTGZUA1WyFb4iBb46CY4hCYOh/GulLoqCOxSn1rF1A4b/BbL8gH9u0T/jhZT2wfbaPrYoVeYTx+nDcVaR+9hd4k0b2Yp/Y9wXscVaf24ulnoyyRVF0oIx+yj/w+dwupsTbonU3QtzegcPU6rLjzEyg6eQpnz54VEje87ZJhSs+GlGRHoKWBrtMIhSRF1fc1Qsa6EqEy9XkLkL7sGqEqhyuhUAgOhwNny8uRWTAHc1esQeWhPdCRxEmhAGQvMe0ON1S6lqTTU8dJho6eRSIVe55I55o1mikdqBD+2L1bvGys8GHnRRmJIfFPILMye0GX2TNPG0B97uawgx6ab0uGueIoTCQthuZK6FtrCUgHpi9ZjYT5q7Hv4CG43aMfqrGmZSBSsEy0mKG+rG9vpUbVedogEXjGnHw6ZXSPH6GHLC0tRUldM1Z9/EHIahimgJuqC2ZPE6zniqAnDaKSao8kZ4rvtLYB588Pfs14cmfsGcL0r72YNnBxlzoQzMGY2a8Lt4ugo3f3RbUp9VIjgWY0mnD1/Z9DzuyFaGp24MT+3QgmpKK+sXEctF6G3kQsasZiyGWHhSpjm8XeuqGFdBrZUp8lCek225h/w+/3o4pq6srrUTB/MaZOn04kxof9Lz+HmtPHIAf9CKflCFPA5cRJYOrUwa83dQokRzMWkSDoRhuqGKux0KX8h8P+YEjtG4Qkxp0OorxSRUPUjDFziydW+Ykf/RpxUwvxzt59OHWmDHJyBonJ+PuUxWKBT28R12KpEw/a4RLqDmQbdSQhev34f8eUnoPzTQ7yZQ/hbIMDW7/0bSwn0sWaRNfepLFVBvDE0B5Qbo74nLl74cUazJ7L7H8qxyIZMwZQn+/jyIkel8FERv9j33wCx4pLUFRURLxCiakrZzKZBEuVM6ZD1+kUrSNcBSpBvUl8HuvCJGv7669jyf+7HfPWbRa2XIkCyD7iUEolPb2nHS8KgIRJgT2N+IIuKoG9i6+KWq0RRcd7Bghv/cJjOFF6BtXV1RPii3dJlxqfIlinHCQfzU+tSCQjQu9jIX2DqdadO3fiqjvuQxq5JDpyJ7rK2SGmb5N6PK78iwIgSV9hbnZ0ZsOQ1vdD9z7hNpws0d4uuXErXIoONTU1Ezi8pT1WRK950VIwIJx2KT6lz+cTUZixvrt7L2548FHhx3bRz/KhAEwQbchKduakA0iGV6JOnWXvwk2X0Nf38xShuJTHPSVY4xMxdfm1OHXq1ORMMnSxTCUEKRIm9W6JKoGJHZLzer0oqazBylvv7DZ+VdXasNtg46lpWt+acjEkMI3NTUqXz6zrNbfWWSrCAl/aoanO5R++G8dOF084cOHuMbqoiudGpCpFpSESmfhobraJcdPnIC4pRUghL6xpaR38/MQkcXuZFwNAYYKTu/R47xkI92ERsVx0XELWzLlwyWahYia6BIPBKHBK1G0xCIdejY5Vdn0+0eXMuQos/NBt3VJYP8TAPQ98kyTmXDQAE7sETx99oZAUeI/i5ddZIlTYF6yAY6guGMPi82lzUjq/tmBIMWvDXEpbozDUgUAg5sx3QBXOwaAwISVnqpDC2rrBz2W3lG4p8WIAKKZGxQxEbwnsOAmvx4cXt0tIsGfDpRomx+5Ro3UPvTWcE7MUqsEMxZYMKRyCSVa77dRkFJfHg5TZi4UUlp0Zwnc1iVOMzCkmG0Ax7G/ucq3k6AvPYex4mydo6a6mFCI4CapT/Cw1GEuXWVKgdnoQTtLMSiSRFIWsg9ygTSa7XC5MVvGZkyAbTGhtlwYlMpaeyZPEyQZQiJy19+wNr9PzHscbuyTIRhMMGVMmpaEYuLa2NsEG5KqTZPeM3QDy1E84JRtqW4MAl+0ggz05bFgiQjMLSkQd1B+Upb4abbJHYvrx6BM4ey6EugYVluw8SPLkJMNoaWkRDNPS0S6kL2SfLqSu20dLzRWTxlL5Uejonvj8/ox1ooold4Y4FhUNNvzX/dJwEQGMdiPPoe6ZB0tO/qQ0EM9csESRtYNafUoMYEdEUFXvp9UhmEW+ctAHU9M5IbGNjY2YjJSb+rgEMf9YekZzKWI2aBHzO434oXp55kGCzhIHY3L6hDcOExKerzOSHpLKDohB5FDWwIMaPMkbSp8GtaUOVm+LYKSTBaIlJ4/AIzIz0LyxevEAjGjOcfRdx3GcqwiT06rCnDltUkhLc3MzjDrqMGf2i4ndwJS5YspqUEc/bYqQTvV8KSw+Jzo7O9HQ0DDhroUl2h7FA4xl9AqBdE82gJ4+N+Apwt5DXTc8dUIbpLW1VYBnoKeQS/aL/3FIQ9c0zpDOfvZMRBJIO1SdgrWjTfiOdXV1EzrQoLPaYEhIRknphWxU6ZHA0GQDGNCGr6J6wHsSew9q7NOYYp8wtskSwwFOJkmFrmSfGDMOTJknHPaR2msOforEp0GtKYbV0yzAq62t7R4ImIhipk7tI9eqqt9EjC+6nnW0gU2xAFCEXnuifnGTQ0FVDalPe+7ggSDjKNzILCms9ixKEHLx+0Jd+qcthGIe5Sw75wfJnaW5F7VlsBCx0Ya86ifMTzRHXaqSkgtVKN3OqHtOLABs6w3ge/u61EU8Aq2NCDmJ2vs6YhKUy5LBEsIgWjtagTMHoVhsCExbNCK1OZgkcnAVuxxqK/mIlcdg0GkuBhOjWJAbznYQ9jgRbGuCEg4J7XS6uG/n5mxR5Nm0jZrdxsIUiRvwiBQbeOZ/o6aw7Fi/zi5Bb4snKp1OqjVD9ETZZB65mJO6ZJunp6c0NJRBbW8SRCSYVdAdCDyeEmYfkdSvsf4M9MV7oStcIVwTdvgzMzNFGMYIx/JExw046hFsb0bE245I8EKz1h4Envw5cO892joNHvQny9A8Rsdt7GVTqpapaFYBdKVEjwtmJuEjH8mlHlcKvy8s1jp0kH6vbwSqzwO1DT2AGtOyYMufK2JLhhrbZEkQPp5Elv/sYUhkcEMZeRfElMbEkw36YaorgeTvgJRbCF9ChgCPQRwqFCPi70RHZQl8tWcRCWiLIXh0iuOEcjIBzuXGzjovjDHE56OmVsIfn69Ahl3Fpz4J/PKXUJsceIts4IcmFUAum9Ph4GxLq6+djcd+9BCMzU9pc4EDFBdJahEJ524ijfsOa5OcxqRUJC5YIxzdPo1Cvgn7aAG/X9B9lRgjq8pgzqzR27tRjX0pMDRViNhS2JIQnr5QRGxzlLatXzSbGgmTtjlO4J2mr6nIpT51/bXAmuVA3rRBaACPF+c8gsNHXPjqZ3+F2YViiE2lx32aAHxwVMw2BhIYTzf5jfSMZN33n34UFvefSB8cGdyIm7QHu24tffc6bYlBSbEPnTVnxRtTaqZ4ao4vYTKh0FOZG89CbahA85rbcOrRbZDVCKyOGm2idiKKrEPboo1oXbwJCaxOm6ugo/tydfiERrBGB37ZvrftfxP+5jrMmKYtaHn4fmDhPCA5aQgOx5EK5C9nz9tKUq3Hzh3lYr6ZPnm5wofdk61Cv0uHr/74mYcxf66BdORPRn2Niirgh08C5ZWkZrKmQVewGC2tbWJdvY5UJkJ+BDNn4NQjv0Hr3KvFd0yuZmQeeBX2ozthcjbGQHfK8EyZg9Z56+BYuB6B6CC4tf4sln9jI0wtNSIguNOcKMIWk+UwXEffg06K4JNkx7bcqIVGjKrEzSdT8BAeuv3bqK1sYl/w0ySBT08agAReGvWymrw77rR89LHvYFf1HuiCdbCrzZivnsJctRiZGFnjsp1//Keaao0kpEHOKYBUelDEdgZyZkOxJoiZ9dKPf4tAvKbPd211Z5BcdhDx54sRV18mwB2WtJAK7iAC1EG+oJtUpDN/CcLWhAtU6fSdTyP3r78lclMmgoSljGkIEojGmpOIt6n47leBWQUjay9edl0mFeK0NA8VyIdTSsLynKvhdbThhZuF6ftvAvBzkwngN+jwrc3vnsUZUwGeHgCrDDThemUXNqpv4xblNaSJpLgDl+om4Ge/Ao5HCSyvMGLnnGcQutuUuvn5Dffj/Pp7taVoA1HrTjeM3jYYPW3QBXoyPil6I4LUOQIJqQTW0NNu1uZqFLz0OBKqT3b/r2vhjSwTATOq+BypzOtXa6uMBnQfyEt7T7oWb8mbsVO6AUelJVD7NXk+EfEvk8u85wub0bRrp4NUaQ6BGJpwADkMnKME7BtuyLjmJ29J3yOGWT1MdioD3dfNynY8qPwCm9W+y6x5te7JCm059X/+gEyEX4a/YOWgY5pekpyqmz4L54ylsXW02xuQ++5zyDi0XVv716+wm8HL3z5+J7BgIXGRNCAzpe85dVIOnpQfxrPSPTgvDT8XygAm1r2Hd7bwAiXcQQC+MBmO/HXUWzJnP/jPEgNXPYLUYpzx4WX5w7hR/yaW6I9iu3Rz92dN7dp4YLNDczvEENcQA9I2Umnzf/V5LHryQWQU7RBSN9Zi6HCKa8z/9aNY/oO7hG0dCDzR0VI0l6e8ou99c2lAFj6j+zny9JX4nvzVEYHH5V0XkZ68q6BLFD3hnklRoSSBv4Te8Kmth514yWnFLufYrnOTugM/Cz8MV3m1SGDw3Dbg1GmSxCnzoVrj+0zIDsn8SZ16c+fCkzub7NpMUpPpRETsUHqpXx35eDry70zuFpjb6mBtqoKttlgw2gtGiug983qiwdqR3AU1FKIahNVVB33Ej0cf1fy7XLuM51K+gH/X/btIPzLaYiIx+uF0oHLbYzj1+HdD9NPpJIWuCQOQs1GQ+nRMv+cfE5f962/wZWKRznFMbCe0l+NrjZ/BvIZd+AkRmZDBCp8lrXu8kpc+C4pHVSwJY37eVcX/pGEfRVWV3qPhPUcGStWOQpTotQBsCBdFFwkgrqMJq8n+XXNLCh6z/AAH8x8Yl+r+NJHemd6T2LmRV8jiAQLwNxM5lHYNp/e/+rpFkP3FKAx5UYccNEkZQ6Z/HKy42/34svw47qrixIZ7EDQm9JWEXmEPl0JCvIjOhIjehIOHAnh26y9QFcojvU8CEzfqqEAkox1ZagPMXg+WpsXjXXJRAj4fJ32fUAA3CvU3tROpnn/D3WEtPTSDVynloViaiyPSUhySVmC/tJpuMXnwK3WQ7QoFYJM64Hj7GFS9mRrIiEu9BKiT6TodmOo4jio7AdjuGBJAziK1SD2OlepBUeeppzFbLUVil6Z0k+q1/ycOr5+JXW+cuH6kawXHBCBprBuypqSrKelpxEPP9LpYGDPVs6Juwatab4VOAPmWtBnb5I8LP6jvKLWWHmVZ/RuQO73otNpxOZSw3iL8UsMf/gfy57dAYQnk9Ye9bC4n29qqvIIt6qvYqLyNlKEmGzgzcaARq66di7d3nODxupVU98WchVLP4J1RlqzfNIdwJNXmrxxmrC6C1ep+fFP5Fs6EZ+FAeBX+QflfLe1WmNwdrxN6KQL973+rhQHqzbhcSsAQD7muFsu8e6OdUfNx56gl+HXkATSFMvBc5G7cofxxaPC6iq8ccxbN7no3ohxqY3EjuGfI85cWEHi1PNk1ui+T+ng2cg/KwoX4iFMbNVrq3gO5qUEEG+nT7CLjA+RLe18uSc9xppnimPTa78T/st2n8ELkdpwKz8f9ym9gG+1eIARgalYWrDYx1rp6omzgCv4zpWAadcGyMTdAvlqBb7d/FteGrsKOl50ispV9Lx7lkJJTxSi7oO3BAFU/1WAfMjO5aDFgBkhGEySTSTtGfdSQLx36o0dw34Yf41MpL2Gh108dcIy/468RozrLV+dh967TEweg2WpBagbxXsfbY26TTjIXfhLetLPvg+y55lA3VYgqFqNYE8X4p2JJhBpn62GkIQaS/bGw5puJGukVFjcOkBgUclm0ox6SwaABxyt6o1MLUtAHnaeF7LVb5JqRwkEtUd5r22C+D2glThY/VgBDTWJPjAVLp+G9t0+nk7maQkTmfEwBpJtdsmjZFG38zz/2vRzao6E7Bw9E20bSppaEXidnmyvatPVYbBs5WEkVq4ysUI1UbXF9sjt1ATzg627nQ7rgYfoce50vUUfhVb2y1wUpwPcTTaU1wAgN/9TZMm39H7eLqo4xHIgbINCAGbO6o/kWUY0dgNQjzHRzUwvnZEenEMY+jeMk89DWDpSU0k0ky7DkGRB2KzD6IjCHFDT1mlDgXq6jio72fhZcJ0ZaxGA3gSzWAZLkiOQ+siY13bnS+BhtfLFal0HiY5hX74bEyiVx5KXYocCwMTw8tpBNzdAUJok1SghUh0XY/OYbAI8PSBirFFKb2nOnd71jRrM9lhLIF5SmzyD1GSYRUsYWfhcIaerz6NGo6kzXCTqlT5KxcLGKm5YoIidoJRHc6hpe7Qo0NHIEdv/hfrKZPNsQ6MREFpamFHJlMzM10Djny7SpWh7Rn72pg9tHfLw5gv0HVWzYALi84wCQ1Ghy2gqxnkRVlGGzVowWQJEJM2ta1riljzv44SKxtBhKQg/jTLVpPT+OiOj8+Vrt9vkJ1MYmDuglFdwerU4OeNI+G48ZZDB470G+H15tnBw9cgqQDLu2H+FAJS1BFQDq03Twnw+j/BzdO3lCU8bqzpIvaDDokJWVoNbXOWfFGkChnJN4QXx47ClCeGcTlixu+LVXAyd6ZdbVDzF2zaDOyNfqgNonqAHJEV4cYM2xRWxWeLKYwWWQ+PrMUfg1L0rla3KExFgzj+ijfc+QIiNYq81lzpmlaRnTWNa0hjV/cer0eKmxwZkXawDFtmJxiWlEI4+NGUCvT8teJPzCZUApEZlgV/rJcUiR2LXT2Gu9/iSUUPR+JYOE+FQJJ0+r2OLTOqkpcSwX1ADMzIxjLZUx3JDaaL3lXL2BCIdF391TRn1/YQ2kE6c0m2InVTMlrWemoNV7ee3L3NbrfgtmS4InVVRobtLYRsqJW6hhZGRxYluBT0YsR2LSk+Kji8xDbWPusWzHOsgOzomOGs3J6QGwqvny2RmdO5urU+omOlev0JqG7WDnmDebo2uEnUhK7o40t8cMQLrJJFt81MNROscsgRXR2eyc6D6P83IjsJm1h3dSg1Q7Lg8QT1T3GOy5uQqy0lRkE787XTJwovORS2EnrHHdrCkplgCm2GxRlTHG/Wp51v18rdZj//A81Fdf09yEGxb2DJO9c1o3KfnNx1OYeR4+pwHIZGXdnDDOlGmLVDxuUq3OcVyc2jYurntWIzFmJIYaNcHYtQ3LGH1AZoNtmvYNkO988sABLN6/H3p7hqJMmxWW2yI61LfLeK9Ej3Vzw5ckeNwJXz2kF+YgxaoikRjYz36qKmQWWCD4pvXjyp9AbWsw6kYkgWNf3BIZmwTy5hqzZoBHWozBAJZHx7nKHPS+uSkynWcQzfGSciYsy0qbhClZKtLStH0WpIvIb7o6nsNBN1snw90YgfdcWPWEVL4rRZYEU2QA9by3/bSs8anQvqO0sR0LHVexkmb4188Cn/8UpINHxO7P0oEizCRmyqEtXpLyQ36P2ll9IrKg8him9hq6UtmhTk2DlERKJYEANVu0HVV4zQlXdiH4fdfoGathg7FPCg/0H/fmKUnOphjsqgHNfrE/6XYBLrdQ8WJj464hVUkSQTU8ksGGioN35NxsyLwmYt1aIDtj8jrWaAEMdtsmaXwr07iheYsCri4PpHd2A2+9A9u5Km0ik5qIpzr+BdoC0jnU6LPqGzCzuRl5pMJyohluJ7TIMlwc+0q/zbPWPHfGo+sciHoz/X621SI2OcGNG0YenT2yHzb1XpfojyWAbW6Poi0hkg1AjJL+cZ61rTdp9XQp8NLrwN6D2EggbqQGPEjPwlvT9Fl0wYtqovahf2Xl9Thno+DM+NrAdS87LiLZdCLJuhQOctLS70c7yQX1LYe2YpajEOjwTfrqd+leTNmZ2r3ecF10k5OYD77qyM3qprFtsSQxDpdbLRB6WTJNSK+fN1urTWRr/vAy8OZfsYIkYA81Ikdpfb5rDXn0yPV8P2A5mvbxiDVRLJ0erIh1DpGQ7y8t6pDbqNH1PsobONOzp+VPA+65HVizYoLtsWyG19MNYGssJbCypTVyVZjol55TKwfrJ+wZMtIJrU8DH70F0k+fBo6exP3UaGupQTcQeHW9GpjtEGuFrh4lEsTw0jOeGhrcXRYIJNH3p/ceieQG69oalT77Dh2+xlOPn76HJG79JBEpfQqqq7r9kMpYAnicdPPdbWSI7P1zY09QySGF+P2vA9teBH77PAqpAZ+PNuxHqDXXk1oY0ProW2pEHa6fDNRAm9KkBrouZzy4Op/g/c5XIKVNzuNqpNOQjNLiVu4s9TtbYqhCEQ1zK9p7Ah/aNHnhf9zr7/4o8Lf3gZpasUHGG/RP1ZScLplS7NCZLJDHOJ3gk41QulMzE3GIhKB42rOCtWezmKJ+5j6imZMGHkTSeLcrgONHOXsU3os1C91LjXniN0/tWjB74Z1S3iT6ZcVl2hp7vSUOSXOXIS47T+JsD+Mt1nBYLOMWSe/Y/eCg4tQ4YicJUEv2i+3kFs+fvOf0ydPxwrM7ENGmZX4x3PmjWmJdQZYh34Lzfl/gbo8ngqyMFiTZlD5+1kQVtoN1DeRjrd8KS8aU7qiw8bsKslgyzXln+qTa4qyGHU7U0ENvuAaIt038M7YRJfvroTT87inekVV9m2zx/48pgFEQz86wIqu6vHG5o1VBOtkoq3mMk5cj/c1q6oq/pd/Jno6EgtiLQxeIXdvadRejGWpLvZgQXr184p6PhY0Xt+4/Cvzq502qElFb6TZuorZ2xxxALgQg77K1uL4es3hqKD1TmybiYTJdjCcSuD3/6xltADx9+XVChU6M0z4AiGRbJXcLKsoDuPaqXnnBY/hsLS7gHJH5Q8eIpD0rIiQ76P83kvSNKL3/mACknhEhEIkXIo8I6cKSUqiZ2ZD8YW1gkyUyVmr1BNm+Xz9L18yahsTCRSNvHHZVR/lbnA+Gc8H02e6OpFBpaRCRZmtj6P+5O4n+kkloII75JonDa6+Jm24m8DYReIdHfM9jVmsaiK+wM03mY+PBw8IsSQnJPTGfDOR4HpjHJJ/8Hy1dv33V9dCZhw/1qkAytqMQB5CLJtjIq3cTU+ubGpC3Pp0zR9uhur1fpCJvy8OVbaImhVYhhdUVASxaTH7HOBkph1pUNQKNBNy5KuB3JHXFxWIceC+Bt5HAG1W4+7jyxDCpobqPiM3r7DOVl8N+9DhUm41InE1TD8zMOSP7aJc68JTNniPAH0nO49j2zVwwPFNFOv5Gfnk4+lhu8u3PIxF5aIchCuLWrcADDwBLlpBEkUOybBlQW9s9xaUJndEokgx17y/BwcRkC3mWfcE87XlGWzgSj+0cS1w9Hf+8HdhOrUb9hBMacLKITxJ4o14nHpMdPAnEBgKRV6p0BAJYc/IUjCVniLnFCzMCh1MLWjIS0TGMgDwy6GwXnn9Rm+y1r9wwrPQxeHtwYX5SH0FXRVKZLzlx78ci2LSp7+d8j7zDJsec9t6Li3PBcLIhscsL20JvG85X+FFQSH5h8shIG3fCVpemKh10bGoBdu2iTvmn7t3MeE+bWwm4V6kNxzSFHbMtWOkGFKp7CchfMwmnBlly7Dj0VFVeC2IliWz3RmNCuZfrByY8zMjK64CScuqh2zXmmTiM9A0GXlcJkBKtlpJw+8IW5E9TBxwoWLCA8273gMg6jUHkdM6C1Bg1KSRMkZWrSeFAO1TzqWwv6wmsKup8LjKnVeS/vvkW8OLL2m6e9HPsJ9zPbgK1Wdt42j1mAPYCsoPqmwTkM9x29MALSceb9+2H6vFC4ih4lYBrdmpgcvwk91QGjm1nZaNm+7b9njMgyshYs5l8a9OYwesN4qunUrAiYWAQuTCIZWVa4HAXM+22hyyFPg/qKzswcybP4GrR5Qw+axcGqoG+V9OkLXBxkG09RszylT9rUheVuDeoPkzAfZXaqCJGA28TWzalio1B7qMHfZB6p6CRaWlQFy+CNGsWkJN9IdEpIn/oT6RmmHWmLFg16LVrkUA6aHQ7tiVLfuz+p2LMmzswiC28ffjX++40xhtZiSy+AarFe5CdpeKhz1yoQThnKu8LUXwavGMb505gQfbQcz9HH//XSF2DiyqBA0hkiOrhc534ObHWl6Hlbc2rqED8oUPkvB6A2twktvjj1WKCTDz/AvV+UlnpqzZqGSoGKUeRBScs+DBKBds8h5Ror1QH7Zt+ksSckBPXLB84GRJHafOajOZei2vMRFfFJiG8cIbQ8NS3i9XUHObRQPatiMjWG6Qid+zQEppTJ+BUIewrPxYlJ2zjHBPRvnpMYqEH4XjsR0kqvwRtZvtW0k6bjxzDMpK67nuR9TpkrN4I2TB0sgMT8U0GK46IXBdcHPewDA0EbiZ9OjD1DQ6TyCojA+i9xSGr0XhiO5wAVsqaQYynHbvf59rHjvLcGkcRbCfw3hxt7utLVoWOUM3yvDYReuw2p2VK6Ss2QG8dfvDRCyNewhyCT+7OQcbgnYRdSNpAJQ2deOW+Eqy9avDrPvEEUNov3SmzUU73rEb3IoSLBCoUhJ5cjlC5WGawKNpBJ7VcEhG09OA888rzb5I5PXtE4HGxIYibye81RmM7hgMvhZyKH647MyR4f/vbheB1jdLExcX10NYkO5CeCympe1ot+2K03aUUAi2SkOnNo1tYx6BswRmsIkozHHg/XleK+z4++OYe770H/OEPg/9WN4C93YYeBpbzQQdQRFLqLKOft2Fbx4RmMPDs6MATw4C3fz/w+utDL8xlMiP1o8wRte/9f+AlUGce3fYBbcRCeexzKPB+sK4M9w4DXgoR2C99aeilaSJRe7+VnsImanOTH3gJFDZkNNNFEbr9N1AwKHgWojf/cfXIwCss1FbjcgbCxCFWIwy0B70uLkG5AiCrIOrhHN8y0uKAleRrcFdjsakV99w1tM3rAm/3bo19sh94222D/6bBcOEgqByXyCkTLwqJ0V9CAAZNyekuaoiqkX7BhIgpCf5Bt0jLsvnb29oGz7RH4AVJ2ow8YH78OOqJfXrLyzHVZhMdu2oQCUwkEPsEz+tsiaGwrPNpUYmTW/5PgAEAbRG88ZIqdcYAAAAASUVORK5CYII=')
-
- e_no_speak = ('No Speak',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkVCQkI3OUQ3NjZBMTFFQzgxMzFFRTI5NENENUMwNzEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkVCQkI3OUU3NjZBMTFFQzgxMzFFRTI5NENENUMwNzEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyRUJCQjc5Qjc2NkExMUVDODEzMUVFMjk0Q0Q1QzA3MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyRUJCQjc5Qzc2NkExMUVDODEzMUVFMjk0Q0Q1QzA3MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnkWjnUAACi0SURBVHja7F0HfFPX9f6epiXLtjywwTY22GwIM4wskkCa1Syyd5pB1j+0IUnTZqdNyGrS0CZNmjRtaPaehAwyCKSMQABj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')
-
- e_palm = ('Face Palm',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RjZERjVBOUI2Q0U4MTFFQkJGMjRDQ0NERjM5OEU2OTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RjZERjVBOUM2Q0U4MTFFQkJGMjRDQ0NERjM5OEU2OTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGNkRGNUE5OTZDRTgxMUVCQkYyNENDQ0RGMzk4RTY5NCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGNkRGNUE5QTZDRTgxMUVCQkYyNENDQ0RGMzk4RTY5NCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvOvxIUAAC+ISURBVHja7H0HfBzV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')
-
- e_ponder = ('Ponder',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTU4NjgxMkY2RENEMTFFQkJFODNCNEM1OENCQTU5ODEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTU4NjgxMzA2RENEMTFFQkJFODNCNEM1OENCQTU5ODEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFNTg2ODEyRDZEQ0QxMUVCQkU4M0I0QzU4Q0JBNTk4MSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFNTg2ODEyRTZEQ0QxMUVCQkU4M0I0QzU4Q0JBNTk4MSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmF7/wUAACncSURBVHja7H0HfFzFtf537xb13pstS3LvFWMbbDAGjB3ABINDewkE8k8lDiSEkEASAuFBIAnJS/6UBAiBEBsCNt00g41xtzEusmVZktV7b6vdve+cmbtN0q600q4sJ29+v9G9u9q9e+98c875zpkzM4qmaRhsURQFZ7KsSEACHdL1mkQ1hmoU1VCqKtVoqhaqHVRtVFv1rzbp5zVU66jWc32vXnzmrCn9YaWMRgAJKBMd5lJdQHUW1en00+PpVmMC+Tt0zUa6ZjmdntZriV75/DgBXPd/AA4etDF0uJwr/cx5dFuhjv+lJQMzpwE52XSeAsQRjNEkd2FhgNEAGLiqAhBR7PRIdjuJoE3Wnh6gswtoaQOaW0gcm0n8GoHKaqCYoCqiarX2C3AT3cdROj2k1wNUDxKwXf8HoATNTId1VG+mutTxft444LKLgDkzgFQCT2V0jHGAmdAzkRY1xhJihKJKCBq4htPNhThbXZSOk0A3CVNnMR1LB7wXBrqjUwJc10AiSHJ5JB/Y9zkB3+oBqpWabD+d7qD6EdWPCdDm/ygACThqcXyPLvd9+vkUvuyMqYTgucDic0jC4iNJvCYA4ePJuo0FQjIJrBDvF7RUUeufILBOAV3F8jW0gDUcg9tIVrSY+sGBL4APt5MENzgBtdMz7KTTzVRfJTBP/NsCSMDxBW6iyzxEP5saGgLtS5dAWX0xqcZMErWoObKGZumcxEuxkv5ro5ZsP0agFVALt464OuvullL66W5C7h26nXYnoIfp2Z6j078TmFX/NgASeCRGeIbqRSYTtKu/BGXtFUZEphJgMedLafNVWBW27aN6mCSsYtQxRJbQnXR7f9sAjaRT0SWTpfJRAnL7WQ0ggbeCvvoS/VT83JnA7bepSB2/CEhcLW2bV9VIrL+VunjzLmIiNWcN3a8l7rqJpHLjZm508dYeqr8gIN886wAk8JigPKVFRisx996lLJkWjXnJUxAbEkoMxgIjrDBpPQhBt3gt3ms/AHPDW2TX8nE2F2a7r9Fj/ONVJ5AfU/0RAbn7rACQwPsmHf6kjMvRih56Q5mTMRnLYr1bt3xyv18mF7uU7IsJPeT0NSNWayLvvV7URK2OvPdaJGjydTwakKTVIpHcNX6P/2cYhb55BVnCZ18Ctn4qcaD6ONWfEpBtoxZAAu8rdHhRzcvTjj78sXJ1Zjomhff/2Q5q8xdrSc+0Da+hFGobBjFFq0YaKpGs1TiP6agQYDuOyRh5lfwFca4//IXYbIkgOyXU9Df4Yx9HDEACby599FMtMcV87E+7lNVZYzE70ou9ICf7D8RJqntGtjFZdadqVcSsypCplSED5cjQypGFUnF0vGbVHshSSM+6idTqu+8JWbRR8/+AQHx81ADIPh597JBdNeVWPvsJ0rIWYm2iF8mzAw+Vjjx4/hSW1HStQgCdpZUiWytGNooxVisRNdVPT6GbnvVwEVBOQD73PLTWFuFa/ZH9YgJSGw0A/p5vBvc+iP0L7sYvyA83efnaE/Ts+9twVheWUAeo4qifj9cKkKsVIlbE0ftKYVObJDkvvAiUlYm3n6Z6my8Qgw4ggTeZHdmUJKj3/TYLkeNuhjFyuuCWdqIuPQpTE5N4XdxShe3VBWhBtLM2K0xbYoiaxKNeSUA7InC2FyZaDjDzcBJ52klkdR6HUnYckbZmdJGG/tvzQFGR+PhjBOAdZxLAN+iw6p71wNILs4Gxd3uJTbXTHd83YASFgXaAycc6JVHwUT5vUOLFeR1x0CollRRdMiqVNHQi7KwBN9FaibHdx5FF7pLlmWfRs2MXv30LgfjXEQeQwFtMh+1TJgK/vZ8+m/ktIHJm/x+ufoH0xydBaZRWRAkga4mPVijp4sivGeAqsljVSgqqkSLe60bIqAEzpqcWC+6YrymlJRaCZC6BeGQwABoDeA8/5D83XcMDAykE3vT+P9VFCr/ZxZyt5ELknwBOlciRAB4aiiTNGUmsNTJcHqPcXptMvm8iiiHUWjGBY8oD9E2W4DJF8FB5dD/Xj22IHBEAm01JOH3f35WsW5eFqLD9jQRiwWAGnAMCIP0YyR0uz82WQ0CIWQKv7nrtRmpYOzo7yWl/Hdj8rgRu0KTB7AYwHeNjCTQ6j4mWNZbHCiPlkf/H73Gn6K+IAIFWj5n43CvYbJPLlQxyLrIEoKVKFgRNUQRtEa/tvgLvfpTjCUuQ9o3bYfrzY3Po5deZ5w2oFQOhQgnA39Hh9ru+CyxfSq2V8xB1jei+H2w/SpTr9yg4Bdz/KFA1Ar403zKDyIPA8XES2IQ4CW5CPJBELk5ivPyf0eD/9ZmUOUA9peQ4gS1SxolaiTS/rhdBxGbhrXmaobGulqDJJinsDKoN5PQHersiIhyJ/3yKVFzsNCDzu/1foOQBnDx6Gnf+XA6eOoo9PBq2yHhoxhAhnYrdCsVmJZJjFefiaLO5nVvF5wINdGy0BJQB5iOxaSQnypqSLDuBv+FgZtInlTxRCzAeJ5QJKFDGi8q2uL9y3r7fIPR+YZG+TQD+Kdg2cCVdN/GCxbp94vG8/krLXnQ2nsYvfuMCTzOFwpI+QQDof2TXLoBUrOQZ23rovEd/bZGvrXzeLd/vsQwIOLdNY7OsXu2NUYLJWQLpqTK9w/08vB8CHEEQztQ+F7V3+aw4CqfU8TgVOgXF5sniWETHz2d+DfPCfgFjV9u3OJYcbBu4TkjiMu7Gav/MUyNbXLdJROWrax3gkQucPYOkzjxEkVHFdwf9fbtNgOsAVJxz7enWz7sHBJrzZjgwzXX/oX6YZBQBSkBmpMojgzoxl7yprP4lN5oI16Su/aJ6/A75y/+YqODoQUwlDTeDpPBQUADU1ecqVjkT8+iN0HHEGPphbc2for25RoyROX08krwhgzeUohqgmcOIq5CY+HAVnQALYLvlsadLP0qwvTLJVlmPn/R8n1Xx5ZcCV6wEzG4sWvWijo1aD2ZNAQPI5UogSABSOZ9UT/S58/QeFjGlH+mjbtvwNt58D4J5CmGIiCW16T1D0G40oYdtIl1UpQYztzaMGM6awSQqQiO8q25LF1QG1dIlwXV73Z8Es9Z56nng7Q+An90BjBsj3zf4IE15OVKh0eXW0MtfBgvAlfxn4Xz9VXg/ADbvgLWzAf9yG4u2xmd4MjkCtH7aMjTlzUPLmCmwRCd53mRXO8KrChFXsAfJ+95ESHPtmfO4WXWHhMMW0v/YmFDHOrBqdwfU9kaoXTJhpqwCuONe4NFfShB98SFOmWQQC05iJmm6OFKjjcEAcBlT7xmTWR+YZQZZP9K3Yw8d9J+3h0QQ44xzSlrFknUoX7yWJM57aoWVpKGF7CXX08u/htTdmzD23SfZyJ/xCIq9ox1aN0mewQiFGkOhZ1LCyBgysxafyCYQm2CuOCHA5eSnnz8M/PkRarIB3MfsbAEg47yQ6tsBBZB6BevA2RPHk3Mdots/xdBH+tDTgHc+dAuDxrn8IpUYZObW50W1kX3qSM1Be0oOmnNmoTl3LixRCX01GD115cI1qJ+yBJP/fg+iSo+dUQDV8AjSMARiR7uHT6KGhUONiiFAjcJkdGfPREjJIWFHOaH4JSJ0yy7wfe2sLOfpIm8ADieEIMItMx1aMyy3L/NseAe19TI51qF+rDFJ/V7MYOlE1OkjSN37JtJ3vEKg/h2Jhz5EWG2JIBZ9At2kZr+47X9QN2P5GZdCY2yCpzgRMWDJtNZWwt7Z4WTdTNwchVMR7QMEylJcbuL0YNhAnruAyRP1V73VZwvpzZ56bPnImdADW3SiYIP9DlCQaq0gVVp5zuV9bKAvspO/7l5MpGsmHdxy5hAkNqJGRsHe0suJtGuwNdZRx02CGhomiJs9LBpqZ4vwhY8XkLuR4f2yPH0gJBQgDT3RqwYYxm3P4z/jcxxBykzP/zZIn0FP5JG2LLb/yEPd9Auw94cvoWTFLYMGz51UHL/mHjRMXnxGpdAQHtk/K6HOa2usl5M1uKNGxTv/dbJw4OumpQqNnEcmyxhQAOmiczmeyJUMAWByy5toI51pqURpOVBSpj8H+Xx9XAe6SNGq7yL/ul8KJjocZpj/lZ+jzU1FnREpDPWStUXg2drl2KedCY4DwFMDXzY5SWgwBi8tYAAyraWLpvPogy/pY/bpVJG9CQmBd3LNj1C+5JrAsEFTKI7d+ODwOsJgf4s6Y3tqLpGtOWicsECca6TGlbBw7/6lbgsFgHpYpqjEKZg+1ahDGANpA0VXz3Lo79Axrv90FMhJJlT2uoX/7G6qQ/hE51+HqvmrA9qw3aSij93wK0x/en2/xGc4hVV77YwLUD/1fLSOmSYA85AEchGiSo8i/pONSPhsMwwdnmNkGs9xY9ZC32NXSiUXyGIB6km7JiUNCsCkQAI40QPAkPQ+0seTP44cc6k4m5v6ZFVXcvGtgfWvbVZo5Iu1EF0/dsMDyHv1YZhbhj8/sy19PMqWXi8CDZpq8CmVzeNmiVqy7h6kvfUk0t96Qjjzzs9Qo7B7wYEA6D5sTY1vACNcAaHEQAIoZqJkOnAzJcsjj7a3y0yAYwVytF3cOI82KC5tfery7/tsjKGFwIwIaaoWUtgw6Vzs/vEriKguRsyp/cjY9pL4nz+lM2kMii/9f+Rvnue/iiWAytd8H3WLr0LuE99HVME+eY8W6tUEIP/f8fTVBODUqd6vFeLK+ogKJIBjHEFaCaDeORrfgWNo+7DbtAab23AR242WsdODE+UiNRZTdFBIQfTpo0jb+S/hSypeHC62mzZzKEztTW5hvRgR7ak658rBdzLNLuK13EnYZeqOT0UP2fzu5DE49pMNGPfM3Uj6ZINUo/xxtzBc7QBRQbdBZmMgARTKk0eyodAlTHFkJOhOWvY5P+AekWffx1HYzwtW6UrMwuQX74OprYEatH7gKEpPl1CPzTmzRazVSgSjgSSOQfWXBVvIx+Uaf2QbJjz6VaiWLrTlzERb7mzULl0niEvS9pdle5hdwyH1A9ym263EBtKNyOTRaR7ghEGX7EbOFXdRqsJitw4aGqmHwQxonBRcf43jpYMBz6lKPvgrwmqKUHnuVaidtcIJnsHNdvlTGqaehy/ufxudqTmIObwNGZsex5T7r0Lc3nfkVF8SUY7KODXSAPlAAyUADAlA6kzp8Y7Ys4GsrK1Nxj310kov6/Q25Jtl+yQIQcZE/3u3n6U9NcdP46khb9NjyProeRGbTTjyCWIK93sdbRhM6YlJRP5dL6Aja5JL1bU369rWJkc0DHJgsHWYk4v9BpB8QAM9c5ST3jKAnOOpuWh7hdt0Ac1NXXSkjAu6j2bp5a4MFsSxW57EuT+/GGH1ZWjOnTPs+7CFReLE+r+IY+/fku1mdL7s7PTRGVzN2hwoCRSyF+W4L158oOkjjw+UV7rZPzcAu2OSgg6gLXToeZxNBBz7pwHzSxMzUXrNj/tEZRys2cl4fQDoxr+04ADYXU7+gqcir3EzQe763j4CKRSGIY4RskorvPwHAb+fmguuQ1dKdl8JdHOrun3MYOtyZXC0BgpA4Vo6czt6+hKGFjc8RaqgM1oR/Hlk5pb6oTX07EvQlZAR8Pth4la94qtu+Gl9JNAns+4OvAoVvxzqg4s0uA/+G41ujRv8lavCa4qH9L3KhVcG7Z7qF6xySVw/uZ2+UnMtrjWhWgIFYGQvB9NXr6EeqANIFDq8pijoAMYUfe6//xifLhhysEpPbDI6M8b7YvXe3SKX4qwLpB/o23hbPJ1cGQfsQmT5cRgswVtmLLShAhFVJ4dEXoJd2sd6xssU++AWY3ADsGLEAHSjviKHRRy7OoUNjD+2PWiNlLL3Dd/6yEvpSM0NOoDdun11Tk9wA9DsY5Zbk7R8/OGaEQPQo6fpeZL27k7RuGk7Xw3K7xg7WpD22dCu3e0lUyCgZMZo8tCXYn6Hw277SDRuaBBfqX6vHvYRAzDcPYjhEAi7BntXB6KLDyHuxO6A/2b2lqeGnGZoDYtC8BHUPA2ePl7JL8O8AGizy0X16KsnAxaJcbChTh+mzCPfUXOpCnu7TL3Lfe03AbWF8fk7RK7okMNRPd1Bx8/cVONqHJ6noUtgtI95Pc3NzkTvwkAC2NabafYusW43pTh8P7pxToDlIZXQxkpM2HB/QKaIcV7oxJd+MSTb5yimtsagAxhaVahzOlXkhjrbykcGSJNrlCvwAPqSwNiYvgAquuNqb5NWmYPGEzc8MGg21r/LcBBT/7p+yCMHjhJWdzq4PICkLbLwc6kvybFXLa7YWbyP0K3bWOExn065v6y7d7Sld0mIcwdQ9jbFZCTps4hEVzXSQq/NIpfT3FyNgrU/RVdc6uAbhEDP/PhFMRTkTgaGWtguB7NEH/1UgKaYZShR6XZlcacme/9etSuJ4FDAJJDYUAd1pM5GHwCmu2GhdMvepjhYmMiTbHCqPHa85/z2RmS/+wTMLbUD2qqUfW9j7mM3iNGDQIAnGrjki6Cq0aRtL+udWAKodrk0RoqPfltWLoSWP3wqkBLIpbyhEXne/pnlFlJULPJmFTdnhyXR1tIEQ0ycDkyXSKVnqeLZSa1jpqMzMVMEv9kNCSECwEGAmMK9QQkEKHa78CHLlt0YeNtXXYz4PW/J3wmR8UfOzHaUjHQvzJgnk1aIfn7ImwsxZADpolXkYOZx0lJ/ITWehhwaIomO0Pc8p457n+JyK+xtraJ7GaLdrDh9LrrksKgjXTK2bxCj8pziH8gy5sX7nZpCCQmRU8/0SaKJCXK1jf4KLwBhk/TAp881VD+wiIe1anzEpifkutBWO9sEC3WoEKdb0doCa201+YedONOFE5uy33kisKrzkw2IO/C+roFImxCBMXS4qGW2j/HtSlfgbGcwABS0tqLS+wemTnL7EV1lKCF9PVZOtbPV16Knsgy2hjryFduEij0TJW3XayKLLRAl8uR+ZD/3U1cb6Fnbqtts4zwfETxeU1Qvn/mMQA0HQJ5xOm9W/x+Y5gaggXq3NSFTPIS91csyECTSYiqWnoLO6lUxmWRlAsQTJ8UkSqP/a334YRsmbPwV7KaQYU2Wic7fiQm/+7orQEC3K9Lu6RkNegoj+/MTJ3gP2pw4IR6zfEsdioMBoKC1hT4uPW2yHApkY6x2NMvogwDEPDgJ4+wti0VUT8bBPiVv1WISYMpzg/Qz+ci5nOrQI4QccOeJo8Urv4nyxdf411nIhqe9/RSyNj7swZCZvPD9GZhl68GLnHHex1Q52bdNRgXfH+gnhwrgMXquHgLQ68plYaFy2a3d+yUYBqLpPD/QEBsHa13N0CMnGs/ctom0b81bNEhVJKBsdx2A8rnB4Pkeg6OocoTADXT2M8e9+UckfrEVxZfcKpKRB+pscQc/QOYrjyL89NG+txMhY61Gt+zwGT5ym0tdcYXgAEi0tmdFAg4VncZczudwpH+38dY15KOmxsu9jBbN1wHkH2qsEDOU2J0wJiYLe6fZgrRAuZ2k197jwNsP8XMDlDthdQUm79mCrtRcNM5ajrZx09FF7g3nzzC7DqktRdTJfYjb9x7MDf3vZcFahyd3cvhM1dUnL4g0Y4b32zjiirt8ECwJ5LKd2n/ukeP6Ane67q4iG11L95kYA8yfI8FlkNWOFoScPgwLj3wziMlpsJE9ZNIynDhmoIHnobfedxNSdhypVIekkiOj9Q7sYnzTpnnMefAoHKI8USBO95CgVA54/WE87lZhDN1WtXRoIR4GqW4ETpObcf21bv8nWxhauA/GhnJhy9iRN6aki+nJw7Fbo7UI6QuPEGu8uQO4aKEP/+yU00wOanhlOK3Gm1jYdx/01EC9y3gSuHUEotnhApJ9MVUXIfTkXhjry+kGNAGkKTUDhjhSsWzZlX8PAB2RJkNjlXMEPicHyMz0/p2Drqjnq0EFUF94ZitPEy7T1b+3lYdmkor97nc8/R6ORphqCMiC3WINFZZONTwcxoRkAjOTyE48gRkWPJchyEVIHrNPYqPG+jLn++f7mK3WTh7UkaPikb+g9j0abAnk8iz/2ayvgeYrU43DRrfcDCy5RIUhQvWg3obmGmEfQwv2wFRVCLWrVTSAMSEJprRMQXrUqGgZzR/tePIaMXSv3AFFm9SVOl2KsWO9+35c8vOloBIleH6wPzfclZo20v0+8tb7SFl3lVzwINTskU3cp/SEGRA+WSUCY4elxgZbk92VbUBSybZC2Aui+jZeUy0iTqzspDhipsI/7Bb+oZ2P7FPazvx2O+zfsgZRWPL0eYVqZ6tg345y2aW+r7FzlzQyVF8cEQB5K1JyJ35t6cHvnvkHcMc3gcgw3wDWNEsRMkSpCKO6JM8KtcWGAwdl9N3FCG0wtNaLys4mry3KM315kQBxpF6uukVxGEiNnHAe8descmFYTZ/OFVjdqOoRIYOMDjFwTCndJoNK4CpJs9Q6HZnpxDzHjPHh+5U59494ndq1fKQkkMufSQq/+e6HmMg7cI4fD9T5WDS1vdtTB04ea0cSMe0li2UCzzHygfKJsZeUeO5ry4vHGZq7hLqVrWSAPTRSTFfWQiPEwgH2sAggQu0TotOY1jGQ7tWpwe0e6s9jVWLh6EvfUPxPVfvaZLqWQj4hg8YLG6gdTR4pEyKonQRcMcC81l27nKf/45fkB2jN7IW8V1IMmak//jeUikbpSvRXHnw1xMPtuOvy7n55CueWFhZKn+jkSbkn36ACNTwfkaSVj3ZzqDiHWELSKOcj6OeDDY0pjiWe7XJ1YI91RLsJOB7v9NKGHEpcMB+4eIV3v48LT0V45FFh3vPpUlO87d4StG0H6Ad3Eoh3NzXjv+/9NbD+e0Bbl1cb73zemDDNK8nkaMWkSbI6GNrp07KydPJodU8/c2UcC7MKNT2gOjRQSykuH8iu6b16eKo3LU2GyubyjrKDyFjctl0PEQK/HGj/pKBIoJsk8o4jX8slX+f66/rPd/zjO2a0dMrrJMdo+PqFQxs6Ys3Hs4CrqvRaLY+cimcP7HroPgsnGthMxKwjFcGuw+MU3Llm8M/EiUu/fVwAeIqgmEgAWr2HXIO78QcXXvzFVHgKNzzxFHDjDXJpfw97EK05AfRGdkpLgQ8/klF5FgxetW/KFGDWTJevyeqXl6Hi6h4YZt7CIPKetpzVzOcdHbLyREo+8twNh/QKEusGOMdwRfKAIkcLOLOAMyE4OE+8ScyLZKmK01e2L21S8fJOkxsb9SMuT3hsftMZeVnvC7xgkhh3VWojKbyJTiurq/HDx/8Abc2VUNiRdwhvdrIdhdWSaDCQFrpls9td1FCPfPIvRGB65PpqPDJQ32DDUSI3770P0PV8+lIMMKfqcc3NCb4ERvRKJjAbB6/Rdu4m+y7jnm9R220eEikO9AOxDqf6Izq9lnp58z83AM+/ICWCy5QMu0fYs6TO8xYOHZLgYfxc2KcuQdyyNUhYeDFCU7KEND37HLDjs9Hjt/f0ckHjIwYHYFEx8MabomPX6ZoLowJANyA3kIqYxr2LXYPfPAbtbY7Y2OjNLNdTf17sSTUc043t5nBibiEII8c4JDEN8fMvRNycpcJJfv0NOWI9GkpnLzOQEDUwgJyK8tzfhHdjpTa6ltpqyPuqG4P5cLpDuorU6mq62Uc+2YZJO3ZCmzvfpkSYVbRbFJyoVFHZqCAtTj64I1PZQFSdR6Xj6Q2jPss3LD1bGIzGA9vwGimcO3/g/yAGL7RaXSXXZ9GnaqCry0U6mf1yxI5tHK/VGRPj+3qVjZ43MDbJN4M6dUru3MnJBvTyJmqjYSXhGEeil9JNvkEgsvxdRy7Vj3bt0KaS94usSSrMSQa8fcCEm5ZaRCw127Hwb30FtKRsNDY2kiPsWt0iLCMH7adPoLG+WsQOp0zx/du8EhIvrFpcLBOFmpr8u/fcXGDtl70DWVSjutk/IC/V7pU1b/8UePtd4e/16OD9c7htaxwpVaMzLN5WjQO1F1P/u7Us336FdsxuVMm3fr5CUaZN1JCTK6Wwoa4chpQctLa2IjY2liTDRe8ixkyEhQA8fKQvgNxQvBvmUT2i0+C25YSROH/q+Fwkjs1FRHwiQiOixHsqMx8HyyJR7G5vQ1t9LUoO7UEhUeoNG8lIfb3vM5XVq6hudrlWs8fZYDL0rzI3bZY+LP1MFf3E1dQenwaiXY0jbTN0R/VdrgQmr5K3zt6DKwvytWUnjknfW0YtNJjtFnTSLTYTe0lMdK22GJIs05ndUu9wmlyP/fshQHWoRoPBiNy585Ez51yMmTwV8amZaKEOwVLdRKLYTh9sIj3d1dVGtrcbVquVvmNAREQEEvOmYdVFq7H54Z/gVFGp8DNTe80D3XrUhVa4WcPiiZ5eQCUBR2YDB13T9v9J4PGGVvWBas+g7SPvb+FVgCE3ErmQfoY31EpXkseiIyGL7JyKsWPHiqOjVH/4Cmwdbbj0EgLugFx3U9gwctomLlqGSYsuQGbeJNQR/a0mn6aKvPwGEkfNzwhL+/H9aC74AleR+zJ/vlvsssCADw67+v+1i3qQm2IXnYcXM9+zR6ptPfp0UN9u/KPhtNFIOPLDkUweIH5RrwxomVZbmgEC0E56sYuYRrg+9ZeHkRys45135Zy7vPmLMPOiVciYMAWVJC6nSV/tfPU18d1hNZq+ppnFLWx3uNSAD48YnY7/rHQrSo/Z8f5mGeZzLAUDmVX2GL1+198Q2ahVoX6Uk8Q4M1TqvnZqAVZ3oaRb2wqPoP3UYTF0FBIeiXmrr8acFavQYbERqcnHrmGAxj3cZrOhhxxYvgZXi572zz7obnK8G1oVlLcCse09qK/U0NqkYasLGv5h9lJf545IoJUGu5FGM4A50MHj0lpXg+5D28SwDavJJdfdirkXr0ZVTS22bv+M2KZ/ZoWBYrvnqBbi9T29ouMhqga1vNAVcHYKlvBj7XR7ZfSSs1i4Min5zNseR/9RAJL65AlqWUqsnP1o4AVcy4+LQd4JC5fistvWo4Ucunffe3/QwLE0dXZ2OqvF4j3gbDIoMNWUQKtxZti+QpW37+IRWv5Bjp6UbKmD5Uy31WiVwFXSq08XCUGmmmJh51Z84w5MXbKcCMIecohPDfpiHR0dgsQMhsCYVAXGw9scBouHWe8kqdo+WtWUcQSkieegOrw17rEteg+uo4ax9PosTxpdQPVeITXkzJuaqslfi8SX734IhsgYbNq0SRAaf23bYNmn5mLaW+j+LsEoL8ZgAkcu1TNkarym8qxMQR21azN9hh0qdvQi3bxuKARebFom1hJ4xeUVOLprr99ugPQHB79CvpujVImzoBiDBJ6R2myTyYh5N18HzJgi0wscY3G8/ldFrVjZN7G6BomniqXzbTQboYZFw9LcAFgtSJswFZd//2fYQ44eq8AhO7t++K+qa+mTpv9YAKl8m6RqwYO/no3ZV/1esmvezaVhi9gMGfZO1FDzlNZ4RlKeetomwaOSd875OP/6b+CjT7ahrW14Gz2qfkS8Vde0sP+ijsi95klSpQ3/MQDSQ6dRez24ZHEkZn9lI3D8G0Bj30k2STFyRL6hRY6I8wiAXc9JmXbhKkxavhrvffCBoPvDLX4BaOkQzpxiDonRLN2/ptP76Jmeo+Pjg82WHskS8FAaPeyzpC5v2rj1ESXCTC5RyYM+P99KanUrOchP/1WmPMxZvRZxk+bgWH5+wB6SXYiiosGtVRpeR+5DbSnUGUvJnVBhLTkGW4NTffNMkH9ALjzQpJOxSs5EGAmwgh5KI/B4U8ibbrw+TYlInkHu7WUDfqeANOuTT8uB3AVrboA1ISOg4PndSJyMy6mHvOMmvzFmCow9HbC2inn+s/Tq1qlhJzJWQYric2pfnqvFO1F+GKzQWVABJE31WEQ4tC/fvFZB/tc8FrpzL5yw29QiJ8Xc92tJbOYReC1hcWgZBlkZdmOwquV1aNy3LiBn3tbWIrLssjJlMhTfv0LwmBWRr6qWVSLzdBkyik9jJT3Lj4jAcZrlFQRizVkDIN3wpaSpzr+Jp5I1bRQbQPYunMD6z9cgNkXmiYxSIyuYvvJq1ClhsLS0BOUhBxsbNWo6gYlwjd5q3Z2Ij1MwbaqnQGUmASmeG28rVhuUjz8Ffvek8GVf4GY5KwAk8Hj6+cOJ8bCvughqb/C41258nYzHK57LMUuVruHo1rcQPXmeTJk4gwCq7c1C7xljk1xGjR6sx20tvexUwjdUTuLp05jkbi4/nzpqE9SnnsdF1C6c53k8mAAGKqnpGrIB02+8BqqxV5fgXcy+cSfw7D8keKylViwDfnw7MF2Pz9g629G4/2M07vsY9iCs3TlYJqtVl5BWUJGWN0kkVMkWMjiHksLorYTo/sFzL5dcIFfXZD4w6iVQl7770lJgX7HUY8IQ/raBpO5froQhnkv/na+T+tE3E71wCbCXeN2fnpH2sLOymPzAOiQsuAjGyJgRBZAZJ2/KGJqSCWNIKFJTU1FWVgYbIdHdrTklbDCFtyWaOwPKvkO4nl7eM9ol8Apqn8k3kfQ5vAyOtNz9K+DFVyR4/ED3rAce+pkLPEfhhYL+/2+Ay/WAG4+y125/E5amwO0x0dMz8IYjvGUdl8isPKfLJLLh9IkwFj/HHZYtFp14LHXwOaMaQOqV96cmw37+ufI1MTLcTn3uwBd6w1x/A5r/8hamLkr0eg3eBeY7twA//I7s5TxYW79zS8BAtAzQ+uzoa6X5UE1mhGeM8wwA6PP+2M3xJ6awcJ4gaSy6a0YtgNS7LiDmNe26L8tn5ZWb1t8jN7/iLWfsD/wOb619Hu+bV2KecS8OKTN8X28p8AB9P8QsQWzY/T6sbc3DfkhfoxcGuvHQ6kIxITRmwkwy4iZPAPWUCjGfwg8AeQ7F9MnCvFw9agGk51sfHwvtImJe+QXAHfcCzaQ+7aHhaHridXww9XbnZ0uUsVhk3IH3FN/MevZ04N4f6muDW7rRsOdDIjZDHzd1ZJv1V8JsXTDn74BWV44wsn0MYJ8QnL7CIrs9Vj/jLYsWCKmdRB19zKgDkG4qh3T8l1ZdDIWcWPz4fpn1jKgYVD71IfYmrezznXZEYJXxTbyq+tYq88kufk+fLWBtb0HT50NPoeSUxD4qW1UQXn4MOLEXYaEKFq1diJTFl8oZuL0B1CWwS257gR4/5g+5LQS4cjRK4JM8zDaXOu1dv5TgGYwqKv/0No5GneOdUMCEqw0v4wX1ep8Xv+wiWUXjVZ1Gx+mCIanOVrctMlldhrfVwnBkG7SWeixdk4u/7LwGC6+YIdyH/mwjdJXqTMP3QxmMyQCSEkTuzOpRBSBJ31iTEReeMxd45I9SbTID/cntdlwX/vrAjjX97H8ZnsNm1ffE8W/dLBtBMNtje8X+S/6AV62vGs6MMszWDfOJXURWjiMjNwYPvbIK9zy1HIlpEc78zX4BNIWQZCrORd67/NTm1EbMzi/gnU9HkwQ+QKpE4ZRxx26dt98GnLeQVKn9IXzZ/srAvhk9z1rDRmxVlvlkp3d+W3YOtoPNR/f4dsT19MPKykqUl5eLqdLhnY0IJeBwYg9MqhVfvXsentx2NeYslT1jxw7g4MH+r+cYfTGYzUMGkG06mRpex3n2aHLkL2O/t1jPerxqtUvdMXN+1vZV5CuTcESZ6pvew4w1xlfxmfVcTNL6jkCwvUmndl65HHjrfSIS5acQkT0J5rgkjzAZZ5kxcFy5R5q62xBWdQpoaxI8PiouFMvXTsO135uFhNRwZxjvX/8Ctmzx7V6Iz5pC0dgoI0Ttfq65PsM1d+NCqnvPOICkCqKoY8Y5piWzDbyt12LvkWjD67YvYb5xD+qR4PN6TYjFasMb2GU9hz4pUwR5XLeyXi6Yx+W6tcDHO+RCBy35+xE2Y4lQkVyZZYpMMo6icCqgvoOnalAwf8UYXPyVCTj30mwYzS5lw6kdTz8NHDkyEMuW37GZI1BZ3SLith16UvhgszRiooUZ0Mg/voBePjwaJPAhR2gsMV7GNPsb8B6nFeFV6xosN34giIuvUqjk4gbj3/GmdRWRITuKq4j+uwVPmqnBr70S+OuLJLX1VegqLhBqTSWwQmrLxApPmgBNxexlmViyOpvqOMQm9l1lgRcT+vhj4NJL5fIlvvavdQCohISjsVITjjwTNwYxwo/d1KdPIXNTJUYozqwNJOm7j3ret6R9INKynnqYj2U0ztO24UnbbYO69jvKpbir8yc4XuoJniAwBOBF1H8j9R0B1KLPoR3fA63yFKwGMwzZk/HdR5dhY/6NeOjly7D6q1P6Be/AAVnXrQMmTABuucW3JDkzEMiv5R7SqGuENj8X2ecV/MmHjA+GP/i/AgwAd1NQSKotCL4AAAAASUVORK5CYII=')
-
- e_pray = ('Pray',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NkYzODVGRUY3NjZBMTFFQ0IwRDQ4MUREQUY4Q0EwMEIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NkYzODVGRjA3NjZBMTFFQ0IwRDQ4MUREQUY4Q0EwMEIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2RjM4NUZFRDc2NkExMUVDQjBENDgxRERBRjhDQTAwQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo2RjM4NUZFRTc2NkExMUVDQjBENDgxRERBRjhDQTAwQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnTHOpwAAChaSURBVHja7F0HeBzVtf5ntmi1q16s5l6w5d6xcQzGxhgwmNj0FkjyyCPkkYTA4yWBEMILSQiEkgCPkLw8SCAESOiYYjAG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')
-
- e_relief = ('Relief',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0UyNDM4M0Q3NkRGMTFFQkFCN0FEN0FBQkJCNDI0RDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0UyNDM4M0U3NkRGMTFFQkFCN0FEN0FBQkJCNDI0RDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozRTI0MzgzQjc2REYxMUVCQUI3QUQ3QUFCQkI0MjRENCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozRTI0MzgzQzc2REYxMUVCQUI3QUQ3QUFCQkI0MjRENCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkcqXg4AACTLSURBVHja7H0HeFzV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')
-
- e_smile = ('Smile',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QURGRTRDNDE3OTk2MTFFQjg5OTlFM0FGNERCNDQ2MDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QURGRTRDNDI3OTk2MTFFQjg5OTlFM0FGNERCNDQ2MDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBREZFNEMzRjc5OTYxMUVCODk5OUUzQUY0REI0NDYwNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBREZFNEM0MDc5OTYxMUVCODk5OUUzQUY0REI0NDYwNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtdWIMkAACF7SURBVHja7F0JmFxV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')
-
- e_stare = ('Stare',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDU2RENDRDY3NkRGMTFFQkFDMkZGNEIwRDA4NDUwMEEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDU2RENDRDc3NkRGMTFFQkFDMkZGNEIwRDA4NDUwMEEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpENTZEQ0NENDc2REYxMUVCQUMyRkY0QjBEMDg0NTAwQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpENTZEQ0NENTc2REYxMUVCQUMyRkY0QjBEMDg0NTAwQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjonYg0AACDcSURBVHja7F0JeFvV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')
-
- e_think = ('Think',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDRFMTMyOTc2RENFMTFFQjlENkFFNDNGMjQ1NDU1REQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDRFMTMyOTg2RENFMTFFQjlENkFFNDNGMjQ1NDU1REQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowNEUxMzI5NTZEQ0UxMUVCOUQ2QUU0M0YyNDU0NTVERCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowNEUxMzI5NjZEQ0UxMUVCOUQ2QUU0M0YyNDU0NTVERCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmNHEb0AADADSURBVHja7H0HfFzV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')
-
- e_thumb = ('Thumb',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzlGMEE5Mzc3OTk2MTFFQjgxOTNCMDJBN0NBQTUwNDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzlGMEE5Mzg3OTk2MTFFQjgxOTNCMDJBN0NBQTUwNDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OUYwQTkzNTc5OTYxMUVCODE5M0IwMkE3Q0FBNTA0NiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OUYwQTkzNjc5OTYxMUVCODE5M0IwMkE3Q0FBNTA0NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pk4O+RQAACQYSURBVHja7H0HeFzV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')
-
- e_weary = ('Weary',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTNEMDY4M0Y2Q0U4MTFFQjkyQzZGQjIyNEUzNDI1NTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTNEMDY4NDA2Q0U4MTFFQjkyQzZGQjIyNEUzNDI1NTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpFM0QwNjgzRDZDRTgxMUVCOTJDNkZCMjI0RTM0MjU1NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpFM0QwNjgzRTZDRTgxMUVCOTJDNkZCMjI0RTM0MjU1NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Phd5p5MAACVgSURBVHja7H0JnBzVeee/+j6me46ee0bSaEb3iYRkAQKMBPgCIzsOCofl+MDYEP/iEIc17NoOSRx7N/Em2djJ+rdeO8bYhAAO5pCwETcSIBC60H2gkWakuc/u6Zk+a7/vVXV1dU93dc9M9zCD98FTVdfU+f7vO9/3vifJsgxJkjDby/U+mGlTTbWBaq265d/lVMvUqt/nj3ZRtdHnS9QMHtqG6XeI9mXaBqn61dpPtYfqBaodVM8k6s4+jL1f3yywm00AEkgltFmq1oVUm9XapIJlyuc+LifgcABuN2ChKxx2wEN3Hg0BgQAQjRJ6o8AIQTgWMrxVjOpxqgeovkl1F9VDBGr89x5AAquUNpdTvVSta1SgxpUyL6FIf5k/F6ivIyR9gI9oraREActmI6AsgJnAmsynxgmOiArqMNFjby9w6izw7jHg4GEgHEmeS/cfoCZ9lnaforqDwPT/XgBIgDE7u5bqdVSvprpKT1F2opJL6cglKwmseUBNFVBKwNltkwOlkIWBPU2APv8K8MJrBHZEA3OUmvdx2v0pAfnKBw5AAq2SNn9I9VP0CpvoVWx83EzS7ENrgY3riVcuJoqqZAAJSwuRlp1IzErcUqKTxlqJ752mL4nNGM4RIin6zkHipcRQd79Nrzeq/ekdqj+g+mihWOz7AiCBxiB9muof80+qFj6+dBFw08eI7JYBlRWMD/E+J4k5F1XnAgKuQQHNT+JmiLp58AR/woyW2T2DwPYXgNd2A21t2uH9VP8Lgfj8rAKQgGPN8Kv0qK/SI2v42CUrgFsIyuVLVApztJDgIj7pJh3FxoCpHDTSBwwSBxp6ndQGP2ZT6Rog8LqBs8QsdhKYrWe1P/2S6j0EZO+MBpCAY7DuV4Gzs2Jx5zYScpezgkHPdRGP9JCO4llHvNOVevEoaer91FEDrOTFMVvLqXZSfoLc4KT4HCHNZgf1xSEhIzvp2C2TlY9FBZCAI0Ud99Gt76VHuEgblIlFSp+5kZSPClIRSzdSvYLkmW/8xQESIn07FBn3AShh0mCP0qfE1D4YJDC3k566b59mivwZgfijGQMggcea5I+pttispKF8QmGVJRVzgIqPKBTH8ixVWSf5Rl/UR18Wap+RQAyS/T8klWIYXgyRlSMq/Q6SAh0gE5XrqOTECNxkO3gwCqf4G58TjkoYjLoQlWyIUB0zuVDXsRdl938B5hEhFv6WQPzW+wogAUeaB/6R6lf491WXAXd9npSSunqg6tOKfMtU/CTXe5+krtpRdBC4cfulCvSgCn3wif1+VIj9PslHAqlSbNNB4t/FKPOGD2LRn5Mu18uOHnyXQPz2+wIggcdG9m+ori4nE/xrdxCAGz0E3B8Qq7wss5NklPhKz6OKrJusDUY9vEOqE4B0STXoIpHL+xelegFGt1StgcJAhWCfcZQ9138Yi+/ZnADxawTiv0wrgATeerrFs3QrH2uU3/4Gccq5pKVUk4lnLsnggBqhl32CeNKujKYAvRG6US1AuIh6tEuNYr+TFFkGiIHiv3dKtQLAD0JpGtqP5q9cCfNYkCQmNhGIu6YFQAJvA12+k53BN5J4u/tLDlgaycTzrM3slho5jM7OnWiNVeCcNA/nMVeA04E6tElzBGBMURFY8ftW1rQ+hso/28raaTu153ICcbioABJ4a+nSlxm8bVuBbbfXQ264CyO2ZiEzhiWvJtwHqT7WK+HRoSpEFdv9/5cM5bpffwnSQz/j3Z8QgHcWDUACr4Eu20eXV3u/fR98Gz+GjfWrETZ5SZ9MlXdjpGD+8CJweuyD2/DcTb3yMOmefmLqQe6+ZEeNwSGPiWNW4il8zE6/B/vH4Ir5qZViMMsxuOKKc8JMXds93IGX/+oFjI0J2bKOQNxnBKBlkpTH1z3G4Jm/8U0cuvL7+DopmmMZ+kGQrJwfXAAuhGc2AEIXlfuVLVWf3Kftl8mDAgQGIAGSV+Ex4jfrqtIE3HonCK/AaPa/W8kIe/oZMV75d1Cc+1nLZHnZf6V6ue3aTdiz6fv4b7X00Azgxeibftw5/eBxo1fL3aTydIptJemhCVDEvg6oxL5pGj09HpcxgOvWAbt2AwMDuJaI5SNEhc8VDEC6IQ+kfgveUrxz10P4XI0Elznzua8OUW8bLcxHc8NXyT2k6nRo4NTIXWQw0DG5Q2xZZ+VzbJi+HjM6pgz6EssTw0o8+sAeFyu1bKVPGUkZx26dxvdk58f1ZBo++qj4eS/V5wpJgf/AVC5/YguaXnsGrtYyDC9cCW/z0pSBOZZ7T/fnvhnLhgb5gmj8OXIbGtEufjfggva7Vu4U5xW6+APKAC1v/WTZjIwoo/ABdT+Q2FdH5sU2DbBchQeWr7pc8UbV1yjH3I7c161cDuwgMzrgx3VENCuJCt/NdF7eSgzdhE96gOp3Mv3d3diMZX/yACrXbEQkMIy3o248GS6H18PD6OfQJLfSthXz5bOYgzYBUqPcTtZc94TkR7YSI1k7REr3IFF9/6ACTN+AckwcH9YBRnU4oDiXp6tYiEvdvIU09a3K/tFzSgiHUXmNLMEdz4pdHhC+Y9JaqBre8CuqNyShl2Cy2hCPhA1bguNN5jYC8+dRryIiXUGGfn1t/h/Oo9u9RMkDBEpPn7JlYPr6FaB6+1SQ3udRJtlkUUaiJRPtmyDF45DC40mUh9D+5j6ga0gZLzR0+xH1f+9/0L3jCFITVxGIwQkDqI4qvESV/WGwl1eibNk6OKsb6F3NdPM4hk4dwsDht/L+WA6H2LhBGXGvIzB7eoHuXgUgsdXtM0UVtfA3mK1UGQALNb5Z3VJlQPRb/pvJJBzxyjGzckzKEksVJzNhuBfW3jZIkaQNdRkpKV+/C2jtzP16Dz8CvKswz9sIwH+fDIB/pwpSlC5chYYPXYOly5ahtrYWQ0ND2PnYr9C953lYS0rp7yvhqqyDxeFAPBpFOBhAaGgAocEehAd6ER7qE4AXrxAztlgFIFC3ssUmjglQzNZUsPi8yXqhdN8hohBl8Xi6XYbIKQLS1nFKgJkod38RmNOS+zHHjgG/+KXY5QCpGyYEIIFHtILzzAndDfOx4qbbcc0118Bms5Ec8ePJ/3gYrc8+As+8Rbjq9juxctUqWK2pLrAoAclA9/b2oqerC23HDqLr5BEEL7YiNhbMExdiS8SuZbNN2VrG1wRg01Xio0HEBvtTgNQKUafJ5YbZ7VHYqgqz/fwRmEYUvllKf7r3L0Q/Miwc8fa336NtGOwj9enda/kY8l9i8LhHVV5yBa688koBHpcDBw6g++CbsPtq8NE778GSJUsyC2+LBT6fT9TFixcDV18tAD1x/Dj2vfYihnu7EW49CjmUlBdxlxfRsjrIdicB5lAoZoYVk9MFib4tSu8/DkTSqOL+YcRHAjCXVYhzmTzDdQvgOPOO0BlYZh8+DKy+JLdJsYx0hwMHBVZs1P/nRMyILfyPk9jiwuWr4HK51PeL4dyZ0wh2nsPqW/8E1dXVOHHiBBmeAwgGgwgEAuIcRdeRBFU6iK3y9W63G6WlpViydCmc9Hv37t3o81TCFg4icuYgffQwTMFhWAnQSP0ixB0lM9Z7IxE3sPiqFBAzKXIEbKyf2GY5gegqEZ0x5q2Ceahb/PnlV4FVq3NzcaYNApDLjXkDqGqeG3jf1dCExsZG7W8nT57ESFcbsc4lGCJjaAcHeUymAejNS0pKSNOMEFUSK196OeyhAMJHSSGKRWBrO4JIbQui5XUzF0SbHWZvGWIk67OaOIMDAmyuUV+DBmBnF3DiJAG02PgZ8+drux8bxwkMrluviGXioZX1qKys1GTakSPUsP4heBcsn5rqrfba8vJyOJ1O8TtsI9mxdjPMFYrVa+08o8mNmVpMJR5IdrvRh2oAx+1uxN1l2p/eykN5Z1u6RjG96oiwWvIFcI1CJSZ4qutEA3M5f/48xsbGYPWUCs2zUIU7iMmkvE4sTsA2XwJzebUiB7rem/GjEebScrW7Z8EwFIIcVix3PUdhCmR7L1dZmIRtY74ACq3EQkAxhSTKqVOnxNZZM6ewDUDaGstGTXxQrzU3KzE0UiiYYkfNVHlochhHB8QDigIZKynXFDPWf1T5ZljmzZ04gItE7/eUaw3LCgqbA+JCS+FVdrPZnObdMKWwoZleTB7jwKf42ChknvpEXI2VmUTZtz/3vesatN0N+QIoMLeQLcOaY4J9ykVsyFAo1TloVlkOez9km2PGAygUFYfBe1LTxYMBhQpLq7XDFy8CPT3G964oU2ZZUVlGctBqCCCdwMfrBYBOtwZge3tx4zVHR1N9h/GBLmXr8MBQwMwkKnQZmz3xoCLw4k5PSqc8cjSXxg7MUaQWg7c4FwVWJUwMs1Ox3Vj77MnVTaYIHj9Db2KEL55RZUYFZksxOZyKvzSrTRGDPDaqfpcvxWWWqzTUa7urcgGo3dnicAsNlMFLGOfFKGz864uVp4xFlTHAmGf2AChGaRzOnG649O9qa0+ZipaZqpJiMycFanc2kaHKXpSOjuJFTTPlsYKUIi76O1T2WUKsxonZVKRcADIFki4Rd3rFiEZCR3svh7WkMwaacwGoBQJYiYWydpjQPotR2DGuV44E+2w7qfRSbyVmWzHZHcYim2wHYRPSd8ZcSdPpvbPG99VZWRMB0C0at6+vrygfy/dmAFPYZzyqY5+zD0CWgZLVOIQ/HlLsWnbcJ8r5thwUWKbpcjkB9CVsPXZEM3jFkn8s++Jp3ny5t13HPh2YjYV9pGM1TTjynf/E6bt/OG7QV04A6PSkmBORiJGdrLjVqNSqaVWMZSDLv2Kzz+Hh4TQdgNhn+6lZyz4TJdi8EkceeBKBlrXou+wmhMtrUgFUQ1EUE0njrOjqzsFGvSmWQlYAyxUAHWI8j4eJimU6RNK6nDUe0cbXZiX7pNK17kYcuucXJN+8Qs5Zh/tg6+8YZ9QLEIWTIqn0dHUZ37ss6QcXPcJiBKBZpcD+/v5poT7RC7vbZi37HK2ai9NbvoGh5jXaIJ8Ui6Lq1Uczy38CkFlt3E6KohoAlQtAb5JgeXzioMXAkBcUyCMExQCQKS/d88LsM5Iw3mcR+wxWN6F90zb0rL5OsQd0I7Qc9FT90q+yAKhwHz0F5mpqd9Jf7jGiQDHeYSZ1mBs6XoRApHTNUzHeowgl2OcMBzBUVoO+ZVeiZ81H4W9cCikegywCmnQdkrTpij3bYe/JrF7KqudJz2kGcgx96oYdSzICSNoNn6I5snnsrxhlJNMg2GB3kn1aZw77jBGLG/U1YKRuAfxzV2CIFJNRX6MASMSDqpQ2HiFgzuN/b3BjFUCdyTGUI4xS5ysvy0aBnE1InGYr9Y1jc4Uo4XA4o1kS6TynAKgbsS5m6V77cbR/+DaYQ0GYxwKCihTjyoyI04soGdkRt5cAdKsUFRPsUVZNggR4Gc0I4iRzn/lRVuoT16ttoI+mC+YI1LNYDCiQqI/jDr8meG1DswjeLUbJRNVmk4ToiDrgOQEA4xYb4qwtB4cn/B4XrrpFyK+8nQ4mc342IAFd+t5+NLz4EGLGXoxxAPIhphlnFm+cNYmYJQVANdncv4qDTjcq115VtJ6faUzRHIsgMRahN27HXUsfG2hYhOF5qzCweAOGmlYLVXzFT/4UpWcPTug9mp/+J5zc+m2EvT6NqqZswBNbdXW1YsmvvoW8U4GldQzu31kBTBtH11PgvQnZV3np1cKIL56nKUNjjSkykX2Dw81rxWh8lICMlFQgRAoNy5+R2hahPDAbY/VcHy8adU2c7TKVrPv7P0LHhi1o2/x58TzZNHkgJTkOb+u7WPrQ/bDQ98TzjPqWzeZJP9OiUh/j+nXed9XNK3i8S3pJBAenfITKAvtWbcahr/xIaxCh3XHIfFpwr/73vJ0/he/I5LI5SkT59a8/jro9T6J7zUfQfvWtZM/NU56bL8tUlZF5z/0EDbseEfJPtYvyfYs0HWGCAFJZmTDeSxdfUnTlIT38XvMjCUpK+oqYrclmU5beLotpOwsf/z6q9/9u6qyPgKzZu13UkbqFZNNdi94VH8aYr1GwQgZJ4keq+ZmZUhlg68gAXbMD9bsfg83fl/GbJlqMLksH16JXSYWaWlFddACZhbKLTj8Cr/0tmnsiJ1OHNTCAZQ9+EyUXTxb8/dwdp0Rt+u2PRYcKEKBjlY0Il5QLp7Q5NEpg9aLkwkk4e89nD7iS8wQwHstmKowr0eSpfj2A0eS9okWJOBtvkNpTQygsClu1BAaMtTaiAKa4+c/8s5AzxS6s3ZbxfAauhSSlNJMjhUPZDEzHJIAxPYCaDh4Ph6YNwBRj3q6oXdyzM1rE9L+r5xyan/pHatB9s8LFJmfgMGmsSG301PPsBgDqzPKAHkDNrxWPhBI24rQqMpLaaay6OXQJTbOk/QQaX30YlYdfyZ8tzQQAY8YASqoiJkXDunYZbyroi87Q79cDqHngYqHRafm4cZqoCqBtsEvItxKSQWWn9qLi2C6SM22YjUUMFxkBaFG0XEl3XmmO2QojWQDUKDAaHJmWj2NFhrXRxHhgwi3Fbq0N370x+7Tl2QIex7zEcxjyaqfVTxsoK8sbQKHyilba2ScSq/QqAAam7SMtOsee3oCWohHM9hIfy83JJFVbMYWTqFSUG1/Tlxxu6tIAVIvQx2Oj0weg3h6UdcbsrAeQQyVGcrejpIoRSadN1+bI4KGOF4aI6LrTARSBKGH/4PtCgSncJh6d1fjFhodymhA8PVsoMaSUmXTpSOoM5rKKrFAKt9WUgnEARob6p+1D9T7RuD4uNB6bteDxFLLENDJDAO2KtW4aTWYcYs9bbU32a4aStHU+3RPD5bjS+SOIjvjFYO50AqgcMCteidlEgRykS1qkmDqWmD6Wj/GuRm+bgskR3IaGlBF3I/l3PBOAexM7nM9lOgAcN6ykBQLNTAoUdh1pzTJ1co5nYeB4f8KZwqjjmlQKNOumj7c051Bgeg0AJKF47nofOHdQbWigF676pmnovPGZCRJREW9ldjyKbUShrAK9r4kH+9QhMdNokt025wDwQjIy8UgmCuSyh+qWsb7OaWmsdGc2q9Wi4aYwPmakGcrMnnl6F1N4XN0mfvNzeTsNM4ETcwhNgX7tecw6m+cbX9faqu0eyAYgL2K4JdTfLT5GKkZD6kr6jFw5YT7E4gJIKT0cnd1oYhgpWQUbjqvHGRTeZ7kktjHd/sygdnNpmYgFFfs6tyEn87EYZO3hnHFqGO0p4pb92QDkgbXvc+ON9XbAWdNYPFWbOkg6gIkordjwIKKjs9+YT5d75rJyYp9uVfv0k/xLjrysXGl8ecdFbTclMUm6v4pJk9eJRbCzuP5HntSSPqVMC/KZ5W60dMWM88hYa+o08DjRj/38Ye17PaQvLlxgfJvTybVRXskKIJEm31GkXQpeOFtU6htKC4A066IKZMk8+4HjhHceLyy19UoOGTKRmOrs596FjQeh4zFN8f7MHxizTy7HTqRwSWRjoVx47dcvR8nAZFloL/AIPVMdT9dO10BNOtsvbpql60qweUAaJueLSc7SlWEmZcXSdyHF5uPCyugtW4FFi4xvyzOWBhSpd4KI7HwuAHdCGaqo8Lce1wBkeWW326cMHk9VyxjtHfRr4M0mFipZrcKrwvPiE94VgSUHCxOr5Kof79MrLTd9MvfwkbAZNKNBrE0FQwAJ4RDZg4/Q7t0jbWdQsepyMULf2dmJqqoqLWPhZNgmU162UP1Y7wVla7bPfMBIi2SwOD+aZErmAxWKib9P1Ezplrl4KyVsvUlGS0t+z2NL64092s8HcwKolv/NALJbLXDuBLwtKwT1dHd3k8D1oKysbFxWJSOq44ksg4ODWQ13EZXdo6hZUesMWcxKUkbMecQgkWlQDP/o3H9MZZyIj1kjVynbCDzdy1phhrXKBBcB2NKSf9zgoXdF5nouLxBxHcsLQDrxMFEh58neNHTiEDzzlwm/JQPAYLAGybljmBo5g0W6TzNGwI/0dWN0oA9jQ/2Ih8eUOe/xmGoqqPmJ2RvP4XlCG1MClqSGJnopk+L5UD0gwj5MGNyFNLT5edwRqQqwWJMgbiOJakmJ6+SIa2l0GKaxgKA09qAYDXvxpZzfTCozo0fieyvHR3i5gpAElz33d/CK2L9Lrhjx3UznGGkL/50BZGUm0HoCFkepmJSSoCoGMZHbRWiQgUHIg92I+weUIN0JNHRM5y2xv7cf4XkrEXewyu3M5oNT81SruaoTzsiMz5TUuNnkVpgsiZrBY8PDO5KfKCpMFBYaFaBlY4n6wsObnNuT5dvSJcQuvcBhssae2ptmlAdBAOZulxde1Iz3p4moXp4QgLzcC1HhbtrdOHB0L1wbPqYBqBV/v0hIEB3szujp4PbhJcWrKpWZpZ4SZXIGR11x74pElSgrXtOBlw/o6lGMeQZR5MK2OWhrF9OvRE3kxRaZ5C1q8vI8TQ7ODS48MxElSJeoR4qGRDwKb0FbU2SMgBpDvt5pfjTnwV3QovgxmeLSX6fRN75deDnWXM84dRp47TXRhiP06n+a7bxc+vo3qe7iQKc4T5NyVSgP7u+C3EFPSEtaXksK67pLgMUtSn7LuQ3j7ZvhtOlTJP6EWOH4nr/4DnD8lAp+NJxRezNS4eWEWcs3jcsp7K8QhTXGxgYFNB76YcBsNuNrylyy+DZdQK7ouEaFM5o9/O9av7ubiKl1UgDShbuJCh+i3W0jx/fBvOhSxM4fJ7Lxp4D20U3AhzfSh+WRGflUlnx5/JGuqSRk4oU2EgtYTdHtyaBwWqvqaoV78Cg55ynzTHKEzWElkRNLsmuHAeicT+LfHtRG3v8XYfALo3vnYzF/g+rHIccrYyfe1g4uXgB8bqtCcYVYQ5k5cGL+N/fsT96oLADCDht/YrkcqhxqwmsXsRs1PIk1rtiU5dB1NqI5ZQdTlaheJSKMM0uXFi4RsUJxsdQGKndnZp+cQ/vffq7JvYfVtsdUARxUDXsxaZ1XXfnq54Er1hcGOA1AOZkDhQFiFtXQkFOsCSC5JkQwrxzGYZasUCTkEbNoBo6rNM1ZK/l9Qjpl1eOUUeIYD+BRMhD+41GtUzLX+wJRX6wQAF4LNXsvs0peccQ5henr6fIgXcYI3SjPdZAYDKYmxwzORtIxkGpitdSk8neOtN75AvDmm9qhv+Kq+qVRCABbEhrXn9819R5sBGAiqJU/iqnKPrOdMnmVM12pAK5pimnc49BhYPszyqpq1K4ddOyLBNxvJ9SeeZwjxkAcBWI/FgOtv9KXKsxra2c3eMw+D5xLAthM1FdbJovkrkx1ugye/5fAu5fAm3BMZz4AunI1vKEvjx5xQlqMU9JC8AqC+22luBByoU/yYQDlCMOGEcktFk6OL2jARmmR6J4fBADfPmPGiLqwMLdfvTmKf/4XUlaSwLFxfj8B9+akCSKPcwL52C6K9m7CEWk5dksb8YZ0OQ5Kq3FUWpa6Jrz9AqmSWWJuovQ6DaSCtp8TttDSpbMXvF6/hNeOWVBOSostFEPb4Tie3aOJtRfZ00XA7ZwyR8vjHGF6Z1tu9ILUgO3SDaK+arqaeECO2RlGsxfDIdhWLkWYAOzsnp3AsTw7R2b3/tMSRo+H0e/XgnZ5MJDN8x8RcEcK9bx8ANR0QgaRje12qREPSdvwqGkrDkgTnFNvlMAuPAZpCZHds79FZ+fMB4tNF56rcOEi0NZGCstZPXuMM2jMvbZTfYSkwrM8VFfod8gHQO2Vfha6Bb/x3IEXpc0pk1EKBmAsiuG5K0Wur27VvWqaAWO7rIywTB4cVABjg5tB4wStaQMSbCMcVFnkDgJtlzrzq2glHwDPJXZ+6ribKG6KCYB4TlwihD5DOe9dLtY555GjE+9JWLqguHGaPGGEZ3qz6SJWrg4oK1cnwBKVg8cyvwYPYu5T6+tcCbBpXc03HwA5uon7mbW6hwwXTwEyOPEaQ8HM33kuXo9mlwdm+vtTT1PL1CojGYnRDHeJYkM57cqWQyx5hIOVrMRE13BUGXZkcHgFTM7yzxMjg4ltYolxv3GK44QnDMpkEo4L49AiDmvngdXDBFbP+80dcgJILxm93ideeqWr9Ygu3XZxALSEhlG2ugX+Nw5gsFemWsyvtyJu1y/haoGlX0QGMM19Eso0rnZqgxk7MT/f8C9mESvD+4m9by4EgO6Un06MYn38bVyH57HJ/yre8QSE5FfZ981QkrBXqJX3OTbdql0OITaHdIyONedRVQFjjnx3vKQckap5utWqM3+6eaiHk/7wPNn96ct+z2YAOazmj0N79lJLhei/qfm47E4rFsuHsE7ei8vkN7FSfpfQSPKyJdTk25VQgnlUe6gh357ss4h73MQA8kBwPsu58iCypESFswvxXfUebrXjsA3EjLqrGBplMQHcxf+YSM1fPPw2DnmvnNBD5stn8SH5LVwqv4Mr5NcFcCelEMJZfKLzUyd5XEP151P4RmVwRqc0ieCjWESk1xIj87GIEJrKKL3WkZ4g4BgwTj+drjrH6W+nocwl2a3WY+8Hq80XQNJelKlnDcd+h0MbMgNYQmbPCvmwoCjeriIq41qB8bN+vdSne7Nkp+WoiYY6bTrVpnwBpEZl6Hnhyma14avV3yJ6zHFqjwJefvE6LSwXza4SSMTyTXaX4tEn9TjmHzTFhnoXQY7zKM3n1POH6Pmvq2Dy9i0CdET3bkzFlaoYKE1zlByeLLs2XEc+rXF4ZHib5ZLVOPSX20mwnCI2eELUBdQZGbAmuZXzCub14EFS189czAIg2X67XgGeUvzynI2hLtvwCr0XexK+QPVTUNNlZv1YjpwmFml2OGG2OUVO8ORvu5h0aeYM8naHWLN+WF2RO+O9qM0skixWF5UHexDpPA85NfCJqXGAs2bS1kM2bdZ4SV4qg2D4P7R7nx70nOw+j3Xk9eVJBjB64CB2Hm3E0kVTI32PSxndyEQMbDivWKYByLPG16iKVAI0Zmm3UP0qdCta2ssrRZpoXtvXZHeqwCRBmmgKsUqXC16vV2TtTw9I5saL8LtzHCspR1ytHIvTewHRc0eIOGWTwwHf3EYlLKOKJGgV0Z6XxDDHRieSMLI58+obsL21T2RK5qCUPywGC+XCk164d7jpgVMGkD+ghPRHfxbG0TRPCYhS54B+ggEk4BapoDHFCaertcQLT/MylMxZQCAVPiiYM0rV1taK1dV4AZSIgeEYjRNFXjiJ8jIZt92ast4fvPRqC7PM1vsISfkf/gR4+jl8hr7xZqLCx/J9v7wdVXRT5g/P8P5Lu1Oy5k26lLoNPCTUTquWaT+/QB/2gmpI30OkW+ZumI/aq25A40dvQenCVUUBT184iLm+vh4+ny97VDrnhwmHsWxJKngcxNRYZXz/Oz4rllnlJL//pMrLwgKoFhGbz66lt/ZPvVHKDaK8gqSkf2it9pOVks2cy7t82aWY+4nbUX3Z9UVLyp5dVkliakFDQ4NgreN0B54LSO94tlWnURNTXN6keI6MCgdZfXkbTNQHGPr7igUgz00TgYE7ni8Ae7IobDRb0Y8HeuYvQePHb0XZ0kuLTm05G400k4qKCkGR6ZN92GHAju5EJk3XBEzmzVcBi1pEUuB7iQobCg6gauf8lPdJ6OJiV3GpkBRBLFBdd5y7Rpph0844VVh1dTVqamq0rFNSiZLs7OLFpF82fwoH7vycyOjMsP91MSiQC89cCrH2+Ounpt4IFZ7ssTaBUSV8kctYTwfikcmPzPSSFn8SPnTnEC887esqooT16/OPD+U1hpmt8hYlyoB2YjHH0Qn6a1jub1iryf1lhdRCE1TYpUZr3/G7l8iu2Erq4BQCYTlWpIxU6wF/Rp0AK5Yn9uMY7WyDe07LhO7P8dovoQlnkssCYw6GsRlnqZtHdWyRZNCXgbVrU5//zjvAE09QB+jNLR95xhavdGOy23HmvRCu3axo2TXlE2uTL94udAymxO+o5lJBKZDL/+Tv46GaXz8zdSr0eQ1YbIViQwkq7J84z95Ftr0ePC5t8OIJLMGAzkN2222p4CVY2rp1wAMPAJs25X6WQw1QjZf4hCLDE3cYwPgEhzTnzwWuvlzs/hERy5qCA0hUyMNLYlG83+xQBzynUNhGsmbhBdxJ6tU5F7HRiSWj3Y9aetHKLA5SO35DIJ5DKa69VmGb2WUdkQHRwbZtxhECLAdZLkpenxgXOdemgOefhJPsszdrouUvi0GBXHhtmRhPE/vl41NVz7NTIXtl3KqmGgvnL1BOE9W9nUORi8BMavUCPLi3GmfzSMpx5ZUKiEaeR0GFHoVlnDmtOkknkQR5XqNGhVuMZOGkASQqPJ1wMrNJ0T7FZeaN7KRkXtj8eNFFePAyyb28XUxDc3DDD5rwxpu5fcJXXAFcd10OAHk6tqsEx9XUICzfJzOx+LNJp9r9xaDABHkHOfjoX382tRv1GMQkJ7xXEf8QYmPG/GiQ5NpzaBHKy0TKsagPn/75Yry5J/d1W7aQbC43loOyt0ooPlx5KsGkqHAOaaSXCoq/jaiwqeAAEhVyaom/4f29B4RTdlLlYp9iMmQqPKd88RKVhRJ4Xa//Vklal5ElmvAsscQwJhdG3iW78b3HfTmphTnC+vVZbFezWZGDZYrv7KQ6YbVveHJtc8unlFnfUNe2KjQFcvkHIXKo/PhBZWrYZHyiRpMeFxGAt96s7HMqzMGjmVdReY/knp+UEw9ByGbCwrRxyHxo8uRwiYhIy1WMsssLKnSXwmSz4fCRpByMTGKi8PIlSiXl6UuZfKT/T4ABACFAKoF1Vl4ZAAAAAElFTkSuQmCC')
-
- e_wink = ('Wink',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEU4NTA4QjM3OTk2MTFFQkEwOTNDM0Q1REQ2NURFNjAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEU4NTA4QjQ3OTk2MTFFQkEwOTNDM0Q1REQ2NURFNjAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4RTg1MDhCMTc5OTYxMUVCQTA5M0MzRDVERDY1REU2MCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4RTg1MDhCMjc5OTYxMUVCQTA5M0MzRDVERDY1REU2MCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmA0NjoAACG+SURBVHja7F0HfBzV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')
-
- e_zipped_shut = ('Zipped',
- b'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UmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzhCMTU0ODc3NjZBMTFFQzkyNzFGNTJGMzIzQzdGNjIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzhCMTU0ODg3NjZBMTFFQzkyNzFGNTJGMzIzQzdGNjIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OEIxNTQ4NTc2NkExMUVDOTI3MUY1MkYzMjNDN0Y2MiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OEIxNTQ4Njc2NkExMUVDOTI3MUY1MkYzMjNDN0Y2MiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiFa8hIAACO+SURBVHja7F0JnBxVmf+q72Nmeq7MfSUTckAOQkgi4UiEDaBAAuoCggeyCioKiOwirri7KouyIgoeyyEgGmGNqwQRcEm4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')
-
- e_not_understand = ('Not Understand',
- b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTE4QUQ1ODQ2Q0U5MTFFQkJFNUJFNkE0MDVDMTU3RkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTE4QUQ1ODU2Q0U5MTFFQkJFNUJFNkE0MDVDMTU3RkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MThBRDU4MjZDRTkxMUVCQkU1QkU2QTQwNUMxNTdGRCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MThBRDU4MzZDRTkxMUVCQkU1QkU2QTQwNUMxNTdGRCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PvaUPHYAADXuSURBVHja1H0HfBzV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')
-
- e_blank_stare = ('blank stare', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0VCODlFNkMyOUM0MTFFREFCQUVDNUFGRTg5RUYwMEMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0VCODlFNkIyOUM0MTFFREFCQUVDNUFGRTg5RUYwMEMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_cool = ('cool', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjAxMTUyM0IyOUM1MTFFRDk4RDdDMzgwQzNCOTA1RjAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjAxMTUyM0EyOUM1MTFFRDk4RDdDMzgwQzNCOTA1RjAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_eye_roll = ('eye roll', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzM4ODc4MTcyOUM1MTFFREE0MUJDMzNDMUNBNDM4NTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzM4ODc4MTYyOUM1MTFFREE0MUJDMzNDMUNBNDM4NTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_ok = ('ok', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjRBNkQ4QkZEMkMzNjExRURBNDc3RUQ0NkI0MTM2OTdEIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjRBNkQ4QkZFMkMzNjExRURBNDc3RUQ0NkI0MTM2OTdEIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEE2RDhCRkIyQzM2MTFFREE0NzdFRDQ2QjQxMzY5N0QiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEE2RDhCRkMyQzM2MTFFREE0NzdFRDQ2QjQxMzY5N0QiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6AqwGBAAAurklEQVR42ux9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')
-
- e_question = ('question', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUQyRkMwMzAyOUM0MTFFRDkyQkQ4Mjk4RjE5NUM0MkUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUQyRkMwMkYyOUM0MTFFRDkyQkQ4Mjk4RjE5NUM0MkUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_skeptic = ('skeptic', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Qzk3MUM5QzIyOUM0MTFFRDg0NjRBMEI1RTRDRkE1NzAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Qzk3MUM5QzEyOUM0MTFFRDg0NjRBMEI1RTRDRkE1NzAiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_sleeping = ('sleeping', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODcyQzE0MEUyOUM0MTFFREEzRTc5NzhENTQzNDhBQjIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODcyQzE0MEQyOUM0MTFFREEzRTc5NzhENTQzNDhBQjIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_tear = ('tear', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDlENTU1RjgyOUM1MTFFRDg1RDE4MDJGOEMyQTQzNkEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDlENTU1RjcyOUM1MTFFRDg1RDE4MDJGOEMyQTQzNkEiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_upside_down = ('upside down', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjBBNjk1MDcyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjBBNjk1MDYyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_wizard = ('wizard', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODU2RDE3MTgyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODU2RDE3MTcyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
- e_wave = ('wave', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkRBNTQ1ODFGMzQwQTExRURCNUJCQ0EwMTFGRDI2NUM1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkRBNTQ1ODIwMzQwQTExRURCNUJCQ0EwMTFGRDI2NUM1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6REE1NDU4MUQzNDBBMTFFREI1QkJDQTAxMUZEMjY1QzUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6REE1NDU4MUUzNDBBMTFFREI1QkJDQTAxMUZEMjY1QzUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7BCSZzAAAtj0lEQVR42ux9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')
-
- e_crazy = ('crazy', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjY5MUNDMzIwMzQwQjExRUQ5NzAwRjUyRTU4MzA2QjkyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjY5MUNDMzIxMzQwQjExRUQ5NzAwRjUyRTU4MzA2QjkyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NjkxQ0MzMUUzNDBCMTFFRDk3MDBGNTJFNTgzMDZCOTIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NjkxQ0MzMUYzNDBCMTFFRDk3MDBGNTJFNTgzMDZCOTIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5mF7EvAAApLklEQVR42uxd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')
-
- e_glasses = ('glasses', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE0NDBCM0JFMzQwQjExRURBN0RDQzM2N0I1NkY0OTAxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE0NDBCM0JGMzQwQjExRURBN0RDQzM2N0I1NkY0OTAxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTQ0MEIzQkMzNDBCMTFFREE3RENDMzY3QjU2RjQ5MDEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTQ0MEIzQkQzNDBCMTFFREE3RENDMzY3QjU2RjQ5MDEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5EdTqxAAAnZ0lEQVR42ux9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')
-
- e_head_explode = ('head explode', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjk1NjQyODBEMzQwQzExRURBN0U0QjkyN0FBQTc1MTQ4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjk1NjQyODBFMzQwQzExRURBN0U0QjkyN0FBQTc1MTQ4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTU2NDI4MEIzNDBDMTFFREE3RTRCOTI3QUFBNzUxNDgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OTU2NDI4MEMzNDBDMTFFREE3RTRCOTI3QUFBNzUxNDgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7E0s7FAAAiwElEQVR42uxd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')
-
- e_laptop = ('laptop', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjIyRUJDMzFBMzQwQzExRURCQkI2RDUwMEU5QzE0NTQ1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjIyRUJDMzFCMzQwQzExRURCQkI2RDUwMEU5QzE0NTQ1Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjJFQkMzMTgzNDBDMTFFREJCQjZENTAwRTlDMTQ1NDUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjJFQkMzMTkzNDBDMTFFREJCQjZENTAwRTlDMTQ1NDUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5fLI6QAAAjoUlEQVR42ux9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')
-
- e_party = ('party', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFDMzgzRjg5MzQwQjExRURCMjg3OTFDMTJDQzQ4NUNDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFDMzgzRjhBMzQwQjExRURCMjg3OTFDMTJDQzQ4NUNDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUMzODNGODczNDBCMTFFREIyODc5MUMxMkNDNDg1Q0MiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUMzODNGODgzNDBCMTFFREIyODc5MUMxMkNDNDg1Q0MiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4KgKfvAAAojklEQVR42ux9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')
-
- e_rainedon = ('rained on', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZEREVDMDY0MzQwQzExRUQ4MzJDOEQ0QzJGODk4MzY4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZEREVDMDY1MzQwQzExRUQ4MzJDOEQ0QzJGODk4MzY4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkRERUMwNjIzNDBDMTFFRDgzMkM4RDRDMkY4OTgzNjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkRERUMwNjMzNDBDMTFFRDgzMkM4RDRDMkY4OTgzNjgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7rB3aZAAA6X0lEQVR42tx9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')
-
- e_reading = ('reading', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjAyODk1NEYxMzQwQzExRURBODVFODRDNzMzOUUwRTREIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjAyODk1NEYyMzQwQzExRURBODVFODRDNzMzOUUwRTREIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDI4OTU0RUYzNDBDMTFFREE4NUU4NEM3MzM5RTBFNEQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDI4OTU0RjAzNDBDMTFFREE4NUU4NEM3MzM5RTBFNEQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6qdxYAAAAgcklEQVR42uxd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')
-
- e_santa = ('santa', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNGMTBBRkM2MzQwQjExRURBMTQzRDIwNjlGMEJDMDM4IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNGMTBBRkM3MzQwQjExRURBMTQzRDIwNjlGMEJDMDM4Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6M0YxMEFGQzQzNDBCMTFFREExNDNEMjA2OUYwQkMwMzgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6M0YxMEFGQzUzNDBCMTFFREExNDNEMjA2OUYwQkMwMzgiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz57Dg6vAAAm0UlEQVR42ux9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')
-
- e_search = ('search', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkI2RTlEMEI2MzQwQzExRUQ5NzVEOTcwMkM4NjRENTdDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkI2RTlEMEI3MzQwQzExRUQ5NzVEOTcwMkM4NjRENTdDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjZFOUQwQjQzNDBDMTFFRDk3NUQ5NzAyQzg2NEQ1N0MiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjZFOUQwQjUzNDBDMTFFRDk3NUQ5NzAyQzg2NEQ1N0MiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5fHY4pAAA3AklEQVR42ux9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')
-
- e_depressed = ('depressed', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo1MCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo1MCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDMyOUQ3ODYzQTE5MTFFREFCRDc5QjJCRTEwMkI3MDQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDMyOUQ3ODczQTE5MTFFREFCRDc5QjJCRTEwMkI3MDQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_gold_star = ('Gold Star', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkZENjgxMzIzM0VENjExRUQ4MDhBODgzMkUyMzJFQjBFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkZENjgxMzI0M0VENjExRUQ4MDhBODgzMkUyMzJFQjBFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RkQ2ODEzMjEzRUQ2MTFFRDgwOEE4ODMyRTIzMkVCMEUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RkQ2ODEzMjIzRUQ2MTFFRDgwOEE4ODMyRTIzMkVCMEUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5xZRiZAAAp3klEQVR42ux9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')
-
- e_honest = ('Honest', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMyswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMyswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTk1QUE2RjUzQTE5MTFFREI4MEZEQ0E4MkMxQkZDOTEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTk1QUE2RjYzQTE5MTFFREI4MEZEQ0E4MkMxQkZDOTEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_ill2 = ('Ill 2', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjgzNzQ0MDBEMzk1RjExRUQ4NjkzRUE4MzMxQkMwOURFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjgzNzQ0MDBFMzk1RjExRUQ4NjkzRUE4MzMxQkMwOURFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODM3NDQwMEIzOTVGMTFFRDg2OTNFQTgzMzFCQzA5REUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODM3NDQwMEMzOTVGMTFFRDg2OTNFQTgzMzFCQzA5REUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4vuqT+AAAi+klEQVR42ux9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')
-
- e_ill = ('Ill', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo1MSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo1MSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUY3RTI3MTMzQTE5MTFFREE2NkRDQ0NBRTIxNTBCQjgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUY3RTI3MTQzQTE5MTFFREE2NkRDQ0NBRTIxNTBCQjgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_key = ('Key',b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxNSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxNSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzlGMzg5RUMzQkM2MTFFREJENjM5NzFDOTY5QkQwQUUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzlGMzg5RUQzQkM2MTFFREJENjM5NzFDOTY5QkQwQUUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_mask = ('Mask', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI3VDA4OjI3OjA1KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjhFREY5RkMzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjhFREY5RkQzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCOEVERjlGQTNFMEMxMUVEQTI5QkJGMUI5NjczMzJERSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCOEVERjlGQjNFMEMxMUVEQTI5QkJGMUI5NjczMzJERSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkdNbj4AACZFSURBVHja7F0JfFxV1f+/2ffsbZp039KVlkIXutCP0tJCLUuBSlGUVVE2QUQRBVFx/QQU5UNALaCiAgVklbZqC3ShdE/3pk3TNM0+mUwyyWzvfefc92ZJMjNZmqRJ9f5+t286ee/Nved/z3rPvVdSFAX/Lf23GNq7QZKkftOZRVlw0kWv/deiVS51cbc1rqlBsL/0qT0Gk9q94QwDSKAMpUsB1WFazaOaQzWDKzUvm67p1A1zZ95Lz3noUkPP1dLVTZWvlVRLqB6nWkT1AIHt+y+AHQdrHF1mUp1BdTr99ERqnq31fVbiq7xcKDnZkLIzAZcDMJvV77nYrCRajC2faWgE5DBV6q7XCwSIB2sIsupaKOUVdHVDkuW29KM2nKA27KDPn1DdSnUTgdrwXwBVwBicZVSX0M8soqbkR/7GAF0wHdK40UD+ICCLgLITMEYjt0lH/+i4dVovu0cihglgvx/wEMAVVcAx4sWde4BPdwHBYJRzQ9TOjfRxLdXXCMx9/1EAEmhM+Uuo3kivXsYcpqNvZk4DFs4Hxo8FMtMBnYGwNQ+mShLTTAia6Goiyal3ETWJdRqIKRqIus0k6ZRwj3NCUzNwooxYcDvw9hooxL2SBuhe6sPL9PF5ArPirAWQgCP+wW30urvpJ0cZyHy6fDGx3gJgKOGkM5IctJEEtY8nWTiKwBpIt+tiLwgQS3hJgnmJgv4TZ9y4YJG8jTjzj69COX5CkIk58xX6088JyB1nDYAEHFu6t9JrHqWfGkD6SVm6CNJiBm4YsZpzOtWpBNrIloAJmUb2g5dUT/0WYoFj3J0+ZyX6A6QUaVy98R6w72D061epfoeAPNivASTwzqfHX6CfmOB0QFm5HNLShRKsOQRY+jziuPGaLmstr46S4b+BwPu02/Rbb5TCA8BLxIM7dgvRKlO/f0Jff5+A9PcrAAk4tgF/SI/eT1VavhTS9Vfr4MifS4b/IhKPAxK0NEScRkPZva5PiMiulhJyRLbsBN55F0rZSUG+/UTiGwjEbf0CQAIvhx5ZTa+dO5Rsym/dDYyeQhZK9lXJgfN8TDY9yaCQu99HRsLkihSStPeT4Fi/HlizTtjKAaLHbQTii30aQAJvMN3+bzZSFl4IfO3OdJgGXw84piR+oJ5EZPVqsiprElt+ZPf4Nf/cI6WRBoy1pRkWUZPqJnqOn5foqTThsycv6S0CNaSOlSZ6WpV6/KzUSd1bSa87Ual+PkHC5IWXoDQ2isY/SCD+pE8CqIG3RZb0eRO/tgwXLpqIEYMWQdY7ECSJGoAJYejF59qQgncqa7DHZ4wSul5yQSYjJkQ2TyPsfY6z9NR6h+a/2+CDWfELcBloK/XApdSLz3ZqvVPxormuHtZQPexyPZT6euz74zalec8BSTNuHutTABJ4LrptM4E33v/LF2GafD2uyW5jU4qynWiwikanX8Z/VLGH6zH3p5dA/mQL//cmAnFVdwCo66b2raLfGa889gTMBN6KJOD9g1Tcs+X/eeBxadS7sPGB96AbNYrDc8/SoJ/eHe89bQCpIbfR5SrTjTfixLS7cHV24vs21gOra/qiJ9d7xWvIwL5H/y6FzDYjgfhnLZR45gCkBgykhjyuGz5c+fjKX+GGAYlf6CaL7K/V+G9ho8YxAYFv/5hEI0bTfx8+3fedlg4kAJ+hy5fdv30LzrGfwXU5SeRrBbDJm7ohTngJfFkYCCYlQKZOUBgEiaxINijYUEhUTGQu2RLMALGBVA9XwmeCkrGN4RQxrtjw8oppRkQNLR/9QhDGrhOd+nTxo9Oh27mNw2+jSB+WdFUHGk6D+4YTtrc5phQgnGPDHWkHkUW/xZYYE5EB4GswUIXcupeElcZWnE1034d0pU4FAt5+y00MIgPP7oxPsokB0kC9FD2k/9eE03Ckhj7rnGjQpcGrT49W84qrEdixjen/Xaq3dbUNhtNo/1dpcOjunH8QF9m+SW+6LbGCq/4DJsmbz0pxyIM06kO27rsiWA073OocZFvOAn6ZSz5jBW4gZvgmcWFtrwHIMwvMfRlpwLwL6AvXzMQ3cmSl/pO2ji7pwyqqjSTpQiHA16zOxfH/+drcrE64BgL0mfzpUDj2faTzjQnmyRs6MHduMqq1BRD0f7NJE896wBKZGKYrT3U57LHvI/dazEQ8+s5GZojLKeYvxXetC9/b5E+kmoC5s4HXVotIxa1Uf9abHLiciJi+9BJ6gYl6Z5+Y+C73v4T2ER9Jjb3+DrBuA4FXc/ZxI4M5ZRJw5WXq3GYUQGNiALmcMxl4620owSBu6XUA+Z+LL2QPlVoh6RPICGKhug/Fx/UbSVw8q86hna2FpQTPD3JlAL95t8q55hS2jom489xzIW3ZgrEk1SaTGN3T4wDSDzmI/ZeOGkFig+dceUooWZxT9uHN94Hf/K6VRWh1QjZT73R6URWdliJBV/ZyoTOothrLLf6/NkAUvj9iFEva31qPG32KLskymd0JogicLKMpMZEYIyw/Rf2ePkviKosqhdXZfykcit4jhQLQNXroO3Xqa8t24J6HgMd/kBpALpMm0P0iOIMVVPf0Bgcu5AywuRG1Z08CoOdD7CoEnv597KuwIwPBgSOhmKxnhk14gCTyVONA73KggYhi8FTAWHFMgHriJPDY48BD96d+bPhwwYksRi/XLNIed+QX8D/nncPaP5uGQFrbO/xlkBuL8MRvtcHMIiY9F4EhE88ceKdZ5IZ6BE+WqLWsBKHykwjVVJGQaVA7yTkV1Ef/8HOiUmAnDeBNW9rhILp17Bj2xzGZpFtmjwNI7byY0/bGcAaEZXgS7tuAjVuBsnKt8yQug7mj+rWO0zlc0DldUTZVSJQqzU0Iu2sRqjwFJeCP6+vo6HOr32n/3aNHa/49cFGPAkgjhBNoJ0war5rXsAxLIErI9vdswT8/jFPw2UMS6qv+VvSudEjmtr6CQr5QqLoSMgEqVIUrG4pZDXMWl5DVXZn6vUOGRD/O6WkOPJf/KYgMMHN+gojtLjT5fPhke+QX9Ag7M3G2FH1aJiAl1oFhd7UAUwxaVyyuWLg39TsHDlDtOSrTegXA0SMidnBuAutzM7ZsUx3xiOGSMHGpnxaJPHmdNckkgqxA9tZFuTBSdu1uZ1AQeIPzhZCaRlJO6kkAp0YB1JETY8xq5QzVA7592ByXvhN25Zx1Pp/OkZbc2GnyCXeFjTVZE6MVlWoaf6rCABITc9R8WE8COIpVQA7jZshKID4/Eb7Szj0xiydsTz/rAGQulExJ1tIoGogMpiOmOoqKUr9zQCzfa0yPAUh4jM2PSE1jAgA9m4TSrq2LOewR4X7WcaHNnoIL1ZBT/OA9fCT1+9Jjt47qEQA5AkMsnj1oYBIAyfeDvxTb42IJZyP3RQnHejCJthIuBYlR2eaK6v+jRTGfOFHJ6GkAqQiTMyeim/XOtuKTLa79cSPxLAaQ/SjJaEouRv3NAjwBIhUfeRiVKdwJhyOmDnsKQCGlMyOYGFoByLFPKgcORwUuZIsDZ3ORzMnzUhW/OvcVT4MTKRLOeVrKoAZwsnsKQKH9MtKipljsL03FQLBKTBlVa9aWYraelvvAAW5/+kD4Bo5EyObqdXBCFjt8A4ajOTNPDaInNGZMnQLwZFnq30xTaZvXmXZ2JpgtRkaaKwEHelXuOx43wmRL15Jzm7IH4+S8lag+52JBxOgIrTyOAdvfw6BNq6EPNPUIaIreiIrzl6J8xjI0DBoTjR7pgs3I2rsBgze8DPupmDUimVIAyA4968G4PpS3s3ownUhaW4ucngJQODVWa2sdKAMN26JhoxiAnRSfRKzS+Z/D8YU3C0K2Lr4Bw1C85HaUXrgSo998Atm713UreJ6R03Do2geJ69sGJ2SjBVVTL0HVlIUCxGFrnhfTSRIHrTmmKCdOdFWCAYAlEXOwHEZFOwDarDE694QIFYjZIwDqND+Il4IFVbl5Kq6BisnWKXF56NqHULz4ywnBayHabGk4sPJ7OLb0rm6Lr5bNvhp7bn0yIXgtB5lODLL9n/thtJ2SITkPCAB5AJhVojU1xdJCEhWLVViq9p4CULBUJF+E7OgW4lMAGGdlySZLh19cvOQrqDx3caeIfnLuCgH46ZaK8z+Do8u+1qnBUDt+Dg4v/4YKoD4VgGo8UTHGaOFOsQArklNDLpu9J0SouNcYYRCeEedZam8sblYdFy5SjB3b9aN++BTSede17EjNSdgrjoor6zueEQ8TEYLOLPhyhqIxbwxkg0lwQ3bhejhK93cJvAC9r+iKe9Xu0G/Yy4/CWnkM5vpq6P0+YbzI1A82ZBoHjkBTTizKVTntUvrtDUjb/FZyAMOhNgB6yNAbNCjx/XEq1ditANKIuFaSpJX8+Xd/UnDL54CBBQRQ4wE1/qmVusgqLZH60DHmLptzjZAbruN7kL3nn4IopvqqdowNAxryC1A/7BycTrI+D4Kh61aJAeA6XiiMlVQl6MhAzcQLUU21bvT51PZrkf5Jigm/CIBxXNqQZIOSY8Xqjhi8A4eiyH8jmt+/pga72zUd2sv8vSRbupQu7xrIZHZlZKK2spz8FQlXXH8xPneVD47Qxui9S69Xt+NQSHw2jzq/Q0T0Dp0Eo7caFnd5v/IBmXubSBo492xAuM6d1DAz5g2B3lMJU9kh8dUS0hTzL4zdUkVj9b33gf0HNGd78FBUlpbQ+NfVKbI87oNqpeJ0daBQNL9Z9yle3luGh57/K3LyR+C1F9fiC5/fjFffiu2hErkqnYh/OksK+x14Qtx5a5B2dEdqSRNhjjh6RGjEmw29/gbw5K8kAd7UeQsEjf+48zhu/8HjpJ1kDpms6A4RKpSZk7iP10nMv3IF5lx2Jf7++6fx51/8AM++WIs339dh5VVxprR0dgawTyfsFnWHfMC6fwIbPpQQCCgYNm4Cbn3kp5i5aGnMH8wZ0IL2p8uBvGUG7ls6Dx++9ZpYbGEgbbv89q9h1adFWHHXA3B7jHjyt3ELYc6C9IluDRDEcem2HTqsJRfWkZGLe594Dr9dvysKnr+5CX958sd44t4vKURLzl98szt0IKPxKL3wIbpXN2HGbNz2yM8wcWYsfYNl9qoffQfrXvmjAJiVdoAMjMiEZqf8ebY6OWGIRy29R9FyR88Q6dU8UDmkXrlvJnMLX1X2NSLsTp5qbswfCkPNCZiqSgRtLHY7PnvXN3HNHV8nH1+lD4lLrP3bS/jDYw+h+tRJ1n819N2XyIhZ3W1LrMkq4pzF70e+n/uZ5bj5uz/G4FFjo/cWFe7Esw/fjx0b1qmTuWkDECTTWzGY2qGTTJ0shbGOdKHm/LZph8GomvUsnvWcDGzQkn51UY6PJghrTncL/SSHYu/SEnYjvx1N3uUk3bgacQPaWK9WF/VrqJhtkRu9SY0YfTggNkzQ+TwkRfVY+sUv4fMPPIKMnIHRe7b/ew2efeR+HN27m+6RIMsKzwbnEnheVY12H4CfpctfvvhZNX2cN7XRGwzUqC/jBmpUWlYshLd13ft4/tEHcGzfHlKHegQz8hDMGpyQkzgkZT6xF1KTF+nZAzBryTLk5A1Gg6cOjfWeNtXnrRfXYMDf7fxmdThhd6W1rE71anO6YCAnuKKmEh+9+mcESJkFyTcMGB0I17dcv6ijwWL218EYVGfmZ5PNcOvDP8Hg0QXRe47u3UXAfUMAyCQ+bxpQUiIW/Rz4oBrjY3ZQ9wG4kC5rvnozcCU5Fps+BZ57SUJpmUIddwixcDWLBYs1KhY++MsLWPXj76KGxQK5IYGsISL5NV5HmskH05FFt/j6m3Dnz34Tfb69Eg6F0NTYQEwTRlODFzJxEoPbkaIn0Wy1O2g86QVo3EcGqUNuTziIYz43Xrzti9i99n00ZQ5FMBQhpkzAeWAKqsm+486biS89+r+YNGtuLNhRVoo/kLpZ+9cXBTgFJMCWLCGWI6Z87EdQGhrxMXHfvJ4AkDd72blyOXDTSo2IJHXeW8fbS+ngrpORlTsINz74Q1yy8kaW41HF/NrTj+Ovv/yJIDhILwZIrIbJj9IR15mLd2Ha/IX48asf9Jvdgfc1uRGiAfTw1AI0+prgtebAFPDCQpXF8KDhowTHzV12dbRPLDWYBqufeQIBvx/5eRIuXaJg1KgYLb+jLrh+nQBc3lEAOxMLLWsdLuN0uM9cAqx6SsbnrwHqqsrxi3tuwZfnT8HWte+pHEYcdf19D+HF7Udxxa13Qh8KwERcZz6+Bwa3OkG2kv7en7Z2dpIRo+h1uPaRxyAFm+FqPAVLcx2caWn46o9+id9t3Id5l1+jbmEYCOCN557CF84bib8QgCZjECuuBe74agy8iF8YT+duD2bTqKii9gQSpcfxTrlfIN14wXR1tBQf2IuHrrsM31y+EEf2qDsvso684ydP4flN+4QBxIpd71FDZuOmzehXboFFp7rPQyarO1AZyPi47p5v4QVyq6780t3CzWLO+fDvr+LWORPx9IN3o0GLM952i4xzp7b1tLyxENuJHgEw8vKKFGHK4YNjEQieyGRr9I4F5+GnX7kBFSeOiz/ljxyDh1e9hiff/VgEBwSXWm39CkCTZt3qtKmku372tLDIHWlqvknh5o/wtUtn4wc3X4uy4qNiuZxC+pG1SnaShIk49V3SYwASLkXllaq8TlSGxqXjsIntHzYZYYNZ+Ic3zyrAc997QFiXXNifnDxrXr90zA2twmdpWSoqpUcO4tEvLsd9n5mH/Z9uRtiRieYRU6IuDIOnS0Lx2phkK+5JDjzI4JUnya4SK5YiL25uhGxLg2/gGDRZsxAIyXjl1z/HF0kXrH7mSaEb+m1krNX/2UB56oE7cOvsifj4nddp0FrQ6BiEwODx2kJQteQNSv7Oytg+Ogc6NZg62XYRUufFi/kJGsML/Tnlgmee2cLkSIbObEHQaKdqgznkg9RQj2e+cy/eePZXcGVm9UsA9a0U2JNfvx1BfzMZNiY02TIRMlghWSzQ0X0qHdSSn5/8nZx+T7fXkg/o7kkOFOtsjpYkczmASRFflcxpXVODmoKuU3eY9xvs8GYMRSgzHxWlJTi089N+yoMtAQwGg2i2ZMJrzxXgCcJqaRS89DpShiVZ9cApNWVlwu4pPF1p0F7ZJUJmx5LfMHVy3MsbVX2ni3POZX8QTXobmoZN6dS0U58KTreaRG4yZyBgapnEJVnVBBe9TwWQU1HykyQMVtcAoaAYFTt6FEDejIa4rPhICgCnnRMnahpUzdx6HYFCjmxABID756yF3Mq5VlqJVF4Eyrkyeh7A2qYKI0cmN2DiMra39zQH8qDaxtlndUk2wR05TFu9BFUPSkG/yGCWDPrWVEi9WKAvA9geUa3qgNV7Y5bJ+HEpfLOY5/dpjwNI5SP+Z8/+5Hpw/uw4LtQ6obM5cbaUsJICQmIzIXF4HzJvTTRiNWli8keOHI2e5XSgNwAUq98LUySCXTQ3zsytU1M6dHbSEbqzY6I3lEJyiH4SGnoCL+JCjBkTl47ZqvAM/cmTAu/1pKLk3gBwJ7XPu21X8hvYHxwxVONIv0+EzXhk6l0ZZwWAgSRH/fDCT71DXXtgcJ+Kfn/+ecnfdbwkagls6A6ftCOGTJhGyz9KTiZ36Lksi8vTNdSejI5OfWY2MaIMQ6gJ/XX/Xr/cEkCeuNUTixmyB6oitLlBHbRQF6yk0n+HDkU/vtcrAGrlbf5nc6ujLIrLSSRo86x8kJWW60/ipBbmYzthLimEvbQQDk8pbL6qxNte9YPS1ApAngO0Vx6C9dgOMctiKom5czOmJ7c+2f/bXSiM2ONdPQWtq5vdvcu/v34jdDy5K/QC9WnvQeAfZWIPTJRzdkRIinIZj0qeI+Rg9phzpmH0Oefi43ffwP6tmyJba/aLEqRB528lQi+8cgX8pMyO7N6OmvKWs0GbNutITMrCB+SMbA6nZWaqxh6LT596nsQbXW1PlwDkqaVFWViz9wAW//BxdUem4hMSQqGYSORE4OHjJopTW0ZPPlfUkZOmwBLnE+7d8jEsTpeYIE3Tm0R16I19GszaUNtUjgXLV4q0CS6emioc3rVdTKMVUeXPhw8XkaiM0cZikZCbq8AfSwR/uVcB5BPJJEkaxrGfDZsAq92OgvOmCs4aNWmqAG1YwUSRQ5LUnyT50eRr1Kw6GTWhZlE5zmjXGeHQGQSYPPfWFwBtlEOife5Q6lwcnvc8f8FiUaMit8ErEr6O7N4hgGVOPX5wn0gL0coSqlu6FNTryqbnvFaCLn/jUXeLlpkm6ZKr01AwiJJD+8Ro5FEpOrFnJ5obG2B1peH7hUUpoo4SrDo9VYO4miWqdDX24OZBLCabSc81E2iNWg0l0NfeoiJ8/6KZcLjSMX7GBVFJwwM4d+iIlFkGnJR1cPtWMVdaWXpcJhzyEh0g2VObnousqWU3fQVDxrQ0sZqJqzhFjkcZjzoGrXh/IYEYmz6SyB+UjGrWnyLL7cYdfURAnxxqAyxPrDKQBlElceUZAD39LX7GQGpl77IZLdM3HBIL0ZXB4Rrgypv0dNI6bmzyiBSSSBoJF85ii4DJUomlE9NKr00CG01mkex00fLrONWCRyMnWFT0ighlX5D/+dMvfgAfiYfy40eJswgsAq206FALUMxmCfmDFOSREue69rAJskkSVG0+FkJzjVfstah0MieGiczGhL8Xjl9NVhqq1fQE62gjdKTXzs0NIl0vi7XwZWVeFG7egN0b10fvN5ktGDFhMhlwBOrkqSIz7oOXV3EWdoA4rUtr5LoKIC+Ke6Vw80fXcvpAVP67dJhQIINTRNnaYsCys5QW+R//LpMQ0JjJ4JLEwWVucobSCwr6nTux7rmnodProLepAzI7V8KM0bEhxiqO18WfYkBP8SYHzTha+CkO7tjaciwCd5P4dPcagPRjipboywd/TKJ6M9UpVy+Tcc0y8m2OJo9Tx0fTbDl66Kpk/N9N1+Hb67dCMRr6DXgnN2/Crg/ehWlgbBvo1pFClpa8B9pgbSKX9wx/+hlFcdcK0B7TROY6oueBrraju04v4yN4tvEx4t+4ExhLarE6yWzFc+tMqKpX32k3K1g8KoAXXwKyBg/Frb99AdkTJqop8n3Wi2/G1pdfwt++9yDSMnUIDzdGM/iXzwxiXF5inc7HJ/z+D9GZBz4nokO71Pfm+YET6FYOdGfe9gVgZEFiLnxzqxF7S3Xau4EHLvfjyBE+P0EHr1ftvDUtHeMumIcxs+YgnwDNHDoMZvpOb7VA7mFwRW/Jag4Su/hIx1UcOYwSMv8PfLweJYW7IWum/9ixwJBzDPikODZNdvuiADIdbTvNq3JXvagGran8hsC7s8O6vpdP8JxMt6+hVw6cOwdYuDB2oEak7DquxzvbY6Ly1gUBDEhTxCEfe/eq0Ynqat6eUUJdXdu2Gcxm5JOPmTe2ABmD8pGeOwiO7GzYM7JgslrF3/Wa/2m02UT7w4EgwpoV7BdrnMmydbvRUFuD+qpK1FWcgpuoe4ws5rpTJ9sQjVckc0ZZFunzrCxgAtngw4bSoNtixMEydUC5rAruXNI2UYvXO/zpZXEGJBPyKar3sArqkwBqIA6hR16h186kziorroU0dEicKAlSL94zI6gZj/8zIYTZBYktSQa1WjvlhXd34A0CPPVqDqWnXgefT0E4fPoBcbaUea8yl0sRGxlxAJorg8V7w/FOgq3JwGflPv52rB/cB+5LfNvX/QvYsEE8y2fo3kvAPd3Ztp2pU6zFoU706Hd4XnPKFOLGBbGk1rV7SPQcUUVPhl3Bl0n0dHWqkAkV2X+FrzzRz1IulOD08khqDjMop6xwRjlfuyKVd5fo8fY2zaejrnzlkgAcFkXkzO4gJ+uDtVBooDH5CokGn+vIhgV9BsB4kUqXn1NdzAKEj5qZMYPci3zVmGloVt+9ZGoI00acOX+u04OGBsjz1P46n9r+BZNCmDgojJ27gI0bodTVCbJ5iLTfoz8/TeB1OQn2jAIYBySfNfENLeaHjEwoYybrpJNhA+oJRB7BN18UQJazf8wPsg5nXW4gzs21h6GrDGHffpE9z+SqJpKyrnuqq75dnwMwDkgOwd1Cr7yOXQ4h1lySMmikTnJlAjNHh8U6Oaul74HGZOKFPQeO63CYDBdPhYzyYkJMVhcj09/XcnCK6l9Ph+P6NIBxQLLW4dQnnk1cRJWTDnSRsEQWcWhuLqScHPJJMgCnU90Q1W7nGKJq2ZqM3QtOU7N23F2TerQdG6u8oIhzNiurRDSFd86SYnRBDT23huMaVN8m0Cp7ZuD0QQATAMrLY/lUZ94daBr9JHNqATUtKUyc6cUz/lzt9th3lhQbc3CItkmbg+P9WjihiMBSyMmWUtMAldQWnjHnDaW3avVQV5KQzkoAk4DKZio7IJyQPlj7zBmnvIkK27OcCp1GzXNStVA38qKbHkCb5dD6Jul1iMa71HQInoispT/Xa5/ZOazRKudB8rR6KdSlXsUElOfMie5+CmAnweY5rf2hzDxxOlrSvoRDsBwSx8GynrquPxhM3bnEui8XNWu4nbUW4jxCtZw1m3kb+lNjidM4MDdFE6vxIIgJZt4kSO9pZ05UkhQa1qPpXTe2DllS5WXEu7rTiuzp0udFqHam3lVUOY1jPnsePfyTbObwLOwrUHeMqD2T/e+XOpBAY0NleRxoQvaZM7Jhyc6D0ZkGncks9tbsElGo+siWCcixbzhHVfI3I+w+hWBZcWRVUTgOzNU95Sr0J0eerUde22vTamR3HSZUSPMNGbA5Ef1syc6FPX8EbHkjYLB1r+ryeDzk69W1IRLn1RjkAJTqMgRKD0c2Ned/OP2AU+A/hrqrbkSpspXq0+opArr6rAKQgLvKYMBPQ6H2D3biwLLO4kDa2HMIuJHQW3p2B4sAee9VVVVilW2y/hvlIEJFu6B4ayB3wPOjvh6mvn6LN6vr9wASeJzx+vr4sVAWXwQpl4Sj06Ee0c1gVbjJ+aLx6/eTQ0Ye2YFDJLNojOfMWADHkNG9Jqbcbjfq65Ns1VVbDuXYbrHT7rixauCAT3HLIvkxMENlUE6X4L1eeL3IP/4FZf8h4XheRSC+0ZMA9qgVytNKBj2eLBgjKY///i5JckziEzGop1vJXX5THFfAidqcgc/t5O3yho8Atn4qIejtPd+ZB2lmZiasViuqq6sRbrWPitLcCJtVwpLFSnx0BiPyaTAmEBBLFkC672Eoh47gSaIBh9lCPdX2nvYDV4TCGHbf9z4vSdmXAid/DRTdT1riD9GzJpgAkwi0fG2uMCBCXAr0JjN6uzCA+fn5sNlaosJbXfqalOippNxWbrPTllwN3HI9JO47OrBtcp8FkPzmb48drZOHzLoPOPgVkjO7yVzxtbnPZFBFEZfIzvcGR++fl6QSX4cBAwYgKysrpj60HScibeO2mtqRXZMniHWSMtOgXwJIomM+SaKJt9+3VIfaf5B3Vdyh5yJEMjrSOvxbI3O9uPyCElw+qwTDBibe199rsOGTtAl4Y8CFeGXgAqzPOBeN+uRbWzqdTuTlkcvC0/fa+UfRYxU6Kn6ugI5pwLTod5EYGrz3pLkQnjB9lh7Fj7V7fyS3hHNfeOQbOrCm3mSUcd38o5g1PraB25LpJ/HPnYPw2kfDo1lxO5xjsc1VADnOb3QbnSixDMTimi0YEEg878rgpaeno4osVW6T261E22rqAOXmzATS0xD21OMezZ/sHxxII453RLni8kv1ep37PRKb3nafadIW/fCWG2anPeViGRHMtAbx9asLW4AXKQumnsLNiw/BoFew3z4cW9PGtwAv+pt6M97OmYMyc/Ij+0x8nAqvt7Cao9uBNHVws2DemGPZYuErXqHRpN+I0FuYCS9dQEPV81GHHogQ5VQ56U5H6i240h0B3Lt8L4bkNCa957wxNfjqsv0oCJYiM5h8J9+QpMf72bNQZ3Qm8ekMamqiySna1hkAuVy2UBVIGk36PoA8206K+/aZ50HK6sSeBrw0m0Ve6UlynNOyUnBeSIA3KLP9MwTHDfHgvqW7cbV7A7KCnpQgrsmcnpBLhSNPolSxOlFaKok2+joBINOAacE00TIR+jwHLiLFnXfZxZ17qKFJzfsMBhSYXJlJ77th4RHkpDV3+L1jB3tw79I9uNy9EY5wctBZJx6wD0uqCyWrA8GgItrY0MnzJ5kWTBOo6SN9G0AasJ8nxS1PP7fjzzQHIDYOr9B0jCktMYC5GU2YPNydAHwDfv3meFH5cyIQb5q3Hxe6U29FVmgfkRRAWFURy23ktjZ3YsKJacE0Ydr0aQD53Dtq5DUL5gkx2uFSr7mGZWW8tt6Q1IUYnpvYRdh1NAv7StJF3VGUWPzOHFeFEcEKOEO+pO3wGB3JAbTYoCOrpEzbw8Dr65Q/DKYJ06YzZwOeCQ68QpZhWTC3cw9FiMErd0wZOUmP7rGZE0ekxg+tE2KVjZuCwYl1nV6niHQZfYo8JJMcSg4grwm2u3CitOWg62hhmjBtmEZ91g8ky39F7gDIY0d1fGBwKnx9oxoQLjomwTp8YKd/N9Ppx6NfaEc8FmegWnGizpB8SirfX5kCQNJj1nQUHa3j01XUNisd3z2MaMIb4srllSK09uc+x4EkGizUlyX/M7tz7/Q0qITg3MuAX4ElK7fbraoqjwUvrBsjoi9JxZwi43zPgSR6XVLdCUe6aCO3ldvsaehcO5g2TCOmVV8UoZeGZZgvmN65h9wNMfHJhOIJ3O4sdQ0m/O/qyVhtm41T5uTuyXwycNJDyRERXOjIENI9sj2ku5MAMm2YRlATmvscgA/y0qyxozr+QPwoPlJEdkJGBnRGU7eC9/jqSXjdPAvHLckHxgV1hRjtK035LgEgb+Jqd4q2xkuPDrs0oyCWrzGt+hSAJBKc1L/zZkzr3NGBtfUqAXiaZv9+CeYBw7odvL/pZ+OoNflu4zM8+zDWdwKVpoz2AWSn35HNC1lEm7nttfUdbxPThmnEtGKa9SUOvDoUhG7SuE7qJi26f6IEwkm25Q7tlsaU11rx81cnC/CO2AanBG9cYwneypkjYqKpQIwAKKXniLWHJ0pa9qGjhWnEtGKadUdf/1+AAQCrIkb0EMnrrQAAAABJRU5ErkJggg==')
-
- e_salute = ('Salute', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowNSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowNSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDMxRUIwOTUzQkM3MTFFRDlFNTZDOTNFRDVGQ0ZDRTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDMxRUIwOTYzQkM3MTFFRDlFNTZDOTNFRDVGQ0ZDRTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_scream = ('Scream', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozNiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozNiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODMwM0E4NzEzQTE5MTFFRDlCQTJFQjRDMUVGMzgzMjQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODMwM0E4NzIzQTE5MTFFRDlCQTJFQjRDMUVGMzgzMjQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_smirking = ('Smirking', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFEMEUwNDhCMzk1RjExRUQ4NTAyQjQ0RkY4QjYzNDMzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFEMEUwNDhDMzk1RjExRUQ4NTAyQjQ0RkY4QjYzNDMzIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QUQwRTA0ODkzOTVGMTFFRDg1MDJCNDRGRjhCNjM0MzMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QUQwRTA0OEEzOTVGMTFFRDg1MDJCNDRGRjhCNjM0MzMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4JM0EHAAAi8UlEQVR42ux9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')
-
- e_warning2 = ('Warning2', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxNiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxNiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzcxNjY1MDUzQTE5MTFFRDg4MzI4RTQ0MTMxMUQ2NDkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzcxNjY1MDYzQTE5MTFFRDg4MzI4RTQ0MTMxMUQ2NDkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_warning = ('Warning', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1NyswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1NyswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NkJCRTI2Q0UzQTE5MTFFREI0MDNDRTQyQzFFM0UzQzIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NkJCRTI2Q0YzQTE5MTFFREI0MDNDRTQyQzFFM0UzQzIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- e_python_hearts = ('PyHearts', sg.PYTHON_COLORED_HEARTS_BASE64)
- e_psg_hero = ('PySimpleGUI Hero', sg.EMOJI_BASE64_SUPERHERO)
-
- all_emojis = (e_happy, e_wave, e_search, e_santa, e_reading, e_blank_stare, e_stare, e_party, e_laptop, e_head_explode, e_glasses,e_laugh, e_joy, e_idea, e_cool, e_relief, e_wink, e_thumb, e_love, e_clap, e_fingers_crossed, e_ok, e_pray, e_smile, e_guess, e_crazy, e_eye_roll, e_dream, e_sleeping, e_python_hearts, e_psg_hero, e_wizard, e_grimace, e_weary, e_rainedon, e_upside_down, e_think, e_frust, e_dead, e_gasp, e_tear, e_cry, e_no_speak, e_no_hear, e_no_see, e_zipped_shut, e_ponder, e_skeptic, e_palm, e_eyebrow, e_not_understand, e_question, e_depressed, e_ill, e_ill2, e_mask, e_warning, e_warning2, e_key, e_salute, e_honest, e_gold_star, e_scream, e_smirking)
-
-
- # Build the "all_emojis" data structure. Converts the all_emojis tuple from 1 size to having 3 sizes
- # all_emojis = ('Description', smallest size, mid size, large size)
-
- new_all_emojis = []
- for e in all_emojis:
- description = e[0]
- base_emoji = e[1]
- new_emoji_info = [description, ]
- for s in EMOJI_SIZES:
- new_encoded = convert_to_bytes(base_emoji, (s, s))
- new_emoji_info.append(new_encoded)
- new_all_emojis.append(tuple(new_emoji_info))
- all_emojis = new_all_emojis
-
- if len(sys.argv) > 1:
- location = sys.argv[1]
- location = location.split(',')
- location = (int(location[0]), int(location[1]))
- else:
- location = (None, None)
- main(location)
-
diff --git a/DemoPrograms/Demo_Emojis.py b/DemoPrograms/Demo_Emojis.py
deleted file mode 100644
index 9bbc09225..000000000
--- a/DemoPrograms/Demo_Emojis.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""
- Demo - the PySimpleGUI helpers (emojis)
-
- The list of characters available to you to use in your messages.
- They are used internally when you get an error or as the icon for windows like
- the SDK help window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-import PySimpleGUI as sg
-
-layout = [[sg.Text('The PySimpleGUI Helpers', font='_ 20')],
- [sg.Text('Sometimes frustrated or tired....', font='_ 15')],
- [sg.Image(data=emoji) for emoji in sg.EMOJI_BASE64_SAD_LIST],
- [sg.Text('But they are usually happy!', font='_ 15')],
- [sg.Image(data=emoji) for emoji in sg.EMOJI_BASE64_HAPPY_LIST],
- [sg.Button('Bad Key'), sg.Button('Hello'), sg.Button('Exit')] ]
-
-window = sg.Window('The PySimpleGUI Helpers', layout, icon=sg.EMOJI_BASE64_HAPPY_JOY, keep_on_top=True)
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Bad Key':
- elem = window['-IM-']
- elif event == 'Hello':
- sg.popup('Hi!', image=sg.EMOJI_BASE64_HAPPY_JOY, keep_on_top=True)
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Event_Binding.py b/DemoPrograms/Demo_Event_Binding.py
deleted file mode 100644
index a69d36a5b..000000000
--- a/DemoPrograms/Demo_Event_Binding.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Extending PySimpleGUI using the tkinter event bindings
-
- The idea here is to enable you to receive tkinter "Events" through the normal place you
- get your events, the window.read() call.
-
- Both elements and windows have a bind method.
- window.bind(tkinter_event_string, key) or element.bind(tkinter_event_string, key_modifier)
- First parameter is the tkinter event string. These are things like
- Second parameter for windows is an entire key, for elements is something added onto a key. This key or modified key is what is returned when you read the window.
- If the key modifier is text and the key is text, then the key returned from the read will be the 2 concatenated together. Otherwise your event will be a tuple containing the key_modifier value you pass in and the key belonging to the element the event happened to.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-sg.theme('Dark Blue 3')
-
-def main():
- layout = [ [sg.Text('Move mouse over me', key='-TEXT-')],
- [sg.In(key='-IN-')],
- [sg.Button('Right Click Me', key='-BUTTON-'), sg.Button('Right Click Me2', key=(2,3)),sg.Button('Exit'),]]
-
- window = sg.Window('Window Title', layout, finalize=True)
-
- window.bind('', '+FOCUS OUT+')
-
- window['-BUTTON-'].bind('', '+RIGHT CLICK+')
- window[(2,3)].bind('', '+RIGHT CLICK+')
- window['-TEXT-'].bind('', '+MOUSE OVER+')
- window['-TEXT-'].bind('', '+MOUSE AWAY+')
- window['-IN-'].bind('', '+INPUT FOCUS+')
- window.bind('', '* WINDOW ENTER *')
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Event_Callback_Simulation.py b/DemoPrograms/Demo_Event_Callback_Simulation.py
index 760ac808e..a79f37186 100644
--- a/DemoPrograms/Demo_Event_Callback_Simulation.py
+++ b/DemoPrograms/Demo_Event_Callback_Simulation.py
@@ -9,10 +9,6 @@
functions as a mechanism for communicating when button presses or other events happen.
BUT, should you want to quickly convert some existing code that does use callback functions, then this
is one way to do a "quick and dirty" port to PySimpleGUI.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
# The callback functions
diff --git a/DemoPrograms/Demo_Exception_Traceback_Popup.py b/DemoPrograms/Demo_Exception_Traceback_Popup.py
deleted file mode 100644
index 4e77e4425..000000000
--- a/DemoPrograms/Demo_Exception_Traceback_Popup.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Show an error popup with traceback information
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-layout = [ [sg.Text('Choose the type of error to generate')],
- [sg.Button('Go'), sg.B('Key Error'), sg.B('Div 0'), sg.Button('Exit')] ]
-
-window = sg.Window('Exception Handling and Error Information Display', layout)
-
-while True: # Event Loop
- try:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- # When choice has been made, then fill in the listbox with the choices
- if event == 'Key Error':
- window['bad key']
- elif event == 'Div 0':
- a = 1/0
- except Exception as e:
- sg.popup_error_with_traceback('Error in the event loop', e, emoji=sg.EMOJI_BASE64_SCREAM)
-window.close()
diff --git a/DemoPrograms/Demo_Execute_Py.py b/DemoPrograms/Demo_Execute_Py.py
deleted file mode 100644
index 2fdb34675..000000000
--- a/DemoPrograms/Demo_Execute_Py.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
- Demo Execute Py - Using the PySimpleGUI Execute APIs
-
- Creating a virtual environment using PySimpleGUI & sg.execute_py_file()
-
- This Demo's purpose is to show the link between Execute APIs to the Global User Settings
-
- The function execute_py_file() uses the interpreter set in the Global Settings
- To see and change global settings, call main_global_pysimplegui_settings()
- Or you can use the "Global Settings" button found in the sg.main()
-
- If you have set an interpreter in your global settings, then this is what will be
- used when calling execute_py_file. It nothing is set, then the default python
- interpreter will be used
-
- Demo also shows another handy function, main_get_debug_data, which returns a string with
- version numbers for Python tkinter, PySimpleGUI
-
- http://www.PySimpleGUI.org
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-
-def main():
- # --------- Define layout and create Window -------
- layout = [ [sg.Text('User Exec API Demo', font='_ 18')],
- [sg.T(sg.main_get_debug_data(True))],
- [sg.T('Python Version', text_color='yellow'),
- sg.T(f'{sg.sys.version_info.major}.{sg.sys.version_info.minor}.{sg.sys.version_info.micro}', text_color = 'yellow')],
- [sg.B('Global Settings'), sg.B('Relaunch'), sg.B('Main'), sg.B('Refresh'), sg.Exit()],
- ]
-
- window = sg.Window('Execute Py File Demo', layout, keep_on_top=True, font='_ 14')
-
- # --------- Event Loop -------
- while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event.startswith('Global'):
- sg.main_global_pysimplegui_settings()
- elif event == 'Relaunch':
- sg.execute_py_file(__file__) # Run using Global Settings to determine which python version to use
- elif event == 'Main':
- sg.main()
-
- # --------- After event loop ---------
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Fill_Form.py b/DemoPrograms/Demo_Fill_Form.py
index 135ee5e5c..fe497e98e 100644
--- a/DemoPrograms/Demo_Fill_Form.py
+++ b/DemoPrograms/Demo_Fill_Form.py
@@ -3,14 +3,10 @@
'''
Example of GUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
def main():
- sg.theme('TanBlue')
+ sg.change_look_and_feel('TanBlue')
column1 = [
[sg.Text('Column 1', background_color=sg.DEFAULT_BACKGROUND_COLOR,
diff --git a/DemoPrograms/Demo_Floating_Toolbar.py b/DemoPrograms/Demo_Floating_Toolbar.py
index babfb4e74..162685efe 100644
--- a/DemoPrograms/Demo_Floating_Toolbar.py
+++ b/DemoPrograms/Demo_Floating_Toolbar.py
@@ -3,10 +3,6 @@
'''
Example of borderless floating toolbar.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
button_names = ('close', 'cookbook', 'cpu', 'github',
@@ -18,14 +14,15 @@
def main():
-
- def tbutton(image_data, key):
- return sg.Button(image_data=image_data, button_color=('white', 'black'), pad=(0,0), key=key)
-
- toolbar_buttons = [[tbutton(close64, '-CLOSE-'),
- tbutton(timer64, '-TIMER-'),
- tbutton(house64, '-HOUSE-'),
- tbutton(cpu64, '-CPU-') ]]
+ btn_css = {
+ 'button_color': ('white', 'black'),
+ 'pad': (0, 0),
+ }
+
+ toolbar_buttons = [[sg.Button(image_data=close64, **btn_css, key='-CLOSE-'),
+ sg.Button(image_data=timer64, **btn_css, key='-TIMER-'),
+ sg.Button(image_data=house64, **btn_css, key='-HOUSE-'),
+ sg.Button(image_data=cpu64, **btn_css, key='-CPU-'), ]]
# layout = toolbar_buttons
layout = [[sg.Col(toolbar_buttons, background_color='black')]]
diff --git a/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py b/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py
deleted file mode 100644
index 7695ed477..000000000
--- a/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import PySimpleGUI as sg
-
-
-"""
- Demo - Navigating a window's focus using arrow keys
-
- This Demo Program has 2 features of PySimpleGUI in use:
- 1. Binding the arrow keys
- 2. Navigating a window's elements using focus
-
- The first step is to bind the left, right and down arrows to an event.
- The call to window.bind will cause events to be generated when these keys are pressed
-
- The next step is to add the focus navigation to your event loop.
- When the right key is pressed, the focus moves to the element that should get focus next
- When the left arrow key is pressed, the focus moves to the previous element
- And when the down arrow is pressed the program exits
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-def main():
- layout = [ [sg.Text('My Window')],
- [sg.Input(key='-IN-')],
- [sg.Input(key='-IN2-')],
- [sg.Input(key='-IN3-')],
- [sg.Input(key='-IN4-')],
- [sg.Input(key='-IN5-')],
- [sg.Input(key='-IN6-')],
- [sg.Input(key='-IN7-')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- window = sg.Window('Window Title', layout, finalize=True)
-
- # Bind the Left, Right and Down arrow keys to events
- window.bind('', '-NEXT-')
- window.bind('', '-PREV-')
- window.bind('', 'Exit')
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # Right arrow pressed, so move to the next element that should get focus
- if event == '-NEXT-':
- next_element = window.find_element_with_focus().get_next_focus()
- next_element.set_focus()
-
- # Left arrow pressed, so move to the previous element that should get focus
- if event == '-PREV-':
- prev_element = window.find_element_with_focus().get_previous_focus()
- prev_element.set_focus()
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Font_Previewer.py b/DemoPrograms/Demo_Font_Previewer.py
index 75452ac3d..db0e2d4e3 100644
--- a/DemoPrograms/Demo_Font_Previewer.py
+++ b/DemoPrograms/Demo_Font_Previewer.py
@@ -1,23 +1,18 @@
#!/usr/bin/env python
+import sys
import PySimpleGUI as sg
+from tkinter import font
+import tkinter
+root = tkinter.Tk()
+fonts = list(font.families())
+fonts.sort()
+root.destroy()
'''
- Demo Font Previewer
-
- Gets a list of the installed fonts according to tkinter.
- Requires PySimpleGUI version 4.57.0 and newer (that's when sg.Text.fonts_installed_list was added)
-
- Uses the Text element's class method to get the fonts reported by tkinter.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ Showing fonts in PSG / tk
'''
-fonts = sg.Text.fonts_installed_list()
-
-
-sg.theme('Black')
+sg.change_look_and_feel('Black')
layout = [[sg.Text('My Text Element',
size=(20, 1),
@@ -39,7 +34,7 @@
while True: # Event Loop
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
text_elem = window['-text-']
print(event, values)
diff --git a/DemoPrograms/Demo_Font_Sizer.py b/DemoPrograms/Demo_Font_Sizer.py
index 321769f61..84b56b579 100644
--- a/DemoPrograms/Demo_Font_Sizer.py
+++ b/DemoPrograms/Demo_Font_Sizer.py
@@ -1,11 +1,5 @@
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Testing async form, see if can have a slider
# that adjusts the size of text displayed
@@ -23,7 +17,7 @@
window = sg.Window("Font size selector", layout, grab_anywhere=False)
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Quit':
+ if event is None or event == 'Quit':
break
sz_spin = int(values['spin'])
sz_slider = int(values['slider'])
diff --git a/DemoPrograms/Demo_Font_String.py b/DemoPrograms/Demo_Font_String.py
index f217b330d..831839a0d 100644
--- a/DemoPrograms/Demo_Font_String.py
+++ b/DemoPrograms/Demo_Font_String.py
@@ -3,10 +3,6 @@
'''
App that shows "how fonts work in PySimpleGUI".
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
layout = [[sg.Text('This is my sample text', size=(20, 1), key='-text-')],
@@ -24,17 +20,17 @@
text_elem = window['-text-']
while True: # Event Loop
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
font_string = 'Helvitica '
- font_string += str(int(values['-slider-']))
+ font_string += str(values['-slider-'])
if values['-bold-']:
font_string += ' bold'
if values['-italics-']:
font_string += ' italic'
if values['-underline-']:
font_string += ' underline'
- text_elem.update(font=font_string)
+ text_elem.update(font=int(font_string.split(' ')[1].split('.')[0]))
window['-fontstring-'].update('"'+font_string+'"')
print(event, values)
diff --git a/DemoPrograms/Demo_Frame_Based_Dashboard.py b/DemoPrograms/Demo_Frame_Based_Dashboard.py
deleted file mode 100644
index bf1360c44..000000000
--- a/DemoPrograms/Demo_Frame_Based_Dashboard.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Resizable Dashboard using Frames
-
- This Demo Program looks similar to the one based on the Column Element.
- This version has a big difference in how it was implemented and the fact that it can be resized.
-
- It's a good example of how PySimpleGUI evolves, continuously. When the original Column-based demo
- was written, none of these techniques such as expansion, were easily programmed.
-
- Dashboard using blocks of information.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-theme_dict = {'BACKGROUND': '#2B475D',
- 'TEXT': '#FFFFFF',
- 'INPUT': '#F2EFE8',
- 'TEXT_INPUT': '#000000',
- 'SCROLL': '#F2EFE8',
- 'BUTTON': ('#000000', '#C2D4D8'),
- 'PROGRESS': ('#FFFFFF', '#C7D5E0'),
- 'BORDER': 0,'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0}
-
-sg.theme_add_new('Dashboard', theme_dict)
-sg.theme('Dashboard')
-
-BORDER_COLOR = '#C7D5E0'
-DARK_HEADER_COLOR = '#1B2838'
-BPAD_TOP = ((20,20), (20, 10))
-BPAD_LEFT = ((20,10), (0, 0))
-BPAD_LEFT_INSIDE = (0, (10, 0))
-BPAD_RIGHT = ((10,20), (10, 0))
-
-top_banner = [
- [sg.Text('Dashboard', font='Any 20', background_color=DARK_HEADER_COLOR, enable_events=True, grab=False), sg.Push(background_color=DARK_HEADER_COLOR),
- sg.Text('Wednesday 27 Oct 2021', font='Any 20', background_color=DARK_HEADER_COLOR)],
- ]
-
-top = [[sg.Push(), sg.Text('Weather Could Go Here', font='Any 20'), sg.Push()],
- [sg.T('This Frame has a relief while the others do not')],
- [sg.T('This window is resizable (see that sizegrip in the bottom right?)')]]
-
-block_3 = [[sg.Text('Block 3', font='Any 20')],
- [sg.Input(), sg.Text('Some Text')],
- [sg.T('This frame has element_justification="c"')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-
-block_2 = [[sg.Text('Block 2', font='Any 20')],
- [sg.T('This is some random text')],
- [sg.Image(data=sg.DEFAULT_BASE64_ICON, enable_events=True)] ]
-
-block_4 = [[sg.Text('Block 4', font='Any 20')],
- [sg.T('You can move the window by grabbing this block (and the top banner)')],
- [sg.T('This block is a Column Element')],
- [sg.T('The others are all frames')],
- [sg.T('The Frame Element, with a border_width=0\n and no title is just like a Column')],
- [sg.T('Frames that have a fixed size \n handle element_justification better than Columns')]]
-
-
-layout = [
- [sg.Frame('', top_banner, pad=(0,0), background_color=DARK_HEADER_COLOR, expand_x=True, border_width=0, grab=True)],
- [sg.Frame('', top, size=(920, 100), pad=BPAD_TOP, expand_x=True, relief=sg.RELIEF_GROOVE, border_width=3)],
- [sg.Frame('', [[sg.Frame('', block_2, size=(450,150), pad=BPAD_LEFT_INSIDE, border_width=0, expand_x=True, expand_y=True, )],
- [sg.Frame('', block_3, size=(450,150), pad=BPAD_LEFT_INSIDE, border_width=0, expand_x=True, expand_y=True, element_justification='c')]],
- pad=BPAD_LEFT, background_color=BORDER_COLOR, border_width=0, expand_x=True, expand_y=True),
- sg.Column(block_4, size=(450, 320), pad=BPAD_RIGHT, expand_x=True, expand_y=True, grab=True),],[sg.Sizegrip(background_color=BORDER_COLOR)]]
-
-window = sg.Window('Dashboard PySimpleGUI-Style', layout, margins=(0,0), background_color=BORDER_COLOR, no_titlebar=True, resizable=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT)
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(sg.get_versions(), keep_on_top=True)
- elif event == 'File Location':
- sg.popup_scrolled('This Python file is:', __file__)
-window.close()
diff --git a/DemoPrograms/Demo_Frame_For_Screen_Captures.py b/DemoPrograms/Demo_Frame_For_Screen_Captures.py
deleted file mode 100644
index 7c3d72b27..000000000
--- a/DemoPrograms/Demo_Frame_For_Screen_Captures.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Frame For Screen Captures
-
- This program can be used to help you record videos.
-
- Because it relies on the "transparent color" feature that's only available on Windows, this Demo is only going
- to work the indended way on Windows.
-
- Some video recorders that record a portion of the screen do not show you, at all times, what portion of the screen
- is being recorded. This can make it difficult for you to stay within the bounds being recorded.
- This demo program is meant to help the situation by showing a thin line that is 20 pixels larger than the area
- being recorded.
-
- The top edge of the window has the controls. There's an exit button, a solid "bar" for you to grab with your mouse to move
- the frame around your window, and 2 inputs with a "resize" button that enables you to set the frame to the size you want to stay
- within.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- offset = (20, 20) # Number of extra pixels to add to the recording area
- default_size = (1920, 1080) # The default size of the recording
- location = (None, None) # A specific location to place the window if you want a specific spot
-
- window = sg.Window('Window Title',
- [[sg.Button('Exit'), sg.T(sg.SYMBOL_SQUARE * 10, grab=True), sg.I(default_size[0], s=4, k='-W-'), sg.I(default_size[1], s=4, k='-H-'), sg.B('Resize')],
- [sg.Frame('', [[]], s=(default_size[0] + offset[0], default_size[1] + offset[1]), k='-FRAME-')]], transparent_color=sg.theme_background_color(),
- right_click_menu=['', ['Edit Me', 'Exit']], location=location, no_titlebar=True, keep_on_top=True)
-
- while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Resize':
- window['-FRAME-'].set_size((int(values['-W-']) + offset[0], int(values['-H-']) + offset[1]))
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship.py b/DemoPrograms/Demo_Game_Frontend_Battleship.py
deleted file mode 100644
index 08ee3f3d3..000000000
--- a/DemoPrograms/Demo_Game_Frontend_Battleship.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from random import randint
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def Battleship():
- sg.theme('Dark Blue 3')
- MAX_ROWS = MAX_COL = 10
-
- # Start building layout with the top 2 rows that contain Text elements
- layout = [[sg.Text('BATTLESHIP', font='Default 25')],
- [sg.Text(size=(15,1), key='-MESSAGE-', font='Default 20')]]
- # Add the board, a grid a buttons
- layout += [[sg.Button(str('O'), size=(4, 2), pad=(0,0), border_width=0, key=(row,col)) for col in range(MAX_COL)] for row in range(MAX_ROWS)]
- # Add the exit button as the last row
- layout += [[sg.Button('Exit', button_color=('white', 'red'))]]
-
- window = sg.Window('Battleship', layout)
-
- while True: # The Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if randint(1,10) < 5: # simulate a hit or a miss
- window[event].update('H', button_color=('white','red'))
- window['-MESSAGE-'].update('Hit')
- else:
- window[event].update('M', button_color=('white','black'))
- window['-MESSAGE-'].update('Miss')
- window.close()
-
-Battleship()
diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py b/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py
deleted file mode 100644
index 579461f44..000000000
--- a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from random import randint
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def Battleship():
- sg.theme('Dark Blue 3')
- MAX_ROWS = MAX_COL = 10
-
- # Start building layout with the top 2 rows that contain Text elements
- layout = [[sg.Text('BATTLESHIP', font='Default 25')],
- [sg.Text(size=(15,1), key='-MESSAGE-', font='Default 20')]]
-
- # Build the "board", a grid of Buttons
- board = []
- for row in range(MAX_ROWS):
- layout_row = []
- for col in range(MAX_COL):
- layout_row.append(sg.Button(str('O'), size=(4, 2), pad=(0,0), border_width=0, key=(row,col)))
- board.append(layout_row)
-
- # Add the board to the layout
- layout += board
- # Add the exit button as the last row
- layout += [[sg.Button('Exit', button_color=('white', 'red'))]]
-
- window = sg.Window('Battleship', layout)
-
- while True: # The Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if randint(1,10) < 5: # simulate a hit or a miss
- window[event].update('H', button_color=('white','red'))
- window['-MESSAGE-'].update('Hit')
- else:
- window[event].update('M', button_color=('white','black'))
- window['-MESSAGE-'].update('Miss')
- window.close()
-
-Battleship()
diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py b/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py
deleted file mode 100644
index 236467a40..000000000
--- a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from random import randint
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def Battleship():
- sg.theme('Dark Blue 3')
- MAX_ROWS = MAX_COL = 10
- # Start building layout with the top 2 rows that contain Text elements
- layout = [[sg.Text('BATTLESHIP', font='Default 25')],
- [sg.Text(size=(15,1), key='-MESSAGE-', font='Default 20')]]
- # Build the "board", a grid of Buttons
- board = []
- for row in range(MAX_ROWS):
- board.append([sg.Button(str('O'), size=(4, 2), pad=(0,0), border_width=0, key=(row,col)) for col in range(MAX_COL)])
- # Add the board and the exit button to the layout
- layout += board
- # Add the exit button as the last row
- layout += [[sg.Button('Exit', button_color=('white', 'red'))]]
-
- window = sg.Window('Battleship', layout)
-
- while True: # The Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if randint(1,10) < 5: # simulate a hit or a miss
- window[event].update('H', button_color=('white','red'))
- window['-MESSAGE-'].update('Hit')
- else:
- window[event].update('M', button_color=('white','black'))
- window['-MESSAGE-'].update('Miss')
- window.close()
-
-Battleship()
diff --git a/DemoPrograms/Demo_Game_Wordle.py b/DemoPrograms/Demo_Game_Wordle.py
deleted file mode 100644
index 3c081dbf4..000000000
--- a/DemoPrograms/Demo_Game_Wordle.py
+++ /dev/null
@@ -1,100 +0,0 @@
-import PySimpleGUI as sg
-import copy
-
-"""
- Wordle GUI Demo
-
- Enter characters for each position
- Press enter or click enter to submit a row
-
- This is a prototype GUI of the front-end for WORDL
- It currently:
- * Takes input
- * Makes sure only characters
- * Automatically converts to upper case
- * Handles backspace
- * Checks for Enter key
- * Compares against a word (the constant "answer")
- * Color codes the submitted guess
-
- To complete an application, you'll need to:
- * Supply a word to guess from list of words
- * Check if user's submission is a word (I think this is how WORDLE works)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Insert code to generate a word here
-answer = 'WORDS'
-
-
-def TextChar(value, key):
- return sg.Input(value, key=key, font='Courier 22', size=(1,1), disabled_readonly_background_color='gray', border_width=1, p=1, enable_events=True, disabled=True)
-
-def main():
- layout = [[sg.Text('Wordle', font='_ 20')],
- [[TextChar('', (row, col)) for col in range(5)]for row in range(6)],
- [sg.B('Enter', bind_return_key=True)],
- [sg.Text('Or press enter', font='_ 10')]]
-
- window = sg.Window("Wordle", layout, finalize=True, element_justification='c')
-
- cur_row, correct = 0, False
- [window[(cur_row, col)].update(disabled=False) for col in range(5)]
- window.bind('', '-BACKSPACE-')
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- if isinstance(event, tuple):
- if len(values[event]):
- row, col = event
- char_input = values[event][-1]
- if not char_input.isalpha(): # if not a character input, remove the input
- window[event].update('')
- else:
- window[event].update(char_input.upper()[0]) # convert to uppercase
- if col < 4:
- window[(row, col+1)].set_focus() # Move to next position
- elif event == 'Enter' and cur_row < 5:
- guess = ''.join([values[(cur_row, j)] for j in range(5)])
- answer2 = copy.copy(answer)
- for i, letter in enumerate(guess):
- if letter == answer2[i]:
- window[(cur_row, i)].update(background_color='green', text_color='white')
- answer2 = answer2.replace(letter, '*')
- elif letter in answer2:
- window[(cur_row, i)].update(background_color='#C9B359', text_color='white')
- answer2 = answer2.replace(letter, '*')
- else:
- window[(cur_row, i)].update(background_color='gray', text_color='white')
- if guess == answer:
- correct = True
- break
- cur_row += 1 # Move to the next row
- [window[(cur_row, col)].update(disabled=False) for col in range(5)] # Enable inputs on next row
- window[(cur_row, 0)].set_focus() # Move to first position on row
- elif event == 'Enter' and cur_row == 5:
- correct = False
- break
- elif event == '-BACKSPACE-':
- current_focus = window.find_element_with_focus()
- current_key = current_focus.Key
- if isinstance(current_key, tuple):
- window[current_key].update('')
- if current_key[1] > 0:
- window[(current_key[0], current_key[1]-1)].set_focus()
- window[(current_key[0], current_key[1]-1)].update('')
-
-
- if correct:
- sg.popup('You win!')
- else:
- sg.popup(f'Sorry... the answer was {answer}')
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_GitHub_File_Copier.py b/DemoPrograms/Demo_GitHub_File_Copier.py
deleted file mode 100644
index a7e49fb66..000000000
--- a/DemoPrograms/Demo_GitHub_File_Copier.py
+++ /dev/null
@@ -1,283 +0,0 @@
-import os.path
-import shutil
-import subprocess
-import sys
-
-import PySimpleGUI as sg
-
-"""
- Demo - GitHub File Management
-
- A program that helps manage the demo programs on a local PC. This is done by copying files from your working folder to a folder that is kept in sync with GitHub.
- It works well when used in conjunction with the GUI version of GitHub.
-
- Two folders are shown...
- * the left side is your local "working copy"
- * the right side is the GitHub folder
-
- The basic file operations are
- * Copy from working folder to GitHub folder
- * Edit a file in PyCharm
- * Run a file (in either folder)
- * Filter file list
- * Search in files in list
-
- Additional operations
- * Edit this file in PyCharm
- * Launch GitHub GUI program
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def get_demo_git_files():
- """
- Get the files in the demo and the GitHub folders
- Returns files as 2 lists
-
- :return: two lists of files
- :rtype: Tuple[List[str], List[str]]
- """
-
- demo_path = sg.user_settings_get_entry('-demos folder-', '')
- git_demo_path = sg.user_settings_get_entry('-github folder-', '')
-
- try:
- git_demo_files = os.listdir(git_demo_path)
- except:
- git_demo_files = []
-
- try:
- demo_files = os.listdir(demo_path)
- except:
- demo_files = []
-
- return demo_files, git_demo_files
-
-
-def find_in_file(string):
- """
- Search through the demo files for a string.
- The case of the string and the file contents are ignored
-
- :param string: String to search for
- :return: List of files containing the string
- :rtype: List[str]
- """
-
- demo_path = sg.user_settings_get_entry('-demos folder-')
- demo_files, git_files = get_demo_git_files()
- string = string.lower()
- file_list = []
- for file in demo_files:
- filename = os.path.join(demo_path, file)
- try:
- with open(filename, 'r', encoding="utf8") as f:
- for line in f.readlines():
- if string in line.lower():
- file_list.append(file)
- # print(f'{os.path.basename(file)} -- {line}')
- except Exception as e:
- pass
- # print(e)
- return list(set(file_list))
-
-
-def settings_window():
- """
- Show the settings window.
- This is where the folder paths and program paths are set.
- Returns True if settings were changed
-
- :return: True if settings were changed
- :rtype: (bool)
- """
-
- layout = [[sg.T('Program Settings', font='DEFAIULT 18')],
- [sg.T('Path to Demos', size=(20, 1)), sg.In(sg.user_settings_get_entry('-demos folder-', ''), k='-DEMOS-'), sg.FolderBrowse()],
- [sg.T('Path to GitHub Folder', size=(20, 1)), sg.In(sg.user_settings_get_entry('-github folder-', ''), k='-GITHUB-'), sg.FolderBrowse()],
- [sg.T('Github Program', size=(20, 1)), sg.In(sg.user_settings_get_entry('-GitHub Program-', ''), k='-GITHUB PROGRAM-'), sg.FileBrowse()],
- [sg.T('Editor Program', size=(20, 1)), sg.In(sg.user_settings_get_entry('-Editor Program-', ''), k='-EDITOR PROGRAM-'), sg.FileBrowse()],
- [sg.Combo(sg.theme_list(), sg.user_settings_get_entry('-theme-', None), k='-THEME-')],
- [sg.B('Ok'), sg.B('Cancel')],
- ]
-
- window = sg.Window('Settings', layout)
- event, values = window.read(close=True)
- if event == 'Ok':
- sg.user_settings_set_entry('-demos folder-', values['-DEMOS-'])
- sg.user_settings_set_entry('-github folder-', values['-GITHUB-'])
- sg.user_settings_set_entry('-GitHub Program-', values['-GITHUB PROGRAM-'])
- sg.user_settings_set_entry('-Editor Program-', values['-EDITOR PROGRAM-'])
- sg.user_settings_set_entry('-theme-', values['-THEME-'])
- return True
-
- return False
-
-
-# --------------------------------- Create the window ---------------------------------
-def make_window():
- """
- Creates the main window
- :return: The main window object
- :rtype: (Window)
- """
-
- theme = sg.user_settings_get_entry('-theme-')
- demo_files, git_files = get_demo_git_files()
-
- sg.theme(theme)
- # First the window layout...2 columns
-
- find_tooltip = "Find in file\nEnter a string in box to search for string inside of the files.\nFile list will update with list of files string found inside."
- filter_tooltip = "Filter files\nEnter a string in box to narrow down the list of files.\nFile list will update with list of files with string in filename."
-
- left_col = [
- [sg.Text('Demo Programs', font='Any 20')],
- [sg.Listbox(values=demo_files, select_mode=sg.SELECT_MODE_EXTENDED, size=(40, 20), key='-DEMO LIST-')],
- [sg.Text('Filter:', tooltip=filter_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FILTER-', tooltip=filter_tooltip)],
- [sg.Button('Run'), sg.Button('Copy'), sg.B('Edit')],
- [sg.Text('Find:', tooltip=find_tooltip), sg.Input(size=(25, 1), enable_events=True, key='-FIND-', tooltip=find_tooltip)],
- ]
-
- right_col = [
- [sg.Text('GitHub Demo Programs', font='Any 20')],
- [sg.Listbox(values=git_files, select_mode=sg.SELECT_MODE_EXTENDED, size=(40, 20), key='-GIT DEMO LIST-')],
- [sg.Button('Run', key='Run Git Version')],
- ]
-
- # ----- Full layout -----
- ML_KEY = '-ML-' # Multline's key
-
- layout = [[sg.vtop(sg.Column(left_col, element_justification='c')), sg.VSeperator(), sg.vtop(sg.Column(right_col, element_justification='c'))],
- [sg.HorizontalSeparator()],
- [sg.Multiline(size=(90, 10), write_only=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True)],
- [sg.Combo(sg.user_settings_get_entry('-filenames-', []), default_value=sg.user_settings_get_entry('-last filename-'), size=(65, 1),
- k='-FILENAME-'), sg.FileBrowse(), sg.B('Clear'), sg.B('Run', k='-RUN INDIVIDUAL-'), sg.B('Edit', k='-EDIT INDIVIDUAL-')],
- [sg.Button('Edit Me (this program)'),
- sg.B('Launch GitHub', button_color=(sg.theme_input_background_color(), sg.theme_input_text_color())),
- sg.Button('Exit'), sg.B('Settings')],
- ]
-
- # --------------------------------- Create Window ---------------------------------
- window = sg.Window('GitHub Demo Copier', layout, icon=icon)
-
- sg.cprint_set_output_destination(window, ML_KEY)
- return window
-
-
-# --------------------------------- Main Program Layout ---------------------------------
-
-def main():
- """
- The main program that contains the event loop.
- It will call the make_window function to create the window.
- """
-
- demo_path = sg.user_settings_get_entry('-demos folder-', '')
- git_demo_path = sg.user_settings_get_entry('-github folder-', '')
- github_program = sg.user_settings_get_entry('-GitHub Program-', '')
- editor_program = sg.user_settings_get_entry('-Editor Program-', '')
- demo_files, git_files = get_demo_git_files()
-
- window = make_window()
-
- while True:
- event, values = window.read()
- if event == sg.WINDOW_CLOSED or event == 'Exit':
- break
- if event == 'Copy':
- confirm = sg.popup_yes_no('Are you sure you want to copy:', *values['-DEMO LIST-'], keep_on_top=True)
- if confirm == 'Yes':
- sg.cprint('Copying....', c='white on red')
- for file in values['-DEMO LIST-']:
- sg.cprint(f'{os.path.join(demo_path, file)}', text_color='blue')
- sg.cprint('TO', text_color='red', background_color='white')
- sg.cprint(f'{os.path.join(git_demo_path, file)}', text_color='green')
- shutil.copyfile(os.path.join(demo_path, file), os.path.join(git_demo_path, file))
- sg.cprint('Copy complete', background_color='red', text_color='white')
- elif event == 'Edit':
- for file in values['-DEMO LIST-']:
- sg.cprint(f'opening (in PyCharm)', text_color='white', background_color='red', end='')
- sg.cprint(f' {os.path.join(demo_path, file)}', text_color='purple')
- execute_command_subprocess(f'{editor_program}', os.path.join(demo_path, file))
- elif event == 'Run':
- sg.cprint('Running local program....', c='white on green')
- for file in values['-DEMO LIST-']:
- sg.cprint(os.path.join(demo_path, file))
- run_py(os.path.join(demo_path, file))
- elif event == 'Run Git Version':
- sg.cprint('Running GitHub version of program....', c='white on green')
- for file in values['-GIT DEMO LIST-']:
- sg.cprint(os.path.join(git_demo_path, file))
- run_py(os.path.join(git_demo_path, file))
- elif event.startswith('Edit Me'):
- sg.cprint(f'opening using {editor_program}\nThis file - {__file__}', text_color='white', background_color='green', end='')
- execute_command_subprocess(f'{editor_program}', __file__)
- elif event == 'Launch GitHub':
- run(github_program)
- elif event == '-FILTER-':
- new_list = [i for i in demo_files if values['-FILTER-'].lower() in i.lower()]
- window['-DEMO LIST-'].update(values=new_list)
- elif event == '-RUN INDIVIDUAL-':
- 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-'])
-
- window['-FILENAME-'].update(values=list(set(sg.user_settings_get_entry('-filenames-', []))))
- sg.cprint('Running Individual File...', c='white on purple')
- sg.cprint(values['-FILENAME-'], c='white on red')
- run_py(values['-FILENAME-'])
- elif event == 'Clear':
- sg.user_settings_set_entry('-filenames-', [])
- sg.user_settings_set_entry('-last filename-', '')
- window['-FILENAME-'].update(values=[], value='')
- elif event == '-FIND-':
- file_list = find_in_file(values['-FIND-'])
- window['-DEMO LIST-'].update(values=sorted(file_list))
- elif event == 'Settings':
- if settings_window() is True:
- window.close()
- window = make_window()
- demo_path = sg.user_settings_get_entry('-demos folder-')
- git_demo_path = sg.user_settings_get_entry('-github folder-')
- github_program = sg.user_settings_get_entry('-GitHub Program-')
- editor_program = sg.user_settings_get_entry('-Editor Program-')
- demo_files, git_files = get_demo_git_files()
- window.close()
-
-
-def run(app_name, parm=''):
- execute_command_subprocess(app_name, parm)
-
-
-def run_py(pyfile, parms=None):
- if parms is not None:
- execute_command_subprocess('python', pyfile, parms)
- else:
- execute_command_subprocess('python', pyfile)
-
-
-def execute_command_subprocess(command, *args, wait=False):
- if sys.platform == 'linux':
- arg_string = ''
- for arg in args:
- arg_string += ' ' + str(arg)
- sp = subprocess.Popen(['python3' + arg_string, ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- else:
- expanded_args = ' '.join(args)
- sp = subprocess.Popen([command, expanded_args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- if wait:
- out, err = sp.communicate()
- if out:
- print(out.decode("utf-8"))
- if err:
- print(err.decode("utf-8"))
-
-
-if __name__ == '__main__':
- icon = b'iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAB69LymqOSm6LSq2OTSrOjS2Ox28RjqdQC6qSiy3Riu3UTisRzirVDi1STq0UiuyYz6pYz62ZCjDNyjQPzTAOxrIQinARTXDRzXBVEWsP1ieZ0OrSUaqV0S0SkOzVFKnSVKrWlK0W0iqZUWmcEe0a1eoZ1apclW0Z1uzd2G8X2W8Z2i3dXStdnS/ZHW7dkXCTEnCWVnDbF3Gc1zUc2bGbGjId2fRbWjQfnLFbnTGeHfReXu6hWzFgWzRgXfGhn3Jk3bShHvWkd5HPNhYJ9RWPtRbPdxVOtlbM9xdPM5iPNRjO9VsMtNoOttiPOFVNOVUPeNZNOJbPelVPelZN+pcO/ZYPeNjPeFqPOlgNOpiPfBkO8xcR85ZUtZOUNJXQdNcQtNcTNpTRdxVT9xdQ95cSdlbUsBgR8xkRctkTc1oQ81pS8tmVMtxTsx3XtVjQdRjStRoQtNqStxiRNtjSdxpQ9toS9NkU9diWdFqUtVsW9xiU9xlXN5uVtZzWsptZ8Z3Y8p2ddBuY9duat1qY9Nvcdh3Z+VOQ+NUROJcQ+NcSutTROlcQ+pdSuhdVPJcQ/FbS/heQvZbVuFhReJjSeJpRORpTOpiRepiS+toTeVlU/RhRfJhUuZnYeBvaeR4aoPCfN+Hb9eHfNmQfeaIbOKIeOWSefaHbP+Ia/CMffCSePigeoTHhovJmIjWiYXXl5HMnpbYmY3bp4fes5PHoJnapJzUspDhnozjpo3lspnjqaLTm6HOsaPYp7XOuLbduajkqavpuLTpt7f2uKvbwbLYw7nmx7f1ybjw1tqIhtiThtiSkNasnNuimeSLhOWPkOWThuicl/mdiPKbku6fouWjl+Oinuaom+ynl+yjmuqpl+qqm/OllfOlmPSqnf6mkvqhneekoPOho8buuNPtvtbd08bpyMro1cT2ysj109XozNXo2NHzydT52M/45tvs4tj8497+8eD6y+b82+bq6Of+5+n+9fnq7f/p//b96fv7+gAAAAAAAAAAAAAAAAAAAFSfM6AAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAMlUlEQVR4Xu2Zf5gbRRnHtd5Fm+Z2FUQOuWQplXI+oAVqA0RrAKUlRGINlkCpei2b2EI1187eFUitBfFgc0nah5m7pFsFnvJD1FIseoDFk1/agj+wpz5gBX8geu31ODmtqb39J76zO5vb/Lzsnjw8Pt7nLpfZmcnMd99533dmc28rvMXMCJgRMCNgRsCMgP9tAQdv23jDTYm72JU9piPg5U29W8OB1O2Jl1mFHaYh4I+dS7NAbkeg8yCrsoF9AS9Ge6++Ik6k4BV9qVW/ZJXWsS3gwf4ORDAWZYQwRsqDrNoydgUc7EcwP8KEEEyQiJQh1mAVmwJeIaKI+5EoUiMggpbYVmBPwFDmk0QiWBaxjCmEoCsz9hTYE/D8J65FGIl0AegawGqQCE7YigWbS9DTK4LvYSwDhMjgiShIEnZsYNcJt9DVJ7Iowy8toQ4cxHZWwa6AAiEwM5HJdpm6AZGVDhTptaHAsoDvdr6gF76WvDqckqT1KJ3GCsnIEJNItJ4PrAoYikc3MgWbU6l+HN+AUql0HEFM2MsHFgUMZe7oiq86oF8kRImaPxtAUpdoNx9YEzCUuTIb6pNjTMHdq6Srli3PdgWxGKYxYScfWBJwMIEjIo5Eigq23JpQYitFBefAIe3lAysChhIkiNbnwsFcb2wnqwNe+OYd27YHtZiwkQ8sCBjKQKh3EEgAKEfE+1kt5bZLUdBuPmhcAKx/BHUoadKZjl8euqqXxYLG5kDKbj5oWMCDCpJgkfXNB0DdzA8oQ6uWs2rYnazlg0YFHFRg/4WtH8ysE+k03+W6LKuGPtbyQYMChjIQ4jAwmwWIJFiTxrrPsGrAWj5oTMBQZhlE2KT9gbDC2jTWrWDVOhbyQUMCaPzDmHTg4hKs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'
-
- main()
-
diff --git a/DemoPrograms/Demo_GoodColors.py b/DemoPrograms/Demo_GoodColors.py
index a29b8e6a7..7132eca74 100644
--- a/DemoPrograms/Demo_GoodColors.py
+++ b/DemoPrograms/Demo_GoodColors.py
@@ -2,12 +2,6 @@
import sys
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Example of colors in PSG
def main():
diff --git a/DemoPrograms/Demo_GoodColors_2.py b/DemoPrograms/Demo_GoodColors_2.py
index ba73acfbe..5da9f0a08 100644
--- a/DemoPrograms/Demo_GoodColors_2.py
+++ b/DemoPrograms/Demo_GoodColors_2.py
@@ -3,10 +3,6 @@
'''
Example of colors in PySimpleGUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
def main():
diff --git a/DemoPrograms/Demo_Google_TTS.py b/DemoPrograms/Demo_Google_TTS.py
index c2eb00497..279d066c0 100644
--- a/DemoPrograms/Demo_Google_TTS.py
+++ b/DemoPrograms/Demo_Google_TTS.py
@@ -12,10 +12,6 @@
Play back the speech
Note that there are 2 temp files created. The program tries to delete them but will fail on one of them
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
layout = [[sg.Text('What would you like me to say?')],
@@ -28,7 +24,7 @@
mixer.init()
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
# Get the text and convert to mp3 file
tts = gTTS(text=values[0], lang='en',slow=False)
diff --git a/DemoPrograms/Demo_Graph_Ball_Game.py b/DemoPrograms/Demo_Graph_Ball_Game.py
index 8c02f0284..5dca7ef84 100644
--- a/DemoPrograms/Demo_Graph_Ball_Game.py
+++ b/DemoPrograms/Demo_Graph_Ball_Game.py
@@ -5,14 +5,9 @@
import socket
"""
- python -m pip install pymunk==5.7.0
Demo that shows integrating PySimpleGUI with the pymunk library. This combination
of PySimpleGUI and pymunk could be used to build games.
Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -42,7 +37,7 @@ def __init__(self, graph_elem):
self.add_wall((0, 400), (600, 400)) # ground
self.add_wall((0, 0), (0, 600)) # Left side
self.add_wall((600, 0), (600, 400)) # right side
- self.arena_balls = [] # type: List[Ball]
+ self.arena_balls = [] # type: [] Ball
self.graph_elem = graph_elem # type: sg.Graph
def add_wall(self, pt_from, pt_to):
@@ -50,7 +45,6 @@ def add_wall(self, pt_from, pt_to):
ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0)
ground_shape.friction = 0.8
ground_shape.elasticity = .99
- ground_shape.mass = pymunk.inf
self.space.add(ground_shape)
def add_random_balls(self):
@@ -88,18 +82,16 @@ def shoot_a_ball(self, x, y, r, vector=(-10, 0), fill_color='black', line_color=
sg.Button('Player 2 Shoot', size=(15, 2)), sg.Button('Exit')]
]
-window = sg.Window('Window Title', layout, disable_close=True, finalize=True)
+window = sg.Window('Window Title', layout, disable_close=True)
area = Playfield(graph_elem)
-area.add_wall((0,300), (300,300))
-graph_elem.draw_line((0,300),(300,300))
# area.add_random_balls()
# ------------------- GUI Event Loop -------------------
while True: # Event Loop
event, values = window.read(timeout=10)
# print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
area.space.step(0.01)
diff --git a/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py b/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py
deleted file mode 100644
index 8d8cc5faa..000000000
--- a/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import PySimpleGUI as sg
-import random
-
-"""
- Bar Chart - Dual Axis Version
-
- A simple bar chart with a twist
- If you've got 2 values to plot, this technique enables you to trivially plot them both.
- Simply set your Graph element coordinates to be negative. Make your y=0 line run through the middle
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-BAR_WIDTH = 25 # width of each bar
-BAR_SPACING = 30 # space between each bar
-EDGE_OFFSET = 3 # offset from the left edge for first bar
-GRAPH_SIZE= (500,500) # size in pixels
-
-sg.theme('Light brown 1')
-
-layout = [[sg.Text('Dual-Axis Bar Chart')],
- [sg.Graph(GRAPH_SIZE, (0, -GRAPH_SIZE[0]//2), (GRAPH_SIZE[0]//2, GRAPH_SIZE[1]//2), k='-GRAPH-')],
- [sg.Button('OK'), sg.T('Click to display more data'), sg.Exit()]]
-
-window = sg.Window('Bar Graph', layout, finalize=True)
-
-# get the Graph Element into a variable to make code completion easier
-graph:sg.Graph = window['-GRAPH-']
-
-while True:
- graph.erase()
- for i in range(8):
- graph_value = random.randint(0, GRAPH_SIZE[1]//2)
- graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
- bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0),
- fill_color='green', line_width=0)
-
- # get a second value and draw an inverted bar. Simply set the Y value to be negative and top to be 0
- graph_value = random.randint(0, GRAPH_SIZE[1]//2)
- graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, 0),
- bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, -graph_value),
- fill_color='red', line_width=0)
-
- # Normally at the top of the loop, but because we're drawing the graph first, making it at the bottom
- event, values = window.read()
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py b/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py
deleted file mode 100644
index a0fe36246..000000000
--- a/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py
+++ /dev/null
@@ -1,70 +0,0 @@
-"""
- Demo Graph Custom Progress Meter
-
- The "Graph Element" is a "Gateway Element"
- Looking to create your own custom elements? Then the Graph Element is an excellent
- place to start.
-
- This short demo implements a Circular Progress Meter
-
- The event loop has a little trick some may like....
- Rather than adding a sleep instead use window.read with a timeout
- This has a dual purpose. You get the delay you're after AND your GUI is refreshed
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-import PySimpleGUI as sg
-
-# Settings for you to modify are the size of the element, the circle width & color and the font for the % complete
-GRAPH_SIZE = (300 , 300) # this one setting drives the other settings
-CIRCLE_LINE_WIDTH, LINE_COLOR = 20, 'yellow'
-TEXT_FONT = 'Courier'
-
-
-# Computations based on your settings above
-TEXT_HEIGHT = GRAPH_SIZE[0]//4
-TEXT_LOCATION = (GRAPH_SIZE[0]//2, GRAPH_SIZE[1]//2)
-TEXT_COLOR = LINE_COLOR
-
-def update_meter(graph_elem, percent_complete):
- """
- Update a circular progress meter
- :param graph_elem: The Graph element being drawn in
- :type graph_elem: sg.Graph
- :param percent_complete: Percentage to show complete from 0 to 100
- :type percent_complete: float | int
- """
- graph_elem.erase()
- arc_length = percent_complete/100*360+.9
- if arc_length >= 360:
- arc_length = 359.9
- graph_elem.draw_arc((CIRCLE_LINE_WIDTH, GRAPH_SIZE[1] - CIRCLE_LINE_WIDTH), (GRAPH_SIZE[0] - CIRCLE_LINE_WIDTH, CIRCLE_LINE_WIDTH),
- arc_length, 0, 'arc', arc_color=LINE_COLOR, line_width=CIRCLE_LINE_WIDTH)
- percent = percent_complete
- graph_elem.draw_text(f'{percent:.0f}%', TEXT_LOCATION, font=(TEXT_FONT, -TEXT_HEIGHT), color=TEXT_COLOR)
-
-
-def main():
-
- layout = [ [sg.Graph(GRAPH_SIZE, (0,0), GRAPH_SIZE, key='-GRAPH-')],
- [sg.Button('Go')]]
-
-
- window = sg.Window('Circlular Meter', layout, finalize=True)
-
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- for i in range(500):
- update_meter(window['-GRAPH-'], i/500*100)
- window.read(timeout=5) # an easy way to make a loop that acts like it has a "sleep" in it
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Drag_Rectangle.py b/DemoPrograms/Demo_Graph_Drag_Rectangle.py
index 6b903d946..dd4854d2c 100644
--- a/DemoPrograms/Demo_Graph_Drag_Rectangle.py
+++ b/DemoPrograms/Demo_Graph_Drag_Rectangle.py
@@ -6,41 +6,36 @@
This demo shows how to use a Graph Element to (optionally) display an image and then use the
mouse to "drag a rectangle". This is sometimes called a rubber band and is an operation you
see in things like editors
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
+
# image_file = r'Color-names.png'
-# image_file = None # image is optional
-image_file = r'C:\Python\PycharmProjects\PSG\logo200.png' # image is optional
+image_file = None # image is optional
layout = [[sg.Graph(
- canvas_size=(400, 400),
- graph_bottom_left=(0, 0),
- graph_top_right=(400, 400),
- key="-GRAPH-",
- change_submits=True, # mouse click events
- background_color='lightblue',
- drag_submits=True), ],
- [sg.Text(key='info', size=(60, 1))]]
+ canvas_size=(400, 400),
+ graph_bottom_left=(0, 400),
+ graph_top_right=(400, 0),
+ key="-GRAPH-",
+ change_submits=True, # mouse click events
+ drag_submits=True),],
+ [sg.Text(key='info', size=(60, 1))]]
window = sg.Window("draw rect on image", layout, finalize=True)
# get the graph element for ease of use later
-graph = window["-GRAPH-"] # type: sg.Graph
+graph = window["-GRAPH-"] # type: sg.Graph
-graph.draw_image(image_file, location=(0,400)) if image_file else None
+graph.draw_image(image_file, location=(0,0)) if image_file else None
dragging = False
start_point = end_point = prior_rect = None
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break # exit
-
- if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
+
+ if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
x, y = values["-GRAPH-"]
if not dragging:
start_point = (x, y)
@@ -51,12 +46,12 @@
graph.delete_figure(prior_rect)
if None not in (start_point, end_point):
prior_rect = graph.draw_rectangle(start_point, end_point, line_color='red')
-
- elif event.endswith('+UP'): # The drawing has ended because mouse up
+
+ elif event.endswith('+UP'): # The drawing has ended because mouse up
info = window["info"]
info.update(value=f"grabbed rectangle from {start_point} to {end_point}")
- start_point, end_point = None, None # enable grabbing a new rect
+ start_point, end_point = None, None # enable grabbing a new rect
dragging = False
-
+
else:
print("unhandled event", event, values)
diff --git a/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py b/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py
deleted file mode 100644
index 835363ef5..000000000
--- a/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Drag a rectangle and move
-
- This demo shows how to use a Graph Element to draw a square and move it with the mouse.
- It's a very simple, single element program. Like many Demo Programs, it started as
- a "Test Harness" that demonstrated a bug that happened with a timeout of 0
- was added to the window.read()
-
- Original code comes courtesy of user @davesmivers .... Thanks Dave!!
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-GRAPH_SIZE = (400, 400)
-START = (200, 200) # We'll assume X and Y are both this value
-SQ_SIZE = 40 # Both width and height will be this value
-
-layout = [[sg.Graph(
- canvas_size=GRAPH_SIZE, graph_bottom_left=(0, 0), graph_top_right=GRAPH_SIZE, # Define the graph area
- change_submits=True, # mouse click events
- drag_submits=True, # mouse move events
- background_color='lightblue',
- key="-GRAPH-",
- pad=0)]]
-
-window = sg.Window("Simple Square Movement", layout, finalize=True, margins=(0,0))
-
-# draw the square we'll move around
-square = window["-GRAPH-"].draw_rectangle(START, (START[0]+SQ_SIZE, START[1]+SQ_SIZE), fill_color='black')
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- print(event, values) if event != sg.TIMEOUT_EVENT else None # our normal debug print, but for this demo, don't spam output with timeouts
-
- if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse movement. Move the square
- x, y = values["-GRAPH-"] # get mouse position
- window["-GRAPH-"].relocate_figure(square, x - SQ_SIZE // 2, y + SQ_SIZE // 2) # Move using center of square to mouse pos
-
-window.close()
diff --git a/DemoPrograms/Demo_Graph_Drawing.py b/DemoPrograms/Demo_Graph_Drawing.py
index b37126ea6..d0f90bee5 100644
--- a/DemoPrograms/Demo_Graph_Drawing.py
+++ b/DemoPrograms/Demo_Graph_Drawing.py
@@ -1,31 +1,23 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Usage of Graph element.
-layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0, 0), graph_top_right=(400, 400), background_color='red', enable_events=True, key='graph')],
+layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0, 0), graph_top_right=(400, 400), background_color='red', key='graph')],
[sg.Text('Change circle color to:'), sg.Button('Red'), sg.Button('Blue'), sg.Button('Move')]]
window = sg.Window('Graph test', layout, finalize=True)
-graph = window['graph'] # type: sg.Graph
+graph = window['graph']
circle = graph.draw_circle((75, 75), 25, fill_color='black', line_color='white')
point = graph.draw_point((75, 75), 10, color='green')
oval = graph.draw_oval((25, 300), (100, 280), fill_color='purple', line_color='purple')
rectangle = graph.draw_rectangle((25, 300), (100, 280), line_color='purple')
line = graph.draw_line((0, 0), (100, 100))
arc = graph.draw_arc((0, 0), (400, 400), 160, 10, style='arc', arc_color='blue')
-poly = graph.draw_polygon(((10,10), (20,0), (40,200), (10,10)), fill_color='green')
while True:
event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event in ('Blue', 'Red'):
graph.TKCanvas.itemconfig(circle, fill=event)
@@ -35,6 +27,5 @@
graph.MoveFigure(oval, 10, 10)
graph.MoveFigure(rectangle, 10, 10)
graph.MoveFigure(arc, 10, 10)
- graph.MoveFigure(poly, 10, 10)
window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
deleted file mode 100644
index 6903980b2..000000000
--- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
+++ /dev/null
@@ -1,143 +0,0 @@
-import PySimpleGUI as sg
-from PIL import ImageGrab
-
-"""
- Demo - Drawing and moving demo
-
- This demo shows how to use a Graph Element to (optionally) display an image and then use the
- mouse to "drag" and draw rectangles and circles.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def save_element_as_file(element, filename):
- """
- Saves any element as an image file. Element needs to have an underlyiong Widget available (almost if not all of them do)
- :param element: The element to save
- :param filename: The filename to save to. The extension of the filename determines the format (jpg, png, gif, ?)
- """
- widget = element.Widget
- box = (widget.winfo_rootx(), widget.winfo_rooty(), widget.winfo_rootx() + widget.winfo_width(), widget.winfo_rooty() + widget.winfo_height())
- grab = ImageGrab.grab(bbox=box)
- grab.save(filename)
-
-
-
-def main():
-
- sg.theme('Dark Blue 3')
-
- col = [[sg.T('Choose what clicking a figure does', enable_events=True)],
- [sg.R('Draw Rectangles', 1, key='-RECT-', enable_events=True)],
- [sg.R('Draw Circle', 1, key='-CIRCLE-', enable_events=True)],
- [sg.R('Draw Line', 1, key='-LINE-', enable_events=True)],
- [sg.R('Draw points', 1, key='-POINT-', enable_events=True)],
- [sg.R('Erase item', 1, key='-ERASE-', enable_events=True)],
- [sg.R('Erase all', 1, key='-CLEAR-', enable_events=True)],
- [sg.R('Send to back', 1, key='-BACK-', enable_events=True)],
- [sg.R('Bring to front', 1, key='-FRONT-', enable_events=True)],
- [sg.R('Move Everything', 1, key='-MOVEALL-', enable_events=True)],
- [sg.R('Move Stuff', 1, key='-MOVE-', enable_events=True)],
- [sg.B('Save Image', key='-SAVE-')],
- ]
-
- layout = [[sg.Graph(
- canvas_size=(400, 400),
- graph_bottom_left=(0, 0),
- graph_top_right=(800, 800),
- key="-GRAPH-",
- enable_events=True,
- background_color='lightblue',
- drag_submits=True,
- right_click_menu=[[],['Erase item',]]
- ), sg.Col(col, key='-COL-') ],
- [sg.Text(key='-INFO-', size=(60, 1))]]
-
- window = sg.Window("Drawing and Moving Stuff Around", layout, finalize=True)
-
- # get the graph element for ease of use later
- graph = window["-GRAPH-"] # type: sg.Graph
- graph.draw_image(data=logo200, location=(0,400))
-
- dragging = False
- start_point = end_point = prior_rect = None
- # graph.bind('', '+RIGHT+')
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED:
- break # exit
-
- if event in ('-MOVE-', '-MOVEALL-'):
- graph.set_cursor(cursor='fleur') # not yet released method... coming soon!
- elif not event.startswith('-GRAPH-'):
- graph.set_cursor(cursor='left_ptr') # not yet released method... coming soon!
-
- if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
- x, y = values["-GRAPH-"]
- if not dragging:
- start_point = (x, y)
- dragging = True
- drag_figures = graph.get_figures_at_location((x,y))
- lastxy = x, y
- else:
- end_point = (x, y)
- if prior_rect:
- graph.delete_figure(prior_rect)
- delta_x, delta_y = x - lastxy[0], y - lastxy[1]
- lastxy = x,y
- if None not in (start_point, end_point):
- if values['-MOVE-']:
- for fig in drag_figures:
- graph.move_figure(fig, delta_x, delta_y)
- graph.update()
- elif values['-RECT-']:
- prior_rect = graph.draw_rectangle(start_point, end_point,fill_color='green', line_color='red')
- elif values['-CIRCLE-']:
- prior_rect = graph.draw_circle(start_point, end_point[0]-start_point[0], fill_color='red', line_color='green')
- elif values['-LINE-']:
- prior_rect = graph.draw_line(start_point, end_point, width=4)
- elif values['-POINT-']:
- graph.draw_point((x,y), size=8)
- elif values['-ERASE-']:
- for figure in drag_figures:
- graph.delete_figure(figure)
- elif values['-CLEAR-']:
- graph.erase()
- elif values['-MOVEALL-']:
- graph.move(delta_x, delta_y)
- elif values['-FRONT-']:
- for fig in drag_figures:
- graph.bring_figure_to_front(fig)
- elif values['-BACK-']:
- for fig in drag_figures:
- graph.send_figure_to_back(fig)
- window["-INFO-"].update(value=f"mouse {values['-GRAPH-']}")
- elif event.endswith('+UP'): # The drawing has ended because mouse up
- window["-INFO-"].update(value=f"grabbed rectangle from {start_point} to {end_point}")
- start_point, end_point = None, None # enable grabbing a new rect
- dragging = False
- prior_rect = None
- elif event.endswith('+RIGHT+'): # Righ click
- window["-INFO-"].update(value=f"Right clicked location {values['-GRAPH-']}")
- elif event.endswith('+MOTION+'): # Righ click
- window["-INFO-"].update(value=f"mouse freely moving {values['-GRAPH-']}")
- elif event == '-SAVE-':
- # filename = sg.popup_get_file('Choose file (PNG, JPG, GIF) to save to', save_as=True)
- filename=r'test.jpg'
- save_element_as_file(window['-GRAPH-'], filename)
- elif event == 'Erase item':
- window["-INFO-"].update(value=f"Right click erase at {values['-GRAPH-']}")
- if values['-GRAPH-'] != (None, None):
- drag_figures = graph.get_figures_at_location(values['-GRAPH-'])
- for figure in drag_figures:
- graph.delete_figure(figure)
-
- window.close()
-
-logo200 = b'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'
-
-main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py
deleted file mode 100644
index 69e202727..000000000
--- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py
+++ /dev/null
@@ -1,143 +0,0 @@
-import PySimpleGUI as sg
-from PIL import ImageGrab
-
-"""
- Demo - Drawing and moving demo
-
- This demo shows how to use a Graph Element to (optionally) display an image and then use the
- mouse to "drag" and draw rectangles and circles.
-
- This demo is an adaptation of a single-window version called Demo_Graph_Drawing_And_Dragging_Figures. The
- difference between the 2 programs is that the "action" portion of the interface is split into a floating
- toolbar kind of interface in this version.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def save_element_as_file(element, filename):
- """
- Saves any element as an image file. Element needs to have an underlyiong Widget available (almost if not all of them do)
- :param element: The element to save
- :param filename: The filename to save to. The extension of the filename determines the format (jpg, png, gif, ?)
- """
- widget = element.Widget
- box = (widget.winfo_rootx(), widget.winfo_rooty(), widget.winfo_rootx() + widget.winfo_width(), widget.winfo_rooty() + widget.winfo_height())
- grab = ImageGrab.grab(bbox=box)
- grab.save(filename)
-
-
-
-def main():
-
- sg.theme('Dark Blue 3')
-
- layout2 = [[sg.T('Choose what clicking a figure does', enable_events=True)],
- [sg.R('Draw Rectangles', 1, key='-RECT-', enable_events=True)],
- [sg.R('Draw Circle', 1, key='-CIRCLE-', enable_events=True)],
- [sg.R('Draw Line', 1, key='-LINE-', enable_events=True)],
- [sg.R('Draw points', 1, key='-POINT-', enable_events=True)],
- [sg.R('Erase item', 1, key='-ERASE-', enable_events=True)],
- [sg.R('Erase all', 1, key='-CLEAR-', enable_events=True)],
- [sg.R('Send to back', 1, key='-BACK-', enable_events=True)],
- [sg.R('Bring to front', 1, key='-FRONT-', enable_events=True)],
- [sg.R('Move Everything', 1, key='-MOVEALL-', enable_events=True)],
- [sg.R('Move Stuff', 1, key='-MOVE-', enable_events=True)],
- [sg.B('Save Image', key='-SAVE-')]]
-
- window2 = sg.Window('Your Palette', layout2, finalize=True)
-
- layout1 = [[sg.Graph(
- canvas_size=(400, 400),
- graph_bottom_left=(0, 0),
- graph_top_right=(800, 800),
- key="-GRAPH-",
- enable_events=True,
- background_color='lightblue',
- drag_submits=True) ],
- [sg.Text(key='info', size=(40, 1))]]
-
- window1 = sg.Window("Drawing and Moving Stuff Around", layout1, keep_on_top=True, finalize=True)
-
- # get the graph element for ease of use later
- graph = window1["-GRAPH-"] # type: sg.Graph
- graph.draw_image(data=logo200, location=(0,400))
-
- dragging = False
- start_point = end_point = prior_rect = None
- graph.bind('', '+RIGHT+')
- drawing_setting = window2.read(timeout=0)[1]
-
- window2.move(window1.current_location()[0]+window1.size[0], window1.current_location()[1])
-
- while True:
- window, event, values = sg.read_all_windows()
- # event, values = window.read()
- # print(event, values)
- if window == window2:
- drawing_setting = values
- if event == sg.WIN_CLOSED:
- break # exit
- if event in ('-MOVE-', '-MOVEALL-'):
- # graph.Widget.config(cursor='fleur')
- graph.set_cursor(cursor='fleur') # not yet released method... coming soon!
- elif not event.startswith('-GRAPH-'):
- graph.set_cursor(cursor='left_ptr') # not yet released method... coming soon!
- # graph.Widget.config(cursor='left_ptr')
-
- if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
- x, y = values["-GRAPH-"]
- if not dragging:
- start_point = (x, y)
- dragging = True
- drag_figures = graph.get_figures_at_location((x,y))
- lastxy = x, y
- else:
- end_point = (x, y)
- if prior_rect:
- graph.delete_figure(prior_rect)
- delta_x, delta_y = x - lastxy[0], y - lastxy[1]
- lastxy = x,y
- if None not in (start_point, end_point) or drawing_setting['-ERASE-'] or drawing_setting['-CLEAR-']:
- if drawing_setting['-RECT-']:
- prior_rect = graph.draw_rectangle(start_point, end_point,fill_color='green', line_color='red')
- elif drawing_setting['-CIRCLE-']:
- prior_rect = graph.draw_circle(start_point, end_point[0]-start_point[0], fill_color='red', line_color='green')
- elif drawing_setting['-LINE-']:
- prior_rect = graph.draw_line(start_point, end_point, width=4)
- elif drawing_setting['-MOVE-']:
- for fig in drag_figures:
- graph.move_figure(fig, delta_x, delta_y)
- graph.update()
- elif drawing_setting['-POINT-']:
- graph.draw_point((x,y), size=8)
- elif drawing_setting['-ERASE-']:
- for figure in drag_figures:
- graph.delete_figure(figure)
- elif drawing_setting['-CLEAR-']:
- graph.erase()
- elif drawing_setting['-MOVEALL-']:
- graph.move(delta_x, delta_y)
- elif drawing_setting['-FRONT-']:
- for fig in drag_figures:
- graph.bring_figure_to_front(fig)
- elif drawing_setting['-BACK-']:
- for fig in drag_figures:
- graph.send_figure_to_back(fig)
- elif event.endswith('+UP'): # The drawing has ended because mouse up
- info = window["info"]
- info.update(value=f"grabbed rectangle from {start_point} to {end_point}")
- start_point, end_point = None, None # enable grabbing a new rect
- dragging = False
- prior_rect = None
- elif event == '-SAVE-':
- # filename = sg.popup_get_file('Choose file (PNG, JPG, GIF) to save to', save_as=True)
- filename=r'test.jpg'
- save_element_as_file(window['-GRAPH-'], filename)
-
- window.close()
-
-logo200 = b'iVBORw0KGgoAAAANSUhEUgAAAMgAAACVCAYAAAAdSLW3AAAACXBIWXMAABcRAAAXEQHKJvM/AAAenklEQVR42u2deXxM1/vHn3OXWTOTTPZVhAgRUWIPvhS11q50UYoqqpYudPm2uv9ain6rlG5o0UYtLVW6WVpC1S4RW0hkTyQzk9mXu/z+yGIymUlSJaF93l73ZXKXMzfnnM99zvOc554QURQBQRDPUFgFCIICQRAUCIKgQBAEBYIgKBAEQYEgCAoEQVAgCIICQRAEBYIgKBAEQYEgCAoEQVAgCIICQRAUCIKgQBAEBYIgKBAEQVAgCIICQRAUCIKgQBAEBYIgKBAEQYEgCAoEQVAgCIKgQBAEBYIgKBAEQYEgCAoEQVAgCIICQRAUCIKgQBAEBYIgCAoEQVAgCIICQRAUCII0NQxWQePg5AU6p6S8WX6pISRArTDEhvtflrK0s8EFiE4anEUBAAwPbLAWCC1iraJA7npK9ObArQczpm47dH6m3myLEkWRIkBEtUJaMLZ3/MrH7uuwwkcusXktgDcroCxlGmi3PwO8MRIIEYH2zQV1nxTwu38DyOMuABCs6NsEEUV8EN0ujl8q6PT6xt/W5pUaEsFzLxb7tI/e8Nbkfk/6yCXmWkcFCwu5/10LpuMPAYh07QGyXAt+Q1dB8NSlQPsasMZRIHcFvCBS638+/fgne06853Dy6vrO79o6YvuyJwZOqiESTquGvNdWg/nkw/WPA/wzIfy5GeDT8wAQWsAWQIHcub4GxzP/+/boCykH0hcJosg29Lre7aK/entKvydUcokZBDMLOc9/CebTE6Ch4yciMYFm+FIInfMmEAZFggK583BwPPv21wf/t/PIxZlwExHCznHhO5Y/MXCiyv5zMhS89z2AIPnLN+HT/SuIeHE2MAF6bJG/D4Z5b6E4lm498vbOIxdn3Wy9Hr9UMPLFdfs+M0gGHIHAh54DoOx/uRDTHw9B7qK1IFgl2Cp/H/q1117DWvj7Pgd5b0vqq1t+z3j+7z50cq+XtzubVZJ4b/LYV6QSSTaYTw8GEP9CtJEQcBbHg7MgEFTJP6NPggJpcr49fGHCp7tPLgcAhhAC7hu4bg2gUGuKu5ivje3Vddi7MkYsAmt6P88iITc2QlV+R+X/jtx7gAm4BPI26dhC6IM0GScyCzs9/fHPP5qtzsAbe0UPnwA87/Re/x1bhu5ePmPAg77mjVPh+ob3K9TmKg6o6cPXECABoBRF0GJdArBBWmwp9EEaHbuTY9/bcmSlxcYF1rIUlZsni0Io158pz5aGEDh1tXjo/6UcWeLUPPoxSKOPV4iBqtgI5WY1KKg+XvWzaAsF7ea52FIokCbhy71pM68U6bsTigChiKCUsVqKIlxFp6c8i8OLSKD6mprX7T97bcqxzLKuEPDACiB0ZeenXQTi4TO47DMemAaOgnBsLRRIo6Iz2Xx/OHZlBhACFEU5nh7d7fFNz49KWjy13/BAX8W1CiNQSxhiTb/B1dK4/njjGkEUpfvPZI8ARbtjQMmMN6wF5cGauFiVqmO8OQJMh4Zji6FAGpUrhbr4Qq25NSEEurWO2P5w34R1UYHqa/3uaf7jo/0T3yA1LAIFEpYxjOnZ5mWVQlpQaXFubNVDLc9WJPe6sTXQfuVAqw2eLYarJaHdPlMETH+MxxZDgTSy/8FrgABDgIBaKbW6HlPLJTpXk0BTlG3O8M7Tpg/uuMLPR55NCIEa/+qJfEkljB1EjgIQqBsRK7et2qKQ2v6JI+seAAEzGlEgjYe/Sp4lZVkDoSj4PT1v3IG0nD42B8deLdJHb0m9OL+qo0tZpnzeyM6T+raP3r9g7f6vC7Sm5GofhPIuDldr0rZZ4BHgroeBaPUHQrtZDG+fXSwJEBYw5femwHT3m6RVuOZy74TILXvP5kxz8IJq0aZDu0L9lNl6sz3QYLWHEEKApoh1zohOU+9NbPbrgrX7Uy7kaQdXRGoJQGV4XfTQbV13qeSSwgEdYraDacsjAKK0osO7nEXcr3D7TABAGnMMgMIJQxRII1YcTfHPju76TG6Zqe3lAl0PJy/65JaZ2oEIQIACiYTWzx7WYXrvhKjfn1//29cX83VDak5jEBBdu7OH+SiaIrZZQzvOaxlot0DO3qcqrIe7EIhLIR6EQlgT+I19F1sMh1hNMMySGRZP7jM+PjLgsKs/wdCUZd7wpCl9E5v98uIXv2+8kKcd4nWOpPq6mo65hGHMM4d0nD2me/jPUPLhxyDaQm5ErGgv/oe7b8I4wX/CfPDptg9b6+bAmfRbQJnRFvjc2gM7L+XrekhYWv/UsA5Tk9tEHHxpw8ENl/J1g0Wop47dZtYrnPqkqeN6RH1PlSzbCJZTIz3PmHsZWhECAIwFNGPng9+YT7GFUCBNTpHOHPHqV4fXD+0cs6J76/CDC9f/vuVKob6/6NHLAK8ZJixDmZ4Y1H7OQ72iviXXV34CluPj6xeD+z7aAZoJM0E97AtMVkSB3DHYnTxdZrT6v7zx8MZLBbqBDTQZ1S4ITRHrvOFJU8Z0i9hNSpZvAuvZ4Q3zM1zFwZrBb+w88B3xObYIOul3FOUWh+rFDakpV4vK7yUeM3crI1eunbxSK1KWNs4YnDh7TLfQn0nph+vAlja8VsTKXQzuCYuEsoNmwpOgGrQJWwOd9DuK/DJTyAtfHtqSVWLoRyhCPM9xeMi5ogiwDG2Ze3+HaeN7RO4g11dsAOvpsV7zrsDTfAcFQEnMoJkwC3z67AD9Ny8Drw/EVkELckdQUm7VvLTpSEp2iaEPcXna1zfHAUBAwlCGmYMSZ43sEvwrKV21HmwZw6pnxL1aDFerAQBA20EzYQYoe++Aso+/AGvaaHBk/gcCnnwEmIAibCH0QZp0WPXfTUdS0nPKhtbwLhpQrwxFbPOGd5g4PCnkF1K6IgVsGUM8CqGuyUDCWsBvzDxQ9t4C2s8/A+uZcdXHJZGHIXDeSKA1pdhSOMRqElIOXZ59Llc7GCpnyOvKr3LbhPG94l4bnhS4j5R9tAFsF4Z4zsytY56DYu2gGf8kKP+zGco+/QJs6WNrHHcWJEPZmhTgDRpsKRRIo2O0OuU7j2U9A4RQNfKrKAKE8p6dC4RAZKAq/cFecauJbtMbYMsYcUMM3vKq3PZRUjP4jX8SFD12gPbz9WA/P7Ji9tHtXGdOfzDtwZemUCCNT3puWTerkw+qZR1crIi3GfQercO2+0rKlWA9Md2rxfBmTQhrA9/xM0HRYytoP/sS7Bmjq2fOVUOfg+BXWoHvhEeBUhYDoQCsJyeBt/kYBJ3020VembkFIRTUmte4kYvo4i1Ufao4kBClOQr2C70BQOoxnOsxGZFU5FapRz0Fis4/gG7dF+C4eCMcLG2zA9QjlgEAABuRCaI1BEx7loJobV6xdCnhsNVQII0GS9NcdXZu7fBH7X3ijc4uZRkd8Ibm1QmIDYpWEQBKagE2NBt0azeC/fKQiiFZ5TFaU1Lj+2jfnIryiRUAcEYdBdK4NA9WZXhbyofUEkbNnXYnrwEmoOQvp6+LtmDQfvITgCAFd3Ha08aCM3slsM3PA6/3B+ufUwEoADbsDKa7o0AanbaRfqf9lNKscosjxrtEKl9DdzMo5/P1Pfq2jl0JhLUACIq6h1ZunwlIa8yVVIvHGQK6j1OB9j8Lgqk5COZmQCgAaeI2bC100hsdCUNzY7vFLKcoSvAazvXisB+5VDJab1c5QNF1TY2lexrqqHs7Jjo1wBX3AcEcDQAEKHkByDttwdZCgTQJw5KafdEyRJ3qfXkfCghFAVT+XxH+JVBcbk1IOXx1tqge9SZI2+6o3dk9LcjgLhSXFVK8Ieu6CujAXGwpFEiToJazxicHxs9laNriLaxbYwIRoMqaUDtP5CzafUY3WPSbPAkkcXu8WwzSMDG4Q/udB2X/D/B19JsH1+a9BQT7yos4QTRn5JcPAACqzuFW9c8AIgBzKrtssEImz24dk/wO4YrjgC+LvyUdmrDloH7wUWDDL2MLoUCanPhw31NFemvQtVJzF48+CLivXAIAhIAgguR0tm6wr1J5vlV09yWEy2sPvDbub96OCMoBC0DRbQtaDxTIHQFDU3zXlkF783XWZnlaSzuAyvQTDyssgptYRADmdLZ2kFquuBjXvPti4ItaAV/a9iZNhxPk3d4F1f1LACjMREUf5E6KalH2p4e0nTm4fcQSQohAKq2Eqy8CXhIZaYpySFnKCJRCD76PPAaSuO9v4hY4UPZ9BVSjXsd5j1sDprvfBgRBpH5KK3hgw6GsxeVWZ3TVqMf1Pzdhlc8bHD++T5uQXypXAwIQLL5gSPkE7BkNWzaUUmWDz5BnQN7lO8/T+AgK5A4jp8wcvfa3K++eyNKOE6v+AI5bdUtZSjerf9ykAe3CdtX2JGxK0G/YBI6LI+tQhh2kbb8Gn6GvABOch7WOArmr4ASRPpWtTd5+PHdh1nVzN7Od8wdRpBmaMkUHKk9N+U+Lp9tHaU5WW45aIrGqwPj9a2A7PQVEh1/lOI0HSlECbLP9oOi7FCQtzgJQPNY2CuSuHnYVGWwRhTprjNXBS0N8ZYXNApWXpAzlqP9qkQBX1BK4orYg8iqg5AXAhJ0HWlOMwykUCII0GRjFQhAUCIKgQBDklvOvfh9Eb3H6Wp2CiiLgCFFLS7A7IH9JIJwgUnqLs84V+ggA56tgdQx1+6MpggigNTv8vd23hKbMajljbkhZuVpryJT1Z3aUmpwxFAH7igcTHujVyv/o3daAZjsvtzp5lWs1+clZLUOTpp1JF3kKBJMGAOiaYxafUo8Laos8DYLZB2h1eZ3l8kZfoKRmIJLa79eLHAWCuWErSlJKLRCG+1sCOV9gCh+x8lhWff023E+W8dbo1nP6xgWkeo3n/02ulVnD5m8+9/HpHMMgb0NDiiK2EfeErHnl/lZv+CtZY13l5elsEReLzB0BQAIAcDbf2OFuE4jW7PQZsPyPNJ3ZGenaTUYnhX64fHzbZ5tMG9b0Ltz1VatFrjjRva0oRbfPmNDnZ9V6GBe9tV6wnhnHBM2dQKn67vTY0Uyp93Ely3cQaezPbMTiUW5HCVeybI1gPjqlQfqQttnNhC16ACiZ46Z9EBFE4ASRqWeT5GitHeZ+dW7LmTxD/O2q9Pd+uvrK8ezy4ZwgSrzdi4MTfLaeKHz2nT2Zi+orT6Ng9UopXfW0EiI1sqt3m/Vw8gJjtvO+bvXAnss3dm4ycdgzW3PFS78RnQWdQOQlIPJMzc3u57Hz2692BZGXiVxJe+9lX+oIIicX7Ve71T4oEuDN/rW/z/MmihYNgFivD95gH+SV+1vNTG6pOea+/2ROecvFe66s1FudoSl/FkzuEKV+/nZU/Mmc8q4AAPFhPr+/M6bNAilDcW5DDeb9X68uTM3Ujf3uVNHU98bFL6irvDZhPld/mt+to9HGhTAUMbUO87l0twkkRC3V7322e4Le4gwDAHh156VFf2bpRzaZODithitemiLyuuZAybS05sEFhA0/f2M8znKULP7szX9BHYMTQgtM6MJHRWfJ21CZ4y8KZl+u4OV9AAB0wJRZlLz9n9WnM0GZQMltt0wgzfzll9tFqE66708IV53cnVYyPTVTd5/O4oy4XZXfpbnv0VyttVNmibnLxSJTzMPdIja7n/PUvc3fPXxFNzLcT5bZkDKjA+T5AJB/NzuRkRpZYaRGVggAoJIxTbcGr2CT8tdXrRCdhR0AQKQ1ExbQfqPWNepMP+VjJVKfU9Ui4A2BN7QZcplIW5xs9CgWIQAMVZ1a7fHtnCKDPajc4gxoEaS8zNLEY86QxcFLs8usrcJ9pTl+Ctbgfvy5gS3eOJ1r6H71uiXple8ufRYdoMjsGas54XpOr1b+x08t6h2iYGmvjrqDE9irpZZWvCBKq+uVEHvrUOV5itTfmCVGe0CpyRnWMkhx/rrREVxudYbIJbQuJkBxTRBF6up1SwsHLyiDVdKcIJVE56mMrFJLxP9+zXq9faQ69bHkyC+OXNF13nG6eKLZwQfLWap0aGJwyr1tAlIbcj+3CpuTl14rs8Zwgih3fWb7KdjicF9ZUd2+pUA47fpFguX4IwBEoFT93qf9xqz9x0exbk3FC9IZX6alpBcYuy0f33b8yA4huz2d9/FvOTM+2Ju1ZGDboJQ1jyZOodwaJMpfXrzsgbaTJ3x88qCDF/wWbMn44usnkgZVWoFqApQSbV33s+VE4ehXvru43l0gKx9uN2JY++Bf6/t9pqw7u/lcgbFXckvNtvR8Y+9yqzNcLqF1D3eNWFpqckTsSS+Z5OAEnwiN7Pw7Y9pM7xMX8Id7GVtPFI3dfrJo2u60kmHFBnvQutTcl21OoToS9d3p4imz+ka/NLd/85US+vYnIV4sMke/sP38J2fzjD05XpDX8NWUkvyJ3SPef2ZAzPsU5fntRMGUOkQo/2kBABAii9/DBE55/Z8S5r3tE4UOTpCXmR3RDk5Q5mqtzb2dd67A2JYXROm1MktbQfTsPHVu7pu+eFybxyQMZc7V2RJmbUzbYLRx8r9yPwoJbVVKGaNSyhgVEsYkiEA4QZRf01pjGxZNsyTwgig9eFn7sM7ijBJEEMx2PvDTgznvfnuqaI7NKagFEcRcra3dC9sufMoLtdfEdfICU/nwCFl94Npim1NQRfnLz93fPnhduJ/sgoMTFB/8mvX+rA3pa7Vmp8/tbJ/9F8r6jPno+NHj2eUDHZygYGnKXFU/hBBnmckR9cGvWcsXbD2/xOYUJB48Zwmv2/ZfAIElTMAlJuTZSUCpjCiQqvCcIFJmO1f1NK7zaWd21IjX1xTSjSdXncOK0R1Dv5+cHPk2AEBavvHeV3dcesvJC3RD73f4PSE/7J7btfPueV07bXuyUxcAsNzs754Qofpt1SPtBvvKmcLK8aUwoUv4kvkDYl6oDCW3Mdt5ZV0jVACAtmE++7fN6nTv6omJUzfPSOrfvYXmOwAgP2dcn7Rw6/kPHJxwWyy9kxeol7698KHBxoXIWKp8waCWT+2e17VT1bZlZqfkxAjV/kqrN39PesmgWvrgywNFvjQGAIBS3beSMIFl8A+iwRW/62zxxIvFpmT3/WdzDS1O5RqSAQDiQpRn3I/LJJQpRC29fK3M2nL7yaLJ8wfELHOPQOXrbYGpmbqRAABxoT6naOJ9koumiPDfobGLr5SY4/ddKJu49WTh3OhAeda8/jErG/QLU0SI8pflAgCY7BwNN7lmbf82gd+seDhhitnOSyQMZQEAeLBr+OLFY+Nf+iGtZEDV1xltnFQtZ0zeyunXJnDz8vHxTwT4SAwAAM0D5AUbH+8wbuHW88u2nyyas+9C6YMZhab3O0Sp029142cUmFrm6WyJlVHKpyb1iNzoerx5gBw2PN5h1KiVx1Ozy6ztDmXq+o7uGFrzVWBRYEEUWQAAIon6x/01qwYLZMfp4jonYGKDlScf7Bq+0X2/hKa4h7qGr/4zSz+4QG9r88PZkkFjkkJ/cD3ny8N5jzs4wZcA8I8lR66ob7KRpoiweFz8MxM/OxV7scjc48O92e+2CfU5Mygh6GBjVVy3Fn4n1DLGYrbz1cOOULU0lxAAGUNVhw8NNk7uLbRHEWJZ5iKOKqQMxc/tH7Pyl4zSyUYb55ens4XdDoFwQkXHBgCI0MiyPZ0ToJQYwvxk17PLrGB38op6Ijaii2mhBMvRQSJXHlMzGqvOoXx67vrHCaRlkCLDT8F6SgNwtg3zOTJ3QMySULXUo4M84p6QH5b+dPVcvt6WsC41d/7QxKBfZCztAAAoLLcFbztZNB0AoGcr/287RftmNOR+QtXS0o8eSXxo7OoTqXqLM+L5bRc2hPvJBidGqC40daUG+Ehc4+teOxVFgSXQTRxVsDThaarCkoqieNt9xd1p1x++VGRO9nSsQG9r9lfLE5058Vzx0u0g8rIaApG2/JHySd51tyxH1GCBvDAkds7gdkH7buZLJAzFT+wesXLxj1c+Oldg7Hk0S9+5T1zAYQCALceLxhYb7DEMTeyP94pa9VfKjQtRXntrVOtpz23J2FJmckQ/vTlj3eYZSQMClKy5ievV5hI+ld8NHeGbYwWzGnBaw4ejtKaIkrX9VeQq1vgS+bIwEGwqDPN6YVynsK1fHM57tshgj/3099w5feICDlscvPTLI3nPAgBpH6k+kByrSf2r5Y7sEPJTvs727Lt7MtdcLDJ1f+6bjNWrHmk3XSGh7XeCQEpNTq8WRBSBtXMCLWWa/n3yFkGKc2qZ90RPmiL2UR1DNze0PEL7lTHhbw2vHs4VvvGVYDnxEArECyG+0tJh7YM3fX4o99XUTO3oi0Wm6D+u6pOLDfaWAACPJUd+KGdpp7frvztdPPTIFd3gab2ilsWFKK+5Hpv+n2afp+Ubk3adLZ6x70LZQ2t+u3bqmftavN9UleqnYFyHWF4tCC+I6lX7s5+a1z/mw6rhVBVpecY2RhunBABBLWNue9j0+cEt5w5KCPq9rlETTZFGEPKd9Qp4o70wRQDg8d7NVrM0MXGCKJ2XkvHNh/uy36l8ep28v33InrquX/LjlTe/Opo/Z9X+7AWCWHNugaWJ8M6Y1gs7RKn3CqLIfHYwd0FTVqpSwtirWpoXxLocW7Jib/aSpT9frf6dOEGkNxzJHz/n6/TNvCBKYwIVZ9tFqjNux30285fnsjQxAgC899PVt0/nGuJoinBeNi/iIDxUhvdF25UWXhwSRuT1oQAAhJI5PPkfhDBOAADRkdMMRN5D2F6gRF4fXnEyY2ustmzUF6YiNbLigQlBX/1wtuSJcwXGrlW/+aQekR+w9by/EB0gv5KrtSbtTiuZlK+3tVLLWFvN544IheX26MpO5vX3Ss83tl65P3uRgxN9eEEgVU/4rScKZx3PLh8CAGLPWM3Oab2i/k6qRJVASInRXqcPwgui5KP9197UW5yaQQlBu35Mvz78m+OFTzl5UeErZwveGBk3I0DJ6r1Eocibuy6/kau1tQcAOJtn6AAAkKuzJUxdf3YHAECgD5v90rDYV/zktdN3glQS4+TkqHfXHsp9PbPE3P3Rz08faBehOu4jZWpZcoYmtum9o97p0tzvtNtQqoSwoedFe2YIX/79y4LtfD9C+9hrtIyzJFB05HQDACDyRI9WisjifxdNBxME8x+POvMXtiKMf437FXm9j2jP6g4AQMnvOeDRQTL+OkYwH5184yKuOsLI67a9KRj3zXX5vl2036jP6luetU6ByCqGPAIAUBKGuiVj+oWDWr6pUbC2zccKpzp5wSc6QJ4xumPojvque25gi9cvFZuTSgz2lkev6gd6NYkEuEe7Ryz3dnxPesnIH86WPOy+/3Kxuf3lYnN7AIBTOeWJ3gQioSvmPGiKWAEAGIrwDFXxxzGrInMShtgYmlg5XlQylPdoDUWIMTZYkXap2Jy88Y/85zf+kV+dCd02XHVo6QPxUxMjVF5XZy/U2/zWHsp9wb0djTYu4JeM6yMqnszAD78n5Jverfw9+ncvDmm5WKNgdSv2Zi022rigI1d0Q7wOHeVMtrtAgJI6mMDp851Fb+8E3tBMtGUM8tLjBCJt9SPtO+Ijjz6O/yNvi46cDqLjWg/RntlX9NLbCBt+jA6Y+KoHK0Xz+l3zRUdWb49GzH65h2uZxJ7VilL1TyG0r/GmBRIbrCh5eVir2QYbp/GU6n6TzmDe6I6hn286mj+70nn/1F/Jltd3XVK077lvZiT133aicKLJzod4G8C2CVWmju4Y+p23csYkhX1ldQp+HC96S+EQuzT3/cXb9W+Oaj37xLXy/wxNDP664gktMb00NHbh+SJzpzFJoTsrfBDW8dao1tOyS63xw9oH76kjzGtfN+WecYt2XFp85IpupCgCQ1Ng7R0XsPXtUa1f9JbsWEWERqZfdH+r2bk6WzvvIWc2J6mZ76m6IoxP9Wu+plesJnXvhbJhRhsX5rGj0MT6YJfwjz0//ducYcPf6S2YDo0Fwdgcao+heCKJOkope+4CSmn13PHD8pnwN4YJhr3jgdfGexj+C0D7XaRU/TYTJkDroQCeDpj4smg5NRYaEEMmsta/EFptqve8xl4XSxBEasbGtM9/TL/+mI+UKU59ITnWX8ma4F/E/+3OfGb1gWvLGJqUZr3TLwgAQGdxqgVBlEkYyqSSMRZA/j1RLCcvMpxQkeh2odDc4uBl7QgAgAldwtb828ThDU1Fir8Ba+JfJhCLg5fMTzm35kyeYQAAgNUpyM123t9XzhRP7B6xDpsA+VcLxGzn5Wn5xm4FenuU6zh/YELQVy2DlDn/xkoP9JGUEgDBX8HiUkN3OI3ig6TlGdtml1kSXXZxPWP9f/q3Dq9sToHZf7F0UPMAxaX4MB/8G4L/doEgyN0KLj2KICgQBEGBIAgKBEFQIAiCAkEQFAiCoEAQBAWCICgQBEFQIAiCAkEQFAiCoEAQBAWCICgQBEGBIAgKBEFQIAiCAkEQBAWCICgQBEGBIAgKBEFQIAiCAkEQFAiCoEAQBAWCIAgKBEFQIAjyN/l/SQUZ4jt6Q7IAAAAASUVORK5CYII='
-
-main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py b/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py
deleted file mode 100644
index 248c593ed..000000000
--- a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py
+++ /dev/null
@@ -1,158 +0,0 @@
-import PySimpleGUI as sg
-import math
-import psutil
-
-"""
- Demo Program - Display CPI Usage as a VU Meter
-
- Artwork and algorithm for handling of needle positioning generously provided by GitHub user neovich.
-
- A long-time PySimpleGUI user and brilliant programmer posted a screenshot of an incredibly
- complex audio recording mixing application with features like custom sliders and VU meters made
- entirely of Graph elements. I asked him to draw us some special artwork for this demo. An ENORMOUS
- thank you to him for the encouragement, support, and hard work!
-
- This demo uses the psutil library to get the CPI utilization. It is then shown on a nicely rendered
- VU meter.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# --- VU Meter Parameters ----------------------------------------------
-
-x_needle_base = 169
-y_needle_base = 10
-needle_length = 280
-needle_multiply = 2
-needle_width = 2
-needle_color = '#434443'
-needle_cutoff = 100
-angle_min = 60
-angle_max = 122
-CANVAS_KEY = 'CANVAS_vu_meter'
-
-# --- Colours ----------------------------------------------------------
-tick1_color = '#222222'
-tick2_color = tick1_color
-background = '#626059'
-module_background = '#F2E2CA'
-win0_background_color = background
-tab_inner_colour = 'black'
-background_main = background
-
-
-sg.set_options(background_color=background, element_background_color=background)
-
-# ---------------------- Definitions -----------------------------------
-
-
-def VU_METER_update(CONT_CANVAS_vu_meter, a):
- if a < angle_min :
- a = angle_min
- if a > angle_max:
- a = angle_max
- CONT_CANVAS_vu_meter.erase()
- OBJ_VU_meter = CONT_CANVAS_vu_meter.draw_image(data=vu_meter_2,location= (0,234))
- x_angle = math.cos(math.radians(180-a))
- y_angle = math.sin(math.radians(180-a))
- x_cur = x_needle_base+(x_angle * needle_length)
- y_cur = y_needle_base+int((y_angle * needle_length)*0.7)
- x_cur_low = int(x_needle_base+(x_angle * (needle_length/needle_multiply)))
- y_cur_low = int(y_needle_base+int((y_angle * (needle_length/needle_multiply))*0.7))
- OBJ_VU_meter_needle = CONT_CANVAS_vu_meter.draw_line( (x_cur_low,y_cur_low),(int(x_cur),int(y_cur)) ,color=needle_color,width=needle_width)
-
-
-def main():
- # ------------------------- Init the VU_Meter --------------------------
-
-
- VU_METER_cont = [[sg.Graph ( canvas_size = ( 339,234 ),
- graph_bottom_left=(0,0),
- graph_top_right=(339,234),
- background_color=module_background,
- drag_submits=True,
- enable_events=True,
- float_values=True,
- key=CANVAS_KEY )]]
-
-
- # ------------------------- Tab Set Ups --------------------------------
- layout = [[sg.Column(VU_METER_cont ,background_color=module_background )]]
-
-
-
- location = sg.user_settings_get_entry('-location-', (None, None))
-
- # ------------------------ Finalize Windows ----------------------------
-
- window = sg.Window('CPU Usage as a VU Meter', layout,
- no_titlebar=True,
- auto_size_buttons=False,
- keep_on_top=True,
- grab_anywhere=True,
- force_toplevel=False,
- finalize=True,
- location=location,
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT,
- enable_close_attempted_event=True)
-
- # ------------------------ Init the VU_Meter ---------------------------
-
- CONT_CANVAS_vu_meter = window[CANVAS_KEY]
- angle = angle_min
- x_angle = math.cos(math.radians(180-angle))
- y_angle = math.sin(math.radians(180-angle))
- x_cur = x_needle_base+(x_angle * needle_length)
- y_cur = y_needle_base+int((y_angle * needle_length)*0.7)
- x_cur_low = int(x_needle_base+(x_angle * (needle_length/needle_multiply)))
- y_cur_low = int(y_needle_base+int((y_angle * (needle_length/needle_multiply))*0.7))
- OBJ_VU_meter_needle = CONT_CANVAS_vu_meter.draw_line( (x_cur_low,y_cur_low),(int(x_cur),int(y_cur)) ,color=needle_color,width=needle_width)
- window.refresh()
-
- ########################################################################
- ## MAIN LOOP ##
- ########################################################################
- temp_angle = 0
- angle_impulse = 2
- angle_range = angle_max-angle_min
- while True:
- event, values = window.read(timeout=30)
- 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__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
-
-
- cpu_percent = psutil.cpu_percent(interval=1)
- target_angle = angle_range * cpu_percent/100 + angle_min
- if temp_angle == 0:
- temp_angle = target_angle
-
- delta = abs(temp_angle - target_angle)
- if temp_angle > target_angle:
- temp_angle -= min(angle_impulse, delta)
- else:
- temp_angle += min(angle_impulse, delta)
- VU_METER_update(CONT_CANVAS_vu_meter, temp_angle)
- CONT_CANVAS_vu_meter.draw_text(f'{int(cpu_percent)}% CPU USED', (170, 40), color=module_background, font='_ 18')
-
-
-
-
-if __name__ == '__main__':
-
- # --------- Images -----------------------------------------------------
-
- needle = b'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'
-
-
- vu_meter_2 = b'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'
-
- dot3 = b'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'
-
- main()
diff --git a/DemoPrograms/Demo_Graph_Elem_Image_Album.py b/DemoPrograms/Demo_Graph_Elem_Image_Album.py
deleted file mode 100644
index b8a441f8d..000000000
--- a/DemoPrograms/Demo_Graph_Elem_Image_Album.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from PIL import Image
-import PIL
-import io
-import base64
-import os
-
-"""
- Demo Image Album.... displays images on Graph Element and has a visual "slide transition"
-
-
- Click on right side of image to navigate down through filenames, left side for up.
-
- PIL is required for this particular demo because it displays PNG, JPG, TIFF, BMP, GIF and ICO files
-
- Contains a couple of handy PIL-based image functions that resize an image while maintaining correct proportion.
- One you pass a filename, the other a BASE64 string.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-G_SIZE = (800,600) # Size of the Graph in pixels. Using a 1 to 1 mapping of pixels to pixels
-
-sg.theme('black')
-
-
-def convert_to_bytes(file_or_bytes, resize=None):
- '''
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (str | bytes)
- :param resize: optional new size
- :type resize: ((int, int) | None)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- '''
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height/cur_height, new_width/cur_width)
- img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS)
- bio = io.BytesIO()
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-
-folder = sg.popup_get_folder('Where are your images?')
-if not folder:
- exit(0)
-
-file_list = os.listdir(folder)
-fnames = [f for f in file_list if os.path.isfile(
- os.path.join(folder, f)) and f.lower().endswith((".png", ".jpg", "jpeg", ".tiff", ".bmp", ".gif", ".ico"))]
-num_files = len(fnames)
-
-graph = sg.Graph(canvas_size=G_SIZE, graph_bottom_left=(0, 0), graph_top_right=G_SIZE, enable_events=True, key='-GRAPH-', pad=(0,0))
-
-layout = [ [sg.Text('Click on the right side of the window to navigate forward, the left side to go backwards')],
- [sg.Text(f'Displaying image: '), sg.Text(k='-FILENAME-')],
- [graph]]
-
-window = sg.Window('Scrolling Image Viewer', layout, margins=(0,0), use_default_focus=False, finalize=True)
-
-offset, move_amount, direction = 0, 5, 'left'
-
-while True:
- file_to_display = os.path.join(folder, fnames[offset])
- window['-FILENAME-'].update(file_to_display)
- img_data = convert_to_bytes(file_to_display, resize=G_SIZE)
- image_id = graph.draw_image(data=img_data, location=(0, G_SIZE[1]))
-
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
-
- # if image is clicked, then move in the left direction if clicked on left half of the image
- if event == '-GRAPH-':
- direction = 'left' if values['-GRAPH-'][0] < (G_SIZE[0] // 2) else 'right'
-
- # Do the animation
- for i in range(G_SIZE[0]//move_amount):
- graph.move_figure(image_id, -move_amount if direction == 'left' else move_amount, 0)
- window.refresh()
- graph.delete_figure(image_id)
-
- # Bump the image index
- if direction == 'left':
- offset = (offset + (num_files - 1)) % num_files # Decrement - roll over to MAX from 0
- else:
- offset = (offset + 1) % num_files # Increment to MAX then roll over to 0
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py b/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py
deleted file mode 100644
index 9a073f8ef..000000000
--- a/DemoPrograms/Demo_Graph_Elem_Image_Album_No_PIL.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import os
-
-"""
- Demo Image Album... NO PIL version.... displays images on Graph Element and has a visual "slide transition"
-
- Click on right side of image to navigate down through filenames, left side for up.
-
- Same program as the Demo_Graph_Elem_Image_Album.py, but without using PIL
-
- Not using PIL has 2 impacts:
- 1. The images are not resized to fit the window
- 2. The images are limited to PNG and GIF files
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-G_SIZE = (800, 600) # Size of the Graph in pixels. Using a 1 to 1 mapping of pixels to pixels
-
-sg.theme('black')
-folder = sg.popup_get_folder('Where are your images?')
-if not folder:
- exit(0)
-
-file_list = os.listdir(folder)
-fnames = [f for f in file_list if os.path.isfile(
- os.path.join(folder, f)) and f.lower().endswith((".png", ".gif"))]
-num_files = len(fnames)
-
-graph = sg.Graph(canvas_size=G_SIZE, graph_bottom_left=(0, 0), graph_top_right=G_SIZE, enable_events=True, key='-GRAPH-', pad=(0, 0))
-
-layout = [[sg.Text('Click on the right side of the window to navigate forward, the left side to go backwards')],
- [sg.Text(f'Displaying image: '), sg.Text(k='-FILENAME-')],
- [graph]]
-
-window = sg.Window('Scrolling Image Viewer', layout, margins=(0, 0), use_default_focus=False, finalize=True)
-
-offset, move_amount, direction = 0, 5, 'left'
-
-while True:
- file_to_display = os.path.join(folder, fnames[offset])
- window['-FILENAME-'].update(file_to_display)
-
- image_id = graph.draw_image(filename=file_to_display, location=(0, G_SIZE[1]))
-
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
-
- # if image is clicked, then move in the left direction if clicked on left half of the image
- if event == '-GRAPH-':
- direction = 'left' if values['-GRAPH-'][0] < (G_SIZE[0] // 2) else 'right'
-
- # Do the animation
- for i in range(G_SIZE[0] // move_amount):
- graph.move_figure(image_id, -move_amount if direction == 'left' else move_amount, 0)
- window.refresh()
- graph.delete_figure(image_id)
-
- # Bump the image index
- if direction == 'left':
- offset = (offset + (num_files - 1)) % num_files # Decrement - roll over to MAX from 0
- else:
- offset = (offset + 1) % num_files # Increment to MAX then roll over to 0
-
-window.close()
diff --git a/DemoPrograms/Demo_Graph_Element.py b/DemoPrograms/Demo_Graph_Element.py
index 801936bf5..906fa4396 100644
--- a/DemoPrograms/Demo_Graph_Element.py
+++ b/DemoPrograms/Demo_Graph_Element.py
@@ -1,101 +1,71 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-import random
+import ping
+from threading import Thread
import time
-import gc
-try:
- import ping3
-except:
- ping3 = None
- if sg.popup_yes_no('This version of Python does not have the ping3 module installed. Would you like it to be installed?') == 'Yes':
- sg.execute_pip_install_package('ping3') # pip install the ping3 package
- sg.execute_restart(__file__) # restart this program so that it'll pick up the new ping3 installation
- else:
- sg.popup_quick_message('OK... Ping3 not installed so data will be simulated', font='_ 18', text_color='white', background_color='red', auto_close_duration=6)
-"""
- Use a Graph element to show ping times to a URL using a line graph
+STEP_SIZE = 1
+SAMPLES = 1000
+CANVAS_SIZE = (1000, 500)
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
-"""
-
-if ping3:
- ping_url = 'google.com'
-else:
- ping_url = 'simulated data'
-
-
-def ping_thread(window: sg.Window):
- while True:
- if ping3:
- ping_time = int(ping3.ping(ping_url) * 1000)
- else:
- time.sleep(.001)
- ping_time = random.randint(0, 100)
- if ping_time:
- window.write_event_value('-THREAD-', ping_time)
+def ping_thread(args):
+ global g_exit, g_response_time
+ while not g_exit:
+ g_response_time = ping.quiet_ping('google.com', timeout=1000)
def main():
- global ping_url
+ global g_exit, g_response_time
- STEP_SIZE = 1
- SAMPLES = 100
- CANVAS_SIZE = (1000, 500)
- Y_MAX = 500
- X_MAX = 500
+ # start ping measurement thread
+ thread = Thread(target=ping_thread, args=(None,))
+ thread.start()
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
+ sg.set_options(element_padding=(0, 0))
layout = [
- sg.vbottom(
- [sg.Column([[sg.T('Ping in MS'), sg.T(k='-TIME-', s=4)],[sg.Slider((50, Y_MAX), default_value=Y_MAX, orientation='v', size=(20, 20), k='-Y SLIDER-', expand_y=True, enable_events=True)]], expand_y=True, element_justification='r'),
- sg.Column([
- [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 200), background_color='black', key='-GRAPH-')],
- [sg.Text('# Samples:'), sg.Slider((50, X_MAX), default_value=SAMPLES, orientation='h', size=(50, 20), k='-X SLIDER-', expand_x=True, enable_events=True)],
- [sg.Text('Ping times to:'), sg.Input(ping_url, size=15, key='-URL-', readonly=not ping3, use_readonly_for_disable=True, disabled_readonly_text_color='black', disabled=not ping3), sg.B('Set', disabled=not ping3)],])],
- expand_x=True, expand_y=True)
+ [sg.Text('Ping times to Google.com', font='Any 12'),
+ sg.Quit(pad=((100, 0), 0), button_color=('white', 'black'))],
+ [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 500),
+ background_color='black', key='graph')]
]
- window = sg.Window('Ping Graph', layout, background_color='black', finalize=True, font='_ 16')
+ window = sg.Window('Canvas test', layout,
+ grab_anywhere=True, background_color='black',
+ no_titlebar=False, use_default_focus=False)
- graph = window['-GRAPH-']
-
- i = prev_x = prev_y = 0
- fig_list = []
- window.start_thread(lambda : ping_thread(window))
+ graph = window['graph']
+ prev_response_time = None
+ i = 0
+ prev_x, prev_y = 0, 0
while True:
- event, values = window.read()
- if event == 'Quit' or event == sg.WIN_CLOSED:
+ event, values = window.read(timeout=200)
+ if event == 'Quit' or event is None:
break
- if event == '-THREAD-':
- new_x, new_y = i, values[event]
- window['-TIME-'].update(values[event])
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ new_x, new_y = i, g_response_time[0]
+ prev_response_time = g_response_time
if i >= SAMPLES:
graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
- fig = fig_list[0]
- fig_list.pop(0)
- graph.delete_figure(fig)
- # gc.collect() # Run garbage collect. Uncomment if you want the space freed immediately
- fig = graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
- fig_list.append(fig)
+ graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
+ # window['graph'].draw_point((new_x, new_y), color='red')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
- if event == '-X SLIDER-' or event == '-Y SLIDER-':
- graph.delete_figure(fig_list)
- graph.change_coordinates((0,0), (values['-X SLIDER-'], values['-Y SLIDER-']))
- graph.erase()
- fig_list = []
- i = 0
- prev_x, prev_y = 0, 0
- SAMPLES = values['-X SLIDER-']
- if event == 'Set': # set a new URL to ping
- ping_url = values['-URL-']
+
+ # tell thread we're done. wait for thread to exit
+ g_exit = True
+ thread.join()
+
window.close()
diff --git a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
index 093701e78..c69072fd1 100644
--- a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
+++ b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
@@ -1,32 +1,11 @@
import PySimpleGUI as sg
import math
-"""
- Demo - Graph Element used to plot a mathematical formula
-
- The Graph element has a flexible coordinate system that you define.
- Thie makes is possible for you to work in your coordinates instead of an
- arbitrary system.
-
- For example, in a typical mathematics graph, (0,0) is located at the center
- of the graph / page / diagram.
- This Demo Program shows a graph with (0,0) being at the center of the Graph
- area rather than at one of the corners.
-
- It graphs the formula:
- y = sine(x/x2) * x1
-
- The values of x1 and x2 can be changed using 2 sliders
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
+# Yet another usage of Graph element.
SIZE_X = 200
-SIZE_Y = 200
-NUMBER_MARKER_FREQUENCY = SIZE_X//8 # How often to put tick marks on the axis
+SIZE_Y = 100
+NUMBER_MARKER_FREQUENCY = 25
def draw_axis():
@@ -34,45 +13,43 @@ def draw_axis():
graph.draw_line((0, -SIZE_Y), (0, SIZE_Y))
for x in range(-SIZE_X, SIZE_X+1, NUMBER_MARKER_FREQUENCY):
- graph.draw_line((x, -SIZE_Y/66), (x, SIZE_Y/66)) # tick marks
+ graph.draw_line((x, -3), (x, 3)) # tick marks
if x != 0:
# numeric labels
- graph.draw_text(str(x), (x, -SIZE_Y/15), color='green', font='courier 10')
+ graph.draw_text(str(x), (x, -10), color='green')
for y in range(-SIZE_Y, SIZE_Y+1, NUMBER_MARKER_FREQUENCY):
- graph.draw_line((-SIZE_X/66, y), (SIZE_X/66, y))
+ graph.draw_line((-3, y), (3, y))
if y != 0:
- graph.draw_text(str(y), (-SIZE_X/11, y), color='blue', font='courier 10')
+ graph.draw_text(str(y), (-10, y), color='blue')
+
-# Create the graph that will be put into the window. Making outside of layout so have element in a variable
-graph = sg.Graph(canvas_size=(500, 500),
+# Create the graph that will be put into the window
+graph = sg.Graph(canvas_size=(400, 400),
graph_bottom_left=(-(SIZE_X+5), -(SIZE_Y+5)),
graph_top_right=(SIZE_X+5, SIZE_Y+5),
- background_color='white', expand_x=True, expand_y=True,
- key='-GRAPH-')
+ background_color='white',
+ key='graph')
# Window layout
-layout = [[sg.Text('Graph Element Combined with Math!', justification='center', relief=sg.RELIEF_SUNKEN, expand_x=True, font='Courier 18')],
+layout = [[sg.Text('Example of Using Math with a Graph', justification='center', size=(50, 1), relief=sg.RELIEF_SUNKEN)],
[graph],
- [sg.Text('y = sin(x / x2) * x1', font='COURIER 18')],
- [sg.Text('x1', font='Courier 14'), sg.Slider((0, SIZE_Y), orientation='h', enable_events=True, key='-SLIDER-', expand_x=True)],
- [sg.Text('x2', font='Courier 14'), sg.Slider((1, SIZE_Y), orientation='h', enable_events=True, key='-SLIDER2-', expand_x=True)]]
-
-window = sg.Window('Graph of Sine Function', layout, finalize=True)
+ [sg.Text('y = sin(x / x2 * x1)', font='COURIER 18')],
+ [sg.Text('x1'), sg.Slider((0, 200), orientation='h',
+ enable_events=True, key='-SLIDER-')],
+ [sg.Text('x2'), sg.Slider((1, 200), orientation='h', enable_events=True, key='-SLIDER2-')]]
-draw_axis() # draw the axis (an empty graph)
+window = sg.Window('Graph of Sine Function', layout)
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
-
- graph.erase() # erase entire graph every time there's a change to a slider
- draw_axis() # redraw the axis
-
- # plot the function by drawing short line segments
+ graph.erase()
+ draw_axis()
prev_x = prev_y = None
+
for x in range(-SIZE_X, SIZE_X):
- y = math.sin(x/int(values['-SLIDER2-'])) * int(values['-SLIDER-'])
+ y = math.sin(x/int(values['-SLIDER2-']))*int(values['-SLIDER-'])
if prev_x is not None:
graph.draw_line((prev_x, prev_y), (x, y), color='red')
prev_x, prev_y = x, y
diff --git a/DemoPrograms/Demo_Graph_Noise.py b/DemoPrograms/Demo_Graph_Noise.py
index 323cadd70..6161c2d6c 100644
--- a/DemoPrograms/Demo_Graph_Noise.py
+++ b/DemoPrograms/Demo_Graph_Noise.py
@@ -5,14 +5,8 @@
'''
Example of random line in Graph element.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-sg.theme('black')
-
STEP_SIZE = 1
SAMPLES = 300
SAMPLE_MAX = 300
@@ -23,12 +17,12 @@ def main():
global g_exit, g_response_time
layout = [[sg.Text('Enter width, height of graph')],
- [sg.Input(300, size=(6, 1), key='w'), sg.Input(300, size=(6, 1), key='h')],
+ [sg.Input(size=(6, 1), key='w'), sg.Input(size=(6, 1), key='h')],
[sg.Ok(), sg.Cancel()]]
window = sg.Window('Enter graph size', layout)
event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Cancel':
+ if event is None or event == 'Cancel':
return
CANVAS_SIZE = int(values['w']), int(values['h'])
@@ -36,29 +30,25 @@ def main():
# start ping measurement thread
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [[sg.Button('Quit', button_color=('white', 'black'))],
- [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, SAMPLE_MAX),
+ [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, SAMPLE_MAX)
background_color='black', key='graph')], ]
window = sg.Window('Canvas test', layout, grab_anywhere=True,
background_color='black', no_titlebar=False,
use_default_focus=False, finalize=True)
- graph = window['graph'] # type:sg.Graph
-
- graph.draw_line((SAMPLES//2, 0), (SAMPLES//2,SAMPLE_MAX),color='white')
- graph.draw_line((0,SAMPLE_MAX//2), (SAMPLES, SAMPLE_MAX//2),color='white')
+ graph = window['graph']
prev_response_time = None
i = 0
prev_x, prev_y = 0, 0
graph_value = 250
- figures = []
while True:
event, values = window.read(timeout=0)
- if event == 'Quit' or event == sg.WIN_CLOSED:
+ if event == 'Quit' or event is None:
break
graph_offset = random.randint(-10, 10)
@@ -73,14 +63,10 @@ def main():
prev_value = graph_value
if i >= SAMPLES:
- graph.delete_figure(figures[0])
- figures = figures[1:]
- for count, figure in enumerate(figures):
- graph.move_figure(figure, -STEP_SIZE, 0)
+ graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
- last_figure = graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
- figures.append(last_figure)
+ graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
diff --git a/DemoPrograms/Demo_Graph_Window_Resize.py b/DemoPrograms/Demo_Graph_Window_Resize.py
deleted file mode 100644
index e6a37409f..000000000
--- a/DemoPrograms/Demo_Graph_Window_Resize.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Graph Element Rescale Figures When Window Resizes
-
- This demo shows how you can redraw your Graph element's figures so that when
- you resize the window, all of the figures on the graph resize.
-
- There may be a tkinter method to help do this?
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-gsize = (400,400)
-
-layout = [ [sg.Text('Rescaling a Graph Element When Window is Resized')],
- [sg.Graph(gsize, (0,0),gsize, expand_x=True, expand_y=True, k='-G-', background_color='green')],
- [sg.Button('Exit'), sg.Sizegrip()] ]
-
-window = sg.Window('Graph Element Scale With Window', layout, finalize=True, resizable=True, enable_window_config_events=True)
-
-graph = window['-G-'] #type: sg.Graph
-
-orig_win_size = window.current_size_accurate()
-# Draw the figure desired (will repeat this code later)
-fig = window['-G-'].draw_circle((200, 200), 50, fill_color='blue')
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == sg.WINDOW_CONFIG_EVENT: # if get a window resized event
- # Determine how much the window was resized by and tell the Graph element the new size for the Canvas
- new_size = window.current_size_accurate()
- dx = orig_win_size[0]-new_size[0]
- dy = orig_win_size[1]-new_size[1]
- gsize = (gsize[0] - dx, gsize[1] - dy)
- orig_win_size = new_size
- graph.CanvasSize = gsize
- # Erase entire Graph and redraw all figures0
- graph.erase()
- # Redraw your figures here
- fig = window['-G-'].draw_circle((200, 200), 50, fill_color='blue')
-
-window.close()
diff --git a/DemoPrograms/Demo_Graph__Element.py b/DemoPrograms/Demo_Graph__Element.py
new file mode 100644
index 000000000..1a40ef375
--- /dev/null
+++ b/DemoPrograms/Demo_Graph__Element.py
@@ -0,0 +1,71 @@
+import PySimpleGUI as sg
+from threading import Thread
+import ping
+import time
+
+# Yet another usage of Graph element.
+
+STEP_SIZE = 1
+SAMPLES = 6000
+CANVAS_SIZE = (6000, 500)
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
+
+
+def ping_thread(args):
+ global g_exit, g_response_time
+ while not g_exit:
+ g_response_time = ping.quiet_ping('google.com', timeout=1000)
+
+
+def main():
+ global g_exit, g_response_time
+
+ # start ping measurement thread
+ thread = Thread(target=ping_thread, args=(None,))
+ thread.start()
+
+ sg.change_look_and_feel('Black')
+ sg.set_options(element_padding=(0, 0))
+
+ layout = [[sg.Text('Ping times to Google.com', font='Any 12'),
+ sg.Quit(pad=((100, 0), 0), button_color=('white', 'black'))],
+ [sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 500),
+ background_color='black', key='graph')]
+ ]
+
+ form = sg.FlexForm('Canvas test', layout, grab_anywhere=True, background_color='black',
+ no_titlebar=False, use_default_focus=False, finalize=True)
+ graph = form['graph']
+
+ prev_response_time = None
+ i = 0
+ prev_x, prev_y = 0, 0
+ while True:
+ time.sleep(.2)
+
+ button, values = form.ReadNonBlocking()
+ if button == 'Quit' or values is None:
+ break
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ new_x, new_y = i, g_response_time[0]
+ prev_response_time = g_response_time
+ if i >= SAMPLES:
+ graph.move(-STEP_SIZE, 0)
+ prev_x = prev_x - STEP_SIZE
+ graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
+ # form['graph'].draw_point((new_x, new_y), color='red')
+ prev_x, prev_y = new_x, new_y
+ i += STEP_SIZE if i < SAMPLES else 0
+
+ # tell thread we're done. wait for thread to exit
+ g_exit = True
+ thread.join()
+
+
+if __name__ == '__main__':
+ main()
+
diff --git a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py
index 72e0d406a..625095c6c 100644
--- a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py
+++ b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py
@@ -1,5 +1,4 @@
-import PySimpleGUI as sg
-# import PySimpleGUIWeb as sg
+import PySimpleGUIWeb as sg
import pymunk
import random
import socket
@@ -8,15 +7,9 @@
"""
- To get a good version of pymunk that works with this code:
- python -m pip install pymunk==5.7.0
Demo that shows integrating PySimpleGUI with the pymunk library. This combination
of PySimpleGUI and pymunk could be used to build games.
Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -35,8 +28,7 @@ def __init__(self, x, y, r, *args, **kwargs):
class Playfield():
- def __init__(self, graph_elem):
- self.graph_elem = graph_elem
+ def __init__(self):
self.space = pymunk.Space()
self.space.gravity = 0, 200
self.add_wall((0, 400), (600, 400)) # ground
@@ -58,46 +50,39 @@ def add_balls(self):
r = random.randint(1, 10)
ball = Ball(x, y, r)
self.arena_balls.append(ball)
- self.space.add(ball.body, ball.shape)
- ball.gui_circle_figure = self.graph_elem.draw_circle(
- (x, y), r, fill_color='black', line_width=0)
-
-
-def main():
-
-
-
- # ------------------- Build and show the GUI Window -------------------
- graph_elem = sg.Graph((600, 400), (0, 400), (600, 0),
- enable_events=True, key='-GRAPH-', background_color='lightblue')
-
- hostname = socket.gethostbyname(socket.gethostname())
- layout = [[sg.Text('Ball Test'), sg.Text('My IP '+hostname)],
- [graph_elem],
- # [sg.Up(), sg.Down()],
- [sg.Button('Kick'), sg.Button('Exit')]]
-
- window = sg.Window('Window Title', layout, finalize=True)
-
- area = Playfield(graph_elem)
- area.add_balls()
-
- # ------------------- GUI Event Loop -------------------
- while True: # Event Loop
- event, values = window.read(timeout=0)
- # print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- area.space.step(0.02)
-
- for ball in area.arena_balls:
- if event == 'Kick':
- ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(
- 1, 200)
- graph_elem.RelocateFigure(
- ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
+ area.space.add(ball.body, ball.shape)
+ ball.gui_circle_figure = graph_elem.draw_circle(
+ (x, y), r, fill_color='black', line_color='red')
+
+
+# ------------------- Build and show the GUI Window -------------------
+graph_elem = sg.Graph((600, 400), (0, 400), (600, 0),
+ enable_events=True, key='-GRAPH-', background_color='lightblue')
+
+hostname = socket.gethostbyname(socket.gethostname())
+layout = [[sg.Text('Ball Test'), sg.Text('My IP '+hostname)],
+ [graph_elem],
+ # [sg.Up(), sg.Down()],
+ [sg.Button('Kick'), sg.Button('Exit')]]
+
+window = sg.Window('Window Title', layout, finalize=True)
+
+area = Playfield()
+area.add_balls()
+
+# ------------------- GUI Event Loop -------------------
+while True: # Event Loop
+ event, values = window.read(timeout=0)
+ # print(event, values)
+ if event in (None, 'Exit'):
+ break
+ area.space.step(0.02)
+
+ for ball in area.arena_balls:
+ if event == 'Kick':
+ ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(
+ 1, 200)
+ graph_elem.RelocateFigure(
+ ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
+
+window.close()
diff --git a/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py b/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py
deleted file mode 100644
index 0a3c4f9a6..000000000
--- a/DemoPrograms/Demo_Graph_pymunk_Desktop_Balls.py
+++ /dev/null
@@ -1,113 +0,0 @@
-import PySimpleGUI as sg
-import pymunk
-import random
-"""
- Demo of pymunk physics lib combined with a large Window that is transparent. Result appears like
- a screensaver type of screen
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-class Ball():
- def __init__(self, x, y, r, *args, **kwargs):
- mass = 10
- # Create a Body with mass and moment
- self.body = pymunk.Body(mass, pymunk.moment_for_circle(mass, 0, r, (0, 0)))
- self.body.position = x, y
- # Create a box shape and attach to body
- self.shape = pymunk.Circle(self.body, r, offset=(0, 0))
- self.shape.elasticity = 0.99999
- self.shape.friction = 0.8
- self.gui_circle_figure = None
-
-
-class Playfield():
- def __init__(self, graph_elem, screensize):
- self.graph_elem = graph_elem # type: sg.Graph
- self.space = pymunk.Space()
- self.space.gravity = 0, 200
- self.screensize = screensize
- self.add_wall((0, screensize[1]), (screensize[0],screensize[1])) # ground
- self.add_wall((0, 0), (0, screensize[1])) # Left side
- self.add_wall((screensize[0], 0), (screensize[0], screensize[1])) # right side
- self.arena_balls = [] # type: List[Ball]
-
- def add_wall(self, pt_from, pt_to):
- body = pymunk.Body(body_type=pymunk.Body.STATIC)
- ground_shape = pymunk.Segment(body, pt_from, pt_to, 1.0)
- ground_shape.friction = 0.8
- ground_shape.elasticity = .99
- self.space.add(ground_shape)
-
- def add_balls(self, num_balls = 30):
- for i in range(1, num_balls):
- x = random.randint(0, self.screensize[0])
- y = random.randint(0, self.screensize[1])
- r = random.randint(5, 10)
- ball = Ball(x, y, r)
- self.arena_balls.append(ball)
- self.space.add(ball.body, ball.shape)
- ball.gui_circle_figure = self.graph_elem.draw_circle(
- (x, y), r, fill_color=random.choice(('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29')), line_width=0)
-
-
-def main():
- screensize = sg.Window.get_screen_size()
-
- # ------------------- Build and show the GUI Windows -------------------
- graph_elem = sg.Graph(screensize, (0, screensize[1]), (screensize[0], 0),
- enable_events=True, key='-GRAPH-', background_color='lightblue')
- layout = [[graph_elem]]
- window1 = sg.Window('Bouncing Balls', layout, finalize=True, location=(0,0), keep_on_top=True, element_padding=(0,0), margins=(0,0), no_titlebar=True, right_click_menu=[[''], ['Front', 'Back', 'Controls', 'Exit']])
-
- area = Playfield(graph_elem, screensize)
- area.add_balls()
- transparent, paused = False, True
- layout2 = [[sg.B('❎', border_width=0, button_color=('white', sg.theme_background_color()), key='Exit')],[sg.B('Kick'), sg.B('Front'), sg.B('Back'), sg.B('More Balls'),sg.B('Transparent'), sg.B('Resume', key='Pause')]]
- window2 = sg.Window('Buttons', layout2, keep_on_top=True, grab_anywhere=True, no_titlebar=True, finalize=True)
-
-
-
- # ------------------- GUI Event Loop -------------------
- while True:
- window, event, values = sg.read_all_windows(timeout=0)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- if event == 'More Balls':
- area.add_balls()
- elif event == 'Kick':
- for ball in area.arena_balls:
- ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(200,400)
- elif event == 'Front':
- window1.bring_to_front()
- elif event == 'Back':
- window1.send_to_back()
- elif event == 'Transparent':
- window1.set_transparent_color('lightblue' if not transparent else 'black')
- transparent = not transparent
- elif event == 'Controls':
- window2.bring_to_front()
- elif event == 'Pause':
- paused = not paused
- window['Pause'].update(text='Resume' if paused else 'Pause')
-
- if paused:
- continue
-
- area.space.step(0.02)
-
- for ball in area.arena_balls:
- if ball.body.position[1] > screensize[1]:
- ball.body.position = ball.body.position[0],screensize[1]-30
-
- graph_elem.RelocateFigure(
- ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
-
- window1.close()
- window2.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Hello_World.py b/DemoPrograms/Demo_Hello_World.py
index afc76e316..ae48f4773 100644
--- a/DemoPrograms/Demo_Hello_World.py
+++ b/DemoPrograms/Demo_Hello_World.py
@@ -3,10 +3,6 @@
"""
Oh yes, the classic "Hello World". The problem is that you
can do it so many ways using PySimpleGUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
sg.popup_no_buttons('Hello World') # the single line
diff --git a/DemoPrograms/Demo_Hotkey.py b/DemoPrograms/Demo_Hotkey.py
deleted file mode 100644
index 370440893..000000000
--- a/DemoPrograms/Demo_Hotkey.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import PySimpleGUI as sg
-"""
- Demo Hotkey
-
- Want a keyboard hotkey to cause your program to take some action
- that's identical to a button being clicked?
-
- Well... that's 1 line of code that's needed.
-
- This line binds the F10 keybaord key to the window. It produces a "Go" event:
- window.bind('', 'Go')
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [ [sg.Text('Press F10 to get same result as clicking "Go" button')],
- [sg.Input(key='-IN-')],
- [sg.Output(size=(30,8))],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-window = sg.Window('Window Title', layout, finalize=True)
-
-window.bind('', 'Go') # Make sure your window is finalized first
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_HowDoI.py b/DemoPrograms/Demo_HowDoI.py
index 477da7b87..679126c7d 100644
--- a/DemoPrograms/Demo_HowDoI.py
+++ b/DemoPrograms/Demo_HowDoI.py
@@ -4,10 +4,6 @@
'''
Famouns howdoi command in PSG
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
@@ -25,7 +21,7 @@ def HowDoI():
'''
# ------- Make a new Window ------- #
# give our form a spiffy set of colors
- sg.theme('GreenTan')
+ sg.change_look_and_feel('GreenTan')
layout = [
[sg.Text('Ask and your answer will appear here....', size=(40, 1))],
diff --git a/DemoPrograms/Demo_IP_Address_Entry.py b/DemoPrograms/Demo_IP_Address_Entry.py
deleted file mode 100644
index 69193b66f..000000000
--- a/DemoPrograms/Demo_IP_Address_Entry.py
+++ /dev/null
@@ -1,56 +0,0 @@
-import PySimpleGUI as sg
-
-'''
- IP Address entry window with digit validation and auto advance
- If not a digit or ., the ignored
- . will advance the focus to the next entry
- On the last input, once it's complete the focus moves to the OK button
- Pressing spacebar with focus on OK generates an -OK- event
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-'''
-
-# create a short-cut element so don't have to type this in over and over
-
-
-def MyInput(key): return sg.I('', size=(3, 1), key=key, pad=(0, 2))
-
-
-layout = [[sg.T('Your typed chars appear here:'), sg.T('', key='-OUTPUT-')],
- [MyInput(0), sg.T('.'), MyInput(1), sg.T('.'),
- MyInput(2), sg.T('.'), MyInput(3)],
- [sg.B('Ok', key='-OK-', bind_return_key=True), sg.B('Exit')]]
-
-window = sg.Window('Window Title', layout, return_keyboard_events=True)
-
-while True: # Event Loop
- event, values = window.read()
- print(event)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elem = window.find_element_with_focus()
-
- if elem is not None:
- key = elem.Key
- # get value of input field that has focus
- value = values[key]
- if event == '.' and key != '-OK-': # if a ., then advance to next field
- elem.update(value[:-1])
- value = value[:-1]
- next_elem = window[key+1]
- next_elem.set_focus()
-
- elif event not in '0123456789':
- elem.update(value[:-1])
-
- elif len(value) > 2 and key < 3: # if 2 digits typed in, move on to next input
- next_elem = window[key+1]
- next_elem.set_focus()
-
- elif len(value) > 2 and key == 3:
- window['-OK-'].set_focus()
- print('You entered IP Address {}.{}.{}.{}'.format(*values.values()))
-
-window.close()
diff --git a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py
deleted file mode 100644
index 7993d2af0..000000000
--- a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py
+++ /dev/null
@@ -1,107 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIQt as sg
-import os.path
-import PIL.Image
-import io
-import base64
-
-"""
- Demo for displaying any format of image file.
-
- Normally tkinter only wants PNG and GIF files. This program uses PIL to convert files
- such as jpg files into a PNG format so that tkinter can use it.
-
- The key to the program is the function "convert_to_bytes" which takes a filename or a
- bytes object and converts (with optional resize) into a PNG formatted bytes object that
- can then be passed to an Image Element's update method. This function can also optionally
- resize the image.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-def convert_to_bytes(file_or_bytes, resize=None):
- '''
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (Union[str, bytes])
- :param resize: optional new size
- :type resize: (Tuple[int, int] or None)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- '''
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- try:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
- except Exception as e:
- dataBytesIO = io.BytesIO(file_or_bytes)
- img = PIL.Image.open(dataBytesIO)
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height/cur_height, new_width/cur_width)
- img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS)
- with io.BytesIO() as bio:
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-
-
-
-# --------------------------------- Define Layout ---------------------------------
-
-# First the window layout...2 columns
-
-left_col = [[sg.Text('Folder'), sg.In(size=(25,1), enable_events=True ,key='-FOLDER-'), sg.FolderBrowse()],
- [sg.Listbox(values=[], enable_events=True, size=(40,20),key='-FILE LIST-')],
- [sg.Text('Resize to'), sg.In(key='-W-', size=(5,1)), sg.In(key='-H-', size=(5,1))]]
-
-# For now will only show the name of the file that was chosen
-images_col = [[sg.Text('You choose from the list:')],
- [sg.Text(size=(40,1), key='-TOUT-')],
- [sg.Image(key='-IMAGE-')]]
-
-# ----- Full layout -----
-layout = [[sg.Column(left_col, element_justification='c'), sg.VSeperator(),sg.Column(images_col, element_justification='c')]]
-
-# --------------------------------- Create Window ---------------------------------
-window = sg.Window('Multiple Format Image Viewer', layout,resizable=True)
-
-# ----- Run the Event Loop -----
-# --------------------------------- Event Loop ---------------------------------
-while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-FOLDER-': # Folder name was filled in, make a list of files in the folder
- folder = values['-FOLDER-']
- try:
- file_list = os.listdir(folder) # get list of files in folder
- except:
- file_list = []
- fnames = [f for f in file_list if os.path.isfile(
- os.path.join(folder, f)) and f.lower().endswith((".png", ".jpg", "jpeg", ".tiff", ".bmp"))]
- window['-FILE LIST-'].update(fnames)
- elif event == '-FILE LIST-': # A file was chosen from the listbox
- try:
- filename = os.path.join(values['-FOLDER-'], values['-FILE LIST-'][0])
- window['-TOUT-'].update(filename)
- if values['-W-'] and values['-H-']:
- new_size = int(values['-W-']), int(values['-H-'])
- else:
- new_size = None
- window['-IMAGE-'].update(data=convert_to_bytes(filename, resize=new_size))
- except Exception as E:
- print(f'** Error {E} **')
- pass # something weird happened making the full filename
-# --------------------------------- Close & Exit ---------------------------------
-window.close()
diff --git a/DemoPrograms/Demo_Image_Elem_Splash_Screen.py b/DemoPrograms/Demo_Image_Elem_Splash_Screen.py
deleted file mode 100644
index 6cf2c2884..000000000
--- a/DemoPrograms/Demo_Image_Elem_Splash_Screen.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Splash Screen
-
- Displays a PNG image with transparent areas as see-through on the center
- of the screen for a set amount of time.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-image = b'iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAACXBIWXMAABcRAAAXEQHKJvM/AAAgAElEQVR4nOzdd3gUVdsG8Hu2pfdCCJCA0qQIiIj0pqJ0EBRUioq919eGouBnQ8XepQsCoih2SkBa6L0TQgrpvW+Z+f6gZZOd3dnsbtrcP6693peZs+c8s8hy58ycGUGSJBARERGRemjqugAiIiIiql0MgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDIMgEREREQqwwBIREREpDK6ui6AiOjUudzA5KyCdhsPJnUC0PnI2azmJ1Nz/C/slnq2b5YbFRpwMjYy6EC3K6P2XRUTnuSl14l1WbOsirO+sBTGwJjUBKUHIi5sNSJoaDoEfQYMzVOhCzHXaY1EpHqCJEl1XQMRqVBuUZnvr9uO9/5r16lJZzMLBpUbzc0AGJS8tVlYwL6+nWK+v++Wa34NC/Qt8nStDlmKdchbfR0KN05GxZnBEMuiAfgBECq3AlAAXVg6dKGbEHTDXwgeGgdtSCEELb+IiahWMQASUa3KyCv2Wxp3aNrK/448VFJu6uhKX77e+hPj+3Z4a9KgTgujQvzrZkYwa35v5Cx/CZbCW+D8ZTXn4NvlZwT2+w4hY/ZB480vZCKqFQyARFQryipMhs/X7Bq1avPR2aUVprawnh1zhdgiIvC3h0f2eOLma1ufdVOfjplzfHH2uZdQfvIpQPJ1sbdy6MLXIWLqXAQNiYM2kKeIicijGACJyOOOJWc3eWne+o/OpOfdCg9de6zTao7PuKP/baN6tTvgif6tlO4PQdrc71B+cqybezZB33QNQse+hvBJB92XkYmIrDEAEpFHffxL/PB5/+z7HEBMLQyX8+pdA0aN7d1+q8dGKNwYieRX/gCk7h4bAzDDt+sXiLz7Lfh1T/PgOESkUgyAROQROYVlPv/77t+n95xKe1mS4FNb4+p12nMv3N7ntnF9rtri9s4LNzRF6uwVECv6uL1vWwTtGYSMeRVNHlgOja+xVsYk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IAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqAwCIAAAAIDKIAACAAAAqMz/B7LJu0uHjbFxAAAAAElFTkSuQmCC'
-
-
-FILENAME = r'yourfile.png' # if you want to use a file instead of data, then use this in Image Element
-DISPLAY_TIME_MILLISECONDS = 4000
-
-sg.Window('Window Title', [[sg.Image(data=image)]], transparent_color=sg.theme_background_color(), no_titlebar=True, keep_on_top=True).read(timeout=DISPLAY_TIME_MILLISECONDS, close=True)
diff --git a/DemoPrograms/Demo_Image_From_URL.py b/DemoPrograms/Demo_Image_From_URL.py
deleted file mode 100644
index 44c9c68ec..000000000
--- a/DemoPrograms/Demo_Image_From_URL.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import PySimpleGUI as sg
-import urllib.request
-
-"""
- Display an Image Located at a URL
-
- Downloads and displays a PNG (or GIF) image given a URL
-
- NOTE:
- Early versions of tkinter (for example 8.6.6 found in Python 3.6) have trouble with some PNG formats.
- Moving to Python 3.7 fixes this or you can use a tool to re-encode the image (e.g. psgresizer) save it and
- it will then work OK in Python 3.6.
- Example of one of these images - https://www.python.org/static/community_logos/python-logo-master-v3-TM.png
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-image_URL = r'https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png'
-
-layout = [[sg.Image(urllib.request.urlopen(image_URL).read())]]
-
-window = sg.Window('Image From URL', layout)
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
-
-
diff --git a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py b/DemoPrograms/Demo_Image_Viewer_Thumbnails.py
deleted file mode 100644
index de82521ee..000000000
--- a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py
+++ /dev/null
@@ -1,166 +0,0 @@
-import PySimpleGUI as sg
-import PIL
-from PIL import Image
-import io
-import base64
-import os
-
-"""
- Using PIL with PySimpleGUI
-
- This image viewer uses both a thumbnail creation function and an image resizing function that
- you may find handy to include in your code.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-THUMBNAIL_SIZE = (200,200)
-IMAGE_SIZE = (800,800)
-THUMBNAIL_PAD = (1,1)
-ROOT_FOLDER = r'c:\your\images'
-screen_size = sg.Window.get_screen_size()
-thumbs_per_row = int(screen_size[0]/(THUMBNAIL_SIZE[0]+THUMBNAIL_PAD[0])) - 1
-thumbs_rows = int(screen_size[1]/(THUMBNAIL_SIZE[1]+THUMBNAIL_PAD[1])) - 1
-THUMBNAILS_PER_PAGE = (thumbs_per_row, thumbs_rows)
-
-
-def make_square(im, min_size=256, fill_color=(0, 0, 0, 0)):
- x, y = im.size
- size = max(min_size, x, y)
- new_im = Image.new('RGBA', (size, size), fill_color)
- new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
- return new_im
-
-
-def convert_to_bytes(file_or_bytes, resize=None, fill=False):
- '''
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (Union[str, bytes])
- :param resize: optional new size
- :type resize: (Tuple[int, int] or None)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- '''
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- try:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
- except Exception as e:
- dataBytesIO = io.BytesIO(file_or_bytes)
- img = PIL.Image.open(dataBytesIO)
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height / cur_height, new_width / cur_width)
- img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS)
- if fill:
- img = make_square(img, THUMBNAIL_SIZE[0])
- with io.BytesIO() as bio:
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-
-
-
-
-def display_image_window(filename):
- try:
- layout = [[sg.Image(data=convert_to_bytes(filename, IMAGE_SIZE), enable_events=True)]]
- e,v = sg.Window(filename, layout, modal=True, element_padding=(0,0), margins=(0,0)).read(close=True)
- except Exception as e:
- print(f'** Display image error **', e)
- return
-
-
-def make_thumbnails(flist):
- layout = [[]]
- for row in range(THUMBNAILS_PER_PAGE[1]):
- row_layout = []
- for col in range(THUMBNAILS_PER_PAGE[0]):
- try:
- f = flist[row*THUMBNAILS_PER_PAGE[1] + col]
- # row_layout.append(sg.B(image_data=convert_to_bytes(f, THUMBNAIL_SIZE), k=(row,col), pad=THUMBNAIL_PAD))
- row_layout.append(sg.B('',k=(row,col), size=(0,0), pad=THUMBNAIL_PAD,))
- except:
- pass
- layout += [row_layout]
- layout += [[sg.B(sg.SYMBOL_LEFT + ' Prev', size=(10,3), k='-PREV-'), sg.B('Next '+sg.SYMBOL_RIGHT, size=(10,3), k='-NEXT-'), sg.B('Exit', size=(10,3)), sg.Slider((0,100), orientation='h', size=(50,15), enable_events=True, key='-SLIDER-')]]
- return sg.Window('Thumbnails', layout, element_padding=(0, 0), margins=(0, 0), finalize=True, grab_anywhere=False, location=(0,0), return_keyboard_events=True)
-
-EXTS = ('png', 'jpg', 'gif')
-
-
-def display_images(t_win, offset, files):
- currently_displaying = {}
- row = col = 0
- while True:
- if offset + 1 > len(files) or row == THUMBNAILS_PER_PAGE[1]:
- break
- f = files[offset]
- currently_displaying[(row, col)] = f
- try:
- t_win[(row, col)].update(image_data=convert_to_bytes(f, THUMBNAIL_SIZE, True))
- except Exception as e:
- print(f'Error on file: {f}', e)
- col = (col + 1) % THUMBNAILS_PER_PAGE[0]
- if col == 0:
- row += 1
-
- offset += 1
- if not (row == 0 and col == 0):
- while row != THUMBNAILS_PER_PAGE[1]:
- t_win[(row, col)].update(image_data=sg.DEFAULT_BASE64_ICON)
- currently_displaying[(row, col)] = None
- col = (col + 1) % THUMBNAILS_PER_PAGE[0]
- if col == 0:
- row += 1
-
-
- return offset, currently_displaying
-
-
-def main():
- files = [os.path.join(ROOT_FOLDER, f) for f in os.listdir(ROOT_FOLDER) if True in [f.endswith(e) for e in EXTS]]
- files.sort()
- t_win = make_thumbnails(files)
- offset, currently_displaying = display_images(t_win, 0, files)
- # offset = THUMBNAILS_PER_PAGE[0] * THUMBNAILS_PER_PAGE[1]
- # currently_displaying = {}
- while True:
- win, event, values = sg.read_all_windows()
- print(event, values)
- if win == sg.WIN_CLOSED: # if all windows are closed
- break
-
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if isinstance(event, tuple):
- display_image_window(currently_displaying.get(event))
- continue
- elif event == '-SLIDER-':
- offset = int(values['-SLIDER-']*len(files)/100)
- event = '-NEXT-'
- else:
- t_win['-SLIDER-'].update(offset * 100 / len(files))
-
- if event == '-NEXT-' or event.endswith('Down'):
- offset, currently_displaying = display_images(t_win, offset, files)
- elif event == '-PREV-' or event.endswith('Up'):
- offset -= THUMBNAILS_PER_PAGE[0]*THUMBNAILS_PER_PAGE[1]*2
- if offset < 0:
- offset = 0
- offset, currently_displaying = display_images(t_win, offset, files)
-
-
-
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Img_Viewer.py b/DemoPrograms/Demo_Img_Viewer.py
index de6409242..2b97972f2 100644
--- a/DemoPrograms/Demo_Img_Viewer.py
+++ b/DemoPrograms/Demo_Img_Viewer.py
@@ -18,10 +18,6 @@
------------
Python3
PIL
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# Get the folder containin:g the images from the user
@@ -92,7 +88,7 @@ def get_img_data(f, maxsize=(1200, 850), first=False):
event, values = window.read()
print(event, values)
# perform button and keyboard operations
- if event == sg.WIN_CLOSED:
+ if event is None:
break
elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'):
i += 1
diff --git a/DemoPrograms/Demo_Input_Auto_Complete.py b/DemoPrograms/Demo_Input_Auto_Complete.py
index 28d00b43b..9f392e016 100644
--- a/DemoPrograms/Demo_Input_Auto_Complete.py
+++ b/DemoPrograms/Demo_Input_Auto_Complete.py
@@ -1,98 +1,100 @@
import PySimpleGUI as sg
-
-"""
- Autocomplete input
- Thank you to GitHub user bonklers for supplying to basis for this demo!
-
- There are 3 keyboard characters to be aware of:
- * Arrow up - Change selected item in list
- * Arrow down - Change selected item in list
- * Escape - Erase the input and start over
- * Return/Enter - use the current item selected from the list
-
- You can easily remove the ignore case option by searching for the "Irnore Case" Check box key:
- '-IGNORE CASE-'
-
- The variable "choices" holds the list of strings your program will match against.
- Even though the listbox of choices doesn't have a scrollbar visible, the list is longer than shown
- and using your keyboard more of it will br shown as you scroll down with the arrow keys
- The selection wraps around from the end to the start (and vicea versa). You can change this behavior to
- make it stay at the beignning or the end
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- # The list of choices that are going to be searched
- # In this example, the PySimpleGUI Element names are used
- choices = sorted([elem.__name__ for elem in sg.Element.__subclasses__()])
-
- input_width = 20
- num_items_to_show = 4
-
- layout = [
- [sg.CB('Ignore Case', k='-IGNORE CASE-')],
- [sg.Text('Input PySimpleGUI Element Name:')],
- [sg.Input(size=(input_width, 1), enable_events=True, key='-IN-')],
- [sg.pin(sg.Col([[sg.Listbox(values=[], size=(input_width, num_items_to_show), enable_events=True, key='-BOX-',
- select_mode=sg.LISTBOX_SELECT_MODE_SINGLE, no_scrollbar=True)]],
- key='-BOX-CONTAINER-', pad=(0, 0), visible=False))]
- ]
-
- window = sg.Window('AutoComplete', layout, return_keyboard_events=True, finalize=True, font= ('Helvetica', 16))
-
- list_element:sg.Listbox = window.Element('-BOX-') # store listbox element for easier access and to get to docstrings
- prediction_list, input_text, sel_item = [], "", 0
-
- while True: # Event Loop
- event, values = window.read()
- # print(event, values)
- if event == sg.WINDOW_CLOSED:
- break
- # pressing down arrow will trigger event -IN- then aftewards event Down:40
- elif event.startswith('Escape'):
- window['-IN-'].update('')
- window['-BOX-CONTAINER-'].update(visible=False)
- elif event.startswith('Down') and len(prediction_list):
- sel_item = (sel_item + 1) % len(prediction_list)
- list_element.update(set_to_index=sel_item, scroll_to_index=sel_item)
- elif event.startswith('Up') and len(prediction_list):
- sel_item = (sel_item + (len(prediction_list) - 1)) % len(prediction_list)
- list_element.update(set_to_index=sel_item, scroll_to_index=sel_item)
- elif event == '\r':
- if len(values['-BOX-']) > 0:
- window['-IN-'].update(value=values['-BOX-'])
- window['-BOX-CONTAINER-'].update(visible=False)
- elif event == '-IN-':
- text = values['-IN-'] if not values['-IGNORE CASE-'] else values['-IN-'].lower()
- if text == input_text:
- continue
- else:
- input_text = text
- prediction_list = []
- if text:
- if values['-IGNORE CASE-']:
- prediction_list = [item for item in choices if item.lower().startswith(text)]
- else:
- prediction_list = [item for item in choices if item.startswith(text)]
-
- list_element.update(values=prediction_list)
- sel_item = 0
- list_element.update(set_to_index=sel_item)
-
- if len(prediction_list) > 0:
- window['-BOX-CONTAINER-'].update(visible=True)
- else:
- window['-BOX-CONTAINER-'].update(visible=False)
- elif event == '-BOX-':
- window['-IN-'].update(value=values['-BOX-'])
- window['-BOX-CONTAINER-'].update(visible=False)
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
+import re
+
+'''
+ Exampel of Input element features.
+'''
+
+def autocomplete_popup_show(text_list):
+ autocomplete_popup_layout = [
+ [sg.Listbox(values=text_list,
+ size=(15, len(text_list)),
+ change_submits=True, bind_return_key=True,
+ key='-FLOATING-LISTBOX-', enable_events=True)
+ ]
+ ]
+
+ autocomplete_popup = sg.Window("Borderless Window",
+ autocomplete_popup_layout,
+ default_element_size=(12, 1),
+ auto_size_text=False, keep_on_top=True,
+ no_titlebar=True, grab_anywhere=True,
+ return_keyboard_events=True,
+ auto_size_buttons=False,
+ background_color='black',
+ default_button_element_size=(12, 1),
+ location=(1320, 622), finalize=True)
+
+ return window
+
+
+def predict_text(input, lista):
+ pattern = re.compile('.*' + input + '.*')
+ return [w for w in lista if re.match(pattern, w)]
+
+
+choices = ['ABC' + str(i) for i in range(30)] # dummy data
+
+layout = [[sg.Text('Your typed chars appear here:')],
+ [sg.Input(key='-INPUT-', size=(10, 1))],
+ [sg.Button('Show'), sg.Button('Exit')], ]
+
+window = sg.Window('Window Title', layout, return_keyboard_events=True)
+
+sel_item = -1
+skip_event = False
+while True: # Event Loop
+ event, values = window.read(timeout=500)
+
+ if event in (None, 'Exit'):
+ break
+
+ if event != sg.TIMEOUT_KEY:
+ # print(f'event1 {event}')
+ in_val = values['-INPUT-']
+ prediction_list = predict_text(str(in_val), choices)
+ if prediction_list:
+ try:
+ fwindow.close()
+ except:
+ pass
+ fwindow = autocomplete_popup_show(prediction_list)
+ list_elem = fwindow['-FLOATING-LISTBOX-']
+ if event == '_COMBO_':
+ sg.popup('Chose', values['_COMBO_'])
+
+ if event.startswith('Down') or event.startswith('special 16777237'):
+ sel_item = sel_item + (sel_item < len(prediction_list))
+ list_elem.update(set_to_index=sel_item)
+ skip_event = True
+
+ elif event.startswith('Up') or event.startswith('special 16777235'):
+ sel_item = sel_item - (sel_item > 0)
+ list_elem.update(set_to_index=sel_item)
+ skip_event = True
+
+ if event == '\r' or event.startswith('special 16777220'):
+ chosen = values2['-FLOATING-LISTBOX-']
+ window['-INPUT-'].update(values2['-FLOATING-LISTBOX-']
+ [0], select=True)
+ fwindow.close()
+ sel_item = -1
+
+ if event.startswith('Escape') or event.startswith('special 16777216'):
+ window['-INPUT-'].update('')
+
+ try:
+ event2, values2 = fwindow.read(timeout=10)
+ # if event2 == '-FLOATING-LISTBOX-' and skip_event and QT:
+ # skip_event = False
+ if event2 != sg.TIMEOUT_KEY and event2 is not None:
+ # print(f'event2 {event2}')
+ fwindow.close()
+ window['-INPUT-'].update(values2['-FLOATING-LISTBOX-']
+ [0], select=True)
+ sel_item = -1
+ fwindow = None
+ except:
+ pass
+
+window.close()
diff --git a/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py b/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py
deleted file mode 100644
index b3237a030..000000000
--- a/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py
+++ /dev/null
@@ -1,33 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Save previously entered value in Input element by using user_settings calls
-
- Tired of typing in the same value or entering the same filename into an Input element?
- If so, this may be exactly what you need.
-
- It simply saves the last value you entered so that the next time you start your program, that will be the default
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- sg.user_settings_filename(path='.') # The settings file will be in the same folder as this program
-
- layout = [[sg.T('This is your layout')],
- [sg.T('Remembers last value for this:'), sg.In(sg.user_settings_get_entry('-input-', ''), k='-INPUT-')],
- [sg.OK(), sg.Button('Exit')]]
-
- # make a window, read it, and automatically close after 1 event happens (button or X to close window)
- event, values = sg.Window('Save Input Element Last Value', layout).read(close=True)
-
- # only save the value if OK was clicked
- if event == 'OK':
- sg.user_settings_set_entry('-input-', values['-INPUT-'])
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_Input_Validation.py b/DemoPrograms/Demo_Input_Validation.py
index afb74c678..4376ed697 100644
--- a/DemoPrograms/Demo_Input_Validation.py
+++ b/DemoPrograms/Demo_Input_Validation.py
@@ -2,12 +2,8 @@
"""
Simple field validation
- Input field should only accept digits 0-9.
+ Input field should only accept digits.
If non-digit entered, it is deleted from the field
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
layout = [[sg.Text('Enter digits:')],
@@ -18,12 +14,11 @@
while True: # Event Loop
event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
+ if event in (None, 'Exit'):
break
# if last char entered not a digit
- if event == '-INPUT-' and len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'):
+ if len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'):
# delete last char from input
window['-INPUT-'].update(values['-INPUT-'][:-1])
-window.close()
\ No newline at end of file
+window.close()
diff --git a/DemoPrograms/Demo_Invisible_Elements.py b/DemoPrograms/Demo_Invisible_Elements.py
index a803d01a7..4d5c56680 100644
--- a/DemoPrograms/Demo_Invisible_Elements.py
+++ b/DemoPrograms/Demo_Invisible_Elements.py
@@ -6,13 +6,10 @@
were made invisible and then visible, then tkinter puts EACH ELEMENT on a separate row when it is made
visible again. This means a row of 6 elements will become a column of 6 elements if you make each of them
visible one at a time.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+
"""
-layout = [[sg.Col([[sg.Text('My Window')], [sg.Input(key='-IN-'), sg.Button('My button', key='-OUT-')]], key='-COL-'), sg.Canvas(size=(0,0), pad=(0,0))],
+layout = [[sg.Col([[sg.Text('My Window')], [sg.Input(key='-IN-'), sg.Button('My button', key='-OUT-')]], key='-COL-')],
[sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Exit')]]
window = sg.Window('Window Title', layout)
@@ -20,7 +17,7 @@
while True: # Event Loop
event, values = window.read()
print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
if event == 'Invisible':
window['-COL-'].update(visible=False)
diff --git a/DemoPrograms/Demo_Invisible_Elements_Pinning.py b/DemoPrograms/Demo_Invisible_Elements_Pinning.py
deleted file mode 100644
index de360b808..000000000
--- a/DemoPrograms/Demo_Invisible_Elements_Pinning.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - "Pinning" an element into a location in a layout
-
- Requires PySimpleGUI version 4.28.0 and greater
-
- When using the tkinter port of PySimpleGUI, if you make an element invisible and then visible again,
- rather than the element appearing where it was originally located, it will be moved to the bottom
- of whatever it was contained within (a window or a container element (column, frame, tab))
-
- This demo uses a new "pin" function which will place the element inside of a Column element. This will
- reserve a location for the element to be returned.
-
- Additionally, there will be a 1 pixel Canvas element inside the "pin".
- This will cause the area to shrink when the element is made invisible. It's a weird tkinter thing. Not sure
- exactly why it works, but it works.
-
- For other ports of PySimpleGUI such as the Qt port, the position is remembered by Qt and as a
- result this technique using "pin" is not needed.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [[sg.Text('Hide Button or Multiline. Buttons 1 & 2 hide Button 2')],
- [sg.pin(sg.Multiline(size=(60, 10), key='-MLINE-'))],
- [sg.pin(sg.Button('Button1')), sg.pin(sg.Button('Button2'), shrink=False), sg.B('Toggle Multiline')],
- ]
-
-window = sg.Window('Visible / Invisible Element Demo', layout)
-
-toggle = toggle_in = False
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if event in ('Button1', 'Button2'):
- window['Button2'].update(visible=toggle)
- toggle = not toggle
- elif event == 'Toggle Multiline':
- window['-MLINE-'].update(visible=not window['-MLINE-'].visible)
-window.close()
diff --git a/DemoPrograms/Demo_Justification_Columns.py b/DemoPrograms/Demo_Justification_Columns.py
deleted file mode 100644
index 281b1350e..000000000
--- a/DemoPrograms/Demo_Justification_Columns.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import PySimpleGUI as sg
-
-""""
- Demo Justification Columns
-
- Using Column elements to justify one or more elements within a window
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-col1 = [[sg.T('Left side')],[sg.T('Still left')]]
-col2 = [[sg.T('Middle')]]
-col3 = [[sg.T('Right side')]]
-
-layout = [[sg.T('First row of the layout is left justified', font='Any 14')],
- [sg.HorizontalSeparator()],
- [sg.Column(col1, key='c1', element_justification='l', expand_x=True),
- sg.Column(col2, key='c2', element_justification='c', expand_x=True),
- sg.Column(col3, key='c3', element_justification='r', expand_x=True)],
- [sg.HorizontalSeparator()],
- [sg.Text('The remainder of the window is left justified')],
- [sg.Input(key='-IN-')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
-window = sg.Window('Justifying and resizing window contents', layout, finalize=True, resizable=True)
-
-# If using an older version of PySimpleGUI, you can add the expansion using these expand method calls
-# window['c1'].expand(True, False, False)
-# window['c2'].expand(True, False, False)
-# window['c3'].expand(True, False, False)
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-window.close()
diff --git a/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py b/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py
deleted file mode 100644
index 91ac487cb..000000000
--- a/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Element Justification In A Window Using Stretch Elements
-
- How to Justify elements on 1 row to be left, right or left, middle, right
-
- Additionally, locate these buttons at the bottom of the screen
-
-
- To get 2 buttons to be all the way to the left and to the far right, then
- you want to place a Stretch element between them that expands
- If you want a third button that is centered, then add TWO Stretch elements, one
- on each side of the middle one
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-layout = [ [sg.Text('Window with elements on the left and the right')],
- [sg.T('Using a Stretch element that expands enables you to "push" other elements around')],
- [sg.HorizontalSeparator()],
- [sg.VStretch()], # Stretch verticaly
- [sg.Button('Left'), sg.Stretch(), sg.Button('Right')],
- [sg.Stretch(), sg.B('Right')],
- [sg.Button('Left'), sg.Stretch(), sg.B('Middle'), sg.Stretch(), sg.Button('Right')] ]
-
-window = sg.Window('Left and Right Justification', layout, resizable=True)
-
-while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
diff --git a/DemoPrograms/Demo_Keyboard.py b/DemoPrograms/Demo_Keyboard.py
index a6f1983e1..f1acb3be4 100644
--- a/DemoPrograms/Demo_Keyboard.py
+++ b/DemoPrograms/Demo_Keyboard.py
@@ -2,12 +2,6 @@
import sys
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Recipe for getting keys, one at a time as they are released
# If want to use the space bar, then be sure and disable the "default focus"
diff --git a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py
index d584f22e6..afbc91b6b 100644
--- a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py
+++ b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py
@@ -14,9 +14,6 @@
3. Find the Element that currently has focus
4. Click the Button if the Element with focus is a button
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
QT_ENTER_KEY1 = 'special 16777220'
@@ -32,7 +29,7 @@
return_keyboard_events=True)
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event in ('\r', QT_ENTER_KEY1, QT_ENTER_KEY2): # Check for ENTER key
# go find element with Focus
diff --git a/DemoPrograms/Demo_Keyboard_Realtime.py b/DemoPrograms/Demo_Keyboard_Realtime.py
index 34e7ff622..bc362784e 100644
--- a/DemoPrograms/Demo_Keyboard_Realtime.py
+++ b/DemoPrograms/Demo_Keyboard_Realtime.py
@@ -1,12 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
layout = [[sg.Text("Hold down a key")],
[sg.Button("OK")]]
@@ -24,7 +18,7 @@
print('%s - %s' % (event, ord(event)))
else:
print(event)
- elif event == sg.WIN_CLOSED:
+ elif event is None:
break
window.close()
diff --git a/DemoPrograms/Demo_Keypad.py b/DemoPrograms/Demo_Keypad.py
index ab760c64c..a48a78486 100644
--- a/DemoPrograms/Demo_Keypad.py
+++ b/DemoPrograms/Demo_Keypad.py
@@ -1,12 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Demonstrates a number of PySimpleGUI features including:
# Default element size
@@ -35,7 +29,7 @@
keys_entered = ''
while True:
event, values = window.read() # read the form
- if event == sg.WIN_CLOSED: # if the X button clicked, just exit
+ if event is None: # if the X button clicked, just exit
break
if event == 'Clear': # clear keys if clear button
keys_entered = ''
diff --git a/DemoPrograms/Demo_LED_Clock_Weather.py b/DemoPrograms/Demo_LED_Clock_Weather.py
new file mode 100644
index 000000000..9b9ff6988
--- /dev/null
+++ b/DemoPrograms/Demo_LED_Clock_Weather.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+import datetime
+import calendar
+import forecastio
+
+'''
+ Example of a weather App, using:
+ - DARKSKY
+ - google maps coordinates
+'''
+
+
+
+##### CHANGE these settings to match your location... check Google Maps #####
+MY_LOCATION_LAT = 35.0
+MY_LOCATION_LON = -79.0
+
+##### You need a free dark-sky key. You get 1000 calls a month for free #####
+# *** INSERT YOUR DARKSKY KEY HERE **
+DARKSKY_KEY = "INSERT YOUR DARKSKY KEY HERE!"
+
+
+# Changes number of days in forecast
+NUM_COLS = 5
+
+
+class GUI():
+ def __init__(self):
+ self.api_key = DARKSKY_KEY
+ self.lat = MY_LOCATION_LAT
+ self.lng = MY_LOCATION_LON
+ self.blink_count = 0
+
+ sg.set_options(border_width=0, text_color='white',
+ background_color='black', text_element_background_color='black')
+
+ # Create clock layout
+ clock = [
+ [sg.Text('', pad=((120, 0), 0)),
+ sg.Image(data=ledblank[22:], key='-hour1-'),
+ sg.Image(data=ledblank[22:], key='-hour2-'),
+ sg.Image(data=ledblank[22:], key='-colon-'),
+ sg.Image(data=ledblank[22:], key='-min1-'),
+ sg.Image(data=ledblank[22:], key='-min2-')], ]
+
+ # Create the weather columns layout
+ weather_cols = []
+ for i in range(NUM_COLS):
+ weather_cols.append(
+ [[sg.Text('', size=(4, 1), font='Any 20',
+ justification='center', key='-DAY-' + str(i)), ],
+ [sg.Image(data=w1[22:], background_color='black',
+ key='-icon-'+str(i), pad=((4, 0), 3)), ],
+ [sg.Text('--', size=(3, 1), justification='center',
+ font='Any 20', key='-high-' + str(i), pad=((10, 0), 3))],
+ [sg.Text('--', size=(3, 1), justification='center',
+ font='Any 20', key='-low-' + str(i), pad=((10, 0), 3))]])
+
+ # Create the overall layout
+ layout = [[sg.Col(clock, background_color='black')],
+ [sg.Col(weather_cols[x], background_color='black')
+ for x in range(NUM_COLS)],
+
+ [sg.Button('Exit', button_color=('black', 'black'),
+ image_data=orangeround[22:],
+ tooltip='close window', pad=((450, 0), (10, 0)))]]
+
+ # Create the window
+ self.window = sg.Window('My new window', layout, finalize=True,
+ background_color='black', grab_anywhere=True,
+ use_default_focus=False, no_titlebar=True,
+ alpha_channel=.8)
+
+ self.colon_elem = self.window['-colon-']
+ self.hour1 = self.window['-hour1-']
+ self.hour2 = self.window['-hour2-']
+ self.min1 = self.window['-min1-']
+ self.min2 = self.window['-min2-']
+
+ def update_clock(self):
+ # update the clock
+ now = datetime.datetime.now()
+ real_hour = now.hour - 12 if now.hour > 12 else now.hour
+ hour1_digit = led_digits[real_hour // 10]
+ self.hour1.update(data=hour1_digit[22:])
+ self.hour2.update(data=led_digits[real_hour % 10][22:])
+ self.min2.update(data=led_digits[int(now.minute) % 10][22:])
+ self.min1.update(data=led_digits[int(now.minute) // 10][22:])
+ # Blink the :
+ if self.blink_count % 2:
+ self.colon_elem.update(data=ledcolon[22:])
+ else:
+ self.colon_elem.update(data=ledblank[22:])
+ self.blink_count += 1
+
+ def update_weather(self):
+ forecast = forecastio.load_forecast(self.api_key, self.lat, self.lng)
+ daily = forecast.daily()
+ today_weekday = datetime.datetime.today().weekday()
+
+ max_temps = []
+ min_temps = []
+ daily_icons = []
+ for daily_data in daily.data:
+ daily_icons.append(daily_data.d['icon'])
+ max_temps.append(int(daily_data.d['temperatureMax']))
+ min_temps.append(int(daily_data.d['temperatureMin']))
+
+ for i in range(NUM_COLS):
+ day_element = self.window['-DAY-' + str(i)]
+ max_element = self.window['-high-' + str(i)]
+ min_element = self.window['-low-' + str(i)]
+ icon_element = self.window['-icon-' + str(i)]
+ day_element.update(calendar.day_abbr[(today_weekday + i) % 7])
+ max_element.update(max_temps[i])
+ min_element.update(min_temps[i])
+ icon_element.update(data=weather_icon_dict[daily_icons[i]][22:])
+
+
+def led_clock():
+
+ # Get the GUI object that is used to update the window
+ gui = GUI()
+
+ # ---------- EVENT LOOP ----------
+ last_update_time = 0
+ while True:
+ # Wake up once a second to update the clock and weather
+ event, values = gui.window.read(timeout=1000)
+ if event in (None, 'Exit'):
+ break
+ # update clock
+ gui.update_clock()
+ # update weather once ever 6 hours
+ now = datetime.datetime.now()
+ if last_update_time == 0 or (now-last_update_time).seconds >= 60*60*6:
+ print('*** Updating Weather ***')
+ last_update_time = now
+ gui.update_weather()
+
+
+led0 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg=='
+led1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII='
+led2 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII='
+led3 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII='
+led4 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII='
+led5 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC'
+led6 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC'
+led7 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII='
+led8 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII='
+led9 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC'
+ledcolon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII='
+ledblank = 'data:image/png;base64,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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII='
+w1 = 'data:image/png;base64,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'
+w2 = 'data:image/png;base64,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'
+w3 = 'data:image/png;base64,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'
+w4 = 'data:image/png;base64,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'
+w5 = 'data:image/png;base64,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'
+orangeround = 'data:image/png;base64,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'
+weather_icon_dict = {'clear-day': w1, 'clear-night': w1, 'rain': w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'fog': w3,
+ 'cloudy': w4, 'partly-cloudy-day': w5, 'partly-cloudy-night': w5}
+led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9]
+if __name__ == '__main__':
+ led_clock()
diff --git a/DemoPrograms/Demo_LED_Indicators.py b/DemoPrograms/Demo_LED_Indicators.py
index e4ae0bb36..4f44b9073 100644
--- a/DemoPrograms/Demo_LED_Indicators.py
+++ b/DemoPrograms/Demo_LED_Indicators.py
@@ -7,10 +7,6 @@
Demo program showing how to create your own "LED Indicators"
The LEDIndicator function acts like a new Element that is directly placed in a window's layout
After the Window is created, use the SetLED function to access the LED and set the color
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -39,7 +35,7 @@ def SetLED(window, key, color):
i = 0
while True: # Event Loop
event, value = window.read(timeout=400)
- if event == 'Exit' or event == sg.WIN_CLOSED:
+ if event == 'Exit' or event is None:
break
if value is None:
break
diff --git a/DemoPrograms/Demo_LED_Indicators_Text_Based.py b/DemoPrograms/Demo_LED_Indicators_Text_Based.py
deleted file mode 100644
index cd844879f..000000000
--- a/DemoPrograms/Demo_LED_Indicators_Text_Based.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from random import randint as randint
-
-"""
- Demo - LEDS using Text
-
- A simple example of how you can use UNICODE characters as LED indicators in a window
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('Light Brown 4')
-
-CIRCLE = '⚫'
-CIRCLE_OUTLINE = '⚪'
-
-def LED(color, key):
- """
- A "user defined element". In this case our LED is based on a Text element. This gives up 1 location to change how they look, size, etc.
- :param color: (str) The color of the LED
- :param key: (Any) The key used to look up the element
- :return: (sg.Text) Returns a Text element that displays the circle
- """
- return sg.Text(CIRCLE_OUTLINE, text_color=color, key=key)
-
-layout = [ [sg.Text('Status 1 '), LED('Green', '-LED0-') ],
- [sg.Text('Status 2 '), LED('blue', '-LED1-')],
- [sg.Text('Status 3 '), LED('red', '-LED2-')],
- [sg.Button('Exit')]]
-
-window = sg.Window('Window Title', layout, font='Any 16')
-
-while True:
- event, values = window.read(timeout=200)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # Loop through all of the LEDs and update. 25% of the time turn it off.
- for i in range(3):
- window[f'-LED{i}-'].update(CIRCLE if randint(1, 100) < 25 else CIRCLE_OUTLINE)
-
-window.close()
diff --git a/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py b/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py
deleted file mode 100644
index 08366e546..000000000
--- a/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Add and "Delete" Rows from a window
-
- This is cut-down version of the Fed-Ex package tracking demo
-
- The purpose is to show a technique for making windows that grow by clicking an "Add Row" button
- Each row can be individually "deleted".
-
- The reason for using the quotes are "deleted" is that the elements are simply hidden. The effect is the same as deleting them.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def item_row(item_num):
- """
- A "Row" in this case is a Button with an "X", an Input element and a Text element showing the current counter
- :param item_num: The number to use in the tuple for each element
- :type: int
- :return: List
- """
- row = [sg.pin(sg.Col([[sg.B(sg.SYMBOL_X, border_width=0, button_color=(sg.theme_text_color(), sg.theme_background_color()), k=('-DEL-', item_num), tooltip='Delete this item'),
- sg.In(size=(20,1), k=('-DESC-', item_num)),
- sg.T(f'Key number {item_num}', k=('-STATUS-', item_num))]], k=('-ROW-', item_num)))]
- return row
-
-
-def make_window():
-
- layout = [ [sg.Text('Add and "Delete" Rows From a Window', font='_ 15')],
- [sg.Col([item_row(0)], k='-TRACKING SECTION-')],
- [sg.pin(sg.Text(size=(35,1), font='_ 8', k='-REFRESHED-',))],
- [sg.T(sg.SYMBOL_X, enable_events=True, k='Exit', tooltip='Exit Application'), sg.T('↻', enable_events=True, k='Refresh', tooltip='Save Changes & Refresh'), sg.T('+', enable_events=True, k='Add Item', tooltip='Add Another Item')]]
-
- right_click_menu = [[''], ['Add Item', 'Edit Me', 'Version']]
-
- window = sg.Window('Window Title', layout, right_click_menu=right_click_menu, use_default_focus=False, font='_ 15', metadata=0)
-
- return window
-
-
-def main():
-
- window = make_window()
- while True:
- event, values = window.read() # wake every hour
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Add Item':
- window.metadata += 1
- window.extend_layout(window['-TRACKING SECTION-'], [item_row(window.metadata)])
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- elif event[0] == '-DEL-':
- window[('-ROW-', event[1])].update(visible=False)
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Layout_Extend.py b/DemoPrograms/Demo_Layout_Extend.py
deleted file mode 100644
index 346bddb57..000000000
--- a/DemoPrograms/Demo_Layout_Extend.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demonstrates how to use the Window.layout_extend method.
- Layouts can be extended at the Window level or within any container element such as a Column.
- This demo shows how to extend both.
- Note that while you can extend, add to, a layout, you cannot delete items from a layout. Of course you
- can make them invisible after adding them.
-
- When using scrollable Columns be sure and call Column.visibility_changed so that the scrollbars will
- be correctly reposititioned
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [ [sg.Text('My Window')],
- [sg.Text('Click to add a row inside the Frame'), sg.B('+', key='-ADD FRAME-')],
- [sg.Text('Click to add a row inside the Column'), sg.B('+', key='-ADD COL-')],
- [sg.Text('Click to add a row inside the Window'), sg.B('+', key='-ADD WIN-')],
- [sg.Frame('Frame',[[sg.T('Frame')]], key='-FRAME-')],
- [sg.Col([[sg.T('Column')]], scrollable=True, key='-COL-', s=(400,400))],
- [sg.Input(key='-IN-'), sg.Text(size=(12,1), key='-OUT-')],
- [sg.Button('Button'), sg.Button('Exit')] ]
-
-window = sg.Window('Window Title', layout)
-
-i = 0
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == '-ADD FRAME-':
- window.extend_layout(window['-FRAME-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]])
- i += 1
- elif event == '-ADD COL-':
- window.extend_layout(window['-COL-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]])
- window.visibility_changed()
- window['-COL-'].contents_changed()
- i += 1
- elif event == '-ADD WIN-':
- window.extend_layout(window, [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]])
- i += 1
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Layout_Generation.py b/DemoPrograms/Demo_Layout_Generation.py
index 3fac6b50a..7ac1702fa 100644
--- a/DemoPrograms/Demo_Layout_Generation.py
+++ b/DemoPrograms/Demo_Layout_Generation.py
@@ -19,13 +19,8 @@
6 - Questionnaire - Unwinding the comprehensions into 2 for loops instead
7 - Using the * operator to unpack generated items onto a single row
8 - Multiple Choice Test - a practical use showing list comprehension and concatenated layout
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-
"""
Construct #0 - List comprehension to generate a row of Buttons
@@ -302,7 +297,7 @@ def layout8():
while True: # Event Loop
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'SUBMIT'):
+ if event in (None, 'SUBMIT'):
break
sg.popup('The answers submitted were', values)
window.close()
diff --git a/DemoPrograms/Demo_Layout_Reuse_Effect.py b/DemoPrograms/Demo_Layout_Reuse_Effect.py
deleted file mode 100644
index ca4e1f30c..000000000
--- a/DemoPrograms/Demo_Layout_Reuse_Effect.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Layout "Reuse" (but NOT reusing the layout)
- As cautioned in the PySimpleGUI documentation, layouts cannot be "reused".
-
- That said, there is a very simple design pattern that you'll find in many many
- Demo Programs. Any program that is capable of changing the theme uses this
- same kind of pattern.
-
- Goal - write the layout code once and then use it multiple times
- The layout is reused
-
- Solution - create the layout and window in a function and return it
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def make_window():
- """
- Defines the layout and creates the window.
-
- This will allow you to "reuse" the layout.
- Of course, the layout isn't reused, it is creating a new copy of the layout
- every time the function is called.
-
- :return: newly created window
- :rtype: sg.Window
- """
-
- # ------------------- Layout Definition -------------------
- layout = [[sg.Text('This is your layout')],
- [sg.Input(key='-IN-')],
- [sg.Text('You typed:'), sg.Text(size=(20,1), key='-OUT-')],
- [sg.Button('Go'), sg.Button('Dark Gray 13 Theme'), sg.Button('Exit')]]
-
- # ------------------- Window Creation -------------------
- return sg.Window('Window Title', layout)
-
-def main():
- """
- Your main program that contains your event loop
- Rather than creating the layout and Window in this function, you will
- instead call the make_window function to make the layout and Window
- """
-
- window = make_window() # create the window
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Go':
- # change the "output" element to be the value of "input" element
- window['-OUT-'].update(values['-IN-'])
- elif event.startswith('Dark'):
- sg.theme('Dark Gray 13')
- window.close() # close the window
- window = make_window() # make a new window with the "same layout"
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Layout_Vertical.py b/DemoPrograms/Demo_Layout_Vertical.py
deleted file mode 100644
index d0109f37e..000000000
--- a/DemoPrograms/Demo_Layout_Vertical.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo of using the vertical layout parameters and layout helper functions.
- Three methods of vertical alignment are shown:
- 1. Using Column element to align a single element
- 2. Using vtop layout helper function to align a single element
- 3. Using vtop layout helper function to align an entire row
-
- There is also a funciton provided that will convert an entire layout into
- a top aligned layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def top_align_layout(layout):
- """
- Given a layout, return a layout with all rows vertically adjusted to the top
-
- :param layout: List[List[sg.Element]] The layout to justify
- :return: List[List[sg.Element]] The new layout that is all top justified
- """
- new_layout = []
- for row in layout:
- new_layout.append(sg.vtop(row))
- return new_layout
-
-
-def main():
- # -------------------- Example 1 - No alignment --------------------
- layout = [ [sg.T('This layout uses no vertical alignment. The default is "center"')],
- [sg.Text('On row 1'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')],
- [sg.Button('OK')] ]
-
- sg.Window('Example 1', layout).read(close=True)
-
- # -------------------- Example 2 - Top aligned Text element using Column --------------------
- layout = [ [sg.T('This uses a Column Element to align 1 element')],
- [sg.Col([[sg.Text('On row 1')]], vertical_alignment='top', pad=(0,0)), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')],
- [sg.Button('OK')] ]
-
- sg.Window('Example 2', layout).read(close=True)
-
-
- # -------------------- Example 3 - Top aligned Text element using Column --------------------
- layout = [ [sg.T('This layout uses the "vtop" layout helper function on 1 element')],
- [sg.vtop(sg.Text('On row 1')), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')],
- [sg.Button('OK')] ]
-
- sg.Window('Example 3', layout).read(close=True)
-
- # -------------------- Example 4 - Top align an entire row --------------------
- # Note that the vtop function takes a row as input and returns a row. DO NOT place [ ] around vtop
- # because it is a row already.
- layout = [ [sg.T('This layout uses the "vtop" layout helper function on 1 row')],
- sg.vtop([sg.Text('On row 1'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')]),
- [sg.Button('OK')] ]
-
- sg.Window('Example 4', layout).read(close=True)
-
-
- # -------------------- Example 5 - Top align portion of a row --------------------
- # You can combine 2 lists to make a row [a,b] + [c,d] = [a,b,c,d]
- # To combine vtop with a normally specified row, add them vtop(a,b) + [c,d] = [a, b, c, d] (sorta)
- layout = [ [sg.T('This layout uses the "vtop" for first part of row')],
- sg.vtop([sg.Text('On row 1'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')]) + [sg.Text('More elements'), sg.CB('Last')],
- [sg.Button('OK')] ]
-
- sg.Window('Example 5', layout).read(close=True)
-
-
- # -------------------- Example 5B - Top align portion of a row --------------------
- # Same operation as adding the 2 lists, but instead unpacks vtop list directly into a row layout
- try:
- layout = [ [sg.T('This layout uses the "vtop" for first part of row')],
- [*sg.vtop([sg.Text('On row 1'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')]), sg.Text('More elements'), sg.CB('Last')],
- [sg.Button('OK')] ]
-
- sg.Window('Example 5B', layout).read(close=True)
- except:
- print('Your version of Python likely does not support unpacking inside of a list')
-
- # -------------------- Example 6 - Use function to align all rows in layout --------------------
- layout = [ [sg.T('This layout has all rows top aligned using function')],
- [sg.Text('On row 1'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 1')],
- [sg.Text('On row 2'), sg.Listbox(list(range(10)), size=(5,4)), sg.Text('On row 2')],
- [sg.Button('OK')] ]
-
- layout = top_align_layout(layout) # pass in a layout, get a loyout back
-
- sg.Window('Example 6', layout).read(close=True)
-
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered.py b/DemoPrograms/Demo_Layout_Vertical_Centered.py
deleted file mode 100644
index 7de9f3291..000000000
--- a/DemoPrograms/Demo_Layout_Vertical_Centered.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Center a column in a window
-
- Solves a very specific kind of layout.
- If you want to have something centered in a Window, this is a good way to do it
- The "trick" here is:
- * the first row of the layout has a Text element that expands vertically
- * the row with the Column has a text element that expands horizontally
-
- This expanding Text element is what will cause the Column element to be centered
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- column_to_be_centered = [ [sg.Text('My Window')],
- [sg.Input(key='-IN-')],
- [sg.Text(size=(12,1), key='-OUT-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
- layout = [[sg.Text(key='-EXPAND-', font='ANY 1', pad=(0, 0))], # the thing that expands from top
- [sg.Text('', pad=(0,0),key='-EXPAND2-'), # the thing that expands from left
- sg.Column(column_to_be_centered, vertical_alignment='center', justification='center', k='-C-')]]
-
- window = sg.Window('Window Title', layout, resizable=True,finalize=True)
- window['-C-'].expand(True, True, True)
- window['-EXPAND-'].expand(True, True, True)
- window['-EXPAND2-'].expand(True, False, True)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Go':
- window['-OUT-'].update(values['-IN-'])
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py b/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py
deleted file mode 100644
index b2425c88c..000000000
--- a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Sizer Element
-
- Using a Sizer Element to set the size of a window without setting the size on the Window.
-
- If you use the size parameter for a window, you may end up cutting off a portion of your Window
- if the contents of layout are greater in size than the hard coded size you used.
-
- You can use a Sizer element to "pad" a layout into something bigger.
-
- This Element is actually implemented using a Column inside of PySimpleGUI so it's not an
- element in reality, but more along the lines of a User Defined Element
-
- This demo shows how you can make a 500x500 pixel window without hardcoding the size and while
- also centering the contents of your layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# "Centered in a large Window" version
-# A simple layout that you want to "center" in the middle of a 500 x 500 pixel window (not counting titlebar)
-layout = [ [sg.Text('My Window')],
- [sg.In()],
- [sg.In()],
- [sg.Button('Go'), sg.Button('Exit'), sg.Cancel(), sg.Ok()] ]
-
-# If you wanted to center it in a window, just put into a Column element
-# and use the Sizer element to "pad" the layout
-
-# The entire layout is a single row with a sizer that is 500 pixels high.
-# Because elements on a row center themselves vertically, you'll end up with the layout centered vertically
-layout = [[sg.Sizer(0,500), sg.Column([[sg.Sizer(500,0)]] + layout, element_justification='c', pad=(0,0))]]
-
-window = sg.Window('Window Title', layout, margins=(0,0))
-
-window.read(close=True)
-
diff --git a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py b/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py
deleted file mode 100644
index 55a1e5215..000000000
--- a/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- VPush Element
-
- In version 4.49.0 a new VPush Element was added.
- It is not "True Element" but rather a "User Defined Element" because it's a function
- that returns elements versus a class based on the Element class.
- It's not an important detail in the use of it.
-
- Use a VPush to "Push" your elements vertically away from it.
- * If you put one at the top of your layout, then your layout will be "pushed" to the bottom of the window.
- * If you put a VPush at the top and bottom of your layout, then your layout will be centered
-
- This Demo Program shows the "centered" use case.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-layout = [ [sg.VPush()],
- [sg.Text('Resize me to see that I am vertically centered')],
- [sg.In()],
- [sg.In()],
- [sg.Button('Go'), sg.Button('Exit'), sg.Cancel(), sg.Ok()],
- [sg.VPush(), sg.Sizegrip()] ] # toss a Sizegrip onto the bottom corner to make it easier
-
-
-window = sg.Window('Window Title', layout, resizable=True)
-
-window.read(close=True)
-
diff --git a/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py b/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py
deleted file mode 100644
index 21b7323ef..000000000
--- a/DemoPrograms/Demo_Layouts_Using_Walrus_Operator.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import PySimpleGUI as sg
-import random
-
-"""
- Using Python's Walrus Operator in Layouts
-
- Some elements you call many different memeber functions for. Rather than looking up the element by the key and storing
- into a variable, you can use the walrus operator to store the element, right from the layout itself.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [[sg.Text('Using Walrus Operator In Layouts', font='_ 16')],
- [graph_elem := sg.Graph((500, 500), (0, 0), (100, 100), key='-GRAPH-')],
- [sg.Button('Draw'), sg.Button('Exit')]]
-
-window = sg.Window('Walrus Operator In Layouts', layout, auto_save_location=True)
-
-# graph_elem = window['-GRAPH-'] # This is the way elements are normally looked up and stored in a variable
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Draw':
- emoji = random.choice(sg.EMOJI_BASE64_HAPPY_LIST)
- location = random.randint(0, 100), random.randint(0, 100)
- graph_elem.draw_image(data=emoji, location=location)
-
-window.close()
diff --git a/DemoPrograms/Demo_Listbox_Search_Filter.py b/DemoPrograms/Demo_Listbox_Search_Filter.py
index adce582cb..3db24890f 100644
--- a/DemoPrograms/Demo_Listbox_Search_Filter.py
+++ b/DemoPrograms/Demo_Listbox_Search_Filter.py
@@ -1,11 +1,5 @@
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
'Andrea', 'Meredith', 'Deborah', 'Pauline',
'Belinda', 'Wendy']
@@ -19,7 +13,7 @@
# Event Loop
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'): # always check for closed window
+ if event in (None, 'Exit'): # always check for closed window
break
if values['-INPUT-'] != '': # if a keystroke entered in search field
search = values['-INPUT-']
diff --git a/DemoPrograms/Demo_Listbox_Using_Objects.py b/DemoPrograms/Demo_Listbox_Using_Objects.py
deleted file mode 100644
index 63aea7c6e..000000000
--- a/DemoPrograms/Demo_Listbox_Using_Objects.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Listbox Using Objects
-
- Several elements can take not just strings, but objects. The Listsbox is one of them.
- This demo show how you can use objects directly in a Listbox in a way that you can access
- information about each object that is different than what is shown in the Window.
-
- The important part of this design pattern is the use of the __str__ method in your item objects.
- This method is what determines what is shown in the window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-class Item():
- def __init__(self, internal, shown):
- self.internal = internal
- self.shown = shown
-
- def __str__(self):
- return self.shown
-
-# make list of some objects
-my_item_list = [Item(f'Internal {i}', f'shown {i}') for i in range(100)]
-
-layout = [ [sg.Text('Select 1 or more items and click "Go"')],
- [sg.Listbox(my_item_list, key='-LB-', s=(20,20), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED)],
- [sg.Output(s=(40,10))],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-window = sg.Window('Listbox Using Objects', layout)
-
-while True:
- event, values = window.read()
- # print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elif event == 'Go':
- print('You selected:')
- for item in values['-LB-']:
- print(item.internal)
-window.close()
diff --git a/DemoPrograms/Demo_Long_Operations.py b/DemoPrograms/Demo_Long_Operations.py
deleted file mode 100644
index c1759c296..000000000
--- a/DemoPrograms/Demo_Long_Operations.py
+++ /dev/null
@@ -1,161 +0,0 @@
-import time
-import PySimpleGUI as sg
-
-"""
- Demo Long Operations
-
- How to make calls to your functions that take a very long time to complete.
-
- One of the classic GUI problems is when a function takes a long time to complete.
- Normally these functions cause a GUI to appear to the operating system to have
- hung and you'll see a message asking if you want to kill your program.
-
- PySimpleGUI has a Window method - perform_long_operation that can help in these situations
- NOTE - because this method uses threads, it's important you do not make any PySimpleGUI calls
- from your long function. Also, some things simply cannot be safely run as a thread. Just understand
- that this function perform_long_operation utilizes threads.
-
- window.perform_long_operation takes 2 parameters:
- * A lambda expression that represents your function call
- * A key that is returned when you function completes
-
- When you function completes, you will receive an event when calling window.read() that
- matches the key provided.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-'''
-M""MMMMM""M
-M MMMMM M
-M MMMMM M .d8888b. .d8888b. 88d888b.
-M MMMMM M Y8ooooo. 88ooood8 88' `88
-M `MMM' M 88 88. ... 88
-Mb dM `88888P' `88888P' dP
-MMMMMMMMMMM
-
-MM""""""""`M
-MM mmmmmmmM
-M' MMMM dP dP 88d888b. .d8888b.
-MM MMMMMMMM 88 88 88' `88 88' `""
-MM MMMMMMMM 88. .88 88 88 88. ...
-MM MMMMMMMM `88888P' dP dP `88888P'
-MMMMMMMMMMMM
-'''
-
-
-def my_long_func(count, a=1, b=2):
- """
- This is your function that takes a long time
- :param count:
- :param a:
- :param b:
- :return:
- """
- for i in range(count):
- print(i, a, b)
- time.sleep(.5)
- return 'DONE!'
-
-
-'''
- oo
-
-88d8b.d8b. .d8888b. dP 88d888b.
-88'`88'`88 88' `88 88 88' `88
-88 88 88 88. .88 88 88 88
-dP dP dP `88888P8 dP dP dP
-
-
-oo dP oo dP dP dP
- 88 88 88 88
-dP 88d888b. .d888b88 dP 88d888b. .d8888b. .d8888b. d8888P .d8888b. .d8888b. 88 88
-88 88' `88 88' `88 88 88' `88 88ooood8 88' `"" 88 88' `"" 88' `88 88 88
-88 88 88 88. .88 88 88 88. ... 88. ... 88 88. ... 88. .88 88 88
-dP dP dP `88888P8 dP dP `88888P' `88888P' dP `88888P' `88888P8 dP dP
-'''
-
-# This is your new code that uses a thread to perform the long operation
-
-def main():
- layout = [ [sg.Text('Indirect Call Version')],
- [sg.Text('How many times to run the loop?'), sg.Input(s=(4,1), key='-IN-')],
- [sg.Text(s=(30,1), k='-STATUS-')],
- [sg.Button('Go', bind_return_key=True), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elif event == 'Go':
- window['-STATUS-'].update('Calling your function...')
- if values['-IN-'].isnumeric():
-
- # This is where the magic happens. Add your function call as a lambda
- window.perform_long_operation(lambda :
- my_long_func(int(values['-IN-']), a=10),
- '-END KEY-')
- else:
- window['-STATUS-'].update('Try again... how about an int?')
- elif event == '-END KEY-':
- return_value = values[event]
- window['-STATUS-'].update(f'Completed. Returned: {return_value}')
- window.close()
-
-
-'''
- oo
-
-88d8b.d8b. .d8888b. dP 88d888b.
-88'`88'`88 88' `88 88 88' `88
-88 88 88 88. .88 88 88 88
-dP dP dP `88888P8 dP dP dP
-
-
- dP oo dP dP dP
- 88 88 88 88
-.d888b88 dP 88d888b. .d8888b. .d8888b. d8888P .d8888b. .d8888b. 88 88
-88' `88 88 88' `88 88ooood8 88' `"" 88 88' `"" 88' `88 88 88
-88. .88 88 88 88. ... 88. ... 88 88. ... 88. .88 88 88
-`88888P8 dP dP `88888P' `88888P' dP `88888P' `88888P8 dP dP
-'''
-
-# This is your original code... it's all going great.... until the call takes too long
-def old_main():
- layout = [ [sg.Text('Direct Call Version')],
- [sg.Text('How many times to run the loop?'), sg.Input(s=(4,1), key='-IN-')],
- [sg.Text(s=(30,1), k='-STATUS-')],
- [sg.Button('Go', bind_return_key=True), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elif event == 'Go':
- if values['-IN-'].isnumeric():
- window['-STATUS-'].update('Calling your function...')
- window.refresh() # needed to make the message show up immediately20
-
- return_value = my_long_func(int(values['-IN-']), a=10)
-
- window['-STATUS-'].update(f'Completed. Returned: {return_value}')
- else:
- window['-STATUS-'].update('Try again... how about an int?')
-
- window.close()
-
-
-
-
-if __name__ == '__main__':
- # old_main()
- main()
diff --git a/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py b/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py
index e9812863a..1665f3627 100644
--- a/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py
+++ b/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py
@@ -5,10 +5,6 @@
Popup window using the color scheme you chose. It's a simply little program that demonstrates
how snappy a GUI can feel if you enable an element's events rather than waiting on a button click.
In this program, as soon as a listbox entry is clicked, the read returns.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
sg.change_look_and_feel('GreenTan')
diff --git a/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py b/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py
index b0e801e5d..0c5d60fe2 100644
--- a/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py
+++ b/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py
@@ -5,10 +5,6 @@
"""
If you're using the PySimpleGUI color themes, then your code will a line that looks something like this:
sg.change_look_and_feel('Light Green 1') or sg.change_look_and_feel('LightGreen1')
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# Use the built-in Theme Viewer to show all of the themes and their names
diff --git a/DemoPrograms/Demo_MIDI_Player.py b/DemoPrograms/Demo_MIDI_Player.py
index b88fdb4e0..0be9a3480 100644
--- a/DemoPrograms/Demo_MIDI_Player.py
+++ b/DemoPrograms/Demo_MIDI_Player.py
@@ -4,21 +4,12 @@
import mido
import time
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
PLAYER_COMMAND_NONE = 0
PLAYER_COMMAND_EXIT = 1
PLAYER_COMMAND_PAUSE = 2
PLAYER_COMMAND_NEXT = 3
PLAYER_COMMAND_RESTART_SONG = 4
-helv15 = 'Helvetica 15'
-
-
# ---------------------------------------------------------------------- #
# PlayerGUI CLASS #
# ---------------------------------------------------------------------- #
@@ -56,37 +47,45 @@ def PlayerChooseSongGUI(self):
sg.FolderBrowse(size=(10, 1))],
[sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
[sg.Text('Choose MIDI Output Device', size=(22, 1)),
- sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), default_values=(self.PortList[0],), key='device')],
+ sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), key='device')],
[sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
[sg.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=helv15, bind_return_key=True),
sg.Text(' ' * 2, size=(4, 1)),
sg.Cancel(size=(8, 2), font=helv15)]]
- window = sg.Window('MIDI File Player', layout, auto_size_text=False, default_element_size=(30, 1), font=helv)
+ window = sg.Window('MIDI File Player', layout, auto_size_text=False,
+ default_element_size=(30, 1), font=helv)
self.Window = window
return window.read()
def PlayerPlaybackGUIStart(self, NumFiles=1):
# ------- Make a new FlexForm ------- #
+ image_pause = './ButtonGraphics/Pause.png'
+ image_restart = './ButtonGraphics/Restart.png'
+ image_next = './ButtonGraphics/Next.png'
+ image_exit = './ButtonGraphics/Exit.png'
+
self.TextElem = sg.Text('Song loading....',
size=(70, 5 + NumFiles),
font=("Helvetica", 14), auto_size_text=False)
self.SliderElem = sg.Slider(range=(1, 100),
size=(50, 8),
orientation='h', text_color='#f0f0f0')
-
- def pbutton(image_data, key):
- return sg.Button(image_data=image_data, key=key, image_size=(50,50), image_subsample=2, border_width=0, button_color=(sg.theme_background_color(), sg.theme_background_color()))
-
+ css = {
+ 'image_size': (50, 50),
+ 'image_subsample': 2,
+ 'border_width': 0,
+ 'button_color': sg.TRANSPARENT_BUTTON
+ }
layout = [
[sg.Text('MIDI File Player', size=(30, 1), font=("Helvetica", 25))],
[self.TextElem],
[self.SliderElem],
- [pbutton(image_pause,'PAUSE'), sg.Text(' '),
- pbutton(image_next, 'NEXT'), sg.Text(' '),
- pbutton(image_restart, key='Restart Song'), sg.Text(' '),
- pbutton(image_exit, 'EXIT')]
+ [sg.Button('', image_filename=image_pause, **css, key='PAUSE'), sg.Text(' '),
+ sg.Button('', image_filename=image_next, **css, key='NEXT'), sg.Text(' '),
+ sg.Button('', image_filename=image_restart, **css, key='Restart Song'), sg.Text(' '),
+ sg.Button('', image_filename=image_exit, **css, key='EXIT')]
]
window = sg.Window('MIDI File Player', layout, default_element_size=(
@@ -105,7 +104,7 @@ def PlayerPlaybackGUIUpdate(self, DisplayString):
return PLAYER_COMMAND_EXIT
self.TextElem.update(DisplayString)
event, (values) = window.read(timeout=0)
- if event == sg.WIN_CLOSED:
+ if event is None:
return PLAYER_COMMAND_EXIT
if event == 'PAUSE':
return PLAYER_COMMAND_PAUSE
@@ -246,17 +245,5 @@ def GetCurrentTime():
# ---------------------------------------------------------------------- #
# LAUNCH POINT -- program starts and ends here #
# ---------------------------------------------------------------------- #
-
-image_exit = b'iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAACXBIWXMAAAsSAAALEgHS3X78AAAfmUlEQVR4nNV9WXAcx5nmV9U3uhvoxtk4iJskCEgUBEpBWo6lbFkULVGW7ZBNWxEjR+zE2i8zs/Y87JNnw54IR8w+ODzSzsixG3ZYsji2GAiSpnYFyitSNgWZMikRpACCAEg0AII4Gld34+qr+qh9ILKcnZ1ZVQ2SkvxHZFR1dVVl5v/lf+SfR0n4DFN9fb1LluW6pqam2urq6nav19uxe/fuXQBqAHip5Nl6ZBPABpUWb9y4cXNjY2NsaWkpOD09HcrlcvNzc3OJT6M+Zkj6tAtASJIk2Gw2e1tbW6Crq+tgfX39E1VVVQdkWa4FUApAJveqqmr6nRTlAKzncrnQ8vLyxbm5uT9cv369f2JiYiGdTitm33m/6VMHpLKy0tLe3v5gZ2fn0ba2tiMAugBYgELGb5dpDDD07yyA6xMTE30jIyO9wWDw2srKSnZbmdwj+lQAsVqtUnt7e11nZ+dXu7q6XnQ4HHsBlAD5TDdzrkc0ECbO46lUauj69evHRkZG3gwGg/OZTOYTF5tPHJA9e/bsfPzxx/+uvr7+OwD8AJ/ZZo8iIow2e2TOo3Nzc6+/9957r4yOjo4XX8vt0ycCiNVqldvb2/ccPHjwH+vr678hSVIZwGcySexv9hr9HEs0s9lz0TX2ua33r83NzZ3o7+//12AwOJrJZHL3ki/cst/vDNrb231PPvnkj2tra/8WdzwiIXNVVUUulysAgndNBIoIAEmSIMuy7jX6OfpdADZCodCvzp079+NgMLh6P/l13wApLy+3Hzx48OhDDz30E0mSmgA+ADTTSdL7zQOloFIcphPGk3PRb5EUbZV5enBw8J/6+/t7I5GIcj/4ds8BkSQJLS0trUePHn3Z4XA8DcBiBgSSstks95wFxwwgPKbLsgyLxcI9NwMOgGwqlXq7t7f3+1NTU5P32l2+p4DIsiw/++yzz3d3d/87gGogXyp4rT+bzeomco8sy3A6nXC5XCgrK4PL5YLNZoPdbofNZgMApNNpKIqCdDqNRCKBtbU1JBIJJJNJ5HI5jfkWi0U38aQIyJcWAEsff/zx37/11lsnc7ncPbMt9wyQyspKz9e+9rUf1dXV/YOqqg6RbWBByGQy3KMkSSgrK0NdXR0aGhpQXl4Op9MJp9NZoPdZovNMJpNIJpOIRCKYnZ3F/Pw81tbWoKoqLBYLrFYr90iDo2NrUvPz8/92+vTpf15ZWdm8F3y8J4D09PQ0HDly5DiAz7N2ggBBt/ZMJsNNABAIBLBz5040NTXB6/VyVQk5AoWdPl7erNrb2NjA9PQ0xsfHsbCwAACwWq3cREsVL++t8wt9fX3fvnLlyuzd8vKuAXnkkUe6Dh069IbFYnmQ5wnREkEzP51Oa0e3243Ozk60t7fD7/fntVKefqfBAfLcVK5E8uwUKU80GkUwGMTIyAhisRhsNhusVqt2pIGhJYZN2Wz22tmzZ1+4fPny9U8NkIcffnjf008//TsAO3gMIVLBAkH0vNfrRXd3N3bv3o2SkpICdUFUCM0UnlvKdixFDYK1SzQw8XgcN27cwMcff4yNjY08+0SXgXYEWKMPYObtt9/++tWrVwe2y9NtA7Jv375Dhw4d+g9ZlqtFTCD2IJ1Oa0lRFDidTjz66KPo6OiAy+XKY7jVaoXdbteYoaeeWNIDhpYWuoGw0ptIJDA2NoaPPvoIyWRSKwdJtJ3hSUsul1s6e/bs3wwMDJzdDl8t23mou7t731NPPXWSBwZbQUVRkEqlkEqloCgKdu3ahcOHD6O5uRkul0tjvtPphMfjgcfj0TwokcoiksIaXdbGiOwPTw2RZLPZUF1djba2NiQSCSwuLmrqj9cAOIFLd0tLy+FYLPbHhYWFULG8LVpCenp6up566qm3AexgDSgNBi0RiqLA4/HgySefxI4dO7TWZrVa4XA44HK54HA4uAZTL/bEkpGEiPpAdJlp1ZpOpzEzM4Nz585hc3MzT3JJ+VnbQpVx5p133nn6ypUrRdmUoiSku7u74dChQ7+TJGknr3KseiKS0dzcjGeeeQaBQAAOhwN2ux0OhwNerxcejwd2u13XcBu1fL379Tp77H2sJyXLMrxeL1pbW7G6uoqVlZUCqRA1EEmSylpaWv5TLBb7vwsLC+v3HJCKigrP0aNHT0uS9IgRGIqiaJ2xAwcO4Itf/CI8Ho8GhsfjQVlZGZxOp6EnpdeLNgse735ebIvtuZNrdrsd7e3tkGUZs7OzmotuApSa9vb2/WNjY72JRMJUqMUUILIsy9/85jd/4na7v832uomaosFIpVIAgCeffBJ79+6Fw+GAw+GA0+lEaWkp3G635rHohTB4DDUKCvJaPs9NFV0XvUeSJNTU1KCsrAyTk5NCUOjjFq8a6+vr7deuXXtXNRFnMQREkiQcPnz4G21tbf9DVVWrERjJZBJWqxXPPPMMdu3apYFRUlICn8+n9bRFIBi1eBE4POnhgaXHeB6wspwfNikvL0dVVRUmJyehKIqunSNHj8ezz+PxjE1MTIzcNSBNTU2tTzzxxCkAZXpqitgLq9WK5557Ds3NzRoYXq8XpaWleVJhFgwek/VatxnpMkp0Y+Q9W1ZWhtraWoyPj0NRFC4IDFlramoen52dPbW2thbdNiA+n8/+rW9961WLxfIwrapoX55WU6qq4siRI2hubs4z3KWlpaZ63iIwRMAUo26KSTQg5EgkhZDH40FFRQVu3Lihxd5Ez27xzr1z5862GzdunEwmk8Jxe11AvvCFL7wQCAT+GwBZFAohYORyORw+fDhPTXm9Xni93gIg9ELeIkDMgkETq054z9L3sb/Z/9g8SktLUVZWhmAwiFwux80jj9kWS5vD4RgPBoNDRQPS3NzsO3jwYK8kSX4RGERVKYqCxx57DA899FCBmirGizJSOwJ1wAWBp3p4auVu7gUAn88HSZJw69atgvKyz0iSJFdVVe0LhUKvra6uJk0DYrVa5WeeeeZf3G73YV4vnFZTqVQKra2t+NKXviQEg2ayWf0vqhTLNEmScOXKFYRCIdTV1Zlu/SJJofNgr4lACQQCWFpawsrKipn3+ioqKlwjIyPv5HK5Aq+LC0hLS0tnT0/PKwAcvF4tDYjX68Wzzz6r9TOINyVyY3k6vlgg6PPbt2+jr68Pk5OTaGhogN/vFzKfZbQZaRBJpfQX2wBVVREIBBAMBpFIJArqRD8DAG63u2txcfHNaDS6bAqQL3/5y//i8XgO8OJUxG4oioJMJoOvfOUrqK2t1foZ5eXled6UHvN54s0DQsTAtbU19Pb2YnNzE5lMBlNTU+jo6IDT6dS1FWxeAPKMNi9vHiA0KFarFeXl5bh+/Tq30TF5O8rKyhzDw8P/xxCQtra2nQ8//PBLqqo6AXDjPUQ69uzZg0cffVTrgdP9DCNboJd4ILCUSqVw+vRpLC4uakxJJpNYXFzEnj17YLVahYDyABFJihki+Xs8HqyurmJxcVHXgVBVFW63u21lZeVkNBqNCAGxWCzSoUOH/rvH43mc1+egAXE4HHj22Wfh9Xpht9vzPCojMFgVxWOCHlNUVcW7776L0dHRgoBiNBpFIpHArl27dNWN6ChqAPQ1XoebdJYrKysxMjKCdDrNrSf1PmdZWVludHT0/9HvywOkubm5vqen538DcPGMOVFViqLg4MGDaG1t1VQVGekz28vmMYRmiohUVcWVK1fwpz/9KW+wiT7Oz8/D5XKhoaFBFxRR/mYAYK8RXpEIcDAYFPKBkNvt3r24uPgfq6urG+RaXm+nvb39qwD8NBjssGc6nUZpaSm6urq0ELTH44HNZhMabSPjyjJDj2ZmZnD27FmkUqm8yDI9JJxMJtHX14epqSnD94lUFk+ieX0pdlTTZrOhq6sLpaWlSKfTeaOU7LwyAP4tnmukAeL3+y2tra0v6o2Hk0rv27dPG+kjnpUR8/VAMQtGJBLBqVOnEI/H88Ys2PNMJoONjQ0cO3YMKysr2wZFL4LAJhoUl8uFffv25fGMBobmcWtr64t+v1/TVBogO3bseNBms+3VG8DJZDLweDzo6urSMvd4PHlj3Ub9jO2CkclkcPr0aaysrBQwn5UU8t/i4iJef/11pNPpuwJFJCnshDtaWrq6uuDxePKGitkJf6qqwmaz7d2xY8eDeYBIkoSWlpajAEr01FUmk8HevXu1CQl2u12TjmK9p2LAyOVyOHPmDILBoC4IvDQ6Oorjx48jmzVe9sEDBYAwkqAnJSUlJdi7d2+BdHDUVklLS8tRkp8MAFar1d7Q0HBEJB0EDADo6OjQDJfb7TalotjKFgMGAHz00Uf48MMPC4ZZRcOubDp//jzee+89U3nxHAw96WclhpaUjo4OAOCCQgPT0NBwxGq12jVAGhoaAqqqdtE38eZT1dfXo7y8HBaLBTabDS6Xy1AtmXEj9ejWrVt46623kEqluHO6RLaENfLHjh3D2NiYaVBEwOhFo1lQysvLUV9fXzDDheWzqqpdDQ0NAQ2Q1tbWg6CWkYlUVmdnpyYdTqcTVqtVV0JY5psFgVAkEkFvby+SyWTBLEceACJbkk6nEY/H8fOf/xyLi4um8zdyTHhSw0pJZ2enkcoCAMsWBncAqaysfEI004+8bMvOaJnxwhOilsWrqBEpioITJ05geXk5b96vWVB4kjM3N4dXXnkFySQ30KpbRj3byDP2JLW0tECSJK7KonleWVn5BADIVVVVLp/PdwDgSwcBxe/3o6ysLM//1quMGRsiomw2qxlx3qTsYmwIe//Q0BBee+0100beSEr07IrFYkFZWRn8fr/QfhAp8fl8B6qqqlyyLMt1AGpZMFg70tjYmNcK4vG41tK2y3gRDQwM4NKlSwVTQGlQRNIhsjN0+v3vf4+zZ4ufWCjSBkYS09jYWGA/OKDUyrJcJ9fU1NQCKNWbSJbL5dDc3FzQSSK6mbQ2ESjFgDM5OYm+vj5kMhnuvNxiVRYLCgkB/fKXv8Tg4GBRQIhAMQKkubmZq6oYQEprampqZZ/P166qqszeQIMiyzIqKyu5YxcAtMnT9CSy7diOtbU1nDp1SpvTJVrYIwKFBYeWKlbKYrEYXn75ZSwvFwxJGJbZDDg0rwjvRGBsJdnn87XLLperw0g6XC4XXC6X7qifqqp56zyKpVQqhZMnTyISiXBtGDuBmwbGyG6wM9/Ju0KhEH76058iHo8XVVaz3hdJhH9GUuJyuTrkxsbGXSQjNpRNGON2u3W9KrYViSYni0hVVZw7dw7T09MFDUPP8zNjL+j7ed7N8PAwXn31VeRy5lal6bn2ouR0OuF2u/NA4PG8sbFxl6yqag2PCXSih2T1CsJjtBm6evUqBgYGuHkXAwodyGOliwWCnBOP7p133jEEQqSO9Vx+4m35fD5h3ahUI2Nr7TjLSDp5PB5TkqEHjsh+TE9P449//KOw1eiVjR3nNxE34uajqipeffVVDA3xZ+eI6mPEAzp5PB6eIWfJK6uq6hUYGToiaegxbcfNDYfDOH78OGKxGABzErVdd5rYORHFYjG89NJLpsL1ZstE88xms+nyeCt5reBICJDfEh0OR0EG5CiSCCOKx+N4+eWXMTg4CFVVtSXPdrtdC8mIGMjrgAHQ7AApD2+YmLyXli7yrlAohJ/97Gf44Q9/CLfbXVR9eH0T+uhwOIykAwC8VlVVPYD+dhd2u72owpmh48ePY2RkBJJ0J6ywtraGcDisqR2eP0+uEUaqqqoBQt5D1BUA7R6aAfR7eesXh4eH8Zvf/Abf+9737ml97XY7l7fkfIs8eVMzzOrxuyHiUb377rtCN5G2CWzIhHZ9WTsB/IXh7BArPXjEG8ugy3Lu3Dk0Njbi8OHD21aRRjygz+k8rAA2Vc5Cf5rIDO97QePj4zhx4gQAcFs/YSKrX+nYGS0pNCA8gOnIq2i3Bjapqore3l40NzdrYxp3SywPeRIiSdKmrKrqBn0Tj8gCHPYFJnRiHi0vL+NXv/oVFEXRHQ7lDYnSkwjIkSxdphO9YpZO7EJPI3BSqRR+8YtfGPbkWQbzeETzkPccdb4hA9gwMp5kqQH7AtGLeZRMJvHrX/8akUhE2DJFe4+wgNBgsOc0MLx15qItNHgARaNRvPbaa4bheiOeqKqKVCql6wBt3bthJRKi19pjsZjQVWNfyruezWZx6tQp3Lx5EwCEqolXOVYFkdga27Fi7yfPSJKUZ09YoHlg0Ofj4+M4deoUjh49Cln+y6wpMzygE3HtRfdueX8bVgDaEJrIbYtGowVDj2YKRlzM/v5+vP/++3lMIzaB9yydN2EqASKXu7Orj2DkreA5nlrkgcKTHALA+++/j0AggMcff5zbaHjlIL+JRxiNRoXdBooWrTMzMzcbGhp0JWRzcxPJZBIlJSWGksK2dkmS0NzcjB/84Ad5mfPsEE9aDNxE7m82hCFiAi/qwLumqqq2BZTI+RHVQ1VVJJNJbG4WbhbEvmN2dvamNZFIFIz80x0rWZYRi8UQj8fh8/mMQsh5GZH3NDc3b7sD+VkgMw2FTXT8LB6PaxvbEKnj8SKRSIzJq6urQVVV80KdNDOBOzZgZWVFN3RsZAtE1z7rpFcPPR7QvFpZWckbMuZFIVRVza2urgbl5eXlEIB11jCSI5GSyclJw3i+GdXz10hmJEIERi6Xw+TkZF5/C+BO5l5fXl4Oyblcbl5V1RD1h/YAnW7dumVmGFLXvvy1k1GDEwFC1h/yYn/UO0K5XG5eDofDidXV1Yu8AtDuYzgcxurqqjC0TQpiptB/LWSmsYn4QLyr1dVVhMNh7lgSTaurqxfD4XDCCgCRSOQPPp/vP9M3sP5/Op1GMBhERUWFcI4R6R/wEtsqJEnCxMQERkZGCipXjI1iAdaLSLOJdo3Jterqauzfv5+n402rKHrImExlIjE0ESiRSOQPwJ1YFqanp/tbWlqyqqrmTbZiQRkeHkZPTw/sdruWId250wOFNmSkQMPDwzhx4kRB0JBNopE/nsSJApaiziHbB+nu7sb+/fvzQNADhC0LXe50Oo3h4WHuxBAaaADZ6enpfg2QhTs7QV6XJGkvYR6vUrdv30YkEoHT6eRKCem4kWfJOSslpJJra2vagk3exARehFc0IshrQCKms+d0isfjBUDzAOANCbPSEYlEcPv2bWFUmWqc17cwuANINptVQqFQXyAQ2MsWhq4kQby6ujovYzryykoIDQqrVmKxmOFsdtF/bBgegDDczsazyG+eaqRnzRRjL1gwMpkMhoeHNXUlMuZbAtGXzWYVDRBVVTE7O9sbCAS+D6CEMJC8hG5pAwMD2L9/P2w2GzKZjHadLhjdCkihAeSFS4A7IWleqJ2nguhBJd4scvZePeng7TZKEi3RhFhpZG0GSXTjicViGBgYKHg3x+2Nz87O9pL8tAGqUCh0TVGUIZvNdkAkIRaLBevr6xgaGsJjjz2GTCajMYgeyeOJJW1j6N8lJSWm1BNPVRGgWdvEG18ximORczKyR96rBwQ7u4Wux9DQENbX17Xd8ngSIkkSFEUZCoVC18h1DZD19fXszMzMsdbW1gM0EGzFZFnGBx98gO7ublit1gIpoW0HbUtoIgWsr69HT0+PbqsTqQtW7Nn4Fa/8rE1k6yVJEhoaGvLAYMtiRjri8Tg++OCDgnEeXj9kZmbm2Pr6utaNzxvCnZmZebO1tfUn2PrQCishJINIJILBwUEcOHAgT+zJvTwpoSWFMPL555/Py4Nl7CdBrBdFn+upKHY2JW3nBgcHEYlEtI09ddzd6MzMzJv0hbxl0QsLC/PhcPh1UiheCIWI+Pnz5xGJRExNUONVzMilvN+k178RlVWkquiJepFIBOfPn8/b25cNmZC8wuHw6wsLC/N0uSxsIZPJ5ERjY+N3ADhZ148ucCKRQCKRwO7duwvUAa81iFo+Tzrut7SwKo9nM/Q6e/Q1srMFOZ45cwa3b9/OGzoWxLHWLl++/N21tbUwXbb8bdIAzM3NjYfD4RPsdZ4Hc/XqVW3vQVZSeD15Izuhl+4FCEbJbHlpA07qrSgKJicncfXq1TwnQtQzD4fDJ+bm5gq+b8VdBpVKpSaamppeBOAQtVJSgVu3bqGjo0PTl0DhBDVCIj+cVY8smb3Glk90jdfp0+vw8aIHmUxGa4ipVArhcBhvvPEGUqlUwUbLHAnZGBgY+C8bGxvmtmeKx+Phurq6apfLpXlc9JGu2ObmJqLRKLq6urhxIh6ZUUV695hVZSwoPCD0AGFdbjYsQu/9curUKczMzOTtEU87O/TAVDQa/V9DQ0O/UTmthguIqqpqPB6/2NTU9IIkST4jxiwsLMBqtWqbvdAAmm3JIrV0N3ZEJCV6YPCMN08ySEqlUujv78fFixe1GS/st0eYjvL0hx9++O319XXu51+FKzc3NzeTHo9nxefzfVVV1Txbw3MVp6amUFFRgaqqqgJAttuieVQsQHpSYbbjx9oMGpChoSGcOXNGiyLw1BRV5uytW7f+69jY2Iei8uruSrq2tjbW0tLSY7FYdvGYQTM+m81ibGwMdXV18Pv93Pt4TOIxUM+oF2PgWe/JqOOpB0Y2m789laIouHHjBnp7e6GqqiYZZNyclg7Cg3Q6febixYs/UhRle9vEKoqSjUQil5qbm1+QJClvOjjPCGcyGdy8eRONjY0oLS0Fe7/IqOtdo//jual6HhNrE8x6VqJ+Bg3G1NQUjh8/jnQ6nTchj+0kU/Veev/9978RjUZ11zsY7mwdi8WiJSUl036//zkAViOVoSgKRkZGUFNTA5/vL+aH9qR4TDZitBEAZu2CGXeW189gJeP48eNIJpO6n66gGm1qcnLyuzdv3rxgxG9Tm/EvLCyM1dXVlbpcrse2MiAZcc8VRcH169dRXl6OioqKAoazJGr9LAjFgKIXIRCpJVHvm4CSSqUwNDSE3t5epNNps2AgGo2+dOHChf/J86q2BYiqqury8vKfd+7c+bgkSY1GoBCbMjo6ClmWQSbi8UARSYIe843uMSMdei4tq6LIZtH9/f04c+aMZjPMgAHgwvnz57+bTCb5s623AwgApFIpJZlMvhMIBA5JklRDgyICKJfLYXx8HKFQCA0NDdrsPzaWpcd8s1JgxmsyAoTtedOdvpMnT+LSpUuQZZkrGby+l6qq1wYGBr6+sLBgep1cUV/YiUaj64qi9NfW1n4FW19L4BHr7i4tLWFsbAw1NTXwer1cJhYLDE8FFZPYaC271p1Ix8TEBH77299iZmYmb/Y9Pb4ikIyZq1evfn1iYmKiGB4X/VGwSCSynEgk+mtra79GPC+eymJTPB7HlStXEI1GUVNToy2CZFt0sR6UGU9J9D/PThAVtbKygr6+Ppw5cyYvHGJGTamqujQwMPDcxMSEub077gYQAIhGoyFFUQYDgcBhESjknI4EA8D8/DyGhoZgtVq1bcH1GGcESLFSIdr9gYCxubmJy5cv48SJE7h9+3bBIiEjyVBVdenq1at/MzEx8aft8Pau4tutra37Hnnkkd+B+WIbT4fTepocy8vL8fnPfx4PPfSQ9hkko5VNrDoUdTpF5WDLQ8oSi8UwODiICxcuIBKJCJcnGJRj5vLly1+fnJz85D8sSai9vb2ru7v7DVmWH2Q9ID03kx7QKi0txaOPPooHHngAFRUVecE5PUD0ItF6gNABwnA4jOHhYXz00UdYX18vmLnCG4ZlZ7BvSfm1jz/++IVgMPjpfXqVUFtbW8O+ffu0jxMTMmIK21JlWUZTUxP27t2LnTt3wufzcQERTVomeZKjSLWtrq5ifHwcQ0NDmJ6eRi6X466iMpJOKv8LAwMD356YmPj0P05MqLS01LN///4f+f3+f1BV1UGu63lILDD0dYvFgoqKCrS0tKCtrQ1VVVUoKSmBy+UqmFLDEsknm80ikUggHo9jeXkZExMTmJqaQjgc1hoAb2ajnkQyYKSi0ei/Xbp06Z/X19c/O5/vJiTLstzT0/N8S0vLvwOoNupn8Aw4b6oPAcjj8cDtdqOiogJut1v7gAzZaYJ8YCaVSiEWiyEcDmNzcxOxWCwPACJlBAD6t0kgAGBpamrq769cufLZ/MA9TTU1Na2f+9znXrbZbE8DsNxN71rUAWQ7lnmVErjevLF/9sgDgTlm0+n023/+85+/v7i4OHmveXff5tx4PB77nj17jjY1Nf1EkqQmlnk8xhq5ufS97FGrEIeJLCA8oNh7WXW45dJOT09P/9Po6Gjv5ubmvdtNgc7nfryUpkAg4HvggQd+7Pf7/xaAlwcMOepJEO8e9h1GoRw9CRA5CVu/N6LR6K+Gh4d/vLCwsHq3PNGjT2RWmsVikWtqavbs2bPnH/1+/zckSSoIu/DsDX1dDwiWRMCwR9599G9VVdei0eiJ0dHRf11cXBzNZrP3zFaI6JOdJgigrq5uZ2dn59/5/f7vYGuGJI+xPMbrgUiToJXrAsBci0aj0ddHRkZemZ+fL5iqcz/pEwcEAGRZlgKBQF19ff1X6+vrX7RarXsBlLD3iRhu9B+wrVkr8UwmMzQ3N3dsbm7uzYWFhfkc57N295s+FUBo8nq9lpqamgfr6uqOVldXHwHQBSrGZsT4YokBIwvg+tLSUt/8/Hzv4uLitY2NDeMtr+8jfeqAEJIkCRaLxV5dXR2or68/6Pf7n/B6vQckSaoFUArOLMsiKYc7y79DGxsbF6PR6B/m5ub6l5aWFrLZrHKvgd8ufWYA4ZHf73dJklRXWVlZ6/V6251OZ0dtbe0uADW4szUhSZ6tRzYBbFBpMRQK3Uwmk2MbGxvBlZWVkKqq89FolDsn6rNA/x+NrQ1/eZYZxgAAAABJRU5ErkJggg=='
-
-
-image_next = b'iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAB8WSURBVHhezZ17sJZVvccfN8ZFASER2GyQ5KLizgtC4x3MQjPUtJS0qaYxm2aOnVNNnZrKM+lMTae/Ujs459SMWmraTsyOIaOmJ0jykopIXFS2RggbNijiVm6Fnt9n8X5ff/vHet797s3e4HfmO2s961nPb631/T3r8lze5z2oeA+jqalpUENDw5jx48c3jhw5ctKQIUOOPeaYY462XaOMQxwHG8Gbxg7Hjc8///wLHR0dq9rb21evWbOm7e23316/bt267bbvPYn3jEMOOuig4n3ve1//iRMnjm5ubp5hzjjniCOOONUc0mi7hxobUkbDO++8U4nVBjYd3ja+YQ5p27Rp0+PmlEeWL1++qLW1dcM//vGPXfXa7GsccIeMGDGi36RJk44/7rjj5pgzZltSs7Ef+6JIPRUtOMZv7zYuN6fMX7FiRcvq1auXbd68mbQDhgPikIMPPvggc8IYc8InrDd8bsCAASdY8iHs86LXE68F74g64tt27tz5nPWa28w5vzPnrP/nP//ZszNgH7DfHTJlypTJM2fOvNqGpM/b5nDScmLXG5ZBQtcbAhffYkPaLxcuXDh35cqVL1bS9gverU0fwnpEg/WIKTNmzPi6OeJSa/hhpOdEFuN2TFM8By92jJeladuHZn+rOebuRYsW/cR6zErrMcxDfYo9JfchzBHDPvrRj17b2Nh4pW2yIioVF9qkW43XSoM6zsOLGmkLhJpp/jjFK+hoa2u7+Q9/+MO15pjXK2l9gj5zyPvf//7+1iPmnHjiiT+who0nLQrpiehirW1/DMxBooqILuEVL9v29LaAlbdm6dKl11iPaXnttdd2pcReRq87hMofddRRE+bMmXODTdbnW1I/CeeFhF50cffu3dm4qONkIweJmBMd9uvXLxv3lA1Rdg27bfJf0NLS8tWXX375pbI69BS96hBrSMMFF1zwqZNOOum/bHMkaV44L6iI6LWoPIg0cODAYtCgQcVhhx2WQrtuKfr3759CYNcTxa5du1K4ffv2YuvWrSncsWNHsiPxCWuRPCJOIATeOYb2Z5999iu///3v55ntXptbes0hdj0x+OKL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'
-
-image_pause = b'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'
-
-image_restart = b'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'
-
-
-
if __name__ == '__main__':
main()
diff --git a/DemoPrograms/Demo_Machine_Learning.py b/DemoPrograms/Demo_Machine_Learning.py
index 2c152dfb1..a21c2f39d 100644
--- a/DemoPrograms/Demo_Machine_Learning.py
+++ b/DemoPrograms/Demo_Machine_Learning.py
@@ -2,12 +2,6 @@
import sys
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
def MachineLearningGUI():
sg.set_options(text_justification='right')
diff --git a/DemoPrograms/Demo_Main_Control_Test_Panel.py b/DemoPrograms/Demo_Main_Control_Test_Panel.py
deleted file mode 100644
index 6ff9b4e19..000000000
--- a/DemoPrograms/Demo_Main_Control_Test_Panel.py
+++ /dev/null
@@ -1,13 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- This is a simple as it gets. Calls the "main" function which is the PySimpleGUI Test Harness
- or Control Panel of sorts. Use it to view themes, upgrade your PySimpleGUI to the GitHub version, etc.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.main()
-
diff --git a/DemoPrograms/Demo_Matplotlib.py b/DemoPrograms/Demo_Matplotlib.py
new file mode 100644
index 000000000..0f76faa37
--- /dev/null
+++ b/DemoPrograms/Demo_Matplotlib.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+from matplotlib.ticker import NullFormatter # useful for `logit` scale
+import matplotlib.pyplot as plt
+import numpy as np
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
+import PySimpleGUI as sg
+import matplotlib
+matplotlib.use('TkAgg')
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+
+ Based on information from: https://matplotlib.org/3.1.0/gallery/user_interfaces/embedding_in_tk_sgskip.html
+ (Thank you Em-Bo & dirck)
+"""
+
+
+# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+
+# Fixing random state for reproducibility
+np.random.seed(19680801)
+
+# make up some data in the interval ]0, 1[
+y = np.random.normal(loc=0.5, scale=0.4, size=1000)
+y = y[(y > 0) & (y < 1)]
+y.sort()
+x = np.arange(len(y))
+
+# plot with various axes scales
+plt.figure(1)
+
+# linear
+plt.subplot(221)
+plt.plot(x, y)
+plt.yscale('linear')
+plt.title('linear')
+plt.grid(True)
+
+
+# log
+plt.subplot(222)
+plt.plot(x, y)
+plt.yscale('log')
+plt.title('log')
+plt.grid(True)
+
+
+# symmetric log
+plt.subplot(223)
+plt.plot(x, y - y.mean())
+plt.yscale('symlog', linthreshy=0.01)
+plt.title('symlog')
+plt.grid(True)
+
+# logit
+plt.subplot(224)
+plt.plot(x, y)
+plt.yscale('logit')
+plt.title('logit')
+plt.grid(True)
+plt.gca().yaxis.set_minor_formatter(NullFormatter())
+plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
+ wspace=0.35)
+fig = plt.gcf() # if using Pyplot then get the figure from the plot
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
+
+# ------------------------------- Beginning of Matplotlib helper code -----------------------
+
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ figure_canvas_agg.draw()
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
+ return figure_canvas_agg
+# ------------------------------- Beginning of GUI CODE -------------------------------
+
+
+# define the window layout
+layout = [[sg.Text('Plot test', font='Any 18')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
+ layout, finalize=True)
+
+# add the plot to the window
+fig_canvas_agg = draw_figure(window['canvas'].TKCanvas, fig)
+
+event, values = window.read()
+
+window.close()
diff --git a/DemoPrograms/Demo_Matplotlib_Animated.py b/DemoPrograms/Demo_Matplotlib_Animated.py
index 1b05c6a89..9311613bc 100644
--- a/DemoPrograms/Demo_Matplotlib_Animated.py
+++ b/DemoPrograms/Demo_Matplotlib_Animated.py
@@ -4,12 +4,6 @@
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
from matplotlib.figure import Figure
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Yet another usage of MatPlotLib with animations.
def draw_figure(canvas, figure, loc=(0, 0)):
diff --git a/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py b/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py
index ab3e20823..e1dcd0810 100644
--- a/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py
+++ b/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py
@@ -4,12 +4,6 @@
import matplotlib.pyplot as plt
from numpy.random import rand
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
def draw_figure(canvas, figure):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
diff --git a/DemoPrograms/Demo_Matplotlib_Browser.py b/DemoPrograms/Demo_Matplotlib_Browser.py
index 530bf3177..193e1f7b2 100644
--- a/DemoPrograms/Demo_Matplotlib_Browser.py
+++ b/DemoPrograms/Demo_Matplotlib_Browser.py
@@ -16,11 +16,7 @@
* Draw plots onto convas
* Display form (BLOCKING)
-Each plotting function, complete with imports, was copied directly from Matplot examples page
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+Each plotting function, complete with imports, was copied directly from Matplot examples page
"""
import numpy as np
@@ -828,26 +824,15 @@ def get_rgb():
# The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget
def draw_figure(canvas, figure):
- if not hasattr(draw_figure, 'canvas_packed'):
- draw_figure.canvas_packed = {}
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
- widget = figure_canvas_agg.get_tk_widget()
- if widget not in draw_figure.canvas_packed:
- draw_figure.canvas_packed[widget] = figure
- widget.pack(side='top', fill='both', expand=1)
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
-
def delete_figure_agg(figure_agg):
figure_agg.get_tk_widget().forget()
- try:
- draw_figure.canvas_packed.pop(figure_agg.get_tk_widget())
- except Exception as e:
- print(f'Error removing {figure_agg} from list', e)
plt.close('all')
-
# -------------------------------- GUI Starts Here -------------------------------#
# fig = your figure you want to display. Assumption is that 'fig' holds the #
# information to display. #
@@ -861,7 +846,7 @@ def delete_figure_agg(figure_agg):
'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots,
'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram}
-sg.theme('LightGreen')
+sg.change_look_and_feel('LightGreen')
figure_w, figure_h = 650, 650
# define the form layout
@@ -880,7 +865,7 @@ def delete_figure_agg(figure_agg):
while True:
event, values = window.read()
# print(event, values) # helps greatly when debugging
- if event in (sg.WIN_CLOSED, 'Exit'): # if user closed window or clicked Exit button
+ if event in (None, 'Exit'): # if user closed window or clicked Exit button
break
if figure_agg:
# ** IMPORTANT ** Clean up previous drawing before drawing again
@@ -888,9 +873,6 @@ def delete_figure_agg(figure_agg):
choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list)
func = fig_dict[choice] # get function to call from the dictionary
window['-MULTILINE-'].update(inspect.getsource(func)) # show source code to function in multiline
- try:
- fig = func() # call function to get the figure
- figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
- except Exception as e:
- print('Exception in fucntion', e)
+ fig = func() # call function to get the figure
+ figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py
index a9681b9b0..704046dea 100644
--- a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py
+++ b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py
@@ -17,10 +17,6 @@
* Display form (NON BLOCKING)
* Draw plots onto convas
* Display form (BLOCKING)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -841,23 +837,14 @@ def get_rgb():
def draw_figure(canvas, figure):
- if not hasattr(draw_figure, 'canvas_packed'):
- draw_figure.canvas_packed = {}
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
- widget = figure_canvas_agg.get_tk_widget()
- if widget not in draw_figure.canvas_packed:
- draw_figure.canvas_packed[widget] = figure
- widget.pack(side='top', fill='both', expand=1)
+ figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def delete_figure_agg(figure_agg):
figure_agg.get_tk_widget().forget()
- try:
- draw_figure.canvas_packed.pop(figure_agg.get_tk_widget())
- except Exception as e:
- print(f'Error removing {figure_agg} from list', e)
plt.close('all')
@@ -878,7 +865,7 @@ def delete_figure_agg(figure_agg):
'Artist Customized Box Plots 2': ArtistBoxplot2, 'Pyplot Histogram': PyplotHistogram}
-sg.theme('LightGreen')
+sg.change_look_and_feel('LightGreen')
figure_w, figure_h = 650, 650
# define the form layout
listbox_values = list(fig_dict)
@@ -894,14 +881,16 @@ def delete_figure_agg(figure_agg):
[sg.Col(col_listbox), col_instructions], ]
# create the form and show it without the plot
-window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, resizable=True, finalize=True)
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
+ layout, resizable=True, finalize=True)
canvas_elem = window['-CANVAS-']
multiline_elem = window['-MULTILINE-']
figure_agg = None
+
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
if figure_agg:
@@ -913,8 +902,6 @@ def delete_figure_agg(figure_agg):
func = fig_dict[choice]
# show source code to function in multiline
window['-MULTILINE-'].update(inspect.getsource(func))
- try:
- fig = func() # call function to get the figure
- figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
- except Exception as e:
- print('Error in plotting', e)
+ fig = func() # call function to get the figure
+ figure_agg = draw_figure(
+ window['-CANVAS-'].TKCanvas, fig) # draw the figure
diff --git a/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py b/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py
deleted file mode 100644
index 5a0ba5173..000000000
--- a/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py
+++ /dev/null
@@ -1,221 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIQt as sg
-# import PySimpleGUIWeb as sg
-
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.figure
-import matplotlib.pyplot as plt
-import io
-
-from matplotlib import cm
-from mpl_toolkits.mplot3d.axes3d import get_test_data
-from matplotlib.ticker import NullFormatter # useful for `logit` scale
-
-
-"""
- Demo - Matplotlib Embedded figure in a window TEMPLATE
-
- The reason this program is labelled as a "Template" is that it functions on 3
- PySimpleGUI ports by only changing the import statement. tk, Qt, Web(Remi) all
- run this same code and produce identical results.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def create_axis_grid():
- from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
-
- plt.close('all')
-
- def get_demo_image():
- # prepare image
- delta = 0.5
-
- extent = (-3, 4, -4, 3)
- x = np.arange(-3.0, 4.001, delta)
- y = np.arange(-4.0, 3.001, delta)
- X, Y = np.meshgrid(x, y)
- Z1 = np.exp(-X ** 2 - Y ** 2)
- Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
- Z = (Z1 - Z2) * 2
-
- return Z, extent
-
- def get_rgb():
- Z, extent = get_demo_image()
-
- Z[Z < 0] = 0.
- Z = Z / Z.max()
-
- R = Z[:13, :13]
- G = Z[2:, 2:]
- B = Z[:13, 2:]
-
- return R, G, B
-
- fig = plt.figure(1)
- ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
-
- r, g, b = get_rgb()
- kwargs = dict(origin="lower", interpolation="nearest")
- ax.imshow_rgb(r, g, b, **kwargs)
-
- ax.RGB.set_xlim(0., 9.5)
- ax.RGB.set_ylim(0.9, 10.6)
-
- plt.draw()
- return plt.gcf()
-
-
-
-def create_figure():
- # ------------------------------- START OF YOUR MATPLOTLIB CODE -------------------------------
- fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
- t = np.arange(0, 3, .01)
- fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
-
- return fig
-
-
-def create_subplot_3d():
-
-
- fig = plt.figure()
-
- ax = fig.add_subplot(1, 2, 1, projection='3d')
- X = np.arange(-5, 5, 0.25)
- Y = np.arange(-5, 5, 0.25)
- X, Y = np.meshgrid(X, Y)
- R = np.sqrt(X ** 2 + Y ** 2)
- Z = np.sin(R)
- surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
- linewidth=0, antialiased=False)
- ax.set_zlim3d(-1.01, 1.01)
-
- fig.colorbar(surf, shrink=0.5, aspect=5)
-
- ax = fig.add_subplot(1, 2, 2, projection='3d')
- X, Y, Z = get_test_data(0.05)
- ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
- return fig
-
-
-
-
-def create_pyplot_scales():
-
- plt.close('all')
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- # make up some data in the interval ]0, 1[
- y = np.random.normal(loc=0.5, scale=0.4, size=1000)
- y = y[(y > 0) & (y < 1)]
- y.sort()
- x = np.arange(len(y))
-
- # plot with various axes scales
- plt.figure(1)
-
- # linear
- plt.subplot(221)
- plt.plot(x, y)
- plt.yscale('linear')
- plt.title('linear')
- plt.grid(True)
-
- # log
- plt.subplot(222)
- plt.plot(x, y)
- plt.yscale('log')
- plt.title('log')
- plt.grid(True)
-
- # symmetric log
- plt.subplot(223)
- plt.plot(x, y - y.mean())
- plt.yscale('symlog', linthreshy=0.01)
- plt.title('symlog')
- plt.grid(True)
-
- # logit
- plt.subplot(224)
- plt.plot(x, y)
- plt.yscale('logit')
- plt.title('logit')
- plt.grid(True)
- # Format the minor tick labels of the y-axis into empty strings with
- # `NullFormatter`, to avoid cumbering the axis with too many labels.
- plt.gca().yaxis.set_minor_formatter(NullFormatter())
- # Adjust the subplot layout, because the logit one may take more space
- # than usual, due to y-tick labels like "1 - 10^{-3}"
- plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
- wspace=0.35)
- return plt.gcf()
-
-# ----------------------------- The draw figure helpful function -----------------------------
-
-def draw_figure(element, figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is None:
- return None
- buf.seek(0)
- element.update(data=buf.read())
- return canv
-
-
-# ----------------------------- The GUI Section -----------------------------
-
-def main():
- dictionary_of_figures = {'Axis Grid': create_axis_grid,
- 'Subplot 3D': create_subplot_3d,
- 'Scales': create_pyplot_scales,
- 'Basic Figure': create_figure}
-
-
- left_col = [[sg.T('Figures to Draw')],
- [sg.Listbox(list(dictionary_of_figures), default_values=[list(dictionary_of_figures)[0]], size=(15, 5), key='-LB-')],
- [sg.T('Matplotlib Styles')],
- [sg.Combo(plt.style.available, key='-STYLE-')]]
-
- layout = [ [sg.T('Matplotlib Example', font='Any 20')],
- [sg.Column(left_col), sg.Image(key='-IMAGE-')],
- [sg.B('Draw'), sg.B('Exit')] ]
-
- window = sg.Window('Matplotlib Template', layout)
-
- image_element = window['-IMAGE-'] # type: sg.Image
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == 'Exit' or event == sg.WIN_CLOSED:
- break
- if event == 'Draw' and values['-LB-']:
- # Get the function to call to make figure. Done this way to get around bug in Web port (default value not working correctly for listbox)
- func = dictionary_of_figures.get(values['-LB-'][0], list(dictionary_of_figures.values())[0])
- if values['-STYLE-']:
- plt.style.use(values['-STYLE-'])
- draw_figure(image_element, func())
-
- window.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py b/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py
deleted file mode 100644
index 49a275171..000000000
--- a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import PySimpleGUI as sg
-import numpy as np
-
-"""
- Embedding the Matplotlib toolbar into your application
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ------------------------------- This is to include a matplotlib figure in a Tkinter canvas
-import matplotlib.pyplot as plt
-from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
-
-
-def draw_figure_w_toolbar(canvas, fig, canvas_toolbar):
- if canvas.children:
- for child in canvas.winfo_children():
- child.destroy()
- if canvas_toolbar.children:
- for child in canvas_toolbar.winfo_children():
- child.destroy()
- figure_canvas_agg = FigureCanvasTkAgg(fig, master=canvas)
- figure_canvas_agg.draw()
- toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
- toolbar.update()
- figure_canvas_agg.get_tk_widget().pack(side='right', fill='both', expand=1)
-
-
-class Toolbar(NavigationToolbar2Tk):
- def __init__(self, *args, **kwargs):
- super(Toolbar, self).__init__(*args, **kwargs)
-
-
-# ------------------------------- PySimpleGUI CODE
-
-layout = [
- [sg.T('Graph: y=sin(x)')],
- [sg.B('Plot'), sg.B('Exit')],
- [sg.T('Controls:')],
- [sg.Canvas(key='controls_cv')],
- [sg.T('Figure:')],
- [sg.Column(
- layout=[
- [sg.Canvas(key='fig_cv',
- # it's important that you set this size
- size=(400 * 2, 400)
- )]
- ],
- background_color='#DAE0E6',
- pad=(0, 0)
- )],
- [sg.B('Alive?')]
-
-]
-
-window = sg.Window('Graph with controls', layout)
-
-while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'): # always, always give a way out!
- break
- elif event is 'Plot':
- # ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE
- plt.figure(1)
- fig = plt.gcf()
- DPI = fig.get_dpi()
- # ------------------------------- you have to play with this size to reduce the movement error when the mouse hovers over the figure, it's close to canvas size
- fig.set_size_inches(404 * 2 / float(DPI), 404 / float(DPI))
- # -------------------------------
- x = np.linspace(0, 2 * np.pi)
- y = np.sin(x)
- plt.plot(x, y)
- plt.title('y=sin(x)')
- plt.xlabel('X')
- plt.ylabel('Y')
- plt.grid()
-
- # ------------------------------- Instead of plt.show()
- draw_figure_w_toolbar(window['fig_cv'].TKCanvas, fig, window['controls_cv'].TKCanvas)
-
-window.close()
diff --git a/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py b/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py
deleted file mode 100644
index b1a49dc4f..000000000
--- a/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py
+++ /dev/null
@@ -1,948 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-# import PySimpleGUIQt as sg
-# import PySimpleGUIWeb as sg
-
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.figure
-import matplotlib.pyplot as plt
-import io
-
-from matplotlib import cm
-from mpl_toolkits.mplot3d.axes3d import get_test_data
-from matplotlib.ticker import NullFormatter # useful for `logit` scale
-
-import PIL
-import base64
-
-"""
-Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
-
-Basic steps are:
- * Create a Canvas Element
- * Layout form
- * Display form (NON BLOCKING)
- * Draw plots onto convas
- * Display form (BLOCKING)
-
-Each plotting function, complete with imports, was copied directly from Matplot examples page
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import numpy as np
-import matplotlib.pyplot as plt
-
-
-def PyplotSimple():
- import numpy as np
- import matplotlib.pyplot as plt
-
- # evenly sampled time .2 intervals
- t = np.arange(0., 5., 0.2) # go from 0 to 5 using .2 intervals
-
- # red dashes, blue squares and green triangles
- plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^')
-
- fig = plt.gcf() # get the figure to show
- return fig
-
-
-def PyplotHistogram():
- """
- =============================================================
- Demo of the histogram (hist) function with multiple data sets
- =============================================================
-
- Plot histogram with multiple sample sets and demonstrate:
-
- * Use of legend with multiple sample sets
- * Stacked bars
- * Step curve with no fill
- * Data sets of different sample sizes
-
- Selecting different bin counts and sizes can significantly affect the
- shape of a histogram. The Astropy docs have a great section on how to
- select these parameters:
- http://docs.astropy.org/en/stable/visualization/histogram.html
- """
-
- import numpy as np
- import matplotlib.pyplot as plt
-
- np.random.seed(0)
-
- n_bins = 10
- x = np.random.randn(1000, 3)
-
- fig, axes = plt.subplots(nrows=2, ncols=2)
- ax0, ax1, ax2, ax3 = axes.flatten()
-
- colors = ['red', 'tan', 'lime']
- ax0.hist(x, n_bins, normed=1, histtype='bar', color=colors, label=colors)
- ax0.legend(prop={'size': 10})
- ax0.set_title('bars with legend')
-
- ax1.hist(x, n_bins, normed=1, histtype='bar', stacked=True)
- ax1.set_title('stacked bar')
-
- ax2.hist(x, n_bins, histtype='step', stacked=True, fill=False)
- ax2.set_title('stack step (unfilled)')
-
- # Make a multiple-histogram of data-sets with different length.
- x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
- ax3.hist(x_multi, n_bins, histtype='bar')
- ax3.set_title('different sample sizes')
-
- fig.tight_layout()
- return fig
-
-
-def PyplotArtistBoxPlots():
- """
- =========================================
- Demo of artist customization in box plots
- =========================================
-
- This example demonstrates how to use the various kwargs
- to fully customize box plots. The first figure demonstrates
- how to remove and add individual components (note that the
- mean is the only value not shown by default). The second
- figure demonstrates how the styles of the artists can
- be customized. It also demonstrates how to set the limit
- of the whiskers to specific percentiles (lower right axes)
-
- A good general reference on boxplots and their history can be found
- here: http://vita.had.co.nz/papers/boxplots.pdf
-
- """
-
- import numpy as np
- import matplotlib.pyplot as plt
-
- # fake data
- np.random.seed(937)
- data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
- labels = list('ABCD')
- fs = 10 # fontsize
-
- # demonstrate how to toggle the display of different elements:
- fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
- axes[0, 0].boxplot(data, labels=labels)
- axes[0, 0].set_title('Default', fontsize=fs)
-
- axes[0, 1].boxplot(data, labels=labels, showmeans=True)
- axes[0, 1].set_title('showmeans=True', fontsize=fs)
-
- axes[0, 2].boxplot(data, labels=labels, showmeans=True, meanline=True)
- axes[0, 2].set_title('showmeans=True,\nmeanline=True', fontsize=fs)
-
- axes[1, 0].boxplot(data, labels=labels, showbox=False, showcaps=False)
- tufte_title = 'Tufte Style \n(showbox=False,\nshowcaps=False)'
- axes[1, 0].set_title(tufte_title, fontsize=fs)
-
- axes[1, 1].boxplot(data, labels=labels, notch=True, bootstrap=10000)
- axes[1, 1].set_title('notch=True,\nbootstrap=10000', fontsize=fs)
-
- axes[1, 2].boxplot(data, labels=labels, showfliers=False)
- axes[1, 2].set_title('showfliers=False', fontsize=fs)
-
- for ax in axes.flatten():
- ax.set_yscale('log')
- ax.set_yticklabels([])
-
- fig.subplots_adjust(hspace=0.4)
- return fig
-
-
-def ArtistBoxplot2():
- # fake data
- np.random.seed(937)
- data = np.random.lognormal(size=(37, 4), mean=1.5, sigma=1.75)
- labels = list('ABCD')
- fs = 10 # fontsize
-
- # demonstrate how to customize the display different elements:
- boxprops = dict(linestyle='--', linewidth=3, color='darkgoldenrod')
- flierprops = dict(marker='o', markerfacecolor='green', markersize=12,
- linestyle='none')
- medianprops = dict(linestyle='-.', linewidth=2.5, color='firebrick')
- meanpointprops = dict(marker='D', markeredgecolor='black',
- markerfacecolor='firebrick')
- meanlineprops = dict(linestyle='--', linewidth=2.5, color='purple')
-
- fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(6, 6), sharey=True)
- axes[0, 0].boxplot(data, boxprops=boxprops)
- axes[0, 0].set_title('Custom boxprops', fontsize=fs)
-
- axes[0, 1].boxplot(data, flierprops=flierprops, medianprops=medianprops)
- axes[0, 1].set_title('Custom medianprops\nand flierprops', fontsize=fs)
-
- axes[0, 2].boxplot(data, whis='range')
- axes[0, 2].set_title('whis="range"', fontsize=fs)
-
- axes[1, 0].boxplot(data, meanprops=meanpointprops, meanline=False,
- showmeans=True)
- axes[1, 0].set_title('Custom mean\nas point', fontsize=fs)
-
- axes[1, 1].boxplot(data, meanprops=meanlineprops, meanline=True,
- showmeans=True)
- axes[1, 1].set_title('Custom mean\nas line', fontsize=fs)
-
- axes[1, 2].boxplot(data, whis=[15, 85])
- axes[1, 2].set_title('whis=[15, 85]\n#percentiles', fontsize=fs)
-
- for ax in axes.flatten():
- ax.set_yscale('log')
- ax.set_yticklabels([])
-
- fig.suptitle("I never said they'd be pretty")
- fig.subplots_adjust(hspace=0.4)
- return fig
-
-
-def PyplotScatterWithLegend():
- import matplotlib.pyplot as plt
- from numpy.random import rand
-
- fig, ax = plt.subplots()
- for color in ['red', 'green', 'blue']:
- n = 750
- x, y = rand(2, n)
- scale = 200.0 * rand(n)
- ax.scatter(x, y, c=color, s=scale, label=color,
- alpha=0.3, edgecolors='none')
-
- ax.legend()
- ax.grid(True)
- return fig
-
-
-def PyplotLineStyles():
- """
- ==========
- Linestyles
- ==========
-
- This examples showcases different linestyles copying those of Tikz/PGF.
- """
- import numpy as np
- import matplotlib.pyplot as plt
- from collections import OrderedDict
- from matplotlib.transforms import blended_transform_factory
-
- linestyles = OrderedDict(
- [('solid', (0, ())),
- ('loosely dotted', (0, (1, 10))),
- ('dotted', (0, (1, 5))),
- ('densely dotted', (0, (1, 1))),
-
- ('loosely dashed', (0, (5, 10))),
- ('dashed', (0, (5, 5))),
- ('densely dashed', (0, (5, 1))),
-
- ('loosely dashdotted', (0, (3, 10, 1, 10))),
- ('dashdotted', (0, (3, 5, 1, 5))),
- ('densely dashdotted', (0, (3, 1, 1, 1))),
-
- ('loosely dashdotdotted', (0, (3, 10, 1, 10, 1, 10))),
- ('dashdotdotted', (0, (3, 5, 1, 5, 1, 5))),
- ('densely dashdotdotted', (0, (3, 1, 1, 1, 1, 1)))])
-
- plt.figure(figsize=(10, 6))
- ax = plt.subplot(1, 1, 1)
-
- X, Y = np.linspace(0, 100, 10), np.zeros(10)
- for i, (name, linestyle) in enumerate(linestyles.items()):
- ax.plot(X, Y + i, linestyle=linestyle, linewidth=1.5, color='black')
-
- ax.set_ylim(-0.5, len(linestyles) - 0.5)
- plt.yticks(np.arange(len(linestyles)), linestyles.keys())
- plt.xticks([])
-
- # For each line style, add a text annotation with a small offset from
- # the reference point (0 in Axes coords, y tick value in Data coords).
- reference_transform = blended_transform_factory(ax.transAxes, ax.transData)
- for i, (name, linestyle) in enumerate(linestyles.items()):
- ax.annotate(str(linestyle), xy=(0.0, i), xycoords=reference_transform,
- xytext=(-6, -12), textcoords='offset points', color="blue",
- fontsize=8, ha="right", family="monospace")
-
- plt.tight_layout()
- return plt.gcf()
-
-
-def PyplotLinePolyCollection():
- import matplotlib.pyplot as plt
- from matplotlib import collections, colors, transforms
- import numpy as np
-
- nverts = 50
- npts = 100
-
- # Make some spirals
- r = np.arange(nverts)
- theta = np.linspace(0, 2 * np.pi, nverts)
- xx = r * np.sin(theta)
- yy = r * np.cos(theta)
- spiral = np.column_stack([xx, yy])
-
- # Fixing random state for reproducibility
- rs = np.random.RandomState(19680801)
-
- # Make some offsets
- xyo = rs.randn(npts, 2)
-
- # Make a list of colors cycling through the default series.
- colors = [colors.to_rgba(c)
- for c in plt.rcParams['axes.prop_cycle'].by_key()['color']]
-
- fig, axes = plt.subplots(2, 2)
- fig.subplots_adjust(top=0.92, left=0.07, right=0.97,
- hspace=0.3, wspace=0.3)
- ((ax1, ax2), (ax3, ax4)) = axes # unpack the axes
-
- col = collections.LineCollection([spiral], offsets=xyo,
- transOffset=ax1.transData)
- trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0 / 72.0)
- col.set_transform(trans) # the points to pixels transform
- # Note: the first argument to the collection initializer
- # must be a list of sequences of x,y tuples; we have only
- # one sequence, but we still have to put it in a list.
- ax1.add_collection(col, autolim=True)
- # autolim=True enables autoscaling. For collections with
- # offsets like this, it is neither efficient nor accurate,
- # but it is good enough to generate a plot that you can use
- # as a starting point. If you know beforehand the range of
- # x and y that you want to show, it is better to set them
- # explicitly, leave out the autolim kwarg (or set it to False),
- # and omit the 'ax1.autoscale_view()' call below.
-
- # Make a transform for the line segments such that their size is
- # given in points:
- col.set_color(colors)
-
- ax1.autoscale_view() # See comment above, after ax1.add_collection.
- ax1.set_title('LineCollection using offsets')
-
- # The same data as above, but fill the curves.
- col = collections.PolyCollection([spiral], offsets=xyo,
- transOffset=ax2.transData)
- trans = transforms.Affine2D().scale(fig.dpi / 72.0)
- col.set_transform(trans) # the points to pixels transform
- ax2.add_collection(col, autolim=True)
- col.set_color(colors)
-
- ax2.autoscale_view()
- ax2.set_title('PolyCollection using offsets')
-
- # 7-sided regular polygons
-
- col = collections.RegularPolyCollection(
- 7, sizes=np.abs(xx) * 10.0, offsets=xyo, transOffset=ax3.transData)
- trans = transforms.Affine2D().scale(fig.dpi / 72.0)
- col.set_transform(trans) # the points to pixels transform
- ax3.add_collection(col, autolim=True)
- col.set_color(colors)
- ax3.autoscale_view()
- ax3.set_title('RegularPolyCollection using offsets')
-
- # Simulate a series of ocean current profiles, successively
- # offset by 0.1 m/s so that they form what is sometimes called
- # a "waterfall" plot or a "stagger" plot.
-
- nverts = 60
- ncurves = 20
- offs = (0.1, 0.0)
-
- yy = np.linspace(0, 2 * np.pi, nverts)
- ym = np.max(yy)
- xx = (0.2 + (ym - yy) / ym) ** 2 * np.cos(yy - 0.4) * 0.5
- segs = []
- for i in range(ncurves):
- xxx = xx + 0.02 * rs.randn(nverts)
- curve = np.column_stack([xxx, yy * 100])
- segs.append(curve)
-
- col = collections.LineCollection(segs, offsets=offs)
- ax4.add_collection(col, autolim=True)
- col.set_color(colors)
- ax4.autoscale_view()
- ax4.set_title('Successive data offsets')
- ax4.set_xlabel('Zonal velocity component (m/s)')
- ax4.set_ylabel('Depth (m)')
- # Reverse the y-axis so depth increases downward
- ax4.set_ylim(ax4.get_ylim()[::-1])
- return fig
-
-
-def PyplotGGPlotSytleSheet():
- import numpy as np
- import matplotlib.pyplot as plt
-
- plt.style.use('ggplot')
-
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- fig, axes = plt.subplots(ncols=2, nrows=2)
- ax1, ax2, ax3, ax4 = axes.ravel()
-
- # scatter plot (Note: `plt.scatter` doesn't use default colors)
- x, y = np.random.normal(size=(2, 200))
- ax1.plot(x, y, 'o')
-
- # sinusoidal lines with colors from default color cycle
- L = 2 * np.pi
- x = np.linspace(0, L)
- ncolors = len(plt.rcParams['axes.prop_cycle'])
- shift = np.linspace(0, L, ncolors, endpoint=False)
- for s in shift:
- ax2.plot(x, np.sin(x + s), '-')
- ax2.margins(0)
-
- # bar graphs
- x = np.arange(5)
- y1, y2 = np.random.randint(1, 25, size=(2, 5))
- width = 0.25
- ax3.bar(x, y1, width)
- ax3.bar(x + width, y2, width,
- color=list(plt.rcParams['axes.prop_cycle'])[2]['color'])
- ax3.set_xticks(x + width)
- ax3.set_xticklabels(['a', 'b', 'c', 'd', 'e'])
-
- # circles with colors from default color cycle
- for i, color in enumerate(plt.rcParams['axes.prop_cycle']):
- xy = np.random.normal(size=2)
- ax4.add_patch(plt.Circle(xy, radius=0.3, color=color['color']))
- ax4.axis('equal')
- ax4.margins(0)
- fig = plt.gcf() # get the figure to show
- return fig
-
-
-def PyplotBoxPlot():
- import numpy as np
- import matplotlib.pyplot as plt
-
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- # fake up some data
- spread = np.random.rand(50) * 100
- center = np.ones(25) * 50
- flier_high = np.random.rand(10) * 100 + 100
- flier_low = np.random.rand(10) * -100
- data = np.concatenate((spread, center, flier_high, flier_low), 0)
- fig1, ax1 = plt.subplots()
- ax1.set_title('Basic Plot')
- ax1.boxplot(data)
- return fig1
-
-
-def PyplotRadarChart():
- import numpy as np
-
- import matplotlib.pyplot as plt
- from matplotlib.path import Path
- from matplotlib.spines import Spine
- from matplotlib.projections.polar import PolarAxes
- from matplotlib.projections import register_projection
-
- def radar_factory(num_vars, frame='circle'):
- """Create a radar chart with `num_vars` axes.
-
- This function creates a RadarAxes projection and registers it.
-
- Parameters
- ----------
- num_vars : int
- Number of variables for radar chart.
- frame : {'circle' | 'polygon'}
- Shape of frame surrounding axes.
-
- """
- # calculate evenly-spaced axis angles
- theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False)
-
- def draw_poly_patch(self):
- # rotate theta such that the first axis is at the top
- verts = unit_poly_verts(theta + np.pi / 2)
- return plt.Polygon(verts, closed=True, edgecolor='k')
-
- def draw_circle_patch(self):
- # unit circle centered on (0.5, 0.5)
- return plt.Circle((0.5, 0.5), 0.5)
-
- patch_dict = {'polygon': draw_poly_patch, 'circle': draw_circle_patch}
- if frame not in patch_dict:
- raise ValueError('unknown value for `frame`: %s' % frame)
-
- class RadarAxes(PolarAxes):
-
- name = 'radar'
- # use 1 line segment to connect specified points
- RESOLUTION = 1
- # define draw_frame method
- draw_patch = patch_dict[frame]
-
- def __init__(self, *args, **kwargs):
- super(RadarAxes, self).__init__(*args, **kwargs)
- # rotate plot such that the first axis is at the top
- self.set_theta_zero_location('N')
-
- def fill(self, *args, **kwargs):
- """Override fill so that line is closed by default"""
- closed = kwargs.pop('closed', True)
- return super(RadarAxes, self).fill(closed=closed, *args, **kwargs)
-
- def plot(self, *args, **kwargs):
- """Override plot so that line is closed by default"""
- lines = super(RadarAxes, self).plot(*args, **kwargs)
- for line in lines:
- self._close_line(line)
-
- def _close_line(self, line):
- x, y = line.get_data()
- # FIXME: markers at x[0], y[0] get doubled-up
- if x[0] != x[-1]:
- x = np.concatenate((x, [x[0]]))
- y = np.concatenate((y, [y[0]]))
- line.set_data(x, y)
-
- def set_varlabels(self, labels):
- self.set_thetagrids(np.degrees(theta), labels)
-
- def _gen_axes_patch(self):
- return self.draw_patch()
-
- def _gen_axes_spines(self):
- if frame == 'circle':
- return PolarAxes._gen_axes_spines(self)
- # The following is a hack to get the spines (i.e. the axes frame)
- # to draw correctly for a polygon frame.
-
- # spine_type must be 'left', 'right', 'top', 'bottom', or `circle`.
- spine_type = 'circle'
- verts = unit_poly_verts(theta + np.pi / 2)
- # close off polygon by repeating first vertex
- verts.append(verts[0])
- path = Path(verts)
-
- spine = Spine(self, spine_type, path)
- spine.set_transform(self.transAxes)
- return {'polar': spine}
-
- register_projection(RadarAxes)
- return theta
-
- def unit_poly_verts(theta):
- """Return vertices of polygon for subplot axes.
-
- This polygon is circumscribed by a unit circle centered at (0.5, 0.5)
- """
- x0, y0, r = [0.5] * 3
- verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta]
- return verts
-
- def example_data():
- # The following data is from the Denver Aerosol Sources and Health study.
- # See doi:10.1016/j.atmosenv.2008.12.017
- #
- # The data are pollution source profile estimates for five modeled
- # pollution sources (e.g., cars, wood-burning, etc) that emit 7-9 chemical
- # species. The radar charts are experimented with here to see if we can
- # nicely visualize how the modeled source profiles change across four
- # scenarios:
- # 1) No gas-phase species present, just seven particulate counts on
- # Sulfate
- # Nitrate
- # Elemental Carbon (EC)
- # Organic Carbon fraction 1 (OC)
- # Organic Carbon fraction 2 (OC2)
- # Organic Carbon fraction 3 (OC3)
- # Pyrolized Organic Carbon (OP)
- # 2)Inclusion of gas-phase specie carbon monoxide (CO)
- # 3)Inclusion of gas-phase specie ozone (O3).
- # 4)Inclusion of both gas-phase species is present...
- data = [
- ['Sulfate', 'Nitrate', 'EC', 'OC1', 'OC2', 'OC3', 'OP', 'CO', 'O3'],
- ('Basecase', [
- [0.88, 0.01, 0.03, 0.03, 0.00, 0.06, 0.01, 0.00, 0.00],
- [0.07, 0.95, 0.04, 0.05, 0.00, 0.02, 0.01, 0.00, 0.00],
- [0.01, 0.02, 0.85, 0.19, 0.05, 0.10, 0.00, 0.00, 0.00],
- [0.02, 0.01, 0.07, 0.01, 0.21, 0.12, 0.98, 0.00, 0.00],
- [0.01, 0.01, 0.02, 0.71, 0.74, 0.70, 0.00, 0.00, 0.00]]),
- ('With CO', [
- [0.88, 0.02, 0.02, 0.02, 0.00, 0.05, 0.00, 0.05, 0.00],
- [0.08, 0.94, 0.04, 0.02, 0.00, 0.01, 0.12, 0.04, 0.00],
- [0.01, 0.01, 0.79, 0.10, 0.00, 0.05, 0.00, 0.31, 0.00],
- [0.00, 0.02, 0.03, 0.38, 0.31, 0.31, 0.00, 0.59, 0.00],
- [0.02, 0.02, 0.11, 0.47, 0.69, 0.58, 0.88, 0.00, 0.00]]),
- ('With O3', [
- [0.89, 0.01, 0.07, 0.00, 0.00, 0.05, 0.00, 0.00, 0.03],
- [0.07, 0.95, 0.05, 0.04, 0.00, 0.02, 0.12, 0.00, 0.00],
- [0.01, 0.02, 0.86, 0.27, 0.16, 0.19, 0.00, 0.00, 0.00],
- [0.01, 0.03, 0.00, 0.32, 0.29, 0.27, 0.00, 0.00, 0.95],
- [0.02, 0.00, 0.03, 0.37, 0.56, 0.47, 0.87, 0.00, 0.00]]),
- ('CO & O3', [
- [0.87, 0.01, 0.08, 0.00, 0.00, 0.04, 0.00, 0.00, 0.01],
- [0.09, 0.95, 0.02, 0.03, 0.00, 0.01, 0.13, 0.06, 0.00],
- [0.01, 0.02, 0.71, 0.24, 0.13, 0.16, 0.00, 0.50, 0.00],
- [0.01, 0.03, 0.00, 0.28, 0.24, 0.23, 0.00, 0.44, 0.88],
- [0.02, 0.00, 0.18, 0.45, 0.64, 0.55, 0.86, 0.00, 0.16]])
- ]
- return data
-
- N = 9
- theta = radar_factory(N, frame='polygon')
-
- data = example_data()
- spoke_labels = data.pop(0)
-
- fig, axes = plt.subplots(figsize=(9, 9), nrows=2, ncols=2,
- subplot_kw=dict(projection='radar'))
- fig.subplots_adjust(wspace=0.25, hspace=0.20, top=0.85, bottom=0.05)
-
- colors = ['b', 'r', 'g', 'm', 'y']
- # Plot the four cases from the example data on separate axes
- for ax, (title, case_data) in zip(axes.flatten(), data):
- ax.set_rgrids([0.2, 0.4, 0.6, 0.8])
- ax.set_title(title, weight='bold', size='medium', position=(0.5, 1.1),
- horizontalalignment='center', verticalalignment='center')
- for d, color in zip(case_data, colors):
- ax.plot(theta, d, color=color)
- ax.fill(theta, d, facecolor=color, alpha=0.25)
- ax.set_varlabels(spoke_labels)
-
- # add legend relative to top-left plot
- ax = axes[0, 0]
- labels = ('Factor 1', 'Factor 2', 'Factor 3', 'Factor 4', 'Factor 5')
- legend = ax.legend(labels, loc=(0.9, .95),
- labelspacing=0.1, fontsize='small')
-
- fig.text(0.5, 0.965, '5-Factor Solution Profiles Across Four Scenarios',
- horizontalalignment='center', color='black', weight='bold',
- size='large')
- return fig
-
-
-def DifferentScales():
- import numpy as np
- import matplotlib.pyplot as plt
-
- # Create some mock data
- t = np.arange(0.01, 10.0, 0.01)
- data1 = np.exp(t)
- data2 = np.sin(2 * np.pi * t)
-
- fig, ax1 = plt.subplots()
-
- color = 'tab:red'
- ax1.set_xlabel('time (s)')
- ax1.set_ylabel('exp', color=color)
- ax1.plot(t, data1, color=color)
- ax1.tick_params(axis='y', labelcolor=color)
-
- ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
-
- color = 'tab:blue'
- ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
- ax2.plot(t, data2, color=color)
- ax2.tick_params(axis='y', labelcolor=color)
-
- fig.tight_layout() # otherwise the right y-label is slightly clipped
- return fig
-
-
-def ExploringNormalizations():
- import matplotlib.pyplot as plt
- import matplotlib.colors as mcolors
- import numpy as np
- from numpy.random import multivariate_normal
-
- data = np.vstack([
- multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
- multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
- ])
-
- gammas = [0.8, 0.5, 0.3]
-
- fig, axes = plt.subplots(nrows=2, ncols=2)
-
- axes[0, 0].set_title('Linear normalization')
- axes[0, 0].hist2d(data[:, 0], data[:, 1], bins=100)
-
- for ax, gamma in zip(axes.flat[1:], gammas):
- ax.set_title(r'Power law $(\gamma=%1.1f)$' % gamma)
- ax.hist2d(data[:, 0], data[:, 1],
- bins=100, norm=mcolors.PowerNorm(gamma))
-
- fig.tight_layout()
- return fig
-
-
-def PyplotFormatstr():
- def f(t):
- return np.exp(-t) * np.cos(2 * np.pi * t)
-
- t1 = np.arange(0.0, 5.0, 0.1)
- t2 = np.arange(0.0, 5.0, 0.02)
-
- plt.figure(1)
- plt.subplot(211)
- plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
-
- plt.subplot(212)
- plt.plot(t2, np.cos(2 * np.pi * t2), 'r--')
- fig = plt.gcf() # get the figure to show
- return fig
-
-
-def UnicodeMinus():
- import numpy as np
- import matplotlib
- import matplotlib.pyplot as plt
-
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- matplotlib.rcParams['axes.unicode_minus'] = False
- fig, ax = plt.subplots()
- ax.plot(10 * np.random.randn(100), 10 * np.random.randn(100), 'o')
- ax.set_title('Using hyphen instead of Unicode minus')
- return fig
-
-
-def Subplot3d():
- from mpl_toolkits.mplot3d.axes3d import Axes3D
- from matplotlib import cm
- # from matplotlib.ticker import LinearLocator, FixedLocator, FormatStrFormatter
- import matplotlib.pyplot as plt
- import numpy as np
-
- fig = plt.figure()
-
- ax = fig.add_subplot(1, 2, 1, projection='3d')
- X = np.arange(-5, 5, 0.25)
- Y = np.arange(-5, 5, 0.25)
- X, Y = np.meshgrid(X, Y)
- R = np.sqrt(X ** 2 + Y ** 2)
- Z = np.sin(R)
- surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
- linewidth=0, antialiased=False)
- ax.set_zlim3d(-1.01, 1.01)
-
- # ax.w_zaxis.set_major_locator(LinearLocator(10))
- # ax.w_zaxis.set_major_formatter(FormatStrFormatter('%.03f'))
-
- fig.colorbar(surf, shrink=0.5, aspect=5)
-
- from mpl_toolkits.mplot3d.axes3d import get_test_data
- ax = fig.add_subplot(1, 2, 2, projection='3d')
- X, Y, Z = get_test_data(0.05)
- ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
- return fig
-
-
-def PyplotScales():
- import numpy as np
- import matplotlib.pyplot as plt
-
- from matplotlib.ticker import NullFormatter # useful for `logit` scale
-
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- # make up some data in the interval ]0, 1[
- y = np.random.normal(loc=0.5, scale=0.4, size=1000)
- y = y[(y > 0) & (y < 1)]
- y.sort()
- x = np.arange(len(y))
-
- # plot with various axes scales
- plt.figure(1)
-
- # linear
- plt.subplot(221)
- plt.plot(x, y)
- plt.yscale('linear')
- plt.title('linear')
- plt.grid(True)
-
- # log
- plt.subplot(222)
- plt.plot(x, y)
- plt.yscale('log')
- plt.title('log')
- plt.grid(True)
-
- # symmetric log
- plt.subplot(223)
- plt.plot(x, y - y.mean())
- plt.yscale('symlog', linthreshy=0.01)
- plt.title('symlog')
- plt.grid(True)
-
- # logit
- plt.subplot(224)
- plt.plot(x, y)
- plt.yscale('logit')
- plt.title('logit')
- plt.grid(True)
- # Format the minor tick labels of the y-axis into empty strings with
- # `NullFormatter`, to avoid cumbering the axis with too many labels.
- plt.gca().yaxis.set_minor_formatter(NullFormatter())
- # Adjust the subplot layout, because the logit one may take more space
- # than usual, due to y-tick labels like "1 - 10^{-3}"
- plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
- wspace=0.35)
- return plt.gcf()
-
-
-def AxesGrid():
- import numpy as np
- import matplotlib.pyplot as plt
- from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
-
- def get_demo_image():
- # prepare image
- delta = 0.5
-
- extent = (-3, 4, -4, 3)
- x = np.arange(-3.0, 4.001, delta)
- y = np.arange(-4.0, 3.001, delta)
- X, Y = np.meshgrid(x, y)
- Z1 = np.exp(-X ** 2 - Y ** 2)
- Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
- Z = (Z1 - Z2) * 2
-
- return Z, extent
-
- def get_rgb():
- Z, extent = get_demo_image()
-
- Z[Z < 0] = 0.
- Z = Z / Z.max()
-
- R = Z[:13, :13]
- G = Z[2:, 2:]
- B = Z[:13, 2:]
-
- return R, G, B
-
- fig = plt.figure(1)
- ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
-
- r, g, b = get_rgb()
- kwargs = dict(origin="lower", interpolation="nearest")
- ax.imshow_rgb(r, g, b, **kwargs)
-
- ax.RGB.set_xlim(0., 9.5)
- ax.RGB.set_ylim(0.9, 10.6)
-
- plt.draw()
- return plt.gcf()
-
-
-
-
-def figure_to_image(figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is None:
- return None
- buf.seek(0)
- return buf.read()
-
-
-
-def convert_to_bytes(file_or_bytes, resize=None):
- '''
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (Union[str, bytes])
- :param resize: optional new size
- :type resize: (Tuple[int, int] or None)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- '''
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- try:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
- except Exception as e:
- dataBytesIO = io.BytesIO(file_or_bytes)
- img = PIL.Image.open(dataBytesIO)
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height/cur_height, new_width/cur_width)
- img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.LANCZOS)
- with io.BytesIO() as bio:
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-
-
-
-# -------------------------------- GUI Starts Here -------------------------------#
-# fig = your figure you want to display. Assumption is that 'fig' holds the #
-# information to display. #
-# --------------------------------------------------------------------------------#
-
-fig_dict = {'Pyplot Simple': PyplotSimple, 'Pyplot Formatstr': PyplotFormatstr, 'PyPlot Three': Subplot3d,
- 'Unicode Minus': UnicodeMinus, 'Pyplot Scales': PyplotScales, 'Axes Grid': AxesGrid,
- 'Exploring Normalizations': ExploringNormalizations, 'Different Scales': DifferentScales,
- 'Pyplot Box Plot': PyplotBoxPlot, 'Pyplot ggplot Style Sheet': PyplotGGPlotSytleSheet,
- 'Pyplot Line Poly Collection': PyplotLinePolyCollection, 'Pyplot Line Styles': PyplotLineStyles,
- 'Pyplot Scatter With Legend': PyplotScatterWithLegend, 'Artist Customized Box Plots': PyplotArtistBoxPlots,
- 'Artist Customized Box Plots 2': ArtistBoxplot2, 'Pyplot Histogram': PyplotHistogram}
-
-sg.theme('LightGreen')
-
-figure_w, figure_h = 250, 250
-# define the form layout
-col_listbox = [[sg.Listbox(values=list(fig_dict.keys()), select_mode=sg.SELECT_MODE_EXTENDED, enable_events=True, size=(28, len(list(fig_dict))), key='-LISTBOX-')],
- [sg.Exit(size=(5, 2))]]
-
-image_col = sg.Col([[sg.Image(k=(i,j)) for i in range(4)]for j in range(4)])
-
-layout = [[sg.Text('Matplotlib Grid of Plots Using PIL', font=('current 18'))],
- [sg.Col(col_listbox, element_justification='c'),
- image_col]
- ]
-
-# create the form and show it without the plot
-window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, grab_anywhere=False, finalize=True)
-figure_agg = None
-# The GUI Event Loop
-while True:
- event, values = window.read()
- # print(event, values) # helps greatly when debugging
- if event in (sg.WIN_CLOSED, 'Exit'): # if user closed window or clicked Exit button
- break
- for i, choice in enumerate(values['-LISTBOX-']):
- func = fig_dict[choice] # get function to call from the dictionary
- fig = func() # call function to get the figure
- image = figure_to_image(fig)
- image = convert_to_bytes(image, (figure_w, figure_h))
- image = convert_to_bytes(image, (figure_w, figure_h))
- window[(i%4, i//4)].update(data=image)
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem.py b/DemoPrograms/Demo_Matplotlib_Image_Elem.py
deleted file mode 100644
index 9f5977640..000000000
--- a/DemoPrograms/Demo_Matplotlib_Image_Elem.py
+++ /dev/null
@@ -1,138 +0,0 @@
-import PySimpleGUI as sg
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.pyplot as plt
-import io
-
-"""
- Demo_Matplotlib_Image_Elem Demo
-
- Demo to show
- * How to use an Image element to show a Matplotlib figure
- * How to draw a Spectrogram
- * Hide the Image when a figure isn't present (shrinks the window automatically)
-
- The example graph can be found in the matplotlib gallery:
- https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# .d88888b dP dP
-# 88. "' 88 88
-# `Y88888b. d8888P .d8888b. 88d888b. d8888P
-# `8b 88 88' `88 88' `88 88
-# d8' .8P 88 88. .88 88 88
-# Y88888P dP `88888P8 dP dP
-# oooooooooooooooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-def your_matplotlib_code():
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- dt = 0.0005
- t = np.arange(0.0, 20.0, dt)
- s1 = np.sin(2 * np.pi * 100 * t)
- s2 = 2 * np.sin(2 * np.pi * 400 * t)
-
- # create a transient "chirp"
- s2[t <= 10] = s2[12 <= t] = 0
-
- # add some noise into the mix
- nse = 0.01 * np.random.random(size=len(t))
-
- x = s1 + s2 + nse # the signal
- NFFT = 1024 # the length of the windowing segments
- Fs = int(1.0 / dt) # the sampling frequency
-
- fig, (ax1, ax2) = plt.subplots(nrows=2)
- ax1.plot(t, x)
- Pxx, freqs, bins, im = ax2.specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900)
-
- return fig
-
-
-# 88888888b dP
-# 88 88
-# 88aaaa 88d888b. .d888b88
-# 88 88' `88 88' `88
-# 88 88 88 88. .88
-# 88888888P dP dP `88888P8
-# ooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
-
-
-# dP dP dP
-# 88 88 88
-# 88aaaaa88a .d8888b. 88 88d888b. .d8888b. 88d888b.
-# 88 88 88ooood8 88 88' `88 88ooood8 88' `88
-# 88 88 88. ... 88 88. .88 88. ... 88
-# dP dP `88888P' dP 88Y888P' `88888P' dP
-# ooooooooooooooooooooooo~88~oooooooooooooooooooooooo function starts below
-# dP
-
-def draw_figure(element, figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is not None:
- buf.seek(0)
- element.update(data=buf.read())
- return canv
- else:
- return None
-
-
-
-# .88888. dP dP dP
-# d8' `88 88 88 88
-# 88 88 88 88
-# 88 YP88 88 88 88
-# Y8. .88 Y8. .8P 88
-# `88888' `Y88888P' dP
-# ooooooooooooooooooooooo
-
-
-def main():
- # define the window layout
- layout = [[sg.Text('Spectrogram test')],
- [sg.pin(sg.Image(key='-IMAGE-'))],
- [sg.Button('Ok'), sg.B('Clear')]]
-
- # create the form and show it without the plot
- window = sg.Window('Spectrogram', layout, element_justification='c', font='Helvetica 14')
-
- while True:
- # add the plot to the window
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- elif event == 'Ok':
- draw_figure(window['-IMAGE-'], your_matplotlib_code())
- window['-IMAGE-'].update(visible=True)
- elif event == 'Clear':
- plt.close('all') # close all plots
- window['-IMAGE-'].update() # clears the image
- window['-IMAGE-'].update(visible=False) # hides the blank image
-
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py
deleted file mode 100644
index 3d1e8effa..000000000
--- a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated.py
+++ /dev/null
@@ -1,156 +0,0 @@
-import PySimpleGUI as sg
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.pyplot as plt
-import io
-import time
-
-"""
- Demo_Matplotlib_Image_Elem_Spetrogram_Animated Demo
-
- Demo to show
- * How to use an Image element to show a Matplotlib figure
- * How to draw a Spectrogram
- * How to animate the drawing by simply erasing and drawing the entire figure
-
- The point here is to keep things simple to enable you to get started.
-
- The example static graph can be found in the matplotlib gallery:
- https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-np.random.seed(19801)
-
-# .d88888b dP dP
-# 88. "' 88 88
-# `Y88888b. d8888P .d8888b. 88d888b. d8888P
-# `8b 88 88' `88 88' `88 88
-# d8' .8P 88 88. .88 88 88
-# Y88888P dP `88888P8 dP dP
-# oooooooooooooooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-def your_matplotlib_code():
- # The animated part of this is the t_lower, t_upper terms as well as the entire dataset that's graphed.
- # An entirely new graph is created from scratch every time... implying here that optimization is possible.
- if not hasattr(your_matplotlib_code, 't_lower'):
- your_matplotlib_code.t_lower = 10
- your_matplotlib_code.t_upper = 12
- else:
- your_matplotlib_code.t_lower = (your_matplotlib_code.t_lower + .5) % 18
- your_matplotlib_code.t_upper = (your_matplotlib_code.t_upper + .5) % 18
-
- dt = 0.0005
- t = np.arange(0.0, 20.0, dt)
- s1 = np.sin(2 * np.pi * 100 * t)
- s2 = 2 * np.sin(2 * np.pi * 400 * t)
-
- # create a transient "chirp"
- # s2[t <= 5] = s2[15 <= t] = 0 # original line of code (not animated)
- # If running the animation, use the t_lower and t_upper values
- s2[t <= your_matplotlib_code.t_lower] = s2[your_matplotlib_code.t_upper <= t] = 0
-
- # add some noise into the mix
- nse = 0.01 * np.random.random(size=len(t))
-
- x = s1 + s2 + nse # the signal
- NFFT = 1024 # the length of the windowing segments
- Fs = int(1.0 / dt) # the sampling frequency
-
- fig, (ax2) = plt.subplots(nrows=1)
- # ax1.plot(t, x)
- Pxx, freqs, bins, im = ax2.specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900)
-
- return fig
-
-
-# 88888888b dP
-# 88 88
-# 88aaaa 88d888b. .d888b88
-# 88 88' `88 88' `88
-# 88 88 88 88. .88
-# 88888888P dP dP `88888P8
-# ooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
-
-
-# dP dP dP
-# 88 88 88
-# 88aaaaa88a .d8888b. 88 88d888b. .d8888b. 88d888b.
-# 88 88 88ooood8 88 88' `88 88ooood8 88' `88
-# 88 88 88. ... 88 88. .88 88. ... 88
-# dP dP `88888P' dP 88Y888P' `88888P' dP
-# ooooooooooooooooooooooo~88~oooooooooooooooooooooooo function starts here
-# dP
-
-def draw_figure(element, figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is not None:
- buf.seek(0)
- element.update(data=buf.read())
- return canv
- else:
- return None
-
-
-# .88888. dP dP dP
-# d8' `88 88 88 88
-# 88 88 88 88
-# 88 YP88 88 88 88
-# Y8. .88 Y8. .8P 88
-# `88888' `Y88888P' dP
-# ooooooooooooooooooooooo
-
-
-def main():
- # define the window layout
- layout = [[sg.Text('Spectrogram Animated - Not Threaded', font='Helvetica 24')],
- [sg.pin(sg.Image(key='-IMAGE-'))],
- [sg.T(size=(50, 1), k='-STATS-')],
- [sg.B('Animate', focus=True, k='-ANIMATE-')]]
-
- # create the form and show it without the plot
- window = sg.Window('Animated Spectrogram', layout, element_justification='c', font='Helvetica 14')
-
- counter = delta = start_time = 0
- timeout = None
- while True:
- event, values = window.read(timeout=timeout)
- if event == sg.WIN_CLOSED:
- break
- sg.timer_start()
- if event == '-ANIMATE-':
- timeout = 0
- window['-IMAGE-'].update(visible=True)
- start_time = time.time()
- elif event == sg.TIMEOUT_EVENT:
- plt.close('all') # close all plots
- window['-IMAGE-'].update() # clears the image
- draw_figure(window['-IMAGE-'], your_matplotlib_code())
- seconds_elapsed = int(time.time() - start_time)
- fps = counter/seconds_elapsed if seconds_elapsed != 0 else 1.0
- window['-STATS-'].update(f'Frame {counter} Write Time {delta} FPS = {fps:2.2} seconds = {seconds_elapsed}')
- counter += 1
- delta = sg.timer_stop()
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py b/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py
deleted file mode 100644
index 1a7865bb8..000000000
--- a/DemoPrograms/Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded.py
+++ /dev/null
@@ -1,177 +0,0 @@
-import PySimpleGUI as sg
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.pyplot as plt
-import io
-import time
-
-"""
- Demo_Matplotlib_Image_Elem_Spetrogram_Animated_Threaded Demo
-
- Demo to show
- * How to use an Image element to show a Matplotlib figure
- * How to draw a Spectrogram
- * How to animate the drawing by simply erasing and drawing the entire figure
- * How to communicate between a thread and the GUI
-
- The point here is to keep things simple to enable you to get started.
-
- NOTE:
- This threaded technique with matplotlib hasn't been thoroughly tested.
- There may be resource leaks for example. Have run for several hundred seconds
- without problems so it's perhaps safe as written.
-
- The example static graph can be found in the matplotlib gallery:
- https://matplotlib.org/stable/gallery/images_contours_and_fields/specgram_demo.html
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-np.random.seed(19801)
-
-
-# .d88888b dP dP
-# 88. "' 88 88
-# `Y88888b. d8888P .d8888b. 88d888b. d8888P
-# `8b 88 88' `88 88' `88 88
-# d8' .8P 88 88. .88 88 88
-# Y88888P dP `88888P8 dP dP
-# oooooooooooooooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-def the_thread(window: sg.Window):
- """
- The thread that communicates with the application through the window's events.
-
- Because the figure creation time is greater than the GUI drawing time, it's safe
- to send a non-regulated stream of events without fear of overrunning the communication queue
- """
- while True:
- fig = your_matplotlib_code()
- buf = draw_figure(fig)
- window.write_event_value('-THREAD-', buf) # Data sent is a tuple of thread name and counter
-
-
-def your_matplotlib_code():
- # The animated part of this is the t_lower, t_upper terms as well as the entire dataset that's graphed.
- # An entirely new graph is created from scratch every time... implying here that optimization is possible.
- if not hasattr(your_matplotlib_code, 't_lower'):
- your_matplotlib_code.t_lower = 10
- your_matplotlib_code.t_upper = 12
- else:
- your_matplotlib_code.t_lower = (your_matplotlib_code.t_lower + .5) % 18
- your_matplotlib_code.t_upper = (your_matplotlib_code.t_upper + .5) % 18
-
- dt = 0.0005
- t = np.arange(0.0, 20.0, dt)
- s1 = np.sin(2 * np.pi * 100 * t)
- s2 = 2 * np.sin(2 * np.pi * 400 * t)
-
- # create a transient "chirp"
- # s2[t <= 5] = s2[15 <= t] = 0 # original line of code (not animated)
- # If running the animation, use the t_lower and t_upper values
- s2[t <= your_matplotlib_code.t_lower] = s2[your_matplotlib_code.t_upper <= t] = 0
-
- # add some noise into the mix
- nse = 0.01 * np.random.random(size=len(t))
-
- x = s1 + s2 + nse # the signal
- NFFT = 1024 # the length of the windowing segments
- Fs = int(1.0 / dt) # the sampling frequency
-
- fig, (ax2) = plt.subplots(nrows=1)
- # ax1.plot(t, x)
- Pxx, freqs, bins, im = ax2.specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900)
-
- return fig
-
-
-# 88888888b dP
-# 88 88
-# 88aaaa 88d888b. .d888b88
-# 88 88' `88 88' `88
-# 88 88 88 88. .88
-# 88888888P dP dP `88888P8
-# ooooooooooooooooooooooooooooo of your Matplotlib code
-
-
-# ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
-
-
-# dP dP dP
-# 88 88 88
-# 88aaaaa88a .d8888b. 88 88d888b. .d8888b. 88d888b.
-# 88 88 88ooood8 88 88' `88 88ooood8 88' `88
-# 88 88 88. ... 88 88. .88 88. ... 88
-# dP dP `88888P' dP 88Y888P' `88888P' dP
-# ooooooooooooooooooooooo~88~oooooooooooooooooooooooo function starts here
-# dP
-
-def draw_figure(figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param figure: a Matplotlib figure
- :return: BytesIO object
- """
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is not None:
- buf.seek(0)
- # element.update(data=buf.read())
- return buf
- else:
- return None
-
-
-# .88888. dP dP dP
-# d8' `88 88 88 88
-# 88 88 88 88
-# 88 YP88 88 88 88
-# Y8. .88 Y8. .8P 88
-# `88888' `Y88888P' dP
-# ooooooooooooooooooooooo
-
-
-def main():
- # define the window layout
- layout = [[sg.Text('Spectrogram Animated - Threaded', font='Helvetica 24')],
- [sg.pin(sg.Image(key='-IMAGE-'))],
- [sg.T(k='-STATS-')],
- [sg.B('Animate', focus=True, k='-ANIMATE-')]]
-
- # create the form and show it without the plot
- window = sg.Window('Animated Spectrogram', layout, element_justification='c', font='Helvetica 14')
-
- counter = start_time = delta = 0
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- sg.timer_start()
- if event == '-ANIMATE-':
- window['-IMAGE-'].update(visible=True)
- start_time = time.time()
- window.start_thread(lambda: the_thread(window), '-THEAD FINISHED-')
- elif event == '-THREAD-':
- plt.close('all') # close all plots... unclear if this is required
- window['-IMAGE-'].update(data=values[event].read())
- counter += 1
- seconds_elapsed = int(time.time() - start_time)
- fps = counter / seconds_elapsed if seconds_elapsed != 0 else 1.0
- window['-STATS-'].update(f'Frame {counter} Write Time {delta} FPS = {fps:2.2} seconds = {seconds_elapsed}')
- delta = sg.timer_stop()
-
- window.close()
-
-
-if __name__ == '__main__':
- # Newer versions of PySimpleGUI have an alias for this method that's called "start_thread" so that it's clearer what's happening
- # In case you don't have that version installed this line of code creates the alias for you
- sg.Window.start_thread = sg.Window.perform_long_operation
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Matplotlib_Ping_Graph.py b/DemoPrograms/Demo_Matplotlib_Ping_Graph.py
new file mode 100644
index 000000000..457464c9f
--- /dev/null
+++ b/DemoPrograms/Demo_Matplotlib_Ping_Graph.py
@@ -0,0 +1,673 @@
+#!/usr/bin/env python
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import matplotlib.pyplot as plt
+import PySimpleGUI as sg
+import tkinter as tk
+
+"""
+A graph of time to ping Google.com
+Demonstrates Matploylib used in an animated way.
+
+Note this file contains a copy of ping.py. It is contained in the first part of this file
+
+"""
+
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+# =============================================================================#
+import argparse
+import os, sys, socket, struct, select, time, signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+# =============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+
+# =============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string) / 2)) * 2
+ sum = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum = sum + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum = sum + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string) - 1]
+ try: # For Python3
+ sum += loByte
+ except: # For Python2
+ sum += ord(loByte)
+
+ sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
+ sum += (sum >> 16) # Add carry from above (if any)
+ answer = ~sum & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+
+# =============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime - sentTime) * 1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+
+# =============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ # destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size - 8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ # data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ mySocket.sendto(packet, (destIP, 1)) # Port number is irrelevant for ICMP
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+
+# =============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout / 1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ # print (len(recPacket.encode()))
+ return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+
+# =============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd) / myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+
+# =============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+
+# =============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" % (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ dump_stats(myStats)
+
+#=============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return 0,0,0,0
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent - myStats.pktsRcvd)/myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+# =============================================================================#
+
+
+
+#================================================================================
+# Globals
+# These are needed because callback functions are used.
+# Need to retain state across calls
+#================================================================================
+SIZE=(320,240)
+
+class MyGlobals:
+ axis_pings = None
+ ping_x_array = []
+ ping_y_array = []
+
+g_my_globals = MyGlobals()
+
+#================================================================================
+# Performs *** PING! ***
+#================================================================================
+def run_a_ping_and_graph():
+ global g_my_globals # graphs are global so that can be retained across multiple calls to this callback
+
+ #===================== Do the ping =====================#
+ response = quiet_ping('google.com',timeout=1000)
+ if response[0] == 0:
+ ping_time = 1000
+ else:
+ ping_time = response[0]
+ #===================== Store current ping in historical array =====================#
+ g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array))
+ g_my_globals.ping_y_array.append(ping_time)
+ # ===================== Only graph last 100 items =====================#
+ if len(g_my_globals.ping_x_array) > 100:
+ x_array = g_my_globals.ping_x_array[-100:]
+ y_array = g_my_globals.ping_y_array[-100:]
+ else:
+ x_array = g_my_globals.ping_x_array
+ y_array = g_my_globals.ping_y_array
+
+ # ===================== Call graphinc functions =====================#
+ g_my_globals.axis_ping.clear() # clear before graphing
+ set_chart_labels()
+ g_my_globals.axis_ping.plot(x_array,y_array) # graph the ping values
+
+#================================================================================
+# Function: Set graph titles and Axis labels
+# Sets the text for the subplots
+# Have to do this in 2 places... initially when creating and when updating
+# So, putting into a function so don't have to duplicate code
+#================================================================================
+def set_chart_labels():
+ global g_my_globals
+
+ g_my_globals.axis_ping.set_xlabel('Time', fontsize=8)
+ g_my_globals.axis_ping.set_ylabel('Ping (ms)', fontsize=8)
+ g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize = 8)
+
+def draw(fig, canvas):
+ # Magic code that draws the figure onto the Canvas Element's canvas
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(SIZE[0] / 2, SIZE[1] / 2, image=photo)
+ figure_canvas_agg = FigureCanvasAgg(fig)
+ figure_canvas_agg.draw()
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+#================================================================================
+# Function: MAIN
+#================================================================================
+def main():
+ global g_my_globals
+
+ # define the form layout
+ layout = [
+ [ sg.Canvas(size=SIZE, background_color='white',key='canvas'),
+ sg.Button('Exit', pad=(0, (210, 0)))]
+ ]
+
+ # create the form and show it without the plot
+ window = sg.Window('Ping Graph', layout, background_color='white', grab_anywhere=True, finalize=True)
+
+ canvas_elem = window['canvas']
+ canvas = canvas_elem.TKCanvas
+
+ fig = plt.figure(figsize=(3.1, 2.25), tight_layout={'pad':0})
+ g_my_globals.axis_ping = fig.add_subplot(1,1,1)
+ plt.rcParams['xtick.labelsize'] = 8
+ plt.rcParams['ytick.labelsize'] = 8
+ set_chart_labels()
+ plt.tight_layout()
+
+ while True:
+ event, values = window.read(timeout=0)
+ if event in ('Exit', None):
+ break
+
+ run_a_ping_and_graph()
+ photo = draw(fig, canvas)
+
+ window.close()
+
+if __name__ == '__main__':
+ main()
diff --git a/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py b/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py
index 9d894e2a3..c1f85fa77 100644
--- a/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py
+++ b/DemoPrograms/Demo_Matplotlib_Ping_Graph_Large.py
@@ -1,21 +1,10 @@
#!/usr/bin/env python
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
import matplotlib.pyplot as plt
import PySimpleGUI as sg
-import io
-import random
-import time
-import ping3
-
-"""
- Shows ping time to google.com using Matplotlib and ping3 module.
-
- Note that you will need to pip install ping3 for this demo program.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
+import tkinter as tk
+import ping
# ================================================================================
# Globals
@@ -37,13 +26,16 @@ class MyGlobals:
# ================================================================================
-def graph_a_ping(ping_time):
+def run_a_ping_and_graph():
# graphs are global so that can be retained across multiple calls to this callback
global g_my_globals
#===================== Do the ping =====================#
- # Insert your code to run a ping
- # ping_time = random.randint(0, 100)
+ response = ping.quiet_ping('google.com', timeout=1000)
+ if response[0] == 0:
+ ping_time = 1000
+ else:
+ ping_time = response[0]
#===================== Store current ping in historical array =====================#
g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array))
g_my_globals.ping_y_array.append(ping_time)
@@ -69,14 +61,6 @@ def graph_a_ping(ping_time):
# ================================================================================
-def ping_thread(window: sg.Window):
- while True:
- # time.sleep(.1)
- # ping_time = random.randint(0, 100)
- ping_time = ping3.ping('google.com')
- window.write_event_value('-THREAD-', ping_time)
-
-
def set_chart_labels():
global g_my_globals
@@ -85,25 +69,16 @@ def set_chart_labels():
g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize=12)
-def draw(element, figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
- # plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is not None:
- buf.seek(0)
- element.update(data=buf.read())
- return canv
- else:
- return None
+def draw(fig, canvas):
+ # Magic code that draws the figure onto the Canvas Element's canvas
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(640 / 2, 480 / 2, image=photo)
+ figure_canvas_agg = FigureCanvasAgg(fig)
+ figure_canvas_agg.draw()
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
# ================================================================================
# Function: MAIN
@@ -116,28 +91,28 @@ def main():
# define the form layout
layout = [[sg.Text('Animated Ping', size=(40, 1),
justification='center', font='Helvetica 20')],
- [sg.Image(size=(640, 480), key='-IMAGE-')],
+ [sg.Canvas(size=(640, 480), key='canvas')],
[sg.Button('Exit', size=(10, 2), pad=((280, 0), 3), font='Helvetica 14')]]
# create the form and show it without the plot
window = sg.Window(
'Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
- image_elem = window['-IMAGE-']
+ canvas_elem = window['canvas']
+ canvas = canvas_elem.TKCanvas
fig = plt.figure()
g_my_globals.axis_ping = fig.add_subplot(1, 1, 1)
set_chart_labels()
plt.tight_layout()
- window.start_thread(lambda: ping_thread(window))
+
while True:
event, values = window.read(timeout=0)
if event in ('Exit', None):
break
- if event == '-THREAD-':
- graph_a_ping(values[event])
- draw(image_elem, fig)
+ run_a_ping_and_graph()
+ photo = draw(fig, canvas)
if __name__ == '__main__':
diff --git a/DemoPrograms/Demo_Matplotlib_PyLab.py b/DemoPrograms/Demo_Matplotlib_PyLab.py
deleted file mode 100644
index 7ad2117cc..000000000
--- a/DemoPrograms/Demo_Matplotlib_PyLab.py
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/env python
-from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
-import PySimpleGUI as sg
-import matplotlib
-import pylab
-matplotlib.use('TkAgg')
-
-"""
-Demonstrates one way of embedding PyLab figures into a PySimpleGUI window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# ------------------------------- PASTE YOUR PYLAB CODE HERE -------------------------------
-from numpy import sin
-from numpy import cos
-
-x = pylab.linspace(-3, 3, 30)
-y = x**2
-pylab.plot(x, sin(x))
-pylab.plot(x, cos(x), 'r-')
-pylab.plot(x, -sin(x), 'g--')
-
-fig = pylab.gcf()
-figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
-
-# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
-
-# ------------------------------- Beginning of Matplotlib helper code -----------------------
-
-
-def draw_figure(canvas, figure, loc=(0, 0)):
- figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
- figure_canvas_agg.draw()
- figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
- return figure_canvas_agg
-# ------------------------------- Beginning of GUI CODE -------------------------------
-
-
-# define the window layout
-layout = [[sg.Text('Plot test', font='Any 18')],
- [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
- [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
-
-# create the form and show it without the plot
-window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
- layout, finalize=True)
-
-# add the plot to the window
-fig_canvas_agg = draw_figure(window['canvas'].TKCanvas, fig)
-
-event, values = window.read()
-
-window.close()
diff --git a/DemoPrograms/Demo_Matplotlib_Styles.py b/DemoPrograms/Demo_Matplotlib_Styles.py
deleted file mode 100644
index 8d17f5f21..000000000
--- a/DemoPrograms/Demo_Matplotlib_Styles.py
+++ /dev/null
@@ -1,232 +0,0 @@
-import PySimpleGUI as sg
-
-import numpy as np
-from matplotlib.backends.backend_tkagg import FigureCanvasAgg
-import matplotlib.figure
-import matplotlib.pyplot as plt
-import io
-
-from matplotlib import cm
-from mpl_toolkits.mplot3d.axes3d import get_test_data
-from matplotlib.ticker import NullFormatter # useful for `logit` scale
-
-"""
- Demo - Matplotlib Non-interactive Embedded with Theme and Style selection
-
- This demo is based on the Matplotlib "TEMPLATE" demo that is a general purpose, display-only
- demo as only the image of the plot is shown. None of the buttons and interactive parts
- of the MAtplotlib interface are included.
-
- This demo adds the ability to change the Window's "Theme" and the Matplotlib's "Style".
- It gives you a way to quickly see how well a theme is going to match a particular Matplotlib Style.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def create_axis_grid():
- from mpl_toolkits.axes_grid1.axes_rgb import RGBAxes
-
- plt.close('all')
-
- def get_demo_image():
- # prepare image
- delta = 0.5
-
- extent = (-3, 4, -4, 3)
- x = np.arange(-3.0, 4.001, delta)
- y = np.arange(-4.0, 3.001, delta)
- X, Y = np.meshgrid(x, y)
- Z1 = np.exp(-X ** 2 - Y ** 2)
- Z2 = np.exp(-(X - 1) ** 2 - (Y - 1) ** 2)
- Z = (Z1 - Z2) * 2
-
- return Z, extent
-
- def get_rgb():
- Z, extent = get_demo_image()
-
- Z[Z < 0] = 0.
- Z = Z / Z.max()
-
- R = Z[:13, :13]
- G = Z[2:, 2:]
- B = Z[:13, 2:]
-
- return R, G, B
-
- fig = plt.figure(1)
- ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8])
-
- r, g, b = get_rgb()
- kwargs = dict(origin="lower", interpolation="nearest")
- ax.imshow_rgb(r, g, b, **kwargs)
-
- ax.RGB.set_xlim(0., 9.5)
- ax.RGB.set_ylim(0.9, 10.6)
-
- plt.draw()
- return plt.gcf()
-
-
-def create_figure():
- # ------------------------------- START OF YOUR MATPLOTLIB CODE -------------------------------
- fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
- t = np.arange(0, 3, .01)
- fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
-
- return fig
-
-
-def create_subplot_3d():
- fig = plt.figure()
-
- ax = fig.add_subplot(1, 2, 1, projection='3d')
- X = np.arange(-5, 5, 0.25)
- Y = np.arange(-5, 5, 0.25)
- X, Y = np.meshgrid(X, Y)
- R = np.sqrt(X ** 2 + Y ** 2)
- Z = np.sin(R)
- surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet,
- linewidth=0, antialiased=False)
- ax.set_zlim3d(-1.01, 1.01)
-
- fig.colorbar(surf, shrink=0.5, aspect=5)
-
- ax = fig.add_subplot(1, 2, 2, projection='3d')
- X, Y, Z = get_test_data(0.05)
- ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
- return fig
-
-
-def create_pyplot_scales():
- plt.close('all')
- # Fixing random state for reproducibility
- np.random.seed(19680801)
-
- # make up some data in the interval ]0, 1[
- y = np.random.normal(loc=0.5, scale=0.4, size=1000)
- y = y[(y > 0) & (y < 1)]
- y.sort()
- x = np.arange(len(y))
-
- # plot with various axes scales
- plt.figure(1)
-
- # linear
- plt.subplot(221)
- plt.plot(x, y)
- plt.yscale('linear')
- plt.title('linear')
- plt.grid(True)
-
- # log
- plt.subplot(222)
- plt.plot(x, y)
- plt.yscale('log')
- plt.title('log')
- plt.grid(True)
-
- # symmetric log
- plt.subplot(223)
- plt.plot(x, y - y.mean())
- plt.yscale('symlog', linthreshy=0.01)
- plt.title('symlog')
- plt.grid(True)
-
- # logit
- plt.subplot(224)
- plt.plot(x, y)
- plt.yscale('logit')
- plt.title('logit')
- plt.grid(True)
- # Format the minor tick labels of the y-axis into empty strings with
- # `NullFormatter`, to avoid cumbering the axis with too many labels.
- plt.gca().yaxis.set_minor_formatter(NullFormatter())
- # Adjust the subplot layout, because the logit one may take more space
- # than usual, due to y-tick labels like "1 - 10^{-3}"
- plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
- wspace=0.35)
- return plt.gcf()
-
-
-# ----------------------------- The draw figure helpful function -----------------------------
-
-def draw_figure(element, figure):
- """
- Draws the previously created "figure" in the supplied Image Element
-
- :param element: an Image Element
- :param figure: a Matplotlib figure
- :return: The figure canvas
- """
-
- plt.close('all') # erases previously drawn plots
- canv = FigureCanvasAgg(figure)
- buf = io.BytesIO()
- canv.print_figure(buf, format='png')
- if buf is None:
- return None
- buf.seek(0)
- element.update(data=buf.read())
- return canv
-
-
-dictionary_of_figures = {'Axis Grid': create_axis_grid,
- 'Subplot 3D': create_subplot_3d,
- 'Scales': create_pyplot_scales,
- 'Basic Figure': create_figure}
-
-
-# ----------------------------- The GUI Section -----------------------------
-def create_window():
- """
- Defines the window's layout and creates the window object.
- This function is used so that the window's theme can be changed and the window "re-started".
-
- :return: The Window object
- :rtype: sg.Window
- """
-
- left_col = [[sg.T('Figures to Draw')],
- [sg.Listbox(list(dictionary_of_figures), default_values=[list(dictionary_of_figures)[0]], size=(15, 5), key='-LB-')],
- [sg.T('Matplotlib Styles')],
- [sg.Combo(plt.style.available, size=(15, 10), key='-STYLE-')],
- [sg.T('PySimpleGUI Themes')],
- [sg.Combo(sg.theme_list(), default_value=sg.theme(), size=(15, 10), key='-THEME-')]]
-
- layout = [[sg.T('Matplotlib Example', font='Any 20')],
- [sg.Col(left_col), sg.Image(key='-IMAGE-')],
- [sg.B('Draw'), sg.B('Exit')]]
-
- window = sg.Window('Matplotlib Embedded Template', layout, finalize=True)
-
- return window
-
-
-def main():
- window = create_window()
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == 'Exit' or event == sg.WIN_CLOSED:
- break
- if event == 'Draw':
- if values['-THEME-'] != sg.theme(): # if new theme chosen, create a new window
- window.close()
- sg.theme(values['-THEME-'])
- window = create_window()
- if values['-LB-']: # make sure something selected to draw
- func = dictionary_of_figures[values['-LB-'][0]]
- if values['-STYLE-']:
- plt.style.use(values['-STYLE-'])
- draw_figure(window['-IMAGE-'], func())
-
- window.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/DemoPrograms/Demo_Matplotlib_Two_Windows.py b/DemoPrograms/Demo_Matplotlib_Two_Windows.py
index 4768fb6e9..31a23972d 100644
--- a/DemoPrograms/Demo_Matplotlib_Two_Windows.py
+++ b/DemoPrograms/Demo_Matplotlib_Two_Windows.py
@@ -1,6 +1,4 @@
-from matplotlib import use
import PySimpleGUI as sg
-# import PySimpleGUIQt as sg; use('qt5agg')
import matplotlib.pyplot as plt
"""
@@ -8,26 +6,20 @@
A number of people have requested the ability to run a normal PySimpleGUI window that
launches a MatplotLib window that is interactive with the usual Matplotlib controls.
It turns out to be a rather simple thing to do. The secret is to add parameter block=False to plt.show()
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-def draw_plot():
- plt.plot([0.1, 0.2, 0.5, 0.7])
- plt.show(block=False)
layout = [[sg.Button('Plot'), sg.Cancel(), sg.Button('Popup')]]
-
window = sg.Window('Have some Matplotlib....', layout)
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Cancel'):
+ if event in (None, 'Cancel'):
break
elif event == 'Plot':
- draw_plot()
+ history = [0.1, 0.2, 0.5, 0.7]
+ plt.plot(history)
+ plt.show(block=False)
elif event == 'Popup':
sg.popup('Yes, your application is still running')
window.close()
diff --git a/DemoPrograms/Demo_Media_Player.py b/DemoPrograms/Demo_Media_Player.py
index 600891157..89814502f 100644
--- a/DemoPrograms/Demo_Media_Player.py
+++ b/DemoPrograms/Demo_Media_Player.py
@@ -1,12 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
#
# An Async Demonstration of a media player
# Uses button images for a super snazzy look
@@ -39,7 +33,7 @@ def ImageButton(title, key):
while True:
event, values = window.read(timeout=100)
- if event == 'Exit' or event == sg.WIN_CLOSED:
+ if event == 'Exit' or event is None:
break
# If a button was pressed, display it on the GUI by updating the text element
if event != sg.TIMEOUT_KEY:
diff --git a/DemoPrograms/Demo_Media_Player_VLC_Based.py b/DemoPrograms/Demo_Media_Player_VLC_Based.py
new file mode 100644
index 000000000..01817fd4b
--- /dev/null
+++ b/DemoPrograms/Demo_Media_Player_VLC_Based.py
@@ -0,0 +1,72 @@
+"""
+ Bare Bones Media Player Demo with Playlist. Adapeted from media player located at https://github.com/israel-dryer/Media-Player
+ Original Author : Israel Dryer
+ Modified to be a PySimpleGUI Demo Program
+ A very simple media player ready for you to customize. Uses the VLC player to playback local files and YouTube streams. You will need to install the Python bindings for VLC as well as the VLC player itself.
+ You will need to pip install:
+ pip install python-vlc
+ pip install youtube-dl
+"""
+import PySimpleGUI as sg
+import vlc
+from sys import platform as PLATFORM
+
+#------- GUI definition & setup --------#
+
+sg.change_look_and_feel('DarkBlue')
+
+def btn(name): # a PySimpleGUI "User Defined Element" (see docs)
+ return sg. Button(name, size=(6, 1), pad=(1, 1))
+
+layout = [[sg.Input(default_text='Video URL or Local Path:', size=(30, 1), key='-VIDEO_LOCATION-'), sg.Button('load')],
+ [sg.Image('', size=(300, 170), key='-VID_OUT-')],
+ [btn('previous'), btn('play'), btn('next'), btn('pause'), btn('stop')],
+ [sg.Text('Load media to start', key='-MESSAGE_AREA-')]]
+
+window = sg.Window('Mini Player', layout, element_justification='center', finalize=True)
+
+#------------ Media Player Setup ---------#
+
+inst = vlc.Instance()
+list_player = inst.media_list_player_new()
+media_list = inst.media_list_new([])
+list_player.set_media_list(media_list)
+player = list_player.get_media_player()
+if PLATFORM.startswith('linux'):
+ player.set_xwindow(window['-VID_OUT-'].Widget.winfo_id())
+else:
+ player.set_hwnd(window['-VID_OUT-'].Widget.winfo_id())
+
+#------------ The Event Loop ------------#
+while True:
+ event, values = window.read(timeout=1000) # run with a timeout so that current location can be updated
+ if event is None:
+ break
+
+ if event == 'play':
+ list_player.play()
+ if event == 'pause':
+ list_player.pause()
+ if event == 'stop':
+ list_player.stop()
+ if event == 'next':
+ list_player.next()
+ list_player.play()
+ if event == 'previous':
+ list_player.previous() # first call causes current video to start over
+ list_player.previous() # second call moves back 1 video from current
+ list_player.play()
+ if event == 'load':
+ if values['-VIDEO_LOCATION-'] and not 'Video URL' in values['-VIDEO_LOCATION-']:
+ media_list.add_media(values['-VIDEO_LOCATION-'])
+ list_player.set_media_list(media_list)
+ window['-VIDEO_LOCATION-'].update('Video URL or Local Path:') # only add a legit submit
+
+ # update elapsed time if there is a video loaded and the player is playing
+ if player.is_playing():
+ window['-MESSAGE_AREA-'].update("{:02d}:{:02d} / {:02d}:{:02d}".format(*divmod(player.get_time()//1000, 60),
+ *divmod(player.get_length()//1000, 60)))
+ else:
+ window['-MESSAGE_AREA-'].update('Load media to start' if media_list.count() == 0 else 'Ready to play media' )
+
+window.close()
diff --git a/DemoPrograms/Demo_Menu_With_Toolbar.py b/DemoPrograms/Demo_Menu_With_Toolbar.py
index e328c22c8..3ab552aac 100644
--- a/DemoPrograms/Demo_Menu_With_Toolbar.py
+++ b/DemoPrograms/Demo_Menu_With_Toolbar.py
@@ -2,12 +2,6 @@
import sys
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Usage of icons as base64 string and toolbar
house64 = 'data:image/png;base64,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'
diff --git a/DemoPrograms/Demo_Menubar_Custom.py b/DemoPrograms/Demo_Menubar_Custom.py
deleted file mode 100644
index c02a9a6df..000000000
--- a/DemoPrograms/Demo_Menubar_Custom.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-"""
- Demo - The MenubarCustom element
-
- With the addition of the Custom Titlebar came the addition of a problem with the
- os provided menubar. It's not possible to use the custom titlebar with the
- normal menubar. The menubar ends up being placed above the titlebar.
-
- Enter the MenubarCustom!
-
- This "Compound Element" is not really an element but rather a combination of
- ButtonMenu elements and Column elements. It's possible for users to create a similar
- construct. In fact, this element started as a Demo Program and then migrated into PySimpleGUI.
-
- At the moment, you cannot perform all of the same operations using this custom menubar
- that you can with a traditional menubar. Modifying the menu isn't possible yet. In
- other words, it's a great start, but more work is needed such as adding an update method, etc.
-
- For statically defined menus, it works great. Shortuts are possible within the menus, but not
- for the initial selection.
-
- You can use the same menu defition as the standard Menu element.
-
- The Menubar will tbe themed according to your current theme's colors. The theme's button
- colors are used. All of the colors can be changed from the menubar to the menu's text an background.
-
- The disabled color has a problem. The default tkinter gray is used even though PySimpleGUI sets the value.
- The color choice for the menubar background and text use the theme's button colors.
- You can change these color choices by changing the Menubar in the layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- sg.theme('dark green 7')
- # sg.theme('dark gray 13')
- sg.theme('dark red')
- # sg.theme('black')
-
- menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
- ['&Edit', ['Edit Me', 'Special', 'Normal',['Normal1', 'Normal2'] , 'Undo']],
- ['!Disabled', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo']],
- ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
- ['&Help', ['&About...']], ]
-
- layout = [[sg.MenubarCustom(menu_def, pad=(0,0), k='-CUST MENUBAR-')],
- [sg.Multiline(size=(70, 20), reroute_cprint=True, write_only=True, no_scrollbar=True, k='-MLINE-')]]
-
- window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True, keep_on_top=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
- # ------ Event Loop ------ #
- while True:
- event, values = window.read()
- # convert ButtonMenu event so they look like Menu events
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- sg.cprint(f'event = {event}', c=(sg.theme_background_color(), sg.theme_text_color()))
- sg.cprint(f'values = {values}',c=(sg.theme_input_text_color(), sg.theme_input_background_color()))
-
- # ------ Process menu choices ------ #
- if event == 'About...':
- window.disappear()
- sg.popup('About this program', 'Simulated Menubar to accompany a simulated Titlebar',
- 'PySimpleGUI Version', sg.get_versions(), grab_anywhere=True, keep_on_top=True)
- window.reappear()
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True)
- elif event.startswith('Open'):
- filename = sg.popup_get_file('file to open', no_window=True)
- print(filename)
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py b/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py
deleted file mode 100644
index 202f23b75..000000000
--- a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-"""
- Demo - A Custom Menubar Element Simulated Using ButtonMenu Elements
-
- Because a Menubar is created by the OS and not the underlying GUI framework, the
- ability to customize the look and feel of the standard Menubar is not possible.
-
- Additionally, the Titlebar Element and the Meny Element don't work well together.
- The order gets swapped.
-
- One way to get around all of the problems above is to simulate a Menu Element.
- That's exactly what this demo does.
-
- The color choice for the menubar background and text use the theme's button colors.
- You can change these color choices by changing the Menubar in the layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.MENU_SHORTCUT_CHARACTER = '&'
-
-def Menubar(menu_def, text_color, background_color, pad=(0, 0)):
- """
- A User Defined element that simulates a Menu element by using ButtonMenu elements
-
- :param menu_def: A standard PySimpleGUI menu definition
- :type menu_def: List[List[Tuple[str, List[str]]]
- :param text_color: color for the menubar's text
- :type text_color:
- :param background_color: color for the menubar's background
- :type background_color:
- :param pad: Amount of padding around each menu entry
- :type pad:
- :return: A column element that has a row of ButtonMenu buttons
- :rtype: sg.Column
- """
- row = []
- for menu in menu_def:
- text = menu[0]
- if sg.MENU_SHORTCUT_CHARACTER in text:
- text = text.replace(sg.MENU_SHORTCUT_CHARACTER, '')
- if text.startswith(sg.MENU_DISABLED_CHARACTER):
- disabled = True
- text = text[len(sg.MENU_DISABLED_CHARACTER):]
- else:
- disabled = False
- row += [sg.ButtonMenu(text, menu, border_width=0, button_color=f'{text_color} on {background_color}',key=text, pad=pad, disabled=disabled)]
-
- return sg.Column([row], background_color=background_color, pad=(0,0), expand_x=True)
-
-def main():
- sg.theme('dark green 7')
-
- menu_def = [['&File', ['&Open & Ctrl-O', '&Save & Ctrl-S', '&Properties', 'E&xit']],
- ['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
- ['!Disabled', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
- ['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
- ['&Help', ['&About...']], ]
-
- layout = [[Menubar(menu_def, sg.theme_button_color()[1], sg.theme_button_color()[0], (5, 0))],
- [sg.Text('This is the "Simulated" Titlebar and Menubar Window')],
- [sg.Checkbox('Checkbox 1', k='-C1W1-'), sg.Checkbox('Checkbox 2', k='-C2W1-')],
- [sg.Slider((0,100), orientation='h', size=(20,20), k='-S1-')],
- [sg.HorizontalSeparator()],
- [sg.Radio('Radio 1', 1, k='-R1W1-'), sg.Radio('Radio 2', 1, k='-R2W1-')],
- [sg.Ok(k='OK 1'), sg.Cancel(k='Cancel 1')],]
-
- layout2 = [[sg.Menu(menu_def, tearoff=False, key='-MENU BAR-')], # This is how a Menu is normally defined
- [sg.Text('This is the "Traditional" Titlebar and Menubar Window')],
- [sg.Checkbox('Checkbox 1', k='-C1W2-'), sg.Checkbox('Checkbox 2', k='-C2W2-')],
- [sg.Slider((0,100), orientation='h', size=(20,20), k='-S2-')],
- [sg.HorizontalSeparator()],
- [sg.Radio('Radio 1', 1, k='-R1W2-'), sg.Radio('Radio 2', 1, k='-R2W2-')],
- [sg.Ok(k='OK 2'), sg.Cancel(k='Cancel 2')],]
-
- layout3 = [[sg.Multiline(size=(70, 20), reroute_stdout=True, reroute_cprint=True, write_only=True)],]
-
- window = sg.Window("Custom Titlebar and Menu", layout, use_custom_titlebar=True, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
- win_loc = window.current_location()
-
- window2 = sg.Window("Traditional Titlebar and Menu", layout2, finalize=True, location=(win_loc[0]-window.size[0]-40, win_loc[1]), right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
- window3 = sg.Window("Output Window", layout3, finalize=True, location=(int(win_loc[0]-window.size[0]//1.5), int(win_loc[1]+window.size[1]+30)), use_custom_titlebar=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
-
- # ------ Event Loop ------ #
- while True:
- window, event, values = sg.read_all_windows()
- # convert ButtonMenu event so they look like Menu events
- elem = window.find_element(event, silent_on_error=True)
- if elem and elem.Type == sg.ELEM_TYPE_BUTTONMENU:
- event = values[event]
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, non_blocking=True)
-
- sg.cprint(f'event = {event}', c='white on red')
- sg.cprint(f'values = {values}', c='white on green')
-
- # ------ Process menu choices ------ #
- if event == 'About...':
- window.disappear()
- sg.popup('About this program', 'Simulated Menubar to accompany a simulated Titlebar',
- 'PySimpleGUI Version', sg.version, grab_anywhere=True, keep_on_top=True)
- window.reappear()
- elif event.startswith('Open'):
- filename = sg.popup_get_file('file to open', no_window=True)
- print(filename)
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Menus.py b/DemoPrograms/Demo_Menus.py
index d58b05be2..5d4b6ba85 100644
--- a/DemoPrograms/Demo_Menus.py
+++ b/DemoPrograms/Demo_Menus.py
@@ -1,15 +1,10 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-
"""
- Demo of Menu element, ButtonMenu element and right-click menus
-
- The same basic structure is used for all menus in PySimpleGUI.
- Each entry is a list of items to display. If any of those items is a list, then a cancade menu is added.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ Demonstration of MENUS!
+ How do menus work? Like buttons is how.
+ Check out the variable menu_def for a hint on how to
+ define menus
"""
@@ -25,44 +20,40 @@ def second_window():
def test_menus():
- sg.theme('LightGreen')
+ sg.change_look_and_feel('LightGreen')
sg.set_options(element_padding=(0, 0))
# ------ Menu Definition ------ #
- menu_def = [
- ['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
- ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo', 'Options::this_is_a_menu_key'], ],
+ menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit']],
+ ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ],
['&Toolbar', ['---', 'Command &1', 'Command &2',
'---', 'Command &3', 'Command &4']],
- ['&Help', ['&About...']]
- ]
-
- right_click_menu = ['Unused', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']]
+ ['&Help', '&About...'], ]
# ------ GUI Defintion ------ #
layout = [
- [sg.Menu(menu_def, tearoff=True, font='_ 12', key='-MENUBAR-')],
- [sg.Text('Right click me for a right click menu example')],
+ [sg.Menu(menu_def, tearoff=False, pad=(20, 1))],
[sg.Output(size=(60, 20))],
- [sg.ButtonMenu('ButtonMenu', right_click_menu, key='-BMENU-', text_color='red', disabled_text_color='green'), sg.Button('Plain Button')],
]
window = sg.Window("Windows-like program",
layout,
default_element_size=(12, 1),
- default_button_element_size=(12, 1),
- right_click_menu=right_click_menu)
+ auto_size_text=False,
+ auto_size_buttons=False,
+ default_button_element_size=(12, 1))
# ------ Loop & Process button menu choices ------ #
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- print(event, values)
+ if event in (None, 'Exit'):
+ return
+ print('Event = ', event)
# ------ Process menu choices ------ #
if event == 'About...':
window.disappear()
- sg.popup('About this program', 'Version 1.0', 'PySimpleGUI Version', sg.get_versions())
+ sg.popup('About this program', 'Version 1.0',
+ 'PySimpleGUI rocks...', grab_anywhere=True)
window.reappear()
elif event == 'Open':
filename = sg.popup_get_file('file to open', no_window=True)
diff --git a/DemoPrograms/Demo_Multi_Window_read_all_windows.py b/DemoPrograms/Demo_Multi_Window_read_all_windows.py
deleted file mode 100644
index 2de1ac814..000000000
--- a/DemoPrograms/Demo_Multi_Window_read_all_windows.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Read all windows example
- The input elements are shown as output on the other window when "Go" is pressed
- The checkboxes on window 1 are mirrored on window 2 if "mirror" checkbox is set
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-layout1 = [ [sg.Text('My Window')],
- [sg.Input(k='-IN-'), sg.Text(k='-OUT-')],
- [sg.CB('Check 1', k='-CB1-', enable_events=True), sg.CB('Check 2', k='-CB2-', enable_events=True), sg.CB('Mirror on Window 2', enable_events=True, k='-CB3-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-window1 = sg.Window('Window 1 Title', layout1, finalize=True, grab_anywhere=True, relative_location=(-600, 0))
-
-layout2 = [ [sg.Text('My Window')],
- [sg.Input(k='-IN-'), sg.Text(k='-OUT-')],
- [sg.CB('Check 1', k='-CB1-'), sg.CB('Check 2', k='-CB2-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-window2 = sg.Window('Window 2 Title', layout2, finalize=True, grab_anywhere=True)
-
-while True: # Event Loop
- window, event, values = sg.read_all_windows()
- if window is None:
- print('exiting because no windows are left')
- break
- print(window.Title, event, values) if window is not None else None
- if event == sg.WIN_CLOSED or event == 'Exit':
- window.close()
- if event == 'Go':
- # Output the input element to the other windwow
- try: # try to update the other window
- if window == window1:
- window2['-OUT-'].update(values['-IN-'])
- else:
- window1['-OUT-'].update(values['-IN-'])
- except:
- pass
- try:
- if window == window1 and values['-CB3-']:
- window2['-CB1-'].update(values['-CB1-'])
- window2['-CB2-'].update(values['-CB2-'])
- except:
- pass
diff --git a/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py b/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py
deleted file mode 100644
index 4643b5f6d..000000000
--- a/DemoPrograms/Demo_Multiline_Elem_Input_Justification.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
- Multline Element - Input Justification
-
- The justification of text for the Multiline element defaults to Left Justified
- Because of the way tkinter's widget works, setting the justification when creating the element
- is not enough to provide the correct justification.
-
- The demo shows you the technique to achieve justified input
-
- Key points:
- * Enable events on the multiline
- * Add 2 lines of code to your event loop
- * If get mline element event
- * Set the contents of the multline to be the correct justificaiton
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-def main():
- justification = 'l' # start left justified
-
- layout = [[sg.Text('Multiline Element Input Justification')],
- [sg.Multiline(size=(40,10), key='-MLINE-', justification=justification, enable_events=True, autoscroll=True)],
- # We'll be fancy and allow user to choose which justification to use in the demo
- [sg.Radio('Left', 0, True, k='-L-'), sg.Radio('Center', 0, k='-C-'),sg.Radio('Right', 0, k='-R-'),],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- window = sg.Window('Window Title', layout, keep_on_top=True, resizable=True, finalize=True)
-
- while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # Get desired justication from radio buttons. You don't need this if you know your justification already
- justification = 'l' if values['-L-'] else 'r' if values['-R-'] else 'c'
-
- # This is the important bit of code. It sets the current contents of the multiline to be the correct justification
- if event == '-MLINE-':
- window['-MLINE-'].update(values['-MLINE-'][:-1], justification=justification)
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multiline_Multicolored_Text.py b/DemoPrograms/Demo_Multiline_Multicolored_Text.py
deleted file mode 100644
index a0cea9ce2..000000000
--- a/DemoPrograms/Demo_Multiline_Multicolored_Text.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIQt as sg
-
-"""
- Demonstration of how to work with multiple colors and fonts when outputting text to a multiline element or with Debug Print
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-MLINE_KEY = '-MLINE-'
-
-layout = [ [sg.Text('Demonstration of Multiline Element\'s ability to show multiple colors ')],
- [sg.Multiline(size=(60,20), key=MLINE_KEY, reroute_cprint=True, write_only=True)],
- [sg.Input(k='-IN-')],
- [sg.B('Plain'), sg.Button('Text Blue Line'), sg.Button('Text Green Line')],
- [sg.Button('Background Blue Line'),sg.Button('Background Green Line'), sg.B('White on Green'), sg.B('Font Courier 12')] ]
-
-window = sg.Window('Demonstration of Multicolored Multline Text', layout)
-
-# print = lambda *args, **kwargs: window[MLINE_KEY].print(*args, **kwargs, text_color='red')
-mline:sg.Multiline = window[MLINE_KEY]
-while True:
- event, values = window.read() # type: (str, dict)
- print(event, values)
- sg.cprint(event, values, c='white on green', font='courier 12')
- sg.Print(event, c='white on green', font='courier 12', end='')
- sg.Print(values, c='white on red', font='Courier 12 underline italic bold', end='')
- sg.Print('')
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if 'Text Blue' in event:
- mline.update('This is blue text\n', text_color_for_value='blue', append=True)
- if 'Text Green' in event:
- mline.update('This is green text\n', text_color_for_value='green', append=True)
- if 'Background Blue' in event:
- mline.update('This is Blue Background\n', background_color_for_value='blue', append=True)
- if 'Background Green' in event:
- mline.update('This is Green Background\n', background_color_for_value='green', append=True)
- if 'Font' in event:
- mline.update('This is Green Background\n', background_color_for_value='green', append=True, font_for_value=('Courier', 12, 'underline'))
- mline.print('\nThis is Green Background\n', c='white on green', font='Courier 12 bold ')
- if 'White on Green' in event:
- mline.update('This is white text on a green background\n', text_color_for_value='white', background_color_for_value='green', append=True)
- if event == 'Plain':
- mline.update('This is plain text with no extra coloring\n', append=True)
-window.close()
diff --git a/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py b/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py
deleted file mode 100644
index aa6d259ba..000000000
--- a/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Adding a right click menu to perform multiline element common operations
-
- Sometimes Multiline Elements can benefit from a right click menu. There are no default menu
- that come with tkinter, so you'll need to create your own.
-
- Some common clipboard types of operations
- Select all
- Copy
- Paste
- Cut
-
- The underlying Widget is accessed several times in this code because setting selections,
- getting their values, and clipboard operations are not currently exposed in the APIs
-
- NOTE - With tkinter, if you use the built-in clipboard, you must keep your program
- running in order to access the clipboard. Upon exit, your clipboard will be deleted.
- You can get around this by using other clipboard packages.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-right_click_menu = ['', ['Copy', 'Paste', 'Select All', 'Cut']]
-MLINE_KEY = '-MLINE-'
-
-def do_clipboard_operation(event, window, element):
- if event == 'Select All':
- element.Widget.selection_clear()
- element.Widget.tag_add('sel', '1.0', 'end')
- elif event == 'Copy':
- try:
- text = element.Widget.selection_get()
- window.TKroot.clipboard_clear()
- window.TKroot.clipboard_append(text)
- except:
- print('Nothing selected')
- elif event == 'Paste':
- element.Widget.insert(sg.tk.INSERT, window.TKroot.clipboard_get())
- elif event == 'Cut':
- try:
- text = element.Widget.selection_get()
- window.TKroot.clipboard_clear()
- window.TKroot.clipboard_append(text)
- element.update('')
- except:
- print('Nothing selected')
-
-def main():
- layout = [ [sg.Text('Using a custom right click menu with Multiline Element')],
- [sg.Multiline(size=(60,20), key=MLINE_KEY, right_click_menu=right_click_menu)],
- [sg.B('Go'), sg.B('Exit')]]
-
- window = sg.Window('Right Click Menu Multiline', layout)
-
- mline:sg.Multiline = window[MLINE_KEY]
-
- while True:
- event, values = window.read() # type: (str, dict)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- # if event is a right click menu for the multiline, then handle the event in func
- if event in right_click_menu[1]:
- do_clipboard_operation(event, window, mline)
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Multiline_cprint_Printing.py b/DemoPrograms/Demo_Multiline_cprint_Printing.py
deleted file mode 100644
index 527d1a4c9..000000000
--- a/DemoPrograms/Demo_Multiline_cprint_Printing.py
+++ /dev/null
@@ -1,724 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - cprint usage
-
- "Print" to any Multiline Element in any of your windows.
-
- cprint in a really handy way to "print" to any multiline element in any one of your windows.
- There is an initial call - cprint_set_output_destination, where you set the output window and the key
- for the Multiline Element.
-
- There are FOUR different ways to indicate the color, from verbose to the most minimal are:
- 1. Specify text_color and background_color in the cprint call
- 2. Specify t, b paramters when calling cprint
- 3. Specify c/colors parameter a tuple with (text color, background color)
- 4. Specify c/colors parameter as a string "text on background" e.g. "white on red"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
-
-
- cprint = sg.cprint
-
- MLINE_KEY = '-ML-'+sg.WRITE_ONLY_KEY # multiline element's key. Indicate it's an output only element
- MLINE_KEY2 = '-ML2-'+sg.WRITE_ONLY_KEY # multiline element's key. Indicate it's an output only element
- MLINE_KEY3 = '-ML3-'+sg.WRITE_ONLY_KEY # multiline element's key. Indicate it's an output only element
-
- output_key = MLINE_KEY
-
- layout = [ [sg.Text('Multiline Color Print Demo', font='Any 18')],
- [sg.Multiline('Multiline\n', size=(80,20), key=MLINE_KEY)],
- [sg.Multiline('Multiline2\n', size=(80,20), key=MLINE_KEY2)],
- [sg.Text('Text color:'), sg.Combo(list(color_map.keys()), size=(12,20), key='-TEXT COLOR-'),
- sg.Text('on Background color:'), sg.Combo(list(color_map.keys()), size=(12,20), key='-BG COLOR-')],
- [sg.Input('Type text to output here', size=(80,1), key='-IN-')],
- [sg.Button('Print', bind_return_key=True), sg.Button('Print short'),
- sg.Button('Force 1'), sg.Button('Force 2'),
- sg.Button('Use Input for colors'), sg.Button('Toggle Output Location'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout)
-
- sg.cprint_set_output_destination(window, output_key)
-
- while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Print':
- sg.cprint(values['-IN-'], text_color=values['-TEXT COLOR-'], background_color=values['-BG COLOR-'])
- elif event == 'Print short':
- sg.cprint(values['-IN-'], c=(values['-TEXT COLOR-'], values['-BG COLOR-']))
- elif event.startswith('Use Input'):
- sg.cprint(values['-IN-'], colors=values['-IN-'])
- elif event.startswith('Toggle'):
- output_key = MLINE_KEY if output_key == MLINE_KEY2 else MLINE_KEY2
- sg.cprint_set_output_destination(window, output_key)
- sg.cprint('Switched to this output element', c='white on red')
- elif event == 'Force 1':
- sg.cprint(values['-IN-'], c=(values['-TEXT COLOR-'], values['-BG COLOR-']), key=MLINE_KEY)
- elif event == 'Force 2':
- sg.cprint(values['-IN-'], c=(values['-TEXT COLOR-'], values['-BG COLOR-']), key=MLINE_KEY2)
-
- window.close()
-
-
-if __name__ == '__main__':
- color_map = {
- 'alice blue': '#F0F8FF',
- 'AliceBlue': '#F0F8FF',
- 'antique white': '#FAEBD7',
- 'AntiqueWhite': '#FAEBD7',
- 'AntiqueWhite1': '#FFEFDB',
- 'AntiqueWhite2': '#EEDFCC',
- 'AntiqueWhite3': '#CDC0B0',
- 'AntiqueWhite4': '#8B8378',
- 'aquamarine': '#7FFFD4',
- 'aquamarine1': '#7FFFD4',
- 'aquamarine2': '#76EEC6',
- 'aquamarine3': '#66CDAA',
- 'aquamarine4': '#458B74',
- 'azure': '#F0FFFF',
- 'azure1': '#F0FFFF',
- 'azure2': '#E0EEEE',
- 'azure3': '#C1CDCD',
- 'azure4': '#838B8B',
- 'beige': '#F5F5DC',
- 'bisque': '#FFE4C4',
- 'bisque1': '#FFE4C4',
- 'bisque2': '#EED5B7',
- 'bisque3': '#CDB79E',
- 'bisque4': '#8B7D6B',
- 'black': '#000000',
- 'blanched almond': '#FFEBCD',
- 'BlanchedAlmond': '#FFEBCD',
- 'blue': '#0000FF',
- 'blue violet': '#8A2BE2',
- 'blue1': '#0000FF',
- 'blue2': '#0000EE',
- 'blue3': '#0000CD',
- 'blue4': '#00008B',
- 'BlueViolet': '#8A2BE2',
- 'brown': '#A52A2A',
- 'brown1': '#FF4040',
- 'brown2': '#EE3B3B',
- 'brown3': '#CD3333',
- 'brown4': '#8B2323',
- 'burlywood': '#DEB887',
- 'burlywood1': '#FFD39B',
- 'burlywood2': '#EEC591',
- 'burlywood3': '#CDAA7D',
- 'burlywood4': '#8B7355',
- 'cadet blue': '#5F9EA0',
- 'CadetBlue': '#5F9EA0',
- 'CadetBlue1': '#98F5FF',
- 'CadetBlue2': '#8EE5EE',
- 'CadetBlue3': '#7AC5CD',
- 'CadetBlue4': '#53868B',
- 'chartreuse': '#7FFF00',
- 'chartreuse1': '#7FFF00',
- 'chartreuse2': '#76EE00',
- 'chartreuse3': '#66CD00',
- 'chartreuse4': '#458B00',
- 'chocolate': '#D2691E',
- 'chocolate1': '#FF7F24',
- 'chocolate2': '#EE7621',
- 'chocolate3': '#CD661D',
- 'chocolate4': '#8B4513',
- 'coral': '#FF7F50',
- 'coral1': '#FF7256',
- 'coral2': '#EE6A50',
- 'coral3': '#CD5B45',
- 'coral4': '#8B3E2F',
- 'cornflower blue': '#6495ED',
- 'CornflowerBlue': '#6495ED',
- 'cornsilk': '#FFF8DC',
- 'cornsilk1': '#FFF8DC',
- 'cornsilk2': '#EEE8CD',
- 'cornsilk3': '#CDC8B1',
- 'cornsilk4': '#8B8878',
- 'cyan': '#00FFFF',
- 'cyan1': '#00FFFF',
- 'cyan2': '#00EEEE',
- 'cyan3': '#00CDCD',
- 'cyan4': '#008B8B',
- 'dark blue': '#00008B',
- 'dark cyan': '#008B8B',
- 'dark goldenrod': '#B8860B',
- 'dark gray': '#A9A9A9',
- 'dark green': '#006400',
- 'dark grey': '#A9A9A9',
- 'dark khaki': '#BDB76B',
- 'dark magenta': '#8B008B',
- 'dark olive green': '#556B2F',
- 'dark orange': '#FF8C00',
- 'dark orchid': '#9932CC',
- 'dark red': '#8B0000',
- 'dark salmon': '#E9967A',
- 'dark sea green': '#8FBC8F',
- 'dark slate blue': '#483D8B',
- 'dark slate gray': '#2F4F4F',
- 'dark slate grey': '#2F4F4F',
- 'dark turquoise': '#00CED1',
- 'dark violet': '#9400D3',
- 'DarkBlue': '#00008B',
- 'DarkCyan': '#008B8B',
- 'DarkGoldenrod': '#B8860B',
- 'DarkGoldenrod1': '#FFB90F',
- 'DarkGoldenrod2': '#EEAD0E',
- 'DarkGoldenrod3': '#CD950C',
- 'DarkGoldenrod4': '#8B6508',
- 'DarkGray': '#A9A9A9',
- 'DarkGreen': '#006400',
- 'DarkGrey': '#A9A9A9',
- 'DarkKhaki': '#BDB76B',
- 'DarkMagenta': '#8B008B',
- 'DarkOliveGreen': '#556B2F',
- 'DarkOliveGreen1': '#CAFF70',
- 'DarkOliveGreen2': '#BCEE68',
- 'DarkOliveGreen3': '#A2CD5A',
- 'DarkOliveGreen4': '#6E8B3D',
- 'DarkOrange': '#FF8C00',
- 'DarkOrange1': '#FF7F00',
- 'DarkOrange2': '#EE7600',
- 'DarkOrange3': '#CD6600',
- 'DarkOrange4': '#8B4500',
- 'DarkOrchid': '#9932CC',
- 'DarkOrchid1': '#BF3EFF',
- 'DarkOrchid2': '#B23AEE',
- 'DarkOrchid3': '#9A32CD',
- 'DarkOrchid4': '#68228B',
- 'DarkRed': '#8B0000',
- 'DarkSalmon': '#E9967A',
- 'DarkSeaGreen': '#8FBC8F',
- 'DarkSeaGreen1': '#C1FFC1',
- 'DarkSeaGreen2': '#B4EEB4',
- 'DarkSeaGreen3': '#9BCD9B',
- 'DarkSeaGreen4': '#698B69',
- 'DarkSlateBlue': '#483D8B',
- 'DarkSlateGray': '#2F4F4F',
- 'DarkSlateGray1': '#97FFFF',
- 'DarkSlateGray2': '#8DEEEE',
- 'DarkSlateGray3': '#79CDCD',
- 'DarkSlateGray4': '#528B8B',
- 'DarkSlateGrey': '#2F4F4F',
- 'DarkTurquoise': '#00CED1',
- 'DarkViolet': '#9400D3',
- 'deep pink': '#FF1493',
- 'deep sky blue': '#00BFFF',
- 'DeepPink': '#FF1493',
- 'DeepPink1': '#FF1493',
- 'DeepPink2': '#EE1289',
- 'DeepPink3': '#CD1076',
- 'DeepPink4': '#8B0A50',
- 'DeepSkyBlue': '#00BFFF',
- 'DeepSkyBlue1': '#00BFFF',
- 'DeepSkyBlue2': '#00B2EE',
- 'DeepSkyBlue3': '#009ACD',
- 'DeepSkyBlue4': '#00688B',
- 'dim gray': '#696969',
- 'dim grey': '#696969',
- 'DimGray': '#696969',
- 'DimGrey': '#696969',
- 'dodger blue': '#1E90FF',
- 'DodgerBlue': '#1E90FF',
- 'DodgerBlue1': '#1E90FF',
- 'DodgerBlue2': '#1C86EE',
- 'DodgerBlue3': '#1874CD',
- 'DodgerBlue4': '#104E8B',
- 'firebrick': '#B22222',
- 'firebrick1': '#FF3030',
- 'firebrick2': '#EE2C2C',
- 'firebrick3': '#CD2626',
- 'firebrick4': '#8B1A1A',
- 'floral white': '#FFFAF0',
- 'FloralWhite': '#FFFAF0',
- 'forest green': '#228B22',
- 'ForestGreen': '#228B22',
- 'gainsboro': '#DCDCDC',
- 'ghost white': '#F8F8FF',
- 'GhostWhite': '#F8F8FF',
- 'gold': '#FFD700',
- 'gold1': '#FFD700',
- 'gold2': '#EEC900',
- 'gold3': '#CDAD00',
- 'gold4': '#8B7500',
- 'goldenrod': '#DAA520',
- 'goldenrod1': '#FFC125',
- 'goldenrod2': '#EEB422',
- 'goldenrod3': '#CD9B1D',
- 'goldenrod4': '#8B6914',
- 'green': '#00FF00',
- 'green yellow': '#ADFF2F',
- 'green1': '#00FF00',
- 'green2': '#00EE00',
- 'green3': '#00CD00',
- 'green4': '#008B00',
- 'GreenYellow': '#ADFF2F',
- 'grey': '#BEBEBE',
- 'grey0': '#000000',
- 'grey1': '#030303',
- 'grey2': '#050505',
- 'grey3': '#080808',
- 'grey4': '#0A0A0A',
- 'grey5': '#0D0D0D',
- 'grey6': '#0F0F0F',
- 'grey7': '#121212',
- 'grey8': '#141414',
- 'grey9': '#171717',
- 'grey10': '#1A1A1A',
- 'grey11': '#1C1C1C',
- 'grey12': '#1F1F1F',
- 'grey13': '#212121',
- 'grey14': '#242424',
- 'grey15': '#262626',
- 'grey16': '#292929',
- 'grey17': '#2B2B2B',
- 'grey18': '#2E2E2E',
- 'grey19': '#303030',
- 'grey20': '#333333',
- 'grey21': '#363636',
- 'grey22': '#383838',
- 'grey23': '#3B3B3B',
- 'grey24': '#3D3D3D',
- 'grey25': '#404040',
- 'grey26': '#424242',
- 'grey27': '#454545',
- 'grey28': '#474747',
- 'grey29': '#4A4A4A',
- 'grey30': '#4D4D4D',
- 'grey31': '#4F4F4F',
- 'grey32': '#525252',
- 'grey33': '#545454',
- 'grey34': '#575757',
- 'grey35': '#595959',
- 'grey36': '#5C5C5C',
- 'grey37': '#5E5E5E',
- 'grey38': '#616161',
- 'grey39': '#636363',
- 'grey40': '#666666',
- 'grey41': '#696969',
- 'grey42': '#6B6B6B',
- 'grey43': '#6E6E6E',
- 'grey44': '#707070',
- 'grey45': '#737373',
- 'grey46': '#757575',
- 'grey47': '#787878',
- 'grey48': '#7A7A7A',
- 'grey49': '#7D7D7D',
- 'grey50': '#7F7F7F',
- 'grey51': '#828282',
- 'grey52': '#858585',
- 'grey53': '#878787',
- 'grey54': '#8A8A8A',
- 'grey55': '#8C8C8C',
- 'grey56': '#8F8F8F',
- 'grey57': '#919191',
- 'grey58': '#949494',
- 'grey59': '#969696',
- 'grey60': '#999999',
- 'grey61': '#9C9C9C',
- 'grey62': '#9E9E9E',
- 'grey63': '#A1A1A1',
- 'grey64': '#A3A3A3',
- 'grey65': '#A6A6A6',
- 'grey66': '#A8A8A8',
- 'grey67': '#ABABAB',
- 'grey68': '#ADADAD',
- 'grey69': '#B0B0B0',
- 'grey70': '#B3B3B3',
- 'grey71': '#B5B5B5',
- 'grey72': '#B8B8B8',
- 'grey73': '#BABABA',
- 'grey74': '#BDBDBD',
- 'grey75': '#BFBFBF',
- 'grey76': '#C2C2C2',
- 'grey77': '#C4C4C4',
- 'grey78': '#C7C7C7',
- 'grey79': '#C9C9C9',
- 'grey80': '#CCCCCC',
- 'grey81': '#CFCFCF',
- 'grey82': '#D1D1D1',
- 'grey83': '#D4D4D4',
- 'grey84': '#D6D6D6',
- 'grey85': '#D9D9D9',
- 'grey86': '#DBDBDB',
- 'grey87': '#DEDEDE',
- 'grey88': '#E0E0E0',
- 'grey89': '#E3E3E3',
- 'grey90': '#E5E5E5',
- 'grey91': '#E8E8E8',
- 'grey92': '#EBEBEB',
- 'grey93': '#EDEDED',
- 'grey94': '#F0F0F0',
- 'grey95': '#F2F2F2',
- 'grey96': '#F5F5F5',
- 'grey97': '#F7F7F7',
- 'grey98': '#FAFAFA',
- 'grey99': '#FCFCFC',
- 'grey100': '#FFFFFF',
- 'honeydew': '#F0FFF0',
- 'honeydew1': '#F0FFF0',
- 'honeydew2': '#E0EEE0',
- 'honeydew3': '#C1CDC1',
- 'honeydew4': '#838B83',
- 'hot pink': '#FF69B4',
- 'HotPink': '#FF69B4',
- 'HotPink1': '#FF6EB4',
- 'HotPink2': '#EE6AA7',
- 'HotPink3': '#CD6090',
- 'HotPink4': '#8B3A62',
- 'indian red': '#CD5C5C',
- 'IndianRed': '#CD5C5C',
- 'IndianRed1': '#FF6A6A',
- 'IndianRed2': '#EE6363',
- 'IndianRed3': '#CD5555',
- 'IndianRed4': '#8B3A3A',
- 'ivory': '#FFFFF0',
- 'ivory1': '#FFFFF0',
- 'ivory2': '#EEEEE0',
- 'ivory3': '#CDCDC1',
- 'ivory4': '#8B8B83',
- 'khaki': '#F0E68C',
- 'khaki1': '#FFF68F',
- 'khaki2': '#EEE685',
- 'khaki3': '#CDC673',
- 'khaki4': '#8B864E',
- 'lavender': '#E6E6FA',
- 'lavender blush': '#FFF0F5',
- 'LavenderBlush': '#FFF0F5',
- 'LavenderBlush1': '#FFF0F5',
- 'LavenderBlush2': '#EEE0E5',
- 'LavenderBlush3': '#CDC1C5',
- 'LavenderBlush4': '#8B8386',
- 'lawn green': '#7CFC00',
- 'LawnGreen': '#7CFC00',
- 'lemon chiffon': '#FFFACD',
- 'LemonChiffon': '#FFFACD',
- 'LemonChiffon1': '#FFFACD',
- 'LemonChiffon2': '#EEE9BF',
- 'LemonChiffon3': '#CDC9A5',
- 'LemonChiffon4': '#8B8970',
- 'light blue': '#ADD8E6',
- 'light coral': '#F08080',
- 'light cyan': '#E0FFFF',
- 'light goldenrod': '#EEDD82',
- 'light goldenrod yellow': '#FAFAD2',
- 'light gray': '#D3D3D3',
- 'light green': '#90EE90',
- 'light grey': '#D3D3D3',
- 'light pink': '#FFB6C1',
- 'light salmon': '#FFA07A',
- 'light sea green': '#20B2AA',
- 'light sky blue': '#87CEFA',
- 'light slate blue': '#8470FF',
- 'light slate gray': '#778899',
- 'light slate grey': '#778899',
- 'light steel blue': '#B0C4DE',
- 'light yellow': '#FFFFE0',
- 'LightBlue': '#ADD8E6',
- 'LightBlue1': '#BFEFFF',
- 'LightBlue2': '#B2DFEE',
- 'LightBlue3': '#9AC0CD',
- 'LightBlue4': '#68838B',
- 'LightCoral': '#F08080',
- 'LightCyan': '#E0FFFF',
- 'LightCyan1': '#E0FFFF',
- 'LightCyan2': '#D1EEEE',
- 'LightCyan3': '#B4CDCD',
- 'LightCyan4': '#7A8B8B',
- 'LightGoldenrod': '#EEDD82',
- 'LightGoldenrod1': '#FFEC8B',
- 'LightGoldenrod2': '#EEDC82',
- 'LightGoldenrod3': '#CDBE70',
- 'LightGoldenrod4': '#8B814C',
- 'LightGoldenrodYellow': '#FAFAD2',
- 'LightGray': '#D3D3D3',
- 'LightGreen': '#90EE90',
- 'LightGrey': '#D3D3D3',
- 'LightPink': '#FFB6C1',
- 'LightPink1': '#FFAEB9',
- 'LightPink2': '#EEA2AD',
- 'LightPink3': '#CD8C95',
- 'LightPink4': '#8B5F65',
- 'LightSalmon': '#FFA07A',
- 'LightSalmon1': '#FFA07A',
- 'LightSalmon2': '#EE9572',
- 'LightSalmon3': '#CD8162',
- 'LightSalmon4': '#8B5742',
- 'LightSeaGreen': '#20B2AA',
- 'LightSkyBlue': '#87CEFA',
- 'LightSkyBlue1': '#B0E2FF',
- 'LightSkyBlue2': '#A4D3EE',
- 'LightSkyBlue3': '#8DB6CD',
- 'LightSkyBlue4': '#607B8B',
- 'LightSlateBlue': '#8470FF',
- 'LightSlateGray': '#778899',
- 'LightSlateGrey': '#778899',
- 'LightSteelBlue': '#B0C4DE',
- 'LightSteelBlue1': '#CAE1FF',
- 'LightSteelBlue2': '#BCD2EE',
- 'LightSteelBlue3': '#A2B5CD',
- 'LightSteelBlue4': '#6E7B8B',
- 'LightYellow': '#FFFFE0',
- 'LightYellow1': '#FFFFE0',
- 'LightYellow2': '#EEEED1',
- 'LightYellow3': '#CDCDB4',
- 'LightYellow4': '#8B8B7A',
- 'lime green': '#32CD32',
- 'LimeGreen': '#32CD32',
- 'linen': '#FAF0E6',
- 'magenta': '#FF00FF',
- 'magenta1': '#FF00FF',
- 'magenta2': '#EE00EE',
- 'magenta3': '#CD00CD',
- 'magenta4': '#8B008B',
- 'maroon': '#B03060',
- 'maroon1': '#FF34B3',
- 'maroon2': '#EE30A7',
- 'maroon3': '#CD2990',
- 'maroon4': '#8B1C62',
- 'medium aquamarine': '#66CDAA',
- 'medium blue': '#0000CD',
- 'medium orchid': '#BA55D3',
- 'medium purple': '#9370DB',
- 'medium sea green': '#3CB371',
- 'medium slate blue': '#7B68EE',
- 'medium spring green': '#00FA9A',
- 'medium turquoise': '#48D1CC',
- 'medium violet red': '#C71585',
- 'MediumAquamarine': '#66CDAA',
- 'MediumBlue': '#0000CD',
- 'MediumOrchid': '#BA55D3',
- 'MediumOrchid1': '#E066FF',
- 'MediumOrchid2': '#D15FEE',
- 'MediumOrchid3': '#B452CD',
- 'MediumOrchid4': '#7A378B',
- 'MediumPurple': '#9370DB',
- 'MediumPurple1': '#AB82FF',
- 'MediumPurple2': '#9F79EE',
- 'MediumPurple3': '#8968CD',
- 'MediumPurple4': '#5D478B',
- 'MediumSeaGreen': '#3CB371',
- 'MediumSlateBlue': '#7B68EE',
- 'MediumSpringGreen': '#00FA9A',
- 'MediumTurquoise': '#48D1CC',
- 'MediumVioletRed': '#C71585',
- 'midnight blue': '#191970',
- 'MidnightBlue': '#191970',
- 'mint cream': '#F5FFFA',
- 'MintCream': '#F5FFFA',
- 'misty rose': '#FFE4E1',
- 'MistyRose': '#FFE4E1',
- 'MistyRose1': '#FFE4E1',
- 'MistyRose2': '#EED5D2',
- 'MistyRose3': '#CDB7B5',
- 'MistyRose4': '#8B7D7B',
- 'moccasin': '#FFE4B5',
- 'navajo white': '#FFDEAD',
- 'NavajoWhite': '#FFDEAD',
- 'NavajoWhite1': '#FFDEAD',
- 'NavajoWhite2': '#EECFA1',
- 'NavajoWhite3': '#CDB38B',
- 'NavajoWhite4': '#8B795E',
- 'navy': '#000080',
- 'navy blue': '#000080',
- 'NavyBlue': '#000080',
- 'old lace': '#FDF5E6',
- 'OldLace': '#FDF5E6',
- 'olive drab': '#6B8E23',
- 'OliveDrab': '#6B8E23',
- 'OliveDrab1': '#C0FF3E',
- 'OliveDrab2': '#B3EE3A',
- 'OliveDrab3': '#9ACD32',
- 'OliveDrab4': '#698B22',
- 'orange': '#FFA500',
- 'orange red': '#FF4500',
- 'orange1': '#FFA500',
- 'orange2': '#EE9A00',
- 'orange3': '#CD8500',
- 'orange4': '#8B5A00',
- 'OrangeRed': '#FF4500',
- 'OrangeRed1': '#FF4500',
- 'OrangeRed2': '#EE4000',
- 'OrangeRed3': '#CD3700',
- 'OrangeRed4': '#8B2500',
- 'orchid': '#DA70D6',
- 'orchid1': '#FF83FA',
- 'orchid2': '#EE7AE9',
- 'orchid3': '#CD69C9',
- 'orchid4': '#8B4789',
- 'pale goldenrod': '#EEE8AA',
- 'pale green': '#98FB98',
- 'pale turquoise': '#AFEEEE',
- 'pale violet red': '#DB7093',
- 'PaleGoldenrod': '#EEE8AA',
- 'PaleGreen': '#98FB98',
- 'PaleGreen1': '#9AFF9A',
- 'PaleGreen2': '#90EE90',
- 'PaleGreen3': '#7CCD7C',
- 'PaleGreen4': '#548B54',
- 'PaleTurquoise': '#AFEEEE',
- 'PaleTurquoise1': '#BBFFFF',
- 'PaleTurquoise2': '#AEEEEE',
- 'PaleTurquoise3': '#96CDCD',
- 'PaleTurquoise4': '#668B8B',
- 'PaleVioletRed': '#DB7093',
- 'PaleVioletRed1': '#FF82AB',
- 'PaleVioletRed2': '#EE799F',
- 'PaleVioletRed3': '#CD687F',
- 'PaleVioletRed4': '#8B475D',
- 'papaya whip': '#FFEFD5',
- 'PapayaWhip': '#FFEFD5',
- 'peach puff': '#FFDAB9',
- 'PeachPuff': '#FFDAB9',
- 'PeachPuff1': '#FFDAB9',
- 'PeachPuff2': '#EECBAD',
- 'PeachPuff3': '#CDAF95',
- 'PeachPuff4': '#8B7765',
- 'peru': '#CD853F',
- 'pink': '#FFC0CB',
- 'pink1': '#FFB5C5',
- 'pink2': '#EEA9B8',
- 'pink3': '#CD919E',
- 'pink4': '#8B636C',
- 'plum': '#DDA0DD',
- 'plum1': '#FFBBFF',
- 'plum2': '#EEAEEE',
- 'plum3': '#CD96CD',
- 'plum4': '#8B668B',
- 'powder blue': '#B0E0E6',
- 'PowderBlue': '#B0E0E6',
- 'purple': '#A020F0',
- 'purple1': '#9B30FF',
- 'purple2': '#912CEE',
- 'purple3': '#7D26CD',
- 'purple4': '#551A8B',
- 'red': '#FF0000',
- 'red1': '#FF0000',
- 'red2': '#EE0000',
- 'red3': '#CD0000',
- 'red4': '#8B0000',
- 'rosy brown': '#BC8F8F',
- 'RosyBrown': '#BC8F8F',
- 'RosyBrown1': '#FFC1C1',
- 'RosyBrown2': '#EEB4B4',
- 'RosyBrown3': '#CD9B9B',
- 'RosyBrown4': '#8B6969',
- 'royal blue': '#4169E1',
- 'RoyalBlue': '#4169E1',
- 'RoyalBlue1': '#4876FF',
- 'RoyalBlue2': '#436EEE',
- 'RoyalBlue3': '#3A5FCD',
- 'RoyalBlue4': '#27408B',
- 'saddle brown': '#8B4513',
- 'SaddleBrown': '#8B4513',
- 'salmon': '#FA8072',
- 'salmon1': '#FF8C69',
- 'salmon2': '#EE8262',
- 'salmon3': '#CD7054',
- 'salmon4': '#8B4C39',
- 'sandy brown': '#F4A460',
- 'SandyBrown': '#F4A460',
- 'sea green': '#2E8B57',
- 'SeaGreen': '#2E8B57',
- 'SeaGreen1': '#54FF9F',
- 'SeaGreen2': '#4EEE94',
- 'SeaGreen3': '#43CD80',
- 'SeaGreen4': '#2E8B57',
- 'seashell': '#FFF5EE',
- 'seashell1': '#FFF5EE',
- 'seashell2': '#EEE5DE',
- 'seashell3': '#CDC5BF',
- 'seashell4': '#8B8682',
- 'sienna': '#A0522D',
- 'sienna1': '#FF8247',
- 'sienna2': '#EE7942',
- 'sienna3': '#CD6839',
- 'sienna4': '#8B4726',
- 'sky blue': '#87CEEB',
- 'SkyBlue': '#87CEEB',
- 'SkyBlue1': '#87CEFF',
- 'SkyBlue2': '#7EC0EE',
- 'SkyBlue3': '#6CA6CD',
- 'SkyBlue4': '#4A708B',
- 'slate blue': '#6A5ACD',
- 'slate gray': '#708090',
- 'slate grey': '#708090',
- 'SlateBlue': '#6A5ACD',
- 'SlateBlue1': '#836FFF',
- 'SlateBlue2': '#7A67EE',
- 'SlateBlue3': '#6959CD',
- 'SlateBlue4': '#473C8B',
- 'SlateGray': '#708090',
- 'SlateGray1': '#C6E2FF',
- 'SlateGray2': '#B9D3EE',
- 'SlateGray3': '#9FB6CD',
- 'SlateGray4': '#6C7B8B',
- 'SlateGrey': '#708090',
- 'snow': '#FFFAFA',
- 'snow1': '#FFFAFA',
- 'snow2': '#EEE9E9',
- 'snow3': '#CDC9C9',
- 'snow4': '#8B8989',
- 'spring green': '#00FF7F',
- 'SpringGreen': '#00FF7F',
- 'SpringGreen1': '#00FF7F',
- 'SpringGreen2': '#00EE76',
- 'SpringGreen3': '#00CD66',
- 'SpringGreen4': '#008B45',
- 'steel blue': '#4682B4',
- 'SteelBlue': '#4682B4',
- 'SteelBlue1': '#63B8FF',
- 'SteelBlue2': '#5CACEE',
- 'SteelBlue3': '#4F94CD',
- 'SteelBlue4': '#36648B',
- 'tan': '#D2B48C',
- 'tan1': '#FFA54F',
- 'tan2': '#EE9A49',
- 'tan3': '#CD853F',
- 'tan4': '#8B5A2B',
- 'thistle': '#D8BFD8',
- 'thistle1': '#FFE1FF',
- 'thistle2': '#EED2EE',
- 'thistle3': '#CDB5CD',
- 'thistle4': '#8B7B8B',
- 'tomato': '#FF6347',
- 'tomato1': '#FF6347',
- 'tomato2': '#EE5C42',
- 'tomato3': '#CD4F39',
- 'tomato4': '#8B3626',
- 'turquoise': '#40E0D0',
- 'turquoise1': '#00F5FF',
- 'turquoise2': '#00E5EE',
- 'turquoise3': '#00C5CD',
- 'turquoise4': '#00868B',
- 'violet': '#EE82EE',
- 'violet red': '#D02090',
- 'VioletRed': '#D02090',
- 'VioletRed1': '#FF3E96',
- 'VioletRed2': '#EE3A8C',
- 'VioletRed3': '#CD3278',
- 'VioletRed4': '#8B2252',
- 'wheat': '#F5DEB3',
- 'wheat1': '#FFE7BA',
- 'wheat2': '#EED8AE',
- 'wheat3': '#CDBA96',
- 'wheat4': '#8B7E66',
- 'white': '#FFFFFF',
- 'white smoke': '#F5F5F5',
- 'WhiteSmoke': '#F5F5F5',
- 'yellow': '#FFFF00',
- 'yellow green': '#9ACD32',
- 'yellow1': '#FFFF00',
- 'yellow2': '#EEEE00',
- 'yellow3': '#CDCD00',
- 'yellow4': '#8B8B00',
- 'YellowGreen': '#9ACD32',
- }
- main()
-
diff --git a/DemoPrograms/Demo_Multiple_Windows_Experimental.py b/DemoPrograms/Demo_Multiple_Windows_Experimental.py
index be7d154a1..e8c20ca1c 100644
--- a/DemoPrograms/Demo_Multiple_Windows_Experimental.py
+++ b/DemoPrograms/Demo_Multiple_Windows_Experimental.py
@@ -3,10 +3,6 @@
'''
Parallel windows executing.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
layout1 = [[ sg.Text('Window 1') ],
@@ -32,19 +28,19 @@
while True: # Event Loop
event, values = window1.read(timeout=0)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
elif event != '__timeout__':
print(event, values)
event, values = window2.read(timeout=0)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
elif event != '__timeout__':
print(event, values)
event, values = window3.read(timeout=0)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
elif event != '__timeout__':
print(event, values)
diff --git a/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py b/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py
deleted file mode 100644
index e3ee35979..000000000
--- a/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-"""
- Demo - Multiple read_all_window(timeout=20)
- A 2-window event loop run in async mode
-
- Super-simple, 25 lines of code.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-sg.set_options(font='_ 18')
-
-window1 = sg.Window('ONE', [[sg.T('Window 1',size=(30,1),k='-T-')],[sg.B('Run', k='-B-'), sg.B('Exit')]],
- finalize=True)
-
-window2 = sg.Window('TWO', [[sg.T('Window 2',k='-T-')],[sg.B('Run', k='-B-'),sg.B('Exit')]], finalize=True,
- location=(window1.current_location()[0]-250,window1.current_location()[1]))
-
-i, paused = 0, [False, False]
-
-while True: # Event Loop
- window, event, values = sg.read_all_windows(timeout=10)
- print(window, event, values) if event != sg.TIMEOUT_EVENT else None
- if window == sg.WIN_CLOSED and event == sg.WIN_CLOSED:
- window1.close()
- window2.close()
- sg.popup_auto_close('Exiting...')
- break
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- window.close()
- if not paused[0]:
- window1['-T-'].update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100))
- if not paused[1]:
- window2['-T-'].update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100))
- if event == '-B-':
- paused[0 if window == window1 else 1] = not paused[0 if window == window1 else 1]
- window['-B-'].update('Run' if not paused[0 if window == window1 else 1] else 'Pause')
- i += 1
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py b/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py
deleted file mode 100644
index bb5ed4437..000000000
--- a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import subprocess
-import PySimpleGUI as sg
-import threading
-
-
-"""
- Demo - Run a shell command while displaying an animated GIF to inform the user the
- program is still running.
- If you have a GUI and you start a subprocess to run a shell command, the GUI essentually
- locks up and often the operation system will off to terminate the program for you.
-
- This demo fixes this situation by running the subprocess as a Thread. This enables
- the subproces to run async to the main program. The main program then simply runs a loop,
- waiting for the thread to complete running.
-
- The output from the subprocess is saved and displayed in a scrolled popup.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def process_thread():
- global proc
- proc = subprocess.run('pip list', shell=True, stdout=subprocess.PIPE)
-
-
-def main():
- thread = threading.Thread(target=process_thread, daemon=True)
- thread.start()
-
- while True:
- sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, 'Loading list of packages', time_between_frames=100)
- thread.join(timeout=.1)
- if not thread.is_alive():
- break
- sg.popup_animated(None)
-
- output = proc.__str__().replace('\\r\\n', '\n')
- sg.popup_scrolled(output, font='Courier 10')
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Multithreaded_Calling_Popup.py b/DemoPrograms/Demo_Multithreaded_Calling_Popup.py
deleted file mode 100644
index fb65ea6e9..000000000
--- a/DemoPrograms/Demo_Multithreaded_Calling_Popup.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import threading
-import time
-import PySimpleGUI as sg
-
-"""
- Threaded Demo - Uses Window.write_event_value to communicate from thread to GUI
-
- A demo specifically to show how to use write_event_value to
- "show a popup from a thread"
-
- You cannot make any direct calls into PySimpleGUI from a thread
- except for Window.write_event_value()
- Cuation - This method still has a risk of tkinter crashing
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def the_thread(window:sg.Window, seconds):
- """
- The thread that communicates with the application through the window's events.
-
- Wakes every X seconds that are provided by user in the main GUI:
- Sends an event to the main thread
- Goes back to sleep
- """
- i = 0
- while True:
- time.sleep(seconds)
- # send a message to the main GUI. It will be read using window.read()
- # the "Value" send is a tuple that contains all the things to show in the popup
- window.write_event_value('-POPUP-',
- ('Hello this is the thread...',
- f'My counter is {i}',
- f'Will send another message in {seconds} seconds'))
- i += 1
-
-
-def main():
- """
- Every time "Start A Thread" is clicked a new thread is started
- When the event is received from the thread, a popup is shown in its behalf
- """
-
- layout = [ [sg.Output(size=(60,10))],
- [sg.T('How often a thread will show a popup in seconds'),
- sg.Spin((2, 5, 10, 20), initial_value=5, k='-SPIN-')],
- [sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout, finalize=True, font='_ 15')
-
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-POPUP-':
- sg.popup_non_blocking('This is a popup that the thread wants to show',
- *values['-POPUP-'])
- elif event == 'Start A Thread':
- print(f'Starting thread. You will see a new popup every {values["-SPIN-"]} seconds')
- threading.Thread(target=the_thread, args=(window, values['-SPIN-']), daemon=True).start()
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_DataPump.py b/DemoPrograms/Demo_Multithreaded_DataPump.py
deleted file mode 100644
index d91bae877..000000000
--- a/DemoPrograms/Demo_Multithreaded_DataPump.py
+++ /dev/null
@@ -1,144 +0,0 @@
-import PySimpleGUI as sg
-import random
-import time
-import queue
-
-"""
- Demo - Multi-threaded "Data Pump" Design Pattern
-
- Send data to your PySimpleGUI program through a Python Queue, enabling integration with many
- different types of data sources.
-
- A thread gets data from a queue object and passes it over to the main event loop.
- The external_thread is only used here to generaate random data. It's not part of the
- overall "Design Pattern".
-
- The thread the_thread IS part of the design pattern. It reads data from the thread_queue and sends that
- data over to the PySimpleGUI event loop.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-gsize = (400, 400) # size of the graph
-
-THREAD_KEY = '-THREAD-'
-THREAD_INCOMING_DATA = '-INCOMING DATA-'
-THREAD_EXITNG = '-THREAD EXITING-'
-THREAD_EXTERNAL_EXITNG = '-EXTERNAL THREAD EXITING-'
-
-# This queue is where you will send your data that you want to eventually arrive as an event
-thread_queue = queue.Queue()
-
-# M""""""""M dP dP
-# Mmmm mmmM 88 88
-# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88
-# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88
-# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88
-# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8
-# MMMMMMMMMM
-#
-# MP""""""`MM oo dP dP oo
-# M mmmmm..M 88 88
-# M. `YM dP 88d8b.d8b. dP dP 88 .d8888b. d8888P dP 88d888b. .d8888b.
-# MMMMMMM. M 88 88'`88'`88 88 88 88 88' `88 88 88 88' `88 88' `88
-# M. .MMM' M 88 88 88 88 88. .88 88 88. .88 88 88 88 88 88. .88
-# Mb. .dM dP dP dP dP `88888P' dP `88888P8 dP dP dP dP `8888P88
-# MMMMMMMMMMM .88
-# d8888P
-# M""""""'YMM dP MP""""""`MM
-# M mmmm. `M 88 M mmmmm..M
-# M MMMMM M .d8888b. d8888P .d8888b. M. `YM .d8888b. dP dP 88d888b. .d8888b. .d8888b.
-# M MMMMM M 88' `88 88 88' `88 MMMMMMM. M 88' `88 88 88 88' `88 88' `"" 88ooood8
-# M MMMM' .M 88. .88 88 88. .88 M. .MMM' M 88. .88 88. .88 88 88. ... 88. ...
-# M .MM `88888P8 dP `88888P8 Mb. .dM `88888P' `88888P' dP `88888P' `88888P'
-# MMMMMMMMMMM MMMMMMMMMMM
-#
-
-def external_thread(thread_queue:queue.Queue):
- """
- Represents some external source of data.
- You would not include this code as a starting point with this Demo Program. Your data is assumed to
- come from somewhere else. The important part is that you add data to the thread_queue
- :param thread_queue:
- :return:
- """
- i = 0
- while True:
- time.sleep(.01)
- point = (random.randint(0,gsize[0]), random.randint(0,gsize[1]))
- radius = random.randint(10, 40)
- thread_queue.put((point, radius))
- i += 1
-
-
-# M""""""""M dP dP MM""""""""`M
-# Mmmm mmmM 88 88 MM mmmmmmmM
-# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88 M' MMMM .d8888b. 88d888b.
-# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88 MM MMMMMMMM 88' `88 88' `88
-# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88 MM MMMMMMMM 88. .88 88
-# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8 MM MMMMMMMM `88888P' dP
-# MMMMMMMMMM MMMMMMMMMMMM
-#
-# MM"""""""`YM MP""""""`MM MM'"""""`MM MM""""""""`M dP
-# MM mmmmm M M mmmmm..M M' .mmm. `M MM mmmmmmmM 88
-# M' .M M. `YM M MMMMMMMM M` MMMM dP .dP .d8888b. 88d888b. d8888P .d8888b.
-# MM MMMMMMMM MMMMMMM. M M MMM `M MM MMMMMMMM 88 d8' 88ooood8 88' `88 88 Y8ooooo.
-# MM MMMMMMMM M. .MMM' M M. `MMM' .M MM MMMMMMMM 88 .88' 88. ... 88 88 88 88
-# MM MMMMMMMM Mb. .dM MM. .MM MM .M 8888P' `88888P' dP dP dP `88888P'
-# MMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMM
-
-
-def the_thread(window:sg.Window, thread_queue:queue.Queue):
- """
- The thread that communicates with the application through the window's events.
- Waits for data from a queue and sends that data on to the event loop
- :param window:
- :param thread_queue:
- :return:
- """
-
- while True:
- data = thread_queue.get()
- window.write_event_value((THREAD_KEY, THREAD_INCOMING_DATA), data) # Data sent is a tuple of thread name and counter
-
-
-def main():
-
- layout = [ [sg.Text('My Simulated Data Pump')],
- [sg.Multiline(size=(60, 20), k='-MLINE-')],
- [sg.Graph(gsize, (0, 0), gsize, k='-G-', background_color='gray')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
- window = sg.Window('Simulated Data Pump', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
-
- graph = window['-G-'] # type: sg.Graph
-
- while True: # Event Loop
- event, values = window.read()
- # print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Go':
- window.start_thread(lambda: the_thread(window, thread_queue), (THREAD_KEY, THREAD_EXITNG))
- window.start_thread(lambda: external_thread(thread_queue), (THREAD_KEY, THREAD_EXTERNAL_EXITNG))
- # Events coming from the Thread
- elif event[0] == THREAD_KEY:
- if event[1] == THREAD_INCOMING_DATA:
- point, radius = values[event]
- graph.draw_circle(point, radius=radius, fill_color='green')
- window['-MLINE-'].print(f'Drawing at {point} radius {radius}', c='white on red')
- elif event[1] == THREAD_EXITNG:
- window['-MLINE-'].print('Thread has exited')
- elif event[1] == THREAD_EXTERNAL_EXITNG:
- window['-MLINE-'].print('Data Pump thread has exited')
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py b/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py
deleted file mode 100644
index 2edbe96b0..000000000
--- a/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py
+++ /dev/null
@@ -1,153 +0,0 @@
-import PySimpleGUI as sg
-import time
-import threading
-
-"""
- Demo - Multi-threaded - Show Windows and perform other PySimpleGUI calls in what appread to be from a thread
-
- Just so that it's clear, you CANNOT make PySimpleGUI calls directly from a thread. There is ONE exception to this
- rule. A thread may call window.write_event_values which enables it to communicate to a window through the window.read calls.
-
- The main GUI will not be visible on your screen nor on your taskbar despite running in the background. The calls you
- make, such as popup, or even Window.read will create windows that your user will see.
-
- The basic function that you'll use in your thread has this format:
- make_delegate_call(lambda: sg.popup('This is a popup', i, auto_close=True, auto_close_duration=2, keep_on_top=True, non_blocking=True))
-
- Everything after the "lambda" looks exactly like a PySimpleGUI call.
- If you want to display an entire window, then the suggestion is to put it into a function and pass the function to make_delegate_call
-
- Note - the behavior of variables may be a bit of a surprise as they are not evaluated until the mainthread processes the event. This means
- in the example below that the counter variable being passed to the popup will not appear to be counting correctly. This is because the
- value shown will be the value at the time the popup is DISPLAYED, not the value when the make_delegate_call was made.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# Design decision was to make the window a global. You can just as easily pass it to your function after initizing your window
-# But there becomes a problem then of wheere do you place the thread startup code. Using this global decouples them so that
-# the thread is not started in the function that makes and executes the GUI
-
-window:sg.Window = None
-
-# M""MMMM""M
-# M. `MM' .M
-# MM. .MM .d8888b. dP dP 88d888b.
-# MMMb dMMM 88' `88 88 88 88' `88
-# MMMM MMMM 88. .88 88. .88 88
-# MMMM MMMM `88888P' `88888P' dP
-# MMMMMMMMMM
-#
-# M""""""""M dP dP
-# Mmmm mmmM 88 88
-# MMMM MMMM 88d888b. 88d888b. .d8888b. .d8888b. .d888b88
-# MMMM MMMM 88' `88 88' `88 88ooood8 88' `88 88' `88
-# MMMM MMMM 88 88 88 88. ... 88. .88 88. .88
-# MMMM MMMM dP dP dP `88888P' `88888P8 `88888P8
-# MMMMMMMMMM
-
-def the_thread():
- """
- This is code that is unique to your application. It wants to "make calls to PySimpleGUI", but it cannot directly do so.
- Instead it will send the request to make the call to the mainthread that is running the GUI.
-
- :return:
- """
-
- # Wait for the GUI to start running
- while window is None:
- time.sleep(.2)
-
- for i in range(5):
- time.sleep(.2)
- make_delegate_call(lambda: sg.popup('This is a popup', i, relative_location=(0, -300), auto_close=True, auto_close_duration=2, keep_on_top=True, non_blocking=True))
- make_delegate_call(lambda: sg.popup_scrolled(__file__, sg.get_versions(), auto_close=True, auto_close_duration=1.5, non_blocking=True))
-
- make_delegate_call(lambda: sg.popup('One last popup before exiting...', relative_location=(-200, -200)))
-
- # when finished and ready to stop, tell the main GUI to exit
- window.write_event_value('-THREAD EXIT-', None)
-
-
-# -------------------------------------------------------------------------------------------------------- #
-
-# The remainder of the code is part of the overall design pattern. You should copy this code
-# and use it as the basis for creating this time of delegated PySimpleGUI calls
-
-
-# M""""""'YMM oo
-# M mmmm. `M
-# M MMMMM M .d8888b. .d8888b. dP .d8888b. 88d888b.
-# M MMMMM M 88ooood8 Y8ooooo. 88 88' `88 88' `88
-# M MMMM' .M 88. ... 88 88 88. .88 88 88
-# M .MM `88888P' `88888P' dP `8888P88 dP dP
-# MMMMMMMMMMM .88
-# d8888P
-# MM"""""""`YM dP dP
-# MM mmmmm M 88 88
-# M' .M .d8888b. d8888P d8888P .d8888b. 88d888b. 88d888b.
-# MM MMMMMMMM 88' `88 88 88 88ooood8 88' `88 88' `88
-# MM MMMMMMMM 88. .88 88 88 88. ... 88 88 88
-# MM MMMMMMMM `88888P8 dP dP `88888P' dP dP dP
-# MMMMMMMMMMMM
-
-def make_delegate_call(func):
- """
- Make a delegate call to PySimpleGUI.
-
- :param func: A lambda expression most likely. It's a function that will be called by the mainthread that's executing the GUI
- :return:
- """
- if window is not None:
- window.write_event_value('-THREAD DELEGATE-', func)
-
-
-# oo
-#
-# 88d8b.d8b. .d8888b. dP 88d888b.
-# 88'`88'`88 88' `88 88 88' `88
-# 88 88 88 88. .88 88 88 88
-# dP dP dP `88888P8 dP dP dP
-
-def main():
- global window
-
- # create a window. A key is needed so that the values dictionary will return the thread's value as a key
- layout = [[sg.Text('', k='-T-')]]
-
- # set the window to be both invisible and have no taskbar icon
- window = sg.Window('Invisible window', layout, no_titlebar=True, alpha_channel=0, finalize=True, font='_ 1', margins=(0,0), element_padding=(0,0))
- window.hide()
-
- while True:
- event, values = window.read()
- if event in ('Exit', sg.WIN_CLOSED):
- break
- # if the event is from the thread, then the value is the function that should be called
- if event == '-THREAD DELEGATE-':
- try:
- values[event]()
- except Exception as e:
- sg.popup_error_with_traceback('Error calling your function passed to GUI', event, values, e)
- elif event == '-THREAD EXIT-':
- break
- window.close()
-
-
-# MP""""""`MM dP dP
-# M mmmmm..M 88 88
-# M. `YM d8888P .d8888b. 88d888b. d8888P dP dP 88d888b.
-# MMMMMMM. M 88 88' `88 88' `88 88 88 88 88' `88
-# M. .MMM' M 88 88. .88 88 88 88. .88 88. .88
-# Mb. .dM dP `88888P8 dP dP `88888P' 88Y888P'
-# MMMMMMMMMMM 88
-# dP
-
-if __name__ == '__main__':
- # first your thread will be started
- threading.Thread(target=the_thread, daemon=True).start()
- # then startup the main GUI
- main()
diff --git a/DemoPrograms/Demo_Multithreaded_Different_Threads.py b/DemoPrograms/Demo_Multithreaded_Different_Threads.py
deleted file mode 100644
index dba9c7ea7..000000000
--- a/DemoPrograms/Demo_Multithreaded_Different_Threads.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/python3
-import time
-import itertools
-import PySimpleGUI as sg
-
-"""
- DESIGN PATTERN - Multithreaded GUI
- One method for running multiple threads in a PySimpleGUI environment.
- The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
- Other parts of the software are implemented as threads
-
- While users never know the implementation details within PySimpleGUI, the mechanism is that a queue.Queue
- is used to communicate data between a thread and a PySimpleGUI window.
- The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
- a Window is created, and an event loop is executed.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-
-# ######## ## ## ######## ######## ### ########
-# ## ## ## ## ## ## ## ## ## ##
-# ## ## ## ## ## ## ## ## ## ##
-# ## ######### ######## ###### ## ## ## ##
-# ## ## ## ## ## ## ######### ## ##
-# ## ## ## ## ## ## ## ## ## ##
-# ## ## ## ## ## ######## ## ## ########
-
-def worker_thread1(thread_name, run_freq, window):
- """
- A worker thread that communicates with the GUI
- These threads can call functions that block without affecting the GUI (a good thing)
- Note that this function is the code started as each thread. All threads are identical in this way
- :param thread_name: Text name used for displaying info
- :param run_freq: How often the thread should run in milliseconds
- :param window: window this thread will be conversing with
- :type window: sg.Window
- :return:
- """
- print('Starting thread 1 - {} that runs every {} ms'.format(thread_name, run_freq))
- for i in itertools.count(): # loop forever, keeping count in i as it loops
- time.sleep(run_freq/1000) # sleep for a while
- # put a message into queue for GUI
- window.write_event_value(thread_name, f'count = {i}')
-
-
-def worker_thread2(thread_name, run_freq, window):
- """
- A worker thread that communicates with the GUI
- These threads can call functions that block without affecting the GUI (a good thing)
- Note that this function is the code started as each thread. All threads are identical in this way
- :param thread_name: Text name used for displaying info
- :param run_freq: How often the thread should run in milliseconds
- :param window: window this thread will be conversing with
- :type window: sg.Window
- :return:
- """
- print('Starting thread 2 - {} that runs every {} ms'.format(thread_name, run_freq))
- for i in itertools.count(): # loop forever, keeping count in i as it loops
- time.sleep(run_freq/1000) # sleep for a while
- # put a message into queue for GUI
- window.write_event_value(thread_name, f'count = {i}')
-
-
-def worker_thread3(thread_name, run_freq, window):
- """
- A worker thread that communicates with the GUI
- These threads can call functions that block without affecting the GUI (a good thing)
- Note that this function is the code started as each thread. All threads are identical in this way
- :param thread_name: Text name used for displaying info
- :param run_freq: How often the thread should run in milliseconds
- :param window: window this thread will be conversing with
- :type window: sg.Window
- :return:
- """
- print('Starting thread 3 - {} that runs every {} ms'.format(thread_name, run_freq))
- for i in itertools.count(): # loop forever, keeping count in i as it loops
- time.sleep(run_freq/1000) # sleep for a while
- # put a message into queue for GUI
- window.write_event_value(thread_name, f'count = {i}')
-
-
-
-# ###### ## ## ####
-# ## ## ## ## ##
-# ## ## ## ##
-# ## #### ## ## ##
-# ## ## ## ## ##
-# ## ## ## ## ##
-# ###### ####### ####
-
-
-def main():
- """
- Starts and executes the GUI
- Reads data from a Queue and displays the data to the window
- Returns when the user exits / closes the window
- (that means it does NOT return until the user exits the window)
- :param gui_queue: Queue the GUI should read from
- :return:
- """
- layout = [[sg.Text('Multithreaded Window Example')],
- [sg.Text('', size=(15, 1), key='-OUTPUT-')],
- [sg.Multiline(size=(40, 26), key='-ML-', autoscroll=True)],
- [sg.Push(), sg.Button('Exit')], ]
-
- window = sg.Window('Multithreaded Window', layout, finalize=True)
-
- # -- Create a Queue to communicate with GUI --
- # queue used to communicate between the gui and the threads
- # -- Start worker threads, each taking a different amount of time
- window.start_thread(lambda: worker_thread1('Thread 1', 500, window))
- window.start_thread(lambda: worker_thread2('Thread 2', 200, window))
- window.start_thread(lambda: worker_thread3('Thread 3', 1000, window))
- # -- Start the GUI passing in the Queue --
-
- sg.cprint_set_output_destination(window, '-ML-')
-
- colors = {'Thread 1':('white', 'red'), 'Thread 2':('white', 'purple'), 'Thread 3':('white', 'blue')}
- # --------------------- EVENT LOOP ---------------------
- while True:
- # wait for up to 100 ms for a GUI event
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- # --------------- Loop through all messages coming in from threads ---------------
- sg.cprint(event, values[event], c=colors[event])
- # if user exits the window, then close the window and exit the GUI func
- window.close()
-
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_Multithreaded_Logging.py b/DemoPrograms/Demo_Multithreaded_Logging.py
new file mode 100644
index 000000000..9c71f4e9a
--- /dev/null
+++ b/DemoPrograms/Demo_Multithreaded_Logging.py
@@ -0,0 +1,95 @@
+import PySimpleGUI as sg
+import queue
+import logging
+import threading
+import time
+
+"""
+ This code originated in this project:
+ https://github.com/john144/MultiThreading
+ Thanks to John for writing this in the early days of PySimpleGUI
+ Demo program showing one way that a threaded application can function with PySimpleGUI
+ Events are sent from the ThreadedApp thread to the main thread, the GUI, by using a queue
+"""
+
+logger = logging.getLogger('mymain')
+
+
+def externalFunction():
+ logger.info('Hello from external app')
+ logger.info('External app sleeping 5 seconds')
+ time.sleep(5)
+ logger.info('External app waking up and exiting')
+
+
+class ThreadedApp(threading.Thread):
+ def __init__(self):
+ super().__init__()
+ self._stop_event = threading.Event()
+
+ def run(self):
+ externalFunction()
+
+ def stop(self):
+ self._stop_event.set()
+
+
+class QueueHandler(logging.Handler):
+ def __init__(self, log_queue):
+ super().__init__()
+ self.log_queue = log_queue
+
+ def emit(self, record):
+ self.log_queue.put(record)
+
+
+def main():
+
+ layout = [
+ [sg.MLine(size=(50, 15), key='Log')],
+ [sg.Button('Start', bind_return_key=True, key='-START-'), sg.Button('Exit')]
+ ]
+
+ window = sg.FlexForm('Log window', layout,
+ default_element_size=(30, 2),
+ font=('Helvetica', ' 10'),
+ default_button_element_size=(8, 2),
+ return_keyboard_events=True)
+ window.read(timeout=0)
+ appStarted = False
+
+ # Setup logging and start app
+ logging.basicConfig(level=logging.DEBUG)
+ log_queue = queue.Queue()
+ queue_handler = QueueHandler(log_queue)
+ logger.addHandler(queue_handler)
+ threadedApp = ThreadedApp()
+
+ # Loop taking in user input and querying queue
+ while True:
+ # Wake every 100ms and look for work
+ event, values = window.read(timeout=100)
+
+ if event == '-START-':
+ if appStarted is False:
+ threadedApp.start()
+ logger.debug('App started')
+ window['-START-'].update(disabled=True)
+ appStarted = True
+ elif event in (None, 'Exit'):
+ break
+
+ # Poll queue
+ try:
+ record = log_queue.get(block=False)
+ except queue.Empty:
+ pass
+ else:
+ msg = queue_handler.format(record)
+ window['Log'].update(msg+'\n', append=True)
+
+ window.close()
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py b/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py
deleted file mode 100644
index b324a249b..000000000
--- a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo shell_with_animation call
-
- This is a high-level function that could easily live in user's code instead of PySimpleGUI. The
- rationale for bringing it into PySimpleGUI is to encourage users to experiment with working with
- more external tools like ffmpeg. The shell_with_animation function allows users to easily start
- a long-operation without fearing that the GUI will appear to be frozen. It offers a wide range
- of parameters to help create a custom animation window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Here we're running a simple "pip list" command and using the built-in animated GIF.
-
-output = sg.shell_with_animation('pip', ('list',), message='Loading...', font='Helvetica 15')
-sg.popup_scrolled(output, font='Courier 10')
-output = sg.shell_with_animation('dir', message='Loading...', font='Helvetica 15')
-# output = sg.shell_with_animation(r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", message='Loading...', font='Helvetica 15')
-
-sg.popup_scrolled(output, font='Courier 10')
diff --git a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py b/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py
deleted file mode 100644
index feb507175..000000000
--- a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/python3
-import threading
-import time
-import PySimpleGUI as sg
-
-"""
- DESIGN PATTERN - Multithreaded Long Tasks GUI using shared global variables
-
- Presents one method for running long-running operations in a PySimpleGUI environment.
- The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
- The "long work" is contained in the thread that is being started. Communicating is done (carefully) using global variables
-
- There are 2 ways "progress" is being reported to the user.
- You can simulate the 2 different scenarios that happen with worker threads.
- 1. If a the amount of time is known ahead of time or the work can be broken down into countable units, then a progress bar is used.
- 2. If a task is one long chunk of time that cannot be broken down into smaller units, then an animated GIF is shown that spins as
- long as the task is running.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def long_operation_thread(seconds, window):
- """
- A worker thread that communicates with the GUI through a global message variable
- This thread can block for as long as it wants and the GUI will not be affected
- :param seconds: (int) How long to sleep, the ultimate blocking call
- """
- progress = 0
- print('Thread started - will sleep for {} seconds'.format(seconds))
- for i in range(int(seconds * 10)):
- time.sleep(.1) # sleep for a while
- progress += 100 / (seconds * 10)
- window.write_event_value('-PROGRESS-', progress)
-
- window.write_event_value('-THREAD-', '*** The thread says.... "I am finished" ***')
-
-def the_gui():
- """
- Starts and executes the GUI
- Reads data from a global variable and displays
- Returns when the user exits / closes the window
- """
-
- sg.theme('Light Brown 3')
-
- layout = [[sg.Text('Long task to perform example')],
- [sg.MLine(size=(80, 12), k='-ML-', reroute_stdout=True,write_only=True, autoscroll=True, auto_refresh=True)],
- [sg.Text('Number of seconds your task will take'),
- sg.Input(key='-SECONDS-', focus=True, size=(5, 1)),
- sg.Button('Do Long Task', bind_return_key=True),
- sg.CBox('ONE chunk, cannot break apart', key='-ONE CHUNK-')],
- [sg.Text('Work progress'), sg.ProgressBar(100, size=(20, 20), orientation='h', key='-PROG-')],
- [sg.Button('Click Me'), sg.Button('Exit')], ]
-
- window = sg.Window('Multithreaded Demonstration Window', layout, finalize=True)
-
- timeout = thread = None
- # --------------------- EVENT LOOP ---------------------
- while True:
- event, values = window.read(timeout=timeout)
- # print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event.startswith('Do') and not thread:
- print('Thread Starting! Long work....sending value of {} seconds'.format(float(values['-SECONDS-'])))
- timeout = 100 if values['-ONE CHUNK-'] else None
- thread = threading.Thread(target=long_operation_thread, args=(float(values['-SECONDS-']),window), daemon=True)
- thread.start()
- if values['-ONE CHUNK-']:
- sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', transparent_color='white', time_between_frames=100)
- elif event == 'Click Me':
- print('Your GUI is alive and well')
- elif event == '-PROGRESS-':
- if not values['-ONE CHUNK-']:
- window['-PROG-'].update_bar(values[event], 100)
- elif event == '-THREAD-': # Thread has completed
- thread.join(timeout=0)
- print('Thread finished')
- sg.popup_animated(None) # stop animination in case one is running
- thread, message, progress, timeout = None, '', 0, None # reset variables for next run
- window['-PROG-'].update_bar(0,0) # clear the progress bar
- if values['-ONE CHUNK-'] and thread is not None:
- sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', transparent_color='white', time_between_frames=100)
- window.close()
-
-
-if __name__ == '__main__':
- the_gui()
- print('Exiting Program')
diff --git a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
index 487413191..ca5bf0a48 100644
--- a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
+++ b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
@@ -1,39 +1,40 @@
#!/usr/bin/python3
+import queue
+import threading
import time
import PySimpleGUI as sg
+# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
+# To try something other than tkinter version, just comment out the first import and uncomment the one you want
"""
- Demo Program - Multithreaded Long Tasks GUI
-
+ DESIGN PATTERN - Multithreaded Long Tasks GUI
Presents one method for running long-running operations in a PySimpleGUI environment.
-
The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
The "long work" is contained in the thread that is being started.
- So that you don't have to import and understand the threading module, this program uses window.start_thread to run a thread.
-
- The thread is using TUPLES for its keys. This enables you to easily find the thread events by looking at event[0].
- The Thread Keys look something like this: ('-THREAD-', message)
- If event [0] == '-THREAD-' then you know it's one of these tuple keys.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ A queue.Queue is used by the threads to communicate with main GUI code
+ The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
+ a Window is created, and an event loop is executed.
+ What's different is that within this otherwise normal PySimpleGUI Event Loop, there is a check for items
+ in the Queue. If there are items found, process them by making GUI changes, and continue.
+
+ This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it
+ You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy
"""
-def long_operation_thread(seconds, window):
+def long_operation_thread(seconds, gui_queue):
"""
A worker thread that communicates with the GUI through a queue
This thread can block for as long as it wants and the GUI will not be affected
:param seconds: (int) How long to sleep, the ultimate blocking call
- :param window: (sg.Window) the window to communicate with
+ :param gui_queue: (queue.Queue) Queue to communicate back to GUI that task is completed
:return:
"""
- window.write_event_value(('-THREAD-', 'Starting thread - will sleep for {} seconds'.format(seconds)), None)
+ print('Starting thread - will sleep for {} seconds'.format(seconds))
time.sleep(seconds) # sleep for a while
- window.write_event_value(('-THREAD-', '** DONE **'), 'Done!') # put a message into queue for GUI
+ gui_queue.put('** Done **') # put a message into queue for GUI
def the_gui():
@@ -42,12 +43,13 @@ def the_gui():
Reads data from a Queue and displays the data to the window
Returns when the user exits / closes the window
"""
- sg.theme('Light Brown 3')
+
+ gui_queue = queue.Queue() # queue used to communicate between the gui and the threads
layout = [[sg.Text('Long task to perform example')],
[sg.Output(size=(70, 12))],
[sg.Text('Number of seconds your task will take'),
- sg.Input(default_text=5, key='-SECONDS-', size=(5, 1)),
+ sg.Input(key='-SECONDS-', size=(5, 1)),
sg.Button('Do Long Task', bind_return_key=True)],
[sg.Button('Click Me'), sg.Button('Exit')], ]
@@ -55,17 +57,29 @@ def the_gui():
# --------------------- EVENT LOOP ---------------------
while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ event, values = window.read(timeout=100)
+ if event in (None, 'Exit'):
break
- elif event == 'Do Long Task':
- seconds = int(values['-SECONDS-'])
- print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
- window.start_thread(lambda: long_operation_thread(seconds, window), ('-THREAD-', '-THEAD ENDED-'))
+ elif event.startswith('Do'):
+ try:
+ seconds = int(values['-SECONDS-'])
+ print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
+ threading.Thread(target=long_operation_thread,
+ args=(seconds, gui_queue,), daemon=True).start()
+ except Exception as e:
+ print('Error starting work thread. Bad seconds input: "%s"' %
+ values['-SECONDS-'])
elif event == 'Click Me':
print('Your GUI is alive and well')
- elif event[0] == '-THREAD-':
- print('Got a message back from the thread: ', event[1])
+ # --------------- Check for incoming messages from threads ---------------
+ try:
+ message = gui_queue.get_nowait()
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ message = None # break from the loop if no more messages are queued up
+
+ # if message received from queue, display the message in the Window
+ if message:
+ print('Got a message back from the thread: ', message)
# if user exits the window, then close the window and exit the GUI func
window.close()
diff --git a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py b/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py
deleted file mode 100644
index 297eefba8..000000000
--- a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/python3
-import threading
-import time
-import PySimpleGUI as sg
-
-"""
- You want to look for 3 points in this code, marked with comment "LOCATION X".
- 1. Where you put your call that takes a long time
- 2. Where the trigger to make the call takes place in the event loop
- 3. Where the completion of the call is indicated in the event loop
-
- Demo on how to add a long-running item to your PySimpleGUI Event Loop
- If you want to do something that takes a long time, and you do it in the
- main event loop, you'll quickly begin to see messages from windows that your
- program has hung, asking if you want to kill it.
-
- The problem is not that your problem is hung, the problem is that you are
- not calling Read or Refresh often enough.
-
- One way through this, shown here, is to put your long work into a thread that
- is spun off, allowed to work, and then gets back to the GUI when it's done working
- on that task.
-
- Every time you start up one of these long-running functions, you'll give it an "ID".
- When the function completes, it will send to the GUI Event Loop a message with
- the format:
- work_id ::: done
- This makes it easy to parse out your original work ID
-
- You can hard code these IDs to make your code more readable. For example, maybe
- you have a function named "update_user_list()". You can call the work ID "user list".
- Then check for the message coming back later from the work task to see if it starts
- with "user list". If so, then that long-running task is over.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-# ############################# User callable CPU intensive code #############################
-# Put your long running code inside this "wrapper"
-# NEVER make calls to PySimpleGUI from this thread (or any thread)!
-# Create one of these functions for EVERY long-running call you want to make
-
-
-def long_function_wrapper(work_id, window):
- # LOCATION 1
- # this is our "long running function call"
- # sleep for a while as a simulation of a long-running computation
- time.sleep(5)
- # at the end of the work, before exiting, send a message back to the GUI indicating end
- window.write_event_value('-THREAD DONE-', work_id)
- # at this point, the thread exits
- return
-
-
-############################# Begin GUI code #############################
-def the_gui():
- sg.theme('Light Brown 3')
-
-
- layout = [[sg.Text('Multithreaded Work Example')],
- [sg.Text('Click Go to start a long-running function call')],
- [sg.Text(size=(25, 1), key='-OUTPUT-')],
- [sg.Text(size=(25, 1), key='-OUTPUT2-')],
- [sg.Text('⚫', text_color='blue', key=i, pad=(0,0), font='Default 14') for i in range(20)],
- [sg.Button('Go'), sg.Button('Popup'), sg.Button('Exit')], ]
-
- window = sg.Window('Multithreaded Window', layout)
- # --------------------- EVENT LOOP ---------------------
- work_id = 0
- while True:
- # wait for up to 100 ms for a GUI event
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == 'Go': # clicking "Go" starts a long running work item by starting thread
- window['-OUTPUT-'].update('Starting long work %s' % work_id)
- window[work_id].update(text_color='red')
- # LOCATION 2
- # STARTING long run by starting a thread
- thread_id = threading.Thread(
- target=long_function_wrapper,
- args=(work_id, window,),
- daemon=True)
- thread_id.start()
- work_id = work_id+1 if work_id < 19 else 0
-
- # if message received from queue, then some work was completed
- if event == '-THREAD DONE-':
- # LOCATION 3
- # this is the place you would execute code at ENDING of long running task
- # You can check the completed_work_id variable
- # to see exactly which long-running function completed
- completed_work_id = values[event]
- window['-OUTPUT2-'].update(
- 'Complete Work ID "{}"'.format(completed_work_id))
- window[completed_work_id].update(text_color='green')
-
- if event == 'Popup':
- sg.popup_non_blocking('This is a popup showing that the GUI is running', grab_anywhere=True)
- # if user exits the window, then close the window and exit the GUI func
- window.close()
-
-############################# Main #############################
-
-
-if __name__ == '__main__':
- the_gui()
- print('Exiting Program')
diff --git a/DemoPrograms/Demo_Multithreaded_ProgressBar.py b/DemoPrograms/Demo_Multithreaded_ProgressBar.py
deleted file mode 100644
index a1d1b5273..000000000
--- a/DemoPrograms/Demo_Multithreaded_ProgressBar.py
+++ /dev/null
@@ -1,88 +0,0 @@
-import PySimpleGUI as sg
-import random
-import time
-
-"""
- Demo - Multi-threaded downloader with one_line_progress_meter
-
- Sometimes you don't have a choice in how your data is downloaded. In some programs
- the download happens in another thread which means you cannot call PySimpleGUI directly
- from the thread.
-
- Maybe you're still interested in using the one_line_progress_meter feature or perhaps
- have implemented your own progress meter in your window.
-
- Using the write_event_value method enables you to easily do either of these.
-
- In this demo, all thread events are a TUPLE with the first item in tuple being THREAD_KEY ---> '-THEAD-'
- This allows easy separation of all of the thread-based keys into 1 if statment:
- elif event[0] == THREAD_KEY:
- Example
- (THREAD_KEY, DL_START_KEY) indicates the download is starting and provices the Max value
- (THREAD_KEY, DL_END_KEY) indicates the downloading has completed
-
- The main window uses a relative location when making the window so that the one-line-progress-meter has room
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-THREAD_KEY = '-THREAD-'
-DL_START_KEY = '-START DOWNLOAD-'
-DL_COUNT_KEY = '-COUNT-'
-DL_END_KEY = '-END DOWNLOAD-'
-DL_THREAD_EXITNG = '-THREAD EXITING-'
-
-def the_thread(window:sg.Window):
- """
- The thread that communicates with the application through the window's events.
-
- Simulates downloading a random number of chinks from 50 to 100-
- """
- max_value = random.randint(50, 100)
- window.write_event_value((THREAD_KEY, DL_START_KEY), max_value) # Data sent is a tuple of thread name and counter
- for i in range(max_value):
- time.sleep(.1)
- window.write_event_value((THREAD_KEY, DL_COUNT_KEY), i) # Data sent is a tuple of thread name and counter
- window.write_event_value((THREAD_KEY, DL_END_KEY), max_value) # Data sent is a tuple of thread name and counter
-
-
-def main():
- layout = [ [sg.Text('My Multi-threaded PySimpleGUI Program')],
- [sg.ProgressBar(100, 'h', size=(30,20), k='-PROGRESS-', expand_x=True)],
- [sg.Text(key='-STATUS-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout, finalize=True, relative_location=(0, -300))
- downloading, max_value = False, 0
-
- while True: # Event Loop
- event, values = window.read()
- # print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Go' and not downloading:
- window.start_thread(lambda: the_thread(window), (THREAD_KEY, DL_THREAD_EXITNG))
- # Events coming from the Thread
- elif event[0] == THREAD_KEY:
- if event[1] == DL_START_KEY:
- max_value = values[event]
- downloading = True
- window['-STATUS-'].update('Starting download')
- sg.one_line_progress_meter(f'Downloading {max_value} segments', 0, max_value, 1, f'Downloading {max_value} segments', )
- window['-PROGRESS-'].update(0, max_value)
- elif event[1] == DL_COUNT_KEY:
- sg.one_line_progress_meter(f'Downloading {max_value} segments', values[event]+1, max_value, 1, f'Downloading {max_value} segments')
- window['-STATUS-'].update(f'Got a new current count update {values[event]}')
- window['-PROGRESS-'].update(values[event]+1, max_value)
- elif event[1] == DL_END_KEY:
- downloading = False
- window['-STATUS-'].update('Download finished')
- elif event[1] == DL_THREAD_EXITNG:
- window['-STATUS-'].update('Last step - Thread has exited')
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Multithreaded_Queued.py b/DemoPrograms/Demo_Multithreaded_Queued.py
new file mode 100644
index 000000000..b4ec9bb8c
--- /dev/null
+++ b/DemoPrograms/Demo_Multithreaded_Queued.py
@@ -0,0 +1,121 @@
+#!/usr/bin/python3
+
+# Rather than importing individual classes such as threading.Thread or queue.Queue, this
+# program is doing a simple import and then indicating the package name when the functions
+# are called. This seemed like a great way for the reader of the code to get an understanding
+# as to exactly which package is being used. It's purely for educational and explicitness purposes
+import queue
+import threading
+import time
+import itertools
+import PySimpleGUI as sg
+
+"""
+ DESIGN PATTERN - Multithreaded GUI
+ One method for running multiple threads in a PySimpleGUI environment.
+ The PySimpleGUI code, and thus the underlying GUI framework, runs as the primary, main thread
+ Other parts of the software are implemented as threads
+
+ A queue.Queue is used by the worker threads to communicate with code that calls PySimpleGUI directly.
+ The PySimpleGUI code is structured just like a typical PySimpleGUI program. A layout defined,
+ a Window is created, and an event loop is executed.
+ What's different is that within this otherwise normal PySimpleGUI Event Loop, there is a check for items
+ in the Queue. If there are items found, process them by making GUI changes, and continue.
+
+ This design pattern works for all of the flavors of PySimpleGUI including the Web and also repl.it
+ You'll find a repl.it version here: https://repl.it/@PySimpleGUI/Async-With-Queue-Communicationspy
+"""
+
+
+# ######## ## ## ######## ######## ### ########
+# ## ## ## ## ## ## ## ## ## ##
+# ## ## ## ## ## ## ## ## ## ##
+# ## ######### ######## ###### ## ## ## ##
+# ## ## ## ## ## ## ######### ## ##
+# ## ## ## ## ## ## ## ## ## ##
+# ## ## ## ## ## ######## ## ## ########
+
+def worker_thread(thread_name, run_freq, gui_queue):
+ """
+ A worker thrread that communicates with the GUI
+ These threads can call functions that block withouth affecting the GUI (a good thing)
+ Note that this function is the code started as each thread. All threads are identical in this way
+ :param thread_name: Text name used for displaying info
+ :param run_freq: How often the thread should run in milliseconds
+ :param gui_queue: Queue used to communicate with the GUI
+ :return:
+ """
+ print('Starting thread - {} that runs every {} ms'.format(thread_name, run_freq))
+ for i in itertools.count(): # loop forever, keeping count in i as it loops
+ time.sleep(run_freq/1000) # sleep for a while
+ # put a message into queue for GUI
+ gui_queue.put('{} - {}'.format(thread_name, i))
+
+# ###### ## ## ####
+# ## ## ## ## ##
+# ## ## ## ##
+# ## #### ## ## ##
+# ## ## ## ## ##
+# ## ## ## ## ##
+# ###### ####### ####
+
+
+def the_gui(gui_queue):
+ """
+ Starts and executes the GUI
+ Reads data from a Queue and displays the data to the window
+ Returns when the user exits / closes the window
+ (that means it does NOT return until the user exits the window)
+ :param gui_queue: Queue the GUI should read from
+ :return:
+ """
+ layout = [[sg.Text('Multithreaded Window Example')],
+ [sg.Text('', size=(15, 1), key='-OUTPUT-')],
+ [sg.Output(size=(40, 6))],
+ [sg.Button('Exit')], ]
+
+ window = sg.Window('Multithreaded Window', layout)
+ # --------------------- EVENT LOOP ---------------------
+ while True:
+ # wait for up to 100 ms for a GUI event
+ event, values = window.read(timeout=100)
+ if event in (None, 'Exit'):
+ break
+ # --------------- Loop through all messages coming in from threads ---------------
+ while True: # loop executes until runs out of messages in Queue
+ try: # see if something has been posted to Queue
+ message = gui_queue.get_nowait()
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ break # break from the loop if no more messages are queued up
+ # if message received from queue, display the message in the Window
+ if message:
+ window['-OUTPUT-'].update(message)
+ # do a refresh because could be showing multiple messages before next Read
+ window.refresh()
+ print(message)
+ # if user exits the window, then close the window and exit the GUI func
+ window.close()
+
+
+## ## ### #### ## ##
+### ### ## ## ## ### ##
+#### #### ## ## ## #### ##
+## ### ## ## ## ## ## ## ##
+## ## ######### ## ## ####
+## ## ## ## ## ## ###
+## ## ## ## #### ## ##
+
+if __name__ == '__main__':
+ # -- Create a Queue to communicate with GUI --
+ # queue used to communicate between the gui and the threads
+ gui_queue = queue.Queue()
+ # -- Start worker threads, one runs twice as often as the other
+ threading.Thread(target=worker_thread, args=(
+ 'Thread 1', 500, gui_queue,), daemon=True).start()
+ threading.Thread(target=worker_thread, args=(
+ 'Thread 2', 200, gui_queue,), daemon=True).start()
+ threading.Thread(target=worker_thread, args=(
+ 'Thread 3', 1000, gui_queue,), daemon=True).start()
+ # -- Start the GUI passing in the Queue --
+ the_gui(gui_queue)
+ print('Exiting Program')
diff --git a/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py b/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py
deleted file mode 100644
index a682871f6..000000000
--- a/DemoPrograms/Demo_Multithreaded_Signal_Thread_To_End.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import time
-import datetime
-import PySimpleGUI as sg
-
-"""
- Multithreading with signaling to thread when to stop.
- If exiting the program, waits for the thread to finish.
-
- In this example, the thread runs at a rate of twice a second. It sends the time as a string
- The main GUI checks the value sent by the thread to see if it differs from what is displayed.
- If the display is different, then the GUI is updated with the new time.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-
-# dP dP dP
-# 88 88 88
-# d8888P 88d888b. 88d888b. .d8888b. .d8888b. .d888b88
-# 88 88' `88 88' `88 88ooood8 88' `88 88' `88
-# 88 88 88 88 88. ... 88. .88 88. .88
-# dP dP dP dP `88888P' `88888P8 `88888P8
-#
-
-def the_thread(window):
-
- while window.job_running:
- window.write_event_value('-THREAD-', datetime.datetime.now().strftime('%H:%M:%S'))
- time.sleep(0.5)
-
-
-# oo
-#
-# 88d8b.d8b. .d8888b. dP 88d888b.
-# 88'`88'`88 88' `88 88 88' `88
-# 88 88 88 88. .88 88 88 88
-# dP dP dP `88888P8 dP dP dP
-
-def main():
-
- layout = [
- [sg.Text('00:00:00', font=('Courier New', 20, 'bold'), justification='center', expand_x=True, key='-TIME-')],
- [sg.Push(), sg.Button('Start'), sg.Button('Stop')]]
-
- window = sg.Window('Threading', layout, enable_close_attempted_event=True,
- print_event_values=True, # enable to watch the events and values print out
- )
-
- window.job_running = False # Create a member variable to signal to the thread when to stop
- exiting = False # Used when X is clicked
-
- while True:
-
- event, values = window.read()
-
- if event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT:
- if window.job_running: # if thread running, tell it to exit
- window.job_running = False
- exiting = True
- else:
- break # if thread not running then OK to exit
-
- if exiting and event == '-THREAD ENDED-': # If exiting and thread is finished then OK to exit
- break
-
- elif event == 'Start':
- window['Start'].update(disabled=True)
- window.job_running = True
- window.start_thread(lambda: the_thread(window), '-THREAD ENDED-')
-
- elif event == 'Stop':
- window.job_running = False
- window['Start'].update(disabled=False)
-
- elif event == '-THREAD-' and values[event] != window['-TIME-'].get():
- window['-TIME-'].update(values[event])
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py b/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py
deleted file mode 100644
index 2df014ae8..000000000
--- a/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import time
-import PySimpleGUI as sg
-
-
-"""
- Threaded Demo - Uses Window.write_event_value communications
-
- The only PySimpleGUI call allowed from a thread is write_event_value.
- Using a tuple for thread events makes processing them easier to see and understand.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def the_thread(window):
- """
- The thread that communicates with the application through the window's events.
-
- Once a second wakes and sends a new event and associated value to the window
- """
-
- window.write_event_value(('-THREAD-', '-STARTED-'), None) # Tell the GUI the thread started
-
- for i in range(5):
- time.sleep(1)
- window.write_event_value(('-THREAD-', '-PRINT-'), i) # Data sent is a tuple of thread name and counter
- # Note that the thread ended event is sent automatically by PySimpleGUI if you started the thread using window.start_thread
-
-def main():
- """
- The demo will display in the multiline info about the event and values dictionary as it is being
- returned from window.read()
- Every time "Start" is clicked a new thread is started
- Try clicking "Dummy" to see that the window is active while the thread stuff is happening in the background
- """
-
- layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
- [sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
- [sg.T('Input so you can see data in your dictionary')],
- [sg.Input(key='-IN-', size=(30,1))],
- [sg.B('Start A Thread', key='-START-'), sg.B('Dummy'), sg.Button('Exit')] ]
-
- window = sg.Window('Multithreading + Tuple Events', layout)
-
- while True: # Event Loop
- event, values = window.read()
- sg.cprint(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-START-':
- window.start_thread(lambda : the_thread(window), ('-THREAD-', '-ENDED-'))
- if event[0] == '-THREAD-':
- if event[1] == '-PRINT-':
- sg.cprint(f'Data from the thread ', colors='white on purple', end='')
- sg.cprint(f'{values[event]}', colors='white on red')
- elif event[1] == '-ENDED-':
- sg.cprint('Thread has ended', colors='white on blue')
- elif event[1] == '-STARTED-':
- sg.cprint('Thread has started', colors='white on green')
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py b/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py
deleted file mode 100644
index d0b4d42ca..000000000
--- a/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py
+++ /dev/null
@@ -1,89 +0,0 @@
-import threading
-import time
-import PySimpleGUI as sg
-
-"""
- Threaded Demo - Multiwindow Version
-
- This demo uses the write_event_value method in a multi-window environment. Instead of window.read() returning the event to
- the user, the call to read_all_windows is used which will return both the window that had the event along with the event.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-THREAD_EVENT = '-THREAD-'
-PROGRESS_EVENT = '-PROGRESS-'
-
-cp = sg.cprint
-
-
-def the_thread(window, window_prog):
- """
- The thread that communicates with the application through the window's events.
-
- Once a second wakes and sends a new event and associated value to a window for 10 seconds.
-
- Note that WHICH window the message is sent to doesn't really matter because the code
- in the event loop is calling read_all_windows. This means that any window with an event
- will cause the call to return.
- """
- for i in range(10):
- time.sleep(1)
- window.write_event_value(THREAD_EVENT, (threading.current_thread().name, i)) # Data sent is a tuple of thread name and counter
- window_prog.write_event_value(PROGRESS_EVENT, i) # Send a message that the progress bar should be updated
-
-
-def make_progbar_window():
- layout = [[sg.Text('Progress Bar')],
- [sg.ProgressBar(10, orientation='h', size=(15, 20), k='-PROG-')]]
- return sg.Window('Progress Bar', layout, finalize=True, location=(800, 800))
-
-
-def make_main_window():
- layout = [[sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
- [sg.Multiline(size=(65, 20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
- [sg.T('Input so you can see data in your dictionary')],
- [sg.Input(key='-IN-', size=(30, 1))],
- [sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')]]
-
- return sg.Window('Window Main', layout, finalize=True)
-
-
-def main():
- """
- The demo will display in the multiline info about the event and values dictionary as it is being
- returned from window.read()
- Every time "Start" is clicked a new thread is started
- Try clicking "Dummy" to see that the window is active while the thread stuff is happening in the background
- """
-
- main_window = make_main_window()
- window_prog = make_progbar_window()
-
- while True: # Event Loop
- window, event, values = sg.read_all_windows()
- print(window.Title, event, values)
-
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event.startswith('Start'):
- threading.Thread(target=the_thread, args=(main_window, window_prog), daemon=True).start()
- if event == THREAD_EVENT:
- cp(f'Thread Event ', colors='white on blue', end='')
- cp(f'{values[THREAD_EVENT]}', colors='white on red')
- if event == PROGRESS_EVENT:
- cp(f'Progress Event from thread ', colors='white on purple', end='')
- cp(f'{values[PROGRESS_EVENT]}', colors='white on red')
- window_prog['-PROG-'].update(values[event] % 10 + 1) # type: sg.ProgressBar.update()
- if event == 'Dummy':
- window.write_event_value('-DUMMY-', 'pressed')
- if event == '-DUMMY-':
- cp("Dummy pressed")
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Multithreaded_popup.py b/DemoPrograms/Demo_Multithreaded_popup.py
deleted file mode 100644
index 22f0e85c3..000000000
--- a/DemoPrograms/Demo_Multithreaded_popup.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import threading
-import time
-import PySimpleGUI as sg
-import queue
-
-"""
- Threading Demo - "Call popup from a thread"
-
- Can be extended to call any PySimpleGUI function by passing the function through the queue
-
-
- Safest approach to threading is to use a Queue object to communicate
- between threads and maintrhead.
-
- The thread calls popup, a LOCAL function that should be called with the same
- parameters that would be used to call opiup when called directly
-
- The parameters passed to the local popup are passed through a queue to the main thread.
- When a messages is received from the queue, sg.popup is called using the parms passed
- through the queue
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-mainthread_queue:queue.Queue = None
-
-def popup(*args, **kwargs):
- if mainthread_queue:
- mainthread_queue.put((args, kwargs))
-
-def the_thread(count):
- """
- The thread that communicates with the application through the window's events.
-
- Once a second wakes and sends a new event and associated value to the window
- """
- i = 0
- while True:
- time.sleep(2)
- popup(f'Hello, this is the thread #{count}', 'My counter value', i, text_color='white', background_color='red', non_blocking=True, keep_on_top=True, location=(1000-200*count, 400))
- i += 1
-
-
-def process_popup():
- try:
- queued_value = mainthread_queue.get_nowait()
- sg.popup_auto_close(*queued_value[0], **queued_value[1])
- except queue.Empty: # get_nowait() will get exception when Queue is empty
- pass
-
-
-def main():
- """
- The demo will display in the multiline info about the event and values dictionary as it is being
- returned from window.read()
- Every time "Start" is clicked a new thread is started
- Try clicking "Dummy" to see that the window is active while the thread stuff is happening in the background
- """
- global mainthread_queue
-
- mainthread_queue = queue.Queue()
-
- layout = [ [sg.Text('Output Area - cprint\'s route to here', font='Any 15')],
- [sg.Multiline(size=(65,20), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True, reroute_cprint=True)],
- [sg.T('Input so you can see data in your dictionary')],
- [sg.Input(key='-IN-', size=(30,1))],
- [sg.B('Start A Thread'), sg.B('Dummy'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout, finalize=True, keep_on_top=True)
- count = 0
- while True: # Event Loop
- event, values = window.read(timeout=500)
- sg.cprint(event, values) if event != sg.TIMEOUT_EVENT else None
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- process_popup()
- if event.startswith('Start'):
- threading.Thread(target=the_thread, args=(count,), daemon=True).start()
- count += 1
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Net_API_Download_Image.py b/DemoPrograms/Demo_Net_API_Download_Image.py
deleted file mode 100644
index 82a47f5e6..000000000
--- a/DemoPrograms/Demo_Net_API_Download_Image.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-
-
-"""
- Demo of Net API - Download a PNG Image using net_download_file_binary & Display in a Window
-
- This Demo Program shows how to download a binary file (an image) and display it in a window.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-sg.theme('black')
-
-# First the easy case.... display a PNG image
-
-sg.Window('PNG Download', [[sg.Image(sg.net_download_file_binary(r'https://pysimplegui.net/images/tests/powered-by-pysimplegui-5.png'))]]).read(close=True)
-
diff --git a/DemoPrograms/Demo_Net_API_Download_Image_jpg.py b/DemoPrograms/Demo_Net_API_Download_Image_jpg.py
deleted file mode 100644
index d59519e6f..000000000
--- a/DemoPrograms/Demo_Net_API_Download_Image_jpg.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-
-# Only need these imports if using JPGs
-from PIL import Image
-from io import BytesIO
-
-
-"""
- Demo of Net API - Download JPG Image using net_download_file_binary and display in a window
-
- The download is the easiest part. It's the displaying of a JPG that's tricky.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-# Download the binary file (into a variable, not a local file)
-jpg_data = sg.net_download_file_binary(r'https://pysimplegui.net/images/tests/powered-by-pysimplegui-5.jpg')
-
-# Now display a JPG image. It requires converting the image to PNG before using with PySimpleGUI
-# Note a commented out version below of this same code. Here the context manager was removed for simplicity.
-jpg_image = Image.open(BytesIO(jpg_data))
-bio = BytesIO()
-jpg_image.save(bio, format='PNG')
-
-sg.Window('Download JPG', [[sg.Image(data=bio.getvalue())]]).read(close=True)
-
-del bio # delete the BytesIO object since done with it
-
-
-
-
-# This is another implementation using the io module with a context manager
-# The "with" statement makes understanding what's going on a little more difficult
-# but is perhaps the "preferred" method to use.
-"""
-jpg_image = Image.open(BytesIO(jpg_data))
-
-with BytesIO() as bio:
- jpg_image.save(bio, format='PNG')
- data = bio.getvalue()
-
-sg.Window('Download JPG', [[sg.Image(data=data)]]).read(close=True)
-"""
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Nice_Buttons.py b/DemoPrograms/Demo_Nice_Buttons.py
index 835e6a7b3..db911072c 100644
--- a/DemoPrograms/Demo_Nice_Buttons.py
+++ b/DemoPrograms/Demo_Nice_Buttons.py
@@ -6,12 +6,6 @@
import subprocess
import sys
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
orange64 = 'iVBORw0KGgoAAAANSUhEUgAAAiIAAADLCAMAAABkvgh7AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANtvJ99sId5tIt5uI91tJNxuJNxuJttvKN90NN91Ntt3PN52ONx3Otx3PNt4Pdp4Ptx4PepfD+pfEOtgD+piD+tkD+ttD+dnFOdoE+doFOVoFuNqG+JrHOFrHuFsHuRpGORpGuRqGORqGupgEOpiEOpkEOlmEOhnEupoEOpoEupqFettEetsF+tuFOxqFetrGOtsGetvHOxrGOxsGOxtGuxuG+xuHexxFutwH+xxGOxyGOxyGuxxHuBsIOJvJ+NvKORvKONwKeNwKuJxLONyLeJyLuRwKeRwKuRxLOtxIexyIexzJOx0JOx1Ju11KOx2KOx2Kux5Iux4Kux5Le1/LeFyMOFzMuB0NOB1Nux7MOx8MOx8Mu19NO1+NO1+Ntd7RdV8RtN+S9J/TdF/TtV9SNR9Stl5QNl6Qdh6Qth7RK+Tfa+Tfq6Ufr+JZb+JZr+KZ7uMbr6KaL6LaryMbLyNb7yOb7WPdLuNcLqOcLmOcrmPdLOQd7SQdrKReLKRerGSerCTfLCTfrmQde2AN+2AOO2BOu2COu6DPO6EPe6EPsWDV8OFXcOFXsOGXcOGXsaDWMSEWsqCVs+AUM2AUs6CU82CVMqDWMmEWtCAT9CAUMKHYMCIYsCIZMCKZu6FQO6GQe6GQu6HRO6IRe6JRu6KR+6KSO+LSu+MS++MTO+OTe+OTu+OUO+RUu+TVfCNTvCOTvCPUPCQUfCQUvCSU/CRVPCSVPCSVvCUV/CUWPCVWvGWWvGXXPGYXvCWYPGaYfGcYvGcZPKdZvKeZ/GdavKeaPKebfKebvKgavKhbPKibfGibvKjcPGkcfKmdPKiePOod/OpePSpePSqevSrfPSsfPSsfvSqg/SugfWwgvWwhPWyhfWyhvWxi/Wyj/W0ifW2jfa4j/a1kPW2kva2lfW2lvW4kPa6kfa7kva5lvW7lPa8lPW8lve+l/a4mva5nPa6nPa7nva+mPa+mva/nPa8oPa9ovbAm/bAnfXAnvbCofbEo/XGp/bGqPbIqQAAAC/NnaUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAAJXElEQVR4Xu3de3zVdR3H8Xb9/sJh60LlOTtubdIZEyckSdedMzkdZyRGIePmZdqki8s0KllJmtGCTAXRlUAyrireUeZga2JRkooYRWR0JbXMLsIqZ5fT7/L5nRvj9/md0/fhw/Px/fyHP+D33fb4vPj+LvsxXpMA8IREgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgIFEgJF7Ih1Xf3bVsuu/AYXu+mUrL+u8iqbqIcdErvhme0V8SjQCIpwWe+0nli+k2R5NTolc0jYzqpQBcigV+UDltZ57SQ6JfLqyRRXRyiCIis7u7qAhj8B3Ip1tLdg/pFLR0Z+hOR/JbyIrWxGIZCp289E2Ep+J3HzEFqLKy0qhUJUfeUkZnf8lGnYWX4l0tDfTOg5VEqoJNNTXh6EgmaMLBKuaymmcJFLRSfPO5CuRtgitYisPBehDQUFrqC3O2EtUxRdo4Bn8JHJhlNawlNZh85Aj2JQeiRp9JY08nY9Euk+nFUwq1ECLgww1ZTRaS+R8mnk6PpEF8dTDkNIgLQxiHFdNw7U0d9PU07CJdLw+tRUVpy5Cxo19+bz9lYI+n5cNfdhcjWGZf2jsCTTJcDiUmnBR/HKaewqbSHfqQqSJrkLGvuuctZu3jOgBD1u99B7Fg6a+Vwrrk8kNfRX+0XE2+qg527adsc38M723d01yK3lbqhH1SZp7CpfIolnJw4udQk44ddPOn/3q6b+M6K8+/c2vF+jXVw29X/ALI7N+Z3jome+f/QZ7pOG6VCMtl9Dkk7hElifvd0uPs1cb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'
green_pill64 = 'iVBORw0KGgoAAAANSUhEUgAAAYEAAACCCAYAAACgunQ+AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAl2cEFnAAABgQAAAIIAb/yLCQAAGGZJREFUeNrt3XuUXWV9N/Dvb+99bnPOZK7JTBIIF3MBAgElEiIBjEWwVl/f6iIKWhRae9GFlxaKttQQQWyL0db61sWqS1kWqw2vdlWrVqzINZogQtKQGHIDcs/cMnOu++y9n1//mImNM3ufOWdu5yT5ftaKK5x9e05c6/me57KfR1QVRER0ZrLqXQAiIqofhgAR0RmMIUBEdAZz6l2AevrIbkkM+sggQBo2kvUuDxHNrMBBIeYg99C5GFScmQOkcroODP/pAUkN5LDQsrAQgoWqWAjFYgg6IGiBQSsEAgCOJBKOxOP1LjMRzSzX5PMKY0b+swQgD8UggIMAdquF3ZZitwmwO17Ayw9erl69yzzVTpsQeP+vpMOxcI0BVoniGgCLIZCk1dxc77IR0amtZLJZKDwItgB4SgVPB0Vs/Poyzde7bJN1yoaAQOTW3bhGDK43wHUCXMhf9EQ0E0ZCwUDwSwgesw2++09LdGu9yzURp1wIfHCnLAuANQq8SwTz+UufiOqtZLJZVeywBBvUxoavvkb317tM1TolQmDNdok3O7hdgdsBtLPiJ6JGVQqyQ7DwM6P4znmL8ZW1UDP5u06fhg6B23bLbBj8CRQfBNDCyp+IThUjXUb7AXwxl8HXN5ylxXqXKUxDhsBt2+Rs4+CjorglbqfbLVj2RO+lBnCH9H//DCqCssL4gPGAwBv5u1/vb01EM812ACsGWDGBHQMsB7ATgmSrIDFr+E88IxieRzgxJZPNAuiH4stw8eDXLtPj9f7eJ2uoELhlq6SdGD6pij9J2s3tE7lHOavIHTHIHVWU+g1Kxxvn+xHRqSnVLmjqtJDutpCZK3AStaeCa/J5o2ZAgfuKF+ErG6BBvb8X0CAhIBB5/3bcCOBeAHNr6fZRAwztN8gfMxjYG8CcdrN4iajRJFoEzfMsNM+3kOmyamoplEw2qwbbRHDnQ0v1mXp/l7qHwG0vykVG8WUIXlt15a9A7qjB4MsGg/tZ8RNR/TgpQes5FlrOtZFqrz4NSiY7BMW3RfAXX1uqR+pV/rqFwDqItXc7PgaDv6y268d4wLH/9tH/UjAl4+0igq6WBYg5ccTtBGJOAnEngbiTxKQ6AYmoQSn8wEPZd+EFLsq+i7JfwmChDwU3O+m7J1oEHUtstJ5vQ6pcma1ksgcE+PBDS/W79fgXqUsI3PqidBuDByFYXc2vf6+g6N9pMLAnmNAAbiKWwrmzL8S5sy9Ea7oTbenZaE13Ip1sYVVPRACAwATozR7G8XwPBvI9ONi/Bwf79qJn6CAUtdWTTkrQsdhC20IbVmz880smm1Xga6UsPrFh5czOIprxELjlRbkBBl9OWpnzxjvX+EDPtgD9uwxq+f8gFU/jorOuwDmdS7CgcwlamiY0xkxEBGMCvNq3C4cHXsaLBzbhUP++qkNBbKDjAgudF47fMiiZXA7ADsvg1ocu1Rdn6vvNWAgIRG7Zgs+q4MNJK5OpdK4aoH+XQe+O6n/5d7WcjQvnL8fC7mXoajkb7M4houngegX86tAvsffoNuw49AtUU4c6KUHXMguzzh6/j6gU5IYg+KOvL9NvzcT3mZEQWLNd4kkP/wjg3eMFQP6o4uiWAOXc+OVKxFK4aP7rccmCq9DdsmAm/r2IiH6tUM7ixf2bsHX/M+jLjj+229Qp6LrURqKl8o9UN8hlVbDu65fq+un+DtMeAu/bJLOsBL6hwBsrBYDxgSPPB8geHH/EN51owdVL3oYL5i+HVDv6QkQ0jV4+th1bXn0Ge49tG/fcttdYmHOxXbHDomRyOQG+UtqFOzbcOH3vFExrCPz+8zKvrPg2BBdXCoDSgOLwcwG8QuWytKe7sPz8N2FR92Ws/ImoIfVmD+HZvf+FvUe3VRw7SLULui+3EUtFJ8FIEHw/ZXDbg5drYTrKO20h8P7N0hE4eCppZS6MPEmBgb0Gfb8KKu7pk4w1YdWSt+M1c5ZB2NVPRKeA/twxPLb9EfRmD0WeY8WArmU2MnOjf9SOBMHmtll46xcXqjvV5ZyWEHj/ZukIbPzIkcQljsRC1/fXADj0nI9ib/TzLbFw4fwr8Lpz34i4nZjychIRTScFsPfYNmze8ygK5ej3EFoWWJh9cfQSaSWTy4niR02Cm6Z6d7MpD4F3PCPN6Ti+H7MSK6ICICgDh5/z4Q5GP7sjMxfXLX03krH0lJaPiGimGfXx/CtPYtuBn0Wek+m2MGdZ9FTSksnlFNiwZDk+OJXLU09pCKz5maTiDr6jglVRYwBefvz+/wvmLcdlC66BJRNePJSIqOEcHNiDn+/+IVw//H2wVLug+7VO5AtmJwaLH16uH5+qMk1ZCAhEbn4Wj0BxQ9IODwB3SHH4F37k3P+Ek8IVr7ke3S3nTtX3IyJqKMVyDpv2/Cd6sgdDjztJwfwVNuyIlUpLQS4nwL0PX6F/OxXlmbIQuHmTfAzAvVEBUM4pDj/nRy721pxswxsW/Q6a4tw3hohOb6qKLa8+iX2920OPx9KCecsrtAiC3JBl4Z0Pv15/MtmyTEkI3LxJVsHge0kn0xp23C8qDv/SRxAxrt2e7sLrz3szYg4Hf4nozLHr6AvYefi50GOJWYKu1zqRW2qV/NwrloVVD6/QA5Mpw6RD4OZN0qUGTyftzMKw44GrOPJ8AL8U/pzO5vm4/JzVnPdPRGekQwN7sPVA+LYCyVbBnGVO5GCxa3I/9WfhLRsu0vJEn+9MpvBrHhHbmo8NKTuzMOydCDXAsa0BAldD5/d3ZuZh2dmrEGiABtlkh4hoRs1pWYCl6mP7oU1jjrmDit4Xfcy+OLyqVoPXO4O4D8CfT/T5k2oJ3LRRPqKKz0SNA/TtDFDoCZ/J1JLqxLKzVsGa+PbBRESnjQP9u7CnZ2vosdZzbTSfFd4cKPm5rNh4yzdX6saJPHfCIXDTk3I2bDybsDJdYcdzRwyO7w0PgKZ480gATKohQkR0Wnm1bwcODOwee0CA2UttJGZFzBgyuefnDGHlF3+79jeKJ1wLq2B9QtJdYSFSzikGXzahiyPZloNFXZfBwMCYCXdjERGddua2no+sexyDxd4xx/p3BZhzScQmNQaLj2bwZwDur/WZE2oJrHlS/o8F/EvCTo95nVcNcHRrEDkT6LzOi9HaNHv6/zWJiE5BgfHwq8PPohxSicabBbMviugWMvn+QHHl/79Gd9XyvJpbAjc8Kum2BL6UsNPpsMHgoVcNTBmRA8HNyVYE3BmeiCjSOZ0XYM+xrWNWIfVyikKPoqlzbAWblHS7q/l/APCWWp5Vcwi0JPAhBdrD2g9eXpHv0dBuoJidQGfzPPgTn8lERHRGiDkJtGe60Zc/PObY0AGDRKuNsCFVVaxa84S8ecO1+uNqn1VTCKx5XDIC3B7aClBg6BWNXOp5dvN8BOrXtFcwEdGZqi09G0OlXvijek40ALIHDFrOGdstlLDS6ZLJfwLA9IQAFH+oQHvYMEKhR+GVwlsBTfFmJGKpMV+GiIiitaW70JMb+0JwsV+R6lDE0iEVrsGKNY/Jmza8SR+r5hlVh8Atj0pabXwk6YxtBWgA5I+ayFZAS6oDAWcCERHVJBlLIeEkUQ5KY47lDinaFo6tdBNWOu2a/CcBTG0IFGz8gQCdoa2APh1e3TokBJJOE1QUHscCiIhq1pRoRrk4NgS8osIdUsSbx1a8arByzY/l2g1v1ifGu39VIbBunVi4Ch8OGwtQAxT7TOSGyYl4E2cDERFNkG3HYNsOgpA1+As9ingmvDVQ0vyHAExNCGy9Etdainlhg7ql/uFWQFhXkGPFIALOCCIimoSEk0TRy4353C8pyjlFPHxs4Pp3PipzvnO9Hqt076pCQATvi1vptIbMCCoORLcCbNvhYDAR0SSJZUXWs8U+RawppDVgN7WUgsK7AfxDpXuPGwLv+K40Owm8PawVUM4qNIgsG6AKnwPCRESTZosFE7K1sF9UBGXAHrOchIgo3ovJhoATx7ugaAobEHazGpkAAoGvHt8LICKaAirRx9whg1T72PcGVHHx7/5ALvu3t+oLUddW0x30nrA1gow/nEAS3QyAgnsEEBFNlaj61sspUu1jP0/Y6bQr+fcAeCHqnhVD4IZHJd1ksEJD1isq57RCPxAREc0UEwBeQeGkxlbKxuC3Kl1bMQSaPawKBLGwLh0vzxAgImoUXl7hJMdWymJwwZofSPeGt+qRsOsqhoAPrE5aTenRy01rMNwdJMIUICJqBL4LhG0NELebMsWg8EYA3wq7rmIIiGJ1WCvAd8FWABFRA1EDGA+hq4taBqtRawis+aHMhmJpWAgYt9KAMBER1UPgAqHbtiveGHVNZAi4Hq5IWMlU2NRQ3wNbAkREDcYvhw8OK3DW2/9D5n/vbXpw9LFK3UFLBJYVtmIoAmYAEVGj0TJC381KWE1NRa+wBEANIWCwJOzlhMAHE4CIqAEphqeLSsi0fhEsQcjy0pEhoIrFYYmiATgeQETUoCLraIPFYedHtwQUi8PGA9Tw/QAiokZlAkBCBodVsSTs/NAQeOe/yRwArWHHojaPISKi+lOjiKikF4V9GBoCgcH8uJ0KnRmkyu4gIqJGpWa4nh7zuWLuunVirV37m0uRhoaAH6A5ZlWo6hkCRESNK3z1Ztm0EBkAQyd/GBoCImiOWgKarQAiosYlQHgIKGDH0YxqQsAEyIStHIrIriYiImoEKuHdQXGrqalgCpnRn9fWEuB4ABFR44voybECNI/+LDQE1FRoCRARUUPTiLraANW1BKBIRFb4bAkQETW2iPrbNkiM/iw0BCyEr0sNcA8BIqJGF1V/Gx0bD07EiYXQJBGwJUBE1OhM+MeWojj6s6gxgSzs8JuwIUBE1NiievPVQnb0Z+HdQYKsRswOqrwXGRER1ZVGDQyrqldlCGiALMJmB4EtASKiRqa//p/fVA5KpaDalkBgI6ecHUREdOrRyLWDEC8hN/rz8BDwcLxsFYtxO5UKu5FEtBKIiKi+VIGIvWDK3/tDLYz+PDQEbAevqA8NfWHMMASIiBpW1Cqign1hp4eGwI9+T/Nv+aocgI7diYb7CRARNS4NNLQlIAYvhZ0fOdfHKHZqaAgoXxgjImpQJghvCRhgZ9j5lbaXfCksTUwAtgSIiBqUCRD+okCtLQFV7AwdXPA4TZSIqBFpgNC3hV2/WJxIS2BHySsWE85vzhBSBYwPWLF6f10iIjpZ4EW8KGag8UyNIeDH8QunjCKAMdNEAw+w4/X+ukREdLKgHLWRAJ7/wXt1KOxQZAj89ANauu5B2aiKt40+5ruKeIZ9QkREjcR3w1sCgcFPo66puBKQpXgcISEQuCN/YQ4QETWEwBsZExjF9YtFW/B41HUVQ0CBx1y/WIrbyeToA4ErcFJMASKiRhAUNXwfAQO31cXGqOsqvvu76ii2iGIAJ15DPulPOc+9JomIGkU5bxBWVwP4+YaPazHquootgbVr1Vz3j/JDKG4bfczLK9DBJSSIiOrNLylMeeznqsYo8P1K1467O4AafMPV0s1hXULlvCIxi11CRET1VM5p6IBw2SvnPeBfK107bghc04fHn2rHflhYNOYBQ4pkC0OAiKheVIFyVqO2E/vRk7drT6Xrxw2BtWvVrP6SfMNR3DP6mFdU+K7CSTIIiIjqwR3U4aUiRikHpRIM/nm866vaLNJSPFz2SnfFneSYF8eKvYrmsxkCREQzToFin4laK6iv8zj+c7xbiGp1s3xW/708GneSbw471na+xdYAEdEMKx1XZA+Z0GOeX3rgsY/qn493j6q3jRdgfdkvXT1mgBhAoUcxawFDgIhoxihQ6AlvBbhBaUgsfLGa21TdEgCA1X8nT8fs5FVhxzoW23CSVd+KiIgmoTigGNof3gpw/dKXnvi43l7NfapuCQCAGNxfNqVvx52xrYHsQYO2hXxpgIhoumkA5A6HtwLKfinrKD5X7b1qagkIRK5dj2fiTnJl2PGWBRZSHewWIiKaTkP7DQq94XV3OSh9+fE/1Q9Ve6+aWgIK1dUi97te6ZGw1sDQQYNEqw2rprsSEVG1vLwi3xMeAK5fKgjwQC33q6klcMK1n5P/iNvJ3wk7luoQtJ7PbiEioimnQO92A68wtt4u+6USBOufuEPvruWWE/rN7is+ql7pDXEn2Tb6WKFXkWpXJNvYLURENJWGDprIxTsN8HLrLNxf6z0n1BIAgKv/Vu4SxT1h3UKWA8y+hLOFiIimintc0bsjfDZQ2S+V1MLvPnWnjvty2GgT7r2fW8QXDifxHlW9bPSxwAP6dwaYs8zhKqNERJMUuIq+XUHoInFe4LoKfGciAQBMoiUAANd8Vq6C4CcxO5EIO57uttC+yK7TPxsR0alPFTi2xR9eJC6EF7hHEoILfnyXDk7k/pMKAQC4+rNyNwR3RwVB+yIbzXPZHCAimoieHcHwm8EhPM8twcaap+7S7030/pOezHldGff/OIYrjZjftsQaU9v3vxTAsoF0F4OAiKgWA3sCFI5FBMBwN9AXnp5EAADjbC9ZjbVr1ZQ8fCAIvH2hW5sp0LcjQLGP21ESEVVr8BWDoVcjtowc/vN0zMOnJvucSXcHnbDyXllhC/4r5iQyoQ+ygO7LHE4dJSIax9ABg76dQeRxz3dfLftYsfkePTLZZ01ZCADA1Z+RG1Xxz1HjA5YNzFnmINXJICAiCjP4ikH/S9EBUA7cbEzxW4//lT47Fc+b0hAAgDfcK3cIcF9UEIgAnUttzJrPMQIiol9ToHdngMFXTOQpnu/m1MKNG++e2HTQMFMeAgBw1Tq5D4I7ooIAGJ41xFVHiYgANcCxLQFyRyoEQOAWBbj16U/pv9Zw63FNSwgIRK5chy+J4vdjTnQQNM+z0HWpzRfKiOiMZXzg4GYfpYHoutjzXVcVt/9snf7TVD9/WkIAGA6CFffgIUvx7kpBEG8WdL/ORmIWxwmI6MySP6o4+oKPoBx9jue7LoCPblynD05HGaYtBICRFsFa3CuKOyoFgdjA7KU2Ws9jk4CITn9qgN7tAQb2mIrneb6bBfDHGz+t/zJdZZnWEDhh5afkjxVYH3cSTZXOy3QL5i53uB8BEZ22/BJw8Oc+Sscr172e7/aI4KaN6/Qn01meGQkBALhyrbwDBg/FnURrpfMsB+hYYqNtkcWxAiI6bQTl4V//x/eFbwt5Mi9wXzbA/930ad0y3eWasRAAgBV3y3IRfFdgdTp2LFbp3HhG0HWpjUw3xwqI6BSmwPGXDY5tCyr2/QNA2XddAfYZ4PrN9+n+mSjejIYAAFz9SWkrC/4fBO+MVxgnOCHdJei8wEbTHIYBEZ1CdHgv4N4dBu7Q+PWs57tFCNb7Pfj0Lx5Ub6aKOeMhcMLKv5Q/MMADMTveWs35qQ4LnReMvGTGPCCiBqUBMLAvQN/OAOVcFZV/UC4DOAKDWzd9Vh+b6fLWLQQA4HV3ybyYjX8HsCxmx+PVXJOYJWhbaKPtfBtWrJoriIimn19S9O0I0L8rgAmqu2YkAB6VBN7787U6VI9y1zUEAGD1OnHyRXwQgrWOFZsjIlX9zhcBMnMttJ5rYdbZNmcUEdGM80uKwVcMBvbVtlLySOW/D4o7N//15JaCnqy6h8AJ1/yFzC4G+LQl+IBjx2vbnXgkEJrnWkh3WUi1C7uMiGjKqQEKPQa5Iwb5I4r8MVPT9UaDIAiCrACfa0ph/U/v0VK9v1PDhMAJr7tDznEsPATBG6rtIhrzpezhJSlSHRYSrYLELEGiRTjllIiqpgFQGlC4Qwp30CB/TFE4ajDRKtMLyi4Uj4iDj226X/vq/f1OaLgQOOHKT8iqwOBOADfE7Pi4s4iqEc8Mh4EdA6yYwIoBtjPyd3YnEZ1xAg8wnsL4v/n3Yr/CL05N3ej55ZwC3xQL65/9G91Z7+88WsOGwAlX3inLAsUdELwrZsebJn9HIqLpFRjfN8YMieCr5QB/98Ln9WC9yxSl4UPghOUfkwXq4H0iuBXAgol2FRERTRcvKLuq2CTAN+MGGzZ+XvvrXabxnDIhcLLL75DLBbhJFDeqoJuBQET1MjLT5yUFvmkbfGvz53VvvctUi1MyBE624k5Z6StWW4prVbASQIKhQETTZaTSHxLgSVU8oRYef+4B3Vrvck3UKR8CJ1u9TpxCHitNgBsUOA/AJSJYpIDFYCCiWnlBuQyFr4IXBdgOxS8tG08++wC26GlSeZ5WIRD6BdeJdXke56mPRSK4WIBWBWYBaIYgA6AZQFoUtb2bQESnPCMoWIKcKnJQZC0gbwTHLeCgJ3hJA+za8gUcOl0q/DCnfQgQEVE0vj5FRHQGYwgQEZ3BGAJERGcwhgAR0RnsfwCReA5ROFftiwAAADt0RVh0Y29tbWVudABFZGl0ZWQgYnkgUGF1bCBTaGVybWFuIGZvciBXUENsaXBhcnQsIFB1YmxpYyBEb21haW40zfqqAAAAJXRFWHRjcmVhdGUtZGF0ZQAyMDA4LTEwLTE0VDE2OjQwOjIxLTA0OjAwPdgB9gAAACV0RVh0bW9kaWZ5LWRhdGUAMjAwOC0xMC0xNFQxNjo0MDoyMS0wNDowMGJpd8IAAAAASUVORK5CYII='
red_pill64 = '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'
@@ -21,7 +15,7 @@
def image_file_to_bytes(image64, size):
image_file = io.BytesIO(base64.b64decode(image64))
img = Image.open(image_file)
- img.thumbnail(size, Image.LANCZOS)
+ img.thumbnail(size, Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format='PNG')
imgbytes = bio.getvalue()
@@ -32,7 +26,7 @@ def ShowMeTheButtons():
bcolor = ('black', 'black')
wcolor = ('white', 'black')
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
sg.set_options(auto_size_buttons=True, border_width=0,
button_color=sg.COLOR_SYSTEM_DEFAULT)
diff --git a/DemoPrograms/Demo_NonBlocking_Form.py b/DemoPrograms/Demo_NonBlocking_Form.py
index 396f42293..22efe0ed2 100644
--- a/DemoPrograms/Demo_NonBlocking_Form.py
+++ b/DemoPrograms/Demo_NonBlocking_Form.py
@@ -5,10 +5,6 @@
'''
Window that doesn't block
good for applications with an loop that polls hardware
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
def StatusOutputExample():
diff --git a/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py b/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py
index 3a3d497a5..1ac4e5384 100644
--- a/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py
+++ b/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py
@@ -2,12 +2,6 @@
import PySimpleGUI as sg
import time
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Demonstrates a notification window that's partially transparent
# The window slowly fades-in
# Includes a small red-X button to close the window
@@ -15,7 +9,7 @@
# Free online encoder - https://www.base64-image.de/
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
-sg.theme('Topanga')
+sg.change_look_and_feel('Topanga')
sg.set_options(border_width=0, margins=(0, 0))
layout = [[sg.Text('Notification'+' '*14),
diff --git a/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py b/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py
index 078925dcf..25aeaaa87 100644
--- a/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py
+++ b/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py
@@ -1,5 +1,6 @@
import PySimpleGUI as sg
import textwrap
+import time
'''
Notification Window Demo Program
@@ -7,18 +8,12 @@
Displays a small informational window with an Icon and a message in the lower right corner of the display
Option to fade in/out or immediatealy display.
-
- You can click on the notification window to speed things along. The idea is that if you click while fading in, you should immediately see the info. If
- you click while info is displaying or while fading out, the window closes immediately.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
# -------------------------------------------------------------------
# Constants, defaults, Base64 icons
USE_FADE_IN = True
+WINDOW_ALPHA = 0.9
WIN_MARGIN = 60
# colors
@@ -33,7 +28,7 @@
# -------------------------------------------------------------------
-def display_notification(title, message, icon, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, use_fade_in=True, alpha=0.9, location=None):
+def display_notification(title, message, icon, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, use_fade_in=True, location=None):
"""
Function that will create, fade in and out, a small window that displays a message with an icon
The graphic design is similar to other system/program notification windows seen in Windows / Linux
@@ -42,8 +37,7 @@ def display_notification(title, message, icon, display_duration_in_ms=DEFAULT_DI
:param icon: (str) Base64 icon to use. 2 are supplied by default
:param display_duration_in_ms: (int) duration for the window to be shown
:param use_fade_in: (bool) if True, the window will fade in and fade out
- :param alpha: (float) Amount of Alpha Channel to use. 0 = invisible, 1 = fully visible
- :param location: Tuple[int, int] location of the upper left corner of window. Default is lower right corner of screen
+ :param location: Tuple[int, int] locationi of the upper left corner of window. Default is lower right corner of screen
"""
# Compute location and size of the window
@@ -67,25 +61,21 @@ def display_notification(title, message, icon, display_duration_in_ms=DEFAULT_DI
window["-GRAPH-"].draw_text(title, location=(64, 20), color=TEXT_COLOR, font=("Arial", 12, "bold"), text_location=sg.TEXT_LOCATION_TOP_LEFT)
window["-GRAPH-"].draw_text(message, location=(64, 44), color=TEXT_COLOR, font=("Arial", 9), text_location=sg.TEXT_LOCATION_TOP_LEFT)
- # change the cursor into a "hand" when hovering over the window to give user hint that clicking does something
- window['-GRAPH-'].set_cursor('hand2')
+ # change the cursor into a "hand" when hovering over the window. This is a direct call into tkinter, going around PySimpleGUI
+ window["-GRAPH-"].Widget.config(cursor="hand2")
if use_fade_in == True:
- for i in range(1,int(alpha*100)): # fade in
- window.set_alpha(i/100)
- event, values = window.read(timeout=20)
- if event != sg.TIMEOUT_KEY:
- window.set_alpha(1)
- break
+ for i in range(1, int(WINDOW_ALPHA * 100)): # fade in
+ window.set_alpha(i / 100)
+ window.refresh()
+ time.sleep(.02)
event, values = window(timeout=display_duration_in_ms)
- if event == sg.TIMEOUT_KEY:
- for i in range(int(alpha*100),1,-1): # fade out
- window.set_alpha(i/100)
- event, values = window.read(timeout=20)
- if event != sg.TIMEOUT_KEY:
- break
+ for i in range(int(WINDOW_ALPHA * 100), 1, -1): # fade out
+ window.set_alpha(i / 100)
+ window.refresh()
+ time.sleep(.02)
else:
- window.set_alpha(alpha)
+ window.set_alpha(WINDOW_ALPHA)
event, values = window(timeout=display_duration_in_ms)
window.close()
@@ -93,4 +83,4 @@ def display_notification(title, message, icon, display_duration_in_ms=DEFAULT_DI
if __name__ == '__main__':
title = "Action completed successfully"
message = "This message is intended to inform you that the action you have performed has been successful. There is no need for further action."
- display_notification(title, message, img_success, 10000, use_fade_in=True)
\ No newline at end of file
+ display_notification(title, message, img_success, 4000, use_fade_in=True)
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py b/DemoPrograms/Demo_Notification_Window_Multiprocessing.py
deleted file mode 100644
index 1412f96d9..000000000
--- a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py
+++ /dev/null
@@ -1,123 +0,0 @@
-import PySimpleGUI as sg
-import textwrap
-from multiprocessing import Process
-
-'''
- Multiprocessing based Notification Window Demo Program
-
- The PySimpleGUI code for showing the windows themselves ovolved from code supplied by PySimpleGUI user ncotrb
-
- Displays a small informational window with an Icon and a message in the lower right corner of the display
- Option to fade in/out or immediatealy display.
-
- You can click on the notification window to speed things along. The idea is that if you click while fading in, you should immediately see the info. If you click while info is displaying or while fading out, the window closes immediately.
-
- Note - In order to import and use these calls, you must make the call from a "main program".
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-'''
-
-
-# -------------------------------------------------------------------
-# fade in/out info and default window alpha
-WIN_MARGIN = 60
-
-# colors
-WIN_COLOR = "#282828"
-TEXT_COLOR = "#ffffff"
-
-DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS = 3000 # how long to display the window
-DEFAULT_FADE_IN_DURATION = 2000 # how long to fade in / fade out the window
-
-# Base64 Images to use as icons in the window
-image64_error = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAADlAAAA5QGP5Zs8AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAIpQTFRF////20lt30Bg30pg4FJc409g4FBe4E9f4U9f4U9g4U9f4E9g31Bf4E9f4E9f4E9f4E9f4E9f4FFh4Vdm4lhn42Bv5GNx5W575nJ/6HqH6HyI6YCM6YGM6YGN6oaR8Kev9MPI9cbM9snO9s3R+Nfb+dzg+d/i++vt/O7v/fb3/vj5//z8//7+////KofnuQAAABF0Uk5TAAcIGBktSYSXmMHI2uPy8/XVqDFbAAAA8UlEQVQ4y4VT15LCMBBTQkgPYem9d9D//x4P2I7vILN68kj2WtsAhyDO8rKuyzyLA3wjSnvi0Eujf3KY9OUP+kno651CvlB0Gr1byQ9UXff+py5SmRhhIS0oPj4SaUUCAJHxP9+tLb/ezU0uEYDUsCc+l5/T8smTIVMgsPXZkvepiMj0Tm5txQLENu7gSF7HIuMreRxYNkbmHI0u5Hk4PJOXkSMz5I3nyY08HMjbpOFylF5WswdJPmYeVaL28968yNfGZ2r9gvqFalJNUy2UWmq1Wa7di/3Kxl3tF1671YHRR04dWn3s9cXRV09f3vb1fwPD7z9j1WgeRgAAAABJRU5ErkJggg=='
-
-image64_success = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAAEKAAABCgEWpLzLAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAHJQTFRF////ZsxmbbZJYL9gZrtVar9VZsJcbMRYaMZVasFYaL9XbMFbasRZaMFZacRXa8NYasFaasJaasFZasJaasNZasNYasJYasJZasJZasJZasJZasJZasJYasJZasJZasJZasJZasJaasJZasJZasJZasJZ2IAizQAAACV0Uk5TAAUHCA8YGRobHSwtPEJJUVtghJeYrbDByNjZ2tvj6vLz9fb3/CyrN0oAAADnSURBVDjLjZPbWoUgFIQnbNPBIgNKiwwo5v1fsQvMvUXI5oqPf4DFOgCrhLKjC8GNVgnsJY3nKm9kgTsduVHU3SU/TdxpOp15P7OiuV/PVzk5L3d0ExuachyaTWkAkLFtiBKAqZHPh/yuAYSv8R7XE0l6AVXnwBNJUsE2+GMOzWL8k3OEW7a/q5wOIS9e7t5qnGExvF5Bvlc4w/LEM4Abt+d0S5BpAHD7seMcf7+ZHfclp10TlYZc2y2nOqc6OwruxUWx0rDjNJtyp6HkUW4bJn0VWdf/a7nDpj1u++PBOR694+Ftj/8PKNdnDLn/V8YAAAAASUVORK5CYII='
-
-# -------------------------------------------------------------------
-
-def _display_notification(title, message, icon=image64_success, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, fade_in_duration=DEFAULT_FADE_IN_DURATION, alpha=0.9, location=None):
- """
- The PROCESS that is started when a toaster message is to be displayed.
- Note that this is not a user callable function.
- It does the actual work of creating and showing the window on the screen
-
- Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message
- The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window.
- :param title: (str) Text to be shown at the top of the window in a larger font
- :param message: (str) Text message that makes up the majority of the window
- :param icon: (base64) A base64 encoded PNG/GIF image that will be displayed in the window
- :param display_duration_in_ms: (int) Number of milliseconds to show the window
- :param fade_in_duration: (int) Number of milliseconds to fade window in and out
- :param alpha: (float) Alpha channel. 0 - invisible 1 - fully visible
- :param location: Tuple[int, int] Location on the screen to display the window
- :return: (Any) The Process ID returned from calling multiprocessing.Process
- """
- # Compute location and size of the window
- message = textwrap.fill(message, 50)
- win_msg_lines = message.count("\n") + 1
-
- screen_res_x, screen_res_y = sg.Window.get_screen_size()
- win_margin = WIN_MARGIN # distance from screen edges
- win_width, win_height = 364, 66 + (14.8 * win_msg_lines)
-
- layout = [[sg.Graph(canvas_size=(win_width, win_height), graph_bottom_left=(0, win_height), graph_top_right=(win_width, 0), key="-GRAPH-", background_color=WIN_COLOR, enable_events=True)]]
-
- win_location = location if location is not None else (screen_res_x - win_width - win_margin, screen_res_y - win_height - win_margin)
- window = sg.Window(title, layout, background_color=WIN_COLOR, no_titlebar=True,
- location=win_location, keep_on_top=True, alpha_channel=0, margins=(0,0), element_padding=(0,0), grab_anywhere=True, finalize=True)
-
- window["-GRAPH-"].draw_rectangle((win_width, win_height), (-win_width, -win_height), fill_color=WIN_COLOR, line_color=WIN_COLOR)
- window["-GRAPH-"].draw_image(data=icon, location=(20, 20))
- window["-GRAPH-"].draw_text(title, location=(64, 20), color=TEXT_COLOR, font=("Arial", 12, "bold"), text_location=sg.TEXT_LOCATION_TOP_LEFT)
- window["-GRAPH-"].draw_text(message, location=(64, 44), color=TEXT_COLOR, font=("Arial", 9), text_location=sg.TEXT_LOCATION_TOP_LEFT)
- window["-GRAPH-"].set_cursor('hand2')
-
- if fade_in_duration:
- for i in range(1,int(alpha*100)): # fade in
- window.set_alpha(i/100)
- event, values = window.read(timeout=fade_in_duration // 100)
- if event != sg.TIMEOUT_KEY:
- window.set_alpha(1)
- break
- event, values = window(timeout=display_duration_in_ms)
- if event == sg.TIMEOUT_KEY:
- for i in range(int(alpha*100),1,-1): # fade out
- window.set_alpha(i/100)
- event, values = window.read(timeout=fade_in_duration // 100)
- if event != sg.TIMEOUT_KEY:
- break
- else:
- window.set_alpha(alpha)
- event, values = window(timeout=display_duration_in_ms)
-
- window.close()
-
-
-def display_notification(title, message, icon=image64_success, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, fade_in_duration=DEFAULT_FADE_IN_DURATION, alpha=0.9, location=None):
- """
- Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message
- The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window.
- :param title: (str) Text to be shown at the top of the window in a larger font
- :param message: (str) Text message that makes up the majority of the window
- :param icon: (base64) A base64 encoded PNG/GIF image that will be displayed in the window
- :param display_duration_in_ms: (int) Number of milliseconds to show the window
- :param fade_in_duration: (int) Number of milliseconds to fade window in and out
- :param alpha: (float) Alpha channel. 0 - invisible 1 - fully visible
- :param location: Tuple[int, int] Location on the screen to display the window
- :return: (Any) The Process ID returned from calling multiprocessing.Process
- """
- proc = Process(target=_display_notification, args=(title, message, icon, display_duration_in_ms, fade_in_duration, alpha, location))
- proc.start()
- return proc
-
-if __name__ == '__main__':
- proc2 = display_notification('Normal Location', 'This is my notification!')
- proc3 = display_notification('Upper Left', 'This one does not fade in!', icon=image64_error, location=(0,0), fade_in_duration=0)
-
- proc3.join()
- proc2.join()
- print('*** Successfully joined process ***')
diff --git a/DemoPrograms/Demo_Notify_Integration.py b/DemoPrograms/Demo_Notify_Integration.py
deleted file mode 100644
index e17fd91ee..000000000
--- a/DemoPrograms/Demo_Notify_Integration.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import PySimpleGUI as sg
-from notifypy import Notify
-import tempfile
-import base64
-import os
-
-"""
- Demo of Notification integration with PySimpleGUI
-
- You will need to install the py-notifypy package (note spelling!):
- pip install notify-py
-
- Displays an OS created notification
-
- There are more options than those in this Demo... like all PySimpleGUI Demo Programs
- the demo is meant to give you a starting point
-
- For more info about the notifypy package, visit the project's GitHub
- https://github.com/ms7m/notify-py
-
- To show a notification, call the function provided: notify_popout
-
- If you use a base64 icon, then a temp file will be created. If you wish to cleanup these
- temp files (an optional step), then include this line of code when you close the window:
- [os.remove(file) for file in notify_popout.temp_files] if hasattr(notify_popout, 'temp_files') else None
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def notify_popout(title=None, message=None, icon=sg.DEFAULT_BASE64_ICON, app_name=None):
- """
- Show a notification popout window
-
- :param title: Title shown in the notification
- :param message: Message shown in the notification
- :param icon: Icon shown in the notification - defaults to PySimpleGUI icon. Should be a PNG file
- :param app_name: Application name shown in the notification
- """
- if not hasattr(notify_popout, 'temp_files'):
- notify_popout.temp_files = []
-
- notification = Notify()
- notification.title = title
- notification.message = message
- tmp = None
- if isinstance(icon, bytes):
- with tempfile.TemporaryFile(suffix='.png', delete=False) as tmp:
- tmp.write(base64.b64decode(icon))
- tmp.close()
- notification.icon = tmp.name
- elif icon is not None:
- notification.icon = icon
- if app_name is not None:
- notification.application_name = app_name
- notification.send(block=False)
- if tmp is not None:
- notify_popout.temp_files.append(tmp.name)
-
-
-def main():
- """
- A little test application that demonstrates calling the notify_popout function
- """
-
- layout = [ [sg.Text('My Window')],
- [sg.T('Notification message:'), sg.Input(key='-IN-')],
- [sg.B('Show Notification', bind_return_key=True), sg.Button('Exit')] ]
-
- window = sg.Window('My PySimpleGUI Application', layout)
-
- while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Show Notification':
- notify_popout(title=window.Title, message=values['-IN-'], app_name=window.Title)
-
- window.close()
- # enjoy the anti-pattern that cleans up the temp files
- [os.remove(file) for file in notify_popout.temp_files] if hasattr(notify_popout, 'temp_files') else None
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_OpenCV.py b/DemoPrograms/Demo_OpenCV.py
index 05c74bf71..1ade99cdf 100644
--- a/DemoPrograms/Demo_OpenCV.py
+++ b/DemoPrograms/Demo_OpenCV.py
@@ -1,20 +1,16 @@
#!/usr/bin/env python
import PySimpleGUI as sg
+from PIL import Image
import cv2 as cv
-# from PIL import Image
-# import io
+import io
"""
- Demo program to open and play a file using OpenCV
- It's main purpose is to show you:
- 1. How to get a frame at a time from a video file using OpenCV
- 2. How to display an image in a PySimpleGUI Window
-
- For added fun, you can reposition the video using the slider.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+Demo program to open and play a file using OpenCV
+It's main purpose is to show you:
+1. How to get a frame at a time from a video file using OpenCV
+2. How to display an image in a PySimpleGUI Window
+
+For added fun, you can reposition the video using the slider.
"""
@@ -28,43 +24,44 @@ def main():
num_frames = vidFile.get(cv.CAP_PROP_FRAME_COUNT)
fps = vidFile.get(cv.CAP_PROP_FPS)
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
# ---===--- define the window layout --- #
layout = [[sg.Text('OpenCV Demo', size=(15, 1), font='Helvetica 20')],
- [sg.Image(key='-IMAGE-')],
- [sg.Slider(range=(0, num_frames), size=(60, 10), orientation='h', key='-SLIDER-')],
- [sg.Push(), sg.Button('Exit', font='Helvetica 14')]]
+ [sg.Image(filename='', key='-image-')],
+ [sg.Slider(range=(0, num_frames),
+ size=(60, 10), orientation='h', key='-slider-')],
+ [sg.Button('Exit', size=(7, 1), pad=((600, 0), 3), font='Helvetica 14')]]
# create the window and show it without the plot
- window = sg.Window('Demo Application - OpenCV Integration', layout, no_titlebar=False, location=(0, 0))
+ window = sg.Window('Demo Application - OpenCV Integration',
+ layout,
+ no_titlebar=False,
+ location=(0, 0))
# locate the elements we'll be updating. Does the search only 1 time
- image_elem = window['-IMAGE-']
- slider_elem = window['-SLIDER-']
- timeout = 1000//fps # time in ms to use for window reads
-
+ image_elem = window['-image-']
+ slider_elem = window['-slider-']
+
# ---===--- LOOP through video file by frame --- #
cur_frame = 0
while vidFile.isOpened():
- event, values = window.read(timeout=timeout)
+ event, values = window.read(timeout=0)
if event in ('Exit', None):
break
ret, frame = vidFile.read()
if not ret: # if out of data stop looping
break
# if someone moved the slider manually, the jump to that frame
- if int(values['-SLIDER-']) != cur_frame-1:
- cur_frame = int(values['-SLIDER-'])
+ if int(values['-slider-']) != cur_frame-1:
+ cur_frame = int(values['-slider-'])
vidFile.set(cv.CAP_PROP_POS_FRAMES, cur_frame)
slider_elem.update(cur_frame)
cur_frame += 1
- imgbytes = cv.imencode('.ppm', frame)[1].tobytes() # can also use png. ppm found to be more efficient
+ imgbytes = cv.imencode('.png', frame)[1].tobytes() # ditto
image_elem.update(data=imgbytes)
-main()
-
#############
# | | #
# | | #
@@ -80,4 +77,6 @@ def main():
img.save(bio, format= 'PNG') # save image as png to it
imgbytes = bio.getvalue() # this can be used by OpenCV hopefully
image_elem.update(data=imgbytes)
-"""
\ No newline at end of file
+"""
+
+main()
diff --git a/DemoPrograms/Demo_OpenCV_4_Line_Program.py b/DemoPrograms/Demo_OpenCV_4_Line_Program.py
index 841de530d..6430fb066 100644
--- a/DemoPrograms/Demo_OpenCV_4_Line_Program.py
+++ b/DemoPrograms/Demo_OpenCV_4_Line_Program.py
@@ -1,11 +1,4 @@
import cv2, PySimpleGUI as sg
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(key='-IMAGE-')], ], location=(800, 400)), cv2.VideoCapture(0)
+window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(800, 400)), cv2.VideoCapture(0)
while window(timeout=20)[0] is not None:
- window['-IMAGE-'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes())
+ window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes())
diff --git a/DemoPrograms/Demo_OpenCV_7_Line_Program.py b/DemoPrograms/Demo_OpenCV_7_Line_Program.py
index 556b0ecea..82807f79b 100644
--- a/DemoPrograms/Demo_OpenCV_7_Line_Program.py
+++ b/DemoPrograms/Demo_OpenCV_7_Line_Program.py
@@ -1,22 +1,13 @@
import cv2, PySimpleGUI as sg
-
-window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(key='-I-')], ], location=(800, 400))
-cap = cv2.VideoCapture(0) # Setup the camera as a capture device
-while True: # The PSG "Event Loop"
- event, values = window.read(timeout=20) # get events for the window with 20ms max wait
- if event == sg.WIN_CLOSED: break # if user closed window, quit
- window['-I-'].update(data=cv2.imencode('.ppm', cap.read()[1])[1].tobytes()) # Update image in window
+window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')],], location=(800,400))
+cap = cv2.VideoCapture(0) # Setup the camera as a capture device
+while True: # The PSG "Event Loop"
+ event, values = window.read(timeout=20, timeout_key='timeout') # get events for the window with 20ms max wait
+ if event is None: break # if user closed window, quit
+ window['image'].update(data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) # Update image in window
"""
- Putting the comment at the bottom so that you can see that the code is indeed 7 lines long. And, there is nothing
- done out of the ordinary to make it 7 lines long. There are no ; for example. OK, so the if statement is on one line
- but that's the only place that you would traditionally see one more line. So, call it 8 if you want.
-
- NOTE - the encoding format PPM has been shown to be significantly less CPU intensive than using PNG (thank you reporting PySimpleGUI user!)
-
- In some cases however, PPM may not be supported. If you have problems with PPM encoding, then change ".ppm" to ".png" on line 8.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+Putting the comment at the bottom so that you can see that the code is indeed 7 lines long. And, there is nothing
+done out of the ordinary to make it 7 lines long. There are no ; for example. OK, so the if statement is on one line
+but that's the only place that you would traditionally see one more line. So, call it 8 if you want.
"""
\ No newline at end of file
diff --git a/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py b/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py
index 312d1f71a..07a1b9648 100644
--- a/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py
+++ b/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py
@@ -7,17 +7,10 @@
webcam stream, as it's being displayed. To "Draw" simply move your mouse over the image, left click and hold, and
then drag your mouse. You'll see a series of red circles on top of your image.
CURRENTLY ONLY WORKS WITH PySimpleGUI, NOT any of the other ports at this time.
-
- Note also that this demo is using ppm as the image format. This worked fine on all PySimpleGUI ports except
- the web port. If you have trouble with the imencode statement, change "ppm" to "png"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
def main():
- layout = [[sg.Graph((600,450),(0,450), (600,0), key='-GRAPH-', enable_events=True, drag_submits=True)],],
+ layout = [[sg.Graph((600,450),(0,450), (600,0), key='-GRAPH-', enable_events=True, drag_submits=True)],]
window = sg.Window('Demo Application - OpenCV Integration', layout)
graph_elem = window['-GRAPH-'] # type: sg.Graph
@@ -30,15 +23,15 @@ def main():
break
ret, frame = cap.read()
- imgbytes=cv2.imencode('.ppm', frame)[1].tobytes() # on some ports, will need to change to png
+ imgbytes=cv2.imencode('.png', frame)[1].tobytes()
if a_id:
graph_elem.delete_figure(a_id) # delete previous image
a_id = graph_elem.draw_image(data=imgbytes, location=(0,0)) # draw new image
- graph_elem.send_figure_to_back(a_id) # move image to the "bottom" of all other drawings
+ graph_elem.TKCanvas.tag_lower(a_id) # move image to the "bottom" of all other drawings
if event == '-GRAPH-':
graph_elem.draw_circle(values['-GRAPH-'], 5, fill_color='red', line_color='red')
window.close()
-main()
\ No newline at end of file
+main()
diff --git a/DemoPrograms/Demo_OpenCV_Simple_GUI.py b/DemoPrograms/Demo_OpenCV_Simple_GUI.py
index 3401495c8..f0a6cd40d 100644
--- a/DemoPrograms/Demo_OpenCV_Simple_GUI.py
+++ b/DemoPrograms/Demo_OpenCV_Simple_GUI.py
@@ -9,70 +9,85 @@
none: no processing
threshold: simple b/w-threshold on the luma channel, slider sets the threshold value
canny: edge finding with canny, sliders set the two threshold values for the function => edge sensitivity
+contour: colour finding in the frame, first slider sets the hue for the colour to find, second the minimum saturation
+ for the object. Found objects are drawn with a red contour.
blur: simple Gaussian blur, slider sets the sigma, i.e. the amount of blur smear
hue: moves the image hue values by the amount selected on the slider
enhance: applies local contrast enhancement on the luma channel to make the image fancier - slider controls fanciness.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
def main():
- sg.theme('LightGreen')
+ sg.change_look_and_feel('LightGreen')
# define the window layout
layout = [
- [sg.Text('OpenCV Demo', size=(60, 1), justification='center')],
- [sg.Image(filename='', key='-IMAGE-')],
+ [sg.Text('OpenCV Demo', size=(40, 1), justification='center')],
+ [sg.Image(filename='', key='image')],
[sg.Radio('None', 'Radio', True, size=(10, 1))],
- [sg.Radio('threshold', 'Radio', size=(10, 1), key='-THRESH-'),
- sg.Slider((0, 255), 128, 1, orientation='h', size=(40, 15), key='-THRESH SLIDER-')],
- [sg.Radio('canny', 'Radio', size=(10, 1), key='-CANNY-'),
- sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='-CANNY SLIDER A-'),
- sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='-CANNY SLIDER B-')],
- [sg.Radio('blur', 'Radio', size=(10, 1), key='-BLUR-'),
- sg.Slider((1, 11), 1, 1, orientation='h', size=(40, 15), key='-BLUR SLIDER-')],
- [sg.Radio('hue', 'Radio', size=(10, 1), key='-HUE-'),
- sg.Slider((0, 225), 0, 1, orientation='h', size=(40, 15), key='-HUE SLIDER-')],
- [sg.Radio('enhance', 'Radio', size=(10, 1), key='-ENHANCE-'),
- sg.Slider((1, 255), 128, 1, orientation='h', size=(40, 15), key='-ENHANCE SLIDER-')],
+ [sg.Radio('threshold', 'Radio', size=(10, 1), key='thresh'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(40, 15), key='thresh_slider')],
+ [sg.Radio('canny', 'Radio', size=(10, 1), key='canny'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='canny_slider_a'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='canny_slider_b')],
+ [sg.Radio('contour', 'Radio', size=(10, 1), key='contour'),
+ sg.Slider((0, 255), 128, 1, orientation='h', size=(20, 15), key='contour_slider'),
+ sg.Slider((0, 255), 80, 1, orientation='h', size=(20, 15), key='base_slider')],
+ [sg.Radio('blur', 'Radio', size=(10, 1), key='blur'),
+ sg.Slider((1, 11), 1, 1, orientation='h', size=(40, 15), key='blur_slider')],
+ [sg.Radio('hue', 'Radio', size=(10, 1), key='hue'),
+ sg.Slider((0, 225), 0, 1, orientation='h', size=(40, 15), key='hue_slider')],
+ [sg.Radio('enhance', 'Radio', size=(10, 1), key='enhance'),
+ sg.Slider((1, 255), 128, 1, orientation='h', size=(40, 15), key='enhance_slider')],
[sg.Button('Exit', size=(10, 1))]
]
# create the window and show it without the plot
- window = sg.Window('OpenCV Integration', layout, location=(800, 400))
+ window = sg.Window('Demo Application - OpenCV Integration',
+ layout,
+ location=(800, 400),
+ finalize=True)
cap = cv2.VideoCapture(0)
-
while True:
- event, values = window.read(timeout=20)
- if event == 'Exit' or event == sg.WIN_CLOSED:
+ event, values = window.read(timeout=0, timeout_key='timeout')
+ if event == 'Exit' or event is None:
break
ret, frame = cap.read()
- if values['-THRESH-']:
+ if values['thresh']:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)[:, :, 0]
- frame = cv2.threshold(frame, values['-THRESH SLIDER-'], 255, cv2.THRESH_BINARY)[1]
- elif values['-CANNY-']:
- frame = cv2.Canny(frame, values['-CANNY SLIDER A-'], values['-CANNY SLIDER B-'])
- elif values['-BLUR-']:
- frame = cv2.GaussianBlur(frame, (21, 21), values['-BLUR SLIDER-'])
- elif values['-HUE-']:
+ frame = cv2.threshold(frame, values['thresh_slider'], 255, cv2.THRESH_BINARY)[1]
+
+ if values['canny']:
+ frame = cv2.Canny(frame, values['canny_slider_a'], values['canny_slider_b'])
+
+ if values['blur']:
+ frame = cv2.GaussianBlur(frame, (21, 21), values['blur_slider'])
+
+ if values['hue']:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
- frame[:, :, 0] += int(values['-HUE SLIDER-'])
+ frame[:, :, 0] += values['hue_slider']
frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
- elif values['-ENHANCE-']:
- enh_val = values['-ENHANCE SLIDER-'] / 40
+
+ if values['enhance']:
+ enh_val = values['enhance_slider'] / 40
clahe = cv2.createCLAHE(clipLimit=enh_val, tileGridSize=(8, 8))
lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)
lab[:, :, 0] = clahe.apply(lab[:, :, 0])
frame = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)
+ if values['contour']:
+ hue = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
+ hue = cv2.GaussianBlur(hue, (21, 21), 1)
+ hue = cv2.inRange(hue, np.array([values['contour_slider'], values['base_slider'], 40]),
+ np.array([values['contour_slider'] + 30, 255, 220]))
+ cnts = cv2.findContours(hue, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
+ cv2.drawContours(frame, cnts, -1, (0, 0, 255), 2)
+
imgbytes = cv2.imencode('.png', frame)[1].tobytes()
- window['-IMAGE-'].update(data=imgbytes)
+ window['image'].update(data=imgbytes)
window.close()
diff --git a/DemoPrograms/Demo_OpenCV_Webcam.py b/DemoPrograms/Demo_OpenCV_Webcam.py
index 961d9ee0c..8a112d7ab 100644
--- a/DemoPrograms/Demo_OpenCV_Webcam.py
+++ b/DemoPrograms/Demo_OpenCV_Webcam.py
@@ -5,16 +5,12 @@
"""
Demo program that displays a webcam using OpenCV
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
def main():
- sg.theme('Black')
+ sg.change_look_and_feel('Black')
# define the window layout
layout = [[sg.Text('OpenCV Demo', size=(40, 1), justification='center', font='Helvetica 20')],
@@ -33,7 +29,7 @@ def main():
while True:
event, values = window.read(timeout=20)
- if event == 'Exit' or event == sg.WIN_CLOSED:
+ if event == 'Exit' or event is None:
return
elif event == 'Record':
diff --git a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
index fc5236a3a..2d6743702 100644
--- a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
+++ b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
@@ -2,6 +2,8 @@
from PIL import Image
import numpy as np
import PySimpleGUI as sg
+font_size = 6
+USING_QT = False
"""
Interesting program that shows your webcam's image as ASCII text. Runs in realtime, producing a stream of
@@ -20,47 +22,51 @@
pip install opencv-python
On Linux / Mac use pip3 instead of pip
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# The magic bits that make the ASCII stuff work shamelessly taken from https://gist.github.com/cdiener/10491632
chars = np.asarray(list(' .,:;irsXA253hMHGS#9B&@'))
SC, GCF, WCF = .1, 1, 7/4
-sg.theme('Black') # make it look cool with white chars on black background
-font_size = 6
+sg.change_look_and_feel('Black') # make it look cool
# define the window layout
# number of lines of text elements. Depends on cameras image size and the variable SC (scaller)
NUM_LINES = 48
+if USING_QT:
+ layout = [[sg.Text(i, size_px=(800, 12),
+ font=('Courier', font_size),
+ key='-OUT-' + str(i))] for i in range(NUM_LINES)]
+else:
+ layout = [[sg.Text(i, size=(120, 1), font=('Courier', font_size),
+ pad=(0, 0), key='-OUT-'+str(i))] for i in range(NUM_LINES)]
-layout = [[[sg.Text(i, font=('Courier', font_size), pad=(0, 0), key=('-OUT-', i))] for i in range(NUM_LINES)],
- [sg.Text('GCF', s=9, justification='r'), sg.Slider((0.1, 20), resolution=.05, default_value=1, orientation='h', key='-SPIN-GCF-', size=(15, 15))],
- [sg.Text('Font Size', s=9, justification='r'), sg.Slider((4, 20), resolution=1, default_value=font_size, orientation='h', key='-FONT SIZE-', size=(15, 15)),
- sg.Push(), sg.Button('Exit')]]
+layout += [[sg.Button('Exit', size=(5, 1)),
+ sg.Text('GCF', size=(4, 1)),
+ sg.Spin([round(i, 2) for i in np.arange(0.1, 20.0, 0.1)],
+ initial_value=1, key='-SPIN-GCF-', size=(5, 1)),
+ sg.Text('WCF', size=(4, 1)),
+ sg.Slider((1, 4), resolution=.05, default_value=1.75,
+ orientation='h', key='-SLIDER-WCF-', size=(15, 15))]]
# create the window and show it without the plot
-window = sg.Window('Demo Application - OpenCV - ASCII Chars Output', layout, font='Any 18', resizable=True)
+window = sg.Window('Demo Application - OpenCV Integration', layout,
+ location=(800, 400), font='Any 18')
# ---===--- Event LOOP Read and display frames, operate the GUI --- #
# Setup the OpenCV capture device (webcam)
-
cap = cv2.VideoCapture(0)
-
while True:
event, values = window.read(timeout=0)
- if event in ('Exit', sg.WIN_CLOSED):
+ if event in ('Exit', None):
break
# Read image from capture device (camera)
ret, frame = cap.read()
img = Image.fromarray(frame) # create PIL image from frame
GCF = float(values['-SPIN-GCF-'])
- WCF = 1.75
+ WCF = values['-SLIDER-WCF-']
# More magic that coverts the image to ascii
S = (round(img.size[0] * SC * WCF), round(img.size[1] * SC))
img = np.sum(np.asarray(img.resize(S)), axis=2)
@@ -68,8 +74,7 @@
img = (1.0 - img / img.max()) ** GCF * (chars.size - 1)
# "Draw" the image in the window, one line of text at a time!
- font_size = int(values['-FONT SIZE-'])
for i, r in enumerate(chars[img.astype(int)]):
- window[('-OUT-', i)].update("".join(r), font=('Courier', font_size))
+ window['-OUT-'+str(i)].update("".join(r))
window.close()
diff --git a/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py b/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py
index ee1492bf6..f43211d17 100644
--- a/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py
+++ b/DemoPrograms/Demo_OpenCV_Webcam_Minimal.py
@@ -6,13 +6,9 @@
This demo will run on tkinter, Qt, and Web(Remi). The web version flickers at the moment though
To exit, right click and choose exit. If on Qt, you'll have to kill the program as there are no right click menus
in PySimpleGUIQt (yet).
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-sg.theme('Black')
+sg.change_look_and_feel('Black')
# define the window layout
layout = [[sg.Image(filename='', key='-IMAGE-', tooltip='Right click for exit menu')],]
diff --git a/DemoPrograms/Demo_PDF_Viewer.py b/DemoPrograms/Demo_PDF_Viewer.py
index bf4dc66d4..7ad4d690f 100644
--- a/DemoPrograms/Demo_PDF_Viewer.py
+++ b/DemoPrograms/Demo_PDF_Viewer.py
@@ -37,7 +37,7 @@
import PySimpleGUI as sg
from sys import exit
-sg.theme('GreenTan')
+sg.change_look_and_feel('GreenTan')
if len(sys.argv) == 1:
fname = sg.popup_get_file(
@@ -87,6 +87,8 @@ def get_page(pno, zoom=0):
return pix.getPNGData() # return the PNG image
+window = sg.Window(title, layout,
+ return_keyboard_events=True, use_default_focus=False)
cur_page = 0
data = get_page(cur_page) # show page 1 for start
@@ -113,11 +115,6 @@ def get_page(pno, zoom=0):
"Bot-L", "Bot-R", "MouseWheel:Down", "MouseWheel:Up")
zoom_buttons = ("Top-L", "Top-R", "Bot-L", "Bot-R")
-
-
-window = sg.Window(title, layout,
- return_keyboard_events=True, use_default_focus=False)
-
old_page = 0
old_zoom = 0 # used for zoom on/off
# the zoom buttons work in on/off mode.
@@ -126,7 +123,7 @@ def get_page(pno, zoom=0):
event, values = window.read(timeout=100)
zoom = 0
force_page = False
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event in ("Escape:27",): # this spares me a 'Quit' button!
diff --git a/DemoPrograms/Demo_PIL_Color_Picker.py b/DemoPrograms/Demo_PIL_Color_Picker.py
deleted file mode 100644
index b05dbb9d6..000000000
--- a/DemoPrograms/Demo_PIL_Color_Picker.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import PySimpleGUI as sg
-import PIL.ImageGrab
-
-"""
- Color Picker Using Mouse
-
- Move your mouse anywhere on the screen and the window will show you to
- location of the mouse and a square containing the color being shown.
- You're also shown the RGB hex value for the color.
-
- Requires PIL package (and thus only picks colors on primary monitor at the moment)
-
- You can move the window by grabbing it anywhere and dragging it
-
- Pressing the F1 key puts the RBG hex value on the clipboard
- Pressing the F2 key exits
- Clicking moves the window to that location
-
- If you accidently do something that causes the window to lose focus (e.g. click the mouse)
- then the window will move to where your mouse is and force focus back to the window
-
- As always, there is a right click menu with handy options
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [ [sg.Graph((100,100), (0,100), (100,0), key='-GRAPH-')],
- [sg.T(k='-OUT-')],
- [sg.T(k='-OUT LOC-')],
- [sg.T('F1 copy F2 Exit')]]
-
-window = sg.Window('Color Picker', layout, no_titlebar=False, keep_on_top=True, grab_anywhere=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, finalize=True)
-
-window.bind('', '-COPY-')
-window.bind('', 'Exit')
-window.bind('', '-MOVE-')
-
-while True:
- event, values = window.read(timeout=30)
- # print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- sg.popup_quick_message(f'Exiting', background_color='red', text_color='white', keep_on_top=True, font='_ 20', non_blocking=False)
-
- break
- if event == 'Edit Me':
- sp = sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location(), non_blocking=True)
-
- window['-GRAPH-'].erase()
- x, y = window.mouse_location()
- rgb = PIL.ImageGrab.grab().load()[x, y]
- hex_color = sg.rgb(*rgb)
- window['-OUT-'].update(f'{hex_color}')
- window['-OUT LOC-'].update(f'{window.mouse_location()}')
- window['-GRAPH-'].draw_rectangle((0,0), (100,100), hex_color)
-
- if event == '-COPY-':
- sg.clipboard_set(hex_color)
- sg.popup_quick_message(f'{hex_color} copied to clipboard', keep_on_top=True, font='_ 20', non_blocking=True, auto_close_duration=1)
- elif event == '-MOVE-':
- window.move(x,y)
- window.force_focus()
-
-
-window.close()
-
-
diff --git a/DemoPrograms/Demo_PIL_Use.py b/DemoPrograms/Demo_PIL_Use.py
deleted file mode 100644
index a57c8d63c..000000000
--- a/DemoPrograms/Demo_PIL_Use.py
+++ /dev/null
@@ -1,124 +0,0 @@
-import PySimpleGUI as sg
-import PIL
-from PIL import Image
-import io
-import base64
-import random
-
-"""
- Using PIL with PySimpleGUI - for Images and Buttons
-
- The reason for this demo is to give you this nice PIL based function - convert_to_bytes
-
- This function is your gateway to using any format of image (not just PNG & GIF) and to
- resize / convert it so that it can be used with the Button and Image elements.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def make_square(im, fill_color=(0, 0, 0, 0)):
- x, y = im.size
- size = max(x, y)
- new_im = Image.new('RGBA', (size, size), fill_color)
- new_im.paste(im, (int((size - x) / 2), int((size - y) / 2)))
- return new_im
-
-
-
-def convert_to_bytes(source, size=(None, None), subsample=None, zoom=None, fill=False):
- """
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param source: either a string filename or a bytes base64 image object
- :type source: (Union[str, bytes])
- :param size: optional new size (width, height)
- :type size: (Tuple[int, int] or None)
- :param subsample: change the size by multiplying width and height by 1/subsample
- :type subsample: (int)
- :param zoom: change the size by multiplying width and height by zoom
- :type zoom: (int)
- :param fill: If True then the image is filled/padded so that the image is square
- :type fill: (bool)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- """
- if isinstance(source, str):
- image = Image.open(source)
- elif isinstance(source, bytes):
- image = Image.open(io.BytesIO(base64.b64decode(source)))
- else:
- image = PIL.Image.open(io.BytesIO(source))
-
- width, height = image.size
-
- scale = None
- if size != (None, None):
- new_width, new_height = size
- scale = min(new_height/height, new_width/width)
- elif subsample is not None:
- scale = 1/subsample
- elif zoom is not None:
- scale = zoom
-
- resized_image = image.resize((int(width * scale), int(height * scale)), Image.LANCZOS) if scale is not None else image
- if fill and scale is not None:
- resized_image = make_square(resized_image)
- # encode a PNG formatted version of image into BASE64
- with io.BytesIO() as bio:
- resized_image.save(bio, format="PNG")
- contents = bio.getvalue()
- encoded = base64.b64encode(contents)
- return encoded
-
-
-
-
-def random_image():
- return random.choice(sg.EMOJI_BASE64_LIST)
-
-def make_toolbar():
- layout = [[sg.T('❎', enable_events=True, key='Exit')]]
- for i in range(6):
- layout += [[sg.B(image_data = convert_to_bytes(random_image(), (30,30))),
- sg.B(image_data = convert_to_bytes(random_image(), (30,30)))]]
- return sg.Window('', layout, element_padding=(0,0), margins=(0,0), finalize=True, no_titlebar=True, grab_anywhere=True)
-
-def main():
-
- image = random_image()
- size = (60,60)
- image = convert_to_bytes(image, size, fill=False)
-
- layout = [[sg.Button('+', size=(4,2)), sg.Button('-', size=(4,2)), sg.B('Next', size=(4,2)), sg.T(size, size=(10,1), k='-SIZE-')],
- [sg.Image(data=image, k='-IMAGE-')],
- [sg.Button(image_data=image, key='-BUTTON IMAGE-')],]
-
- window = sg.Window('Window Title', layout, finalize=True)
- toolbar = make_toolbar()
-
- while True: # Event Loop
- event_window, event, values = sg.read_all_windows()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '+':
- size = (size[0]+20, size[1]+20)
- elif event == '-':
- if size[0] > 20:
- size = (size[0]-20, size[1]-20)
- elif event in ('Next', '-BUTTON IMAGE-'):
- image = random.choice(sg.EMOJI_BASE64_LIST)
- elif event_window == toolbar:
- image = event_window[event].ImageData
-
- # Resize image and update the window
- image = convert_to_bytes(image, size, fill=True)
- window['-IMAGE-'].update(data=image)
- window['-BUTTON IMAGE-'].update(image_data=image)
- window['-SIZE-'].update(size)
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
index 9936d5e8a..61a24ad79 100644
--- a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
+++ b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
@@ -1,25 +1,11 @@
#!/usr/bin/env python
-import PIL
from PIL import Image
from sys import exit
import PySimpleGUI as sg
import os
import io
-import base64
+import numpy as np
-"""
- Demo PNG Thumbnail Viewer
-
- Displays PNG files from a folder.
-
- OK, so... this isn't the best Demo Program, that's for sure. It's one of the older
- demos in the repo. There are likely better ones to use. The convert_to_bytes function is
- the best thing in this demo.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
thumbnails = {}
@@ -27,62 +13,28 @@
COLUMNS = 8
sg.set_options(border_width=0)
# Get the folder containing the images from the user
+# folder = 'A:/TEMP/pdfs'
folder = sg.popup_get_folder('Image folder to open')
if folder is None:
sg.popup_cancel('Cancelling')
exit(0)
-
-
-def convert_to_bytes(file_or_bytes, resize=None):
- """
- Will convert into bytes and optionally resize an image that is a file or a base64 bytes object.
- Turns into PNG format in the process so that can be displayed by tkinter
- :param file_or_bytes: either a string filename or a bytes base64 image object
- :type file_or_bytes: (Union[str, bytes])
- :param resize: optional new size
- :type resize: (Tuple[int, int] or None)
- :param fill: If True then the image is filled/padded so that the image is not distorted
- :type fill: (bool)
- :return: (bytes) a byte-string object
- :rtype: (bytes)
- """
- if isinstance(file_or_bytes, str):
- img = PIL.Image.open(file_or_bytes)
- else:
- try:
- img = PIL.Image.open(io.BytesIO(base64.b64decode(file_or_bytes)))
- except Exception as e:
- dataBytesIO = io.BytesIO(file_or_bytes)
- img = PIL.Image.open(dataBytesIO)
-
- cur_width, cur_height = img.size
- if resize:
- new_width, new_height = resize
- scale = min(new_height / cur_height, new_width / cur_width)
- img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.LANCZOS)
- with io.BytesIO() as bio:
- img.save(bio, format="PNG")
- del img
- return bio.getvalue()
-#
-# old, original PIL code.
-# def image_file_to_bytes(filename, size):
-# try:
-# image = Image.open(filename)
-# image.thumbnail(size, Image.LANCZOS)
-# bio = io.BytesIO() # a binary memory resident stream
-# image.save(bio, format='PNG') # save image as png to it
-# imgbytes = bio.getvalue()
-# except:
-# imgbytes = None
-# return imgbytes
+def image_file_to_bytes(filename, size):
+ try:
+ image = Image.open(filename)
+ image.thumbnail(size, Image.ANTIALIAS)
+ bio = io.BytesIO() # a binary memory resident stream
+ image.save(bio, format='PNG') # save image as png to it
+ imgbytes = bio.getvalue()
+ except:
+ imgbytes = None
+ return imgbytes
def set_image_to_blank(key):
- img = PIL.Image.new('RGB', (100, 100), (255, 255, 255))
- img.thumbnail((1, 1), PIL.Image.LANCZOS)
+ img = Image.new('RGB', (100, 100), (255, 255, 255))
+ img.thumbnail((1, 1), Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format='PNG')
imgbytes = bio.getvalue()
@@ -91,8 +43,8 @@ def set_image_to_blank(key):
# get list of PNG files in folder
png_files = [os.path.join(folder, f)
- for f in os.listdir(folder) if f.endswith('.png')]
-filenames_only = [f for f in os.listdir(folder) if f.endswith('.png')]
+ for f in os.listdir(folder) if '.png' in f]
+filenames_only = [f for f in os.listdir(folder) if '.png' in f]
if len(png_files) == 0:
sg.popup('No PNG images in folder')
@@ -113,7 +65,7 @@ def set_image_to_blank(key):
# define layout, show and read the window
col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
- [sg.Image(data=convert_to_bytes(png_files[0], (500, 500)), key='image')], ]
+ [sg.Image(data=image_file_to_bytes(png_files[0], (500, 500)), key='image')], ]
layout = [
[sg.Menu(menu)],
@@ -130,11 +82,11 @@ def set_image_to_blank(key):
for x in range(ROWS): # update thumbnails
for y in range(COLUMNS):
- cur_index = display_index + (x * COLUMNS) + y
+ cur_index = display_index + (x * 4) + y
if cur_index < len(png_files):
filename = png_files[cur_index]
if filename not in thumbnails:
- imgbytes = convert_to_bytes(filename, (100, 100))
+ imgbytes = image_file_to_bytes(filename, (100, 100))
thumbnails[filename] = imgbytes
else:
imgbytes = thumbnails[filename]
@@ -144,9 +96,9 @@ def set_image_to_blank(key):
set_image_to_blank((x, y))
event, values = window.read()
- display_index = int(values['-slider-'])
+ display_index = values['-slider-']
# --------------------- Button & Keyboard ---------------------
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event in ('MouseWheel:Down', 'Down:40',) and display_index < len(png_files)-1:
display_index += 4
@@ -176,10 +128,10 @@ def set_image_to_blank(key):
sg.popup('Demo PNG Viewer Program', 'Please give PySimpleGUI a try!')
elif type(event) is tuple:
x, y = event
- image_index = display_index + (x * COLUMNS) + y
+ image_index = display_index + (x * 4) + y
if image_index < len(png_files):
filename = png_files[image_index]
- imgbytes = convert_to_bytes(filename, (500, 500))
+ imgbytes = image_file_to_bytes(filename, (500, 500))
window['image'].update(data=imgbytes)
window['filename'].update(filename)
diff --git a/DemoPrograms/Demo_PNG_Viewer.py b/DemoPrograms/Demo_PNG_Viewer.py
index 5b2f1b1ee..f23c14a17 100644
--- a/DemoPrograms/Demo_PNG_Viewer.py
+++ b/DemoPrograms/Demo_PNG_Viewer.py
@@ -3,13 +3,7 @@
import os
'''
- Simple Image Browser
-
- This is an early demo program, so perhaps not quite as sophisticated as later ones.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ Simple Image Browser based on PySimpleGUI
'''
@@ -22,8 +16,8 @@ def main():
return
# get list of PNG files in folder
- png_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith('.png')]
- filenames_only = [f for f in os.listdir(folder) if f.lower().endswith('.png')]
+ png_files = [folder + '\\' + f for f in os.listdir(folder) if '.png' in f]
+ filenames_only = [f for f in os.listdir(folder) if '.png' in f]
if len(png_files) == 0:
sg.popup('No PNG images in folder')
@@ -33,39 +27,39 @@ def main():
menu = [['File', ['Open Folder', 'Exit']], ['Help', ['About', ]]]
# define layout, show and read the window
- col = [[sg.Text(png_files[0], size=(80, 3), key='-FILENAME-')],
- [sg.Image(filename=png_files[0], key='-IMAGE-', expand_x=True, expand_y=True)],
+ col = [[sg.Text(png_files[0], size=(80, 3), key='filename')],
+ [sg.Image(filename=png_files[0], key='image')],
[sg.Button('Next', size=(8, 2)), sg.Button('Prev', size=(8, 2)),
- sg.Text('File 1 of {}'.format(len(png_files)), size=(15, 1), key='-FILENUM-')]]
+ sg.Text('File 1 of {}'.format(len(png_files)), size=(15, 1), key='filenum')]]
- col_files = [[sg.Listbox(values=filenames_only, size=(60, 30), key='-LISTBOX-', enable_events=True)],
- [sg.Text('Select a file. Use scrollwheel or arrow keys on keyboard to scroll through files one by one.')]]
-
- layout = [[sg.Menu(menu)], [sg.Col(col_files), sg.Col(col, expand_x=True, expand_y=True)]]
-
- window = sg.Window('Image Browser', layout, return_keyboard_events=True, use_default_focus=False)
+ col_files = [[sg.Listbox(values=filenames_only, size=(60, 30), key='listbox')],
+ [sg.Button('Read')]]
+ layout = [[sg.Menu(menu)], [sg.Col(col_files), sg.Col(col)]]
+ window = sg.Window('Image Browser', layout,
+ return_keyboard_events=True,
+ location=(0, 0),
+ use_default_focus=False)
# loop reading the user input and displaying image, filename
- filenum, filename = 0, png_files[0]
+ i = 0
while True:
event, values = window.read()
# --------------------- Button & Keyboard ---------------------
- if event == sg.WIN_CLOSED:
+ if event is None:
break
- elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and filenum < len(png_files)-1:
- filenum += 1
- filename = os.path.join(folder, filenames_only[filenum])
- window['-LISTBOX-'].update(set_to_index=filenum, scroll_to_index=filenum)
- elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33') and filenum > 0:
- filenum -= 1
- filename = os.path.join(folder, filenames_only[filenum])
- window['-LISTBOX-'].update(set_to_index=filenum, scroll_to_index=filenum)
+ elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and i < len(png_files)-1:
+ i += 1
+ elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33') and i > 0:
+ i -= 1
elif event == 'Exit':
break
- elif event == '-LISTBOX-':
- filename = os.path.join(folder, values['-LISTBOX-'][0])
- filenum = png_files.index(filename)
+
+ if event == 'Read':
+ filename = folder + '/' + values['listbox'][0]
+ else:
+ filename = png_files[i]
+
# ----------------- Menu choices -----------------
if event == 'Open Folder':
newfolder = sg.popup_get_folder('New folder', no_window=True)
@@ -73,23 +67,24 @@ def main():
continue
folder = newfolder
- png_files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith('.png')]
- filenames_only = [f for f in os.listdir(folder) if f.lower().endswith('.png')]
+ png_files = [folder + '/' +
+ f for f in os.listdir(folder) if '.png' in f]
+ filenames_only = [f for f in os.listdir(folder) if '.png' in f]
- window['-LISTBOX-'].update(values=filenames_only)
+ window['listbox'].update(values=filenames_only)
window.refresh()
- filenum = 0
+ i = 0
elif event == 'About':
sg.popup('Demo PNG Viewer Program',
'Please give PySimpleGUI a try!')
# update window with new image
- window['-IMAGE-'].update(filename=filename)
+ window['image'].update(filename=filename)
# update window with filename
- window['-FILENAME-'].update(filename)
+ window['filename'].update(filename)
# update page display
- window['-FILENUM-'].update('File {} of {}'.format(filenum + 1, len(png_files)))
+ window['filenum'].update('File {} of {}'.format(i+1, len(png_files)))
window.close()
diff --git a/DemoPrograms/Demo_Paned_Window.py b/DemoPrograms/Demo_Paned_Window.py
index 33c4ef389..0c9aca4c1 100644
--- a/DemoPrograms/Demo_Paned_Window.py
+++ b/DemoPrograms/Demo_Paned_Window.py
@@ -1,12 +1,6 @@
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('GreenTan')
+sg.change_look_and_feel('GreenTan')
col1 = sg.Col([[sg.Text('in pane1', text_color='blue')],
[sg.Text('Pane1')],
@@ -45,7 +39,7 @@
while True: # Event Loop
event, values = window.read()
print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
if event == 'Remove':
window['-COL2-'].update(visible=False)
diff --git a/DemoPrograms/Demo_Password_Login.py b/DemoPrograms/Demo_Password_Login.py
index ee34f2b7a..f33be448f 100644
--- a/DemoPrograms/Demo_Password_Login.py
+++ b/DemoPrograms/Demo_Password_Login.py
@@ -12,10 +12,6 @@
5. Run program again and test your login!
6. Are you paying attention? The first person that can post an issue on GitHub with the
matching password to the hash code in this example gets a $5 PayPal payment
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -37,7 +33,7 @@ def HashGeneratorGUI():
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
password = values['-password-']
@@ -63,15 +59,14 @@ def PasswordMatches(password, a_hash):
login_password_hash = '6adfb183a4a2c94a2f92dab5ade762a47889a5a1' # helloworld
password = sg.popup_get_text(
'Password: (type gui for other window)', password_char='*')
- if password == 'gui': # Remove when pasting into your program
- HashGeneratorGUI() # Remove when pasting into your program
- return # Remove when pasting into your program
- if password and PasswordMatches(password, login_password_hash):
+ if password and password == 'gui': # Remove when pasting into your program
+ HashGeneratorGUI() # Remove when pasting into your program
+ return # Remove when pasting into your program
+ if PasswordMatches(password, login_password_hash):
print('Login SUCCESSFUL')
else:
print('Login FAILED!!')
if __name__ == '__main__':
- sg.theme('DarkAmber')
main()
diff --git a/DemoPrograms/Demo_Pi_LEDs.py b/DemoPrograms/Demo_Pi_LEDs.py
index e2ef2ba9b..23e281092 100644
--- a/DemoPrograms/Demo_Pi_LEDs.py
+++ b/DemoPrograms/Demo_Pi_LEDs.py
@@ -3,12 +3,6 @@
import PySimpleGUI as sg
import time
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# App for Raspberry Pi.
if sys.platform == 'win32':
@@ -70,7 +64,7 @@ def FlashLED():
while True:
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
if event == 'Switch LED':
diff --git a/DemoPrograms/Demo_Pi_Robotics.py b/DemoPrograms/Demo_Pi_Robotics.py
new file mode 100644
index 000000000..a31248727
--- /dev/null
+++ b/DemoPrograms/Demo_Pi_Robotics.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+import sys
+import PySimpleGUI as sg
+
+
+# Robotics design pattern
+# Uses Realtime Buttons to simulate the controls for a robot
+# Rather than sending a single click when a button is clicked, Realtime Buttons
+# send button presses continuously while the button is pressed down.
+# Two examples, one using fancy graphics, one plain.
+
+def RemoteControlExample():
+ # Make a form, but don't use context manager
+ sg.set_options(element_padding=(0,0))
+ back = '#eeeeee'
+
+ sg.set_options(border_width=0,
+ button_color=('black', back),
+ background_color=back,
+ element_background_color=back,
+ text_element_background_color=back)
+
+ mypad = ((50,0),0)
+ layout = [[sg.Text('Robotics Remote Control')],
+ [sg.Text('', justification='center', size=(19,1), key='status')],
+ [ sg.RealtimeButton('', key='Forward', pad=mypad)],
+ [ sg.RealtimeButton('', key='Left', ),
+ sg.RealtimeButton('', key='Right', pad=mypad)],
+ [ sg.RealtimeButton('', key='Reverse', pad=mypad)],
+ [sg.Text('')],
+ [sg.Quit(button_color=('black', 'orange'))]]
+
+ window = sg.Window('Robotics Remote Control', layout, grab_anywhere=False)
+
+ #
+ # Some place later in your code...
+ # You need to perform a ReadNonBlocking on your form every now and then or
+ # else it won't refresh.
+ #
+ # your program's main loop
+ while True:
+ # This is the code that reads and updates your window
+ event, values = window.read(timeout=0, timeout_key='timeout')
+ if event is not None:
+ window['status'].update(event)
+ elif event != 'timeout':
+ window['status'].update('')
+ # if user clicked quit button OR closed the form using the X, then break out of loop
+ if event == 'Quit' or values is None:
+ break
+
+ window.close()
+
+
+def RemoteControlExample_NoGraphics():
+ # Make a form, but don't use context manager
+
+ layout = [[sg.Text('Robotics Remote Control', justification='center')],
+ [sg.Text('', justification='center', size=(19,1), key='status')],
+ [sg.Text(' '*8), sg.RealtimeButton('Forward')],
+ [ sg.RealtimeButton('Left'), sg.Text(' '), sg.RealtimeButton('Right')],
+ [sg.Text(' '*8), sg.RealtimeButton('Reverse')],
+ [sg.Text('')],
+ [sg.Quit(button_color=('black', 'orange'))]]
+ # Display form to user
+ window = sg.Window('Robotics Remote Control', layout, grab_anywhere=False)
+
+ #
+ # Some place later in your code...
+ # You need to perform a Read on your form every now and then or
+ # else it won't refresh.
+ # Notice how the timeout is 100ms. You don't have to use a timeout = 0 for all of your hardware
+ # applications. Leave some CPU for other threads or for your GUI. The longer you are in the GUI, the more
+ # responsive the GUI itself will be Match your timeout with your hardware's capabilities
+ #
+ # your program's main loop
+ while True :
+ # This is the code that reads and updates your window
+ event, values = window.read(timeout=100, timeout_key='timeout')
+ # print(event, values)
+ if event != 'timeout':
+ window['status'].update(event)
+ else:
+ window['status'].update('')
+ # if user clicked quit button OR closed the form using the X, then break out of loop
+ if event in (None, 'Quit'):
+ break
+
+ window.close()
+
+# ------------------------------------- main -------------------------------------
+def main():
+ RemoteControlExample_NoGraphics()
+ # Uncomment to get the fancy graphics version. Be sure and download the button images!
+ RemoteControlExample()
+ # sg.popup('End of non-blocking demonstration')
+
+if __name__ == '__main__':
+
+ main()
diff --git a/DemoPrograms/Demo_Ping_Line_Graph.py b/DemoPrograms/Demo_Ping_Line_Graph.py
new file mode 100644
index 000000000..f3b0b8297
--- /dev/null
+++ b/DemoPrograms/Demo_Ping_Line_Graph.py
@@ -0,0 +1,670 @@
+# !/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+from sys import exit as exit
+from threading import Thread
+import PySimpleGUI as sg
+import time
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+# =============================================================================#
+import argparse
+import os
+import sys
+import socket
+import struct
+import select
+import time
+import signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+# =============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+
+# =============================================================================#
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string) / 2)) * 2
+ sum_val = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ sum_val = sum_val + (hiByte * 256 + loByte)
+ except: # For Python2
+ sum_val = sum_val + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string) - 1]
+ try: # For Python3
+ sum_val += loByte
+ except: # For Python2
+ sum_val += ord(loByte)
+
+ sum_val &= 0xffffffff # Truncate sum_val to 32 bits (a variance from ping.c, which
+ # uses signed ints, but overflow is unlikely in ping)
+
+ sum_val = (sum_val >> 16) + (sum_val & 0xffff) # Add high 16 bits to low 16 bits
+ sum_val += (sum_val >> 16) # Add carry from above (if any)
+ answer = ~sum_val & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+
+# =============================================================================#
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(
+ socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(
+ mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime - sentTime) * 1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+
+# =============================================================================#
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ # destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack("!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size - 8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ # data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack("!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ # Port number is irrelevant for ICMP
+ mySocket.sendto(packet, (destIP, 1))
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+
+# =============================================================================#
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout / 1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack("!BBHHH", icmpHeader)
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ # print (len(recPacket.encode()))
+ return timeReceived, (dataSize + 8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+
+# =============================================================================#
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent -
+ myStats.pktsRcvd) / myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime / myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+
+# =============================================================================#
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+
+# =============================================================================#
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" %
+ (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname,
+ timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ dump_stats(myStats)
+
+
+# =============================================================================#
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return False
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay) / 1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent -
+ myStats.pktsRcvd) / myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+
+# =============================================================================#
+def main():
+ parser = argparse.ArgumentParser(description=__description__)
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='quiet output')
+ parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS,
+ help=('number of packets to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT,
+ help=('time to wait for a response in seoncds '
+ '(default: %(default)s)'))
+ parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE,
+ help=('number of data bytes to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('destination')
+ # args = parser.parse_args()
+
+ ping = verbose_ping
+ # if args.quiet:
+ # ping = quiet_ping
+ ping('Google.com', timeout=1000)
+ # ping(args.destination, timeout=args.timeout*1000, count=args.count,
+ # packet_size=args.packet_size)
+
+
+# set coordinate system
+canvas_right = 300
+canvas_left = 0
+canvas_top = 0
+canvas_bottom = 300
+# define the coordinates you'll use for your graph
+x_right = 100
+x_left = 0
+y_bottom = 0
+y_top = 500
+
+# globale used to communicate with thread.. yea yea... it's working fine
+g_exit = False
+g_response_time = None
+
+
+def ping_thread(args):
+ global g_exit, g_response_time
+
+ while not g_exit:
+ g_response_time = quiet_ping('google.com', timeout=1000)
+
+
+def convert_xy_to_canvas_xy(x_in, y_in):
+ scale_x = (canvas_right - canvas_left) / (x_right - x_left)
+ scale_y = (canvas_top - canvas_bottom) / (y_top - y_bottom)
+ new_x = canvas_left + scale_x * (x_in - x_left)
+ new_y = canvas_bottom + scale_y * (y_in - y_bottom)
+ return new_x, new_y
+
+
+# start ping measurement thread
+thread = Thread(target=ping_thread, args=(None,))
+thread.start()
+
+layout = [[sg.Text('Ping times to Google.com', font='Any 18')],
+ [sg.Canvas(size=(canvas_right, canvas_bottom),
+ background_color='white', key='canvas')],
+ [sg.Quit()]]
+
+window = sg.Window('Ping Times To Google.com',
+ layout, grab_anywhere=True, finalize=True)
+
+canvas = window['canvas'].TKCanvas
+
+prev_response_time = None
+i = 0
+prev_x, prev_y = canvas_left, canvas_bottom
+while True:
+ time.sleep(.2)
+
+ event, values = window.read(timeout=0)
+ if event == 'Quit' or event is None:
+ break
+
+ if g_response_time is None or prev_response_time == g_response_time:
+ continue
+ try:
+ new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0])
+ except:
+ continue
+
+ prev_response_time = g_response_time
+ canvas.create_line(prev_x, prev_y, new_x, new_y, width=1, fill='black')
+ prev_x, prev_y = new_x, new_y
+ if i >= x_right:
+ i = 0
+ prev_x = prev_y = last_x = last_y = 0
+ canvas.delete('all')
+ else:
+ i += 1
+
+# tell thread we're done. wait for thread to exit
+g_exit = True
+thread.join()
+
+window.close()
+exit(0)
diff --git a/DemoPrograms/Demo_Pip_Installs.py b/DemoPrograms/Demo_Pip_Installs.py
deleted file mode 100644
index f84c69cc3..000000000
--- a/DemoPrograms/Demo_Pip_Installs.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-"""
- Obtain the version number for a package installed on any versions of Python on your system by uysing
- the sg.execute_pip_get_local_package_version() call.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-
-layout = [ [sg.T('Package Name:'), sg.In(s=15, setting='', k='-PACKAGE-')],
- [sg.T('Full path to interpreter'), sg.In(setting='', k='-INT-')],
- [sg.CB('Use threading', setting=False, k='-THREADED-')],
- [sg.MLine(s=(80,20), reroute_cprint=True, k='-ML-')],
- [sg.Button('Show', bind_return_key=True), sg.Button('Exit')] ]
-
-window = sg.Window('Get PIP Installed Versions', layout, print_event_values=False, enable_close_attempted_event=True, auto_save_location=True)
-
-while True: # Event Loop
- event, values = window.read()
- if event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT:
- window.settings_save(values)
- break
- if event in (None, 'Exit'):
- break
- if event == 'Show':
- package = values['-PACKAGE-']
- if not package:
- continue
-
- win = window if values['-THREADED-'] else None
-
- out = sg.execute_pip_get_local_package_version(package, interpreter=values['-INT-'] if values['-INT-'] else None, window=win, key='-PIP VER-')
- if win is None:
- if not out:
- out = 'Not Installed'
- sg.cprint(f'Not threaded {package} ', end='', c='white on green')
- sg.cprint(f'version = {out}', end='', c='white on red')
- sg.cprint('')
- elif event == '-PIP VER-':
- out = values[event] if values[event] else 'Not Installed'
- sg.cprint(f'{package} ', end='', c='white on blue')
- sg.cprint(f'version = {out}', end='', c='white on red')
- sg.cprint('')
-
-window.close()
diff --git a/DemoPrograms/Demo_Pong.py b/DemoPrograms/Demo_Pong.py
new file mode 100644
index 000000000..a0f55e7bd
--- /dev/null
+++ b/DemoPrograms/Demo_Pong.py
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+
+import random
+import time
+
+
+"""
+ Pong code supplied by Daniel Young (Neonzz)
+ Modified. Original code: https://www.pygame.org/project/3649/5739
+"""
+
+
+class Ball:
+ def __init__(self, canvas, bat, bat2, color):
+ self.canvas = canvas
+ self.bat = bat
+ self.bat2 = bat2
+ self.playerScore = 0
+ self.player1Score = 0
+ self.drawP1 = None
+ self.drawP = None
+ self.id = self.canvas.create_oval(10, 10, 35, 35, fill=color)
+ self.canvas.move(self.id, 327, 220)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.x = random.choice([-2.5, 2.5])
+ self.y = -2.5
+
+ def checkwin(self):
+ winner = None
+ if self.playerScore >= 10:
+ winner = 'Player left wins'
+ if self.player1Score >= 10:
+ winner = 'Player Right'
+ return winner
+
+ def updatep(self, val):
+ self.canvas.delete(self.drawP)
+ self.drawP = self.canvas.create_text(170, 50, font=(
+ 'freesansbold.ttf', 40), text=str(val), fill='white')
+
+ def updatep1(self, val):
+ self.canvas.delete(self.drawP1)
+ self.drawP1 = self.canvas.create_text(550, 50, font=(
+ 'freesansbold.ttf', 40), text=str(val), fill='white')
+
+ def hit_bat(self, pos):
+ bat_pos = self.canvas.coords(self.bat.id)
+ if pos[2] >= bat_pos[0] and pos[0] <= bat_pos[2]:
+ if pos[3] >= bat_pos[1] and pos[3] <= bat_pos[3]:
+ return True
+ return False
+
+ def hit_bat2(self, pos):
+ bat_pos = self.canvas.coords(self.bat2.id)
+ if pos[2] >= bat_pos[0] and pos[0] <= bat_pos[2]:
+ if pos[3] >= bat_pos[1] and pos[3] <= bat_pos[3]:
+ return True
+ return False
+
+ def draw(self):
+ self.canvas.move(self.id, self.x, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 4
+ if pos[3] >= self.canvas_height:
+ self.y = -4
+ if pos[0] <= 0:
+ self.player1Score += 1
+ self.canvas.move(self.id, 327, 220)
+ self.x = 4
+ self.updatep1(self.player1Score)
+ if pos[2] >= self.canvas_width:
+ self.playerScore += 1
+ self.canvas.move(self.id, -327, -220)
+ self.x = -4
+ self.updatep(self.playerScore)
+ if self.hit_bat(pos):
+ self.x = 4
+ if self.hit_bat2(pos):
+ self.x = -4
+
+
+class pongbat():
+ def __init__(self, canvas, color):
+ self.canvas = canvas
+ self.id = self.canvas.create_rectangle(40, 200, 25, 310, fill=color)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.y = 0
+
+ def up(self, evt):
+ self.y = -5
+
+ def down(self, evt):
+ self.y = 5
+
+ def draw(self):
+ self.canvas.move(self.id, 0, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 0
+ if pos[3] >= 400:
+ self.y = 0
+
+
+class pongbat2():
+ def __init__(self, canvas, color):
+ self.canvas = canvas
+ self.id = self.canvas.create_rectangle(680, 200, 660, 310, fill=color)
+ self.canvas_height = self.canvas.winfo_height()
+ self.canvas_width = self.canvas.winfo_width()
+ self.y = 0
+
+ def up(self, evt):
+ self.y = -5
+
+ def down(self, evt):
+ self.y = 5
+
+ def draw(self):
+ self.canvas.move(self.id, 0, self.y)
+ pos = self.canvas.coords(self.id)
+ if pos[1] <= 0:
+ self.y = 0
+ if pos[3] >= 400:
+ self.y = 0
+
+
+def pong():
+ # ------------- Define GUI layout -------------
+ layout = [[sg.Canvas(size=(700, 400),
+ background_color='black',
+ key='canvas')],
+ [sg.Text(''), sg.Button('Quit')]]
+ # ------------- Create window -------------
+ window = sg.Window('The Classic Game of Pong', layout,
+ return_keyboard_events=True, finalize=True)
+
+ canvas = window['canvas'].TKCanvas
+
+ # ------------- Create line down center, the bats and ball -------------
+ canvas.create_line(350, 0, 350, 400, fill='white')
+ bat1 = pongbat(canvas, 'white')
+ bat2 = pongbat2(canvas, 'white')
+ ball1 = Ball(canvas, bat1, bat2, 'green')
+
+ # ------------- Event Loop -------------
+ while True:
+ # ------------- Draw ball and bats -------------
+ ball1.draw()
+ bat1.draw()
+ bat2.draw()
+
+ # ------------- Read the form, get keypresses -------------
+ event, values = window.read(timeout=0)
+ # ------------- If quit -------------
+ if event is None or event == 'Quit':
+ break
+ # ------------- Keypresses -------------
+ if event is not None:
+ if event.startswith('Up'):
+ bat2.up(2)
+ elif event.startswith('Down'):
+ bat2.down(2)
+ elif event == 'w':
+ bat1.up(1)
+ elif event == 's':
+ bat1.down(1)
+
+ if ball1.checkwin():
+ sg.popup('Game Over', ball1.checkwin() + ' won!!')
+ break
+
+ # ------------- Bottom of loop, delay between animations -------------
+ # time.sleep(.01)
+ canvas.after(10)
+
+ window.close()
+
+if __name__ == '__main__':
+ pong()
diff --git a/DemoPrograms/Demo_Pong_Multiple_Platforms.py b/DemoPrograms/Demo_Pong_Multiple_Platforms.py
index b7c51314d..de9a63321 100644
--- a/DemoPrograms/Demo_Pong_Multiple_Platforms.py
+++ b/DemoPrograms/Demo_Pong_Multiple_Platforms.py
@@ -4,12 +4,6 @@
import PySimpleGUI as sg
import random
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
GAMEPLAY_SIZE = (700, 400)
BAT_SIZE = (20, 110)
STARTING_BALL_POSITION = (327, 200)
@@ -173,7 +167,7 @@ def pong():
event, values = window.read(
timeout=sleep_time) # type: str, str
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event.startswith('Up') or event.endswith('Up'):
bat_2.up(5)
diff --git a/DemoPrograms/Demo_Popup_Custom.py b/DemoPrograms/Demo_Popup_Custom.py
index 2456324c5..32bc6a353 100644
--- a/DemoPrograms/Demo_Popup_Custom.py
+++ b/DemoPrograms/Demo_Popup_Custom.py
@@ -11,10 +11,6 @@
This example is for a DropDown / Combobox Popup. You provide it with a title, a message and the list
of values to choose from. It mimics the return values of existing Popup calls (None if nothing was input)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
diff --git a/DemoPrograms/Demo_Popups.py b/DemoPrograms/Demo_Popups.py
index 0df780e67..6ba21181d 100644
--- a/DemoPrograms/Demo_Popups.py
+++ b/DemoPrograms/Demo_Popups.py
@@ -1,27 +1,28 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-import sys
+
'''
- Usage of Popups in PSG
-
- While this is an older demo, it is a good instroduction to a FEW of the popups available to you.
- Check out the System Call Reference for the full list: http://www.PySimpleGUI.org
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
+ Usage of all Popups in PSG
'''
+
+sg.Print('test')
+sg.popup_get_file('Get file', save_as=True,
+ file_types=(("ALL Files", "*.jpg"),))
+
# Here, have some windows on me....
-[sg.popup_no_wait('No-wait Popup', relative_location=(-500+100*x, -500)) for x in range(10)]
-answer = sg.popup_yes_no('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?')
+[sg.popup_no_wait('No-wait Popup', location=(500+100*x, 500))
+ for x in range(10)]
+answer = sg.popup_yes_no(
+ 'Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?')
if answer == 'No':
- sg.popup_cancel('OK, we will destroy those windows as soon as you close this window')
+ sg.popup_cancel(
+ 'OK, we will destroy those windows as soon as you close this window')
sys.exit()
-sg.popup_no_buttons('Your answer was', answer, relative_location=(0, -200), non_blocking=True)
-text = sg.popup_get_text('This is a call to PopopGetText')
+sg.popup_non_blocking('Your answer was', answer, location=(1000, 600))
+text = sg.popup_get_text(
+ 'This is a call to PopopGetText', location=(1000, 200))
sg.popup_get_file('Get file')
sg.popup_get_folder('Get folder')
sg.popup('Simple popup')
@@ -29,4 +30,5 @@
sg.popup_no_border('No border')
sg.popup_no_frame('No frame')
sg.popup_cancel('Cancel')
-sg.popup_auto_close('This window will Autoclose and then everything else will close too....')
+sg.popup_okCancel('OK Cancel')
+sg.popup_auto_close('Autoclose')
diff --git a/DemoPrograms/Demo_Post_An_Issue.py b/DemoPrograms/Demo_Post_An_Issue.py
deleted file mode 100644
index 0dcc1d35e..000000000
--- a/DemoPrograms/Demo_Post_An_Issue.py
+++ /dev/null
@@ -1,390 +0,0 @@
-import PySimpleGUI as sg
-import webbrowser
-import urllib.parse
-
-"""
- Beta of the GitHub Issue Post Code
-
- This program is going to be inside of PySimpleGUI itself.
-
- It produces Markdown code that
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def _github_issue_post_make_markdown(issue_type, operating_system, os_ver, psg_port, psg_ver, gui_ver, python_ver,
- python_exp, prog_exp, used_gui, gui_notes,
- cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github,
- detailed_desc, code, ):
- body = \
-"""
-### Type of Issue (Enhancement, Error, Bug, Question)
-
-{}
-----------------------------------------
-
-#### Operating System
-
-{} version {}
-
-#### PySimpleGUI Port (tkinter, Qt, Wx, Web)
-
-{}
-
-----------------------------------------
-
-## Versions
-
-Version information can be obtained by calling `sg.main_get_debug_data()`
-Or you can print each version shown in ()
-
-#### Python version (`sg.sys.version`)
-
-{}
-
-#### PySimpleGUI Version (`sg.__version__`)
-
-{}
-
-#### GUI Version (tkinter (`sg.tclversion_detailed`), PySide2, WxPython, Remi)
-
-{}
-""".format(issue_type, operating_system,os_ver, psg_port,python_ver, psg_ver, gui_ver)
-
- body2 = \
-"""
-
-
----------------------
-
-#### Your Experience In Months or Years (optional)
-
-{} Years Python programming experience
-{} Years Programming experience overall
-{} Have used another Python GUI Framework? (tkinter, Qt, etc) (yes/no is fine)
-{}
-
----------------------
-
-#### Troubleshooting
-
-These items may solve your problem. Please check those you've done by changing - [ ] to - [X]
-
-- [{}] Searched main docs for your problem www.PySimpleGUI.org
-- [{}] Looked for Demo Programs that are similar to your goal Demos.PySimpleGUI.org
-- [{}] If not tkinter - looked for Demo Programs for specific port
-- [{}] For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)
-- [{}] Run your program outside of your debugger (from a command line)
-- [{}] Searched through Issues (open and closed) to see if already reported Issues.PySimpleGUI.org
-- [{}] Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed but not released
-
-#### Detailed Description
-
-{}
-
-#### Code To Duplicate
-
-A **short** program that isolates and demonstrates the problem (Do not paste your massive program, but instead 10-20 lines that clearly show the problem)
-
-This pre-formatted code block is all set for you to paste in your bit of code:
-
-```python
-{}
-
-
-```
-
-#### Screenshot, Sketch, or Drawing
-
-
-
- """.format(python_exp, prog_exp, used_gui, gui_notes,
- cb_docs, cb_demos, cb_demo_port, cb_readme_other, cb_command_line, cb_issues, cb_github,
- detailed_desc, code if len(code) > 10 else '# Paste your code here')
-
- return body + body2
-
-
-
-
-
-def _github_issue_post_make_github_link(title, body):
- pysimplegui_url = "https://github.com/PySimpleGUI/PySimpleGUI"
- pysimplegui_issues = f"{pysimplegui_url}/issues/new?"
-
- # Fix body cuz urllib can't do it smfh
- getVars = {'title': str(title), 'body': str(body)}
- return (pysimplegui_issues + urllib.parse.urlencode(getVars).replace("%5Cn", "%0D"))
-
-
-#########################################################################################################
-
-def _github_issue_post_validate(values, checklist, issue_types):
- issue_type = None
- for itype in issue_types:
- if values[itype]:
- issue_type = itype
- break
- if issue_type is None:
- sg.popup_error('Must choose issue type')
- return False
- if values['-OS WIN-']:
- operating_system = 'Windows'
- os_ver = values['-OS WIN VER-']
- elif values['-OS LINUX-']:
- operating_system = 'Linux'
- os_ver = values['-OS LINUX VER-']
- elif values['-OS MAC-']:
- operating_system = 'Mac'
- os_ver = values['-OS MAC VER-']
- elif values['-OS OTHER-']:
- operating_system = 'Other'
- os_ver = values['-OS OTHER VER-']
- else:
- sg.popup_error('Must choose Operating System')
- return False
-
- if os_ver == '':
- sg.popup_error('Must fill in an OS Version')
- return False
-
- checkboxes = any([ values[('-CB-', i)] for i in range(len(checklist))])
- if not checkboxes:
- sg.popup_error('None of the checkboxes were checked.... you need to have tried something...anything...')
- return False
-
- title = values['-TITLE-'].strip()
- if len(title) == 0:
- sg.popup_error("Title can't be blank")
- return False
- elif title[1:len(title)-1] == issue_type:
- sg.popup_error("Title can't be blank (only the type of issue isn't enough)")
- return False
-
- if len(values['-ML DETAILS-']) < 4:
- sg.popup_error("A little more details would be awesome")
- return False
-
- return True
-
-
-
-
-def _github_issue_help():
- heading_font = '_ 12 bold underline'
- text_font = '_ 10'
-
- def HelpText(text):
- return sg.Text(text, size=(80, None), font=text_font)
-
- help_why = \
-""" Let's start with a review of the Goals of the PySimpleGUI project
-1. To have fun
-2. For you to be successful
-
-This form is as important as the documentation and the demo programs to meeting those goals.
-
-The GitHub Issue GUI is here to help you more easily log issues on the PySimpleGUI GitHub Repo. """
-
- help_goals = \
-""" The goals of using GitHub Issues for PySimpleGUI question, problems and suggestions are:
-* Give you direct access to engineers with the most knowledge of PySimpleGUI
-* Answer your questions in the most precise and correct way possible
-* Provide the highest quality solutions possible
-* Give you a checklist of things to try that may solve the problem
-* A single, searchable database of known problems and their workarounds
-* Provide a place for the PySimpleGUI project to directly provide support to users
-* A list of requested enhancements
-* An easy to use interface to post code and images
-* A way to track the status and have converstaions about issues
-* Enable multiple people to help users """
-
- help_explain = \
-""" GitHub does not provide a "form" that normal bug-tracking-databases provide. As a result, a form was created specifically for the PySimpleGUI project.
-
-The most obvious questions about this form are
-* Why is there a form? Other projects don't have one?
-* My question is an easy one, why does it still need a form?
-
-The answer is:
-I want you to get your question answered with the highest quality answer possible as quickly as possible.
-
-The longer answer - For quite a while there was no form. It resulted the same back and forth, multiple questions comversation. "What version are you running?" "What OS are you using?" These waste precious time.
-
-If asking nicely helps... PLEASE ... please fill out the form.
-
-I can assume you that this form is not here to punish you. It doesn't exist to make you angry and frustrated. It's not here for any purpose than to try and get you support and make PySimpleGUI better. """
-
- help_experience = \
-""" Not many Bug-tracking systems ask about you as a user. Your experience in programming, programming in Python and programming a GUI are asked to provide you with the best possible answer. Here's why it's helpful. You're a human being, with a past, and a some amount of experience. Being able to taylor the reply to your issue in a way that fits you and your experience will result in a reply that's efficient and clear. It's not something normally done but perhaps it should be. It's meant to provide you with a personal response.
-
-If you've been programming for a month, the person answering your question can answer your question in a way that's understandable to you. Similarly, if you've been programming for 20 years and have used multiple Python GUI frameworks, then you are unlikely to need as much explanation. You'll also have a richer GUI vocabularly. It's meant to try and give you a peronally crafted response that's on your wavelength. Fun & success... Remember those are our shared goals"""
-
- help_steps = \
-""" The steps to log an issue are:
-1. Fill in the form
-2. Click Post Issue """
- layout = [
- [sg.T('Goals', font=heading_font, pad=(0,0))],
- [HelpText(help_goals)],
- [sg.T('Why?', font=heading_font, pad=(0,0))],
- [HelpText(help_why)],
- [sg.T('FAQ', font=heading_font, pad=(0,0))],
- [HelpText(help_explain)],
- [sg.T('Experience (optional)', font=heading_font)],
- [HelpText(help_experience)],
- [sg.T('Steps', font=heading_font, pad=(0,0))],
- [HelpText(help_steps)],
- [sg.B('Close')]
- ]
- sg.Window('GitHub Issue GUI Help', layout, keep_on_top=True).read(close=True)
-
- return
-
-def main_open_github_issue():
- font_frame = '_ 14'
- issue_types = ('Question', 'Bug', 'Enhancement', 'Error Message')
- # frame_type = [[sg.Radio('Question', 1, size=(10,1), enable_events=True, k='-TYPE: QUESTION-'),
- # sg.Radio('Bug', 1, size=(10,1), enable_events=True, k='-TYPE: BUG-')],
- # [sg.Radio('Enhancement', 1, size=(10,1), enable_events=True, k='-TYPE: ENHANCEMENT-'),
- # sg.Radio('Error Message', 1, size=(10,1), enable_events=True, k='-TYPE: ERROR`-')]]
- frame_type = [[sg.Radio(t, 1, size=(10,1), enable_events=True, k=t)] for t in issue_types]
-
- v_size = (15,1)
- frame_versions = [[sg.T('Python', size=v_size), sg.In(sg.sys.version, size=(20,1), k='-VER PYTHON-')],
- [sg.T('PySimpleGUI', size=v_size), sg.In(sg.ver, size=(20,1), k='-VER PSG-')],
- [sg.T('tkinter', size=v_size), sg.In(sg.tclversion_detailed, size=(20,1), k='-VER TK-')],]
-
- frame_platforms = [ [sg.T('OS '), sg.T('Details')],
- [sg.Radio('Windows', 2, sg.running_windows(), size=(8,1), k='-OS WIN-'), sg.In(size=(8,1),k='-OS WIN VER-')],
- [sg.Radio('Linux', 2,sg.running_linux(), size=(8,1), k='-OS LINUX-'), sg.In(size=(8,1),k='-OS LINUX VER-')],
- [sg.Radio('Mac', 2, sg.running_mac(), size=(8,1), k='-OS MAC-'), sg.In(size=(8,1),k='-OS MAC VER-')],
- [sg.Radio('Other', 2, size=(8,1), k='-OS OTHER-'), sg.In(size=(8,1),k='-OS OTHER VER-')],
- ]
-
-
- frame_experience = [[sg.T('Optional Experience Info')],
- [sg.In(size=(4,1), k='-EXP PROG-'), sg.T('Years Programming')],
- [sg.In(size=(4,1), k='-EXP PYTHON-'), sg.T('Years Writing Python')],
- [sg.CB('Previously programmed a GUI', k='-CB PRIOR GUI-')],
- [sg.T('Share more if you want....')],
- [sg.In(size=(25,1), k='-EXP NOTES-')]]
-
- checklist = (
- ('Searched main docs for your problem', 'www.PySimpleGUI.org'),
- ('Looked for Demo Programs that are similar to your goal ', 'http://Demos.PySimpleGUI.org'),
- ('If not tkinter - looked for Demo Programs for specific port', ''),
- ('For non tkinter - Looked at readme for your specific port if not PySimpleGUI (Qt, WX, Remi)', ''),
- ('Run your program outside of your debugger (from a command line)', ''),
- ('Searched through Issues (open and closed) to see if already reported', 'http://Issues.PySimpleGUI.org'),
- ('Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed vut not released.', ''))
-
- frame_checklist = [[sg.CB(c, k=('-CB-', i)), sg.T(t, k='-T{}-'.format(i), enable_events=True)] for i, (c, t) in enumerate(checklist)]
-
- frame_details = [[sg.Multiline(size=(65,10), font='Courier 10', k='-ML DETAILS-')]]
- frame_code = [[sg.Multiline(size=(80,10), font='Courier 8', k='-ML CODE-')]]
- frame_markdown = [[sg.Multiline(size=(80,10), font='Courier 8', k='-ML MARKDOWN-')]]
-
- top_layout = [ [sg.Col([[sg.Text('Open A GitHub Issue (* = Required Info)', font='_ 15')]], expand_x=True),
- sg.Col([[sg.B('Help')]])],
- [sg.Frame('Title *', [[sg.Input(k='-TITLE-', size=(50,1), font='_ 14', focus=True)]], font=font_frame)],
- sg.vtop([
- sg.Frame('Platform *',frame_platforms, font=font_frame),
- sg.Frame('Type of Issue *',frame_type, font=font_frame),
- sg.Frame('Versions *',frame_versions, font=font_frame),
- sg.Frame('Experience',frame_experience, font=font_frame),
- ]),
- [sg.Frame('Checklist * (note that you can click the links)',frame_checklist, font=font_frame)],
- [sg.HorizontalSeparator()],
- [sg.T(sg.SYMBOL_DOWN + ' If you need more room for details grab the dot and drag to expand', background_color='red', text_color='white')]]
-
- bottom_layout = [
- [sg.TabGroup([[sg.Tab('Details', frame_details), sg.Tab('Code', frame_code), sg.Tab('Markdown', frame_markdown)]], k='-TABGROUP-')],
- # [sg.Frame('Details',frame_details, font=font_frame, k='-FRAME DETAILS-')],
- # [sg.Frame('Minimum Code to Duplicate',frame_code, font=font_frame, k='-FRAME CODE-')],
- [sg.Text(size=(12,1), key='-OUT-')],
- ]
-
- layout_pane = sg.Pane([sg.Col(top_layout), sg.Col(bottom_layout)], key='-PANE-')
-
- layout = [[layout_pane],
- [sg.Col([[sg.B('Post Issue'), sg.B('Create Markdown Only'), sg.B('Quit')]], expand_x=False, expand_y=False)]]
-
- window = sg.Window('Open A GitHub Issue', layout, finalize=True, resizable=True, enable_close_attempted_event=False)
- for i in range(len(checklist)):
- window['-T{}-'.format(i)].set_cursor('hand1')
- window['-TABGROUP-'].expand(True, True, True)
- window['-ML CODE-'].expand(True, True, True)
- window['-ML DETAILS-'].expand(True, True, True)
- window['-ML MARKDOWN-'].expand(True, True, True)
- window['-PANE-'].expand(True, True, True)
- # window['-FRAME CODE-'].expand(True, True, True)
- # window['-FRAME DETAILS-'].expand(True, True, True)
-
- while True: # Event Loop
- event, values = window.read()
- # print(event, values)
- if event in (sg.WINDOW_CLOSE_ATTEMPTED_EVENT, 'Quit'):
- if sg.popup_yes_no( 'Do you really want to exit?',
- 'If you have not clicked Post Issue button and then clicked "Submit New Issue" button '
- 'then your issue will not have been submitted to GitHub.'
- 'Do no exit until you have PASTED the information from Markdown tab into an issue?') == 'Yes':
- break
- if event == sg.WIN_CLOSED:
- break
- if event in ['-T{}-'.format(i) for i in range(len(checklist))]:
- webbrowser.open_new_tab(window[event].get())
- if event in issue_types:
- title = str(values['-TITLE-'])
- if len(title) != 0:
- if title[0] == '[' and title.find(']'):
- title = title[title.find(']')+1:]
- title = title.strip()
- window['-TITLE-'].update('[{}] {}'.format(event, title))
- if event == 'Help':
- _github_issue_help()
- elif event in ('Post Issue', 'Create Markdown Only'):
- issue_type = None
- for itype in issue_types:
- if values[itype]:
- issue_type = itype
- break
- if issue_type is None:
- sg.popup_error('Must choose issue type')
- continue
- if values['-OS WIN-']:
- operating_system = 'Windows'
- os_ver = values['-OS WIN VER-']
- elif values['-OS LINUX-']:
- operating_system = 'Linux'
- os_ver = values['-OS LINUX VER-']
- elif values['-OS MAC-']:
- operating_system = 'Mac'
- os_ver = values['-OS MAC VER-']
- elif values['-OS OTHER-']:
- operating_system = 'Other'
- os_ver = values['-OS OTHER VER-']
- else:
- sg.popup_error('Must choose Operating System')
- continue
- checkboxes = ['X' if values[('-CB-', i)] else ' ' for i in range(len(checklist))]
-
- if not _github_issue_post_validate(values, checklist, issue_types):
- continue
-
- markdown = _github_issue_post_make_markdown(issue_type, operating_system, os_ver, 'tkinter', values['-VER PSG-'], values['-VER TK-'], values['-VER PYTHON-'],
- values['-EXP PYTHON-'], values['-EXP PROG-'], 'Yes' if values['-CB PRIOR GUI-'] else 'No', values['-EXP NOTES-'], *checkboxes, values['-ML DETAILS-'], values['-ML CODE-'])
- window['-ML MARKDOWN-'].update(markdown)
- link = _github_issue_post_make_github_link(values['-TITLE-'], window['-ML MARKDOWN-'].get())
- if event == 'Post Issue':
- webbrowser.open_new_tab(link)
- else:
- sg.popup('Your markdown code is in the Markdown tab', keep_on_top=True)
-
- window.close()
-
-if __name__ == '__main__':
- # sg.theme(sg.OFFICIAL_PYSIMPLEGUI_THEME)
- main_open_github_issue()
diff --git a/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py b/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py
deleted file mode 100644
index 1fa611c8b..000000000
--- a/DemoPrograms/Demo_Program_Desktop_Widget_LED_Clock_Weather.py
+++ /dev/null
@@ -1,249 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import datetime
-import calendar
-import requests
-import webbrowser
-
-'''
- Example of a weather App, using:
- - openweathermap.org
-
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-'''
-
-
-
-NUM_COLS = 5 # Changes number of days in forecast (don't change this)
-
-
-def settings_window(location=(None, None)):
- tsize = 15
- layout = [[sg.Text('Settings')],
- [sg.T('API Key', s=tsize, justification='r'), sg.I(s=35, setting='', k='-api key-')],
- [sg.T('Latitude', s=tsize, justification='r'), sg.I(s=12, setting='', k='-lat-')],
- [sg.T('Longitude', s=tsize, justification='r'), sg.I(s=12, setting='', k='-lon-')],
- [sg.CB('Use F Degrees', s=tsize, setting=True, k='-faren-')],
- [sg.OK(), sg.B('Register with openweathermap.org for API key', k='-register-'), sg.Cancel()],
- ]
-
- window = sg.Window('Settings', layout, location=location)
-
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Cancel':
- break
- if event == 'OK':
- window.settings_save(values)
- break
- if event == '-register-':
- webbrowser.open(r'https://home.openweathermap.org/users/sign_up')
-
- window.close()
-
- return event == 'OK'
-
-
-class GUI():
- lat = 0
- lon = 0
- api_key = ''
- faren = True
- def __init__(self):
- self.blink_count = 0
- sg.theme('black')
- sg.set_options(border_width=0)
-
- # Create clock layout
- clock = [
- [
- sg.Image(data=ledblank, key='-HOUR1-'),
- sg.Image(data=ledblank, key='-HOUR2-'),
- sg.Image(data=ledblank, key='-COLON-'),
- sg.Image(data=ledblank, key='-MIN1-'),
- sg.Image(data=ledblank, key='-MIN2-')]]
-
- # Create the weather columns layout
- weather_cols = []
- for i in range(NUM_COLS):
- weather_cols.append(
- [[sg.T('', size=(4, 1), font='Any 20', justification='center', key='_DAY_' + str(i)), ],
- [sg.Image(data=w1, background_color='black', key='-ICON-' + str(i), pad=((4, 0), 3)), ],
- [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_high_' + str(i), pad=((10, 0), 3))],
- # [sg.T('--', size=(3, 1), justification='center', font='Any 20', key='_low_' + str(i), pad=((10, 0), 3))],
- ])
-
- # Create the overall layout
- layout = [[sg.Column(clock, background_color='black', justification='c')],
- [sg.Column(weather_cols[x], background_color='black') for x in range(NUM_COLS)] + [sg.T('×', enable_events=True, key='Exit')] + [
- sg.T('C' if GUI.faren else 'F', enable_events=True, key='-CELCIUS-')],
- ]
-
- right_click = sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT
- right_click[1].append('Settings')
- # Create the window
- self.window = sg.Window('DarkSky Weather Forecast Widget', layout,
- background_color='black',
- grab_anywhere=True,
- use_default_focus=False,
- no_titlebar=True,
- alpha_channel=.8, # set an alpha channel if want transparent
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT,
- enable_close_attempted_event=True,
- auto_save_location=True,
- finalize=True)
-
- self.colon_elem = self.window.find_element('-COLON-')
- self.hour1 = self.window.find_element('-HOUR1-')
- self.hour2 = self.window.find_element('-HOUR2-')
- self.min1 = self.window.find_element('-MIN1-')
- self.min2 = self.window.find_element('-MIN2-')
-
- self.window['Exit'].set_cursor('hand1')
- self.window['-CELCIUS-'].set_cursor('hand1')
-
- def update_clock(self):
- # update the clock
- now = datetime.datetime.now()
- real_hour = now.hour - 12 if now.hour > 12 else now.hour
- hour1_digit = led_digits[real_hour // 10]
- self.hour1.Update(data=hour1_digit)
- self.hour2.Update(data=led_digits[real_hour % 10])
- self.min2.Update(data=led_digits[int(now.minute) % 10])
- self.min1.Update(data=led_digits[int(now.minute) // 10])
- # Blink the :
- self.colon_elem.Update(data=ledcolon if self.blink_count % 2 else ledblank)
- self.blink_count += 1
-
- def update_weather(self):
- today_weekday = datetime.datetime.today().weekday()
-
- try:
- # Make the API
- units = 'imperial' if GUI.faren else 'metric'
- api_url = f'http://api.openweathermap.org/data/2.5/forecast?lat={GUI.lat}&lon={GUI.lon}&units={units}&appid={GUI.api_key}'
-
- response = requests.get(api_url)
- data = response.json()
- # print(data)
- # Extract relevant information (e.g., temperature, weather conditions)
- i = 0
- for forecast in data["list"]:
- date_time = forecast["dt_txt"]
- if not '12:00:00' in date_time:
- continue
- # print(forecast)
- temp = forecast["main"]["temp"]
- weather_desc = forecast["weather"][0]["description"]
-
- print(f"{date_time}: {temp}°F, {weather_desc}")
- day_element = self.window.find_element('_DAY_' + str(i))
- max_element = self.window.find_element('_high_' + str(i))
- icon_element = self.window.find_element('-ICON-' + str(i))
- day_element.Update(calendar.day_abbr[(today_weekday + i) % 7])
- # sg.Print(icon_data, wait=True)
- try:
- icon_data = weather_icon_dict[weather_desc]
- icon_element.update(icon_data)
- except:
- sg.Print(f'Missing icon data for description: "{weather_desc}"')
- max_element.update(int(temp))
- i += 1
- except requests.RequestException as e:
- print(f"Error fetching data: {e}")
-
-
-def main():
- if not sg.user_settings_get_entry('-api key-', None):
- if not settings_window():
- sg.popup_error('Cancelling setup and exiting')
- exit()
- GUI.lat = sg.user_settings_get_entry('-lat-', 0)
- GUI.lon = sg.user_settings_get_entry('-lon-', 0)
- GUI.api_key = sg.user_settings_get_entry('-api key-', '')
- GUI.faren = sg.user_settings_get_entry('-faren-', True)
-
- # Get the GUI object that is used to update the window
- # location = sg.user_settings_get_entry('-location-', (None, None))
-
- gui = GUI()
-
- # ---------- EVENT LOOP ----------
- last_update_time = 0
- while True:
- # Wake up once a second to update the clock and weather
- event, values = gui.window.read(timeout=1000)
- if event in (None, 'Exit', sg.WIN_CLOSE_ATTEMPTED_EVENT):
- break
- elif event == '-CELCIUS-':
- GUI.faren = not GUI.faren
- sg.user_settings_set_entry('-faren-', GUI.faren)
- gui.window['-CELCIUS-'].update('C' if GUI.faren else 'F')
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.main_get_debug_data()
- elif event == 'Settings':
- if settings_window(gui.window.current_location()): # if settings changed
- GUI.lat = sg.user_settings_get_entry('-lat-', 0)
- GUI.lon = sg.user_settings_get_entry('-lon-', 0)
- GUI.api_key = sg.user_settings_get_entry('-api key-', '')
- GUI.faren = sg.user_settings_get_entry('-faren-', True)
- gui.window['-CELCIUS-'].update('C' if GUI.faren else 'F')
- gui.update_weather()
-
- gui.update_clock()
- # update weather once ever 6 hours
- now = datetime.datetime.now()
- if last_update_time == 0 or (now - last_update_time).seconds >= 60 * 60 * 6 or event == '-CELCIUS-':
- print('*** Updating Weather ***')
- last_update_time = now
- gui.update_weather()
-
-
-led0 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEb0lEQVRoge2Zz4scRRTHP/WqunsDSQjiBvFHSBC8eRJRFAXFgCIYRVBPgrkoiBgU9U/w4iEgHjwEBT2IKHiIiBfBg4oB8SJ4CgHjIXpSE5Ls9HR9PUz1ZGa6dnZ2dmdnlXzh0TPV1a+/9erVq/eqHSB2GWzZBHK4TmpW7EpSIdfokuwE4jrv12QDk40LhNElNmapluFNZtws8bdEsQCCrb69zvEL0FP3DQLk0nUf6P6y1A8hSKAeKG6jNEmnQG8Xhe5cWZE5p5ZHy3mM1GHQz2Z6YGVF33ovgeqkZDukn65vVpVeDUFfr6wIM9k0UgdBa6DfvNc9VaWvErFeGuW80h8Z3Imi0PGqkkCny1KYyY+Q6qw+A64AtzUNn0k8GwI9M56oayLzxxABzjleCgFvxqleb3DDddd5NiT4dL01Rr6oa54pS9aKgqMSl+YgFoG9wFtm7JE42evRkyjJh54sqRZ9YFXi07rmLjMuJEWbXY0B+Ac4Dpysa2qmD6xDavSFnsEoVyVWm4bzEg35gLcRKYA7wuDXRsE561M28R8GVptFYQ5t/yYTj6aSagPnJKlJDNfsJtD2n3Uw3fdnVsNOo0PKwdKJ/YcstSDM71ObeHhR6FpqN04fsHS/2lGfmhU76lNbcvRF5eez7pkbOnpcr+McaPe03KCV6TdsvApccY4KqIESOGvG7yOb6bzT+6MEZvgYqRlkIRdTojypc5iGtnnysbLUFTMJ9Kv3OhLCIGV1Tm5O8c4JMz1fluon3WdC0KrZWDre2kc5Yk+GoJ+KQoeKQjg3mdjPJQGE9zpeFPq+KHRDCDlC6hSjMJjT6BzmPcSIYqSZc8omUQDRDOccagZaJ3V3/NcYJHT3ec8nzrHfORqzbXP02jke854PzSicoyHvo52pu9d7/ZlKq++81w1FIcw6Zt6MeBBmejQEXUw+ddp7VdN8qm280XtdSISupjrtTAja5/3At+Zw8uCccE5Hi0I9M8UR3aeqSjg3VvcNZ6U14T7nOJCWf8lgvu9uGm4fqXO1SWmfe9iMIkb6XItFtwA4N+bYHVfRxBy3NeCsSf809JOOUf2tk4+2zey/25HSWEZHTuvST/Jy9l86qRyWTuq6pWaFMqt6+aQybUsnlcPSSf3/LLUdxUTOqXN6px4vAsPD17bjVg7NQtpmRvfX4YY9K6kmdTjrPefSg3FiR58FbUV0JkZwDpOm6lj3g5HSzfPe82JR8EFdc8iMNTZvqQjsBz4GXi5L3kunw7C+W4xlnYdDGFYyfzinB8tS36Skr2H614Rp0j77elXpRDrYF+jzVJhkk7xRhgG45BzPlSWvNQ0PNQ29dK+ZU8Qg939nbY3LMfJGOinuzxLRA3DZjKfKkhdi5FjTcJVryd5WUQPv1zXnvOfdEDiwTr+xHP1ICHp6zx59lKasv4UpmyrO6ZWq0uNV1Skcxuq+9s9BMx6Jkb+20UKjiAzy/55zfAmdkJAtRrONC8KGX0ZHsQgL5ZCrvHfSKDNjV27I/wIpihClbBNQxAAAAABJRU5ErkJggg=='
-
-led1 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACD0lEQVRoge2Yv27UQBCHv9kkRCAhXgAkSh6AmoKCFFBENLwBFQ0PQIPES0BJky4NDR0lJT28A4ICQc7nH4V3FccZ+9zcrAv/pJVP3jntp525+XMGiIUp1QbwtELN1Qo1V1WhLK+hqkEVIC8fVYFKdDB3gLvW3ZUN9qsAmRlnKfEoQ6WBTShQCxybcW7Gk7blt2N3GAVkGegmcA6ctC0AB45tyE2VgL5txifgROLfhH0YFMBH4DGwYdpFIVBtft5XlwA8l/UVGujtbhMgGMrL3p7W2rcrlor2DtV32dHM7+wdSiOfp7TG1FytUHO1Qnllpko7bL3n3N4pJE+VFvhLftf09n/Kz16KXO/NJJBAr8wEKF23i4GxvDDTh5T0OqUxII2NXntRiavGDJM4pOtChwqfZhrgDfDCjA3jnUOY+zDT2xxTf0Gnea9KTJVD36UkgS5ALWgDeugEe+jg8DTPegnY0k009/JetbF92wMoEFu73rmHB/oVOUCuXbS2zrvqUF6RrgIlLmPKy9zrTXlaJNQi3bc8KGmBUCwgphYzOPRVeqdd/1OFQJVDvuVa1y8tcgaHEKhy7EvgsxlHXE401dxXysqFxHO6UevGhH1YTCkf9kfiFPiaXdk4tuG/vgT8Ap4B31PilmMXOmIVHdAF+wMzGuCHdAWkClQ5mJHDq2X0/q0MVe2mplS99nlaJNR/DW4BrSasyZkAAAAASUVORK5CYII='
-
-led2 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADmElEQVRoge2Zz4scRRiGn7d6NlHJQaKoKHgwxGgiIpiTegrI4kEUkdwEQcRF8pdI0INIrorkoqB48SB4EhQUvSoIIkjixaiExdnNTtfrYaqyPZmamZ6e7GQC88JHM71dVU999ev7tgSYFVO41QAlraHaaiWheqWXSrYMxQnt39LVVwLolT64T+Jem22gOgAQM5w3hyV+8bhPisN3GPhU4qTNf5M+WgBIwCFgS+KqxKU4Oohj3ssvHpL4UuLJGKm5OR7LDQl4NQQeBp4A3oiRCqjT38dWX3btJZszwA8SFbCXCnW1AfteerGqOCLxboz00/A1F1ZxS4gMPXMlRjaB7yQ2UsGqgwWGU0DACxKPxMiHdT0GkzVxutSpsn9sNiU+riqetulP6skM9YA303Q4b7MD3DEvFAw9JmDb5pU07l3UA/rAOeC8zd6MhmcurDwPSJV1UZ7gpwrzpxNUrvQ6XAflcqXdu6S5tqCuW39zK2ijlTyQ11BttYZqq6VCSe3W39pTbbWSUK139EWSidzz0jFTOiVaQYVUuO3ZdaNyuRxlNM/RuUOXDBSBu4GjDOOseT3WA/4CvgbeSnA5fPl3QhlPspCexyX/KjmC++DdOa0PNnhL8supHoM/l3xIMmCNtl0GqtLz8RD8u2SD61RZF8sgWyH4tRB8MQRXZaAyVAaS5O8T0G6quKvVqQ6DXwrBgDfKQONQecjOSH5P8mnJlxue6go1SEDvSw6pnQlAo1AZ6JkQfCVV8kEIfqyqfDkEW3KU7DmtTs93koemwBjw9dWXV9mDEl/YHAV2gbdj5M4QOC1xXOoUpwu4BvwUY+uVO+KlU8kb2e0Gb4MfyPNsRi+n2YwhG/dUVt7omvl8c2+qGu/nVT37E6CweZaOkyZIvQBUW63kgbyGaqvbG+qgJ3dTt7enlqk1VFu1guoam3dVq8Qh/wMW9pOILhLtzr+pUANgA/hR4k8Am7gAFOyHSJ2g6gbQuRD4LEbuSfHUvNlMBI4AH0lciJEeww5P00g8dVLyIIW/P4NPhOBvQlg4ccj2eoo+e9NjqlGoEyl0/U3yoyH4q0biMFjA9nKnJJ9NWcwUsFGopyT/EYKPVZU/SUA7qcJFbS8BXgNvJo+FaVA5TD0m+bmq8sU0ZDkLuVmWQ+wdyc9PABu5xco/7geeZZhSH8R9Xw3cBfwt8a09dpVWvFrjxpdLVvG6Vizn/DEreodc0koeyP8DbP/uIBO2okgAAAAASUVORK5CYII='
-
-led3 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADoUlEQVRoge2ZzascRRTFf6d7TCLBaALiImAIRoObJzqu3JiVCzH/QEACLlyI4sdCiArqwp2gG/8BcavgB7gRsgquRRBc+lwEBTExEMzLdB8XVTWv01090zPznPcgc6FopvtO1al7q+qee0uAOWBS7DeAnGxADZUDCWrU92EdaE1+l6nn/dokB2CUUzguccLmJlD+D0Aq4BBQS/zurk267pM4AnwFbAH/ZJVWB1QB54GbwF/cabGO9UqJSuJUXfMDcAao2Zs15jjgBHgWeA44DFwiTHwS9TpjVTalzW8S54Cfo9JOnN2y7XYEdAN4WuIJ4H2CJ/omMG2KzxKM5OOSr4ANruJz0VbH5zXwGcmvN769G8cbNTB0lksycQWUNn9LvAB8ATwK/Jsz7wxx1K+AF4ELwIexnyNxrLmWarcCXEgzdea1ZIV3onV2YjP4vYyl5k66js9VFnraSY8r2EX0WwgG7va+k3eoJACTmVq7stbYV2YOypwcyIB894Jqho8hcvdaalHZgBoqG1BDpRNmJOHWyZuYw9At3ZaSwBLqzLfcGT8o9pXxz7lOh0g1Y7BcDpAF1bRWmuWx2JYBNgL+BL6XuGBP+RrA1dz4ZCyoRDFsaomzwNc2pwm0eBE3JtePgOcljgLfxAl/ArzVAyJLzErJFIXH4KstWrssHTb4PPhl8Gct+t1q3ZdJ8RD4p9jZrdj5sm3SaFux/8M9oLJHggmp1k5R8ApwjZCrrUr0SuAl4KTEm8At+s+krqUkSwoulPwM+PoKLkz/uQg+1+Dnr0XuX3Q9lV/o090nUQEPAw8SKO2i59UI+APYsvmOsIMr4B7gIvA5u7s86fcCgpicxpx/e0EwTVAT4CMJ7OngAKfTuC39uVKz2ome1k1KHJr93M7oD65dLHuaN/+bW9RD3+27bEANlQ2oobJWUEPD1MZSQ2XjvlxUyL0bFGYSF1qWT5WEuJcb7Ebm3VxLNYPpsuXqFIh/zBTNFk6xSqCSeMTmYylcXbA4W6iB+4APbN4APiVUh2cN3mGdsFtHPwn+lb2po++An5J8SZp+e5UhdXQ71L0l7ge+BR4jpFYFy1MYE5jmZZuxxAPA2+SLsx1QhUQtcW9d8yXwZAS0F5dGE0JCe8VmDJwCTsyYxG5qVRQ+Kvnyii6b58pt8FjyWe5M62gnDunHQ8AYuM7e3/eJQIGPAdvAL3Qz5H29GU27uA0gX+BgfXfIuY2z73fIOTmQLOE/hw5ngBNVOEQAAAAASUVORK5CYII='
-
-led4 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADdElEQVRoge2Zu4tkRRSHv3OqukdFxd0FUQRdxESMFgQDBWFBQ/P1LzBREHSNzAwNRPwbVkMDQUMVdIKNfIAYimAgsivjY3fsufUzmKrZftSdvn3t7tvC/OBw+z6q6runHufUbQPEjsmHBqjpDKqrzqC6qgq1TdJaW9X21XZjzXIgtVyf0f3uXAyBBIQtAF0ajYhmC/cFyPLxwRD0/Xisp0MQoJivr9MiCDO9HqO+Go+F2Un72WahHghBN0PQgbueyWCjNQKVul4JQTLT5zEKM/lpUOdD0K8xSqDfzfScmQCFNQCF7KHX3CWQQF+MRsuhLoSgGxlKoD/MdDlGAfMFVzLPQFdz3Ye5/i+7eOpCCLoRggSa5IIH7nrcvTdY8fKV3GWTqbprUAuzz7gzJQPHM+S+lDif0sn9VVXKPJL9ryX1VKFq5+vIb8qatOzFqlC1Qn081LeOzlDbVDWabAqqa71xoaA2mB1XwklN/5/UZWgtQm2y+zqq7qkNgfVeEnZBOwm1sCQox6Y2TcfGrirP1+qtXVuAcmb7vqTF0zGwllefpvJ8Sa81BeqVtWsB6hbwpxn3SkyAMfCDGb+Z8URKOKsH5wAcANeBf8wYSxwCe8DNlkk1m4iBLrvrwEwCfWemSzHq63w+ATUrWsmd3nPXCyHo73z+jbseypltNUefB3vRXfsx6vnRSPs56WtyZX2slH0/Rr0co/Zj1MM5cZwDWoQqYA7CXZ9loNug9B/tVgZ7KwThrj3quX91IiXyQEyJqynxszt7QFN7g47WAHcB10LgW+AaMDKjob6onp7sg550108xSu5q3KUVrZT5MEY9Ox7rl7yb+dRdd1e60Eoftinkt3w0BJ5yZ9LyZqfJgb8Al/g4Jc6lxO3suY9i5ErT4NLMUtNpe1QZjJ2t7LLfyB46nBr4+3k3Y7PPL1cZY31jUgCOuLOITq91TT5Od1knqALWVzZ3XKbBA3KnT0Hbliqxb3ioyrXBoXaz+yrXzqBq2kmoszFVU80rg0PVdjXlt1We26hKwz+agdlMQB7MU01u6JOUeNXsJEcbFAry/lHig5R40529HPMGH1MNx7nSuxJvx+Os6aiy7+ucT61LDRAl3jk64mIIPNbyda93mtvXSup7D+il/DfI3P21fCLvpc7/921TagEY1FNtGjz21bSTUP8C1hqqTm9IJgsAAAAASUVORK5CYII='
-
-led5 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAADyUlEQVRoge2Zv4tcVRTHP99zZ6NEggg2iYgWpghKEGNlYaGNYifBgAGbNFaCkCJ/haAiiGDAgOkFKxtttrGKFlaCbJFlwVVEo+5m5t2vxdy3+3bmzcybmXVnA/uFw5v35r37Pu/cX+fcK8AcM8WqAdp0AtVVxxKqN+mPo6I14z1NLdfaLx6hWj0VwLMS/9iYIeRhawCcAbYkfrXHHFF70CrHsxG+npIN3gX3wYNDtB2wwXcifDalA+8uv/cBE1ABNyXuSPwlcbOqyMVbh+GxqrznB4nXgC2bkMje99OB9ly/dAB8mDODnHlHIoBcCsxLWL8ArUfwisSWTYIDQGNQo3C3bE5LvJUSSSKV/2IBA1gDvpV4Hfg9572aGa2BiQ0dYBf4NGfeS4nLEXxs829LIbOUgdPA9zZXgb9zJgoQjPf0ieNUDdcHPqoqrqXEuVL4YE6oWgPApaflKfdNhWr2gvMSVBX3l4Cqa2DWGNgKJWnYaWk0/sb5or2wbfTuDNWm5lf+36P91N63Kh3LKOHBgTqpvhaNQ0lDW6FOqq+rjqWnOo/o9QTaDEXm1ULTTP2AGscaJjXgps3w0xQjZXaCEoDNn+V8wDAwQ2IdeBx4jP04qKvM8KO2Jf6w9yLZWc8cCN7PSP4mwgbfB7+Rkm+U8zqRmMd2S6Lwk+SnSqIQjfe22MELNdjDEf46wlcjfEOywVUpfBGrn/05whckA+51harB1sBIfrukWjvgvKTVHluXjGRN9lg7bUhOkk9F+PMC1i9fvIj1C9AG+MUIf5KSX4qYVJXtUCpfApgIfxZhS64ke07L5XhX8nOSb5fmsBnhF1rA2tcSJDwSDq9JXIqg1/ZAB/WAX2w+sHnTZhd4CNiUuAj8NpK6T+sFe20slca5iNVeOM8wbW+2sz74mZH7Oo3oZjiupFk3TlA9Lpn9tN3s18Jced+o5h00azWrZHSKaptnH5woYdU6geqqlUNVjK9NrByqLT5bOVSbTqC66sihDn19atF1qXru63Usp5On6kXTRZeq6zlzA/hRQkyfR2d6KgGVxPUIruTMva5f0pCBU8AmcC2CL3PmQtlimfZMq/VKnP5+yWQyyycO30m+mJI3SvR5D/zkSDzVDiXtAb1bgOp0aZk9mTpx+CrCz0d4G7wr+VwJIKdCpQJ0OSVn6VCARjeLvpB8KcJ3I/z0LKgoQFfqwH/JamuzQTneivDLvZ6fKFB1ojJxv/FV4BFgh8XD4GmqgEcZ7tVsjyQNq94E3Ru3mhBT95CPYp2qTiiaWrmn2nQsJ+T/AHYfURS2h8j3AAAAAElFTkSuQmCC'
-
-led6 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEBUlEQVRoge2ZP4gdVRTGf9+Z3c1qZJFUChJWLBQigmLQiJYhIkQLwcLWwkYrGy1s0sRC0gQUIljYWCRaaKONJoKNIoJKwEgaBcEuJuwmu/vefBZz7+68P/N23p91X7EfHGbmzsy935x777nfuSPAzBlivwkMwwGptphLUgvDCv8vpmVDueibfQMF+4BtT2UyhyUeBP61Kfao0RK4B7gO3Gl4xtkOgY8WhT+RbPAaeGPGtg42+EKEkVxvv2ZY6WJJ8jcRfjrCFxKxTqpkFpbr+qAojGTV2m4kheRrEb4l+VhR+FyEnb6wM6VtJkLnJCM5mgn1kpLk3xKRG5KPR/i95LHuFB4q0/Fs6rJiNCEPhIQ8uFdsrticjGBD4nXgJuOHizyoz0ucLUsWbLrZHQ1Q8hQGQuKqxMNlSYdqaq5LHAeuAodoji27YQsIu9X7g8HT1TcE0AHutllNpDpAd0JSxRjvDpBS7Tx3Vad2T0yGcTzcQ2q3Rrenxh5jLhfkHlKyJ+6eWWLQU97v5XgIqbnz1DSza5aY/4E+Lzgg1RY9EX23iB273B+FcVaDgWWmft5NRPJDJZOrhNwlbYj1kNoCbkpgs0klVf4Erkk8YLPYstJ+CPhbYiOtGG3qMOBIx2OS/0pK8XfJj0T4UlKft0ckBE12O9X1qeQiJQp1pQsNcrif2GMpgXiiKHwxyeNp5HB+91KElyNcgKOZUC8pKn3sJaok4sOah8opLXvsTNLpi6N1+qCnjkr+WPLjki/XUq1JCeXU6mKEn4zwR5KP9HXlUFL55n0R/il12ffg1Qh/G2FL7kr2mJbf+SzCq0XhX9NHXpa80kBsYDJ8J/GczR1gGfhR4hWJ+6WJ4pSoZvUtmy9tHqrV/XkEL9tDE4qdDBl8nZ1cbSudP5/uF81jYFQOZ8CvJu9v1gb+D2l89XuqJ07Vg6PZCXi5bJINj4Iq8cgernu7KRAPRPRRi2GX8VMs9R09pKwfc7kg7yuppklzQKotDjzVFgeeaou58FR/EG1Faha7C3lJaZOBD/0NUq8ogKV0PYlKyF+dG6ovM2OTKtPNfyR+AUgbqONmM3kX8GdgDThMJWUKmj+wkdQCcEPixQjeKkueklhjst3hFeAL4KUIvirLVnVs65lF8B9J66yDT0T4fNJB0/x5yPrp3Qifiti+vpL0VJbh2XpI1/v7lMRp4I2yZDOVdSc0U3XZmbLkUZvTRaXM3LBBF/0XAl4oCk4A75QlG1RdqSktgE3gfZsjNq9FcJe07YyB7st2L/jZovDbM8j1mqwEW/KbEX4mokrndkscliVOJnHfZvqOC1PNvAL4muFKdoBUMPkmxrhoamvofsNe/RHtR5Pen4dfxgOYS5XwH7eZhqnTFNxUAAAAAElFTkSuQmCC'
-
-led7 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAACtElEQVRoge2ZwWoUQRCGv+ruFRPx4iOIGPEuETyLGDH4AqII4tN49KQg+AB6jAjiOeBFg5gHEA+KHiQmJpme38P0hN3ZSZysm949zA9NQ2/t9LfdtV1V0waIOZObNUCbeqiumkuocNgHuWjF+D/NWsayylI/DHHoSi2ZUUgUTH/VDNgHzgK/zPgijazOGJQDSmDZjOdAlIhTBiuARWATuG/GjsQPRrdNzeZSfy8ERTMJVII0hRZTv2mmJee0Brqe5vNDLjYGBSikftVMuwlqPz100raXgDa81+XBQK+9l0BXukIBGqT+pnPadu6/VqxeoXXQee/1Lj1PoKsNqEMdHSpnDMBaWXInBJ46R6DyOTvqiw2VwAKwIfGwLHkRI9fS8wct9kdCAQf/vjdFwUXvCUx2hhjwR+ItHAAdNvk/oaD6pQ7Yi5HdCYEEnAEupDF/hH0nqBrMON62NaFKIHaw7wwF0zn6u/youQzIPVRX9VBd1UN1VQ/VVVmh6lDTNj6srFCO0UCsofGm3YlLVDFvG1i3KvoVaUxm/E5janznxJul/pSZXqU0OIIemAmzg7qgZssCNQLmnF6GoEdmI4XKkF3eYtSlFp0DiSCx32KTTXUuVQCPgVWqtLgtC822fYAw05NUS26Z6XYIbVuY0Z/M9Cw5+S5VebXjnC41fOtY6fCkqh13UeJGrLL0ulQ7XZacG7KDzD7VLBxqiGYxkd3R2yZsFhN9QO6qHqqreqiu6qG6aj6gbPT4zF44dEneshcOYxPa+Bur7IXDR1dNORKEZ7l9AHfNeO89A6oMtE3ZoJQm+xkjKxIfzFpfV2eFgiqf8sD3smRF4nMaj7PevpjAvgK3nOOb9yw0bGZ23+epAJdDYAv4VBQHN2gzvYRsu4CEGZ/o9VHRPKlmfl3bpvmIfQ3NJdRfFS/ZxKoPEs0AAAAASUVORK5CYII='
-
-led8 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEi0lEQVRoge2ZT4gcRRTGf+9Vd/VkIRjxIqggJF5E8JSDF/EQjKAICflDQjAnUdGD6EEQDHrRmwdBD6IIweQkiiIevOTgKSAiiiAiBDxpomhiJLvTVf08TPVkZqdmMz272Z2FfPCoobrr1dev/r1vSgBjwaBbTSCHW6RmxUKSKnKVkuxmw8ivMlld35LZjCU5ra8JUgD3qyJNQ5+bM74R2AGsqPJL02RJGGCSyru9t5NVZf+JmIEFsGYDrQYzsL9U7diOHXavc2P9AzYMhEvlURH2x8iBsuSaKi69KRtgxmAS/y3CwbLkZAg8FuNY/5AZncvAsRA41DQ86T1XRFAgAM06LKTOflflibLkuRjZX9f8I/klZYAVqXy2qsxSiM+UpT3ivV1KQ9mk+q7WtvvNOXuoquwL54bPToiM9Z9+57EMHK9ryqLgcFnyoRlLZkS6bRcGlMCfwDPO8XoIPBojy0BvSpsJUjLyoAYOh0C/LNltxs5EqisUuAp8mQjVieg0TI0UXJ9896lCCFyNsfP+1U5wBfaM+G26kBodmpZAYzbxrCuxBmaO8pqRGnUK04+FWTHrR01sCZtx5t0IC5klbI9ILSSpjYZM+b0WNi1Syvihe6N3Fw6bOqcWbvi6YKYdvT2nlO47envEqMjAj417yPmbIJWbZC4lYs2cpNrjKec7NzITpK6YgQiNGcJgxZwz43Yz7mSQQXZFAfwhwjlV9oRw/WAW4V8RMMsLh6GJ2HtFYZayzTe9tyPeDwVEAIsdLKQM85qqPV5V9s5I1vmW94bImGhgICImdZ+J8EFR0Ae+UeVMv4+kr5lnIbTtVkQ4WhQcEuFi0/ByjEO/uTajLM2DoWoPem8rqhY2QGq17a+o2p6qMkTMr5JWUyOlQCPCKeeIqlw04/0QhonePGgnuQAnvOcBMy4Bb4eAmmWz0LEoIWKnynIw7iL2Qlna096bqVqjatbRRtsc895e837gW9WeL8tWfOYj5Rikq8erijN1TZ3kdAG8UpZ8JcI9ZvTprmYq4IIZJ0R4NQTqtLILVfaL8HWMw/7HItXqrpeS7qtHVs557w3nsuN/I5OR8ufkL3Jdvj+VZPuaui83d9ovaCX8PDDye1yuv0k1k5HR7U4c10Fq1M8YMqS2R+qy2YiLFKl2kuQE6pZHKre9zERqs68ktjxSOdwiNSu2L6mNmuhr/VE2ipnUjKajZ56sc6hmpnRmKUcf628th+2XnY8RzBARrKM1IgN5pcq3xYDW6hRlNaZGKjD49/Z0UXBOle+ahmWRucWqA153jiXgQAgspzoykZpKqgd8UpacLQo+XVlhqWnWLRxO9/scLAp2Ose+GEFktki1Oc/nzvGuCJ8tL7NkRpiTUIsGuMOMszFy1Hs88HCMBJ2cQRM1twHfO8cbzvFxXbPLjHqdhNqO+sBdTcNHdc2LZcmvRcHOKe+PJe/7ej070uvZhSQa5736mGYxlT+q2sFez/YWxYR4GJNYrRDdC+w24zIz7hkdIAxuMnYBP6nyQ+a+b/vcjLbC8WbDyO/yWVJbjYU8kP8HKX/sOnQ6GT4AAAAASUVORK5CYII='
-
-led9 = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAAEYklEQVRoge2ZT2gkRRTGf+91VXeQJcp6kAVBEFn/ggh7ET0IggjBGBNW1+Bpc1E8uDfPIgqC4OLNu6IL4oJ48+RR0LMXvQgii4d1E4PZdFc9D1M9yWRqJjPpbGbAfFBM0l3d7+tXr+q9r0oAY86gsyaQwympSTGXpFzuoqR2p2HkZ5kcvN6SOYkpOcrWECmAh1XxMbIDFHeATAQqIKjyS4zZPgaYpN9zInapquymqhlYDRaPsTVgBrYlYm+UpT1YlgP2AesHeuuRJTPWQ2CtLLklgks95RiaJTvbqqyWJa/EyEXVAfuQmX03gZeaho0QWPaev0RQoEluP2prkrFbIiyXJZdCYLVp+Nvy0WuAufT7WnKvgV0vCnumLO2PojBL7rcjtPa5G6r2bFnaV973771dVQP209957AArIbAAvO49n4lwFqiZbrkweuvOlggbIlwJgbUQ2AEWRjwzRKp1pk8EXgyBWoRHzThDbyimRQFsAdeAtRCoc4bHkWqDrA1KgIdiRMz4xyy/hkwCVc471yc57uOGSDmR3mjvQ2BvBsL0q70kEmFEUB9KKmew6yrfPjdpoh3uJyeR9cZjiNTsKZ16anLMZZE37Kl5HL55wGlMTYrhvJiJqTZPdfmCtq46iFyWGJmQc50iI4r6CZGrDDTjhH6/1tAmgAhmRkgkf1DlbIzcZ0ZzRDI3gO9FeJJegifZ2RwnHGiLdxH7uCzNRMzArjpny2VpO0lINGBhitakyrMWsVXv7aOy7FWdIvap94bIgGhIPIZ1n6nySVGwKMJ3wLW6xpsNlC/ToH0uAutVxfNmRDPeDAGJMRsOB1n26+XHqsq2i6IvjbpKqwD2r6o9UVWGqpUHpNVIT7XecqrUIrxTFFyta+IxeEpF2PCe+4EmRj5sGpTRs3KgFUVhImIKhnP2lvdmqhZVzTq0y1VlV1olI2LvOme0dsZ5SpM4jGlWFCIEVS6IcK8IzZTeMqAEfhfhZeCD3V3qdM+LcNF7vt7dpWBvVmZFRdw3TYMZzoyfY8QmrLGzUOXzJBw0kcWMc8kJ+z90nNLZI0a31VzoKeQmfdT+4cmJiYlItdO56/bQ0YXDHGAiUp1i6bB3Z67N3FNzSSqHmZOaS0/NjNTYDJCZRP9fT/UxoaY8UVIxM1QTCYccNNXsXVFkPHWk4VMgivRyn8iRWrsV8GP6sLDfwKQJuc3iDmhUWSoK3gd20p7ntDB6xx7vqbLoPet1zU56/yj/D1R9qrq3r61qz3lv20nJdN1H31K1FxYW7Bvn+vcuO3f4PrrR24xtRLjgHNebhrtinLrizL33TIx8efs2K95TqrIUY78K3Y8hUgXQiPCIc3wbAvfEyC7dT7ME2AXOmvFF07DiPQ80DYvjjkFo5Y6qPe6c/dlxyA4byt+Kwl5dWLCnve+FzSjh0P7zlCrnY2ST3snDcVZTQu8k427gVxF+yhwYdNmv6IxR+/PZJUE5mc0zIy9EZ+qpUZh5lZDDfw9J5SDpQQEIAAAAAElFTkSuQmCC'
-
-ledcolon = b'iVBORw0KGgoAAAANSUhEUgAAACUAAAA8CAYAAADhR3NQAAAACXBIWXMAADBKAAAwSgHCONjjAAABdklEQVRoge2YQU7DMBBFn9MEVVBYcADEmiVH4BScD3EL7gIcAYEEFSQdFrZRCJGYeBa1qnlSZSuVJz8/k/EkARAqo9m3gDlclBYXpcVFaXFRWlyUFhelpUpRrWVxAFaTYwIMlqApbnX9VJFT+UpOgRugA3ZE195C4EHE7JYs/TVpvAJ5BxGQPo1PTSObEASQUBA7xS/nE/hI8+yMEJ20YBK1G81zwnfWoKXr85MxAF9p3o/+24tT45N2k/EYOLIoovDpy069AvfAOdGxDngR+cmzUg6nTv0XoJ85toQqnapyQ3ZRWlyUFhelpUpR5oo+1xFYq3GVFd3Uo18Cd8CGuN+tgcem4VaErUjxFZtErYFr4ITY8K2AM2ILsy0JnDD36Pnk49a4mh49B2qtQUvX5zzZ8TdnVqVBR5jWD/x2C6Ko6av8UkwloQUuiImd32J64Bnb94TDqVNj5u7/9JYupUqnqtyQXZQWF6XFRWlxUVpclBYXpeUbS+1qOYf8HRgAAAAASUVORK5CYII='
-
-ledblank = b'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/GMzLdsAADpEaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0NSA3OS4xNjIzMTksIDIwMTgvMDIvMTUtMjA6Mjk6NDMgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIgogICAgICAgICAgICB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBFbGVtZW50cyAxNy4wIChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxOC0xMC0yMFQxNjowOToyNS0wNDowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE4LTEwLTIwVDE2OjM2OjMyLTA0OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcDpNZXRhZGF0YURhdGU+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwveG1wOk1ldGFkYXRhRGF0ZT4KICAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9wbmc8L2RjOmZvcm1hdD4KICAgICAgICAgPHBob3Rvc2hvcDpDb2xvck1vZGU+MzwvcGhvdG9zaG9wOkNvbG9yTW9kZT4KICAgICAgICAgPHBob3Rvc2hvcDpJQ0NQcm9maWxlPnNSR0IgSUVDNjE5NjYtMi4xPC9waG90b3Nob3A6SUNDUHJvZmlsZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDoxYTc5NDQ5ZC05ZmM0LWZiNGItOTNjYy0xNTcyMjU1MGU5OTk8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkMGIzZGFmNS1kNGE3LTExZTgtOGI3ZC1jYmQxMWFlODBkMGE8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDowZDlkYjE1OS1lYThmLWQxNDEtYWE4MS04YTY4NzFkNTI4YTc8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6MGQ5ZGIxNTktZWE4Zi1kMTQxLWFhODEtOGE2ODcxZDUyOGE3PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE4LTEwLTIwVDE2OjA5OjI1LTA0OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgRWxlbWVudHMgMTcuMCAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjFhNzk0NDlkLTlmYzQtZmI0Yi05M2NjLTE1NzIyNTUwZTk5OTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxOC0xMC0yMFQxNjozNjozMi0wNDowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIEVsZW1lbnRzIDE3LjAgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgPC9yZGY6U2VxPgogICAgICAgICA8L3htcE1NOkhpc3Rvcnk+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjMxNDAwMDAvMTAwMDA8L3RpZmY6WVJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDxleGlmOkNvbG9yU3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+Mzc8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PvnJsBAAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAEZJREFUeNrszkEBACAMAKHT/p1nDPeABJxqWua2kJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSU1G8PAAD//wMAGdkBdyV2S1QAAAAASUVORK5CYII='
-
-w1 = b'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'
-
-w2 = b'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'
-
-w3 = b'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'
-
-w4 = b'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'
-
-w5 = b'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'
-orangeround = b'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'
-
-weather_icon_dict = {'clear sky': w1, 'rain': w3, 'light rain':w3, 'shower rain':w3, 'thunderstorm':w3, 'snow': w3, 'sleet': w3, 'wind': w3, 'mist': w3,
- 'cloudy': w4, 'scattered clouds': w5, 'few clouds': w5,'broken clouds': w5, 'overcast clouds': w5, 'partly-cloudy-night': w5}
-
-led_digits = [led0, led1, led2, led3, led4, led5, led6, led7, led8, led9]
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Progress_Meter_Simulated.py b/DemoPrograms/Demo_Progress_Meter_Simulated.py
deleted file mode 100644
index 04d1980d2..000000000
--- a/DemoPrograms/Demo_Progress_Meter_Simulated.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""
- Demo Program - Progress Meter using a Text Element
-
- This program was written by @jason990420
-
- This is a clever use of a Text Element to create the same look
- and feel of a progress bar in PySimpleGUI using only a Text Element.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-sg.theme('DarkBlue')
-
-layout = [[sg.Text('', size=(50, 1), relief='sunken',
- text_color='yellow', background_color='black',key='-TEXT-', metadata=0)]]
-
-window = sg.Window('Title', layout, finalize=True)
-
-text = window['-TEXT-']
-
-while True:
-
- event, values = window.read(timeout=100)
-
- if event == sg.WINDOW_CLOSED:
- break
- text.metadata = (text.metadata + 1) % 51
- text.update(sg.SYMBOL_SQUARE * text.metadata)
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Progress_Meters.py b/DemoPrograms/Demo_Progress_Meters.py
index fa65f3be9..c5d6c2326 100644
--- a/DemoPrograms/Demo_Progress_Meters.py
+++ b/DemoPrograms/Demo_Progress_Meters.py
@@ -2,7 +2,6 @@
import PySimpleGUI as sg
from time import sleep
-sg.theme('Dark Blue 3')
"""
Demonstration of simple and multiple one_line_progress_meter's as well as the Progress Meter Element
@@ -15,10 +14,6 @@
If the software determined that a meter should be cancelled early,
calling OneLineProgresMeterCancel(key) will cancel the meter with the matching key
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -40,8 +35,6 @@ def demo_one_line_progress_meter():
'MY MESSAGE1',
'MY MESSAGE 2',
orientation='h',
- no_titlebar=True,
- grab_anywhere=True,
bar_color=('white', 'red')):
print('Hit the break')
break
@@ -74,7 +67,7 @@ def demo_one_line_progress_meter():
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event == 'Show':
max_outer = int(values['CountOuter'])
@@ -209,12 +202,12 @@ def demo_iterable_progress_bar():
# first form takes an iterable and a key and will return a value from your iterable
# and bump the progress meter at the same time
- for value in progress_bar('bar1', my_list, title='First bar Test'):
+ for value in progress_bar('bar1', my_list, ):
# do something useful with value, a value from your list.
print(value)
# Since the progress_bar is an iterator, you can use it within a list comprehension
- my_list = [x for x in progress_bar('bar1', my_list, title='Second bar Test')]
+ my_list = [x for x in progress_bar('bar1', my_list)]
demo_iterable_progress_bar()
diff --git a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py b/DemoPrograms/Demo_PyCharm_Diff_2_Files.py
deleted file mode 100644
index eda74ac70..000000000
--- a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import PySimpleGUI as sg
-import sys
-"""
- Compare 2 .py files using PyCharm's compare utility
- If you use PyCharm, then you've likely used their awesome
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
-
- layout = [[sg.T('Choose 2 files to compare using PyCharm\'s compare utility', font='_ 18')],
- [sg.Text('Filename:'), sg.Combo(values=sorted(sg.user_settings_get_entry('-filenames1-', [])),
- default_value=sg.user_settings_get_entry('-last filename chosen1-', None),
- size=(90,30), auto_size_text=False, k='-COMBO1-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR1-')],
- [sg.Text('Filename:'),sg.Combo(values=sorted(sg.user_settings_get_entry('-filenames2-', [])),
- default_value=sg.user_settings_get_entry('-last filename chosen2-', None),
- size=(90,30), auto_size_text=False, k='-COMBO2-'), sg.FileBrowse(), sg.B('Clear History', k='-CLEAR2-')],
- [sg.Button('Compare'), sg.Button('Exit'), sg.T('PySimpleGUI ver ' + sg.version.split(' ')[0] + ' tkinter ver ' + sg.tclversion_detailed + 'Python ver ' + sys.version, font='Default 8', pad=(0,0))],
- [sg.Text('Note - You must setup the PyCharm information using PySimpleGUI global settings')],
- [sg.Button('Global Settings')]
- ]
-
- window = sg.Window('Compare 2 files using PyCharm', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT)
- while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == 'Compare':
- sg.user_settings_set_entry('-filenames1-', list(set(sg.user_settings_get_entry('-filenames1-', []) + [values['-COMBO1-'],])))
- sg.user_settings_set_entry('-last filename chosen1-', values['-COMBO1-'])
- sg.user_settings_set_entry('-filenames2-', list(set(sg.user_settings_get_entry('-filenames2-', []) + [values['-COMBO2-'],])))
- sg.user_settings_set_entry('-last filename chosen2-', values['-COMBO2-'])
- sg.execute_command_subprocess(sg.pysimplegui_user_settings.get('-editor program-', None), 'diff', '"' +values['-COMBO1-']+'"' , '"' +values['-COMBO2-']+'"' )
- # sg.popup(f"You chose {values['-COMBO1-']} and {values['-COMBO2-']}")
- elif event == '-CLEAR1-':
- sg.user_settings_set_entry('-filenames1-', [])
- sg.user_settings_set_entry('-last filename chosen1-', '')
- window['-COMBO1-'].update(values=[], value='')
- elif event == '-CLEAR2-':
- sg.user_settings_set_entry('-filenames2-', [])
- sg.user_settings_set_entry('-last filename chosen2-', '')
- window['-COMBO2-'].update(values=[], value='')
- elif event == 'Global Settings':
- sg.main_global_pysimplegui_settings()
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), non_blocking=True, keep_on_top=True)
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_PyCharm_Launcher.py b/DemoPrograms/Demo_PyCharm_Launcher.py
deleted file mode 100644
index 307efef31..000000000
--- a/DemoPrograms/Demo_PyCharm_Launcher.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import PySimpleGUI as sg
-import subprocess
-
-"""
- Demo mini-PyCharm "favorites" launcher
- Open a python file for editing using a small window that sits in the corner of your desktop
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ---------------------------- Items for you to edit specific to your setup --------------------
-LOCATION = (2340, 1240) # where the window should be located
-TRANSPARENCY = .7
-
-# A list of the files to edit
-PSG = r'C:\Python\PycharmProjects\PySimpleGUI\PySimpleGUI.py'
-PSGQT = r'C:\Python\PycharmProjects\PySimpleGUI\PySimpleGUIQt.py'
-PSGWX = r'C:\Python\PycharmProjects\PySimpleGUI\PySimpleGUIWx.py'
-PSGWEB = r'C:\Python\PycharmProjects\PySimpleGUI\PySimpleGUIWeb.py'
-
-# The command that will be executed that causes a file to be opened in PyCharm
-PYCHARM = r"C:\Program Files\JetBrains\PyCharm Community Edition 2019.1.1\bin\pycharm.bat"
-
-# Dictionary of buttons to display and their corresponding file to open in PyCharm
-button_dict = {'PySimpleGUI': PSG,
- 'PySimpleGUIQt': PSGQT,
- 'PySimpleGUIWx': PSGWX,
- 'PySimpleGUIWeb': PSGWEB,
- 'This Progam': __file__, }
-
-# ----------------------------- The main program -----------------------------
-def mini_launcher():
- """
- The main program. Creates the Window and runs the event loop
- """
-
- sg.theme('dark')
- sg.set_options(border_width=0)
-
- # layout is built rather than a static definion
- # starting with a blank line. This will give you a place to "grab" the window to move it around on the screen
- layout = [[sg.Text(' ' * 10, background_color='black')]]
-
- # add the buttons to the layout
- for button_text in button_dict:
- layout += [[sg.Button(button_text)]]
-
- # complete the layout with a text "X" that will generate an event when clicked
- layout += [[sg.T('❎', background_color='black', enable_events=True, key='Exit')]]
-
- # Create the Window
- window = sg.Window('Script launcher', layout, no_titlebar=True, grab_anywhere=True, keep_on_top=True, element_padding=(0, 0), default_button_element_size=(20, 1), location=LOCATION, auto_size_buttons=False, use_default_focus=False, alpha_channel=TRANSPARENCY, background_color='black', )
-
- while True: # The Event Loop
- event, values = window.read()
- if event == 'Exit' or event == sg.WINDOW_CLOSED:
- break
-
- file_to_edit = button_dict.get(event) # Use button to find associated filename
- try:
- execute_command_blocking(PYCHARM, file_to_edit) # launch PyCharm
- except Exception as e:
- sg.Print(f'Got an exception {e} trying to open in PyCharm this file:', file_to_edit)
-
-
-def execute_command_blocking(command, *args):
- """
- Creates a subprocess using supplied command and arguments.
- Will not return until the process completes running
- :param command: The command (full path) to execute
- :param args: a tuple of arguments
- :return: string with the output from the command
-
- """
- print(f'Executing {command} with {args}')
- expanded_args = [a for a in args]
- try:
- sp = subprocess.Popen([command, expanded_args], shell=True,
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- out, err = sp.communicate()
- if out:
- print(out.decode("utf-8"))
- if err:
- print(err.decode("utf-8"))
- except Exception as e:
- sg.Print(f'execute got exception {e}')
- out = ''
- return out
-
-
-# ----------------------------- When program is first started -----------------------------
-if __name__ == '__main__':
- mini_launcher()
diff --git a/DemoPrograms/Demo_PyCharm_Self_Edit.py b/DemoPrograms/Demo_PyCharm_Self_Edit.py
deleted file mode 100644
index 0f3f4fbbb..000000000
--- a/DemoPrograms/Demo_PyCharm_Self_Edit.py
+++ /dev/null
@@ -1,32 +0,0 @@
-import PySimpleGUI as sg
-import subprocess
-
-"""
- Demo PyCharm Launch - Edit this file button
-
- Quick demo to show you how to add a button to your code that when pressed will open the file
- in PyCharm for editing.
-
- Note that this is a Windows version. You'll need a slightly different path for Linux.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Change this variable to match the location of your PyCharm folder. It should already have the batch file.
-PYCHARM = r"C:\Program Files\JetBrains\PyCharm Community Edition 2019.1.1\bin\pycharm.bat"
-
-layout = [ [sg.Text('Edit Window Using PyCharm')],
- [sg.Button('PyCharm Me'), sg.Button('Exit')] ]
-
-window = sg.Window('PyCharm Launch Demo', layout)
-
-while True: # Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'PyCharm Me':
- subprocess.Popen([PYCHARM, __file__], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-
-window.close()
diff --git a/DemoPrograms/Demo_PyGame_Integration.py b/DemoPrograms/Demo_PyGame_Integration.py
index 9f1d033b9..2ad78c36a 100644
--- a/DemoPrograms/Demo_PyGame_Integration.py
+++ b/DemoPrograms/Demo_PyGame_Integration.py
@@ -8,10 +8,6 @@
To make it work on Linux, set SDL_VIDEODRIVER like
specified in http://www.pygame.org/docs/ref/display.html, in the
pygame.display.init() section.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# --------------------- PySimpleGUI window layout and creation --------------------
layout = [[sg.Text('Test of PySimpleGUI with PyGame')],
@@ -25,8 +21,7 @@
# -------------- Magic code to integrate PyGame with tkinter -------
embed = graph.TKCanvas
os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
-# change this to 'x11' to make it work on Linux
-os.environ['SDL_VIDEODRIVER'] = 'windib'
+os.environ['SDL_VIDEODRIVER'] = 'windib' # change this to 'x11' to make it work on Linux
# ----------------------------- PyGame Code -----------------------------
@@ -38,7 +33,7 @@
while True:
event, values = window.read(timeout=10)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event == 'Draw':
pygame.draw.circle(screen, (0, 0, 0), (250, 250), 125)
diff --git a/DemoPrograms/Demo_PyGame_Snake_Game.py b/DemoPrograms/Demo_PyGame_Snake_Game.py
index df73c2bae..227518f7e 100644
--- a/DemoPrograms/Demo_PyGame_Snake_Game.py
+++ b/DemoPrograms/Demo_PyGame_Snake_Game.py
@@ -9,10 +9,6 @@
The purpose of the demo is to show one way of adding a PyGame window into your PySimpleGUI window
Note, you must click on the game area in order for PyGame to get keyboard strokes, etc.
Tried using set_focus to switch to the PyGame canvas but still needed to click on game area
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
# --- Globals ---
@@ -93,7 +89,7 @@ def __init__(self, x, y):
while True:
event, values = window.read(timeout=10)
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
pygame.display.update()
diff --git a/DemoPrograms/Demo_Pyplot_Bar_Chart.py b/DemoPrograms/Demo_Pyplot_Bar_Chart.py
index 3f88c81b0..efade3dda 100644
--- a/DemoPrograms/Demo_Pyplot_Bar_Chart.py
+++ b/DemoPrograms/Demo_Pyplot_Bar_Chart.py
@@ -1,10 +1,11 @@
#!/usr/bin/env python
import PySimpleGUI as sg
import matplotlib
-from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
-# matplotlib.use('TkAgg')
-import numpy as np
-import matplotlib.pyplot as plt
+matplotlib.use('TkAgg')
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import tkinter as Tk
+
"""
Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
@@ -16,14 +17,13 @@
The remainder of the program will convert your plot and display it in the GUI.
If you want to change the GUI, make changes to the GUI portion marked below.
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
"""
# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+import numpy as np
+import matplotlib.pyplot as plt
+
values_to_plot = (20, 35, 30, 35, 27)
ind = np.arange(len(values_to_plot))
width = 0.4
@@ -41,21 +41,32 @@
# ------------------------------- Beginning of Matplotlib helper code -----------------------
+
def draw_figure(canvas, figure, loc=(0, 0)):
- figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
+ """ Draw a matplotlib figure onto a Tk canvas
+
+ loc: location of top-left corner of figure on canvas in pixels.
+
+ Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
+ """
+ figure_canvas_agg = FigureCanvasAgg(figure)
figure_canvas_agg.draw()
- figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
- return figure_canvas_agg
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = Tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w / 2, loc[1] + figure_h / 2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
# ------------------------------- Beginning of GUI CODE -------------------------------
-sg.theme('Light Brown 3')
fig = plt.gcf() # if using Pyplot then get the figure from the plot
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
# define the window layout
layout = [[sg.Text('Plot test', font='Any 18')],
- [sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
# create the form and show it without the plot
@@ -63,7 +74,7 @@ def draw_figure(canvas, figure, loc=(0, 0)):
layout, force_toplevel=True, finalize=True)
# add the plot to the window
-fig_photo = draw_figure(window['-CANVAS-'].TKCanvas, fig)
+fig_photo = draw_figure(window['canvas'].TKCanvas, fig)
# show it all again and get buttons
event, values = window.read()
diff --git a/DemoPrograms/Demo_Pyplot_Bar_Chart2.py b/DemoPrograms/Demo_Pyplot_Bar_Chart2.py
deleted file mode 100644
index d214ff243..000000000
--- a/DemoPrograms/Demo_Pyplot_Bar_Chart2.py
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
-import numpy as np
-import matplotlib.pyplot as plt
-# matplotlib.use('TkAgg')
-
-"""
-Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
-
-Paste your Pyplot code into the section marked below.
-
-Do all of your plotting as you normally would, but do NOT call plt.show().
-Stop just short of calling plt.show() and let the GUI do the rest.
-
-The remainder of the program will convert your plot and display it in the GUI.
-If you want to change the GUI, make changes to the GUI portion marked below.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
-label = ['Adventure', 'Action', 'Drama', 'Comedy', 'Thriller/Suspense', 'Horror', 'Romantic Comedy', 'Musical',
- 'Documentary', 'Black Comedy', 'Western', 'Concert/Performance', 'Multiple Genres', 'Reality']
-no_movies = [941, 854, 4595, 2125, 942,
- 509, 548, 149, 1952, 161, 64, 61, 35, 5]
-
-index = np.arange(len(label))
-plt.bar(index, no_movies)
-plt.xlabel('Genre', fontsize=5)
-plt.ylabel('No of Movies', fontsize=5)
-plt.xticks(index, label, fontsize=5, rotation=30)
-plt.title('Market Share for Each Genre 1995-2017')
-
-# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
-
-# ------------------------------- Beginning of Matplotlib helper code -----------------------
-
-def draw_figure(canvas, figure, loc=(0, 0)):
- figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
- figure_canvas_agg.draw()
- figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
- return figure_canvas_agg
-
-# ------------------------------- Beginning of GUI CODE -------------------------------
-
-sg.theme('Light Brown 3')
-
-fig = plt.gcf() # if using Pyplot then get the figure from the plot
-figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
-
-# define the window layout
-layout = [[sg.Text('Plot test', font='Any 18')],
- [sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-')],
- [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
-
-# create the form and show it without the plot
-window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
- layout, force_toplevel=True, finalize=True)
-
-# add the plot to the window
-fig_photo = draw_figure(window['-CANVAS-'].TKCanvas, fig)
-
-# show it all again and get buttons
-event, values = window.read()
-
-window.close()
diff --git a/DemoPrograms/Demo_Pyploy_Bar_Chart2.py b/DemoPrograms/Demo_Pyploy_Bar_Chart2.py
new file mode 100644
index 000000000..2791538f6
--- /dev/null
+++ b/DemoPrograms/Demo_Pyploy_Bar_Chart2.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import numpy as np
+import matplotlib.pyplot as plt
+import tkinter as Tk
+import matplotlib.backends.tkagg as tkagg
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import PySimpleGUI as sg
+import matplotlib
+matplotlib.use('TkAgg')
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Paste your Pyplot code into the section marked below.
+
+Do all of your plotting as you normally would, but do NOT call plt.show().
+Stop just short of calling plt.show() and let the GUI do the rest.
+
+The remainder of the program will convert your plot and display it in the GUI.
+If you want to change the GUI, make changes to the GUI portion marked below.
+
+"""
+
+# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
+label = ['Adventure', 'Action', 'Drama', 'Comedy', 'Thriller/Suspense', 'Horror', 'Romantic Comedy', 'Musical',
+ 'Documentary', 'Black Comedy', 'Western', 'Concert/Performance', 'Multiple Genres', 'Reality']
+no_movies = [941, 854, 4595, 2125, 942,
+ 509, 548, 149, 1952, 161, 64, 61, 35, 5]
+
+index = np.arange(len(label))
+plt.bar(index, no_movies)
+plt.xlabel('Genre', fontsize=5)
+plt.ylabel('No of Movies', fontsize=5)
+plt.xticks(index, label, fontsize=5, rotation=30)
+plt.title('Market Share for Each Genre 1995-2017')
+
+# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
+
+# ------------------------------- Beginning of Matplotlib helper code -----------------------
+
+
+def draw_figure(canvas, figure, loc=(0, 0)):
+ """ Draw a matplotlib figure onto a Tk canvas
+
+ loc: location of top-left corner of figure on canvas in pixels.
+
+ Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
+ """
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = Tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+# ------------------------------- Beginning of GUI CODE -------------------------------
+
+
+fig = plt.gcf() # if using Pyplot then get the figure from the plot
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+# define the window layout
+layout = [[sg.Text('Plot test', font='Any 18')],
+ [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
+
+# create the form and show it without the plot
+window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
+ layout, force_toplevel=True, finalize=True)
+
+# add the plot to the window
+fig_photo = draw_figure(window['canvas'].TKCanvas, fig)
+
+# show it all again and get buttons
+event, values = window.read()
+
+window.close()
diff --git a/DemoPrograms/Demo_Radio_Buttons_Simulated.py b/DemoPrograms/Demo_Radio_Buttons_Simulated.py
deleted file mode 100644
index ca57d573a..000000000
--- a/DemoPrograms/Demo_Radio_Buttons_Simulated.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Simulated Radio Buttons
-
- This demo shows 2 ways to achieve a radio button type of interface.
- 1. Uses Buttons and changes the color of the button to show which is selected
- 2. Uses an Image Element and a Text Element together
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def using_buttons():
- radio_keys = ['Play', 'Stop', 'Pause', 'Off']
- selected_color = ('red', 'white')
- active_radio_button = None
-
- layout = [ [sg.Text('My Window')],
- [sg.Text('These are simulated radio buttons')],
- [sg.Button(name) for name in radio_keys],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout, use_default_focus=False)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (None, 'Exit'):
- break
- if event in radio_keys:
- for k in radio_keys:
- window[k].update(button_color=sg.theme_button_color())
- window[event].update(button_color=selected_color)
- active_radio_button = event
-
- window.close()
-
-def using_images():
- radio_keys = ('-R1-', '-R2-', '-R3-')
-
- def check_radio(key):
- for k in radio_keys:
- window[k].update(radio_unchecked)
- window[k].metadata = False
- window[key].update(radio_checked)
- window[key].metadata = True
-
- def radio_is_checked(key):
- return window[key].metadata
-
- layout = [[sg.T('Radio Buttons Custom')],
- [sg.Image(radio_checked, enable_events=True, k='-R1-', metadata=True), sg.T('Radio Button 1', enable_events=True, k='-T1-')],
- [sg.Image(radio_unchecked, enable_events=True, k='-R2-', metadata=False), sg.T('Radio Button 2', enable_events=True, k='-T2-')],
- [sg.Image(radio_unchecked, enable_events=True, k='-R3-', metadata=False), sg.T('Radio Button 3', enable_events=True, k='-T3-')],
- [sg.Exit()]]
-
- window = sg.Window('Radio Buttons Simulated Using Image Element', layout)
-
- while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- if event in radio_keys:
- check_radio(event)
- elif event.startswith('-T'): # If text element clicked, change it into a radio button key
- check_radio(event.replace('T', 'R'))
-
- for k in radio_keys:
- print(f'Radio key {k} is {radio_is_checked(k)}')
-
- window.close()
-
-if __name__ == '__main__':
- # Base64 Encoded Radio Button Image of unchecked radio button
- radio_unchecked = b'iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAEwElEQVR4nI1W3W9URRT/nZm7ZXdpbajdWpCAjcFEqw88+CACrgaBmFBIwI3fPPpPaJYND/wjYsxFYgwP+BV2kY9gNCIJIhEIBZSWLl3aprvde2fOOT7c3W27fNSTTO7cMzO/35wz55wZYAVRVVMuaxCGoV2qD8PQlsvlQFXNShhPAqduYEr0lrrmhmFoVbVbvWzdQxKGoS0UCgwAFy6PvySx27cQRVvY80YGZyHaIKJbPUHqvCF8k3/tlb+61z2RJAzVFgrE5QuX1q9K9x6Oouj9TCazKmUBawiAglkQO0bsPOqNejOw9qsoan62Z8eWfx9FRMsJkgnnfrv6FgXBUWOD4UzAWJsb8L3ZNFlrCQSwZ8TO6excXe/eux/UY0EcuQkXRx/t3fX6qW6iDomqGiKS87///QaM/Q7K6efXD7rBgf5AVcl7hgBQEYgqVAQEgqroZLXmb9yeTLGgKRztHtu5/XQbr0NSVDU4dAhvj703LGouBpaGXhwZ5v6nem0cO2gCB002AxGBiICZwSwIrEVtZpav3LhjneN76YxsvnDq1D0AKJVKYgBg9NgxKpVKIkpH0ulVQyPrBvxTfb02ih2ICESAdp2darJHIkIUx+jrXW03rB30PT09zzTm5UipVJLR0VECAGqb9csfV16oN3H56f60Hd20gZzzRJR4UzvAusySxBoBi8A5DyLolWvjOv1gjldnUqN7duavFYtFYyoVGACIvd2fzWZSw4P9IqKkLfBugu4GKFSSr4hSbqBfMplMaiFyBwAgn88bU60eUwCI43hbYIBsJk2e+bHAiQVL/xWiSTB4ZmQzabKG4B1vBYBqtapBoVBgVaUfz13aaI3CEBGzgAjouEuXg3bARSG6pImADJEhwLN/TlWJiDhoecOqSHYpUIJPHYclY4CqdBElZ6Otfse9otlKBRaAb5OwqjbaYSnatqKzpEXQAleFsIAlCWERBbfyR4TBwlDVRj4PBgAThqElIgVhPPaicew02R0vi6ClESWcALEkkbV0bhQ7dZ4VpONEpGEYWpPL5QgArLVnYsc0N99QAuC5nWy8JPEYvtW4PS6LfVXFfL2hznkyxv4MALlcjkwlnxcACCj4ul6fjyeqNeOZ1Xu/COoXwX0XkbDAs8B7BjPrVLVm6vVGDOXjAFCpVMSUiCQMQ/vmlpevE+nRyJOZul9jYwix84sEfrG1d94h9A5EQHW6xrEXYwhffFLYe/3dMLSlUkmS2lUsGgB4Nf/OEIleJEPDI88Ocl/vauu8b5UQdA69nS/t2mWIMDM3x+P/TFp2flKM3Tz+569T7dr1UBU+8dPZbWRS30M4s25ojVvT3xcIlNpRpCpd+cI6XZvxd6emUyrUEPW7DhbGzi6twp37mVpu27Nj65lmo7lbgDsT9+dSV2/cotqDWR/HMYt4ERHx7CWKIq7NzPrrN2/TVG0uBcVt56PdBwtjZ1sRKx3sruLaubiOnzy51tq+wy6KP0j19GSsAQwtlnrPjNgxmgvNBWvNl41m8/NPP94/seLN2E0EACd+qGxyse5runi7Zz+iLL2imLcGN1PWnhYNvv3wwM5r3ev+lzzqtdLSB926lV4rK0qxWDTlcvmx7652ZD5J/gNoDCDS80MCGwAAAABJRU5ErkJggg=='
-
- # Base64 Encoded Radio Button Image of checked radio button
- radio_checked = b'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'
- using_buttons()
- using_images()
-
-
-
diff --git a/DemoPrograms/Demo_Reddit_Search.py b/DemoPrograms/Demo_Reddit_Search.py
deleted file mode 100644
index ac418e543..000000000
--- a/DemoPrograms/Demo_Reddit_Search.py
+++ /dev/null
@@ -1,217 +0,0 @@
-import PySimpleGUI as sg
-import praw # The Reddit APIs
-from webbrowser import open_new_tab
-
-"""
- Demo Reddit Searcher
-
- Will search through a list of subreddits for a string(s) of your choice. You can search only the
- posts or the posts and comments. When a match is found the title will be displayed in the window.
- Two progress meters show the current progress.
- Once completed, a listbox is populared with he responses. Click on the titles and a brower tab
- is opened to the topic.
-
- NOTE - you must register with Reddit as a developer. https://www.reddit.com/prefs/apps/
- You can set these credentials using the "Settings Window".
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-settings = sg.UserSettings()
-
-def make_search_row(item_number):
- search_layout = [sg.Combo(sorted(settings.get('-search string-', [])), settings['-last search-'], size=(45,1), k=('-SEARCH STRING-', item_number)),
- # sg.In(key=('-SEARCH STRING-', item_number)),
- sg.CB('Require', key=('-SEARCH REQUIRED-', item_number))]
- return search_layout
-
-def settings_window():
- def input_line(text, key, default):
- return [sg.T(text, size=(15,1), justification='r'), sg.In(default, size=(20,1), k=key)]
-
- layout = [[sg.T('Reddit PRAW Settings', font='default 15')],
- [sg.T('Note - You must register with Reddit to obtain PRAW credentials')],
- input_line('Client ID', '-CLIENT ID-', settings['client_id']),
- input_line('Client Secret', '-CLIENT SECRET-', settings['client_secret']),
- input_line('User Agent', '-USER AGENT-', settings['user_agent']),
- input_line('Username', '-USERNAME-', settings['username']),
- input_line('Password', '-PASSWORD-', settings['password']),
- [sg.CB('Clear Search History', k='-CLEAR HISTORY-')],
- ]
- layout += [[sg.Ok(), sg.Cancel()]]
-
- event, values = sg.Window('Reddit Reader Settings', layout).read(close=True)
-
- if event == 'Ok':
- settings['client_id'] = values['-CLIENT ID-']
- settings['client_secret'] = values['-CLIENT SECRET-']
- settings['user_agent'] = values['-USER AGENT-']
- settings['username'] = values['-USERNAME-']
- settings['password'] = values['-PASSWORD-']
- if values['-CLEAR HISTORY-']:
- settings['-search string-'] = []
- return True
-
- return False
-
-
-def main():
- while True:
- # reddit_praw_parameters = settings.get_dict()
- reddit_praw_parameters = {'client_id' : settings['client_id'], 'client_secret':settings['client_secret'],
- 'user_agent' : settings['user_agent'], 'username' : settings['username'], 'password': settings['password']}
- try:
- reddit = praw.Reddit(**reddit_praw_parameters)
- break
- except Exception as e:
- sg.popup('Problem with your settings file', e)
- if not settings_window():
- sg.popup_error('Must set settings before can continue')
- exit()
-
- # Read your Reddit PRAW configuration from a json file
- # try:
- # with open(path.join(path.dirname(__file__), r'praw.cfg'), 'r') as f:
- # reddit_praw_parameters = load(f)
- # except:
- # sg.popup_error('Failed loading the Reddit API login credential file.', 'The File should be named:', path.join(path.dirname(__file__), r'praw.cfg'))
- # exit()
- # To use the Reddit APIs you will need to sign up by visiting this site:
- # https://www.reddit.com/prefs/apps/
- # You will receive a client_id and client_secret string that you can
- # enter along with your normal Reddit ID & Password and save into a file named praw.cfg
-
- sub_names = ('Python', 'learnpython', 'learnprogramming', 'PySimpleGUI', 'madeinpython', 'AskProgramming', 'Coding', 'Programming', 'learnmachinelearning', 'MLQuestions', 'datascience', 'MachineLearning', 'pythontips', 'pystats', 'pythoncoding', 'pythondev', 'scipy')
-
- sg.theme('Dark Red')
- num_searches = 1
- search_layout = [[sg.B('+'), sg.T('Add term')]]
- search_layout += [make_search_row(i) for i in range(num_searches)]
- layout = [[sg.Text('Reddit Searcher', font='Any 18')],
- [sg.Frame('Choose Subs',
- [[sg.Listbox(sub_names, size=(25, 7), select_mode=sg.SELECT_MODE_MULTIPLE, key='-SUBS-')]]),
- sg.Frame('Options',
- [[sg.Checkbox('Look in Comments', True, key='-COMMENTS-')],
- [sg.Checkbox('Show finds in browser', key='-BROWSER-')],
- [sg.Checkbox('Show popup', key='-POPUP-')],
- [sg.Text('Limit: '), sg.Spin(list(range(200, 5000)), size=(4, 1), key='-LIMIT-')]])],
- [sg.Frame('Search Terms', search_layout, key='-SEARCH FRAME-' )],
- [sg.Frame('Status',[
- [sg.Text('Reading Sub:'), sg.Text(size=(25, 1), key='-OUT SUB-')],
- [sg.Text('Reading Post:'), sg.Text(size=(40, 1), key='-OUT POST-')],
- [sg.Text('Posts Read:'), sg.Text(size=(25, 1), key='-NUM POSTS-')],
- [sg.T('Sub Progress', size=(12,1)), sg.ProgressBar(100, orientation='horizontal', size=(30, 20), key='-PROG-')],
- [sg.T('Overall Progress', size=(12,1)),sg.ProgressBar(100, orientation='horizontal', size=(30, 20), key='-PROG-TOTAL-')],])],
- [sg.Frame('Results (Click to Lauch in Browser)',
- [[sg.Listbox([], size=(60,10), key='-LISTBOX-', enable_events=True)]])],
- [sg.Button('Start Search', bind_return_key=True), sg.B('Settings'), sg.Button('Exit')], ]
-
- window = sg.Window('Reddit Reader', layout, icon=reddit_icon, use_default_focus=False)
-
- results = {}
- while True: # Event Loop
- event, values = window.read()
- if event in (None, 'Exit'):
- break
- if event == 'Settings':
- if settings_window():
- reddit = praw.Reddit(**reddit_praw_parameters)
-
- subs_to_read = values['-SUBS-']
- if event.startswith('Start'):
- window['-LISTBOX-'].update([''])
- results = {}
- search_list = [] # make a list of tuples (search term, bool required)
- for v in values:
- if isinstance(v, tuple): # if value is a tuple
- if v[0] == '-SEARCH STRING-':
- search_list.append((values[v].lower(), values[('-SEARCH REQUIRED-', v[1])]))
- settings['-search string-'] = list(set(settings.get('-search string-', []) + [values['-SEARCH STRING-', v[1]], ]))
- settings['-last search-'] = search_list[0][0]
- print('last search = ', settings['-last search-'])
- print('Search list = ', search_list)
- # Loop through the subs
- for sub_count, sub in enumerate(subs_to_read):
- window['-OUT SUB-'].update(sub)
- subreddit = reddit.subreddit(sub)
- submissions = subreddit.new(limit=int(values['-LIMIT-']))
- num_submissions = int(values['-LIMIT-'])
- # Loop through submissions
- for num, submission in enumerate(submissions):
- opened = False
- text = ''.join([t.lower() for t in submission.selftext if ord(t) in range(65536)])
- window['-PROG-'].update_bar(100 * (num + 1) // num_submissions)
- title = ''.join([t for t in submission.title if ord(t) in range(65536)])
- window['-NUM POSTS-'].update(num)
- window.refresh()
- found = False
- for search_item in search_list:
- if search_item[0] and search_item[0] in text:
- found = True
- elif search_item[1]:
- found = False
- break
- if found:
- opened = True
- results[title] = submission.url
- window['-LISTBOX-'].update(list(results.keys()))
- if values['-BROWSER-']:
- open_new_tab(submission.url)
- elif values['-POPUP-']:
- sg.popup_scrolled(f'Search found', submission.url, f'\nTITLE: {title}', str(text), title=title, non_blocking=True)
- window['-OUT POST-'].update(str(title))
- if values['-COMMENTS-']: # if should also search comments
- for comment in submission.comments:
- found = False
- for search_item in search_list:
- try:
- if search_item[0] and search_item[0] in comment.body.lower():
- found = True
- elif search_item[1]:
- found = False
- break
- except Exception as e:
- print(f'Exception searching the comments:\n{e}')
- if found:
- results[title] = submission.url
- window['-LISTBOX-'].update(list(results.keys()))
- comment_text = ''.join([t for t in comment.body if ord(t) in range(65536)])
- if values['-BROWSER-'] and not opened:
- open_new_tab(submission.url)
- opened = True
- elif values['-POPUP-']:
- sg.popup_scrolled(f'Search found in comment', submission.url, f'\nTITLE: {title}', comment_text, title=title, non_blocking=True)
- window.refresh()
- event, values = window.read(timeout=0)
- if event == '-LISTBOX-': # experimental - see if clicked on an item in the list while it's still being built
- url = results.get(values['-LISTBOX-'][0])
- if url: open_new_tab(url)
- if event in (None, 'Exit'):
- break
- # Done processing the single sub, so update the total progress bar
- window['-PROG-TOTAL-'].update_bar(100 * (sub_count + 1) // len(subs_to_read))
- if event in (None, 'Exit'):
- window['-OUT SUB-'].update('*** Aborted ***')
- break
- else:
- window['-OUT SUB-'].update('*** Done with this sub ***')
- else: # if made it through the loop, then show a popup saying completed
- window['-OUT SUB-'].update('*** DONE with all subs ***')
- if event is None:
- break
- if event == '+':
- window.extend_layout(window['-SEARCH FRAME-'], [make_search_row(num_searches)])
- num_searches += 1
- if event == '-LISTBOX-':
- url = results.get(values['-LISTBOX-'][0])
- if url: open_new_tab(url)
-
-
- window.close()
-
-if __name__ == '__main__':
- reddit_icon = b'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'
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_SDK_Help_Func_Parms.py b/DemoPrograms/Demo_SDK_Help_Func_Parms.py
deleted file mode 100644
index 8a76da926..000000000
--- a/DemoPrograms/Demo_SDK_Help_Func_Parms.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import PySimpleGUI as sg
-import inspect
-import sys
-
-"""
- Demo SDK Help - Function Parms
-
- This is the tool that was used in the Udemy course to display the function parameters
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- """
- Display a window that will display the docstrings for each PySimpleGUI Element and the Window object
-
- """
-
- sg.set_options(font='courier 12')
-
- functions = [m for m in inspect.getmembers(sys.modules['PySimpleGUI'], inspect.isfunction)]
- functions_names_lower = [f for f in functions if f[0][0].islower()]
- functions_names_upper = [f for f in functions if f[0][0].isupper()]
- # functions_names = sorted(functions_names_lower) + sorted(functions_names_upper)
- # func_names_str = [f[0] for f in functions if f[0][0].islower()]
- func_names_str = [f[0] for f in functions]
-
- func_parm_dict = {}
-
- # for func_str, func in functions_names_lower:
- for func_str, func in functions:
- # Build info about init method
- args = inspect.signature(func)
- params = args.parameters
- func_parm_list = []
- for a in params.values():
- func_def = str(a).split('=')
- if len(func_def) == 1:
- name, default = func_def[0], '*Required*'
- if name[0] == '*':
- default = '*Optional*'
- elif len(func_def) == 2:
- name, default = func_def[0], func_def[1]
- elif len(func_def) == 0:
- name, default = '', ''
- else:
- name, default = func_def[0], '*Object*'
- func_parm_list.append((name, default))
- func_parm_dict[func_str] = func_parm_list
-
- sg.theme('black')
- sg.theme_background_color('#131314')
- sg.theme_text_element_background_color('#131314')
- sg.theme_input_background_color('#131314')
- ml = sg.Multiline(size=(35, 20), key='-ML-', write_only=True, reroute_stdout=False, expand_y=True, expand_x=True)
-
- layout = [
- [sg.Titlebar('Func Parm Viewer', background_color='#131314', text_color='white')],
- # [sg.Combo([e for e in sorted(func_names_str)],background_color='#131314', size=(25,30), enable_events=True, key='-COMBO-'), sg.T(' '*6, grab=True)],
- [sg.Combo([e for e in sorted([f[0] for f in functions if f[0][0].islower()])],background_color='#131314', size=(25,30), enable_events=True, readonly=True, expand_x=True, key='-COMBO-')],
- sg.vtop([ml], expand_x=True, expand_y=True)] + [[sg.Sizegrip()]]
-
- window = sg.Window('Func Parms', layout, use_default_focus=False, keep_on_top=True, no_titlebar=True, margins=(0,0), right_click_menu=[[],['Edit Me', 'Upper Case Too', 'Lower Case Only', 'Exit']], resizable=True)
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- continue
- elif event.startswith('Upper'):
- window['-COMBO-'].update(values=[f[0] for f in functions if not f[0][0].startswith('_')])
- elif event.startswith('Lower'):
- window['-COMBO-'].update(values=[f[0] for f in functions if f[0][0].islower()])
- else:
- # ml.print(event, values)
- if event == '-COMBO-':
- func_chosen = values[event]
- else:
- func_chosen = None
- window['-ML-'].update('')
-
- ml.print(f'= {func_chosen} =', background_color='#FFFF00', text_color='black')
- func_parms = func_parm_dict[func_chosen]
- # print(func_parms)
- for parm, default in func_parms:
- ml.print(f'{parm:18}', text_color='green yellow', end=' = ')
- if default != inspect._empty:
- if isinstance(default, str):
- if default in ('None', '(None, None)', '(None,None)'):
- color = 'pink'
- elif default in ('False', 'True'):
- color = '#00FF7F'
- else:
- color = None
- ml.print(f'{default}', end='\n', text_color=color)
- else:
- ml.print(default, end='\n')
- else:
- ml.print(f'{default}', end='\n')
- ml.set_vscroll_position(0)
-
- window.close()
-
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py b/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py
deleted file mode 100644
index f9bc2b79b..000000000
--- a/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py
+++ /dev/null
@@ -1,95 +0,0 @@
-import PySimpleGUI as sg
-import inspect
-
-
-"""
- Demo SDK Help - Init and Update Parms
-
- This is the tool that was used in the Udemy course to display the init and update parameters.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- """
- Display a window that displays the parms for the init and update methods for each element
-
- """
-
- common_parms = ['key','k','font','pad','p', 'visible','size','s', 'change_submits', 'enable_events','right_click_menu','tooltip','metadata', 'expand_x', 'expand_y']
- element_classes = sg.Element.__subclasses__()
- element_names = {element.__name__: element for element in element_classes}
- element_names['Window'] = sg.Window
- element_names['SystemTray'] = sg.SystemTray
- # vars3 = [m for m in inspect.getmembers(sys.modules[__name__])]
- element_arg_default_dict = {}
- element_arg_default_dict_update = {}
- for element in element_classes:
- # Build info about init method
- args = inspect.getargspec(element.__init__).args[1:]
- defaults = inspect.getargspec(element.__init__).defaults
- if len(args) != len(defaults):
- diff = len(args) - len(defaults)
- defaults = ('NO DEFAULT',)*diff + defaults
- args_defaults = []
- for i, a in enumerate(args):
- args_defaults.append((a, defaults[i]))
- element_arg_default_dict[element.__name__] = args_defaults
-
- # Build info about update method
- args = inspect.getargspec(element.update).args[1:]
- defaults = inspect.getargspec(element.update).defaults
- if args is None or defaults is None:
- element_arg_default_dict_update[element.__name__] = (('',''),)
- continue
- if len(args) != len(defaults):
- diff = len(args) - len(defaults)
- defaults = ('NO DEFAULT',)*diff + defaults
- args_defaults = []
- for i, a in enumerate(args):
- args_defaults.append((a, defaults[i]))
- element_arg_default_dict_update[element.__name__] = args_defaults if len(args_defaults) else (('',''),)
-
- sg.theme('black')
- sg.theme_background_color('#131314')
- sg.theme_text_element_background_color('#131314')
- sg.theme_input_background_color('#131314')
- ml = sg.Multiline(size=(40, 30), key='-ML-', write_only=True, reroute_stdout=True, expand_y=True, expand_x=True)
- layout = [ [sg.Titlebar('Element Init & Update Parm Viewer', background_color='#131314', text_color='white')],
- [sg.Combo([e for e in sorted(element_names.keys())],background_color='#131314', size=(25,30), enable_events=True, readonly=True, expand_x=True, key='-COMBO-')],
- sg.vtop([ml], expand_y=True, expand_x=True) ] + [[sg.Sizegrip()]]
- # layout += [[Button('Exit', size=(15, 1))]]
-
- window = sg.Window('Init & Update Parms', layout, use_default_focus=False, keep_on_top=True, no_titlebar=True, margins=(0,0),font='Courier 12', right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, resizable=True)
- # ml = window['-ML-'] # type: sg.MLine
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- # ml.print(event, values)
- if event == '-COMBO-':
- element_chosen = values[event]
- else:
- element_chosen = None
- if element_chosen in element_arg_default_dict:
- window['-ML-'].update('')
- ml.print('========== Init Parms ==========', background_color='#FFFF00', text_color='black')
- for parm, default in element_arg_default_dict[element_chosen]:
- ml.print(f'{parm:18}', text_color='hot pink' if parm in common_parms else 'green yellow', end=' = ')
- ml.print(default, text_color='hot pink' if parm in common_parms else 'white', end = ',\n')
- ml.print('========== Update Parms ==========', background_color='#FFFF00', text_color='black')
- # print(element_arg_default_dict_update[element_chosen])
- for parm, default in element_arg_default_dict_update[element_chosen]:
- ml.print(f'{parm:18}', text_color='hot pink' if parm in common_parms else 'green yellow', end=' = ')
- ml.print(default, text_color='hot pink' if parm in common_parms else 'white', end = ',\n')
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
-
- window.close()
-
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Save_Any_Window_As_Image.py b/DemoPrograms/Demo_Save_Any_Window_As_Image.py
deleted file mode 100644
index fbbcc34c4..000000000
--- a/DemoPrograms/Demo_Save_Any_Window_As_Image.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import PySimpleGUI as sg
-import win32gui
-from PIL import ImageGrab
-
-"""
- Demo - Save Window screenshot
- Works on WINDOWS only.
- Saves a window as an image file. Tested saving as PNG and JPG. Input the title of the Window and it will be
- saved in the format indicated by the filename.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# --------------------------------- Function to Save Window as JPG ---------------------------------
-
-
-def save_win(filename=None, title=None):
- """
- Saves a window with the title provided as a file using the provided filename.
- If one of them is missing, then a window is created and the information collected
-
- :param filename:
- :param title:
- :return:
- """
- C = 7 # pixels to crop
- if filename is None or title is None:
- layout = [[sg.T('Choose window to save', font='Any 18')],
- [sg.T('The extension you choose for filename will determine the image format')],
- [sg.T('Window Title:', size=(12,1)), sg.I(title if title is not None else '', key='-T-')],
- [sg.T('Filename:', size=(12,1)), sg.I(filename if filename is not None else '', key='-F-')],
- [sg.Button('Ok', bind_return_key=True), sg.Button('Cancel')]]
- event, values = sg.Window('Choose Win Title and Filename',layout).read(close=True)
- if event != 'Ok': # if cancelled or closed the window
- print('Cancelling the save')
- return
- filename, title = values['-F-'], values['-T-']
- try:
- fceuxHWND = win32gui.FindWindow(None, title)
- rect = win32gui.GetWindowRect(fceuxHWND)
- rect_cropped = (rect[0]+C, rect[1], rect[2]-C, rect[3]-C)
- grab = ImageGrab.grab(bbox=rect_cropped)
- grab.save(filename)
- sg.popup('Wrote image to file:',filename)
- except Exception as e:
- sg.popup('Error trying to save screenshot file', e)
-
-
-if __name__ == '__main__':
- save_win()
-
diff --git a/DemoPrograms/Demo_Save_Window_As_Image.py b/DemoPrograms/Demo_Save_Window_As_Image.py
deleted file mode 100644
index 355de580c..000000000
--- a/DemoPrograms/Demo_Save_Window_As_Image.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import PySimpleGUI as sg
-from PIL import ImageGrab
-
-"""
- Demo - Saving the contents of a window as an image file
-
- This demo will teach you how to save any portion of your window to an image file.
- You can save in JPG, GIF, or PNG format.
-
- In this example the entire window's layout is placed into a single Column Element. This allows
- us to save an image of the Column which saves the entire window layout
-
- Portions of windows can be saved, such as a Graph Element, by specifying the Graph Element instead of the Column
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def save_element_as_file(element, filename):
- """
- Saves any element as an image file. Element needs to have an underlyiong Widget available (almost if not all of them do)
- :param element: The element to save
- :param filename: The filename to save to. The extension of the filename determines the format (jpg, png, gif, ?)
- """
- widget = element.Widget
- box = (widget.winfo_rootx(), widget.winfo_rooty(), widget.winfo_rootx() + widget.winfo_width(), widget.winfo_rooty() + widget.winfo_height())
- grab = ImageGrab.grab(bbox=box)
- grab.save(filename)
-
-
-def main():
-
- col = [[sg.Text('This is the first line')],
- [sg.In()],
- [sg.Button('Save'), sg.Button('Exit')]]
-
- layout = [[sg.Column(col, key='-COLUMN-')]] # put entire layout into a column so it can be saved
-
- window = sg.Window("Drawing and Moving Stuff Around", layout)
-
- while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break # exit
- elif event == 'Save':
- filename = sg.popup_get_file('Choose file (PNG, JPG, GIF) to save to', save_as=True)
- save_element_as_file(window['-COLUMN-'], filename)
-
- window.close()
-
-main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Save_Windows_As_Images.py b/DemoPrograms/Demo_Save_Windows_As_Images.py
deleted file mode 100644
index f4091ba57..000000000
--- a/DemoPrograms/Demo_Save_Windows_As_Images.py
+++ /dev/null
@@ -1,148 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import os
-import psutil
-import win32api
-import win32con
-import win32gui
-import win32process
-from PIL import ImageGrab
-
-"""
- Demo - Save Windows as Images
-
- Works on WINDOWS only.
- Saves a window as an image file. Tested saving as PNG and JPG.
- saved in the format indicated by the filename.
- The window needs to be on the primary display.
- 2022 update was to remove OpenCV requirement.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def convert_string_to_tuple(string):
- """
- Converts a string that represents a tuple. These strings have the format:
- "('item 1', 'item 2')"
- The desired return value is ('item 1', 'item 2')
- :param string:
- :return:
- """
- parts = string[1:-1].split(',')
- part1 = parts[0][1:-1]
- part2 = parts[1][2:-1]
- return part1, part2
-
-
-def show_list_by_name(window, output_key, python_only):
- process_list = get_window_list()
-
- title_list = []
- for proc in process_list:
- names = convert_string_to_tuple(proc)
- if python_only and names[0] == 'python.exe':
- title_list.append(names[1])
- elif not python_only:
- title_list.append(names[1])
- title_list.sort()
- window[output_key].update(title_list)
- return title_list
-
-
-def get_window_list():
- titles = []
- t = []
- pidList = [(p.pid, p.name()) for p in psutil.process_iter()]
-
- def enumWindowsProc(hwnd, lParam):
- """ append window titles which match a pid """
- if (lParam is None) or ((lParam is not None) and (win32process.GetWindowThreadProcessId(hwnd)[1] == lParam)):
- text = win32gui.GetWindowText(hwnd)
- if text:
- wStyle = win32api.GetWindowLong(hwnd, win32con.GWL_STYLE)
- if wStyle & win32con.WS_VISIBLE:
- t.append("%s" % (text))
- return
-
- def enumProcWnds(pid=None):
- win32gui.EnumWindows(enumWindowsProc, pid)
-
- for pid, pName in pidList:
- enumProcWnds(pid)
- if t:
- for title in t:
- titles.append("('{0}', '{1}')".format(pName, title))
- t = []
- titles = sorted(titles, key=lambda x: x[0].lower())
- return titles
-
-def save_win(filename=None, title=None, crop=True):
- """
- Saves a window with the title provided as a file using the provided filename.
- If one of them is missing, then a window is created and the information collected
-
- :param filename:
- :param title:
- :return:
- """
- C = 7 if crop else 0 # pixels to crop
- try:
- fceuxHWND = win32gui.FindWindow(None, title)
- rect = win32gui.GetWindowRect(fceuxHWND)
- rect_cropped = (rect[0] + C, rect[1], rect[2] - C, rect[3] - C)
- grab = ImageGrab.grab(bbox=rect_cropped)
- grab.save(filename)
- sg.cprint('Wrote image to file:')
- sg.cprint(filename, c='white on purple')
- except Exception as e:
- sg.popup('Error trying to save screenshot file', e, keep_on_top=True)
-
-
-def main():
- layout = [[sg.Text('Window Snapshot', key='-T-', font='Any 20', justification='c')],
- [sg.Text('Choose one or more window titles from list')],
- [sg.Listbox(values=[' '], size=(50, 20), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 12), key='-PROCESSES-')],
- [sg.Checkbox('Show only Python programs', default=True, key='-PYTHON ONLY-')],
- [sg.Checkbox('Crop image', default=True, key='-CROP-')],
- [sg.Multiline(size=(63, 10), font=('Courier', 10), key='-ML-')],
- [sg.Text('Output folder:', size=(15,1)), sg.In(os.path.dirname(__file__), key='-FOLDER-'), sg.FolderBrowse()],
- [sg.Text('Hardcode filename:', size=(15,1)), sg.In(key='-HARDCODED FILENAME-')],
- [sg.Button('Refresh'),
- sg.Button('Snapshot', button_color=('white', 'DarkOrange2')),
- sg.Exit(button_color=('white', 'sea green'))]]
-
- window = sg.Window('Window Snapshot', layout, keep_on_top=True, auto_size_buttons=False, default_button_element_size=(12, 1), finalize=True)
-
- window['-T-'].expand(True, False, False) # causes text to center by expanding the element
-
- sg.cprint_set_output_destination(window, '-ML-')
- show_list_by_name(window, '-PROCESSES-', True)
-
- # ---------------- main loop ----------------
- while True:
- # --------- Read and update window --------
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- # --------- Do Button Operations --------
- if event == 'Refresh':
- show_list_by_name(window, '-PROCESSES-', values['-PYTHON ONLY-'])
- elif event == 'Snapshot':
- for i, title in enumerate(values['-PROCESSES-']):
- sg.cprint('Saving:', end='', c='white on red')
- sg.cprint(' ', title, colors='white on green')
- if values['-HARDCODED FILENAME-']:
- fname = values['-HARDCODED FILENAME-']
- fname = f'{fname[:-4]}{i}{fname[-4:]}'
- output_filename = os.path.join(values['-FOLDER-'], fname)
- else:
- output_filename = os.path.join(values['-FOLDER-'], f'{title}.png')
- save_win(output_filename, title, values['-CROP-'])
- window.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/DemoPrograms/Demo_Script_Launcher.py b/DemoPrograms/Demo_Script_Launcher.py
index 09616427f..8137d363b 100644
--- a/DemoPrograms/Demo_Script_Launcher.py
+++ b/DemoPrograms/Demo_Script_Launcher.py
@@ -4,12 +4,6 @@
import ntpath
import subprocess
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
LOCATION_OF_YOUR_SCRIPTS = ''
# Execute the command. Will not see the output from the command until it completes.
@@ -47,7 +41,7 @@ def execute_command_nonblocking(command, *args):
def Launcher2():
- sg.theme('GreenTan')
+ sg.change_look_and_feel('GreenTan')
filelist = glob.glob(LOCATION_OF_YOUR_SCRIPTS+'*.py')
namesonly = []
diff --git a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py
deleted file mode 100644
index 27efe0edb..000000000
--- a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py
+++ /dev/null
@@ -1,119 +0,0 @@
-import PySimpleGUI as sg
-import re
-
-"""
- Demo Program - Realtime output of a shell command in the window using ANSI color codes
- Shows how you can run a long-running subprocess and have the output
- be displayed in realtime in the window. The output is assumed to have color codes embedded in it.
-
- The commands you enter will be run as shell commands. The output is then shown with the ANSI strings parsed.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def cut_ansi_string_into_parts(string_with_ansi_codes):
- """
- Converts a string with ambedded ANSI Color Codes and parses it to create
- a list of tuples describing pieces of the input string.
- :param string_with_ansi_codes:
- :return: [(sty, str, str, str), ...] A list of tuples. Each tuple has format: (text, text color, background color, effects)
- """
- color_codes_english = ['Black', 'Red', 'Green', 'Yellow', 'Blue', 'Magenta', 'Cyan', 'White', 'Reset']
- color_codes = ["30m", "31m", "32m", "33m", "34m", "35m", "36m", "37m", "0m"]
- effect_codes_english = ['Italic', 'Underline', 'Slow Blink', 'Rapid Blink', 'Crossed Out']
- effect_codes = ["3m", "4m", "5m", "6m", "9m"]
- background_codes = ["40m", "41m", "42m", "43m", "44m", "45m", "46m", "47m"]
- background_codes_english = ["Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"]
-
- ansi_codes = color_codes + effect_codes
-
- tuple_list = []
-
- string_list = string_with_ansi_codes.split("\u001b[")
-
- if (len(string_list)) == 1:
- string_list = string_with_ansi_codes.split("\033[")
-
- for teststring in string_list:
- if teststring == string_with_ansi_codes:
- tuple_list += [(teststring, None, None, None)]
- break
- if any(code in teststring for code in ansi_codes):
- static_string = None
- color_used = None
- effect_used = None
- background_used = None
- for color in range(0, len(color_codes)):
- if teststring.startswith(color_codes[color]):
- working_thread = teststring.split(color_codes[color])
- ansi_strip = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
- static_string = ansi_strip.sub('', working_thread[1])
- color_used = color_codes_english[color]
- for effect in range(0, len(effect_codes)):
- if teststring.startswith(effect_codes[effect]):
- working_thread = teststring.split(effect_codes[effect])
- ansi_strip = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
- static_string = ansi_strip.sub('', working_thread[1])
- effect_used = effect_codes_english[effect]
- for background in range(0, len(background_codes)):
- if teststring.startswith(background_codes[background]):
- working_thread = teststring.split(background_codes[background])
- ansi_strip = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
- static_string = ansi_strip.sub('', working_thread[1])
- background_used = background_codes_english[background]
- try:
- if not tuple_list[len(tuple_list) - 1][0]:
- if not tuple_list[len(tuple_list) - 1][1] == None:
- color_used = tuple_list[len(tuple_list) - 1][1]
- if not tuple_list[len(tuple_list) - 1][2] == None:
- background_used = tuple_list[len(tuple_list) - 1][2]
- if not tuple_list[len(tuple_list) - 1][3] == None:
- effect_used = tuple_list[len(tuple_list) - 1][3]
- tuple_list += [(static_string, color_used, background_used, effect_used)]
- else:
- tuple_list += [(static_string, color_used, background_used, effect_used)]
- except Exception:
- tuple_list += [(static_string, color_used, background_used, effect_used)]
-
- new_tuple_list = []
-
- for x in range(0, len(tuple_list)):
- if tuple_list[x][0]:
- new_tuple_list += [[tuple_list[x][0], tuple_list[x][1], tuple_list[x][2], tuple_list[x][3]]]
-
- return new_tuple_list
-
-
-def main():
- layout = [
- [sg.Multiline(size=(110, 30), font='courier 10', background_color='black', text_color='white', key='-MLINE-', expand_x=True, expand_y=True)],
- [sg.T('Promt> '), sg.Input(key='-IN-', focus=True, do_not_clear=False)],
- [sg.Button('Run', bind_return_key=True), sg.Button('Exit'), sg.Sizegrip()]]
-
- window = sg.Window('Realtime Shell Command Output', layout, resizable=True)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Run':
- args = values['-IN-'].split(' ')
- p = sg.execute_command_subprocess(args[0], *args[1:], wait=False, pipe_output=True, merge_stderr_with_stdout=True )
- lines = sg.execute_get_results(p)
-
- for line in lines:
- if line is None:
- continue
- ansi_list = cut_ansi_string_into_parts(line)
- for ansi_item in ansi_list:
- if ansi_item[1] == 'Reset':
- ansi_item[1] = None
- window['-MLINE-'].update(ansi_item[0] , text_color_for_value=ansi_item[1], background_color_for_value=ansi_item[2], append=True, autoscroll=True)
- window.refresh()
-
- window.close()
-
-main()
diff --git a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
index 1c46ff09c..0c8a3c106 100644
--- a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
+++ b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
@@ -1,34 +1,48 @@
+import subprocess
+import sys
import PySimpleGUI as sg
"""
Demo Program - Realtime output of a shell command in the window
Shows how you can run a long-running subprocess and have the output
be displayed in realtime in the window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-
def main():
- layout = [
- [sg.Multiline(size=(110, 30), echo_stdout_stderr=True, reroute_stdout=True, autoscroll=True, background_color='black', text_color='white', key='-MLINE-')],
- [sg.T('Promt> '), sg.Input(key='-IN-', focus=True, do_not_clear=False)],
- [sg.Button('Run', bind_return_key=True), sg.Button('Exit')]]
-
- window = sg.Window('Realtime Shell Command Output', layout)
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Run':
- cmd_list = values['-IN-'].split(' ')
- sp = sg.execute_command_subprocess(cmd_list[0], *cmd_list[1:], pipe_output=True, wait=False)
- results = sg.execute_get_results(sp, timeout=1)
- print(results[0])
-
- window.close()
+ layout = [ [sg.Text('Enter the command you wish to run')],
+ [sg.Input(key='-IN-')],
+ [sg.Output(size=(60,15))],
+ [sg.Button('Run'), sg.Button('Exit')] ]
+
+ window = sg.Window('Realtime Shell Command Output', layout)
+
+ while True: # Event Loop
+ event, values = window.read()
+ # print(event, values)
+ if event in (None, 'Exit'):
+ break
+ elif event == 'Run':
+ runCommand(cmd=values['-IN-'], window=window)
+ window.close()
+
+
+def runCommand(cmd, timeout=None, window=None):
+ """ run shell command
+ @param cmd: command to execute
+ @param timeout: timeout for command execution
+ @param window: the PySimpleGUI window that the output is going to (needed to do refresh on)
+ @return: (return code from command, command output)
+ """
+ p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ output = ''
+ for line in p.stdout:
+ line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip()
+ output += line
+ print(line)
+ window.refresh() if window else None # yes, a 1-line if, so shoot me
+
+ retval = p.wait(timeout)
+ return (retval, output)
main()
diff --git a/DemoPrograms/Demo_Script_Parameters.py b/DemoPrograms/Demo_Script_Parameters.py
index f614e2a6f..6f3da38cb 100644
--- a/DemoPrograms/Demo_Script_Parameters.py
+++ b/DemoPrograms/Demo_Script_Parameters.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-import sys
+
'''
Quickly add a GUI to your script!
@@ -11,13 +11,8 @@
The 1-line-GUI shows a form that allows the user to browse to find the filename. The GUI
stores the result in the variable fname, just like the command line parsing did.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
-fname = ''
if len(sys.argv) == 1:
layout = [
[sg.Text('Document to open')],
@@ -27,7 +22,6 @@
window = sg.Window('My Script', layout)
event, values = window.read()
window.close()
- fname = values['-FNAME-']
else:
fname = sys.argv[1]
if not fname:
diff --git a/DemoPrograms/Demo_Separator_Elements.py b/DemoPrograms/Demo_Separator_Elements.py
deleted file mode 100644
index bbc03dcc1..000000000
--- a/DemoPrograms/Demo_Separator_Elements.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Separator Elements
-
- Shows usage of both Horizontal and Vertical Separator Elements
- Vertical Separators are placed BETWEEN 2 elements ON the same row. These work well when one
- of the elements is a Column or the element spans several rows
-
- Horizontal separators are placed BETWEEN 2 rows. They will occupy the entire span of the row they
- are located on. If that row is constrained within a container, then it will spand the widget of
- the container.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-left_col = sg.Column([[sg.Listbox((1,2,3,4,5,6), size=(6,4))]])
-
-right_col = sg.Column([[sg.Input(), sg.Input()],
- [sg.HorizontalSeparator()],
- [sg.Column([[sg.In()], [sg.HorizontalSeparator()]], pad=(0,0))],])
-
-layout = [
- [sg.Text('Window with some separators')],
- [left_col, sg.VerticalSeparator(), right_col],
- [sg.Button('Go'), sg.Button('Exit')]
- ]
-
-window = sg.Window('Window Title', layout)
-
-while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-window.close()
diff --git a/DemoPrograms/Demo_Settings_Save_Load.py b/DemoPrograms/Demo_Settings_Save_Load.py
deleted file mode 100644
index 88fec5763..000000000
--- a/DemoPrograms/Demo_Settings_Save_Load.py
+++ /dev/null
@@ -1,104 +0,0 @@
-import PySimpleGUI as sg
-from json import (load as jsonload, dump as jsondump)
-from os import path
-
-"""
- A simple "settings" implementation. Load/Edit/Save settings for your programs
- Uses json file format which makes it trivial to integrate into a Python program. If you can
- put your data into a dictionary, you can save it as a settings file.
-
- Note that it attempts to use a lookup dictionary to convert from the settings file to keys used in
- your settings window. Some element's "update" methods may not work correctly for some elements.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
- Licensed under LGPL-3
-"""
-
-SETTINGS_FILE = path.join(path.dirname(__file__), r'settings_file.cfg')
-DEFAULT_SETTINGS = {'max_users': 10, 'user_data_folder': None , 'theme': sg.theme(), 'zipcode' : '94102'}
-# "Map" from the settings dictionary keys to the window's element keys
-SETTINGS_KEYS_TO_ELEMENT_KEYS = {'max_users': '-MAX USERS-', 'user_data_folder': '-USER FOLDER-' , 'theme': '-THEME-', 'zipcode' : '-ZIPCODE-'}
-
-########################################## Load/Save Settings File ##########################################
-def load_settings(settings_file, default_settings):
- try:
- with open(settings_file, 'r') as f:
- settings = jsonload(f)
- except Exception as e:
- sg.popup_quick_message(f'exception {e}', 'No settings file found... will create one for you', keep_on_top=True, background_color='red', text_color='white')
- settings = default_settings
- save_settings(settings_file, settings, None)
- return settings
-
-
-def save_settings(settings_file, settings, values):
- if values: # if there are stuff specified by another window, fill in those values
- for key in SETTINGS_KEYS_TO_ELEMENT_KEYS: # update window with the values read from settings file
- try:
- settings[key] = values[SETTINGS_KEYS_TO_ELEMENT_KEYS[key]]
- except Exception as e:
- print(f'Problem updating settings from window values. Key = {key}')
-
- with open(settings_file, 'w') as f:
- jsondump(settings, f)
-
- sg.popup('Settings saved')
-
-########################################## Make a settings window ##########################################
-def create_settings_window(settings):
- sg.theme(settings['theme'])
-
- def TextLabel(text): return sg.Text(text+':', justification='r', size=(15,1))
-
- layout = [ [sg.Text('Settings', font='Any 15')],
- [TextLabel('Max Users'), sg.Input(key='-MAX USERS-')],
- [TextLabel('User Folder'),sg.Input(key='-USER FOLDER-'), sg.FolderBrowse(target='-USER FOLDER-')],
- [TextLabel('Zipcode'),sg.Input(key='-ZIPCODE-')],
- [TextLabel('Theme'),sg.Combo(sg.theme_list(), size=(20, 20), key='-THEME-')],
- [sg.Button('Save'), sg.Button('Exit')] ]
-
- window = sg.Window('Settings', layout, keep_on_top=True, finalize=True)
-
- for key in SETTINGS_KEYS_TO_ELEMENT_KEYS: # update window with the values read from settings file
- try:
- window[SETTINGS_KEYS_TO_ELEMENT_KEYS[key]].update(value=settings[key])
- except Exception as e:
- print(f'Problem updating PySimpleGUI window from settings. Key = {key}')
-
- return window
-
-########################################## Main Program Window & Event Loop ##########################################
-def create_main_window(settings):
- sg.theme(settings['theme'])
-
- layout = [[sg.Menu([['&File', []], ['&Edit', ['&Settings'], ],['&Help', '&About...'],])],
- [sg.T('This is my main application')],
- [sg.T('Add your primary window stuff in here')],
- [sg.B('Ok'), sg.B('Exit'), sg.B('Change Settings')]]
-
- return sg.Window('Main Application', layout)
-
-
-def main():
- window, settings = None, load_settings(SETTINGS_FILE, DEFAULT_SETTINGS )
-
- while True: # Event Loop
- if window is None:
- window = create_main_window(settings)
-
- event, values = window.read()
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if event in ('Change Settings', 'Settings'):
- event, values = create_settings_window(settings).read(close=True)
- if event == 'Save':
- window.close()
- window = None
- save_settings(SETTINGS_FILE, settings, values)
- window.close()
-
-
-main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Simple_Material_Feel.py b/DemoPrograms/Demo_Simple_Material_Feel.py
deleted file mode 100644
index 81ebe92de..000000000
--- a/DemoPrograms/Demo_Simple_Material_Feel.py
+++ /dev/null
@@ -1,89 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - A simple minimal window with a material design feel
-
- Contains base64 images for:
- * The PSG Yellow Graphic
- * The 2 toggle buttons
- * The large spinning animation
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def make_window(light_mode):
- if light_mode:
- sg.theme('light grey')
- else:
- sg.theme('black')
- BLUE = '#2196f2'
- DARK_GRAY = '#212021'
- LIGHT_GRAY = '#e0e0e0'
- BLUE_BUTTON_COLOR = '#FFFFFF on #2196f2'
- GREEN_BUTTON_COLOR ='#FFFFFF on #00c851'
- LIGHT_GRAY_BUTTON_COLOR = f'#212021 on #e0e0e0'
- DARK_GRAY_BUTTON_COLOR = '#e0e0e0 on #212021'
-
- layout = [[sg.Col([[sg.T('Welcome to my App')],
- [sg.T('Your license status: '), sg.T('Trial', k='-LIC STATUS-')],
- [sg.B('Light', size=(10,2),button_color=LIGHT_GRAY_BUTTON_COLOR), sg.B('Dark', size=(10,2), button_color=DARK_GRAY_BUTTON_COLOR)],
- [sg.T()],
- [sg.Image(data=PSG_GRAPHIC)],
- [sg.B(image_data=T_OFF, k='-TOGGLE1-', metadata=False, button_color=sg.theme_background_color(), border_width=0, image_subsample=2),
- sg.B(image_data=T_ON, k='-TOGGLE2-', button_color=sg.theme_background_color(), border_width=0, image_subsample=2, metadata=True)],
- [sg.T()],
- [sg.B('Do Something', size=(14,2), button_color=BLUE_BUTTON_COLOR),
- sg.B('Upgrade', size=(14,2), button_color=GREEN_BUTTON_COLOR),
- sg.B('Exit', size=(14,2), button_color=LIGHT_GRAY_BUTTON_COLOR)],
- [sg.Image(k='-GIF-', metadata=0)],
- [sg.T('The end of "my App"')]], element_justification='c', k='-TOP COL-')]]
-
- layout = [[sg.Titlebar('Material Design Custom Titlebar',
- background_color=BLUE if light_mode else DARK_GRAY,
- text_color='white' if light_mode else LIGHT_GRAY,
- k='-TITLEBAR-')]] + layout
-
- window = sg.Window('Window Title', layout)
-
- return window
-
-
-def main():
- light_mode = True
- window = make_window(light_mode)
- show_animation = False
- # LOADING_GIF = sg.DEFAULT_BASE64_LOADING_GIF
- while True: # Event Loop
- event, values = window.read(timeout=100)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event.startswith('-TOGGLE'):
- state = window[event].metadata = not window[event].metadata
- window[event].update(image_data=T_ON if state else T_OFF, image_subsample=2)
- elif event == 'Do Something':
- show_animation = True
- window['-GIF-'].metadata = 0
- elif event == 'Upgrade':
- sg.popup('This is where you would do', 'the upgrade window code')
- elif event == 'Light' and not light_mode or event == 'Dark' and light_mode:
- light_mode = not light_mode
- window.close()
- window = make_window(light_mode)
- # Do the animation stuff
- if show_animation:
- window['-GIF-'].update_animation(LOADING_GIF, time_between_frames=100)
- window['-GIF-'].metadata += 1
- if window['-GIF-'].metadata > 50:
- show_animation = False
- window['-GIF-'].update(data='') # set to illegal value to erase the image
-
- window.close()
-
-if __name__ == '__main__':
- T_OFF = b'iVBORw0KGgoAAAANSUhEUgAAAFAAAAA8CAYAAADxJz2MAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAgmSURBVHhe7ZpdbFTHFcfPzBrb613bGLt4/VEC2AVaQ0RIkNIWJN7iB6TyUiXqawrJY0yEhJEiWYpa06oFqr600Ic8VGqlpGqkShWWeCCqpSIRJwURCGVDDP5a24vX66/1x+6dnv/cucv1F14M9l7T+5NW996ZK8v73zNzzpxzyMfHx8fHx8fH5/8SYa6r5u3T5xqlEMf402BlMhEpAhFLWBFBYrt5xRMoUt2KRDxAKpYRIiaV+kYJcfnSL1v+Y15ZFasS8N0zv9urlHpTWdZRkmK/Gd6oRFmETzMZ629/+vX718xYzjyVgLC2gJAf8u/5lhmigoIAbauNUOWWMgqVFFMoGORrkMKhoHnDG0xMpmgqNU2T/JmamqZ4Ikl9A0M0PTNr3iCySFwWQrU+jVXmJOCJ939TJYoKPrQs9XMhqCAgA7S7cRsLV0011ZUkeHAjwquIhuIJetg3SHe/eUizc3P2hFB/lpb44A9nW7rtgeVZ8ZsfP3N+v1DqH/xqPYRq3FFHr+3bQ8FgsXnjxWCGxbv5VZRu/7ebMlaGzVGN8h7500tnW66YV5bkiQIeP3PuLbbrSyxceGtVBf344MtUUV5qZl9MsNSvdd2ih/2DbKGUZps5dbG95YKZXsSyAp5oPf8eX87jvmF7PR06uI8CgQAeF1ESLKIt5SEqKS6iTbwn4gPSGYvm5tKUmpmjxNgEjU9O63Gvg6XddfMu3bwTNSN0gUVsMffzWFJAWJ5Q4i9seeqVvbvE/qbvmZnHcNhCtVsr6DvsPAo3FZjRJ5NOZ2g4MU59QyPEXs+Mepd793up8/oNLSjL2nqx/eRZe+Yxi0wKex4v27+zeIUH9u1eUrytLNquHbW0uSzEVinN6MpIKak0VEzVleWIy9gjzpgZb1JZUUZl4RJ60BtjEcWRg4feuN7V2ZE1SzBPQO1tA+IzFq8Ky/b1A01mxibAAjRuq9aWh/vVIqWg8tISFjNIyfEpYu9uZrzHls1l2gIHh0ck/5fHXjn0xsdfdnaMmGmapwJCFXhbOAzseW6wr/2goY73urAZeXbKwkFqaqynYFGhGfEmvBLppfoIwrVwgbD9gkNWQATJdpwntLd1OwxY2x5esnAWz5uiwk20Z2dt1vF4lR+9uhd7PduiOPru6fNHzPBjAXHCYO0KEOctDFV2fnfrmojnACe0a3uNpwNyxL1Nu3fqfzAjiVeqjRYQZ1scz3DCQJDsBg7jeS7b5QjzMbCO91Yv8/L3G7SQQtGh462/PYoxLSASA7jieOY+YSBUqY9Umqe1p4YF9PJSxrbWtMtOMvFq0ZrZAiKrwuBs6wbedj2/0Hr/YKthe32NvvJe2NzW1lYg4TyQkkJWBYkBNwiS15uqitJnCpHWmrLSkP7wMq7qmy4/wiGZOIYJpKTcmzicRq4njOcJrBDhjZd5qS6ir3xQ+wkEbMAD8nlucLbNF+vhtJ6FqsrN+mqRbJRIw+MByVA3SAzki5JibwfWIeNopWVF2AIDtoDB+csmn95wUx62jqcBGXdgSRmRKAC5Bx3yKqCHQxngrFZJKsLHetI/98JTgJdPBV5CWiRiuJmcSukBh7l0xtytP8gbeplUyk4MK0FxPrwpW0Az6IBMcr7I54+XC45WwrJiEkVmPKDU5wZp+HyRcpUavciko5WQMYkKPe5Hkkk95oAaRr5IjE2aO2/yKGFrxX4iKtHegIeeviE96IACUD72ImR/vS5gT9+gvvL/2iFNFT6KCv3gcDZTrYmPjpu79QPiebnghOX7aHQM4k3MFiUv61M7Byyf4trTP98KewfXt3oG6+sZeGSevMmD3gH7RonLH7W1TWsB0ViD69fRB7pC7wDx+ocT5mntGRoZo+nZ/DmvlcAPfPue6fYIKK2ZFtB0JV1BbwjaG9wMDI/S2MT8GHEtgOf1uvXdYfHGxnl/VtatusKxTzCWTbxxUHgKV/SGoL3BAapHH8ZoZg0tA5Z+rztGGcu7ex9W5o3bxriE/KCtrU0HylkBbWci/orGGvSGQDgHBLZ3vx2g2TUIriHe3e5+z8d+X9z4mlLTMzC0zovtLdpngKyAgGPCVnQlobEGvSFu8AVv3euhiQUB97OAv/lVtNfzPTN32DfgwzaVlkLN65GZl/b4vLNj9MDh5i6+/dlQfESGS0p0e4MDOgjiCQ5t2G2jirbahAOsGw4j+mCQZtP5OzLmQn8sTp/9+0vzRG9fbD/5T3OvWZQ3+qKz4/5rh5sRADb3DQyp0lBQoL3BDZzKMAuAOkqwuDBnISEc4jzsd4gx3duEF4F4V/51XVmWhS944dLZll/ZM49ZMvHW1dlx7dXDzZv5C/7QbqxRVFNdZWZtYI0QYzCe1Ms6qwWL6RSFcJKZmU3zEk3pcOh+75C2YLS9eR0sWVgexFMWfVJXnHzn6tWri/7xJ5rOidZzp5USumMBvSFob3jROlMXAm8LhwEBDRdqi5KnHK+7kBXX3junzzWz7B/zMg2jNwTtDajQL9dsuVHBKkOch1BFe1t2GDx8nJftR/YbS5PT5oXasRDy95JUM55hhXt379DlPdRINzI42+J4hhOGDpIZhCrwtn/8xcnP9cATyG33N6ArSZFoV0K9boaovCyshazcUq6rVaitLKzweQVkkpEM1QmBRFJnVZAYyMInDATJ7jhvJZ5KQAc01vCSfhPtDajQm+ENCS/dCSQGcLbF8Wy5vW45ViWgA3pD0N6ACr1dZLYiutRHyi7dewzUMJCGRyYZyVAWrwMpKWRVzCs+Pj4+Pj4+Pj4+OUD0P0U7YihhTsPyAAAAAElFTkSuQmCC'
- T_ON = b'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'
- PSG_GRAPHIC = b'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'
- LOADING_GIF = b'R0lGODlhoACgAPcAAAD/AGZ5j2d6j2d6kGh7kGh7kWl8kWp8kmp9kmt9k2t+k2x+k21/lG6AlW+BlnCBlnCClnGCl3GDl3KEmHOEmHOFmXSFmXSGmnWGmnaHmnaHm3eIm3eInHiJnHmJnXmKnXqKnXqLnnuLnnyMn32NoH6OoX+PoYCQooGRo4KRo4KSpIOSpIOTpYSTpYWUpYWUpoaVpoaVp4eWp4iWqIiXqImXqImYqYqZqYuZqouaqoyaq4ybq42brI6crI+drZCerpGerpGfr5Kfr5KgsJOgsJShsJShsZWisZWjspajspeks5ils5iltJmmtJqmtZqntZuntpuotpyot52pt56quJ+ruaCruaCsuqGtuqKuu6Ouu6OvvKSvvKSwvaWwvaaxvqeyvqeyv6izv6mzwKm0wKq0waq1wau1wqy2wq23w624w664xK+5xK+5xbC6xbG7xrK7xrK8x7O8x7O9yLS9yLW+yba/yba/yrfAyrjAy7jBy7nCzLrDzLvDzbvEzbzEzrzFzr3Fz77Gz77G0L/H0MDI0cHI0cHJ0sLJ0sTL1MTM1MXM1MXN1cbN1cfO1sjP18nQ18rQ2MrR2MvR2cvS2czS2s3T2s3T287U28/V3NDV3NDW3dHX3dHX3tLY3tPY39PZ39TZ39Ta4NXa4Nbb4dfc4tjd4tnd49ne49re5Nrf5Nvf5dzg5dzh5t3h5t3i5t7i59/j59/j6ODk6ODk6eHl6eLl6eLm6uPm6uPn6+Tn6+Xo7Obp7efq7ejr7uns7+rt8Ovt8Ovu8ezu8ezv8e3v8u7w8u7w8+/x8+/x9PDy9PHy9PHz9fLz9fL09vP09vT19/T29/X2+PX3+Pb3+Pf4+fj5+vn6+/r6+/r7+/v7/Pv8/Pz8/f39/f39/v7+/v7+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFBAAAACwAAAAAoACgAIcA/wBmeY9neo9nepBoe5Boe5FpfJFqfJJqfZJrfZNrfpNsfpNtf5RugJVvgZZwgZZwgpZxgpdxg5dyhJhzhJhzhZl0hZl0hpp1hpp2h5p2h5t3iJt3iJx4iZx5iZ15ip16ip16i557i558jJ99jaB+jqF/j6GAkKKBkaOCkaOCkqSDkqSDk6WEk6WFlKWFlKaGlaaGlaeHlqeIlqiIl6iJl6iJmKmKmamLmaqLmqqMmquMm6uNm6yOnKyPna2Qnq6Rnq6Rn6+Sn6+SoLCToLCUobCUobGVorGVo7KWo7KXpLOYpbOYpbSZprSaprWap7Wbp7abqLacqLedqbeeqrifq7mgq7mgrLqhrbqirrujrrujr7ykr7yksL2lsL2msb6nsr6nsr+os7+ps8CptMCqtMGqtcGrtcKstsKtt8OtuMOuuMSvucSvucWwusWxu8ayu8ayvMezvMezvci0vci1vsm2v8m2v8q3wMq4wMu4wcu5wsy6w8y7w827xM28xM68xc69xc++xs++xtC/x9DAyNHByNHBydLCydLEy9TEzNTFzNTFzdXGzdXHztbIz9fJ0NfK0NjK0djL0dnL0tnM0trN09rN09vO1NvP1dzQ1dzQ1t3R193R197S2N7T2N/T2d/U2d/U2uDV2uDW2+HX3OLY3eLZ3ePZ3uPa3uTa3+Tb3+Xc4OXc4ebd4ebd4ube4uff4+ff4+jg5Ojg5Onh5eni5eni5urj5urj5+vk5+vl6Ozm6e3n6u3o6+7p7O/q7fDr7fDr7vHs7vHs7/Ht7/Lu8PLu8PPv8fPv8fTw8vTx8vTx8/Xy8/Xy9Pbz9Pb09ff09vf19vj19/j29/j3+Pn4+fr5+vv6+vv6+/v7+/z7/Pz8/P39/f39/f7+/v7+/v////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8I/wCzheMWTiBBgwUHJjyoEKHDhhAZSlxI8eFEixUjZryoEaPHjiA5TgzXLdw3kiZRniy5MiVLlTBfynRJs6XNmDVx3py5MydPnUB/CvVZU+TGox+NJkUakqnSpkujQp1KtKfVoFWxXh26NStXrWC/ipX6tKzTs2SvBSiwYIKFFjuugBGk6Zi1qWbJom0a1qvfroD7RgsQYADhwocNHyhBRZAsbH/7BhZbdG9evJYzZ7MW4MDazp89FwA9ugEMPK40Y9b7MTLlya5jn3xmmHBtxLYTJ4Yw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'
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Smart_Desktop_Icon.pyw b/DemoPrograms/Demo_Smart_Desktop_Icon.pyw
deleted file mode 100644
index 90e1ea9c2..000000000
--- a/DemoPrograms/Demo_Smart_Desktop_Icon.pyw
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-
-Creates what appears to be an icon on your desktop, but is in reality a PySimpleGUI program.
-
-Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-"""
-
-
-
-import PySimpleGUI as sg
-import random
-
-def main():
-
- PROGRAM_TO_LAUNCH_WHEN_DOUBLE_CLICKED = 'explorer' # This will be run when icon is double-clicked. Change to any program you want.
-
- # Set to your own custom icon. This is dislayed on the desktop
- # For fun, the icon is changed every 5 minutes to a random PSG Emoji
- icon=sg.EMOJI_BASE64_COOL
-
- #------- GUI definition & setup --------#
-
- sg.theme('black')
-
-
- layout = [[sg.Image(source=icon, key='-IMAGE-', p=0, enable_events=True)]]
-
- window = sg.Window('Desktop Icon Demo', layout, element_justification='center', finalize=True, resizable=True, no_titlebar=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, margins=(0,0), grab_anywhere=True, auto_save_location=True)
-
- window['-IMAGE-'].bind('', '+DOUBLE_CLICK+')
-
- window.timer_start(5*60*1000) # every 5 minutes, change the icon (totally optional... just for fun)
-
- #------------ The Event Loop ------------#
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- # Add your double-click action here... such as launching another program
- if event == '-IMAGE-+DOUBLE_CLICK+':
- sg.popup_quick_message('Double Clicked', location=window.current_location(), font='_ 20', background_color='red', text_color='white')
- # Example of launch when the icon is double-clicked. Of course you can do some other action than launching a program
- sg.execute_command_subprocess(PROGRAM_TO_LAUNCH_WHEN_DOUBLE_CLICKED, wait=False)
- elif event == sg.TIMER_KEY: # Change the icon shown every TIMER event
- window['-IMAGE-'].update(random.choice(sg.EMOJI_BASE64_HAPPY_LIST))
- elif event == 'Version':
- sg.popup_scrolled(sg.get_versions(), f'This Program: {__file__}' ,keep_on_top=True, non_blocking=True, location=window.current_location())
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
-
- window.close()
-
-if __name__ == '__main__':
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Sort_Visualizer.py b/DemoPrograms/Demo_Sort_Visualizer.py
index 557082a00..f208dda18 100644
--- a/DemoPrograms/Demo_Sort_Visualizer.py
+++ b/DemoPrograms/Demo_Sort_Visualizer.py
@@ -1,11 +1,5 @@
import PySimpleGUI as sg
import random
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
# ------- Sort visualizer. Displays bar chart representing list items -------
BAR_SPACING, BAR_WIDTH, EDGE_OFFSET = 11, 10, 3
DATA_SIZE = GRAPH_SIZE = (700, 500) # width, height of the graph portion
@@ -36,7 +30,7 @@ def draw_bars(graph, items):
def main():
- sg.theme('LightGreen')
+ sg.change_look_and_feel('LightGreen')
# Make list to sort
num_bars = DATA_SIZE[0]//(BAR_WIDTH+1)
list_to_sort = [DATA_SIZE[1]//num_bars*i for i in range(1, num_bars)]
@@ -56,7 +50,7 @@ def main():
timeout = 10 # start with 10ms delays between draws
while True: # ----- The event loop -----
event, values = window.read(timeout=timeout)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
try:
partially_sorted_list = bsort.__next__()
diff --git a/DemoPrograms/Demo_Spin_Element_Wraps_Around.py b/DemoPrograms/Demo_Spin_Element_Wraps_Around.py
deleted file mode 100644
index a7d255d62..000000000
--- a/DemoPrograms/Demo_Spin_Element_Wraps_Around.py
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-
-"""
-
- Demo Spin Element - Wraps around
-
- This is a nice touch for the Spin Element that is yet another jason990420 creation
-
- This Spin element will wrap around going in either direction. When getting to the end then
- it will go back to the beginning.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-lower, upper = 0, 10
-data = [i for i in range(lower - 1, upper + 2)]
-
-layout = [[sg.Text('This Spin element wraps around in both directions')],
- [sg.Spin(data, initial_value=lower, readonly=True, size=3, enable_events=True, key='-SPIN-')]]
-
-window = sg.Window('Wrapping Spin Element', layout, font='_ 18', keep_on_top=True)
-
-while True:
-
- event, values = window.read()
-
- if event == sg.WIN_CLOSED:
- break
-
- # code to make the Spin do the wrap around. Do this prior to using the Spin's value in your code
- if event == '-SPIN-':
- value = values['-SPIN-']
- if value == lower - 1:
- window['-SPIN-'].update(value=upper)
- values['-SPIN-'] = upper # Change the values dictionary too so it'll be correct if used
- elif value == upper + 1:
- window['-SPIN-'].update(value=lower)
- values['-SPIN-'] = lower # Change the values dictionary too so it'll be correct if used
-
- sg.Print('Spin Value:', values['-SPIN-'], relative_location=(-400, 0))
-
-window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Spinner_Compound_Element.py b/DemoPrograms/Demo_Spinner_Compound_Element.py
index 5cb9e9675..d9c0171e9 100644
--- a/DemoPrograms/Demo_Spinner_Compound_Element.py
+++ b/DemoPrograms/Demo_Spinner_Compound_Element.py
@@ -3,33 +3,36 @@
"""
Demo of how to combine elements into your own custom element
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
sg.set_options(element_padding=(0, 0))
-# --- Define the Compound Element. Has 2 buttons and an input field --- #
-NewSpinner = [sg.Input('0', size=(3, 1), font='Any 12', justification='r', key='-SPIN-'),
- sg.Column([[sg.Button('▲', size=(1, 1), font='Any 7', border_width=0, button_color=(sg.theme_text_color(), sg.theme_background_color()), key='-UP-')],
- [sg.Button('▼', size=(1, 1), font='Any 7', border_width=0, button_color=(sg.theme_text_color(), sg.theme_background_color()), key='-DOWN-')]])]
+# sg.change_look_and_feel('Dark')
+# --- Define our "Big-Button-Spinner" compound element. Has 2 buttons and an input field --- #
+NewSpinner = [sg.Button('-', size=(2, 1), font='Any 12'),
+ sg.Input('0', size=(2, 1), font='Any 14',
+ justification='r', key='spin'),
+ sg.Button('+', size=(2, 1), font='Any 12')]
# --- Define Window --- #
-layout = [[sg.Text('Spinner simulation')],
- NewSpinner,
- [sg.Text('')],
- [sg.Ok()]]
+layout = [
+ [sg.Text('Spinner simulation')],
+ NewSpinner,
+ [sg.Text('')],
+ [sg.Ok()]
+]
+
+window = sg.Window('Spinner simulation', layout)
-window = sg.Window('Spinner simulation', layout, use_default_focus=False)
# --- Event Loop --- #
+counter = 0
while True:
event, values = window.read()
- if event == 'Ok' or event == sg.WIN_CLOSED: # be nice to your user, always have an exit from your form
+ if event == 'Ok' or event is None: # be nice to your user, always have an exit from your form
break
- counter = int(values['-SPIN-'])
+
# --- do spinner stuff --- #
- counter += 1 if event == '-UP-' else -1 if event == '-DOWN-' else 0
- window['-SPIN-'].update(counter)
+ counter += 1 if event == '+' else -1 if event == '-' else 0
+ window['spin'].update(counter)
+
window.close()
diff --git a/DemoPrograms/Demo_Status_Bar.py b/DemoPrograms/Demo_Status_Bar.py
deleted file mode 100644
index a581db683..000000000
--- a/DemoPrograms/Demo_Status_Bar.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Status Bar
-
- This demo shows you how to create your statusbar in a way that will keep it at the bottom of
- a resizeable window. The key is the correct setting of the Expand settings for both the
- StatusBar (done for you) and for a line above it that will keep it pushed to the bottom of the window.
- It's possible to also "simulate" a statusbar (i.e. use a text element or something else) by also
- configuring that element with the correct expand setting (X direction = True, expand row=True)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
-
- layout = [ [sg.Text('StatusBar Demo', font='ANY 15')],
- [sg.Text('This window has a status bar that is at the bottom of the window')],
- [sg.Text('The key to getting your bar to stay at the bottom of the window when')],
- [sg.Text('the window is resizeed is to insert a line of text (or some other element)')],
- [sg.Text('that is configured to expand. ')],
- [sg.Text('This is accomplished by calling the "expand" method')],
- [sg.Text('')],
- [sg.Button('Ok'), sg.B('Quit')],
- [sg.Text(key='-EXPAND-', font='ANY 1', pad=(0,0))], # thin row (font size 1) that expands and keeps bar at the bottom
- [sg.StatusBar('This is the statusbar')]]
-
-
- window = sg.Window('Vertical Layout Example', layout, resizable=True, finalize=True)
-
- window['-EXPAND-'].expand(True, True, True) # needed to make the window expand in a way that will cause status to be at the bottom
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Quit'): # if user closes window or clicks Quit
- break
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_Stdout.py b/DemoPrograms/Demo_Stdout.py
index ac76e07dc..3f5847bb5 100644
--- a/DemoPrograms/Demo_Stdout.py
+++ b/DemoPrograms/Demo_Stdout.py
@@ -8,10 +8,6 @@
Use the Output Element in your window layout to reroute stdout
You will see the output of the print in the Output Element in the center of the window
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
"""
@@ -26,7 +22,7 @@
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
print('You typed: ', values[0])
window.close()
diff --git a/DemoPrograms/Demo_Sudoku.py b/DemoPrograms/Demo_Sudoku.py
deleted file mode 100644
index a327bc388..000000000
--- a/DemoPrograms/Demo_Sudoku.py
+++ /dev/null
@@ -1,158 +0,0 @@
-import PySimpleGUI as sg, random
-import numpy as np
-from typing import List, Any, Union, Tuple, Dict
-
-
-"""
- Sudoku Puzzle Demo
-
- How to easily generate a GUI for a Sudoku puzzle.
- The Window definition and creation is a single line of code.
-
- Code to generate a playable puzzle was supplied from:
- https://github.com/MorvanZhou/sudoku
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-
-def generate_sudoku(mask_rate):
- """
- Create a Sukoku board
-
- :param mask_rate: % of squares to hide
- :type mask_rate: float
- :rtype: List[numpy.ndarry, numpy.ndarry]
- """
- while True:
- n = 9
- solution = np.zeros((n, n), np.int)
- rg = np.arange(1, n + 1)
- solution[0, :] = np.random.choice(rg, n, replace=False)
- try:
- for r in range(1, n):
- for c in range(n):
- col_rest = np.setdiff1d(rg, solution[:r, c])
- row_rest = np.setdiff1d(rg, solution[r, :c])
- avb1 = np.intersect1d(col_rest, row_rest)
- sub_r, sub_c = r//3, c//3
- avb2 = np.setdiff1d(np.arange(0, n+1), solution[sub_r*3:(sub_r+1)*3, sub_c*3:(sub_c+1)*3].ravel())
- avb = np.intersect1d(avb1, avb2)
- solution[r, c] = np.random.choice(avb, size=1)
- break
- except ValueError:
- pass
- puzzle = solution.copy()
- puzzle[np.random.choice([True, False], size=solution.shape, p=[mask_rate, 1 - mask_rate])] = 0
- return puzzle, solution
-
-
-
-def check_progress(window, solution):
- """
- Gives you a visual hint on your progress.
- Red - You've got an incorrect number at the location
- Yellow - You're missing an anwer for that location
-
- :param window: The GUI's Window
- :type window: sg.Window
- :param solution: A 2D array containing the solution
- :type solution: numpy.ndarray
- :return: True if the puzzle has been solved correctly
- :rtype: bool
- """
- solved = True
- for r, row in enumerate(solution):
- for c, col in enumerate(row):
- value = window[r,c].get()
- if value:
- try:
- value = int(value)
- except:
- value = 0
- if value != solution[r][c]:
- window[r,c].update(background_color='red')
- solved = False
- else:
- window[r,c].update(background_color=sg.theme_input_background_color())
- else:
- solved = False
- window[r, c].update(background_color='yellow')
- return solved
-
-
-def create_and_show_puzzle(window):
- # create and display a puzzle by updating the Input elements
- rate = DEFAULT_MASK_RATE
- if window['-RATE-'].get():
- try:
- rate = float(window['-RATE-'].get())
- except:
- pass
- puzzle, solution = generate_sudoku(mask_rate=rate)
- for r, row in enumerate(puzzle):
- for c, col in enumerate(row):
- window[r, c].update(puzzle[r][c] if puzzle[r][c] else '', background_color=sg.theme_input_background_color())
- return puzzle, solution
-
-
-def main(mask_rate=0.7):
- """"
- The Main GUI - It does it all.
-
- The "Board" is a grid that's 9 x 9. Even though the layout is a grid of 9 Frames, the
- addressing of the individual squares is via a key that's a tuple (0,0) to (8,8)
- """
-
-
-
-
- # It's 1 line of code to make a Sudoku board. If you don't like it, then replace it.
- # Dude (Dudette), it's 1-line of code. If you don't like the board, write a line of code.
- # The keys for the inputs are tuples (0-8, 0-8) that reference each Input Element.
- # Get an input element for a position using: window[row, col]
- # To get a better understanding, take it apart. Spread it out. You'll learn in the process.
- window = sg.Window('Sudoku',
- [[sg.Frame('', [[sg.I(random.randint(1,9), justification='r', size=(3,1),enable_events=True, key=(fr*3+r,fc*3+c)) for c in range(3)] for r in range(3)]) for fc in range(3)] for fr in range(3)] +
- [[sg.B('Solve'), sg.B('Check'), sg.B('Hint'), sg.B('New Game'), sg.T('Mask rate (0-1)'), sg.In(str(mask_rate), size=(3,1),key='-RATE-')],], finalize=True)
-
- # create and display a puzzle by updating the Input elements
-
- puzzle, solution = create_and_show_puzzle(window)
- check_showing = False
- while True: # The Event Loop
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
-
- if event == 'Solve':
- for r, row in enumerate(solution):
- for c, col in enumerate(row):
- window[r, c].update(solution[r][c], background_color=sg.theme_input_background_color())
- elif event == 'Check':
- check_showing = True
- solved = check_progress(window, solution)
- if solved:
- sg.popup('Solved! You have solved the puzzle correctly.')
- elif event == 'Hint':
- elem = window.find_element_with_focus()
- try:
- elem.update(solution[elem.Key[0]][elem.Key[1]], background_color=sg.theme_input_background_color())
- except:
- pass # Likely because an input element didn't have focus
- elif event == 'New Game':
- puzzle, solution = create_and_show_puzzle(window)
- elif check_showing: # an input was changed, so clear any background colors from prior hints
- check_showing = False
- for r, row in enumerate(solution):
- for c, col in enumerate(row):
- window[r, c].update(background_color=sg.theme_input_background_color())
- window.close()
-
-if __name__ == "__main__":
- DEFAULT_MASK_RATE = 0.7 # % Of cells to hide
- main(DEFAULT_MASK_RATE)
-
diff --git a/DemoPrograms/Demo_Sudoku_1_Line.py b/DemoPrograms/Demo_Sudoku_1_Line.py
deleted file mode 100644
index 2493a4f34..000000000
--- a/DemoPrograms/Demo_Sudoku_1_Line.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo 1-line Sudoku Board
-
- A silly display of what 1 line of PySimpleGUI is capable of producing by
- utilizing the power of Python. The power isn't a PySimpleGUI trick.
- The power is Python List Comprehensions and using them in your layout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.Window('Sudoku', [[sg.Frame('', [[sg.Input(justification='r', size=(3,1))
- for col in range(3)]
- for row in range(3)])
- for frame_col in range(3)]
- for frame_row in range(3)],
- use_custom_titlebar=True).read()
diff --git a/DemoPrograms/Demo_Super_Simple_Form.py b/DemoPrograms/Demo_Super_Simple_Form.py
index 18c4509dd..34c493ea9 100644
--- a/DemoPrograms/Demo_Super_Simple_Form.py
+++ b/DemoPrograms/Demo_Super_Simple_Form.py
@@ -1,13 +1,6 @@
import PySimpleGUI as sg
-"""
- Simple Form (a one-shot data entry window)
- Use this design pattern to show a form one time to a user that is "submitted"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
+# Basic Example
layout = [[sg.Text('Please enter your Name, Address, Phone')],
[sg.Text('Name', size=(10, 1)), sg.InputText(key='-NAME-')],
@@ -16,9 +9,7 @@
[sg.Button('Submit'), sg.Button('Cancel')]]
window = sg.Window('Simple Data Entry Window', layout)
-event, values = window.read(close=True)
+event, values = window.read()
+print(event, values['-NAME-'], values['-ADDRESS-'], values['-PHONE-'])
-if event == 'Submit':
- print('The events was ', event, 'You input', values['-NAME-'], values['-ADDRESS-'], values['-PHONE-'])
-else:
- print('User cancelled')
+window.close()
diff --git a/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py b/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py
deleted file mode 100644
index 69c265f90..000000000
--- a/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py
+++ /dev/null
@@ -1,87 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIWx as sg
-# import PySimpleGUIQt as sg
-import time
-
-"""
- Design pattern - System Tray and GUI Window
-
- This design pattern will show you how to run a system tray icon and a GUI window
- simultaneously. BOTH the system tray and the window will be active at the same time.
-
- The "close window" action is similar to what most windows programs do that have a tray icon.
- When you close the window with an "X", it closes the GUI window and shows a message in the
- tray that the window has been "Minimized".
-
- To make things "easier", a new window is created each time rather than trying to hide and unhide.
- On some systems, the hide method doesn't work very well (Raspberry Pi for example).
-
- You can "Minimize" to the tray in 3 ways in this program:
- 1. Click the "X" on the window
- 2. Click the button "Minimize to tray"
- 3. Right click tray icon and choose "Hide"
-
- To exit the entire program, you will need to do this from the System tray by choosing "Exit"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-icon = sg.DEFAULT_BASE64_ICON
-
-sg.theme('Dark Red')
-delay_time = 15 * 60
-
-def time_as_int():
- return int(round(time.time()))
-
-def make_a_window():
-
- layout = [ [sg.Text(f'{delay_time // 60 % 60:2}:{delay_time % 60:02}', key='-OUT-', size=(20, 2), justification='c', font='Any 24')],
- [sg.Button('Start', size=(10,1))],[sg.Button('Minimize\nTo Tray', size=(10,2))] ]
-
- return sg.Window('Window Title', layout, element_justification='c', icon=icon)
-
-def main():
-
- menu_def = ['UNUSED', ['Show','Hide','Exit']]
-
- tray = sg.SystemTray(menu=menu_def, data_base64=icon)
- window = make_a_window()
- start, current, paused = time_as_int(), 0, True
-
- while True:
- event = tray.read(timeout=100)
- if event == 'Exit':
- break
- elif event in('Show', sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED) and not window:
- print('Showing a new window')
- window, paused = make_a_window(), True
- elif event == 'Hide' and window:
- window.close()
- window = None
-
- if window:
- event, values = window.read(timeout=1000)
- if event in (sg.WIN_CLOSED, 'Minimize\nTo Tray'):
- print('Minimizing to tray')
- tray.show_message('Minimizing', 'Minimizing to Tray')
- window.close()
- window = None
- continue
- elif event == 'Start':
- start, paused = time_as_int(), False
- if not paused:
- remaining = delay_time - (time_as_int() - start)
- if remaining < 0:
- tray.show_message('Look away', 'It is time to look away for 20 seconds')
- start = time_as_int()
- else:
- window['-OUT-'].update(f'{remaining//60%60:2}:{remaining%60:02}')
- tray.close()
- if window:
- window.close()
-
-
-main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_System_Tray_Icon.py b/DemoPrograms/Demo_System_Tray_Icon.py
deleted file mode 100644
index 08d50a8b6..000000000
--- a/DemoPrograms/Demo_System_Tray_Icon.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIWx as sg
-# import PySimpleGUIQt as sg
-
-"""
- System Tray Icon
- Your very own peronsal status monitor in your system tray
- Super easy to use.
- 1. Find an icon file or use this default
- 2. Create your menu defintion
- 3. Add if statements to take action based on your input
-
- Note from the imports that this code works on all PySimpleGUI ports (except Web).
- For the tkinter port, however, the icon isn't located in the system tray. Instead it's located just above
- the system tray in the form of what looks like an "icon" on your desktop. It's actually a very small window.
-
- In June 2021 a new package was added to the PySimpleGUI family - psgtray
- With this package, you can get a real system tray icon while using tkinter rather than a desktop-icon that this
- demo is demonstrating. The Demo Program - Demo_psgtray_Tray_Icon_Tkinter - shows how to integrate it with PySimpleGUI
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-
-menu_def = ['UNUSED', ['My', '&Simple::my key', 'Has Sub', ['1','2'], '---', 'Menu', 'E&xit']]
-
-tray = sg.SystemTray(menu=menu_def, data_base64=sg.DEFAULT_BASE64_ICON)
-
-while True:
- event = tray.read()
- print(event)
- if event == 'Exit':
- break
- elif event == 'Menu':
- tray.show_message('Title', 'Hey, you clicked Menu!')
-tray.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py b/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py
deleted file mode 100644
index 5e0757590..000000000
--- a/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import PySimpleGUI as sg
-from psgtray import SystemTray
-
-
-"""
- A System Tray Icon courtesy of pystray and your friends at PySimpleGUI
-
- Import the SystemTray object with this line of code:
- from psgtray import SystemTray
-
- Key for the system tray icon is:
- tray = SystemTray()
- tray.key
-
- values[key] contains the menu item chosen.
-
- One trick employed here is to change the window's event to be the event from the System Tray.
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
-
- menu = ['', ['Show Window', 'Hide Window', '---', '!Disabled Item', 'Change Icon', ['Happy', 'Sad', 'Plain'], 'Exit']]
- tooltip = 'Tooltip'
-
- layout = [[sg.Text('My PySimpleGUI Celebration Window - X will minimize to tray')],
- [sg.T('Double clip icon to restore or right click and choose Show Window')],
- [sg.T('Icon Tooltip:'), sg.Input(tooltip, key='-IN-', s=(20,1)), sg.B('Change Tooltip')],
- [sg.Multiline(size=(60,10), reroute_stdout=False, reroute_cprint=True, write_only=True, key='-OUT-')],
- [sg.Button('Go'), sg.B('Hide Icon'), sg.B('Show Icon'), sg.B('Hide Window'), sg.Button('Exit')]]
-
- window = sg.Window('Window Title', layout, finalize=True, enable_close_attempted_event=True)
-
-
- tray = SystemTray(menu, single_click_events=False, window=window, tooltip=tooltip, icon=sg.DEFAULT_BASE64_ICON)
- tray.show_message('System Tray', 'System Tray Icon Started!')
- sg.cprint(sg.get_versions())
- while True:
- event, values = window.read()
-
- # IMPORTANT step. It's not required, but convenient. Set event to value from tray
- # if it's a tray event, change the event variable to be whatever the tray sent
- if event == tray.key:
- sg.cprint(f'System Tray Event = ', values[event], c='white on red')
- event = values[event] # use the System Tray's event as if was from the window
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- sg.cprint(event, values)
- tray.show_message(title=event, message=values)
-
- if event in ('Show Window', sg.EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED):
- window.un_hide()
- window.bring_to_front()
- elif event in ('Hide Window', sg.WIN_CLOSE_ATTEMPTED_EVENT):
- window.hide()
- tray.show_icon() # if hiding window, better make sure the icon is visible
- # tray.notify('System Tray Item Chosen', f'You chose {event}')
- elif event == 'Happy':
- tray.change_icon(sg.EMOJI_BASE64_HAPPY_JOY)
- elif event == 'Sad':
- tray.change_icon(sg.EMOJI_BASE64_FRUSTRATED)
- elif event == 'Plain':
- tray.change_icon(sg.DEFAULT_BASE64_ICON)
- elif event == 'Hide Icon':
- tray.hide_icon()
- elif event == 'Show Icon':
- tray.show_icon()
- elif event == 'Change Tooltip':
- tray.set_tooltip(values['-IN-'])
-
- tray.close() # optional but without a close, the icon may "linger" until moused over
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py b/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py
deleted file mode 100644
index b02a9bf96..000000000
--- a/DemoPrograms/Demo_System_Tray_Icon_psgtray_No_Window.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import PySimpleGUI as sg
-from psgtray import SystemTray
-
-"""
- A System Tray Icon using pystray - No visible window version
-
- Import the SystemTray object with this line of code:
- from psgtray import SystemTray
-
- Key for the system tray icon is:
- tray = SystemTray()
- tray.key
-
- values[key] contains the menu item chosen.
-
- One trick employed here is to change the window's event to be the event from the System Tray.
-
- This demo program keeps the Window hidden all the time so that it's a pure "System Tray" application.
- Because the PySimpleGUI architecture implemented the tray icon using the psgtray package combined with the
- overall window event loop, a Window object is still required. The point of this demo is to show that this
- window does not need to ever appear to the user.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def main():
- menu = ['', ['---', '!Disabled Item', 'Change Icon', ['Happy', 'Sad', 'Plain'], 'Exit']]
- tooltip = 'Tooltip'
-
- layout = [[sg.T('Empty Window', key='-T-')]]
-
- window = sg.Window('Window Title', layout, finalize=True, enable_close_attempted_event=True, alpha_channel=0)
- window.hide()
-
- tray = SystemTray(menu, single_click_events=False, window=window, tooltip=tooltip, icon=sg.DEFAULT_BASE64_ICON, key='-TRAY-')
- tray.show_message('System Tray', 'System Tray Icon Started!')
- print(sg.get_versions())
- while True:
- event, values = window.read()
- # IMPORTANT step. It's not required, but convenient. Set event to value from tray
- # if it's a tray event, change the event variable to be whatever the tray sent
- if event == tray.key:
- event = values[event] # use the System Tray's event as if was from the window
-
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- tray.show_message(title=event, message=values)
-
- if event == 'Happy':
- tray.change_icon(sg.EMOJI_BASE64_HAPPY_JOY)
- elif event == 'Sad':
- tray.change_icon(sg.EMOJI_BASE64_FRUSTRATED)
- elif event == 'Plain':
- tray.change_icon(sg.DEFAULT_BASE64_ICON)
- elif event == 'Hide Icon':
- tray.hide_icon()
- elif event == 'Show Icon':
- tray.show_icon()
- elif event == 'Change Tooltip':
- tray.set_tooltip(values['-IN-'])
-
- tray.close() # optional but without a close, the icon may "linger" until moused over
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_System_Tray_Reminder.py b/DemoPrograms/Demo_System_Tray_Reminder.py
deleted file mode 100644
index 777d68a17..000000000
--- a/DemoPrograms/Demo_System_Tray_Reminder.py
+++ /dev/null
@@ -1,86 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIWx as sg
-# import PySimpleGUIQt as sg
-from PIL import Image
-import base64, io
-from time import time
-
-"""
- A periodic reminder that uses the System Tray.
- Will show a popup window every X minutes
- Should work with 3 of the PySimpleGUI ports - tkinter, WxPython, Qt
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-ONE_HOUR_IN_SECONDS = 60*60
-STARTING_FREQUENCY = ONE_HOUR_IN_SECONDS
-POPUP_FONT = 'Helvetica 16' # font to use in popup
-POPUP_TEXT_COLOR, POPUP_BACKGROUND_COLOR = 'white', 'red'
-
-def resize_base64_image(image64, size):
- """
- Resize a base64 image. Good to use for Image elements, Button Images, etc.
-
- :param image64: The Base64 image
- :type image64: bytes
- :param size: Size to make the image in pixels (width, height)
- :type size: Tuple[int, int]
- :return: A new Base64 image
- :rtype: bytes
- """
- image_file = io.BytesIO(base64.b64decode(image64))
- img = Image.open(image_file)
- img.thumbnail(size, Image.LANCZOS)
- bio = io.BytesIO()
- img.save(bio, format='PNG')
- imgbytes = bio.getvalue()
- return imgbytes
-
-
-def main():
- """
- Function with all the good stuff. Creates the System Tray and processes all events
- """
- delay = frequency_in_seconds = STARTING_FREQUENCY
-
- tray_icon = resize_base64_image(icon, (64,64)) if sg.port == 'PySimpleGUI' else icon
-
- menu_def = ['UNUSED', ['Change Frequency', '---', 'Exit']]
-
- tray = sg.SystemTray(menu=menu_def, data_base64=tray_icon, tooltip=f'Reminder every {frequency_in_seconds/60} minutes')
-
- starting_seconds = time()
-
- while True:
- event = tray.read(timeout=delay*1000)
- if event == 'Exit':
- break
-
- delta_from_last = time() - starting_seconds
- if delta_from_last >= frequency_in_seconds:
- starting_seconds = time()
- delta_from_last = 0
- sg.popup_no_wait('Reminder!', f'It has been {frequency_in_seconds/60} minutes since your last reminder', background_color=POPUP_BACKGROUND_COLOR, text_color=POPUP_TEXT_COLOR, font=POPUP_FONT)
-
- if event == 'Change Frequency': # Change how often a reminder should be shown
- freq = sg.popup_get_text(f'Currently you will be reminded every {frequency_in_seconds/60} minutes\n'+
- 'Enter new frequency in minutes', 'Change Timer Frequency')
- try:
- frequency_in_seconds = int(float(freq)*60)
- starting_seconds = time()
- delta_from_last = 0
- tray.update(tooltip=f'Reminder every {frequency_in_seconds/60} minutes')
- except:
- sg.popup_error(f'Invalid value: {freq}', f'Keeping old frequency of {frequency_in_seconds/60} minutes')
-
- delay = frequency_in_seconds - delta_from_last
- tray.close()
-
-if __name__ == '__main__':
- icon = \
- b'iVBORw0KGgoAAAANSUhEUgAAAyAAAAOdCAMAAABK+vbxAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAF4FBV4KCl4PEF0TE10XGFwaG14kJV4rK14zM147O2AUFGAXGGAaGXwEBHsHCHsLDHsPEHwSEn0WGGAsLGAvMWA9PXAjInsiI3s8PUxMTFJSUllZWW5dXH1AQmJiYm1tbXhubnNzc3h4eIAAAIATE4A6PNkAAO4bHfYOD/oGBv4AAPwGBvoHCPwGCPoIB/oICfkLDPgMC/kMDfwJCfkPEPcSFPYVFvMXGvYWGPcYF/IYG/EaHPEcHvYYGvYaHPYcHvgQEfkSFPgUFfwQEfgXGPgZGfgaHPgcHf0bHe8dIPIdIPkdIPUhH+8hJO4mKe8pLO4xL+E9PesxMu8wM+4yNe42Oe44Ou87PO48PvEgIvAhJPEkJfUhIvUiJPUlJvIlKPQrLPghIfoiJPknJ/8mJvwlKPkpKvIuMPExMvAyNfI1NfUxMvUyNPU1NvM2OPE4OvA5PfA8PvU4OvU6PfU8PfoyM/w4Nvo6PPQ+QPg7QPhAP+9KR+9KTO9SVO9YWvJAQvJBRPFERvVBQvVCRPRGQ/VFRvRFSPJIRfFJSvNJTPFNT/ZJSvVKTfdMSPVNT/pDRPhFSPlJR/lKTPZMUfpOU/pUT/FRUvFTVfBVV/ZQUfZSVfRVVfRWWPNaW/FaXPJdXvVYWfVZXPRcXvtTVPtVWftbW/RdYPtfYfthXfNiZPRmaPNqa/1jZPxmafxoZf1rbPJvcP1tcfxwbfRyc/Z2ePN5efR5evZ7fPZ8ffxzdP92e/15dv18e/d/gP2CfYCAgMSFhNOfndqdn+edne6RkeicnPOBgvaBgvaGhvOLi/iBgviChPiFhf6Fgf+EhfqHiP6JhPmLjPmRkvqTlfmUlf+RlPqZmfudnvyZmvyenuWiouihovaurvujo/yioviqqvWzs/K+vsfHx8bKy8zFxMrKx8jIyMnNyczIyM3NzdDQ0NbW1tfY19nZ2d3d3eDf3vHCwvDLy/DR0fDc3ODg4OXl5enp6ezs7PLg4PHx8f///wAAAAAAAAAAAAAAALul9qwAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAA7+UlEQVR4Xu3df5xld33X8bXF0qLGGBHb2a2zzlYXMyFOXDClhGwghU0zSFELWCLJLnRkUxK2NAGJvwoEE2PBogFRCg/5sVnpJsEtBBNSYqaKERYXYTHdsCmd1uhjdIl3JSGbbeaP6znnfmbm/jj3ez7fz/f39/t+/tEm4f4857zm+z3n3Hvulj4ATIVAABQQCIACAgFQQCAACggEQAGBACggEAAFBAKggEAAFBAIgAICGfLd1cdWV0+v1U6v1v9M/92v/0L/H2KAQBqnqIsWp1dP0Y28uPfl8yfoHyECCKS/eoZSUHjKUyS3nT8/P38p/QtEoPRAelQAw+N0F3d+daHKo7JC/w7hFR3I47Tpcz3zXbqjE596wSCP+fmfo/8C4RUcyDO02Wt5mu5s3cMvpjoqC/TfILxSA5m6T97NxVTrxG5qY+A2+s8QXJmBMHbLVU7Tw9jy7T0UxjoMIdEoMRDDPGo2E1m5jLIY8mn63yC08gKxkEetRw9nauWN1MSIXfS/QmilBaJxWLeLlX2Rt1IR4x6h/x0CKywQ0ZGrac7Sg8p9hE58TLqabgGBFRWIpdnVJrNdkWPj++bD6DYQWEmB0FZtFT20wLeGTny0+ATdDMIqJxDrw8eAcE+k7dDViFvohhBWMYGcpQ3aOtHhrBspg+neTLeEsEoJhLZmF/T31U+8gipQuZFuDEGVEYjupxI10bMwrYx+rGSq99PtIaQiArF48qOdzo7IdbT9d6M7QEglBGLwwUQu9o7IiUtp62fAycIIFBCIs93zYcxCXkXbPsvr6U4QUP6BWD15Ph3nnGH3sasRF9PdIKDsA6Ht173OMeQTF9GGz/ZFuieEk3sgtPX6cIaecgr+zvmG6+muEE7mgTxNG68X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'
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_TTK_Scrollbars.py b/DemoPrograms/Demo_TTK_Scrollbars.py
deleted file mode 100644
index 229144781..000000000
--- a/DemoPrograms/Demo_TTK_Scrollbars.py
+++ /dev/null
@@ -1,112 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - TTK Scrollbars
-
- Beginning in release 4.60.0 (May 2022), all scrollbars in the tkinter port use TTK Scrollbars
-
- This feature impacts all elements that have scrollbars including:
- Multiline
- Output
- Listbox
- Table
- Tree
- Column
-
- Not all elements in PySimpleGUI use TTK Widgets. Some of the Widgets are TK Widgets. Regardless of the
- underlying widget, if it has a scrollbar that's visible normally (one of the above elements... unlike the Combo),
- then it will use a TTK scrollbar.
-
- There are many options available to you to set for these scrollbars.
-
- TTK Theme
-
- While the TTK Theme has been available for you to set, most users have likely not experimented much with this feature.
- This may change with these new scrollbars because the TTK Theme will impact how the scrollbars look. Be aware that
- the TTK Theme will also impact elements that use TTK Widgets.
-
- You can see what tkinter widgets are used for all of the elements in the documenation located here:
- https://pysimplegui.readthedocs.io/en/latest/#table-of-elements-in-tkinter-port
-
- Hierarchy of settings
-
- The scrollbar settings used for an element are picked up from one of these 4 locations. The priority order for
- the settings is:
- 1. The Element's parms in the layout (you can change individual element's scrollbars)
- 2. Window parms
- 3. set_options parms
- 4. The Global Settings (changable by calling sg.main())
-
- The TTK Theme follows a similar hierarchy. The order of priority to determine the theme is:
- 1. Window parm
- 2. set_options parm
- 3. The Global Settings
-
- More detailed information is available in the documenation about these scrollbars. The docstrings also tell you about
- each parm. The parm names are identical for the elements, the Window and the set_options call
- sbar_trough_color:
- Scrollbar color of the trough
- sbar_background_color:
- Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- sbar_arrow_color:
- Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- sbar_width:
- Scrollbar width in pixels
- sbar_arrow_width:
- Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- sbar_frame_color:
- Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- sbar_relief:
- Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
-
- Note that some parms can impact others. For example, setting the relief to Ridge negates the frame color setting
-
- This Demo shows 2 different windows to demonstrate the parms in the Window object and set_options.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# Our first window uses your global defaults with the Listbox element directly overriding the settings
-
-layout = [[sg.T('Fun with TTK Scrollbars')],
- [sg.Multiline('\n'.join([str(x) for x in range(50)]), size=(40,20), expand_x=True, expand_y=True),
- sg.Listbox(list(range(40)), s=(10,15),
- sbar_background_color='green', sbar_trough_color='red', sbar_relief='ridge', sbar_arrow_color='purple', sbar_frame_color='yellow',)],
- [sg.Button('Exit'), sg.Sizegrip()]]
-
-
-window = sg.Window('TTK Scrollbars 1', layout, resizable=True)
-
-while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
-
-# Our second window uses both set_options and the Window object to change the scrollbars
-
-
-sg.set_options(sbar_width=30, sbar_arrow_width=30)
-
-layout = [[sg.T('Fun with TTK Scrollbars 2')],
- [sg.Multiline('\n'.join([str(x) for x in range(50)]), size=(40,20), expand_x=True, expand_y=True),
- sg.Listbox(list(range(40)), s=(10,15),
- sbar_background_color='green', sbar_trough_color='red', sbar_arrow_color='purple', sbar_frame_color='yellow',)],
- [sg.Button('Exit'), sg.Sizegrip()]]
-
-
-window = sg.Window('TTK Scrollbars 2', layout, sbar_relief=sg.RELIEF_SOLID, resizable=True)
-
-while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
-
diff --git a/DemoPrograms/Demo_Table_CSV.py b/DemoPrograms/Demo_Table_CSV.py
index db36a18bc..336dda3f3 100644
--- a/DemoPrograms/Demo_Table_CSV.py
+++ b/DemoPrograms/Demo_Table_CSV.py
@@ -2,14 +2,7 @@
import PySimpleGUI as sg
import csv
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Show CSV data in Table
-sg.theme('Dark Red')
def table_example():
filename = sg.popup_get_file('filename to open', no_window=True, file_types=(("CSV Files","*.csv"),))
@@ -38,7 +31,7 @@ def table_example():
max_col_width=25,
auto_size_columns=True,
justification='right',
- # alternating_row_color='lightblue',
+ alternating_row_color='lightblue',
num_rows=min(len(data), 20))]]
diff --git a/DemoPrograms/Demo_Table_Checkmark.py b/DemoPrograms/Demo_Table_Checkmark.py
deleted file mode 100644
index f559a3cfd..000000000
--- a/DemoPrograms/Demo_Table_Checkmark.py
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import random
-import string
-
-"""
- Demo Program - Table with checkboxes
-
- This clever solution was sugged by GitHub user robochopbg.
- The beauty of the simplicity is that the checkbox is simply another column in the table. When the checkbox changes
- state, then the data in the table is changed and the table is updated in the Table element.
- A big thank you again to user robochopbg!
-
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⠆⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⡿⠁⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⠟⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⡿⠃⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀
-⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠺⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠈⠻⣿⣿⣦⣄⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠈⠻⣿⣿⣷⣤⡀⠀⠀⣰⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣦⣼⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠻⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Characters used for the checked and unchecked checkboxes. Feel free to change
-BLANK_BOX = '☐'
-CHECKED_BOX = '☑'
-
-# ------ Some functions to help generate data for the table ------
-def word():
- return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
-def number(max_val=1000):
- return random.randint(0, max_val)
-
-def make_table(num_rows, num_cols):
- data = [[j for j in range(num_cols)] for i in range(num_rows)]
- data[0] = [word() for __ in range(num_cols)]
- for i in range(1, num_rows):
- data[i] = [BLANK_BOX if random.randint(0,2) % 2 else CHECKED_BOX] + [word(), *[number() for i in range(num_cols - 1)]]
- return data
-
-# ------ Make the Table Data ------
-data = make_table(num_rows=15, num_cols=6)
-headings = [str(data[0][x])+' ..' for x in range(len(data[0]))]
-headings[0] = 'Checkbox'
-# The selected rows is stored in a set
-selected = {i for i, row in enumerate(data[1:][:]) if row[0] == CHECKED_BOX}
-
-# ------ Window Layout ------
-layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, auto_size_columns=False, col_widths=[10, 10, 20, 20 ,30, 5],
- display_row_numbers=True, justification='center', num_rows=20, key='-TABLE-', selected_row_colors='red on yellow',
- expand_x=False, expand_y=True, vertical_scroll_only=False, enable_click_events=True, select_mode=sg.TABLE_SELECT_MODE_NONE, font='_ 14'),
- sg.Sizegrip()]]
-
-# ------ Create Window ------
-window = sg.Window('Table with Checkbox', layout, resizable=True, finalize=True)
-
-# Highlight the rows (select) that have checkboxes checked
-window['-TABLE-'].update(values=data[1:][:], select_rows=list(selected))
-
-# ------ Event Loop ------
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- elif event[0] == '-TABLE-' and event[2][0] not in (None, -1): # if clicked a data row rather than header or outside table
- row = event[2][0]+1
- if data[row][0] == CHECKED_BOX: # Going from Checked to Unchecked
- selected.remove(row-1)
- data[row][0] = BLANK_BOX
- else: # Going from Unchecked to Checked
- selected.add(row-1)
- data[row ][0] = CHECKED_BOX
- window['-TABLE-'].update(values=data[1:][:], select_rows=list(selected)) # Update the table and the selected rows
-
-window.close()
-
diff --git a/DemoPrograms/Demo_Table_Element.py b/DemoPrograms/Demo_Table_Element.py
index fd5d05c49..824005075 100644
--- a/DemoPrograms/Demo_Table_Element.py
+++ b/DemoPrograms/Demo_Table_Element.py
@@ -3,72 +3,51 @@
import random
import string
-"""
- Basic use of the Table Element
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
+# Yet another example of showing CSV data in Table
-# ------ Some functions to help generate data for the table ------
def word():
return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
def number(max_val=1000):
return random.randint(0, max_val)
+
def make_table(num_rows, num_cols):
data = [[j for j in range(num_cols)] for i in range(num_rows)]
- data[0] = [word() for __ in range(num_cols)]
+ data[0] = [word() for _ in range(num_cols)]
for i in range(1, num_rows):
data[i] = [word(), *[number() for i in range(num_cols - 1)]]
return data
-# ------ Make the Table Data ------
+
data = make_table(num_rows=15, num_cols=6)
-headings = [str(data[0][x])+' ..' for x in range(len(data[0]))]
+# sg.set_options(element_padding=(0,0))
+headings = [data[0][x] for x in range(len(data[0]))]
-# ------ Window Layout ------
-layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25,
+layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, background_color='lightblue',
auto_size_columns=True,
- # cols_justification=('left','center','right','c', 'l', 'bad'), # Added on GitHub only as of June 2022
display_row_numbers=True,
- justification='center',
+ justification='right',
num_rows=20,
- alternating_row_color='lightblue',
- key='-TABLE-',
- selected_row_colors='red on yellow',
- enable_events=True,
- expand_x=False,
- expand_y=True,
- vertical_scroll_only=False,
- enable_click_events=True, # Comment out to not enable header and other clicks
+ alternating_row_color='blue',
+ key='-table-',
tooltip='This is a table')],
- [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')],
- [sg.Text('Read = read which rows are selected')],
- [sg.Text('Double = double the amount of data in the table')],
- [sg.Text('Change Colors = Changes the colors of rows 8 and 9'), sg.Sizegrip()]]
+ [sg.Button('Read'), sg.Button('Double'), sg.Button('Update')],
+ [sg.Text('Read = read which rows are selected')], [sg.Text('Double = double the amount of data in the table')]]
-# ------ Create Window ------
-window = sg.Window('The Table Element', layout,
- # ttk_theme='clam',
- # font='Helvetica 25',
- resizable=True
- )
+window = sg.Window('Table', layout, grab_anywhere=False, resizable=True)
-# ------ Event Loop ------
while True:
event, values = window.read()
print(event, values)
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event == 'Double':
- for i in range(1,len(data)):
+ for i in range(len(data)):
data.append(data[i])
- window['-TABLE-'].update(values=data[1:][:])
- elif event == 'Change Colors':
- window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green')))
+ window['-table-'].update(values=data)
+ elif event == 'Update':
+ window['-table-'].update(row_colors=((8, 'white',
+ 'red'), (9, 'black')))
window.close()
-
diff --git a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py
deleted file mode 100644
index 19bf40699..000000000
--- a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import random
-import string
-import operator
-
-"""
- Table Element Demo With Sorting and Cell Editing
- NOTE: release 5.0.6.5 needed in order to use the Cell Editing features. Comment out the parameters that contain cell_edit to remove from demo
-
- The data for the table is assumed to have HEADERS across the first row.
- This is often the case for CSV files or spreadsheets
-
- This demo shows how you can use these click events to sort your table by columns
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('Light green 6')
-
-
-# ------ Some functions to help generate data for the table ------
-def word():
- return ''.join(random.choice(string.ascii_lowercase) for i in range(10))
-
-
-def number(max_val=1000):
- return random.randint(0, max_val)
-
-
-def make_table(num_rows, num_cols):
- data = [[j for j in range(num_cols)] for i in range(num_rows)]
- data[0] = [word() for _ in range(num_cols)]
- for i in range(1, num_rows):
- data[i] = [i, word(), *[number() for i in range(num_cols - 2)]]
- return data
-
-
-# ------ Make the Table Data ------
-data = make_table(num_rows=15, num_cols=6)
-# headings = [str(data[0][x])+' ..' for x in range(len(data[0]))]
-headings = [f'Col {col}' for col in range(1, len(data[0]) + 1)]
-
-
-def sort_table(table, cols):
- """ sort a table by multiple columns
- table: a list of lists (or tuple of tuples) where each inner list
- represents a row
- cols: a list (or tuple) specifying the column numbers to sort by
- e.g. (1,0) would sort by column 1, then by column 0
- """
- for col in reversed(cols):
- try:
- table = sorted(table, key=operator.itemgetter(col))
- except Exception as e:
- sg.popup_error('Error in sort_table', 'Exception in sort_table', e)
- return table
-
-
-# ------ Window Layout ------
-layout = [[sg.Table(values=data[1:][:], headings=headings + ['Extra'], max_col_width=25,
- auto_size_columns=True,
- display_row_numbers=False,
- justification='right',
- right_click_selects=True,
- num_rows=20,
- alternating_row_color='lightyellow',
- key='-TABLE-',
- selected_row_colors='red on yellow',
- enable_events=True,
- expand_x=True,
- expand_y=True,
- enable_click_events=True, # Comment out to not enable header and other clicks
- enable_cell_editing=True, # Comment out to if your PSG version does not support cell edint
- cell_edit_colors='white on blue', # Comment out to if your PSG version does not support cell edint
- cell_edit_select_colors='yellow on red', # Comment out to if your PSG version does not support cell edint
- tooltip='This is a table')],
- [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')],
- [sg.Text('Cell clicked:'), sg.T(k='-CLICKED-')],
- [sg.Text('Read = read which rows are selected')],
- [sg.Text('Double = double the amount of data in the table')],
- [sg.Text('Change Colors = Changes the colors of rows 8 and 9'), sg.Sizegrip()]]
-
-# ------ Create Window ------
-window = sg.Window('The Table Element', layout, resizable=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, finalize=True, print_event_values=True)
-
-
-# ------ Event Loop ------
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
- elif event == 'Version':
- sg.popup_scrolled(__file__, sg.get_versions(), location=window.current_location(), keep_on_top=True, non_blocking=True)
- if event == 'Read':
- [print(row) for row in window['-TABLE-'].values]
- if event == 'Double':
- for i in range(1, len(data)):
- data.append(data[i].copy())
- window['-TABLE-'].update(values=data[1:][:])
- elif event == 'Change Colors':
- window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green')))
-
- # See if was a table clicked or edited event by checking event[0] for table's key
- if event[0] == '-TABLE-': # TABLE CELL Event has value in format ('-TABLE=', '+type of event+', (row,col))
- if event[2][0] == -1 and event[2][1] != -1: # Header was clicked and wasn't the "row" column
- col_num_clicked = event[2][1]
- new_table = sort_table(data[1:][:], (col_num_clicked, 0))
- window['-TABLE-'].update(new_table)
- data = [data[0]] + new_table
- window['-CLICKED-'].update(f'{event[2][0]},{event[2][1]}')
-window.close()
diff --git a/DemoPrograms/Demo_Table_Pandas.py b/DemoPrograms/Demo_Table_Pandas.py
index 38664e616..32f9f5449 100644
--- a/DemoPrograms/Demo_Table_Pandas.py
+++ b/DemoPrograms/Demo_Table_Pandas.py
@@ -2,15 +2,8 @@
import PySimpleGUI as sg
import pandas as pd
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Yet another example of showing CSV data in Table
-
def table_example():
sg.set_options(auto_size_buttons=True)
diff --git a/DemoPrograms/Demo_Table_Simulation.py b/DemoPrograms/Demo_Table_Simulation.py
index bb7cbcd7c..b41111ae0 100644
--- a/DemoPrograms/Demo_Table_Simulation.py
+++ b/DemoPrograms/Demo_Table_Simulation.py
@@ -2,31 +2,25 @@
import PySimpleGUI as sg
import csv
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
def TableSimulation():
"""
Display data in a table format
"""
-
- sg.popup_quick_message('Hang on for a moment, this will take a bit to create....', auto_close=True, non_blocking=True, font='Default 18')
-
sg.set_options(element_padding=(0, 0))
menu_def = [['File', ['Open', 'Save', 'Exit']],
['Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
['Help', 'About...'], ]
+ columm_layout = [[]]
+
MAX_ROWS = 20
MAX_COL = 10
-
- columm_layout = [[sg.Text(str(i), size=(4, 1), justification='right')] + [sg.InputText(size=(10, 1), pad=(1,1),border_width=0, justification='right', key=(i, j)) for j in range(MAX_COL)] for i in range(MAX_ROWS)]
-
+ for i in range(MAX_ROWS):
+ inputs = [sg.Text(str(i), size=(4, 1), justification='right')] + [sg.Input(size=(10, 1), pad=(
+ 1, 1), justification='right', key=(i, j)) for j in range(MAX_COL)]
+ columm_layout.append(inputs)
layout = [[sg.Menu(menu_def)],
[sg.Text('Table Using Combos and Input Elements', font='Any 18')],
@@ -36,12 +30,12 @@ def TableSimulation():
sg.Input(key='value', size=(8, 1), pad=(1, 1), justification='right')],
[sg.Col(columm_layout, size=(800, 600), scrollable=True)]]
- window = sg.Window('Table', layout, return_keyboard_events=True, resizable=True)
+ window = sg.Window('Table', layout, return_keyboard_events=True)
while True:
event, values = window.read()
# --- Process buttons --- #
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
elif event == 'About...':
sg.popup('Demo of table capabilities')
diff --git a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py
index 98bc32c4b..13656953b 100644
--- a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py
+++ b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py
@@ -1,70 +1,44 @@
-import PySimpleGUI as sg
+import PySimpleGUIWeb as sg
from random import randint
-import operator
"""
Another simple table created from Input Text Elements. This demo adds the ability to "navigate" around the drawing using
the arrow keys. The tab key works automatically, but the arrow keys are done in the code below.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-sg.theme('Dark Brown 2') # No excuse for gray windows
-# Show a "splash" type message so the user doesn't give up waiting
-sg.popup_quick_message('Hang on for a moment, this will take a bit to create....', auto_close=True, non_blocking=True)
+sg.change_look_and_feel('Light green 5') # No excuse for gray windows
-MAX_ROWS, MAX_COLS, COL_HEADINGS = 15, 6, ('A', 'B', 'C', 'D', 'E', 'F',)
+MAX_COLS = MAX_ROWS = 5
+# Create an Excel style window layout quickly and easily using list comprehensions
+layout = [[sg.Text(' '*11)]+[sg.Text(s+ ' '*19) for s in 'ABCDE'] ] + \
+ [[sg.T(r)] + [sg.Input(randint(0,100), justification='r', key=(r,c)) for c in range(MAX_COLS)] for r in range(MAX_ROWS)] + \
+ [[sg.Button('Table Values'), sg.Button('Exit')]]
-# A HIGHLY unusual layout definition
-# Normally a layout is specified 1 ROW at a time. Here multiple rows are being contatenated together to produce the layout
-# Note the " + \ " at the ends of the lines rather than the usual " , "
-# This is done because each line is a list of lists
-layout = [[sg.Text('Click on a column header to sort by that column', font='Default 16')]] + \
- [[sg.Text(' ' * 15)] + [sg.Text(s, key=s, enable_events=True, font='Courier 14', size=(8, 1)) for i, s in enumerate(COL_HEADINGS)]] + \
- [[sg.T(r, size=(4, 1))] + [sg.Input(randint(0, 100), justification='r', key=(r, c)) for c in range(MAX_COLS)] for r in range(MAX_ROWS)] + \
- [[sg.Button('Show Table As Lists'), sg.Button('Exit')]]
-
-# Create the window
-window = sg.Window('A Table Simulation', layout, default_element_size=(12, 1), element_padding=(1, 1), return_keyboard_events=True)
-
-current_cell = (0, 0)
-while True: # Event Loop
+# Create the window and show it
+window = sg.Window('A Table Simulation', layout, default_element_size=(12,1), element_padding=(1,1), return_keyboard_events=True)
+current_cell = (0,0)
+while True: # Event Loop
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'): # If user closed the window
+ if event in (None, 'Exit'): # If user closed the window
break
elem = window.find_element_with_focus()
- current_cell = elem.Key if elem and type(elem.Key) is tuple else (0, 0)
- r, c = current_cell
-
+ current_cell = elem.Key if elem else (0,0)
+ r,c = current_cell
+ # Process arrow keys
if event.startswith('Down'):
- r = r + 1 * (r < MAX_ROWS - 1)
- elif event.startswith('Left'):
- c = c - 1 * (c > 0)
- elif event.startswith('Right'):
- c = c + 1 * (c < MAX_COLS - 1)
- elif event.startswith('Up'):
+ r = r + 1 * (r < MAX_ROWS-1)
+ if event.startswith('Left'):
+ c = c - 1 *(c > 0)
+ if event.startswith('Right'):
+ c = c + 1 *(c < MAX_COLS-1)
+ if event.startswith('Up'):
r = r - 1 * (r > 0)
- elif event in COL_HEADINGS: # Perform a sort if a column heading was clicked
- col_clicked = COL_HEADINGS.index(event)
- try:
- table = [[int(values[(row, col)]) for col in range(MAX_COLS)] for row in range(MAX_ROWS)]
- new_table = sorted(table, key=operator.itemgetter(col_clicked))
- except:
- sg.popup_error('Error in table', 'Your table must contain only ints if you wish to sort by column')
- else:
- for i in range(MAX_ROWS):
- for j in range(MAX_COLS):
- window[(i, j)].update(new_table[i][j])
- [window[c].update(font='Any 14') for c in COL_HEADINGS] # make all column headings be normal fonts
- window[event].update(font='Any 14 bold') # bold the font that was clicked
# if the current cell changed, set focus on new cell
- if current_cell != (r, c):
- current_cell = r, c
- window[current_cell].set_focus() # set the focus on the element moved to
- window[current_cell].update(select=True) # when setting focus, also highlight the data in the element so typing overwrites
+ if current_cell != (r,c):
+ current_cell = r,c
+ window[current_cell].set_focus() # set the focus on the element moved to
+ window[current_cell].update(select=True) # when setting focus, also highlight the data in the element so typing overwrites
# if clicked button to dump the table's values
- if event.startswith('Show Table'):
- table = [[values[(row, col)] for col in range(MAX_COLS)] for row in range(MAX_ROWS)]
- sg.popup_scrolled('your_table = [ ', ',\n'.join([str(table[i]) for i in range(MAX_ROWS)]) + ' ]', title='Copy your data from here', font='fixedsys', keep_on_top=True)
+ if event == 'Table Values':
+ table = [[values[(row,col)] for col in range(MAX_COLS)] for row in range(MAX_ROWS)]
+ print(f'table = {table}')
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Tabs.py b/DemoPrograms/Demo_Tabs.py
index 2700502b2..7519a3cfe 100644
--- a/DemoPrograms/Demo_Tabs.py
+++ b/DemoPrograms/Demo_Tabs.py
@@ -1,21 +1,12 @@
#!/usr/bin/env python
import sys
import PySimpleGUI as sg
-# import PySimpleGUIWeb as sg
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
# Usage of Tabs in PSG
-#
-# sg.set_options(background_color='cornsilk4',
-# element_background_color='cornsilk2',
-# input_elements_background_color='cornsilk2')
-sg.theme('Light Green 5')
+sg.set_options(background_color='cornsilk4',
+ element_background_color='cornsilk2',
+ input_elements_background_color='cornsilk2')
tab1_layout = [[sg.Text('This is inside tab 1', background_color='darkslateblue', text_color='white')],
[sg.Input(key='-in0-')]]
@@ -41,13 +32,13 @@
selected_title_color='green', tab_location='right'),
sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'),
sg.Tab('Tab 5', tab5_layout)]], key='-group1-', tab_location='top', selected_title_color='purple')],
- # [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='-mykey-'),
- # sg.Tab('Tab 2', tab2_layout, background_color='tan1'),
- # sg.Tab('Tab 3', tab3_layout)]],
- # key='-group3-', title_color='red',
- # selected_title_color='green', tab_location='left'),
- # sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'),
- # sg.Tab('Tab 5', tab5_layout)]], key='-group4-', tab_location='bottom', selected_title_color='purple')],
+ [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='-mykey-'),
+ sg.Tab('Tab 2', tab2_layout, background_color='tan1'),
+ sg.Tab('Tab 3', tab3_layout)]],
+ key='-group3-', title_color='red',
+ selected_title_color='green', tab_location='left'),
+ sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'),
+ sg.Tab('Tab 5', tab5_layout)]], key='-group4-', tab_location='bottom', selected_title_color='purple')],
[sg.Button('Read')]]
window = sg.Window('My window with tabs', layout,
@@ -58,6 +49,6 @@
event, values = window.read()
sg.popup_non_blocking(event, values)
print(event, values)
- if event == sg.WIN_CLOSED: # always, always give a way out!
+ if event is None: # always, always give a way out!
break
window.close()
diff --git a/DemoPrograms/Demo_Tabs_Nested.py b/DemoPrograms/Demo_Tabs_Nested.py
index ed992eb80..46a16e621 100644
--- a/DemoPrograms/Demo_Tabs_Nested.py
+++ b/DemoPrograms/Demo_Tabs_Nested.py
@@ -1,25 +1,9 @@
+#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Demo - Yet another example of TabGroup element
+# Yet another example of TabGroup element
- These are simple tabs and tab groups. This example simply shows groups within groups.
- Be careful with tabs to make sure you don't re-use a layout. If you used a layout in one tab
- you cannot use it again in another tab.
-
- There was an error in this demo for quite some time that makes for a great example of this error.
-
- See how tab_layout is in both Tab elements? That's a no-go and you'll get an error poup
-
- tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout), sg.Tab('Tab 8', tab_layout)]])
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-sg.theme('GreenTan')
+sg.change_look_and_feel('GreenTan')
tab2_layout = [[sg.Text('This is inside tab 2')],
[sg.Text('Tabs can be anywhere now!')]]
@@ -28,12 +12,11 @@
tab3_layout = [[sg.Text('This is inside tab 3')]]
tab4_layout = [[sg.Text('This is inside tab 4')]]
-tab_layout7 = [[sg.Text('This is inside of a tab')]]
-tab_layout8 = [[sg.Text('This is inside of a tab')]]
-tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout7), sg.Tab('Tab 8', tab_layout8)]])
+tab_layout = [[sg.Text('This is inside of a tab')]]
+tab_group = sg.TabGroup([[sg.Tab('Tab 7', tab_layout), sg.Tab('Tab 8', tab_layout)]])
tab5_layout = [[sg.Text('Watch this window')],
- [sg.Output(size=(40,5))]] # generally better to use a Multline, but for super-simple examples, Output is OK
+ [sg.Output(size=(40,5))]]
tab6_layout = [[sg.Text('This is inside tab 6')],
[sg.Text('How about a second row of stuff in tab 6?'), tab_group]]
@@ -50,7 +33,7 @@
while True:
event, values = window.read()
print(event, values)
- if event == sg.WIN_CLOSED: # always, always give a way out!
+ if event is None: # always, always give a way out!
break
window.close()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Tabs_Simple.py b/DemoPrograms/Demo_Tabs_Simple.py
index 3d68ca6df..ebc0827bd 100644
--- a/DemoPrograms/Demo_Tabs_Simple.py
+++ b/DemoPrograms/Demo_Tabs_Simple.py
@@ -1,54 +1,28 @@
#!/usr/bin/env python
+import PySimpleGUI as sg
-"""
- Demo - Simple Tabs
-
- How to use the Tab Element and the TabGroup Element
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
+# Simple example of TabGroup element
-import PySimpleGUI as sg
-# Simple example of TabGroup element and the options available to it
-sg.theme('Dark Red') # Please always add color to your window
-# The tab 1, 2, 3 layouts - what goes inside the tab
tab1_layout = [[sg.Text('Tab 1')],
[sg.Text('Put your layout in here')],
- [sg.Text('Input something'), sg.Input(size=(12,1), key='-IN-TAB1-')]]
+ [sg.Text('Input something'), sg.Input(key='-IN0-')]]
+
+tab2_layout = [[sg.Text('Tab2')]]
-tab2_layout = [[sg.Text('Tab 2')]]
-tab3_layout = [[sg.Text('Tab 3')]]
-tab4_layout = [[sg.Text('Tab 3')]]
-# The TabgGroup layout - it must contain only Tabs
-tab_group_layout = [[sg.Tab('Tab 1', tab1_layout, key='-TAB1-'),
- sg.Tab('Tab 2', tab2_layout, visible=False, key='-TAB2-'),
- sg.Tab('Tab 3', tab3_layout, key='-TAB3-'),
- sg.Tab('Tab 4', tab4_layout, visible=False, key='-TAB4-')]]
+layout = [[sg.TabGroup([[
+ sg.Tab('Tab 1', tab1_layout),
+ sg.Tab('Tab 2', tab2_layout)]], key='-TABGROUP-')],
+ [sg.Button('Read')]]
-# The window layout - defines the entire window
-layout = [[sg.TabGroup(tab_group_layout,
- enable_events=True,
- key='-TABGROUP-')],
- [sg.Text('Make tab number'), sg.Input(key='-IN-', size=(3,1)), sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Select'), sg.Button('Disable')]]
+window = sg.Window('My window with tabs', layout,
+ default_element_size=(12, 1))
-window = sg.Window('My window with tabs', layout, no_titlebar=False)
-tab_keys = ('-TAB1-','-TAB2-','-TAB3-', '-TAB4-') # map from an input value to a key
while True:
- event, values = window.read() # type: str, dict
- print(event, values)
- if event == sg.WIN_CLOSED:
+ event, values = window.read()
+ sg.popup_non_blocking('button = %s' % event, 'Values dictionary', values)
+ if event is None: # always, always give a way out!
break
- # handle button clicks
- if event == 'Invisible':
- window[tab_keys[int(values['-IN-'])-1]].update(visible=False)
- if event == 'Visible':
- window[tab_keys[int(values['-IN-'])-1]].update(visible=True)
- if event == 'Select':
- window[tab_keys[int(values['-IN-'])-1]].select()
- if event == 'Disable':
- window[tab_keys[int(values['-IN-']) - 1]].update(disabled=True)
+
window.close()
diff --git a/DemoPrograms/Demo_Template.py b/DemoPrograms/Demo_Template.py
new file mode 100644
index 000000000..6af2b7b36
--- /dev/null
+++ b/DemoPrograms/Demo_Template.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+import PySimpleGUI as sg
+
+#
+# Choose one of these are your starting point. Copy, paste, have fun
+#
+
+
+# ---------------------------------#
+# DESIGN PATTERN 1 - Simple Window #
+# ---------------------------------#
+layout = [[ sg.Text('My layout') ],
+ [ sg.CloseButton('Next Window')]]
+
+window = sg.Window('My window', layout)
+event, values = window.read()
+
+
+# --------------------------------------------------#
+# DESIGN PATTERN 2 - Persistent Window (stays open) #
+# --------------------------------------------------#
+
+layout = [[ sg.Text('My Window') ],
+ [ sg.Button('Read The Window')]]
+
+window = sg.Window('My Window Title', layout)
+
+while True: # Event Loop
+ event, values = window.read()
+ if event is None: # if window closed with X
+ break
+ print(event, values)
+
+window.close()
diff --git a/DemoPrograms/Demo_Text_Element_Autosize.py b/DemoPrograms/Demo_Text_Element_Autosize.py
deleted file mode 100644
index baab69035..000000000
--- a/DemoPrograms/Demo_Text_Element_Autosize.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo of autosize of Text Element
-
- Beginning in version 4.46.0 the Text element will fully autosize if:
- * auto_size_text is True (default)
- * No size is supplied or (None, None) is supplied
-
- "Fully autosize" means that both the element and the window will grow/shrink
- as the contents of the Text element changes.
-
- Prior versions autosized in 1 direction, either horizontally or vertically
- * Set size = (None, int) to autosize horizontally
- * Set size = (int, None) to autosize vertically
-
- By default autosize is enabled, but setting a size parameter will disable unless None is specified
- in one of the directions.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [[sg.Text('Starting string', size=(None, None), k='-T-'), sg.Text('Also on first row')],
- # THIS is the newly added combination. Note (None, None) is default and not really needed
- [sg.Text('None, 1', size=(None, 1), k='-T1-'), sg.Text('rest of the row')],
- [sg.Text('30, None', size=(30, None), k='-T2-'), sg.Text('rest of the row')],
- [sg.Text('Explicit size', size=(15, 1)), sg.Text('Second Text Element on second row')],
- [sg.Button('Go'), sg.B('Clear'), sg.Button('Exit')]]
-
-window = sg.Window('Autosize Text', layout)
-
-while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Go':
- window['-T-'].update('This is the new string\nThat is multiple\nlines')
- window['-T1-'].update('This is the new string\nThat is multiple\nlines')
- window['-T2-'].update('This is the new string\nThat is multiple\nlines')
- elif event == 'Clear':
- window['-T-'].update('')
- window['-T1-'].update('')
- window['-T2-'].update('')
-
-window.close()
diff --git a/DemoPrograms/Demo_Theme_Add_Your_Own.py b/DemoPrograms/Demo_Theme_Add_Your_Own.py
deleted file mode 100644
index 8bdbe9d64..000000000
--- a/DemoPrograms/Demo_Theme_Add_Your_Own.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo showing how to add your own theme.
-
- There are functions to make the job quick and easy.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# First make a dictionary with the required keys.
-# Use only colors in the format of #RRGGBB
-DarkGrey20 = {'BACKGROUND': '#19232D',
- 'TEXT': '#ffffff',
- 'INPUT': '#32414B',
- 'TEXT_INPUT': '#ffffff',
- 'SCROLL': '#505F69',
- 'BUTTON': ('#ffffff', '#32414B'),
- 'PROGRESS': ('#505F69', '#32414B'),
- 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
- }
-
-# Add your dictionary to the PySimpleGUI themes
-sg.theme_add_new('DarkGrey20', DarkGrey20)
-
-# Switch your theme to use the newly added one
-sg.theme('Dark Grey 20')
-
-def main():
- # Test it out!
- try:
- sg.popup_get_text('Dark Grey 20 looks like this.', image=sg.EMOJI_BASE64_HAPPY_THUMBS_UP)
- except:
- sg.popup_get_text('Dark Grey 20 looks like this.\n' + \
- 'Upgrading to 4.35.0+ will give you a nice emoji like the one above',
- image=EMOJI_BASE64_HAPPY_THUMBS_UP)
-
-if __name__ == '__main__':
- EMOJI_BASE64_HAPPY_THUMBS_UP = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6N0M3M0ExQkM3OTk2MTFFQkFDREU4QkE2OUQ2Njk5ODUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6N0M3M0ExQkQ3OTk2MTFFQkFDREU4QkE2OUQ2Njk5ODUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3QzczQTFCQTc5OTYxMUVCQUNERThCQTY5RDY2OTk4NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3QzczQTFCQjc5OTYxMUVCQUNERThCQTY5RDY2OTk4NSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrSTufUAABP3SURBVHja3Fp5cF31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'
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Theme_Browser.py b/DemoPrograms/Demo_Theme_Browser.py
deleted file mode 100644
index 4dba88f9b..000000000
--- a/DemoPrograms/Demo_Theme_Browser.py
+++ /dev/null
@@ -1,31 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Allows you to "browse" through the theme settings. Click on one and you'll see a
- Popup window using the color scheme you chose. It's a simply little program that demonstrates
- how snappy a GUI can feel if you enable an element's events rather than waiting on a button click.
- In this program, as soon as a listbox entry is clicked, the read returns.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('Dark Green 5')
-
-layout = [[sg.Text('Look and Feel Browser')],
- [sg.Text('Click a look and feel color to see demo window')],
- [sg.Listbox(values=sg.theme_list(),
- size=(20, 20), key='-LIST-', enable_events=True)],
- [sg.Button('Exit')]]
-
-window = sg.Window('Look and Feel Browser', layout)
-
-while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- sg.theme(values['-LIST-'][0])
- sg.popup_get_text('This is {}'.format(values['-LIST-'][0]), default_text=values['-LIST-'][0])
-
-window.close()
diff --git a/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py b/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py
deleted file mode 100644
index 8788337e7..000000000
--- a/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Changing your window's theme at runtime
- * Create your window using a "window create function"
- * When your window's theme changes, close the window, call the "window create function"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# ------------------- Create the window -------------------
-def make_window(theme=None):
- if theme:
- sg.theme(theme)
- # ----- Layout & Window Create -----
- layout = [[sg.T('This is your layout')],
- [sg.Button('Ok'), sg.Button('Change Theme'), sg.Button('Exit')]]
-
- return sg.Window('Pattern for changing theme', layout)
-
-
-# ------------------- Main Program and Event Loop -------------------
-def main():
- window = make_window()
-
- while True:
- event, values = window.read()
- if event == sg.WINDOW_CLOSED or event == 'Exit':
- break
- if event == 'Change Theme': # Theme button clicked, so get new theme and restart window
- event, values = sg.Window('Choose Theme', [[sg.Combo(sg.theme_list(), readonly=True, k='-THEME LIST-'), sg.OK(), sg.Cancel()]]).read(close=True)
- print(event, values)
- if event == 'OK':
- window.close()
- window = make_window(values['-THEME LIST-'])
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Theme_Color_Swatches.py b/DemoPrograms/Demo_Theme_Color_Swatches.py
deleted file mode 100644
index 2cd36a7ca..000000000
--- a/DemoPrograms/Demo_Theme_Color_Swatches.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Theme Color Swatches
-
- Sometimes when working with themes, it's nice ot know all of the hex values
- for the theme. Or, maybe you want to scroll through the list of themes and
- look at the colors in the theme as groups of color swatches. Whatever thr
- reason, this ia good candidate for you.
-
- Thie program is interactive. In addition to showing you the swatches, you can
- interact with them.
- * If you hover with your mouse, you'll get a tooltip popup that tells you the hex value.
- * If you left click, then the value it posted to the clipboard.
- * If you right click a swatch, then the right clip menu will show you the hex value.
- If you then select that menu item, it's copied to the clipbard.
-
- The code has several examples you may want to try out in your prgorams. Everything from
- using "Symbols" to make the swatches, so generating layouts, integrating (optionally) other
- packages like pyperclip, moving a window based on the size of the window
-
- This code's pattern is becoming more widespread lately:
- * Have a "create_window' function where the layout and Window is defined
- * Use a "main" program function where the event loop also lives
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Try and import pyperclip. Save if can be used or not.
-try:
- import pyperclip
- pyperclip_available=True
-except:
- pyperclip_available=False
-
-
-def create_window():
- # Begin the layout with a header
- layout = [[sg.Text('Themes as color swatches', text_color='white', background_color='black', font='Default 25')],
- [sg.Text('Tooltip and right click a color to get the value', text_color='white', background_color='black', font='Default 15')],
- [sg.Text('Left click a color to copy to clipboard (requires pyperclip)', text_color='white', background_color='black', font='Default 15')]]
- layout =[[sg.Column(layout, element_justification='c', background_color='black')]]
- # Create the pain part, the rows of Text with color swatches
- for i, theme in enumerate(sg.theme_list()):
- sg.theme(theme)
- colors = [sg.theme_background_color(), sg.theme_text_color(), sg.theme_input_background_color(),
- sg.theme_input_text_color()]
- if sg.theme_button_color() != sg.COLOR_SYSTEM_DEFAULT:
- colors.append(sg.theme_button_color()[0])
- colors.append(sg.theme_button_color()[1])
- colors = list(set(colors)) # de-duplicate items
- row = [sg.T(sg.theme(), background_color='black', text_color='white', size=(20,1), justification='r')]
- for color in colors:
- if color != sg.COLOR_SYSTEM_DEFAULT:
- row.append(sg.T(sg.SYMBOL_SQUARE, text_color=color, background_color='black', pad=(0,0), font='DEFAUlT 20', right_click_menu=['Nothing',[color]], tooltip=color, enable_events=True, key=(i,color)))
- layout += [row]
- # finish the layout by adding an exit button
- layout += [[sg.B('Exit')]]
- # place layout inside of a Column so that it's scrollable
- layout = [[sg.Column(layout, scrollable=True,vertical_scroll_only=True, background_color='black')]]
- # create and return Window that uses the layout
- return sg.Window('Theme Color Swatches', layout, background_color='black', finalize=True)
-
-
-
-def main():
- sg.popup_quick_message('This is going to take a minute...', text_color='white', background_color='red', font='Default 20')
- window = create_window()
- sg.theme(sg.OFFICIAL_PYSIMPLEGUI_THEME)
- if window.size[1] > 100:
- window.size = (window.size[0], 1000)
- window.move(window.get_screen_size()[0]//2-window.size[0]//2, window.get_screen_size()[1]//2-500)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if isinstance(event, tuple): # someone clicked a swatch
- chosen_color = event[1]
- else:
- if event[0] == '#': # someone right clicked
- chosen_color = event
- else:
- chosen_color = ''
-
- if pyperclip_available:
- pyperclip.copy(chosen_color)
- sg.popup_auto_close(f'{chosen_color}\nColor copied to clipboard', auto_close_duration=1)
- else:
- sg.popup_auto_close(f'pyperclip not installed\nPlease install pyperclip', auto_close_duration=3)
-
- window.close()
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py b/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py
deleted file mode 100644
index 33389e273..000000000
--- a/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py
+++ /dev/null
@@ -1,84 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo of using User Settings to create and store your own personal PySimpleGUI themes
-
- There are 2 operations
- 1. Initialize your settings file. You would normally only do this once and perhaps
- write a simple program to administer it or you can also edit the JSON file directly
- 2. Use your settings file. Add the code to the top of all of your applications that you want
- to have access to your selection of custom themes
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-MY_APPS_SETTING_FILENAME = 'my_awesome_apps.json'
-
-
-def init_your_settings():
- DarkGrey20 = {'BACKGROUND': '#19232D',
- 'TEXT': '#ffffff',
- 'INPUT': '#32414B',
- 'TEXT_INPUT': '#ffffff',
- 'SCROLL': '#505F69',
- 'BUTTON': ('#ffffff', '#32414B'),
- 'PROGRESS': ('#505F69', '#32414B'),
- 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
- }
-
- DarkGrey21 = {'BACKGROUND': '#121212',
- 'TEXT': '#dddddd',
- 'INPUT': '#1e1e1e',
- 'TEXT_INPUT': '#dbdcd9',
- 'SCROLL': '#272727',
- 'BUTTON': ('#69b1ef', '#2e2e2e'),
- 'PROGRESS': ('#69b1ef', '#2e2e2e'),
- 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
- }
- # Set up my app settings file... start with an empty one to be sure
- sg.user_settings_delete_filename(MY_APPS_SETTING_FILENAME)
- sg.user_settings_filename(MY_APPS_SETTING_FILENAME)
- # Add the theme dictionaries
- sg.user_settings_set_entry('Dark Gray 20', DarkGrey20)
- sg.user_settings_set_entry('Dark Gray 21', DarkGrey21)
- sg.user_settings_set_entry('-theme list-', ('Dark Gray 20', 'Dark Gray 21'))
- sg.popup_quick_message('Your settings file has been created and is ready to be used', background_color='#1c1e23', text_color='white', keep_on_top=True, font='_ 30', non_blocking=False)
-
-
-def use_your_settings():
- sg.user_settings_filename(MY_APPS_SETTING_FILENAME)
-
- default_theme_name = sg.user_settings_get_entry('-theme default-', None)
-
- # Only need this section is you want this app to allow user to select the default theme
- # Could also auto-choose the first theme in the list for them
- if default_theme_name is None:
- default_theme_list = sg.user_settings_get_entry('-theme list-', None)
- event, values = sg.Window('Choose a theme', [[sg.T('Your settings do not have a default theme chosen so please choose one')],[sg.Combo(default_theme_list, key='-THEME-', readonly=True, enable_events=True)]]).read(
- close=True)
- if event == sg.WIN_CLOSED:
- sg.popup_error('No theme chosen so exiting')
- exit()
- default_theme_name = values[event]
- sg.user_settings_set_entry('-theme default-', default_theme_name)
-
- my_theme = sg.user_settings_get_entry(default_theme_name, None)
- sg.theme_add_new(default_theme_name, my_theme)
-
- # Switch your theme to use the newly added one
- sg.theme(default_theme_name)
-
- # Test out the theme
- sg.popup_get_text(f'My theme is {default_theme_name} looks like this.', image=sg.EMOJI_BASE64_HAPPY_THUMBS_UP)
-
-if __name__ == '__main__':
- operations = ('Initialize your settings (must do first)', 'Use your settings')
- event, values = sg.Window('Choose an operation', [[sg.T('Choose an operation to perform')],[sg.Combo(operations, key='-OPERATION-', readonly=True, enable_events=True)]]).read(close=True)
- if event == sg.WIN_CLOSED:
- sg.popup_error('No operation chosen so exiting')
- elif values[event] == operations[0]:
- init_your_settings()
- elif values[event] == operations[1]:
- use_your_settings()
diff --git a/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py b/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py
deleted file mode 100644
index 6fb03b988..000000000
--- a/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py
+++ /dev/null
@@ -1,102 +0,0 @@
-
-import PySimpleGUI as sg
-
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-DarkGreyFig = {'BACKGROUND': '#232429',
- 'TEXT': '#828692',
- 'INPUT': '#333742',
- 'TEXT_INPUT': '#f7fbff',
- 'SCROLL': '#505F69',
- 'BUTTON': ('#fafdff', '#1d5ffe'),
- 'PROGRESS': ('#505F69', '#32414B'),
- 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
- }
-
-# Add your dictionary to the PySimpleGUI themes
-sg.theme_add_new('DarkGreyFig', DarkGreyFig)
-
-# Switch your theme to use the newly added one
-sg.theme('Dark GreyFig')
-
-
-def Check(state=None, key=None):
- return sg.Image(state, key=key, metadata=state, enable_events=True)
-
-def Toggle(state=None, key=None):
- return sg.Image(state, key=key, metadata=state, enable_events=True)
-
-def DarkButton(state=None, key=None):
- return sg.Image(state, key=key, metadata=state, enable_events=True)
-
-def main():
- gray_bg= '#333742'
-
- col_cb_layout = [ [Check(cb_blank, ('-CB-', 0)), sg.Text('Label')],
- [Check(cb_check, ('-CB-', 1)), sg.Text('Label')],
- [Check(cb_minus, ('-CB-', 2)), sg.Text('Label')],
- [sg.Text(s=(1,2))],
- [Toggle(toggle_light, ('-TOGGLE-', 0)), sg.Text('Light')],
- [Toggle(toggle_dark, ('-TOGGLE-', 1)), sg.Text('Dark')],
- ]
-
- col_left_layout = [ [sg.Text('Label')],
- [sg.Input(key='-IN-', border_width=0, s=30)],
- [sg.Frame('Tags', [[sg.Image(button_green_keyword, background_color=gray_bg), sg.Image(button_orange_keyword,background_color=gray_bg)]], background_color=gray_bg, border_width=0)],
- [sg.Frame('', [[DarkButton(button_dark, key=('-DARK BUTTON-', 0)), DarkButton(button_darker, key=('-DARK BUTTON-', 1)), DarkButton(button_darker, key=('-DARK BUTTON-', 2))]])],
- [sg.Image(submit_button) ] ]
-
-
- layout = [[sg.Column(col_left_layout), sg.Col(col_cb_layout)]]
- window = sg.Window('Dark Custom Mockup', layout, font='_ 16', border_depth=0, element_padding=(10,10),use_custom_titlebar=True, titlebar_background_color=sg.theme_input_background_color())
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if event[0].startswith('-CB-'):
- if window[event].metadata == cb_blank:
- window[event].update(cb_check)
- window[event].metadata = cb_check
- elif window[event].metadata == cb_check:
- window[event].update(cb_minus)
- window[event].metadata = cb_minus
- elif window[event].metadata == cb_minus:
- window[event].update(cb_blank)
- window[event].metadata = cb_blank
- elif event[0].startswith('-TOGGLE-'):
- if window[event].metadata == toggle_dark:
- window[event].update(toggle_light)
- window[event].metadata = toggle_light
- elif window[event].metadata == toggle_light:
- window[event].update(toggle_dark)
- window[event].metadata = toggle_dark
- elif event[0].startswith('-DARK BUTTON-'):
- [window[('-DARK BUTTON-', i)].update(button_darker) for i in range(3)]
- window[event].update(button_dark)
-
- window.close()
-
-if __name__ == '__main__':
- button_green_keyword = b'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'
- button_orange_keyword = b'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'
-
- cb_blank = b'iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAD+UlEQVR4nM2Y328bRRDHP7O354tTXYpLfsG/UMkIUNWWIiHEG38w4oEn0qoIgdqo/RPSR5vgNBfbt7vDw96eL46bGBqsfKWVvXt3u9+ZnZ2ZHeEDePToe83zDGt7FEWOtT1UPdb2gACYK78BMMYAoKqEEGJTRwgBVaWqKqbTKa//fC6r1r00+HD4WPf3DimKgiyzOFfjfQCUEBTnaozJAG0+Xf4F7z0qICKICAbBGFn0jaHX6+Gc4/TvMb+9+EVWEhp++UT39w+xWY/pdEZVVYQQEImvJGlvgmQGVV30NZGL/SzLEBF6vR5lWeK95927d7w5fiEANn24v39InueMxn/hfVSviKBoS8z28htJJQG6pACUON/c1YgI0/mManrB7u4uh59/xpvj+J4BePrtD7q9vc1oNKKu65ZMUnGSynt/o4ZU9QqZNO69J89zVJWiKHDOMR6PyfOcZ9/9qAD24fCxPniwy+npKSGE1ihBm8m70sfx/4IkoHOOLMuo6xprLc7Nef9+wmBwP2rIWouq4pxbKdn/BRFptelcPIXDr5+qLYoiDtYBDYJkNxvux6GxTV2sU9c13nu2t7cxRVEQQsB73xik+fBct0mr2Q0Radcven1snucEDyEo1mYE9CNJLWv48lwioCqoCiIGY6RxKWCtxWRmcZRFNqed5B66YyaeatMSuh2jNkttmQyANMJLVGgAUUHIMMnab4/QeuhGgO66JvkdEZCV4e62iUD0cTFGGmvAgNfoNDdjNGtCJdwtQrApp7MGkh3dGUIJd4ZQOnV3hlDC3SOU0g9jzEYcY3LEXceYciVVxayTJ98mluNYN1KISCTUHdwksUSiC5PyoE0RWhXpu8+M9x5jTLuPm8Klq1Kztvce45xrCW0aXQM3xlDXdSS0Se0sn7L0P8synHObP2XL6Bq39x5zcX7OvX4fo3IlhU3XlH9j8KoeCIho2yCg6lH1bXaa7oCqSp7nAFRVhXn16kicc5RlyWw2g7DY09TSzXUdYinhaysfDYEsy7DWkuc51tr2thFCaJ+9/uNILMBkcsrOzicU57Eq4ZtLY7KtbrtZQ0LMmbtaBu+VmCn6lnhSRFmWjMfjOA4wGo24uLjg08GgZZ8MLfW70l9PaGETaY5V2oZ47dnZ2QHg5dHPi+rH27e/i7Xf6N7eHgcHB1RVRVVVsfDgA9JsQV27NUg1FRMNl0OCWWg4z+LWDQYD5vM5Jycnna87GA6f6L3yPmVZsrW1hXOO2Wy2KM00VbHrEMJlDS1afG6Mod/v45xjMpnw/NefVheslvHFV8+0KAr6/T5FUQCxOra1tXUtIaMLDSYBnHN47/He49ycs7Mzjo9frlz7HzLiWEBTYnmBAAAAAElFTkSuQmCC'
-
- cb_check = b'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'
- cb_minus = b'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'
- toggle_light = b'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'
- toggle_dark = b'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'
- submit_button = b'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'
-
- button_dark = b'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'
-
- button_darker = b'iVBORw0KGgoAAAANSUhEUgAAAGsAAAA2CAMAAAD3cZcXAAACuFBMVEUfIiscHSEkJy4gIyohJCsjKC4kJjIeISghJC0jJi0gIywjJi9FSVRKTllMUFt8f4tydIBzdoJrbnl6fIh4e4Z9gIuDhpB8f4pucXwiJjF7fop/go2ChY97fodsb3p4eoV6fYh/gYyChY58fYdRVWBWWWROUlxsb3mFiJFVVmBcXWdUVWBSUl1aW2ROT1gdISp8foloa3R7fYhpbHVucXt1d4NWWWNdYGp7fYlgYWokKDF8f4l3eoR3eoVfYm1sbnlhY207PURSVF1tbngiJi9ZXGZhY24+P0YmJy0nKC4lJyxAQUdHSlVucXpiY246O0IoKS8pKzEyMzlMTVYvMDZJS1R7foh1eYI/QUc9PkVdYGtvcXs8PkMkJSpoaXN6fIZBQkl3eIJ9f4oeHyMfICQpKi9maHJtcHl2eINLS1MrLDI2Nz2Fh5EkJzBPUVc9PkNGR05BQ0pmaXNucHo7PUNNTVVoaXRISVBnaHOHiJOChI55e4VAQUhnanQ+QEc6PEJRUlqGh5J+f4lzdX8xMjgsLjQhIic8PURGR09MTlVnaHJTVmBYW2VYWmZXWWRZWmNfX2lHSlIiJS6Ago19foiFh5I6O0FkZ3IjJCl1d4JIS1NdYGmDho96e4UnJy81Nz0sLTJvcnwnKS55e4Z7fol9f4liZ21+gYyBhI5sbHZvcX1tcXttcXpwdH5pbHd4eYMwMjdlaHRtcHssLjNJTVdWWGNNUFhqb3iHiZNeYGx6fIdvcn1zdYFhZG50eIIcIyuBhI9maXGDhY6EhY+DhI+EhpJKTFh5e4d5fIZ2eoGAg4xLT1pTV2B/goxzd4B0doFOUV1VWGOHiZSGiZNdYmpfZm5/g41kZ3EhIy8gJSseIykfIywjJzBMT1ofJCpKTVdOUVtISlQdJCwlKC8fIikkJCwdICkAAACsCdXOAAAA6HRSTlP///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8Asi2gugAAAwJJREFUeJzdmAdTE1EQx7OJSonlrxRRo2KvWFAsIAqWE1tERQRRQcWKWLGhYhcVFAWxgdjF3rBi7xV7x240X8P37iCEGaIzN8kbx525293bffebN2/fldWYi0VDjhGtzkJQVDkHgYpEZ8VyLIlJeQvL4SgmRSwRKA5jrApiWE6cJQbFJqYxOwtkiUKRk0CWi0AWaVz/U5awMmQsvUCWONQ/w6poK1DJ9pjK6lhVULXsQDW42RrjDg9VLE9ULzvgBdgYUqMmaqliGVC77EAd1LU1xhv1VLHqo0Epv2GjxorRBE2JmjVvURJq6dNK1q3b2IXV1heAdztutmcsP+b5dVBCHTsxx7czs/wD7MHqAkW8ZFZgoOJ15aFuCAruHhyEHkQ97TGvXpB6h/Tp209Cf6IBgHFg6KDBRmAIkQ+CwlhGWBCGknO4PeY1LEJWkRhOFAWM4M5II0YRRSNSDsVgNNEYlSxDqfUay47YcRLGE02AMVa+FoGJNAmYLDtxmELxvnZhTZ02fYbElmgm0ayimVAC22izgTlzuczDfHJVu16J1qwFvBSkhRIWcVaScnExYy2BRZaSXm0dJmKZxV7OamPFylWUzFlRxfOKAFavAdampK5bn5a2YSOlByBDFcuATRY7E5tlnYwtvOaNW2UvCdtoO5BleQf6q31uZGNHTglrJ1e7JM7aDcRwb48RWUR7sU9O2Z95gCgcuapYB5Fx6HDUkaPHjhOdgHQyNCSBFccpotNsfyXl5cWx/XWGKAVwO0vn2GY/T6S2Ni5YFv0iUb5suAMMfAm4rARSed6VoqyrRNc8cF0V68bNW7fvGLKzPXPvMi86H/fu04OHj4geFzyhp/zuz5TE576ZL14WvOLm6zdvVbFIp9O/S3//ofAjd7T0iavP/FTIji9fv5U15vsf7vevfG/YnfVDIEsrkBUvkCXyG1vkv4PAQhT4X6kVyNJpzDl/z7KPCO6lmAXtZpO43pde6bOZRLDE9SrJqgf707Ekk3W/12z+5eqgp7CLqRjxG7LsF9Z68qMOAAAAAElFTkSuQmCC'
- main()
diff --git a/DemoPrograms/Demo_Theme_Previewer_Dark.py b/DemoPrograms/Demo_Theme_Previewer_Dark.py
deleted file mode 100644
index 472d5fad1..000000000
--- a/DemoPrograms/Demo_Theme_Previewer_Dark.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import PySimpleGUI as sg
-# import PySimpleGUIWeb as sg
-# import PySimpleGUIQt as sg
-
-"""
- If you're using the PySimpleGUI color themes, then your code will a line that looks something like this:
- sg.theme('Light Green 1') or sg.theme('LightGreen1')
-
- This demo shows how to access the list of all "dark themes" as an example of how you can build your own previewer
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Use the built-in Theme Viewer to show all of the themes and their names
-# sg.theme_previewer()
-
-# The remainder of the program duplicates the built-in Theme Viewer, allowing you to create your
-# own custom theme viewer window. You can configure the number of frames per row for example. Or maybe you only
-# want to see the dark themes
-
-window_background = 'black'
-
-def sample_layout():
- """
- Creates a small window that will represent the colors of the theme. This is an individual theme's preview
- :return: layout of a little preview window
- :rtype: List[List[Element]]
- """
- return [[sg.Text('Text element'), sg.InputText('Input data here', size=(15, 1))],
- [sg.Button('Ok'), sg.Button('Cancel'), sg.Slider((1, 10), orientation='h', size=(10, 15))]]
-
-
-layout = [[sg.Text('List of Dark Themes Provided by PySimpleGUI', font='Default 18', background_color=window_background)]]
-
-FRAMES_PER_ROW = 9
-names = [name for name in sg.theme_list() if 'dark' in name.lower()] # get list of only "dark" themes
-row = []
-for count, theme in enumerate(names):
- sg.theme(theme)
- if not count % FRAMES_PER_ROW:
- layout += [row]
- row = []
- row += [sg.Frame(theme, sample_layout())]
-if row:
- layout += [row]
-
-sg.Window('Custom Preview of Themes', layout, background_color=window_background).read(close=True)
diff --git a/DemoPrograms/Demo_Threaded_Work.py b/DemoPrograms/Demo_Threaded_Work.py
new file mode 100644
index 000000000..b8b5f77e1
--- /dev/null
+++ b/DemoPrograms/Demo_Threaded_Work.py
@@ -0,0 +1,114 @@
+#!/usr/bin/python3
+import queue
+import threading
+import time
+import PySimpleGUI as sg
+
+"""
+ You want to look for 3 points in this code, marked with comment "LOCATION X".
+ 1. Where you put your call that takes a long time
+ 2. Where the trigger to make the call takes place in the event loop
+ 3. Where the completion of the call is indicated in the event loop
+
+ Demo on how to add a long-running item to your PySimpleGUI Event Loop
+ If you want to do something that takes a long time, and you do it in the
+ main event loop, you'll quickly begin to see messages from windows that your
+ program has hung, asking if you want to kill it.
+
+ The problem is not that your problem is hung, the problem is that you are
+ not calling Read or Refresh often enough.
+
+ One way through this, shown here, is to put your long work into a thread that
+ is spun off, allowed to work, and then gets back to the GUI when it's done working
+ on that task.
+
+ Every time you start up one of these long-running functions, you'll give it an "ID".
+ When the function completes, it will send to the GUI Event Loop a message with
+ the format:
+ work_id ::: done
+ This makes it easy to parse out your original work ID
+
+ You can hard code these IDs to make your code more readable. For example, maybe
+ you have a function named "update_user_list()". You can call the work ID "user list".
+ Then check for the message coming back later from the work task to see if it starts
+ with "user list". If so, then that long-running task is over.
+
+"""
+
+# ############################# User callable CPU intensive code #############################
+# Put your long running code inside this "wrapper"
+# NEVER make calls to PySimpleGUI from this thread (or any thread)!
+# Create one of these functions for EVERY long-running call you want to make
+
+
+def long_function_wrapper(work_id, gui_queue):
+ # LOCATION 1
+ # this is our "long running function call"
+ # sleep for a while as a simulation of a long-running computation
+ time.sleep(5)
+ # at the end of the work, before exiting, send a message back to the GUI indicating end
+ gui_queue.put('{} ::: done'.format(work_id))
+ # at this point, the thread exits
+ return
+
+
+############################# Begin GUI code #############################
+def the_gui():
+ # queue used to communicate between the gui and long-running code
+ gui_queue = queue.Queue()
+
+ layout = [[sg.Text('Multithreaded Work Example')],
+ [sg.Text('Click Go to start a long-running function call')],
+ [sg.Text('', size=(25, 1), key='-OUTPUT-')],
+ [sg.Text('', size=(25, 1), key='-OUTPUT2-')],
+ [sg.Graph((10, 10), (0, 0), (10, 10),
+ background_color='black', key=i) for i in range(20)],
+ [sg.Button('Go'), sg.Button('Popup'), sg.Button('Exit')], ]
+
+ window = sg.Window('Multithreaded Window', layout)
+ # --------------------- EVENT LOOP ---------------------
+ work_id = 0
+ while True:
+ # wait for up to 100 ms for a GUI event
+ event, values = window.read(timeout=100)
+ if event in (None, 'Exit'):
+ break
+ if event == 'Go': # clicking "Go" starts a long running work item by starting thread
+ window['-OUTPUT-'].update('Starting long work %s' % work_id)
+ window[work_id].update(background_color='red')
+ # LOCATION 2
+ # STARTING long run by starting a thread
+ thread_id = threading.Thread(
+ target=long_function_wrapper,
+ args=(work_id, gui_queue,),
+ daemon=True)
+ thread_id.start()
+ work_id = work_id+1 if work_id < 19 else 0
+ # --------------- Read next message coming in from threads ---------------
+ try:
+ message = gui_queue.get_nowait() # see if something has been posted to Queue
+ except queue.Empty: # get_nowait() will get exception when Queue is empty
+ message = None # nothing in queue so do nothing
+
+ # if message received from queue, then some work was completed
+ if message is not None:
+ # LOCATION 3
+ # this is the place you would execute code at ENDING of long running task
+ # You can check the completed_work_id variable
+ # to see exactly which long-running function completed
+ completed_work_id = int(message[:message.index(' :::')])
+ window['-OUTPUT2-'].update(
+ 'Complete Work ID "{}"'.format(completed_work_id))
+ window[completed_work_id].update(background_color='green')
+
+ if event == 'Popup':
+ sg.popup('This is a popup showing that the GUI is running')
+ # if user exits the window, then close the window and exit the GUI func
+ window.close()
+
+############################# Main #############################
+
+
+if __name__ == '__main__':
+ the_gui()
+ print('Exiting Program')
diff --git a/DemoPrograms/Demo_Time_Chooser.py b/DemoPrograms/Demo_Time_Chooser.py
deleted file mode 100644
index d0ee946b4..000000000
--- a/DemoPrograms/Demo_Time_Chooser.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Time Chooser
-
- A sample window for choosing a time.
-
- This particular implementation uses a Spin element. Numerous possibilities exist for entering a time of day. Instead
- of Spin elements, Input or Combo Elements could be used.
-
- If you do not want your user to be able to manually enter values using the keyboard, then set readonly=True in
- the Spin elements.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-
-def popup_get_time(title='Time Entry', starting_hour=1, starting_minute=0, allow_manual_input=True, font=None):
- """
- Shows a window that will gather a time of day.
-
- :param title: The title that is shown on the window
- :type title: str
- :param starting_hour: Value to initially show in the hour field
- :type starting_hour: int
- :param starting_minute: Value to initially show in the minute field
- :type starting_minute: int
- :param allow_manual_input: If True, then the Spin elements can be manually edited
- :type allow_manual_input: bool
- :param font: Font to use for the window
- :type font: str | tuple
- :return: Tuple with format: (hour, minute, am-pm string)
- :type: (int, int, str)
- """
-
- max_value_dict = {'-HOUR-':(1, 12), '-MIN-':(0, 59)}
- hour_list = [i for i in range(0, 15)]
- minute_list = [i for i in range(-1, 62)]
-
- layout = [[sg.Spin(hour_list, initial_value=starting_hour, key='-HOUR-', s=3, enable_events=True, readonly=not allow_manual_input),
- sg.Text(':'),
- sg.Spin(minute_list, initial_value=starting_minute, key='-MIN-', s=3, enable_events=True, readonly=not allow_manual_input),
- sg.Combo(['AM', 'PM'], 'AM', readonly=True, key='-AMPM-')],
- [sg.Button('Ok'), sg.Button('Cancel')]]
-
- window = sg.Window(title, layout, font=font)
-
- while True:
- event, values = window.read()
- # print(event, values)
- if event == sg.WIN_CLOSED or event == 'Cancel':
- hours = minutes = ampm = None
- break
-
- if event == '-HOUR-' or event == '-MIN-':
- spin_value = values[event]
- if spin_value > max_value_dict[event][1]:
- values[event] = max_value_dict[event][0]
- window[event].update(values[event])
- elif spin_value < max_value_dict[event][0]:
- values[event] = max_value_dict[event][1]
- window[event].update(values[event])
- if event == 'Ok':
- # Do validation on the input values to ensure they're valid
- try:
- hours = int(values["-HOUR-"])
- minutes = int(values["-MIN-"])
- ampm = values["-AMPM-"]
- except:
- continue # if not valid, then don't allow exiting the window using OK.
- if 1 <= hours <= 12 and 0 <= minutes < 60: # make sure the hour and minute values are in a valid range
- break
-
- window.close()
-
- return hours, minutes, ampm
-
-print(popup_get_time(font='_ 15'))
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Timer.py b/DemoPrograms/Demo_Timer.py
new file mode 100644
index 000000000..85c2ff339
--- /dev/null
+++ b/DemoPrograms/Demo_Timer.py
@@ -0,0 +1,41 @@
+import PySimpleGUI as sg
+import time
+
+# Basic timer in PSG
+
+def Timer():
+ sg.change_look_and_feel('Dark')
+ sg.set_options(element_padding=(0, 0))
+ form_rows = [[sg.Text(size=(8, 2), font=('Helvetica', 20),
+ justification='center', key='text')],
+ [sg.Button('Pause', key='-RUN-PAUSE-'),
+ sg.Button('Reset'),
+ sg.Exit(button_color=('white', 'firebrick4'))]]
+ window = sg.Window('Running Timer', form_rows,
+ no_titlebar=True, auto_size_buttons=False)
+ i = 0
+ paused = False
+ start_time = int(round(time.time() * 100))
+
+ while True:
+ # This is the code that reads and updates your window
+ button, values = window.read(timeout=0)
+ window['text'].update('{:02d}:{:02d}.{:02d}'.format(
+ (i // 100) // 60, (i // 100) % 60, i % 100))
+
+ if values is None or button == 'Exit':
+ break
+
+ if button == 'Reset':
+ i = 0
+
+ elif button == '-RUN-PAUSE-':
+ paused = not paused
+ window['-RUN-PAUSE-'].update('Run' if paused else 'Pause')
+
+ if not paused:
+ i += 1
+
+ window.close()
+
+Timer()
diff --git a/DemoPrograms/Demo_Timer_API_State_Machine.py b/DemoPrograms/Demo_Timer_API_State_Machine.py
deleted file mode 100644
index 9782f68e2..000000000
--- a/DemoPrograms/Demo_Timer_API_State_Machine.py
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-
-"""
- Demo - State Machine using timers
-
- State Machines are very useful when you need to perform a series of operations that you
- cannot do all at once due to a time constraint. Particularly problematic are operations
- where you would normally use "sleeps" as part of the sequence.
-
- In this Demo Program, we're going to use the PySimpleGUI Timer API calls to provide our
- sleep-like behavior.
-
- The sequence of operations we're going to run are:
- User clicks a "Send" Button to start the sequence:
- 1. A "Status Window" is shown that says "Sending" and Disable SEND button
- 2. Sleep for 3 seconds
- 3. Close the "Status Window"
- 4. Sleep for 2 seconds
- 5. Enable SEND button and Go to state 1
-
- Control of the state machine will be through the PySimpleGUI events. This will enable you to use threads
- for any of these states and have the threads communicate the state transitions using the same write_event_value used
- in this example.
-
- Copyright 2018-2026 PySimpleGUI. All Rights Reserved.
-"""
-
-
-class State:
- stopped = 'stopped'
- start = 'start'
- delay_3_sec = 'delay 3 seconds'
- close_win = 'close win'
- delay_2_sec = 'delay 2 seconds'
- enable_send = 'enable send'
-
-
-TIMER1 = 3000
-TIMER2 = 2000
-NEXT_STATE = '-NEXT-'
-
-
-def make_send_window():
- layout = [[sg.Text('Send Window')],
- [sg.Text('State:'), sg.Text(key='-STATE-')]]
-
- # Create window a little lower on screen so windows don't overlap
- window = sg.Window('Send Window', layout, finalize=True, relative_location=(0, 150))
- return window
-
-
-def main():
- layout = [[sg.Text('State Machine Example', font='_ 14')],
- [sg.Text('Click Send to begin sequence')],
- [sg.Text('State:'), sg.Text(key='-STATE-')],
- [sg.Button('Send', key='-SEND-'), sg.Button('Exit')]]
-
- window = sg.Window('State Machine Example', layout, font='Any 12')
-
- window_send = None
- state = State.stopped
-
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- if event == '-SEND-':
- state = State.start
- elif event == NEXT_STATE:
- state = values[event]
-
- window['-STATE-'].update(state)
- if window_send:
- window_send.refresh()
-
- # ----- STATE MACHINE PROCESSING -----
- if state == State.start:
- window['-SEND-'].update(disabled=True)
- window_send = make_send_window()
- window.write_event_value(NEXT_STATE, State.delay_3_sec)
- elif event == sg.TIMER_KEY and state == State.delay_3_sec: # be sure the if with the timer check AND state is above if with only state
- window.write_event_value(NEXT_STATE, State.close_win)
- elif state == State.delay_3_sec:
- window.timer_start(TIMER1, repeating=False)
- elif state == State.close_win:
- window_send.close()
- window_send = None
- window.write_event_value(NEXT_STATE, State.delay_2_sec)
- elif event == sg.TIMER_KEY and state == State.delay_2_sec:
- window.write_event_value(NEXT_STATE, State.enable_send)
- elif state == State.delay_2_sec:
- window.timer_start(TIMER2, repeating=False)
- elif state == State.enable_send:
- window['-SEND-'].update(disabled=False)
- window.write_event_value(NEXT_STATE, State.stopped)
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Timer_Periodic.py b/DemoPrograms/Demo_Timer_Periodic.py
deleted file mode 100644
index 3b4fd54a7..000000000
--- a/DemoPrograms/Demo_Timer_Periodic.py
+++ /dev/null
@@ -1,113 +0,0 @@
-import PySimpleGUI as sg
-import time
-
-"""
- Demo Program - Periodic Timer Event
-
- How to use a thread to generate an event every x seconds
-
- One method of getting periodic timer event that's more predictable than using window.read(timeout=x)
- The problem with using a timeout with window.read is that if any event happens prior to the timer
- expiring, the timer event will not happen. The timeout parameter is not designed to provide a "heartbeat"
- type of timer but rather to guarantee you will get an event within that amount of time, be it a
- user-caused event or a timeout.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-timer_running = {}
-
-
-def timer_status_change(timer_id, start=None, stop=None, delete=None):
- """
- Encapsulates/manages the timers dictionary
-
- :param timer_id: ID of timer to change status
- :type timer_id: int
- :param start: Set to True when timer is started
- :type start: bool
- :param stop: Set to True when timer is stopped
- :type stop: bool
- :param delete: Set to True to delete a timer
- :type delete bool
- """
- global timer_running
-
- if start:
- timer_running[timer_id] = True
- if stop:
- timer_running[timer_id] = False
- if delete:
- del timer_running[timer_id]
-
-
-def timer_is_running(timer_id):
- """
-
- :param timer_id: The timer ID to check
- :type timer_id: int
- :return: True if the timer is running
- :rtype: bool
- """
- if timer_running[timer_id]:
- return True
- return False
-
-
-
-def periodic_timer_thread(window, interval, timer_id):
- """
- Thread that sends messages to the GUI after some interval of time
-
- :param window: Window the events will be sent to
- :type window: sg.Window
- :param interval: How frequently to send an event
- :type interval: float
- :param timer_id: A timer identifier
- :type timer_id: int
- """
-
-
- while True:
- time.sleep(interval) # sleep until time to send a timer event
- window.write_event_value(('-THREAD-', '-TIMER EVENT-'), timer_id)
- if not timer_is_running(timer_id): # If timer has been stopped, delete it and return from thread
- timer_status_change(timer_id, delete=True)
- return
-
-
-def main():
- layout = [[sg.Text('Window with periodic time events')],
- [sg.Text(key='-MESSAGE-')],
- [sg.Text('Timer Status:'), sg.Text(key='-TIMER STATUS-')],
- [sg.Text('Duration:'), sg.In(s=3, key='-DURATION-'), sg.Button('Start')],
- [sg.Text('Timer ID:'), sg.In(s=3, key='-STOP ID-'), sg.Button('Stop'),],
- [ sg.Button('Dummy'), sg.Button('Exit')], ]
-
- window = sg.Window('Blinking LED Window', layout)
-
- timer_counter = 0
- # --------------------- EVENT LOOP ---------------------
- while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- window['-MESSAGE-'].update(f'{event} {values}')
- window['-TIMER STATUS-'].update(f'{timer_running}')
- if event == 'Start':
- if values['-DURATION-']:
- timer_status_change(timer_counter, start=True)
- window.start_thread(lambda: periodic_timer_thread(window, float(values['-DURATION-']), timer_counter), ('-THREAD-', '-THREAD ENDED-'))
- timer_counter += 1
- else:
- window['-MESSAGE-'].update('Please enter a numeric duration')
- elif event == 'Stop':
- if values['-STOP ID-']:
- timer_status_change(int(values['-STOP ID-']), stop=True)
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Titlebar_Custom_Async.py b/DemoPrograms/Demo_Titlebar_Custom_Async.py
deleted file mode 100644
index bc3396b18..000000000
--- a/DemoPrograms/Demo_Titlebar_Custom_Async.py
+++ /dev/null
@@ -1,119 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Custom Titlebar - Async Version
-
- Demo showing how to remove the titlebar and replace with your own
- Unlike previous demos that lacked a titlebar, this one provides a way for you
- to "minimize" your window that does not have a titlebar. This is done by faking
- the window using a hidden window that is minimized.
-
- While this demo uses the button colors for the titlebar color, you can use anything you want.
- If possible it could be good to use combinations that are known to match like the input element colors
- or the button colors.
-
- This version of the demo allows for async execution of your code. In another demo of this
- custom titlebar idea, the user window would stop when the window is minimized. This is OK
- for most applications, but if you're running a window with a timeout value (an async window)
- then stopping execution when the window is minimized is not good.
-
- The way to achieve both async window and the custom titlebar is to use the "read_all_windows"
- function call. Using this function with a timeout has the same effect as running your
- window.read with a timeout.
-
- Additionally, if you right click and choose "close" on the minimized window on your
- taskbar, now the program will exist rather than restoring the window like the other demo does.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def minimize_main_window(main_window):
- """
- Creates an icon on the taskbar that represents your custom titlebar window.
- The FocusIn event is set so that if the user restores the window from the taskbar.
- If this window is closed by right clicking on the icon and choosing close, then the
- program will exit just as if the "X" was clicked on the main window.
- """
- main_window.hide()
- layout = [[sg.T('This is your window with a customized titlebar... you just cannot see it')]]
- window = sg.Window(main_window.Title, layout, finalize=True, alpha_channel=0)
- window.minimize()
- window.bind('', '-RESTORE-')
- # store the dummy window as a function property
- minimize_main_window.dummy_window = window
-
-
-def restore_main_window(main_window):
- """
- Call this function when you want to restore your main window
-
- :param main_window:
- :return:
- """
- if hasattr(minimize_main_window, 'dummy_window'):
- minimize_main_window.dummy_window.close()
- minimize_main_window.dummy_window = None
- main_window.un_hide()
-
-
-def title_bar(title, text_color, background_color):
- """
- Creates a "row" that can be added to a layout. This row looks like a titlebar
- :param title: The "title" to show in the titlebar
- :type title: str
- :return: A list of elements (i.e. a "row" for a layout)
- :type: List[sg.Element]
- """
- bc = background_color
- tc = text_color
-
- return [sg.Col([[sg.T(title, text_color=tc, background_color=bc)]], pad=(0, 0), background_color=bc),
- sg.Col([[sg.T('_', text_color=tc, background_color=bc, enable_events=True, key='-MINIMIZE-'),
- sg.Text('❎', text_color=tc, background_color=bc, enable_events=True, key='Exit')]], element_justification='r', key='-TITLEBAR-',
- pad=(0, 0), background_color=bc)]
-
-
-def main():
- # sg.theme('light green 3')
- # sg.theme('dark red')
- # sg.theme('dark green 3')
- sg.theme('light brown 10')
-
- title = 'Customized Titlebar Window'
- # Here the titlebar colors are based on the theme. A few suggestions are shown. Try each of them
- layout = [title_bar(title, sg.theme_button_color()[0], sg.theme_button_color()[1]),
- # title_bar(title, sg.theme_button_color()[1], sg.theme_slider_color()),
- # title_bar(title, sg.theme_slider_color(), sg.theme_button_color()[0]),
- [sg.T('This is normal window text. The above is the fake "titlebar"')],
- [sg.T('Input something:')],
- [sg.Input(key='-IN-'), sg.Text(size=(12, 1), key='-OUT-')],
- [sg.Button('Go')]]
-
- window_main = sg.Window(title, layout, resizable=True, no_titlebar=True, grab_anywhere=True, keep_on_top=True, margins=(0, 0), finalize=True)
-
- window_main['-TITLEBAR-'].expand(True, False, False) # expand the titlebar's rightmost column so that it resizes correctly
- counter = 0
- while True: # Event Loop
- window, event, values = sg.read_all_windows(timeout=100)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- # ------ events to handle minimize and restore of window ------
- if event == '-MINIMIZE-':
- minimize_main_window(window_main)
- continue
- elif event == '-RESTORE-' or (event == sg.WINDOW_CLOSED and window != window_main):
- restore_main_window(window_main)
- continue
-
- # ------ remainder of your "normal" events and window code ------
- window_main['-OUT-'].update(counter)
- counter += 1
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py b/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py
deleted file mode 100644
index bb7071dbc..000000000
--- a/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py
+++ /dev/null
@@ -1,107 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo showing how to remove the titlebar and replace with your own
- Unlike previous demos that lacked a titlebar, this one provides a way for you
- to "minimize" your window that does not have a titlebar. This is done by faking
- the window using a hidden window that is minimized.
-
- While this demo uses the button colors for the titlebar color, you can use anything you want.
- If possible it could be good to use combinations that are known to match like the input element colors
- or the button colors.
-
- This code eventually grew into the internal implementation of the Titlebar element. It's a good example
- of how user code is just as powerful as internal PySimpleGUI code.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-# If not running 4.28.0.4+ that has the DarkGrey8 theme, then uncomment to get it added.
-DarkGrey8 = {'BACKGROUND': '#19232D',
- 'TEXT': '#ffffff',
- 'INPUT': '#32414B',
- 'TEXT_INPUT': '#ffffff',
- 'SCROLL': '#505F69',
- 'BUTTON': ('#ffffff', '#32414B'),
- 'PROGRESS': ('#505F69', '#32414B'),
- 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
- }
-
-sg.theme_add_new('DarkGrey8', DarkGrey8)
-
-sg.theme('DarkGrey8')
-
-def dummy_minimized_window(title):
- """
- Creates an invisible window that is minimized to the taskbar
- As soon as something happens to the window, it is closed and the function
- returns.
- The FocusIn event is set so that if the user restores the window from the taskbar, then the read
- wille return, the window will be closed, and the function will return
- """
-
- layout = [[sg.T('This is your window with a customized titlebar... you just cannot see it')]]
- window = sg.Window(title, layout, finalize=True, alpha_channel=0)
- window.minimize()
- window.bind('', '-FOCUS-')
- window.read(close=True)
-
-
-def title_bar(title, text_color, background_color):
- """
- Creates a Column element meant to be used as a single row. This row looks like a titlebar.
- :param title: The "title" to show in the titlebar
- :type title: str
- :return: A single Column element that can be used as a single row in your layout
- :type: sg.Column
- """
- bc = background_color
- tc = text_color
-
- return sg.Col([[sg.Col(
- [[sg.T(title,text_color=tc, background_color=bc, grab=True, expand_x=True)]],
- pad=(0, 0), background_color=bc, expand_x=True),
- sg.Col(
- [[sg.T('_', text_color=tc, background_color=bc, enable_events=True, key='-MINIMIZE-'),sg.Text('❎', text_color=tc, background_color=bc, enable_events=True, key='Exit')]],
- element_justification='r', key='-C-', pad=(0, 0), expand_x=True, background_color=bc, grab=True)]],
- pad=(0,0), grab=True, expand_x=True)
-
-
-
-
-def main():
- # sg.theme('light green 3')
- # sg.theme('dark red')
- sg.theme('DarkGrey8')
-
- title = 'Customized Titlebar Window'
- # Here the titlebar colors are based on the theme. A few suggestions are shown. Try each of them
- layout = [ [title_bar(title, sg.theme_button_color()[0], sg.theme_button_color()[1])],
- # [title_bar(title, sg.theme_button_color()[1], sg.theme_slider_color())],
- # [title_bar(title, sg.theme_slider_color(), sg.theme_button_color()[0])],
- [sg.T('This is normal window text. The above is the fake "titlebar"')],
- [sg.T('Input something:')],
- [sg.Input(key='-IN-'), sg.Text(size=(12,1), key='-OUT-')],
- [sg.Button('Go')]]
-
- window = sg.Window(title, layout, resizable=True, no_titlebar=True, keep_on_top=True, margins=(0,0), finalize=True)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-MINIMIZE-':
- window.hide()
- dummy_minimized_window(window.Title)
- window.un_hide()
- if event == 'Go':
- window['-OUT-'].update(values['-IN-'])
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py b/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py
deleted file mode 100644
index 8e7d5137a..000000000
--- a/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py
+++ /dev/null
@@ -1,154 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Titlebar Multiple Combintions - how to make a custom titlebar with different color options
-
- Demo showing how to remove the titlebar and replace with your own
- Unlike previous demos that lacked a titlebar, this one provides a way for you
- to "minimize" your window that does not have a titlebar. This is done by faking
- the window using a hidden window that is minimized.
-
- Use the "theme" calls to experiment with the color combinations to get to the colors you like. With themes, there
- are pairs of colors that usually match well. You're shown each of these combinations to help you decide which you
- like the best. These color combinations are shown to you one by one as you click the "next" button:
-
- ['1 - Button Colors', sg.theme_button_color()[0], sg.theme_button_color()[1]],
- ['2 - Reversed Button Colors', sg.theme_button_color()[1], sg.theme_button_color()[0]],
- ['3 - Input Colors', sg.theme_input_text_color(), sg.theme_input_background_color()],
- ['4 - Reversed Input Colors', sg.theme_input_background_color(), sg.theme_input_text_color()],
- ['5 - Reversed background & Text', sg.theme_background_color(), sg.theme_text_color()],
- ['6 - Button Background & Slider', sg.theme_button_color()[1], sg.theme_slider_color()],
- ['7 - Slider & Button Text', sg.theme_slider_color(), sg.theme_button_color()[0]],
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def dummy_minimized_window(title):
- """
- Creates an invisible window that is minimized to the taskbar
- As soon as something happens to the window, it is closed and the function
- returns.
- The FocusIn event is set so that if the user restores the window from the taskbar, then the read
- wille return, the window will be closed, and the function will return
- """
-
- layout = [[sg.T('This is your window with a customized titlebar... you just cannot see it')]]
- window = sg.Window(title, layout, finalize=True, alpha_channel=0)
- window.minimize()
- window.bind('', '-FOCUS-')
- window.read(close=True)
-
-
-def title_bar(title, text_color, background_color):
- """
- Creates a "row" that can be added to a layout. This row looks like a titlebar
- :param title: The "title" to show in the titlebar
- :type title: str
- :param text_color: Text color for titlebar
- :type text_color: str
- :param background_color: Background color for titlebar
- :type background_color: str
- :return: A list of elements (i.e. a "row" for a layout)
- :rtype: List[sg.Element]
- """
- bc = background_color
- tc = text_color
- font = 'Helvetica 12'
-
- return [sg.Col([[sg.T(title, text_color=tc, background_color=bc, font=font, grab=True)]], pad=(0, 0), background_color=bc),
- sg.Col([[sg.T('_', text_color=tc, background_color=bc, enable_events=True, font=font, key='-MINIMIZE-'),
- sg.Text('❎', text_color=tc, background_color=bc, font=font, enable_events=True, key='Exit')]], element_justification='r', key='-C-', expand_x=True, grab=True,
- pad=(0, 0), background_color=bc)]
-
-
-def create_window(title, bar_text_color, bar_background_color):
- """
- Creates a window using the title and colors provided to make the titlebar
- :return: A window with a custom titlebar using specificied colors
- :rtype: sg.Window
- """
-
- layout = [
- title_bar(title, bar_text_color, bar_background_color),
-
- [sg.T('This is normal window text. The above is the fake "titlebar"')],
- [sg.T('Input something:')],
- [sg.Input('Color of input text', focus=True, key='-IN-'), sg.Text(size=(12, 1), key='-OUT-')],
- [sg.Button('Go'), sg.Button('Next'), sg.B('New Theme'), sg.Button('Exit')]]
-
- window = sg.Window(title, layout, resizable=True, no_titlebar=True, grab_anywhere=False, keep_on_top=True, margins=(0, 0), finalize=True)
-
- # window['-C-'].expand(True, False, False) # expand the titlebar's rightmost column so that it resizes correctly
-
- return window
-
-
-def choose_theme():
- layout = [[sg.Text('Custom Titlebar Demo', font='Any 14')],
- [sg.Text('This program requires version 4.28.0.20 and later')],
- [sg.Text('Click a look and feel color to see demo window')],
- [sg.Listbox(values=sg.theme_list(),
- size=(20, 20), key='-LIST-', enable_events=True)],
- [sg.Button('Choose')]]
-
- window = sg.Window('Look and Feel Browser', layout)
-
- while True: # Event Loop
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Choose'):
- break
-
- window.close()
- if event is None:
- theme = sg.theme()
- else:
- theme = values['-LIST-'][0]
-
- sg.theme(theme)
- color_pairs = [['1 - Button Colors', sg.theme_button_color()[0], sg.theme_button_color()[1]],
- ['2 - Reversed Button Colors', sg.theme_button_color()[1], sg.theme_button_color()[0]],
- ['3 - Input Colors', sg.theme_input_text_color(), sg.theme_input_background_color()],
- ['4 - Reversed Input Colors', sg.theme_input_background_color(), sg.theme_input_text_color()],
- ['5 - Reversed background & Text', sg.theme_background_color(), sg.theme_text_color()],
- ['6 - Button Background & Slider', sg.theme_button_color()[1], sg.theme_slider_color()],
- ['7 - Slider & Button Text', sg.theme_slider_color(), sg.theme_button_color()[0]], ]
-
- return theme, color_pairs
-
-
-def main():
- theme, color_pairs = choose_theme()
-
- index = 0
- window = create_window('{} - {}'.format(color_pairs[index][0],theme), color_pairs[index][1], color_pairs[index][2])
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event.startswith('Exit'):
- break
- if event == '-MINIMIZE-':
- window.hide()
- dummy_minimized_window(window.Title)
- window.un_hide()
- window.force_focus()
- elif event == 'Go':
- window['-OUT-'].update(values['-IN-'])
- elif event == 'Next':
- window.close()
- index = (index + 1) % len(color_pairs)
- window = create_window('{} - {}'.format(color_pairs[index][0],theme), color_pairs[index][1], color_pairs[index][2])
- elif event == 'New Theme':
- window.close()
- theme, color_pairs = choose_theme()
- index = 0
- window = create_window('{} - {}'.format(color_pairs[index][0],theme), color_pairs[index][1], color_pairs[index][2])
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Titlebar_Element.py b/DemoPrograms/Demo_Titlebar_Element.py
deleted file mode 100644
index e1d76c14d..000000000
--- a/DemoPrograms/Demo_Titlebar_Element.py
+++ /dev/null
@@ -1,47 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- The Custom Titlebar Demo
- 3 ways of getting a custom titlebar:
- 1. set_options - will create a titlebar that every window will have based on theme
- 2. Titlebar element - Adds custom titlebar to your window
- 3. use_custom_titlebar parameter - Add to your Window object
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-
-"""
-
-# sg.set_options(use_custom_titlebar=True)
-# sg.set_options(titlebar_background_color='red', titlebar_text_color='white', titlebar_font='courier 12', )
-
-
-
-def main():
- layout = [
- # [sg.Titlebar('My Custom Titlebar', background_color='light blue', text_color='red', k='-T-')],
- [sg.Text('My Window')],
- [sg.Input(k='-IN1-')],
- [sg.Input(k='-IN2-')],
- [sg.Input(k='-IN3-')],
- [sg.Button('Clear'), sg.Button('Popup'), sg.Button('Exit')]]
-
- # Use the same title so that when the window minimizes, the title will be the same as the custom titlebar title
- # window = sg.Window('My Custom Titlebar', layout)
- window = sg.Window('My Custom Titlebar', layout, use_custom_titlebar=True)
-
- while True:
- event, values = window.read()
- print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- elif event == 'Clear':
- [window[k]('') for k in ('-IN1-', '-IN2-', '-IN3-')]
- elif event == 'Popup':
- sg.popup('This is a popup')
-
- window.close()
-
-
-main()
diff --git a/DemoPrograms/Demo_Tooltips.py b/DemoPrograms/Demo_Tooltips.py
deleted file mode 100644
index f31f3da69..000000000
--- a/DemoPrograms/Demo_Tooltips.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-"""
- Example tooltip operations.
- Removal of tooltips feature added in version 5.0.2.11
- You disable a tooltip by using the remove_tooltip method or set the tooltip to the value None
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-import PySimpleGUI as sg
-
-layout = [ [sg.Text('Tooltip Operations')],
- [sg.Input(key='-IN-', tooltip='My default tooltip')],
- [sg.Text(key='-OUT-')],
- [sg.Button('Remove'), sg.B('Add'), sg.B('Set None'), sg.Button('Exit')] ]
-
-window = sg.Window('Tooltip Test', layout, print_event_values=True)
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Remove':
- window['-IN-'].remove_tooltip()
- window['-OUT-'].update('Tooltip removed')
- elif event == 'Add':
- window['-IN-'].set_tooltip(values['-IN-'])
- window['-OUT-'].update(f"Added tooltip {values['-IN-']}")
- elif event == 'Set None':
- window['-IN-'].set_tooltip(None)
- window['-OUT-'].update('Tooltip set to None')
-
-window.close()
diff --git a/DemoPrograms/Demo_Touch_Keyboard.py b/DemoPrograms/Demo_Touch_Keyboard.py
index b279f2de5..48abb7119 100644
--- a/DemoPrograms/Demo_Touch_Keyboard.py
+++ b/DemoPrograms/Demo_Touch_Keyboard.py
@@ -2,10 +2,6 @@
'''
Example of on-screen keyboard.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
'''
class keyboard():
@@ -92,7 +88,7 @@ def run(self):
self.keyboard.update(self.focus)
if event == 'keyboard':
self.keyboard.togglevis()
- elif event == 'close' or event == sg.WIN_CLOSED:
+ elif event == 'close' or event is None:
break
self.keyboard.close()
self.mainWindow.Close()
diff --git a/DemoPrograms/Demo_Tree_Element.py b/DemoPrograms/Demo_Tree_Element.py
index 2d5c62a5c..554477ece 100644
--- a/DemoPrograms/Demo_Tree_Element.py
+++ b/DemoPrograms/Demo_Tree_Element.py
@@ -3,17 +3,11 @@
import os
import PySimpleGUI as sg
-sg.theme('light brown 8')
-
-
"""
- Demo program that will display a folder hierarchy with icons for the folders and files.
- Note that if you are scanning a large folder then tkinter will eventually complain about too many bitmaps.
- This can be fixed easily enough by reusing the images within PySimpleGUI (enhancement request can be opened if you hit this problem)
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
+ A PySimpleGUI or PySimpleGUIQt demo program that will display a folder heirarchy with icons for the folders and files.
+ Note that if you are scanning a large folder then tkinter will eventually complain abouit too many bitmaps and crash
+ Getting events back from clicks on the entries works for PySimpleGUI, but appears to not be implemented in PySimpleGUIQt
+ If you need tree events using PySimpleGUIQt then post an Issue on the GitHub http://www.PySimpleGUI.com
"""
# Base64 versions of images of a folder and a file. PNG files (may not work with PySimpleGUI27, swap with GIFs)
@@ -37,31 +31,32 @@ def add_files_in_folder(parent, dirname):
treedata.Insert(parent, fullname, f, values=[], icon=folder_icon)
add_files_in_folder(fullname, fullname)
else:
- treedata.Insert(parent, fullname, f, values=[os.stat(fullname).st_size], icon=file_icon)
+
+ treedata.Insert(parent, fullname, f, values=[
+ os.stat(fullname).st_size], icon=file_icon)
+
add_files_in_folder('', starting_path)
+
layout = [[sg.Text('File and folder browser Test')],
[sg.Tree(data=treedata,
headings=['Size', ],
auto_size_columns=True,
- select_mode=sg.TABLE_SELECT_MODE_EXTENDED,
num_rows=20,
- col0_width=40,
- col0_heading='Files & Folders',
+ col0_width=30,
key='-TREE-',
show_expanded=False,
- enable_events=True,
- expand_x=True,
- expand_y=True,
- ),],
+ enable_events=True),
+ ],
[sg.Button('Ok'), sg.Button('Cancel')]]
-window = sg.Window('Tree Element Test', layout, resizable=True, finalize=True)
+window = sg.Window('Tree Element Test', layout)
+
while True: # Event Loop
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Cancel'):
+ if event in (None, 'Cancel'):
break
print(event, values)
window.close()
diff --git a/DemoPrograms/Demo_Turtle.py b/DemoPrograms/Demo_Turtle.py
index bb1ebc749..3c778061c 100644
--- a/DemoPrograms/Demo_Turtle.py
+++ b/DemoPrograms/Demo_Turtle.py
@@ -9,10 +9,6 @@
Get the tkinter Canvas from the Canvas element
Draw on the tkinter Canvas using turtle commands.
Results are shown on the canvas immiedately after button press / drawing command
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
@@ -32,7 +28,7 @@
while True: # Event Loop
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event == 'F':
diff --git a/DemoPrograms/Demo_Unicode_Characters.py b/DemoPrograms/Demo_Unicode_Characters.py
deleted file mode 100644
index 6c21c45a3..000000000
--- a/DemoPrograms/Demo_Unicode_Characters.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-from random import randint as randint
-
-"""
- To get a good display of the unicode characters visit https://en.wikipedia.org/wiki/List_of_Unicode_characters
- You can directly copy and paste characters from the site into your strings.
- Unicode characters make it possible to add simple graphics to your windows by using text. No Base64 required. They're plain chars.
- They're good for a quick status display / dashboard, for use on buttons (arrows), or as "simple clipart" to name a few uses
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('Light Brown 4')
-
-SQUARE = '█'
-CIRCLE = '⚫'
-CIRCLE_OUTLINE = '◯'
-UP = '▲'
-RIGHT = '►'
-DOWN = '▼'
-LEFT = '◄'
-ROAD = '⛖'
-
-layout = [ [sg.Text('Unicode Characters Demo', font='Def 16')],
- [sg.T('Network Status', size=(12,1)), sg.Text(size=(10,1), font='Default 18', text_color='green', key='-OUT1-')],
- [sg.T('Gas Level', size=(12,1)), sg.Text(size=(10,1), font='Default 18', text_color='green', key='-OUT2-')],
- [sg.T('Oil Temp', size=(12,1)), sg.Text(size=(10,1), font='Default 18', text_color='blue', key='-OUT3-')],
- [sg.T('Status4', size=(12,1)), sg.Text(CIRCLE, size=(10,1), font='Default 18', text_color='green', key='-OUT4-')],
- [sg.T('Status5', size=(12,1)), sg.Text(CIRCLE_OUTLINE, size=(10,1), font='Default 18', text_color='green', key='-OUT5-')],
- [sg.Frame('Unicode Converter',
- [[sg.T('Enter a Number'), sg.In(size=(6,1), key='-NUM-'), sg.T('Unicode char: '), sg.I(size=(2,1), font='Any 18', key='-OUT CHAR-')],
- [sg.T('Enter a Char'), sg.In(size=(2,1), key='-CHAR-', font='Any 18'), sg.T('Unicode number: '), sg.T(size=(6,1), key='-OUT NUM-')]])],
- [sg.Frame('Display Unicode Characters In Range',
- [[sg.T('Starting Number'), sg.In(size=(6, 1), key='-START-'), sg.T('Ending Number char: '), sg.I(size=(6, 1), key='-END-')],
- [sg.B('Display Chars', bind_return_key=True), sg.T('Display Font Size'), sg.Spin(list(range(10,25)), initial_value=18, font='Any 14', key='-FONTSIZE-')],
- ])],
- [sg.Multiline(size=(30,10), font='Any 18',key='-MLINE-'+sg.WRITE_ONLY_KEY)],
- [sg.B(UP), sg.B(DOWN), sg.B(LEFT), sg.B(RIGHT), sg.B('Exit')] ]
-
-window = sg.Window('Window Title', layout)
-
-i = j = 0
-multiline_font_size = 18
-while True:
- event, values = window.read(timeout=200)
- print(f'{event} - {values}') if event != sg.TIMEOUT_KEY else None
- if event in (sg.WIN_CLOSED, 'Exit'): # always, always give a way out!
- break
- elif event == RIGHT:
- window['-OUT2-'](text_color='blue')
- window['-OUT5-']((UP,DOWN,RIGHT,LEFT)[j%4])
- window['-OUT5-'](chr(ord(ROAD)+j))
- j = j +1
- elif event == LEFT:
- window['-OUT2-'](text_color='yellow')
- elif event == UP:
- window['-OUT1-'](text_color='green')
- window['-OUT3-'](text_color='green')
- window['-OUT4-'](text_color='green')
- elif event == DOWN:
- window['-OUT1-'](text_color='red')
- window['-OUT3-'](text_color='red')
- window['-OUT4-'](text_color='red')
- elif event.startswith('Display'): # process the dump range section
- try:
- for c in range(int(values['-START-']), int(values['-END-'])):
- window['-MLINE-'+sg.WRITE_ONLY_KEY](chr(c), append=True, text_color_for_value='red')
- window.refresh()
- sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, 'Writing chars to display', text_color='red', font='Any 20', time_between_frames=100)
- except: pass
- sg.popup_animated(None)
-
- window['-OUT1-']('◯' if i % randint(1,3) else '⚫')
- window['-OUT2-'](SQUARE * (i%10))
- window['-OUT3-'](SQUARE * (7-(i%8)))
-
- if multiline_font_size != int(values['-FONTSIZE-']):
- window['-MLINE-'+sg.WRITE_ONLY_KEY](font='Any '+ str(values['-FONTSIZE-']))
- multiline_font_size = int(values['-FONTSIZE-'])
-
- if not i % 15:
- window['-OUT1-'](text_color='red')
- i += 1
- # Output stuff for Unicode Converter Section
- try:
- window['-OUT CHAR-'](chr(int(values['-NUM-'])))
- except: pass
- try:
- window['-OUT NUM-'](ord(values['-CHAR-']))
- except: pass
-
-window.close()
diff --git a/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py b/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py
deleted file mode 100644
index 02b4b0c41..000000000
--- a/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py
+++ /dev/null
@@ -1,59 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Setting API to save and load a window's contents
-
- The PySimpleGUI "User Settings API" is a simple interface to JSON and Config Files.
- If you're thinking of storying information in a JSON file, consider using the PySimpleGUI
- User Settings API calls. They make JSON files act like dictionaries. There's no need
- to load nor save as that's done for you.
-
- There are 2 interfaces to the User Settings API.
- 1. Function calls - sg.user_settings
- 2. UserSettings Object - Uses a simple class interface
-
- Note that using the Object/class interface does not require you to write a class. If you're using
- PySimpleGUI, you are already using many different objects. The Elements & Window are objects.
-
- In this demo, a UserSetting object is used to save the values from Input elements into a JSON file.
- You can also re-loda the values from the JSON into your window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# Create a UserSettings object. The JSON file will be saved in the same folder as this .py file
-window_contents = sg.UserSettings(path='.', filename='mysettings.json')
-
-def main():
- layout = [ [sg.Text('My Window')],
- [sg.Input(key='-IN1-')],
- [sg.Input(key='-IN2-')],
- [sg.Input(key='-IN3-')],
- [sg.Input(key='-IN4-')],
- [sg.Input(key='-IN5-')],
- [sg.Button('Save'), sg.Button('Load'), sg.Button('Exit')] ]
-
- window = sg.Window('Save / Load Inputs Using User Settings API', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
- # To SAVE the values, loop through all elements in the values dictionary and save their values
- if event == 'Save':
- for key in values:
- window_contents[key] = values[key]
- # To LOAD values from a settings file into a window, loop through values dictionary and update each element
- if event == 'Load':
- for key in values:
- saved_value = window_contents[key]
- window[key].update(saved_value)
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_User_Settings.py b/DemoPrograms/Demo_User_Settings.py
deleted file mode 100644
index 3525ed010..000000000
--- a/DemoPrograms/Demo_User_Settings.py
+++ /dev/null
@@ -1,110 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Settings
-
- Use the "user_settings" API calls to make a "settings window"
-
- This demo is very basic. The user_settings functions are used directly without a lookup table
- or some other mechanism to map between PySimpleGUI keys and user settings keys.
-
- Two windows are shown. One is a super-simple "save previously entered filename"
- The other is a larger "settings window" where multiple settings are saved/loaded
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-SETTINGS_PATH = '.'
-
-
-def make_window():
- """
- Creates a new window. The default values for some elements are pulled directly from the
- "User Settings" without the use of temp variables.
-
- Some get_entry calls don't have a default value, such as theme, because there was an initial call
- that would have set the default value if the setting wasn't present. Could still put the default
- value if you wanted but it would be 2 places to change if you wanted a different default value.
-
- Use of a lookup table to map between element keys and user settings could be aded. This demo
- is intentionally done without one to show how to use the settings APIs in the most basic,
- straightforward way.
-
- If your application allows changing the theme, then a make_window function is good to have
- so that you can close and re-create a window easily.
-
- :return: (sg.Window) The window that was created
- """
-
- sg.theme(sg.user_settings_get_entry('-theme-', 'DarkBlue2')) # set the theme
-
- layout = [[sg.Text('Settings Window')],
- [sg.Input(sg.user_settings_get_entry('-input-', ''), k='-IN-')],
- [sg.Listbox(sg.theme_list(), default_values=[sg.user_settings_get_entry('theme')], size=(15, 10), k='-LISTBOX-')],
- [sg.CB('Option 1', sg.user_settings_get_entry('-option1-', True), k='-CB1-')],
- [sg.CB('Option 2', sg.user_settings_get_entry('-option2-', False), k='-CB2-')],
- [sg.T('Settings file = ' + sg.user_settings_filename())],
- [sg.Button('Save'), sg.Button('Exit without saving', k='Exit')]]
-
- return sg.Window('A Settings Window', layout)
-
-
-def settings_window():
- """
- Create and interact with a "settings window". You can a similar pair of functions to your
- code to add a "settings" feature.
- """
-
- window = make_window()
- current_theme = sg.theme()
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- if event == 'Save':
- # Save some of the values as user settings
- sg.user_settings_set_entry('-input-', values['-IN-'])
- sg.user_settings_set_entry('-theme-', values['-LISTBOX-'][0])
- sg.user_settings_set_entry('-option1-', values['-CB1-'])
- sg.user_settings_set_entry('-option2-', values['-CB2-'])
-
- # if the theme was changed, restart the window
- if values['-LISTBOX-'][0] != current_theme:
- current_theme = values['-LISTBOX-'][0]
- window.close()
- window = make_window()
-
-
-def save_previous_filename_demo():
- """
- Saving the previously selected filename....
- A demo of one of the likely most popular use of user settings
- * Use previous input as default for Input
- * When a new filename is chosen, write the filename to user settings
- """
-
- # Notice that the Input element has a default value given (first parameter) that is read from the user settings
- layout = [[sg.Text('Enter a filename:')],
- [sg.Input(sg.user_settings_get_entry('-filename-', ''), key='-IN-'), sg.FileBrowse()],
- [sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]]
-
- window = sg.Window('Filename Example', layout)
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- elif event == 'Save':
- sg.user_settings_set_entry('-filename-', values['-IN-'])
-
- window.close()
-
-
-if __name__ == '__main__':
- sg.user_settings_filename(path=SETTINGS_PATH) # Set the location for the settings file
- # Run a couple of demo windows
- save_previous_filename_demo()
- settings_window()
diff --git a/DemoPrograms/Demo_User_Settings_As_Simple_Database.py b/DemoPrograms/Demo_User_Settings_As_Simple_Database.py
deleted file mode 100644
index 4ba9906e4..000000000
--- a/DemoPrograms/Demo_User_Settings_As_Simple_Database.py
+++ /dev/null
@@ -1,68 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Settings as a Database
-
- The PySimpleGUI User Settings APIs are implemnted to look like a dictionary to the
- user and utilize JSON files to store the data. As a result, one "key" is used to
- store and retrieve each "setting". This capability cab be used to implement a
- simple database.
-
- In this demo the User Settings file is used to store a user ID and data associated
- with that ID. Each User ID has a dictionary stored in the User Settings file. This
- dictionary is built from the values dictionary of the window. There is a map varaible
- called data_map that translates between the two dictionaries.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def get_id_data(user_setting, id):
- return user_setting[id]
-
-def main():
- # Maps between keys used in the User Settings an the Window itself
- data_map = {'-name-': '-NAME-', '-password-': '-PASSWORD-', '-dept-': '-DEPT-', '-security-': '-SECURITY-'}
- user_data = sg.UserSettings('my_user_data.json')
- INPUT_SIZE=30
- layout = [ [sg.Text('User ID Management')],
- [sg.Push(), sg.Text('User ID:'), sg.Input(key='-ID-', size=INPUT_SIZE)],
- [sg.Push(), sg.Text('Name:'), sg.Input(key='-NAME-', size=INPUT_SIZE,)],
- [sg.Push(), sg.Text('Password:'), sg.Input(key='-PASSWORD-', size=INPUT_SIZE, password_char='*')],
- [sg.Push(), sg.Text('Department:'), sg.Input(key='-DEPT-', size=INPUT_SIZE,)],
- [ sg.Text('Security Level:'), sg.Combo(('Low', 'Medium', 'High'), size=(INPUT_SIZE-2,3), readonly=True, default_value='Low', key='-SECURITY-')],
-
- [sg.Button('Add/Update'), sg.Button('Load'), sg.Button('Display'), sg.Button('Exit')] ]
-
- window = sg.Window('User Settings as Database', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- elif event == 'Add/Update':
- # Make a dictionary of data for the ID being added/updated based on the window's values
- user = values['-ID-']
- data = {}
- for setting_key, values_key in data_map.items():
- data[setting_key] = values[values_key]
- user_data[user] = data
- sg.popup(f'Added or updated user: {values["-ID-"]}')
- elif event == 'Load':
- user = values['-ID-']
- data = user_data[user]
- for setting_key, values_key in data_map.items():
- value = data[setting_key] if data is not None else ''
- window[values_key].update(value)
- elif event == 'Display':
- user = values['-ID-']
- data = user_data[user]
- output = f'Detailed User Information for ID: {user}\n'
- for setting_key, values_key in data_map.items():
- value = data[setting_key] if data is not None else ''
- output += f'{setting_key} = {value}\n'
- sg.popup_scrolled(output, title='Detailed User Data')
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py b/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py
deleted file mode 100644
index 316fff6df..000000000
--- a/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py
+++ /dev/null
@@ -1,57 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Setting API to automatically save and load Input Elements
-
- This Demo Program shows an easy way to add saving and loading of Input elements.
-
- The variable keys_to_save is used to determine which elements will be saved to the user settings file.
-
- The function make_key returns a dictionary that's used as keyword parameters that are passed to the Input elements. Using this technique allows the Input elements in the layout to benefit from the docstrings provided by PySimpleGUI. Another approach could be to use a function that returns an Input element, but that limits the flexibility for configuring Input elements.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-keys_to_save = ('-IN1-', '-IN2-', '-IN3-', '-IN4-')
-
-def make_key(key):
- """
- Returns a dictionary that is used to pass parameters to an Input element.
- Another approach could be to return an Input element. The downside to that approach is
- the lack of parameters and associated docstrings when creating the layout.
-
- :param key:
- :return: Dict
- """
- return {'default_text':sg.user_settings_get_entry(key, ''), 'key':key}
-
-
-def main():
- layout = [ [sg.Text('Automatically Load and Save Of Inputs', font='_ 15')],
- [sg.Text('Input 1'), sg.Input(**make_key('-IN1-'))],
- [sg.Text('Input 2'), sg.Input(**make_key('-IN2-'), background_color='green')],
- [sg.Text('Input 3'), sg.Input(**make_key('-IN3-'), text_color='blue')],
- [sg.Text('Input 4'), sg.Input(**make_key('-IN4-'), size=5)],
- [sg.Button('Exit (and save)', key='-EXIT SAVE-'), sg.Button('Exit without save')] ]
-
- window = sg.Window('Save / Load Inputs Using User Settings API', layout)
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit without save':
- sg.popup_quick_message('Exiting without save', text_color='white', background_color='red', font='_ 20')
-
- break
- elif event == '-EXIT SAVE-':
- sg.popup_quick_message('Saving settings & Exiting', text_color='white', background_color='red', font='_ 20')
- for key in keys_to_save:
- sg.user_settings_set_entry(key, values[key])
- break
-
- window.close()
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py b/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py
deleted file mode 100644
index a6617ec2b..000000000
--- a/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py
+++ /dev/null
@@ -1,75 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo of a Better File / Folder Input Window
-
- This construct is very common in PySimpleGUI.
- [sg.InputText(size=(50,1), key='-FILENAME-'), sg.FileBrowse()],
-
- The new user settings APIs can significantly improve the experience. Now instead of being
- shown a blank input element, the user is shown their previous entry and a history of their
- prior entries to choose from.
-
- Two new capabilities are presented in this demo
- 1. Recalling the last entry
- 2. Recalling a history of all of the previous entries as a Combo instead of Input Element
-
- The previous operations you're used to remain. You can paste a filename/full path into the combo.
- You can also use the browse button as before.
-
- But, you also get the 2 history features - last entry used, list of previous choices.
-
- If your window is not a 1-shot, add an event loop instead of a read with close paramter
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-# ------------------- 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('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('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('Filename History Clearable', layout)
-
-while True:
- event, values = window.read()
-
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- 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-'])
- window['-FILENAME-'].update(values=list(set(sg.user_settings_get_entry('-filenames-', []))))
- elif event == 'Clear':
- sg.user_settings_set_entry('-filenames-', [])
- sg.user_settings_set_entry('-last filename-', '')
- window['-FILENAME-'].update(values=[], value='')
diff --git a/DemoPrograms/Demo_User_Settings_Class.py b/DemoPrograms/Demo_User_Settings_Class.py
deleted file mode 100644
index 012139238..000000000
--- a/DemoPrograms/Demo_User_Settings_Class.py
+++ /dev/null
@@ -1,125 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Settings Using Class
-
- There are 2 interfaces for the User Settings APIs in PySimpleGUI.
- 1. Function calls
- 2. The UserSettings class
-
- This demo focuses on using the class interface. The advantage of using the class is that
- lookups resemble the syntax used for Python dictionaries
-
- This demo is very basic. The user_settings functions are used directly without a lookup table
- or some other mechanism to map between PySimpleGUI keys and user settings keys.
-
- Note that there are 2 coding conventions being used. The PySimpleGUI Demo Programs all use
- keys on the elements that are strings with the format '-KEY-'. They are upper case. The
- coding convention being used in Demo Programs that use User Settings use keys that have
- the same format, but are lower case. A User Settings key is '-key-'. The reason for this
- convention is so that you will immediately know what the string you are looking at is.
- By following this convention, someone reading the code that encounters '-filename-' will
- immediately recognize that this is a User Setting.
-
- Two windows are shown. One is a super-simple "save previously entered filename"
- The other is a larger "settings window" where multiple settings are saved/loaded
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-SETTINGS_PATH = '.'
-
-# create the settings object that will be used globally, but not need to change so not declared as global
-settings = sg.UserSettings(path=SETTINGS_PATH)
-
-def make_window():
- """
- Creates a new window. The default values for some elements are pulled directly from the
- "User Settings" without the use of temp variables.
-
- Some get_entry calls don't have a default value, such as theme, because there was an initial call
- that would have set the default value if the setting wasn't present. Could still put the default
- value if you wanted but it would be 2 places to change if you wanted a different default value.
-
- Use of a lookup table to map between element keys and user settings could be aded. This demo
- is intentionally done without one to show how to use the settings APIs in the most basic,
- straightforward way.
-
- If your application allows changing the theme, then a make_window function is good to have
- so that you can close and re-create a window easily.
-
- :return: (sg.Window) The window that was created
- """
-
- sg.theme(settings.get('-theme-', 'DarkBlue2')) # set the theme
-
- layout = [[sg.Text('Settings Window')],
- [sg.Input(settings.get('-input-', ''), k='-IN-')],
- [sg.Listbox(sg.theme_list(), default_values=[settings['-theme-'],], size=(15, 10), k='-LISTBOX-')],
- [sg.CB('Option 1', settings.get('-option1-', True), k='-CB1-')],
- [sg.CB('Option 2', settings.get('-option2-', False), k='-CB2-')],
- [sg.T('Settings file = ' + settings.get_filename())],
- [sg.Button('Save'), sg.Button('Settings Dictionary'), sg.Button('Exit without saving', k='Exit')]]
-
- window = sg.Window('A Settings Window', layout)
-
-
-def settings_window():
- """
- Create and interact with a "settings window". You can a similar pair of functions to your
- code to add a "settings" feature.
- """
-
- window = make_window()
- current_theme = sg.theme()
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- if event == 'Save':
- # Save some of the values as user settings
- settings['-input-'] = values['-IN-']
- settings['-theme-'] = values['-LISTBOX-'][0]
- settings['-option1-'] = values['-CB1-']
- settings['-option2-'] = values['-CB2-']
- elif event == 'Settings Dictionary':
- sg.popup(settings)
- # if a listbox item is selected and if the theme was changed, then restart the window
- if values['-LISTBOX-'] and values['-LISTBOX-'][0] != current_theme:
- current_theme = values['-LISTBOX-'][0]
- window.close()
- window = make_window()
-
-
-def save_previous_filename_demo():
- """
- Saving the previously selected filename....
- A demo of one of the likely most popular use of user settings
- * Use previous input as default for Input
- * When a new filename is chosen, write the filename to user settings
- """
-
- # Notice that the Input element has a default value given (first parameter) that is read from the user settings
- layout = [[sg.Text('Enter a filename:')],
- [sg.Input(settings.get('-filename-', ''), key='-IN-'), sg.FileBrowse()],
- [sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]]
-
- window = sg.Window('Filename Example', layout)
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- elif event == 'Save':
- settings['-filename-'] = values['-IN-']
-
- window.close()
-
-
-if __name__ == '__main__':
- # Run a couple of demo windows
- save_previous_filename_demo()
- settings_window()
diff --git a/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py b/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py
deleted file mode 100644
index fea6ed3eb..000000000
--- a/DemoPrograms/Demo_User_Settings_Class_Remember_Input_and_Combo.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Save previously entered strings for Input and Combo elements by using user_settings calls
-
- This demo is the same as the Demo_User_Settings_Remember_Input_and_Combo.py
- The difference between the 2 files is that this one users the UserSettings class syntax while the other uses the function calls.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- settings = sg.UserSettings(path='.') # The settings file will be in the same folder as this program
-
- layout = [[sg.T('This is your layout')],
- [sg.T('Enter or choose name'),
- sg.Combo(values=sorted(settings.get('-names-', [])),
- default_value=settings['-last name chosen-'],
- size=(20,1), k='-COMBO-')],
- [sg.T('Remembers last value'), sg.In(settings.get('-input-', ''), k='-INPUT-')],
- [sg.OK(), sg.Button('Exit')]]
-
- event, values = sg.Window('Pattern for saving with Combobox', layout).read(close=True)
-
- if event == 'OK':
- settings['-names-'] = list(set(settings.get('-names-', []) + [values['-COMBO-'],]))
- settings['-last name chosen-'] = values['-COMBO-']
- settings['-input-'] = values['-INPUT-']
- sg.popup(f"You chose {values['-COMBO-']} and input {values['-INPUT-']}",
- 'The settions dictionary:', settings)
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_User_Settings_Config_INI_Format.py b/DemoPrograms/Demo_User_Settings_Config_INI_Format.py
deleted file mode 100644
index a3b2f3db8..000000000
--- a/DemoPrograms/Demo_User_Settings_Config_INI_Format.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Settings - Config.ini format
-
- There are now 2 types of settings files available through the UserSettings APIs
- 1. JSON - .json files
- 2. INI - Config.ini files
-
- The default is JSON files.
-
- If you wish to use .ini files, then you can do so using the UserSettings object. The function interface
- for the UserSettings API does not support .ini files, only the object interface at this time. You'll see
- why by looking at this demo.
-
- JSON settings:
- settings['key']
-
- CONFIG.INI settings:
- settings['section']['key']
-
- NOTE - There is a setting (default is ON) that converts True", "False, "None" into Python values of True, False, None
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def show_settings_file(filename):
- """
- Display the contents of any .INI file you wish to display
- :param filename: full path and filename
- """
- settings_obj = sg.UserSettings(filename, use_config_file=True)
- sg.popup_scrolled(settings_obj, title=f'INI File: {filename}')
-
-
-def save_previous_filename_demo():
- """
- Saving the previously selected filename....
- A demo of one of the likely most popular use of user settings
- * Use previous input as default for Input
- * When a new filename is chosen, write the filename to user settings
- """
-
- layout = [[sg.Text('The filename value below will be auto-filled with previously saved entry')],
- [sg.T('The format for this entry is:')],
- [sg.T('settings["My Section"]["filename"]', background_color=sg.theme_text_color(), text_color=sg.theme_background_color())],
- [sg.Input(settings['My Section'].get('filename', ''), key='-IN-'), sg.FileBrowse()],
- [sg.B('Save')],
- [sg.B('Display Settings'), sg.B('Display Section'), sg.B('Display filename setting')],
- [sg.B('Dump an INI File')],
- [sg.B('Exit Without Saving', key='Exit')]]
-
- window = sg.Window('Filename Example', layout)
-
- while True:
- event, values = window.read()
- if event in (sg.WINDOW_CLOSED, 'Exit'):
- break
- elif event == 'Save':
- settings['My Section']['filename'] = values['-IN-']
- elif event == 'Display Settings':
- sg.popup_scrolled(settings, title='All settings')
- elif event == 'Display Section':
- sect = settings['My Section']
- sg.popup_scrolled(sect, title='Section Contents')
- elif event == 'Display filename setting':
- sg.popup_scrolled(f'filename = {settings["My Section"]["filename"]}', title='Filename Setting')
- elif event.startswith('Dump'):
- filename = sg.popup_get_file('What INI file would you like to display?', file_types= (("INI Files", "*.ini"),))
- if filename:
- show_settings_file(filename)
-
- window.close()
-
-
-if __name__ == '__main__':
- sg.theme('dark green 7')
- SETTINGS_PATH = '.'
- # create the settings object and use ini format
- settings = sg.UserSettings(path=SETTINGS_PATH, use_config_file=True, convert_bools_and_none=True)
- # sg.popup(settings)
- # settings['My Section1'].delete_entry(key='test')
- # settings.delete_entry(section='My Section1', key='test')
- # settings['My Section1'].delete_section()
- # del settings['My Section1']
- # settings.delete_section(section='My Section1')
- settings['Section 2'].set('var1', 'Default')
- settings['Section 2']['var'] = 'New Value'
- settings['NEW SECTION']['a'] = 'brand new section'
- save_previous_filename_demo()
diff --git a/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py b/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py
deleted file mode 100644
index 8d1211303..000000000
--- a/DemoPrograms/Demo_User_Settings_Element_setting_Parameter.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - User Settings
-
- Using the PySimpleGUI 5 setting parameter.
-
- New in the PSG5 release is a capability to automatically save and restore values in elements. Each element that has the capability has a parameter called "setting"
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def make_window():
- layout = [[sg.Text('Window with values saved between runs')],
- [sg.Input(key='-IN-', setting='My initial value')],
- [sg.Checkbox('Checkbox', key='-CB-', setting=True)],
- [sg.Button('Re-create Window'), sg.Button('Exit')]]
-
- window = sg.Window('Setting Example', layout, enable_close_attempted_event=True, print_event_values=True, auto_save_location=True)
-
- return window
-
-
-def main():
-
- window = make_window()
-
- while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit' or event == sg.WIN_CLOSE_ATTEMPTED_EVENT:
- window.settings_save(values)
- break
-
- if event == 'Re-create Window': # You can also close and re-open a window using the values previously entered
- window.settings_save(values)
- window.close()
- window = make_window()
-
- window.close()
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py b/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py
deleted file mode 100644
index bb93c7955..000000000
--- a/DemoPrograms/Demo_User_Settings_Remember_Input_and_Combo.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Save previously entered strings for Input and Combo elements by using user_settings calls
-
- It's literally 1 parameter in the layout to get the list of previously used entries shown.
- Then, when the OK button is clicked, it's one line of code to save the newly added
- name into the saved list.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- sg.user_settings_filename(path='.') # The settings file will be in the same folder as this program
-
- layout = [[sg.T('This is your layout')],
- [sg.T('Enter or choose name'),
- sg.Combo(values=sorted(sg.user_settings_get_entry('-names-', [])),
- default_value=sg.user_settings_get_entry('-last name chosen-', None),
- size=(20,1), k='-COMBO-')],
- [sg.T('Remembers last value'), sg.In(sg.user_settings_get_entry('-input-', ''), k='-INPUT-')],
- [sg.OK(), sg.Button('Exit')]]
-
- event, values = sg.Window('Pattern for saving with Combobox', layout).read(close=True)
-
- if event == 'OK':
- sg.user_settings_set_entry('-names-', list(set(sg.user_settings_get_entry('-names-', []) + [values['-COMBO-'],])))
- sg.user_settings_set_entry('-last name chosen-', values['-COMBO-'])
- sg.user_settings_set_entry('-input-', values['-INPUT-'])
- sg.popup(f"You chose {values['-COMBO-']} and input {values['-INPUT-']}",
- 'The settions dictionary:', sg.user_settings())
-
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/Demo_Watermark_Window.py b/DemoPrograms/Demo_Watermark_Window.py
deleted file mode 100644
index bebe45421..000000000
--- a/DemoPrograms/Demo_Watermark_Window.py
+++ /dev/null
@@ -1,111 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Watermarking all windows
-
- Watermarking windows can be done in 4.60.0.160 and greater. It's a very simple mechanism for now.
-
- The option is normally set in the Global Settings control panel. However, you can "Force" the watermark
- on all windows by setting the Window paramter watermark=True on any window you create and from then on
- all windows will have the watermark.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-"""
-M"""""""`YM
-M mmmm. M
-M MMMMM M .d8888b.
-M MMMMM M 88' `88
-M MMMMM M 88. .88
-M MMMMM M `88888P'
-MMMMMMMMMMM
-
-M""MMM""MMM""M dP dP
-M MMM MMM M 88 88
-M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP
-M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888"
-M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b.
-M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP
-MMMMMMMMMMMMMM
-"""
-
-layout = [ [sg.Text('No Watermark')],
- [sg.Button('Exit')] ]
-
-window = sg.Window('No Watermark', layout)
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
-
-
-"""
-MP""""""`MM dP
-M mmmmm..M 88
-M. `YM dP dP .d8888b. d8888P .d8888b. 88d8b.d8b.
-MMMMMMM. M 88 88 Y8ooooo. 88 88ooood8 88'`88'`88
-M. .MMM' M 88. .88 88 88 88. ... 88 88 88
-Mb. .dM `8888P88 `88888P' dP `88888P' dP dP dP
-MMMMMMMMMMM .88
- d8888P
-M""MMM""MMM""M dP dP
-M MMM MMM M 88 88
-M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP
-M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888"
-M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b.
-M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP
-MMMMMMMMMMMMMM
-"""
-
-sg.set_options(watermark_text='') # noramlly not requird unless previously set by user
-
-layout = [ [sg.Text('System Provided Watermark')],
- [sg.Button('Exit')] ]
-
-window = sg.Window('System Watermark', layout, watermark=True)
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
-
-
-"""
-M""MMMMM""M
-M MMMMM M
-M MMMMM M .d8888b. .d8888b. 88d888b.
-M MMMMM M Y8ooooo. 88ooood8 88' `88
-M `MMM' M 88 88. ... 88
-Mb dM `88888P' `88888P' dP
-MMMMMMMMMMM
-
-M""MMM""MMM""M dP dP
-M MMM MMM M 88 88
-M MMP MMP M .d8888b. d8888P .d8888b. 88d888b. 88d8b.d8b. .d8888b. 88d888b. 88 .dP
-M MM' MM' .M 88' `88 88 88ooood8 88' `88 88'`88'`88 88' `88 88' `88 88888"
-M `' . '' .MM 88. .88 88 88. ... 88 88 88 88 88. .88 88 88 `8b.
-M .d .dMMM `88888P8 dP `88888P' dP dP dP dP `88888P8 dP dP `YP
-MMMMMMMMMMMMMM
-"""
-
-sg.set_options(watermark_text='User Supplied Version 1.0')
-
-layout = [ [sg.Text('User Supplied Watermark')],
- [sg.Button('Exit')] ]
-
-window = sg.Window('User Supplied Watermark', layout, watermark=True)
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
-
-window.close()
diff --git a/DemoPrograms/Demo_Window_Background_Image.py b/DemoPrograms/Demo_Window_Background_Image.py
deleted file mode 100644
index 8f98316fa..000000000
--- a/DemoPrograms/Demo_Window_Background_Image.py
+++ /dev/null
@@ -1,107 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Highly experimental demo of how the illusion of a window with a background image is possible with PySimpleGUI.
-
- Requires the latest PySimpleGUI from GitHub. Your copy of PySimpleGUI should be local to your application so that
- the global variable _move_all_windows can be changed.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-sg.Window._move_all_windows = True
-
-
-def title_bar(title, text_color, background_color):
- """
- Creates a "row" that can be added to a layout. This row looks like a titlebar
- :param title: The "title" to show in the titlebar
- :type title: str
- :param text_color: Text color for titlebar
- :type text_color: str
- :param background_color: Background color for titlebar
- :type background_color: str
- :return: A list of elements (i.e. a "row" for a layout)
- :rtype: List[sg.Element]
- """
- bc = background_color
- tc = text_color
- font = 'Helvetica 12'
-
- return [sg.Col([[sg.T(title, text_color=tc, background_color=bc, font=font, grab=True)]], pad=(0, 0), background_color=bc),
- sg.Col([[sg.T('_', text_color=tc, background_color=bc, enable_events=True, font=font, key='-MINIMIZE-'), sg.Text('❎', text_color=tc, background_color=bc, font=font, enable_events=True, key='Exit')]], element_justification='r', key='-C-', grab=True,
- pad=(0, 0), background_color=bc)]
-
-
-
-def main():
-
- background_layout = [ title_bar('This is the titlebar', sg.theme_text_color(), sg.theme_background_color()),
- [sg.Image(data=background_image)]]
- window_background = sg.Window('Background', background_layout, no_titlebar=True, finalize=True, margins=(0, 0), element_padding=(0,0), right_click_menu=[[''], ['Exit',]])
-
- window_background['-C-'].expand(True, False, False) # expand the titlebar's rightmost column so that it resizes correctly
-
-
- # ------ Column Definition ------ #
- column1 = [[sg.Text('Column 1', justification='center', size=(10, 1))],
- [sg.Spin(values=('Spin Box 1', 'Spin Box 2', 'Spin Box 3'),
- initial_value='Spin Box 1')],
- [sg.Spin(values=['Spin Box 1', '2', '3'],
- initial_value='Spin Box 2')],
- [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]
-
- layout = [
- [sg.Text('Window + Background Image\nWith tkinter', size=(30, 2), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
- [sg.Text('Here is some text.... and a place to enter text')],
- [sg.InputText('This is my text')],
- [sg.Frame(layout=[
- [sg.CBox('Checkbox', size=(10, 1)),
- sg.CBox('My second checkbox!', default=True)],
- [sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10, 1)),
- sg.Radio('My second Radio!', "RADIO1")]], title='Options', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
- [sg.MLine(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
- sg.MLine(default_text='A second multi-line', size=(35, 3))],
- [sg.Combo(('Combobox 1', 'Combobox 2'),default_value='Combobox 1', size=(20, 1)),
- sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
- [sg.OptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
- [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
- sg.Frame('Labelled Group', [[
- sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=25),
- sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),
- sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),
- sg.Col(column1)]])
- ],
- [sg.Text('_' * 80)],
- [sg.Text('Choose A Folder', size=(35, 1))],
- [sg.Text('Your Folder', size=(15, 1), justification='right'),
- sg.InputText('Default Folder'), sg.FolderBrowse()],
- [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()],
- [sg.Text('Right Click To Exit', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_SUNKEN)], ]
-
- top_window = sg.Window('Everything bagel', layout, finalize=True, keep_on_top=True, grab_anywhere=False, transparent_color=sg.theme_background_color(), no_titlebar=True)
-
- # window_background.send_to_back()
- # top_window.bring_to_front()
-
- while True:
- window, event, values = sg.read_all_windows()
- print(event, values)
- if event is None or event == 'Cancel' or event == 'Exit':
- print(f'closing window = {window.Title}')
- break
-
- top_window.close()
- window_background.close()
-
-
-
-if __name__ == '__main__':
-
-
- background_image = b'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'
-
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Window_Config_Events.py b/DemoPrograms/Demo_Window_Config_Events.py
deleted file mode 100644
index aac08622f..000000000
--- a/DemoPrograms/Demo_Window_Config_Events.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Window Config Events
-
- The Window object has a parameter enable_window_config_events that when set to True will
- cause sg.WINDOW_CONFIG_EVENT events to be generated when the window is moved or resized.
-
- Note that if you move the window using the Titlebar supplied by the operating system, then you
- will only get an event at the end of the window being moved. If you want to receive numerous
- events during the movement, then you can achieve this using a grab_anywhere setting either
- at the window level or on a single element as shown in this demo.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-layout = [ [sg.Text('Demonstration of the enable_window_config_events')],
- [sg.Text('Grab me HERE for continuous location changed events', grab=True, text_color=sg.theme_background_color(), background_color=sg.theme_text_color())],
- [sg.Text(key='-OUT-', font='_18')],
- [sg.VPush()],
- [sg.Button('Go'), sg.Button('Exit'), sg.Sizegrip()] ]
-
-window = sg.Window('Window Title', layout, resizable=True, enable_window_config_events=True, finalize=True)
-
-window.set_min_size(window.current_size_accurate())
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == sg.WINDOW_CONFIG_EVENT:
- window['-OUT-'].update(f'Size: {window.current_size_accurate()}\nLocation:{window.current_location()}')
-
-window.close()
diff --git a/DemoPrograms/Demo_Window_Disappear.py b/DemoPrograms/Demo_Window_Disappear.py
index bb6553ed2..32ac9b82f 100644
--- a/DemoPrograms/Demo_Window_Disappear.py
+++ b/DemoPrograms/Demo_Window_Disappear.py
@@ -1,12 +1,6 @@
#!/usr/bin/env python
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
# Example .disappear() .reappear() methods in window
@@ -17,7 +11,7 @@
while True:
event, values = window.read()
- if event == sg.WIN_CLOSED:
+ if event is None:
break
if event == 'Disappear':
window.disappear()
diff --git a/DemoPrograms/Demo_Window_Location_Finder.py b/DemoPrograms/Demo_Window_Location_Finder.py
deleted file mode 100644
index 30506b0f4..000000000
--- a/DemoPrograms/Demo_Window_Location_Finder.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Find window's location according to tkinter
-
- Drag this window around your multiple monitors. It will show you where
- tkinter believes the corners are for the window.
-
- You can then use this information to locate your what to pass in the location
- parameter when you want to create a window at a specific spot.
-
- The value in the center is the screen dimensions for the primary window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-sg.theme('dark green 7')
-layout = [
- [sg.T(sg.SYMBOL_UP_ARROWHEAD),
- sg.Text(size=(None,1), key='-OUT-'),
- sg.Text(size=(None,1), key='-OUT2-', expand_x=True, expand_y=True, justification='c'), sg.T(sg.SYMBOL_UP_ARROWHEAD)],
- [sg.T('Screen size: '),sg.T(sg.Window.get_screen_size()), sg.T(sg.SYMBOL_SQUARE)],
- [sg.T(sg.SYMBOL_DOWN_ARROWHEAD),
- sg.Text(size=(None,1), key='-OUT4-'),
- sg.Text(size=(None,1), key='-OUT3-', expand_x=True, expand_y=True, justification='r'), sg.T(sg.SYMBOL_DOWN_ARROWHEAD, justification='r')],
- ]
-
-window = sg.Window('Title not seen', layout, grab_anywhere=True, no_titlebar=True, margins=(0,0), element_padding=(0,0), right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, keep_on_top=True, font='_ 25', finalize=True, transparent_color=sg.theme_background_color())
-
-while True:
- event, values = window.read(timeout=100)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Edit Me':
- sg.execute_editor(__file__)
-
- loc = window.current_location()
- window['-OUT-'].update(loc)
- window['-OUT2-'].update((loc[0]+window.size[0], loc[1]))
- window['-OUT3-'].update((loc[0]+window.size[0], loc[1]+window.size[1]))
- window['-OUT4-'].update((loc[0], loc[1]+window.size[1]))
-
-window.close()
diff --git a/DemoPrograms/Demo_Window_Open_Multiple_Times.py b/DemoPrograms/Demo_Window_Open_Multiple_Times.py
deleted file mode 100644
index d99fae0bf..000000000
--- a/DemoPrograms/Demo_Window_Open_Multiple_Times.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Restart Window (sorta reopen)
-
- Once a window is closed, you can't do anything with it. You can't read it. You can't "re-open" it.
- The only choice is to recreate the window. It's important that you use a "Fresh Layout" every time.
- You can't pass the same layout from one indow to another. You will get a popup error infomrning you
- that you've attempted to resuse a layout.
-
- The purpose of this demo is to show you the simple "make window" design pattern. It simply makes a
- window using a layout that's defined in that function and returns the Window object. It's not a bad
- way to encapsulate windows if your applcation is gettinga little larger than the typical small data
- entry window.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def make_window():
- """
- Defines a window layout and createws a indow using this layout. The newly made Window
- is returned to the caller.
-
- :return: Window that is created using the layout defined in the function
- :rtype: Window
- """
- layout = [[sg.Text('My Window')],
- [sg.Input(key='-IN-'), sg.Text(size=(12, 1), key='-OUT-')],
- [sg.Button('Go'), sg.Button('Exit')]]
-
- return sg.Window('Window Title', layout)
-
-
-def main():
- window = make_window()
-
- while True: # Event Loop
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- window.close()
- window = make_window()
- elif event == 'Go':
- window['-OUT-'].update(values['-IN-'])
-
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Window_Pin_On_Top.py b/DemoPrograms/Demo_Window_Pin_On_Top.py
deleted file mode 100644
index 13716cde6..000000000
--- a/DemoPrograms/Demo_Window_Pin_On_Top.py
+++ /dev/null
@@ -1,81 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Pin a window on top
-
- Note that the PIN used requires Python 3.7+ due to a tkinter problem
- This demo uses a Window call only recently added to GitHub in Aug 2021
-
- 4.46.0.7 of PySimpleGUI provides the methods:
- Window.keep_on_top_set
- Window.keep_on_top_clear
-
- A temporary implementation is included in case you don't have that version
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-def main():
- sg.theme('dark green 7')
-
- PIN = '📌'
-
- # This custom titlebar inveses the normal text/background colors. Uses a little bigger font
- my_titlebar = [[sg.Text('Window title', expand_x=True, grab=True,
- text_color=sg.theme_background_color(), background_color=sg.theme_text_color(), font='_ 12', pad=(0,0)),
- sg.Text(PIN, enable_events=True, k='-PIN-', font='_ 12', pad=(0,0), metadata=False,
- text_color=sg.theme_background_color(), background_color=sg.theme_text_color())]]
-
- layout = my_titlebar + \
- [ [sg.Text('This is my window layout')],
- [sg.Input(key='-IN-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout, no_titlebar=True, resizable=True, margins=(0,0))
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == '-PIN-':
- window['-PIN-'].metadata = not window['-PIN-'].metadata # use metadata to store current state of pin
- if window['-PIN-'].metadata:
- window['-PIN-'].update(text_color='red')
- window.keep_on_top_set()
- else:
- window['-PIN-'].update(text_color=sg.theme_background_color())
- window.keep_on_top_clear()
-
- window.close()
-
-# Temp definitions of the Window methods added to 4.46.0.7 of PySimpleGUI
-def keep_on_top_set(window):
- """
- Sets keep_on_top after a window has been created. Effect is the same
- as if the window was created with this set. The Window is also brought
- to the front
- """
- window.KeepOnTop = True
- window.bring_to_front()
- window.TKroot.wm_attributes("-topmost", 1)
-
-
-def keep_on_top_clear(window):
- """
- Clears keep_on_top after a window has been created. Effect is the same
- as if the window was created with this set.
- """
- window.KeepOnTop = False
- window.TKroot.wm_attributes("-topmost", 0)
-
-
-if __name__ == '__main__':
- if 'keep_on_top_set' not in dir(sg.Window):
- print('You do not have a PySimpleGUI version with required methods. Using the temp ones from this file.')
- sg.Window.keep_on_top_set = keep_on_top_set
- sg.Window.keep_on_top_clear = keep_on_top_clear
- main()
-
diff --git a/DemoPrograms/Demo_Window_Relative_Location.py b/DemoPrograms/Demo_Window_Relative_Location.py
deleted file mode 100644
index a0b4e98b3..000000000
--- a/DemoPrograms/Demo_Window_Relative_Location.py
+++ /dev/null
@@ -1,55 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo - Relative Location
-
- How to create a window at a location relative to where it would normally be placed.
-
- Normally, by default, windows are centered on the screen.
- Other ways initial window position is determined:
- 1. You can also specify the location when creating it by using the location parameter
- 2. You can use set_options to set the location all windows will be created
-
- This demo shows how to use the paramter to Window called relative_location.
-
- As the name suggests, it is a position relative to where it would normally be created.
-
- Both positive and negative values are valid.
- relative_location=(0, -150) will create the window UP 150 pixels from where it would normally be created
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def second_window():
- layout = [[sg.Text('Window 2\nrelative_location=(0,-150)')],
- [sg.Button('Exit')]]
-
- window = sg.Window('Window 2', layout, relative_location=(0,-150), finalize=True)
- return window
-
-
-def main():
- sg.set_options(font='_ 18', keep_on_top=True)
- layout = [ [sg.Text('Window 1\nrelative_location=(0,150)')],
- [sg.Button('Popup'), sg.Button('Exit')] ]
-
- window = sg.Window('Window 1', layout, relative_location=(0,150), finalize=True)
-
- window2 = second_window()
-
- while True: # Event Loop
- window, event, values = sg.read_all_windows()
- if window == None: # If all windows were closed
- break
- if event == sg.WIN_CLOSED or event == 'Exit':
- window.close()
- if event == 'Popup':
- sg.popup('Popups will go to the center of course!')
-
- sg.popup_no_buttons('All windows closed... Bye!', background_color='red', text_color='white', auto_close_duration=3, auto_close=True, no_titlebar=True)
-
-if __name__ == '__main__':
- main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_YouTube_Intro.py b/DemoPrograms/Demo_YouTube_Intro.py
index 8042678a5..2961dee47 100644
--- a/DemoPrograms/Demo_YouTube_Intro.py
+++ b/DemoPrograms/Demo_YouTube_Intro.py
@@ -1,11 +1,5 @@
import PySimpleGUI as sg
-"""
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
layout = [[sg.Text('What is your name?')],
[sg.InputText()],
[sg.Button('Ok')]]
diff --git a/DemoPrograms/Demo_Youtube-dl_Frontend.py b/DemoPrograms/Demo_Youtube-dl_Frontend.py
index 5ae53dba2..1c2a37e5a 100644
--- a/DemoPrograms/Demo_Youtube-dl_Frontend.py
+++ b/DemoPrograms/Demo_Youtube-dl_Frontend.py
@@ -8,17 +8,12 @@
Paste the youtube link into the GUI. The GUI link is queried when you click Get List.
Get List will populate the pulldown list with the language options available for the video.
Choose the language to download and click Download
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
-
youtube_executable = 'path/to/youtube-dl'
def DownloadSubtitlesGUI():
- sg.theme('Dark')
+ sg.change_look_and_feel('Dark')
combobox = sg.Combo(values=['', ], size=(10, 1), key='lang')
layout = [
diff --git a/DemoPrograms/Demo_one_line_progress_meter.py b/DemoPrograms/Demo_one_line_progress_meter.py
deleted file mode 100644
index 8141a3922..000000000
--- a/DemoPrograms/Demo_one_line_progress_meter.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""
- Demo one_line_progress_meter
-
- Add 1 line of code, get a very nice graphical progress meter window
-
- As a software engineer, it's frustrating to know that there is a better way that
- are not being shown. Adding a progress meter to your loop does not require 2 lines
- of code. It can be done with 1.
-
- So many of the popular progress meter packages require multiple changes to your code.
- There are 2 varieties:
- * Add 2 lines of code
- 1. Add - A setup outside your loop
- 2. Add - A call to a meter update function inside inside your loop
- * Modify 1, add 1
- 1. Modify - Your existing for statement to use an iterator made by the meter API
- 2. Add - A call to the meter update function inside your loop
-
- The PySimpleGUI "One Line Progress Meter" requires you to:
- * Add - A call to the meter update funciton inside your loop
-
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-import PySimpleGUI as sg
-import time
-
-
-
-# --------------------------------- BEFORE ---------------------------------
-# Your EXISTING code may look like this
-
-MAX=100 # the max number of items you'll process
-for i in range(MAX):
- # Do your processing stuff here (simulated with this sleep)
- time.sleep(.1)
- print(f'Your old code simply looped through {i}')
-
-
-# --------------------------------- AFTER ---------------------------------
-# Now let's add a PySimpleGUI one line progress meter
-
-MAX=100 # the max number of items you'll process
-for i in range(MAX):
- # Here is your line of code
- sg.one_line_progress_meter('Some test', i+1, MAX)
- time.sleep(.1)
- print(f'Your new code still simply loops through, but you also get the nifty progress window {i}')
-
-sg.popup('Done', 'As you can see, the bar auto disappeared', 'because it reached max value')
-
-# --------------------------------- FANCY ---------------------------------
-# What about that "Cancel" button? Let's hook it up
-
-MAX=100 # the max number of items you'll process
-for i in range(MAX):
- # This time we're checking to see if the meter stopped. If it stopped early, then it was cancelled.
- if not sg.one_line_progress_meter('A Meter You Can Cancel', i+1, MAX, 'KEY', 'Try Clicking Cancel Button') and i+1 != MAX:
- sg.popup_auto_close('Cancelling your loop...')
- break
- time.sleep(.1)
- print(f'Your new code still simply loops through, but you also get the nifty progress window {i}')
-
-sg.popup('Done with your loop!', 'About to exit program')
\ No newline at end of file
diff --git a/DemoPrograms/Demo_psutil_Kill_Processes.py b/DemoPrograms/Demo_psutil_Kill_Processes.py
index 7b9d932f5..6bc167087 100644
--- a/DemoPrograms/Demo_psutil_Kill_Processes.py
+++ b/DemoPrograms/Demo_psutil_Kill_Processes.py
@@ -7,15 +7,9 @@
CONFIRM_KILLS = False
-
-
"""
Utility to show running processes, CPU usage and provides way to kill processes.
Based on psutil package that is easily installed using pip
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
"""
def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
@@ -41,55 +35,43 @@ def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
def show_list_by_name(window):
psutil.cpu_percent(interval=.1)
procs = psutil.process_iter()
- all_procs = []
- for proc in procs:
- pinfo = [proc.cpu_percent(), proc.name(), proc.pid]
- try:
- cmd = proc.cmdline()
- pinfo.append(' '.join(cmd))
- except:
- pinfo.append('')
- all_procs.append(pinfo)
- # all_procs = [[proc.cpu_percent(), proc.name(), proc.pid, proc.cmdline()] for proc in procs]
+ all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(1), reverse=False)
display_list = []
for process in sorted_by_cpu_procs:
- display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[2], process[0] / 10, process[1], process[3]))
- window['-PROCESSES-'].update(display_list)
+ display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0] / 10, process[1]))
+ window['-processes-'].update(display_list)
return display_list
def main():
# ---------------- Create Form ----------------
- sg.theme('Dark Grey 9')
+ # sg.change_look_and_feel('Topanga')
layout = [[sg.Text('Process Killer - Choose one or more processes',
- size=(45,1), font=('Helvetica', 15), text_color='yellow')],
- [sg.Listbox(values=[' '], size=(130, 30), select_mode=sg.SELECT_MODE_EXTENDED, horizontal_scroll=True, font=('Courier', 12), key='-PROCESSES-')],
- [sg.Col([
+ size=(45,1), font=('Helvetica', 15), text_color='red')],
+ [sg.Listbox(values=[' '], size=(50, 30), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 12), key='-processes-')],
[sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')],
- [sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15,1), font='any 14', key='-FILTER-')],
+ [sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15,1), font='any 14', key='-filter-')],
[sg.Button('Sort by Name', ),
sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')),
sg.Button('Kill', button_color=('white','red'), bind_return_key=True),
- sg.Exit(button_color=('white', 'sea green')), sg.Sizegrip()]], expand_x=True) ]]
+ sg.Exit(button_color=('white', 'sea green'))]]
window = sg.Window('Process Killer', layout,
keep_on_top=True,
auto_size_buttons=False,
default_button_element_size=(12,1),
return_keyboard_events=True,
- resizable=True,
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT,
finalize=True)
- window['-PROCESSES-'].expand(True, True)
- window.set_min_size(window.size)
+
+
display_list = show_list_by_name(window)
# ---------------- main loop ----------------
while True:
# --------- Read and update window --------
event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
+ if event in (None, 'Exit'):
break
# skip mouse, control key and shift key events entirely
@@ -106,44 +88,35 @@ def main():
# display_list = []
# for process in sorted_by_cpu_procs:
# display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
- # window['-PROCESSES-'].update(display_list)
- new_output = []
- for line in display_list:
- if values['-FILTER-'] in line.lower():
- new_output.append(line)
- window['-PROCESSES-'].update(new_output)
+ # window['-processes-'].update(display_list)
elif event == 'Kill':
- processes_to_kill = values['-PROCESSES-']
+ processes_to_kill = values['-processes-']
for proc in processes_to_kill:
pid = int(proc[0:5])
# if sg.popup_yes_no('About to kill {} {}'.format(pid, proc[12:]), keep_on_top=True) == 'Yes':
try:
kill_proc_tree(pid=pid)
except:
- sg.popup_non_blocking('Error killing process', auto_close_duration=2, auto_close=True, keep_on_top=True)
+ sg.popup_no_wait('Error killing process', auto_close_duration=1, auto_close=True)
elif event == 'Sort by % CPU':
psutil.cpu_percent(interval=.1)
procs = psutil.process_iter()
all_procs = [[proc.cpu_percent(), proc.name(), proc.pid] for proc in procs]
- # procs = psutil.process_iter()
- # for proc in procs:
- # sg.Print(sg.obj_to_string_single_obj(proc))
sorted_by_cpu_procs = sorted(all_procs, key=operator.itemgetter(0), reverse=True)
display_list = []
for process in sorted_by_cpu_procs:
display_list.append('{:5d} {:5.2f} {}\n'.format(process[2], process[0]/10, process[1]))
- window['-PROCESSES-'].update(display_list)
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
+ window['-processes-'].update(display_list)
else: # was a typed character
if display_list is not None:
new_output = []
for line in display_list:
- if values['-FILTER-'] in line.lower():
+ if values['-filter-'] in line.lower():
new_output.append(line)
- window['-PROCESSES-'].update(new_output)
- window.close()
+ window['-processes-'].update(new_output)
+ window.close()
if __name__ == "__main__":
- main()
\ No newline at end of file
+ main()
+
\ No newline at end of file
diff --git a/DemoPrograms/Demo_psutil_Kill_Python_Processes.py b/DemoPrograms/Demo_psutil_Kill_Python_Processes.py
deleted file mode 100644
index 3dbd0bdbf..000000000
--- a/DemoPrograms/Demo_psutil_Kill_Python_Processes.py
+++ /dev/null
@@ -1,219 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import os
-import signal
-import psutil
-import operator
-import sys
-
-CONFIRM_KILLS = False
-
-"""
- Task killer program focused on Python only programs
-
- While there is another demo program that handles all running processes, this specific
- demo is for Python oriented processes only. It is based on the original, more general
- purpose task killer demo.
-
- In addition to filtering out all but Python programs, it also displays the command line used
- to launch the program. This is particularly good for programs that have no titlebar or
- are running in the background or system tray.
-
- Copyright 2018-2026 PySimpleGUI. All rights reserved.
-
-
-"""
-
-
-def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
- timeout=None, on_terminate=None):
- """Kill a process tree (including grandchildren) with signal
- "sig" and return a (gone, still_alive) tuple.
- "on_terminate", if specified, is a callabck function which is
- called as soon as a child terminates.
- """
- if pid == os.getpid():
- raise RuntimeError("I refuse to kill myself")
- parent = psutil.Process(pid)
- children = parent.children(recursive=True)
- if include_parent:
- children.append(parent)
- for p in children:
- p.send_signal(sig)
- gone, alive = psutil.wait_procs(children, timeout=timeout,
- callback=on_terminate)
- return (gone, alive)
-
-
-def kill_proc(pid, sig=signal.SIGTERM, include_parent=True,
- timeout=None, on_terminate=None):
- """Kill a process tree (including grandchildren) with signal
- "sig" and return a (gone, still_alive) tuple.
- "on_terminate", if specified, is a callabck function which is
- called as soon as a child terminates.
- """
- if pid == os.getpid():
- raise RuntimeError("I refuse to kill myself")
- parent = psutil.Process(pid)
- parent.send_signal(sig)
-
-
-def get_all_procs():
- psutil.cpu_percent(interval=.1)
- procs = psutil.process_iter()
- all_procs = []
- for proc in procs:
- try:
- all_procs.append([proc.cpu_percent(), proc.name(), proc.pid, proc.cmdline()])
- except: pass
-
- disp_data = []
- for process in all_procs:
- try:
- name = process[3][1]
- except:
- name = ''
- disp_data.append([process[2], process[0]/10, process[1], name])
- return disp_data
-
-
-def show_list_by_name(python_only=False):
- disp_data = get_all_procs()
- disp_data = sorted(disp_data, key=operator.itemgetter(3), reverse=False)
- display_list = []
- for process in disp_data:
- if not python_only or (python_only and 'python' in process[2].lower()):
- display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[0], process[1], process[2], process[3]))
- return display_list
-
-
-def show_list_by_cpu(python_only=False):
- disp_data = get_all_procs()
- disp_data = sorted(disp_data, key=operator.itemgetter(1), reverse=True)
-
- display_list = []
- for process in disp_data:
- if not python_only or (python_only and 'python' in process[2].lower()):
- display_list.append('{:5d} {:5.2f} {} {}\n'.format(process[0], process[1], process[2], process[3]))
- return display_list
-
-
-def make_window():
- layout = [[sg.Text('Python Process Killer - Choose one or more processes',
- size=(45, 1), font=('Helvetica', 15), text_color='yellow')],
- [sg.Listbox(values=[' '], size=(130, 30), select_mode=sg.SELECT_MODE_EXTENDED, font=('Courier', 10), key='-PROCESSES-', expand_x=True, expand_y=True)],
- [sg.Text('Click refresh once or twice.. once for list, second to get CPU usage')],
- [sg.Text('Filter by typing name', font='ANY 14'), sg.Input(size=(15, 1), font='any 14', key='-FILTER-', enable_events=True),
- sg.Checkbox('Show only Python processes', default=True, enable_events=True, key='-PYTHON ONLY-')],
- [sg.Button('Sort by Name', ),
- sg.Button('Sort by % CPU', button_color=('white', 'DarkOrange2')),
- sg.Button('Show Open Files', button_color=('white', 'dark green')),
- sg.Button('Kill Selected', button_color=('white', 'red'), bind_return_key=True),
- sg.Button('Kill All', button_color='red on white'),
- sg.Button('Kill All & Exit', button_color='red on white'),
- sg.Exit(button_color=('white', 'sea green')), sg.Sizegrip()]]
-
- window = sg.Window('Python Process Killer', layout,
- keep_on_top=True,
- auto_size_buttons=False,
- default_button_element_size=(12, 1),
- return_keyboard_events=True,
- resizable=True,
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT,
- finalize=True)
- window.bind('', 'Kill Selected')
- window.set_min_size(window.size)
- return window
-
-def kill_all(python_only=True):
- processes_to_kill = show_list_by_name(python_only=python_only)
- for proc in processes_to_kill:
- pid = int(proc[0:5])
- try:
- kill_proc(pid=pid)
- # kill_proc_tree(pid=pid)
- except Exception as e:
- pass
-
-def main(silent=False):
- if silent:
- kill_all(python_only=True)
- sg.popup_auto_close('Killed everything....', 'This window autocloses')
- sys.exit()
- # ---------------- Create Form ----------------
- sg.theme('Dark Grey 9')
- sg.set_options(icon=icon)
-
- window = make_window()
- current_display_list = display_list = show_list_by_name(window['-PYTHON ONLY-'].get())
- window['-PROCESSES-'].update(display_list)
- name_sorted = True
-
- # ---------------- main loop ----------------
- while True:
- # --------- Read and update window --------
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- # skip mouse, control key and shift key events entirely
- if 'Mouse' in event or 'Control' in event or 'Shift' in event:
- continue
-
- # --------- Do Button Operations --------
- if event == 'Sort by Name':
- window['-PROCESSES-'].update(show_list_by_name(values['-PYTHON ONLY-']))
- name_sorted = True
- elif event.startswith('Kill'):
- if event.startswith('Kill All'):
- processes_to_kill = show_list_by_name(values['-PYTHON ONLY-'])
- else:
- processes_to_kill = values['-PROCESSES-']
- for proc in processes_to_kill:
- pid = int(proc[0:5])
- try:
- kill_proc(pid=pid)
- # kill_proc_tree(pid=pid)
- except Exception as e:
- if event.endswith('Selected'): # only show the error if trying to kill only 1 process
- sg.popup_no_wait('Error killing process', e, auto_close_duration=2, auto_close=True, keep_on_top=True)
- current_display_list = show_list_by_name(values['-PYTHON ONLY-']) if name_sorted else show_list_by_cpu(values['-PYTHON ONLY-'])
- window['-PROCESSES-'].update(current_display_list)
- if event.endswith('Exit'):
- break
- elif event == 'Sort by % CPU':
- window['-PROCESSES-'].update(show_list_by_cpu(values['-PYTHON ONLY-']))
- name_sorted = False
- elif event == 'Show Open Files':
- for proc in values['-PROCESSES-']:
- pid = int(proc[0:5])
- parent = psutil.Process(pid)
- file_list = parent.open_files()
- out = ''
- for f in file_list:
- out += f'{f}\n'
- sg.popup_scrolled(out, non_blocking=True, keep_on_top=True,size=(100,30))
- elif event == '-PYTHON ONLY-': # if checkbox changed
- current_display_list = show_list_by_name(values['-PYTHON ONLY-']) if name_sorted else show_list_by_cpu(values['-PYTHON ONLY-'])
- window['-PROCESSES-'].update(current_display_list)
- elif event == '-FILTER-': # was a typed character
- # display_list = window['-PROCESSES-'].get_list_values()
- display_list = current_display_list
- if display_list is not None:
- new_output = []
- for line in display_list:
- if values['-FILTER-'] in line.lower():
- new_output.append(line)
- window['-PROCESSES-'].update(new_output)
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- window.close()
-
-
-if __name__ == "__main__":
- icon = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAFLklEQVR4nO2ZW2xURRjHfzNnz9meXnYplHKtIhKEAgoEabUgKARBQTQ8+mLi5dXERIJPhMREownhyQfii8+aKKCCRIPRQiGEi3IRuSXc5dbSbbvdc5vxYUvAsmfP6bKtmuwvOS87s9/3/We++WbOHKhQoUKFChVKR4Q1fP3T3k1Jy5rluu5IxhOKZVk4rnvitWVtGwu1J4r8d0WyqqpVyFCtI4plJXFcdxIwVCHacZwcrutiGgkMwwCthynMEIQgCAK8wEdrDWgnrGuxGcl3MAz2nDzM2WuXQBpljTMSFTBtQhNLm+dFdo0WIg32nztJ+5H9YJoxnOv8yhNlSEnPY9G8VpbPXoCKijOOPdNIgGlFC9EaWVuNdj2065VBjMj7joF8SE/30BohJaPfWEl1SzP4QdlMx6F8QrwAu2Um1S3NpFa1IOvrQEUlRPkoj5BAYTSkSa9dBFpjNjVSt3wBBP83IVqTerkVs6kR/1Y32vWoXTYf89HxI5ZiDy/ED0g2T6H2hfmo3iy3t+6g/+hZEmPSpNY8C4aEEdh+4pUEpfIjKwbp1hphJxm17jlkrU33tnaco2fQjkvVrClUL5xJtuME/Yf+BLOAq0AV32T9IPY6ixaiNUZDmsRjExCJQd0Dhf30DJLNU3AvXKfn+wNgmbhnr9C75wjptYtJvdJG7tRFtOP+sxwrTWJcPcJOhorRvo9RX5dvjyjlkUK06zNq3VIaGtqwVAFjIi8os2Mvwa07YJkQKHp+OIg9fzrJJ5qoXfIUPd/tB2vAnR+QmNhA44bXSTSkQlPPRVF7zkVnfEgW38OiZ0QIgkwfvt+L1AWEGAbOmUtk9528lz6GJLjZRebbDsa8vZq6lS1kD58muHEnv2akIL22DbNxFH5nBt3vFjyH+1qheo1YG2ukEGEluPPlz9w+dhASBUZFgA5UPpfvd2gmyHYcp6a1GXv+dFKrWun6Yhe4PvbCGdS0ziLI9HFry1e456+CUeAc53v0zFmAeGlqZL2IV7UChfZ8tF/g8fyB89WgURMCnfPo3taO6slSu/hJrOlNiJok6VcXI+wkPT8ewjl1Ea11cdsxiCfk7iEw9An5nylxTl2k95ffkHU2qdXPkFrThvX4JJzzV+nZfRASRnHbMYlXfktGAJqeXQew507LP3Omol2PzPZ2VGcmXxzKQPnOWmEYEv9aJ5mdBxBCICyT/sOnyR74o/DeUiLDLwTANOj79XdyZy6j+vrp/qY9vxmW451lgGFOrQGEQGdzZLbvw5rcgHfhr/zaKCMjIwTATJA7do7c8fNlFwExhfhBAJ5X5PIoJnePInFTyvPyvmMQKcT1fdYtXMLzM+bCSF8NKc3oVBrX90lEFIZIIUorpjVOQo5vKlt8Q0Epha+iZyVeaqkAYhj7NwkXIrBtuxpZ6AwUhdZ4IVetpmWVVHaTVhLHdeyw9mIzsrk/29fk+N6Qneb6c2Nvdna/jxgUsdZ67Oj0p1V21c2h2lS+D3AprH1YVu9b6z+eXD+u/mIhIV3Xux75/JMNl8vtc1j2kXGNdSKQ8sEU0ppxjXXDMnglG/1gy2ezlTJbpSFNNei9WgjRiNYbC80IQmzSWt+4/2cpJSpQnonu+PC9d06UEk9JQtZv3jpLCHYnq+yJd0+4g+MtttgH67trw8nlrkgpV3z07psnhxpTSaklpFhRU5ua6DoOhFwvJ0LuibXWA58IHrBKTV1qUl9v5kVgZIRIoS/5nrvT90I/V5SElAIpdGhlqlChQoUK/zn+BhjXF7IsC7cbAAAAAElFTkSuQmCC'
-
- if len(sys.argv) == 2 and sys.argv[1] == 'silent':
- main(silent=True)
- else:
- main(silent=False)
\ No newline at end of file
diff --git a/DemoPrograms/TutorialCPUUtilization.py b/DemoPrograms/TutorialCPUUtilization.py
new file mode 100644
index 000000000..f868fd9e1
--- /dev/null
+++ b/DemoPrograms/TutorialCPUUtilization.py
@@ -0,0 +1,23 @@
+import PySimpleGUI as sg
+import psutil
+
+# Usage of PSG and cpu data
+
+layout = [[sg.Text('CPU Utilization')],
+ [sg.Text('', size=(8, 2), font='Helvetica 20',
+ justification='center', key='-text-')],
+ [sg.Exit()]]
+
+window = sg.Window('CPU Meter', layout)
+
+while True:
+ event, values = window.ReadNonBlocking()
+
+ if event == 'Exit' or values is None:
+ break
+
+ cpu_percent = psutil.cpu_percent(interval=1)
+
+ window['-text-'].update(f'CPU {cpu_percent:02.0f}%')
+
+window.close()
diff --git a/DemoPrograms/default_icon.ico b/DemoPrograms/default_icon.ico
new file mode 100644
index 000000000..1a41525ec
Binary files /dev/null and b/DemoPrograms/default_icon.ico differ
diff --git a/DemoPrograms/ping.py b/DemoPrograms/ping.py
new file mode 100644
index 000000000..7422b9ce6
--- /dev/null
+++ b/DemoPrograms/ping.py
@@ -0,0 +1,606 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+ A pure python ping implementation using raw sockets.
+
+ (This is Python 3 port of https://github.com/jedie/python-ping)
+ (Tested and working with python 2.7, should work with 2.6+)
+
+ Note that ICMP messages can only be sent from processes running as root
+ (in Windows, you must run this script as 'Administrator').
+
+ Derived from ping.c distributed in Linux's netkit. That code is
+ copyright (c) 1989 by The Regents of the University of California.
+ That code is in turn derived from code written by Mike Muuss of the
+ US Army Ballistic Research Laboratory in December, 1983 and
+ placed in the public domain. They have my thanks.
+
+ Bugs are naturally mine. I'd be glad to hear about them. There are
+ certainly word - size dependencies here.
+
+ Copyright (c) Matthew Dixon Cowles, .
+ Distributable under the terms of the GNU General Public License
+ version 2. Provided with no warranties of any sort.
+
+ Original Version from Matthew Dixon Cowles:
+ -> ftp://ftp.visi.com/users/mdc/ping.py
+
+ Rewrite by Jens Diemer:
+ -> http://www.python-forum.de/post-69122.html#69122
+
+ Rewrite by George Notaras:
+ -> http://www.g-loaded.eu/2009/10/30/python-ping/
+
+ Enhancements by Martin Falatic:
+ -> http://www.falatic.com/index.php/39/pinging-with-python
+
+ Enhancements and fixes by Georgi Kolev:
+ -> http://github.com/jedie/python-ping/
+
+ Bug fix by Andrejs Rozitis:
+ -> http://github.com/rozitis/python-ping/
+
+ Revision history
+ ~~~~~~~~~~~~~~~~
+ May 1, 2014
+ -----------
+ Little modifications by Mohammad Emami
+ - Added Python 3 support. For now this project will just support
+ python 3.x
+ - Tested with python 3.3
+ - version was upped to 0.6
+
+ March 19, 2013
+ --------------
+ * Fixing bug to prevent divide by 0 during run-time.
+
+ January 26, 2012
+ ----------------
+ * Fixing BUG #4 - competability with python 2.x [tested with 2.7]
+ - Packet data building is different for 2.x and 3.x.
+ 'cose of the string/bytes difference.
+ * Fixing BUG #10 - the multiple resolv issue.
+ - When pinging domain names insted of hosts (for exmaple google.com)
+ you can get different IP every time you try to resolv it, we should
+ resolv the host only once and stick to that IP.
+ * Fixing BUGs #3 #10 - Doing hostname resolv only once.
+ * Fixing BUG #14 - Removing all 'global' stuff.
+ - You should not use globul! Its bad for you...and its not thread safe!
+ * Fix - forcing the use of different times on linux/windows for
+ more accurate mesurments. (time.time - linux/ time.clock - windows)
+ * Adding quiet_ping function - This way we'll be able to use this script
+ as external lib.
+ * Changing default timeout to 3s. (1second is not enought)
+ * Switching data syze to packet size. It's easyer for the user to ignore the
+ fact that the packet headr is 8b and the datasize 64 will make packet with
+ size 72.
+
+ October 12, 2011
+ --------------
+ Merged updates from the main project
+ -> https://github.com/jedie/python-ping
+
+ September 12, 2011
+ --------------
+ Bugfixes + cleanup by Jens Diemer
+ Tested with Ubuntu + Windows 7
+
+ September 6, 2011
+ --------------
+ Cleanup by Martin Falatic. Restored lost comments and docs. Improved
+ functionality: constant time between pings, internal times consistently
+ use milliseconds. Clarified annotations (e.g., in the checksum routine).
+ Using unsigned data in IP & ICMP header pack/unpack unless otherwise
+ necessary. Signal handling. Ping-style output formatting and stats.
+
+ August 3, 2011
+ --------------
+ Ported to py3k by Zach Ware. Mostly done by 2to3; also minor changes to
+ deal with bytes vs. string changes (no more ord() in checksum() because
+ >source_string< is actually bytes, added .encode() to data in
+ send_one_ping()). That's about it.
+
+ March 11, 2010
+ --------------
+ changes by Samuel Stauffer:
+ - replaced time.clock with default_timer which is set to
+ time.clock on windows and time.time on other systems.
+
+ November 8, 2009
+ ----------------
+ Improved compatibility with GNU/Linux systems.
+
+ Fixes by:
+ * George Notaras -- http://www.g-loaded.eu
+ Reported by:
+ * Chris Hallman -- http://cdhallman.blogspot.com
+
+ Changes in this release:
+ - Re-use time.time() instead of time.clock(). The 2007 implementation
+ worked only under Microsoft Windows. Failed on GNU/Linux.
+ time.clock() behaves differently under the two OSes[1].
+
+ [1] http://docs.python.org/library/time.html#time.clock
+
+ May 30, 2007
+ ------------
+ little rewrite by Jens Diemer:
+ - change socket asterisk import to a normal import
+ - replace time.time() with time.clock()
+ - delete "return None" (or change to "return" only)
+ - in checksum() rename "str" to "source_string"
+
+ December 4, 2000
+ ----------------
+ Changed the struct.pack() calls to pack the checksum and ID as
+ unsigned. My thanks to Jerome Poincheval for the fix.
+
+ November 22, 1997
+ -----------------
+ Initial hack. Doesn't do much, but rather than try to guess
+ what features I (or others) will want in the future, I've only
+ put in what I need now.
+
+ December 16, 1997
+ -----------------
+ For some reason, the checksum bytes are in the wrong order when
+ this is run under Solaris 2.X for SPARC but it works right under
+ Linux x86. Since I don't know just what's wrong, I'll swap the
+ bytes always and then do an htons().
+
+ ===========================================================================
+ IP header info from RFC791
+ -> http://tools.ietf.org/html/rfc791)
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Version| IHL |Type of Service| Total Length |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identification |Flags| Fragment Offset |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Time to Live | Protocol | Header Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Source Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Options | Padding |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ ===========================================================================
+ ICMP Echo / Echo Reply Message header info from RFC792
+ -> http://tools.ietf.org/html/rfc792
+
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Type | Code | Checksum |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Identifier | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Data ...
+ +-+-+-+-+-
+
+ ===========================================================================
+ ICMP parameter info:
+ -> http://www.iana.org/assignments/icmp-parameters/icmp-parameters.xml
+
+ ===========================================================================
+ An example of ping's typical output:
+
+ PING heise.de (193.99.144.80): 56 data bytes
+ 64 bytes from 193.99.144.80: icmp_seq=0 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=1 ttl=240 time=127 ms
+ 64 bytes from 193.99.144.80: icmp_seq=2 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=3 ttl=240 time=126 ms
+ 64 bytes from 193.99.144.80: icmp_seq=4 ttl=240 time=127 ms
+
+ ----heise.de PING Statistics----
+ 5 packets transmitted, 5 packets received, 0.0% packet loss
+ round-trip (ms) min/avg/max/med = 126/127/127/127
+
+ ===========================================================================
+"""
+
+#=============================================================================#
+import argparse
+import os
+import sys
+import socket
+import struct
+import select
+import time
+import signal
+
+__description__ = 'A pure python ICMP ping implementation using raw sockets.'
+
+if sys.platform == "win32":
+ # On Windows, the best timer is time.clock()
+ default_timer = time.clock
+else:
+ # On most other platforms the best timer is time.time()
+ default_timer = time.time
+
+NUM_PACKETS = 3
+PACKET_SIZE = 64
+WAIT_TIMEOUT = 3.0
+
+#=============================================================================#
+# ICMP parameters
+
+ICMP_ECHOREPLY = 0 # Echo reply (per RFC792)
+ICMP_ECHO = 8 # Echo request (per RFC792)
+ICMP_MAX_RECV = 2048 # Max size of incoming buffer
+
+MAX_SLEEP = 1000
+
+
+class MyStats:
+ thisIP = "0.0.0.0"
+ pktsSent = 0
+ pktsRcvd = 0
+ minTime = 999999999
+ maxTime = 0
+ totTime = 0
+ avrgTime = 0
+ fracLoss = 1.0
+
+
+myStats = MyStats # NOT Used globally anymore.
+
+#=============================================================================#
+
+
+def checksum(source_string):
+ """
+ A port of the functionality of in_cksum() from ping.c
+ Ideally this would act on the string as a series of 16-bit ints (host
+ packed), but this works.
+ Network data is big-endian, hosts are typically little-endian
+ """
+ countTo = (int(len(source_string)/2))*2
+ suma = 0
+ count = 0
+
+ # Handle bytes in pairs (decoding as short ints)
+ loByte = 0
+ hiByte = 0
+ while count < countTo:
+ if (sys.byteorder == "little"):
+ loByte = source_string[count]
+ hiByte = source_string[count + 1]
+ else:
+ loByte = source_string[count + 1]
+ hiByte = source_string[count]
+ try: # For Python3
+ suma = suma + (hiByte * 256 + loByte)
+ except: # For Python2
+ suma = suma + (ord(hiByte) * 256 + ord(loByte))
+ count += 2
+
+ # Handle last byte if applicable (odd-number of bytes)
+ # Endianness should be irrelevant in this case
+ if countTo < len(source_string): # Check for odd length
+ loByte = source_string[len(source_string)-1]
+ try: # For Python3
+ suma += loByte
+ except: # For Python2
+ suma += ord(loByte)
+
+ # Truncate suma to 32 bits (a variance from ping.c, which
+ suma &= 0xffffffff
+ # uses signed ints, but overflow is unlikely in ping)
+
+ suma = (suma >> 16) + (suma & 0xffff) # Add high 16 bits to low 16 bits
+ suma += (suma >> 16) # Add carry from above (if any)
+ answer = ~suma & 0xffff # Invert and truncate to 16 bits
+ answer = socket.htons(answer)
+
+ return answer
+
+#=============================================================================#
+
+
+def do_one(myStats, destIP, hostname, timeout, mySeqNumber, packet_size, quiet=False):
+ """
+ Returns either the delay (in ms) or None on timeout.
+ """
+ delay = None
+
+ try: # One could use UDP here, but it's obscure
+ mySocket = socket.socket(
+ socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname("icmp"))
+ except socket.error as e:
+ print("failed. (socket error: '%s')" % e.args[1])
+ raise # raise the original error
+
+ my_ID = os.getpid() & 0xFFFF
+
+ sentTime = send_one_ping(mySocket, destIP, my_ID, mySeqNumber, packet_size)
+ if sentTime == None:
+ mySocket.close()
+ return delay
+
+ myStats.pktsSent += 1
+
+ recvTime, dataSize, iphSrcIP, icmpSeqNumber, iphTTL = receive_one_ping(
+ mySocket, my_ID, timeout)
+
+ mySocket.close()
+
+ if recvTime:
+ delay = (recvTime-sentTime)*1000
+ if not quiet:
+ print("%d bytes from %s: icmp_seq=%d ttl=%d time=%d ms" % (
+ dataSize, socket.inet_ntoa(struct.pack("!I", iphSrcIP)), icmpSeqNumber, iphTTL, delay)
+ )
+ myStats.pktsRcvd += 1
+ myStats.totTime += delay
+ if myStats.minTime > delay:
+ myStats.minTime = delay
+ if myStats.maxTime < delay:
+ myStats.maxTime = delay
+ else:
+ delay = None
+ print("Request timed out.")
+
+ return delay
+
+#=============================================================================#
+
+
+def send_one_ping(mySocket, destIP, myID, mySeqNumber, packet_size):
+ """
+ Send one ping to the given >destIP<.
+ """
+ #destIP = socket.gethostbyname(destIP)
+
+ # Header is type (8), code (8), checksum (16), id (16), sequence (16)
+ # (packet_size - 8) - Remove header size from packet size
+ myChecksum = 0
+
+ # Make a dummy heder with a 0 checksum.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ padBytes = []
+ startVal = 0x42
+ # 'cose of the string/byte changes in python 2/3 we have
+ # to build the data differnely for different version
+ # or it will make packets with unexpected size.
+ if sys.version[:1] == '2':
+ bytes = struct.calcsize("d")
+ data = ((packet_size - 8) - bytes) * "Q"
+ data = struct.pack("d", default_timer()) + data
+ else:
+ for i in range(startVal, startVal + (packet_size-8)):
+ padBytes += [(i & 0xff)] # Keep chars in the 0-255 range
+ #data = bytes(padBytes)
+ data = bytearray(padBytes)
+
+ # Calculate the checksum on the data and the dummy header.
+ myChecksum = checksum(header + data) # Checksum is in network order
+
+ # Now that we have the right checksum, we put that in. It's just easier
+ # to make up a new header than to stuff it into the dummy.
+ header = struct.pack(
+ "!BBHHH", ICMP_ECHO, 0, myChecksum, myID, mySeqNumber
+ )
+
+ packet = header + data
+
+ sendTime = default_timer()
+
+ try:
+ # Port number is irrelevant for ICMP
+ mySocket.sendto(packet, (destIP, 1))
+ except socket.error as e:
+ print("General failure (%s)" % (e.args[1]))
+ return
+
+ return sendTime
+
+#=============================================================================#
+
+
+def receive_one_ping(mySocket, myID, timeout):
+ """
+ Receive the ping from the socket. Timeout = in ms
+ """
+ timeLeft = timeout/1000
+
+ while True: # Loop while waiting for packet or timeout
+ startedSelect = default_timer()
+ whatReady = select.select([mySocket], [], [], timeLeft)
+ howLongInSelect = (default_timer() - startedSelect)
+ if whatReady[0] == []: # Timeout
+ return None, 0, 0, 0, 0
+
+ timeReceived = default_timer()
+
+ recPacket, addr = mySocket.recvfrom(ICMP_MAX_RECV)
+
+ ipHeader = recPacket[:20]
+ iphVersion, iphTypeOfSvc, iphLength, \
+ iphID, iphFlags, iphTTL, iphProtocol, \
+ iphChecksum, iphSrcIP, iphDestIP = struct.unpack(
+ "!BBHHHBBHII", ipHeader
+ )
+
+ icmpHeader = recPacket[20:28]
+ icmpType, icmpCode, icmpChecksum, \
+ icmpPacketID, icmpSeqNumber = struct.unpack(
+ "!BBHHH", icmpHeader
+ )
+
+ if icmpPacketID == myID: # Our packet
+ dataSize = len(recPacket) - 28
+ #print (len(recPacket.encode()))
+ return timeReceived, (dataSize+8), iphSrcIP, icmpSeqNumber, iphTTL
+
+ timeLeft = timeLeft - howLongInSelect
+ if timeLeft <= 0:
+ return None, 0, 0, 0, 0
+
+#=============================================================================#
+
+
+def dump_stats(myStats):
+ """
+ Show stats when pings are done
+ """
+ print("\n----%s PYTHON PING Statistics----" % (myStats.thisIP))
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent -
+ myStats.pktsRcvd)/myStats.pktsSent
+
+ print("%d packets transmitted, %d packets received, %0.1f%% packet loss" % (
+ myStats.pktsSent, myStats.pktsRcvd, 100.0 * myStats.fracLoss
+ ))
+
+ if myStats.pktsRcvd > 0:
+ print("round-trip (ms) min/avg/max = %d/%0.1f/%d" % (
+ myStats.minTime, myStats.totTime/myStats.pktsRcvd, myStats.maxTime
+ ))
+
+ print("")
+ return
+
+#=============================================================================#
+
+
+def signal_handler(signum, frame):
+ """
+ Handle exit via signals
+ """
+ dump_stats()
+ print("\n(Terminated with signal %d)\n" % (signum))
+ sys.exit(0)
+
+#=============================================================================#
+
+
+def verbose_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Send >count< ping to >destIP< with the given >timeout< and display
+ the result.
+ """
+ signal.signal(signal.SIGINT, signal_handler) # Handle Ctrl-C
+ if hasattr(signal, "SIGBREAK"):
+ # Handle Ctrl-Break e.g. under Windows
+ signal.signal(signal.SIGBREAK, signal_handler)
+
+ myStats = MyStats() # Reset the stats
+
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ print("\nPYTHON PING %s (%s): %d data bytes" %
+ (hostname, destIP, packet_size))
+ except socket.gaierror as e:
+ print("\nPYTHON PING: Unknown host: %s (%s)" % (hostname, e.args[1]))
+ print()
+ return
+
+ myStats.thisIP = destIP
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname,
+ timeout, mySeqNumber, packet_size)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ dump_stats(myStats)
+
+#=============================================================================#
+
+
+def quiet_ping(hostname, timeout=WAIT_TIMEOUT, count=NUM_PACKETS,
+ packet_size=PACKET_SIZE, path_finder=False):
+ """
+ Same as verbose_ping, but the results are returned as tuple
+ """
+ myStats = MyStats() # Reset the stats
+ mySeqNumber = 0 # Starting value
+
+ try:
+ destIP = socket.gethostbyname(hostname)
+ except socket.gaierror as e:
+ return False
+
+ myStats.thisIP = destIP
+
+ # This will send packet that we dont care about 0.5 seconds before it starts
+ # acrutally pinging. This is needed in big MAN/LAN networks where you sometimes
+ # loose the first packet. (while the switches find the way... :/ )
+ if path_finder:
+ fakeStats = MyStats()
+ do_one(fakeStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+ time.sleep(0.5)
+
+ for i in range(count):
+ delay = do_one(myStats, destIP, hostname, timeout,
+ mySeqNumber, packet_size, quiet=True)
+
+ if delay == None:
+ delay = 0
+
+ mySeqNumber += 1
+
+ # Pause for the remainder of the MAX_SLEEP period (if applicable)
+ if (MAX_SLEEP > delay):
+ time.sleep((MAX_SLEEP - delay)/1000)
+
+ if myStats.pktsSent > 0:
+ myStats.fracLoss = (myStats.pktsSent -
+ myStats.pktsRcvd)/myStats.pktsSent
+ if myStats.pktsRcvd > 0:
+ myStats.avrgTime = myStats.totTime / myStats.pktsRcvd
+
+ # return tuple(max_rtt, min_rtt, avrg_rtt, percent_lost)
+ return myStats.maxTime, myStats.minTime, myStats.avrgTime, myStats.fracLoss
+
+#=============================================================================#
+
+
+def main():
+
+ parser = argparse.ArgumentParser(description=__description__)
+ parser.add_argument('-q', '--quiet', action='store_true',
+ help='quiet output')
+ parser.add_argument('-c', '--count', type=int, default=NUM_PACKETS,
+ help=('number of packets to be sent '
+ '(default: %(default)s)'))
+ parser.add_argument('-W', '--timeout', type=float, default=WAIT_TIMEOUT,
+ help=('time to wait for a response in seoncds '
+ '(default: %(default)s)'))
+ parser.add_argument('-s', '--packet-size', type=int, default=PACKET_SIZE,
+ help=('number of data bytes to be sent '
+ '(default: %(default)s)'))
+ parser. add_argument('destination')
+ # args = parser.parse_args()
+
+ ping = verbose_ping
+ # if args.quiet:
+ # ping = quiet_ping
+ ping('Google.com', timeout=1000)
+ # ping(args.destination, timeout=args.timeout*1000, count=args.count,
+ # packet_size=args.packet_size)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Demo_Toolbar/Demo_Floating_Toolbar.py b/Demo_Toolbar/Demo_Floating_Toolbar.py
new file mode 100644
index 000000000..de69a7cc6
--- /dev/null
+++ b/Demo_Toolbar/Demo_Floating_Toolbar.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import os
+
+BUTTON_PATH = '.'
+button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer', 'checkmark', 'camera', 'house', 'download')
+
+
+def ShowMeTheButtons():
+ button_files = [os.path.join(BUTTON_PATH, b+'.png') for b in button_names]
+
+ sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+ toolbar_buttons = [[sg.RButton('{}'.format(button_names[i]), image_size=(32,32), image_filename=f, pad=(0,0), tooltip=button_names[i]) for i, f in enumerate(button_files)],]
+
+ layout = [[sg.Frame('', toolbar_buttons,)]]
+
+ form = sg.FlexForm('Toolbar',
+ no_titlebar=True,
+ grab_anywhere=True,
+ background_color='grey76',
+ keep_on_top=True,
+ ).Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = form.Read()
+ print(button)
+ if button == 'close' or button is None:
+ break # exit button clicked
+
+if __name__ == '__main__':
+ ShowMeTheButtons()
\ No newline at end of file
diff --git a/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py b/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py
new file mode 100644
index 000000000..05019d693
--- /dev/null
+++ b/Demo_Toolbar/Demo_Floating_Toolbar_Includes_Buttons.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+
+import io
+from PIL import Image
+import base64
+import subprocess
+
+button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer')
+
+
+house64='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'
+
+
+timer64='iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAAJDUlEQVRYhbWWe2xT1x3Hv/fht6+feTiJm6TYCUnaLYUmJFmb0pWu0NKmYhtQxoaKCmKjRe1aVRVV/xh/dFPfj0mZNFUr3TSKIHQCOtYVSkehzCEkJORpJ8GJY8eO7Xvt2L7O9bV97/5Iy3iEdK3YT7rS0e/e8/t+zvmee84hcJOj/nu31zQ23LkxFAxaWC5WYC8rHQDgPXnq9Mcsx6Wu/Z66meLVTkfxbbU1O/oHBo8Mjbg/8IyNd9TW1g46nc5ilYJew3Kx/rm5OfFmal6OhoY7y3bt/OWftvx8s2qh9y++8PyD69c9+ti1+Zs2AzRFN1lMRu7SpK+nra3NVFuztH3z5s3y8RMn3ABQbLNFCFl+YGjEfeb/AsAw+mVT/oDIxWLee1pbf1dZWbHDarVuanv44erKysqp9/d+cMloND7lDwQ6ruxH3iwAAKlqp0N8+623msxm049NJhOCwWmc/OzEYw+uWf2Q1WKhrGbTzLWd6O+i1NzcTNlsNoYgCCkYDKZcLpfEMMxgZUXF1nSaf5Cm6dJ0mod7eBjfr7+j57U33txnLytd5qyqGsAnn343gBUrVuieeOKJlqmpqXV1dXXFhYWFhlwuJwUCgdnm5uaJlpbmI2Nu96X+vr4VdbffjlGPG/lcDhqt7o9yPjdV7XRs9YyNH7q2LvFNwi+//HLNpk2bfuL1el/geZ6RJAn5fB6iKCKTySCfz0MQBPA8D5VKFRi42FeaSiaIrCiivKIiqNNq3xgZGSnr6x94xTM2fp0FNwRoaWnB9u3b766pqWkXRbEmGo0q3G43RkaGQRIkjEYTQADpdBoAUFRUBJqmkckIYKNRtN5996sfffTRxe6enlEAg/7ANL+QzoIWNDc3EwcPHnxubGzsRY7jzF1dXfB4faioq8cjv9oNvbUIFEWDJAiQkJDmIvBccCE8OY5cLg/GYMSw27NBq2f+7Q9Mn1u+fLnh6NGPt3V1nXs2Fo+fevvtd54LBoPpG87Ae++9d7/D4TgkCIKho6MDKosNP3j0ZygvL4dBo4KSIiCkEpBlQM0wkGUgm81hOhDASOfn8I8OQxRF0DQ9abPZNhRYrVtEUdyq1Wi06TQf1OmZzY9v3fo5sMA+sGfPnhWNjY3vx+Pxko6DHVh61wO4b8PjsJs0QCaNnEKDQIRDmBeRysmIxpOQaQ1CAR90ahWqljWBYYwI+cbBp1KmSCT8kEatrpFlyTo40I+xMc9cU3OLd9++D88uCNDe3v5SIpH40cmTJwmF2YYf/nQLbEYtYpEIhse9CLGzyGQEMAYjFAoFkpEQ2JkAaJpGYVk5aJqCucgGiHOIBAPguJjB4x5h0nwqYbFYhpY3rHjqr/s+/JvH4xGvWwN79+6tmZiY2MGyLBHkEnhk+zYUqglEQ0F4QiwonRmEnEdBsQ0EAFKSYLulHEkuClKWQJEEKGLe2DJnLYRUEix7ApRCGdux86mWJ5/c6X/l9TfTV2petROGw+GHs9kscb6rC433rUFJUQF4ngcrypgYugiapmAtsgGShBQbQZINg5Ak6HU6lFXcCgoySFlCMsZBp2dQU78Mer0ekiRZ9u/fX9LTc+Eq8asA1q1bZ2hsbLw/l8shFo/DcUczrCYDxi55MdR9DnZHNb449Gec/fgg2MAkKBJgjAbMRkNQ0BQUJOBzD6LPdRpZgUdJaSnKKp24dckSGI1GHDt2bP1CC/6yBaIoWjKZjGVmZgaWIhsMJhNIALqSSlSZi8AYzSi7pQJ/efUluLvPYsuzL0GjVkNJkTCZzaBJAuVLHMhmSqHVaEAC0GjUsBYUQqVSIZFIFC0EQF4BYBRF0Tg7OwtjoQ1UXsR0cBoCn4Reb4BOq4W1sAjbdv8WZmshXvv1Npz/16cosFqh+Mp7vU4LlUKBcGAKQiqBdCIOlVoDmqahUCgW0v8vgCRJVDabpURRBK1UIptOYWygDzMTYxD5JCgCIAnAUlCAXzy9GzZ7Ob74+6HLeZokQBEEhHQKQZ8XoalJcJGZRcWvsoCiqKQkSUmappFJ82AshVh272qks/I1IvMQu1//w3yOIi/nSQKw2+2ovMUOigAokkBg3INMJgNBEBYHUCgUCVEUE2q1GlwwBDGbg0pBgyLkq8RJAlAQgNpguCr/9UNfAUsSgIKmkc/nIctyZlELWJYNC4LQTRAEUskEOL8XBGSwQR/YaR+EVAIUCShJYv5/J3HZ+/k2EGcjCAV8SHBRQMqDT8QxOuoBy7JobW39x6IALpdLDofDnyQSCej1elwavIBIYBKTwwOYGO5HPBKEgpgf1fxIv2qT821IEob6ejA+PIQ4x2JksB9cNAKWZeHz+fKrVq36bFELACAcDh93Op1fplKpuyaHL8K+pAqtq9eCJIAUF8WEZwhLnFVQKJUgya+mHTK4cAhSTkTrPfdCp9OAIoBYNILj//wEvb290tq1a9t37dp13V0AuOYscLlcMJlMPMMwD/B8SpWeZVFRVQutRouJ0WGEAz5YrQXQ63WQ81nQBAE5n0N351nkxQwMBgaMXoesIKD3Qg/OdXbC6/V68/n8bwYGBgLfCAAAarV6dOXKlfLk5OR9qUSCmOPCMJpMkHI53OpwoLi0FHPJWZw8dhjh6QBq6upQXV0NnVaLqYlL0Gk1GOzvx9GjR3D69Om59evX7zxz5sxxv9+/kP71ANPT0/lgMHhh5cqVt/n9/qUcGyWSbBgOhxOFJaXQqFRQ0hQyc2kweh3sdjtIAlAraOg0Gnx5+gucPfslTp06Ja5atar98OHDv+/s7JQXVMciV7L6+npm48aNT3d3d78gy7LeaDSiqqoKlY4qFJeUwlpgBUWSSM7OIjOXBhuNYGhoCL29vQiFQqG2trbnOzo69p8/fz53I41FAQCgoaFBuWfPng0HDhx4OhgMNuh0OhQXF8NgMMBisUCtVoPneYTDYfj9fvh8PixduvQIy7LtsVjsU5fLdcOR/08AX8czzzxDxmKxtmw2uyaXy92RyWQMgiAwkiTJSqVyVqVSxfR6vctkMh159913z3xzxW8J8HU0NTWRAOyJRMKQTCYZgiBko9E4azabY9lsNuRyub5NOQDAfwBU9w9d4+VBlQAAAABJRU5ErkJggg=='
+
+close64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEQ0lEQVR42r2XW2wbRRSG/1177TgkdkyoS4shaaWogVIKRAXUVn4BgRBEIRBSkSK1lAakPhTxABJSK6BEtAoXCUHEWwWi4oEXUAVvRUASSBuJliAh5QJp6hrspoGQi69r73LO7Npu6kvsBGek0ezOrvf79szsmbG0D2iwAN8DaMQaFA0YHQFaLwCX6TQuHQAuNtjR2PawD05LZeFzKeC7b/txPoLxU8Aj1BVkAf1wqw/uejeU9RsASaqYQGp+Dv8EAvjgdD9OAg9S14gQOPKED1XNWyv7+lT0VArxiVH0fCUEOqjr3JoKcImN/pYW2EOnQyUJTESBJkdpgGkV8Cj/owDDdx59A8Mf92FT+GpR+KSlBrt6ehE6+hL0pLp6AYbvfusE5FontFgUZ989UVAiDU+X0OsvQ0/EVy4g4MeOQ3a6Mn38wKHet3MkrofzZJMsFlzpeRVaeLF8ASPsb8Javy7nDXRVxdA7x7FpIZQXnrlP0yDJMoKvHVpZBKq23Qv3M8/nzQt6PIah93qhRxaLwvPNhbLmgGP7Drg694mHlVqKwcsWEBItD8DVvleM6WrhRQXUwBSsnpthvclDY++BZLdnflS9YxecrZ2QFGVZePDIYcq5yWuGK47k39NIzlCdDkHxNuYXiJzrz/xIrr4BFpdbfAFyTS1CSi1uf7IDrqeeheyoLihxubsD2sI8UuEFaItUKfen5mahRcLZl7nft7xAvjIQs+GFP2cLCmjRCL5p3oDN6nzR56xIYDl4ORJlCwyqDnT7Z5aFL5G4w4vN8dnVCwymatA9daVkeCkSJQv8qDtxcDKYF86AwKEuSDYbvB+doq/DlnMPJ6uvmzfmSJQk0E9D+OLVcEG4f38bwgNnxLmz9Wl4+z6HZLXm3JuYHMfE7i0ri8Ck3Y3Hx4L0lvYl8Et7H0Xk7NJ7Xe1d8H74GX2/2YyZmv8XY3euo4SUXJkAFyvtEbdc+CsDn2r3Ifrrz3nHvW7Pftzy/kmxdhSCly2Qlmj66Xf88dB2qP6LRme+jauuo67rIDyvHMN4i1esmvlK6QIUTrEISbKxDnDlPkk2BK6VIDhXXaddP6Vk0H6A9wSUn0WKFn2lCgiYbDEmFVXJYjWOuU1LcHudgAASSLS0FnD4dV4TksYxNEOqsMDwgAAxELToSFZFfGaiVWzGNV6MWM4Uyc5OE8wQCr2AqwmxIuoJowX3k5CjZSd6vvxhqcBj921Fc2g8C2Mwzf5sax7zNZZjSdkcCg6/EEgacAYzlLZvRk1kW7rm39iELwZHsgLPATN311rqb7trG+65dT2FXTEg4o1NoDinZKOYQ8ICFo4ADwMJpEwBDrnKIU+YMqZQ0pAbC4QwODwCf0Rd/BQ4IATagM46oI+CeiNPPVS40EDF6M/pJ78Ap+n0PL8Cp7sGs9asgQSFDLxBmKJ6STKBVSbcZsa10gKcJHi/Hv0PWqbBbaFH/AEAAAAASUVORK5CYII='
+
+
+def ExecuteCommandSubprocess(command, *args, wait=False):
+ # try:
+ if sys.platform == 'linux':
+ arg_string = ''
+ for arg in args:
+ arg_string += ' ' + str(arg)
+ sp = subprocess.Popen(['python3' + arg_string, ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ else:
+ expanded_args = []
+ for a in args:
+ expanded_args += a
+ sp = subprocess.Popen([command, expanded_args], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if wait:
+ out, err = sp.communicate()
+ if out:
+ print(out.decode("utf-8"))
+ if err:
+ print(err.decode("utf-8"))
+ # except: pass
+
+
+def get_image_bytes(image64):
+ image_file = io.BytesIO(base64.b64decode(image64))
+ img = Image.open(image_file)
+ bio = io.BytesIO()
+ img.save(bio, format='PNG')
+ imgbytes = bio.getvalue()
+ return imgbytes
+
+def ShowMeTheButtons():
+
+ sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+ toolbar_buttons = [[sg.RButton('', image_data=get_image_bytes(close64),button_color=('white', 'black'), pad=(0,0), key='_close_'),
+ sg.RButton('', image_data=get_image_bytes(timer64), button_color=('white', 'black'), pad=(0, 0), key='_timer_'),
+ sg.RButton('', image_data=get_image_bytes(house64), button_color=('white', 'black'), pad=(0, 0), key='_house_'),
+ ]]
+
+ # layout = toolbar_buttons
+ layout = [[sg.Frame('Launcher', toolbar_buttons,title_color='white', background_color='black')]]
+
+ window = sg.Window('Toolbar', no_titlebar=True, grab_anywhere=True, background_color='black').Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = window.Read()
+ print(button)
+ if button == '_close_' or button is None:
+ break # exit button clicked
+ elif button == '_timer_':
+ pass # add your call to launch a timer program
+ elif button == '_cpu_':
+ pass # add your call to launch a CPU measuring utility
+if __name__ == '__main__':
+ ShowMeTheButtons()
+
diff --git a/Demo_Toolbar/Mike_Toolbar.py b/Demo_Toolbar/Mike_Toolbar.py
new file mode 100644
index 000000000..67af45171
--- /dev/null
+++ b/Demo_Toolbar/Mike_Toolbar.py
@@ -0,0 +1,27 @@
+import PySimpleGUI as sg
+import os
+
+BUTTON_PATH = 'C:/Python/PycharmProjects/GooeyGUI/ButtonGraphics/Good ones/For toolbar'
+button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer')
+
+
+def ShowMeTheButtons():
+ button_files = [os.path.join(BUTTON_PATH, b+'.png') for b in button_names]
+
+ sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT)
+
+ toolbar_buttons = [[sg.RButton('{}'.format(button_names[i]), image_size=(32,32), image_filename=f, pad=(0,0), tooltip=button_names[i]) for i, f in enumerate(button_files)],]
+
+ layout = [[sg.Frame('', toolbar_buttons)]]
+
+ form = sg.FlexForm('Toolbar', no_titlebar=True).Layout(layout)
+
+ # ---===--- Loop taking in user input --- #
+ while True:
+ button, value = form.Read()
+ print(button)
+ if button == 'close' or button is None:
+ break # exit button clicked
+
+if __name__ == '__main__':
+ ShowMeTheButtons()
\ No newline at end of file
diff --git a/Demo_Toolbar/camera.png b/Demo_Toolbar/camera.png
new file mode 100644
index 000000000..9f7cbc09f
Binary files /dev/null and b/Demo_Toolbar/camera.png differ
diff --git a/Demo_Toolbar/checkmark.png b/Demo_Toolbar/checkmark.png
new file mode 100644
index 000000000..e5f4d178b
Binary files /dev/null and b/Demo_Toolbar/checkmark.png differ
diff --git a/Demo_Toolbar/close.png b/Demo_Toolbar/close.png
new file mode 100644
index 000000000..391665608
Binary files /dev/null and b/Demo_Toolbar/close.png differ
diff --git a/Demo_Toolbar/cookbook.png b/Demo_Toolbar/cookbook.png
new file mode 100644
index 000000000..726234afc
Binary files /dev/null and b/Demo_Toolbar/cookbook.png differ
diff --git a/Demo_Toolbar/cpu.png b/Demo_Toolbar/cpu.png
new file mode 100644
index 000000000..6337c8a3f
Binary files /dev/null and b/Demo_Toolbar/cpu.png differ
diff --git a/Demo_Toolbar/download.png b/Demo_Toolbar/download.png
new file mode 100644
index 000000000..53de7e071
Binary files /dev/null and b/Demo_Toolbar/download.png differ
diff --git a/Demo_Toolbar/github.png b/Demo_Toolbar/github.png
new file mode 100644
index 000000000..3245ab502
Binary files /dev/null and b/Demo_Toolbar/github.png differ
diff --git a/Demo_Toolbar/house.png b/Demo_Toolbar/house.png
new file mode 100644
index 000000000..e4fbd085c
Binary files /dev/null and b/Demo_Toolbar/house.png differ
diff --git a/Demo_Toolbar/pysimplegui.png b/Demo_Toolbar/pysimplegui.png
new file mode 100644
index 000000000..4fe82d1b3
Binary files /dev/null and b/Demo_Toolbar/pysimplegui.png differ
diff --git a/Demo_Toolbar/run.png b/Demo_Toolbar/run.png
new file mode 100644
index 000000000..93d2892ee
Binary files /dev/null and b/Demo_Toolbar/run.png differ
diff --git a/Demo_Toolbar/storage.png b/Demo_Toolbar/storage.png
new file mode 100644
index 000000000..fe9f038ac
Binary files /dev/null and b/Demo_Toolbar/storage.png differ
diff --git a/Demo_Toolbar/timer.png b/Demo_Toolbar/timer.png
new file mode 100644
index 000000000..f2df8f43e
Binary files /dev/null and b/Demo_Toolbar/timer.png differ
diff --git a/images/GIFs/bar_striped.gif b/GIFs/bar_striped.gif
similarity index 100%
rename from images/GIFs/bar_striped.gif
rename to GIFs/bar_striped.gif
diff --git a/images/GIFs/blue_blocks.gif b/GIFs/blue_blocks.gif
similarity index 100%
rename from images/GIFs/blue_blocks.gif
rename to GIFs/blue_blocks.gif
diff --git a/images/GIFs/blue_circle.gif b/GIFs/blue_circle.gif
similarity index 100%
rename from images/GIFs/blue_circle.gif
rename to GIFs/blue_circle.gif
diff --git a/images/GIFs/blue_dots.gif b/GIFs/blue_dots.gif
similarity index 100%
rename from images/GIFs/blue_dots.gif
rename to GIFs/blue_dots.gif
diff --git a/images/GIFs/dots_pulse.gif b/GIFs/dots_pulse.gif
similarity index 100%
rename from images/GIFs/dots_pulse.gif
rename to GIFs/dots_pulse.gif
diff --git a/images/GIFs/dots_wave.gif b/GIFs/dots_wave.gif
similarity index 100%
rename from images/GIFs/dots_wave.gif
rename to GIFs/dots_wave.gif
diff --git a/images/GIFs/gray_circle.gif b/GIFs/gray_circle.gif
similarity index 100%
rename from images/GIFs/gray_circle.gif
rename to GIFs/gray_circle.gif
diff --git a/images/GIFs/gray_dots.gif b/GIFs/gray_dots.gif
similarity index 100%
rename from images/GIFs/gray_dots.gif
rename to GIFs/gray_dots.gif
diff --git a/images/GIFs/gray_spokes.gif b/GIFs/gray_spokes.gif
similarity index 100%
rename from images/GIFs/gray_spokes.gif
rename to GIFs/gray_spokes.gif
diff --git a/images/GIFs/light_blue_circle.gif b/GIFs/light_blue_circle.gif
similarity index 100%
rename from images/GIFs/light_blue_circle.gif
rename to GIFs/light_blue_circle.gif
diff --git a/images/GIFs/line_boxes.gif b/GIFs/line_boxes.gif
similarity index 100%
rename from images/GIFs/line_boxes.gif
rename to GIFs/line_boxes.gif
diff --git a/images/GIFs/line_bubbles.gif b/GIFs/line_bubbles.gif
similarity index 100%
rename from images/GIFs/line_bubbles.gif
rename to GIFs/line_bubbles.gif
diff --git a/images/GIFs/output.py b/GIFs/output.py
similarity index 100%
rename from images/GIFs/output.py
rename to GIFs/output.py
diff --git a/images/GIFs/red_circle.gif b/GIFs/red_circle.gif
similarity index 100%
rename from images/GIFs/red_circle.gif
rename to GIFs/red_circle.gif
diff --git a/images/GIFs/red_dots_ring.gif b/GIFs/red_dots_ring.gif
similarity index 100%
rename from images/GIFs/red_dots_ring.gif
rename to GIFs/red_dots_ring.gif
diff --git a/images/GIFs/ring_black_dots.gif b/GIFs/ring_black_dots.gif
similarity index 100%
rename from images/GIFs/ring_black_dots.gif
rename to GIFs/ring_black_dots.gif
diff --git a/images/GIFs/ring_blue.gif b/GIFs/ring_blue.gif
similarity index 100%
rename from images/GIFs/ring_blue.gif
rename to GIFs/ring_blue.gif
diff --git a/images/GIFs/ring_gray_segments.gif b/GIFs/ring_gray_segments.gif
similarity index 100%
rename from images/GIFs/ring_gray_segments.gif
rename to GIFs/ring_gray_segments.gif
diff --git a/images/GIFs/ring_lines.gif b/GIFs/ring_lines.gif
similarity index 100%
rename from images/GIFs/ring_lines.gif
rename to GIFs/ring_lines.gif
diff --git a/images/GIFs/squish.gif b/GIFs/squish.gif
similarity index 100%
rename from images/GIFs/squish.gif
rename to GIFs/squish.gif
diff --git a/HowDoI/PySimpleGUI-HowDoI.py b/HowDoI/PySimpleGUI-HowDoI.py
new file mode 100644
index 000000000..7df8a04e5
--- /dev/null
+++ b/HowDoI/PySimpleGUI-HowDoI.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+import sys
+if sys.version_info[0] >= 3:
+ import PySimpleGUI as sg
+else:
+ import PySimpleGUI27 as sg
+import subprocess
+
+
+# Test this command in a dos window if you are having trouble.
+HOW_DO_I_COMMAND = 'python -m howdoi.howdoi'
+
+# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file
+DEFAULT_ICON = './QuestionMark.ico'
+
+def HowDoI():
+ '''
+ Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle
+ Excellent example of 2 GUI concepts
+ 1. Output Element that will show text in a scrolled window
+ 2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form
+ :return: never returns
+ '''
+ # ------- Make a new Window ------- #
+ sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors
+
+ layout = [
+ [sg.Text('Ask and your answer will appear here....', size=(40, 1))],
+ [sg.Output(size=(127, 30), font=('Helvetica 10'))],
+ [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'),
+ sg.Text('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15'),
+ sg.T('Command History', font='Helvetica 15'), sg.T('', size=(40,3), text_color=sg.BLUES[0], key='history')],
+ [sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
+ sg.ReadButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
+ sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]
+ ]
+
+ window = sg.Window('How Do I ??',
+ default_element_size=(30, 2),
+ font=('Helvetica',' 13'),
+ default_button_element_size=(8,2),
+ icon=DEFAULT_ICON,
+ return_keyboard_events=True).Layout(layout)
+
+ # ---===--- Loop taking in user input and using it to query HowDoI --- #
+ command_history = []
+ history_offset = 0
+ while True:
+ (button, value) = window.Read()
+ if button == 'SEND':
+ query = value['query'].rstrip()
+ print(query)
+ QueryHowDoI(query, value['Num Answers'], value['full text']) # send the string to HowDoI
+ command_history.append(query)
+ history_offset = len(command_history)-1
+ window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear
+ window.FindElement('history').Update('\n'.join(command_history[-3:]))
+ elif button in (None, 'EXIT'): # if exit button or closed using X
+ break
+ elif 'Up' in button and len(command_history): # scroll back in history
+ command = command_history[history_offset]
+ history_offset -= 1 * (history_offset > 0) # decrement is not zero
+ window.FindElement('query').Update(command)
+ elif 'Down' in button and len(command_history): # scroll forward in history
+ history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list
+ command = command_history[history_offset]
+ window.FindElement('query').Update(command)
+ elif 'Escape' in button: # clear currently line
+ window.FindElement('query').Update('')
+
+
+def QueryHowDoI(Query, num_answers, full_text):
+ '''
+ Kicks off a subprocess to send the 'Query' to HowDoI
+ Prints the result, which in this program will route to a gooeyGUI window
+ :param Query: text english question to ask the HowDoI web engine
+ :return: nothing
+ '''
+ howdoi_command = HOW_DO_I_COMMAND
+ full_text_option = ' -a' if full_text else ''
+ t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE)
+ (output, err) = t.communicate()
+ print('{:^88}'.format(Query.rstrip()))
+ print('_'*60)
+ print(output.decode("utf-8") )
+ exit_code = t.wait()
+
+if __name__ == '__main__':
+ HowDoI()
+
diff --git a/HowDoI/QuestionMark.ico b/HowDoI/QuestionMark.ico
new file mode 100644
index 000000000..dee9a36e9
Binary files /dev/null and b/HowDoI/QuestionMark.ico differ
diff --git a/HowDoI/readme.md b/HowDoI/readme.md
new file mode 100644
index 000000000..a90ac8743
--- /dev/null
+++ b/HowDoI/readme.md
@@ -0,0 +1,46 @@
+# PySimpleGUI-HowDoI
+
+## Introduction
+This package contains a GUI front-end to the AMAZING tool, HowDoI. You can ask this tool any programming question and it will tap into the enormous database of programming questions and answers, StackOverflow.
+
+This program takes you question and returns CODE as a response.
+
+The way it works is that it searches StackOverflow, gets the results and then finds the highest voted answer. From that answer it takes the code it finds and that is what is returned to you. It works shockingly well.
+
+To learn more about HowDoI, visit their GitHub site:
+https://github.com/gleitz/howdoi
+
+
+
+
+
+
+Check out this example. This was not rehearsed. While typing this readme, an example was needed and a random question, that I've never asked before, was posed. Once again this program delivered a great answer.
+
+You can copy and paste the solution right into your code if you wish.
+
+## Installing
+
+When you install PySimpleGUI-HowDoI, it will install the other components that it requires. To install, on windows, type this into a command prompt:
+
+ pip install pysimplegui-howdoi
+
+
+## Running the GUI Program
+
+Afer your Pip install completes you can run the program. Do run it, type this into your command prompt:
+
+ python -m pysimplegui-howdoi.pysimplegui-howdoi
+
+Once running you simply type in your question and press enter or click the "SEND" button. If you want to ask a question again, you can use the arrow keys or your mouse wheel to access the history of questions you've previously asked.
+
+Ask ANY question you want for ANY programming language. I recommend starting the question with the programming language.
+
+
+## PySimpleGUI Project
+
+This program was built as a sample application of the PySimpleGUI GUI Framework. It quickly became a tool I was unable to live without. I've been trying for some time to bring it to life for others to try.
+
+## Windows Only?
+
+This has only been tested using Windows. I have not gotten it to work under Linux. The linkage between the program and the howdoI package was messed up on Linux. If you're able to get a Linux version running, please let me know at info@PySimpleGUI.org
diff --git a/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py
new file mode 100644
index 000000000..0343059c7
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py
@@ -0,0 +1,65 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+Adapted: From https://gitlab.com/lotspaih/PySimpleGUI/tree/master
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+"""
+
+#No exactly sure how all this works, but taken from example given as a template.
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code ----------------------
+#see https://matplotlib.org/
+fig = plt.figure()
+ax = fig.add_subplot(111)
+#x-values
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+#y-values
+y = np.sin(x)
+plt.plot(x,y)
+
+ax.set_title('sin(x)')
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py
new file mode 100644
index 000000000..f20bce435
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py
@@ -0,0 +1,57 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+fig=plt.figure()
+ax = fig.add_subplot(111)
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+y= np.sin(x)
+plt.plot(x,y)
+
+ax.set_title('sin(x)')
+
+#centre bottom and left axes to zero
+
+ax.spines['left'].set_position('zero')
+ax.spines['right'].set_color('none')
+ax.spines['bottom'].set_position('zero')
+ax.spines['top'].set_color('none')
+
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes centred)', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py
new file mode 100644
index 000000000..721ffbad2
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py
@@ -0,0 +1,73 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+"""
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+fig=plt.figure()
+ax = fig.add_subplot(111)
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+y= np.sin(x)
+plt.plot(x/np.pi,y)
+
+ax.set_title('sin(x)')
+#centre bottom and left axes to zero
+
+ax.spines['left'].set_position('zero')
+ax.spines['right'].set_color('none')
+ax.spines['bottom'].set_position('zero')
+ax.spines['top'].set_color('none')
+
+#Format axes - nicer eh!
+ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes pi format)', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py
new file mode 100644
index 000000000..203c3281e
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py
@@ -0,0 +1,100 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 14, 'bold'),
+ text_color = 'DarkBlue',
+ input_text_color ='DarkBlue',
+ button_color = ('DarkBlue', 'White'))
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(amp, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-np.pi*2, np.pi*2, 100)
+ if function == 'sine':
+ y= amp*np.sin(x)
+ ax.set_title('sin(x)')
+ else:
+ y=amp*np.cos(x)
+ ax.set_title('cos(x)')
+ plt.plot(x/np.pi,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+ #Format axes - nicer eh!
+ ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'sine'
+set_plot(amp, function)
+
+#------------End Matplotlib code --------------------
+
+#use Tabs - one for options, one for canvas to be displayed
+#set spinner for amplitude and combo for function type
+
+tab1_layout = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))],
+ [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'),
+ sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))],
+ [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))],
+ [sg.ReadButton('Redraw Plot')],
+ [sg.Text('', size = (2, 25))]]
+
+tab2_layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+layout = [[sg.TabGroup([[sg.Tab('Select options', tab1_layout), sg.Tab('Display Plot', tab2_layout)]])]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ amp = int(value['_spin_'])
+ function = value['_function_']
+ set_plot(amp,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py
new file mode 100644
index 000000000..041bfe541
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py
@@ -0,0 +1,98 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 14, 'bold'),
+ text_color = 'DarkBlue',
+ input_text_color ='DarkBlue',
+ button_color = ('DarkBlue', 'White'))
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(amp, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-np.pi*2, np.pi*2, 100)
+ if function == 'sine':
+ y= amp*np.sin(x)
+ ax.set_title('sin(x)')
+ else:
+ y=amp*np.cos(x)
+ ax.set_title('cos(x)')
+ plt.plot(x/np.pi,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+ #Format axes - nicer eh!
+ ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'sine'
+set_plot(amp, function)
+
+#------------End Matplotlib code --------------------
+
+#using one window based on two columns instead of Tabs
+column1 = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))],
+ [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'),
+ sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))],
+ [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))],
+ [sg.ReadButton('Redraw Plot')],
+ [sg.Text('', size = (1, 27))]]
+
+column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+layout = [[sg.Column(column1), sg.Column(column2)]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ amp = int(value['_spin_'])
+ function = value['_function_']
+ set_plot(amp,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py
new file mode 100644
index 000000000..580fa88ff
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py
@@ -0,0 +1,121 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import matplotlib
+# added this to work with MacOs
+matplotlib.use('TkAgg')
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+sg.SetOptions (background_color = 'Grey',
+ element_background_color = 'Grey',
+ text_element_background_color = 'Grey',
+ font = ('Arial', 14, 'bold'),
+ text_color = 'Black',
+ input_text_color ='Black',
+ button_color = ('Black', 'White'))
+
+#sg.ChangeLookAndFeel('Black')
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(a,b,c, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-10, 10, 100)
+ if function == 'y = ax + b':
+ y= a*x + b
+ if a == 1:
+ a = ''
+ if a == -1:
+ a = '-'
+ title = str('y = ') + str(a) + 'x + ' + str(b)
+ ax.set_title(title)
+ else:
+ y = a*x**2 + b*x + c
+ #avoiding getting -1x or -1x**2 instead of -x for title
+ if a == 1:
+ a = ''
+ if a == -1:
+ a = '-'
+ if b == 1:
+ b = ''
+ if b == -1:
+ b = '-'
+ title = str('y = ') + str(a) + 'x**2 + ' + str(b) + 'x + ' + str(c)
+ ax.set_title(title)
+ plt.plot(x,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'y = ax + b'
+set_plot(1,1,1, function)
+
+#------------End Matplotlib code --------------------
+
+#column 1 for function type and constant values ...
+
+column1 = [
+ [sg.Text('Select constants & function type', )],
+ [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))],
+ [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'),
+ sg.Text('a', size = (3, 1)),
+ sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'),
+ sg.Text('b', size = (3, 1)),
+ sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'),
+ sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))],
+ [sg.ReadButton('Redraw Plot', size = (14,1))],
+ [sg.Text('', size = (1, 14))]]
+
+column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1))]]
+
+layout = [[sg.Column(column1), sg.Column(column2)]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ a = int(value['_a_'])
+ b = int(value['_b_'])
+ c = int(value['_c_'])
+ function = value['_function_']
+ set_plot(a,b,c,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py
new file mode 100644
index 000000000..86ecab1c3
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py
@@ -0,0 +1,36 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+#layout, Text, Input,button on line below
+layout = [
+ [sg.Text('Celcius'), sg.InputText()],
+ [sg.Submit()],
+ ]
+
+#setup window with Title
+window = sg.Window('Temperature Converter').Layout(layout)
+
+#get value (part of a list)
+button, value = window.Read()
+if button is None:
+ #windows was closed without button being pressed
+ exit(0)
+
+#convert and create string
+fahrenheit = round(9/5*float(value[0]) +32, 1)
+result = 'Temperature in Fahrenheit is: ' + str(fahrenheit)
+#display in Popup
+sg.Popup('Result', result)
+
+
+
+
+
+
+
+
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py
new file mode 100644
index 000000000..346705478
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py
@@ -0,0 +1,41 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+#Set formatting options for all elements rather than individually.
+#MacOs - colour background issue buttons - make text LightBlue
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 10, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('Blue', 'White')
+ )
+#adjust widths
+layout = [
+ [sg.Text('Celcius', size =(12,1)), sg.InputText(size = (8,1))],
+ [sg.Submit()]
+ ]
+
+window = sg.Window('Converter').Layout(layout)
+button, value = window.Read()
+if button is None:
+ #windows was closed without button being pressed
+ exit(0)
+fahrenheit = round(9/5*float(value[0]) +32, 1)
+result = 'Temperature in Fahrenheit is: ' + str(fahrenheit)
+sg.Popup('Result',result)
+
+
+
+
+
+
+
+
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py
new file mode 100644
index 000000000..e686da7fc
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py
@@ -0,0 +1,35 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 12, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('Blue', 'White')
+ )
+#update (via list) values and and display answers
+#value[0] is celcius input, value[1] is input to place result.
+#Use ReadButton with while true: - keeps window open.
+
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1))],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1))],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+#Return = button press
+window = sg.Window('Converter').Layout(layout)
+
+while True:
+ #get result
+ button, value = window.Read()
+ #break out of loop is button not pressed.
+ if button is not None:
+ fahrenheit = round(9/5*float(value[0]) +32, 1)
+ #put result in 2nd input box
+ window.FindElement(1).Update(fahrenheit)
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py
new file mode 100644
index 000000000..88c567ba6
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py
@@ -0,0 +1,36 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 12, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('Blue', 'White')
+ )
+#name inputs (key) uses dictionary- easy to see updating of results
+#value[input] first input value te c...
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+
+window = sg.FlexForm('Temp Converter').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #catch program errors for text or blank entry:
+ try:
+ fahrenheit = round(9/5*float(value['_input_']) +32, 1)
+ #put result in text box
+ window.FindElement('_result_').Update(fahrenheit)
+ except ValueError:
+ sg.Popup('Error','Please try again')
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py
new file mode 100644
index 000000000..c31194ae1
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py
@@ -0,0 +1,36 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+
+#Can use a variety of themes - plus individual options
+#Not on MacOS
+#sg.ChangeLookAndFeel('SandyBeach')
+#use set Options see previous
+sg.SetOptions (font = ('Calbri', 12, 'bold'))
+
+
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (6,1),key = '_input_')],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (6,1),key = '_result_')],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+
+window = sg.Window('Temp Converter').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #catch program errors for text, floats or blank entry:
+ #Also validation for range [0, 50]
+ try:
+ if float(value['_input_']) > 50 or float(value['_input_']) <0:
+ sg.Popup('Error','Out of range')
+ else:
+ fahrenheit = round(9/5*int(value['_input_']) +32, 1)
+ window.FindElement('_result_').Update(fahrenheit)
+ except ValueError:
+ sg.Popup('Error','Please try again')
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py
new file mode 100644
index 000000000..3db950a1b
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py
@@ -0,0 +1,34 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#Can use a variety of themes - plus individual options
+sg.ChangeLookAndFeel('SandyBeach')
+sg.SetOptions (font = ('Arial', 10, 'bold'))
+
+
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+
+window = sg.Window('Temp Converter').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #catch program errors for text, floats or blank entry:
+ #Also validation for range [0, 50]
+ try:
+ if float(value['_input_']) > 50 or float(value['_input_']) <0:
+ sg.Popup('Error','Out of range')
+ else:
+ fahrenheit = round(9/5*int(value['_input_']) +32, 1)
+ window.FindElement('_result_').Update(fahrenheit)
+ except ValueError:
+ sg.Popup('Error','Please try again')
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py
new file mode 100644
index 000000000..189959b42
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py
@@ -0,0 +1,49 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+#Set colour scheme and font
+#sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions (background_color = 'LightPink',
+ element_background_color = 'LightPink',
+ text_element_background_color = 'LightPink',
+ font = ('Arial', 14, 'bold'),
+ text_color = 'Green',
+ input_text_color ='Green',
+ button_color = ('Green', 'White'))
+
+#One checkbox and three radio buttons (grouped as 'Radio1')
+#value[0] - checkbox, Value[1-3] radiobutton selection
+layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))],
+ [sg.Checkbox(' Student? 10% off', size = (25,1)),
+ sg.ReadButton('Display Cost', size = (14,1))],
+ [sg.Radio('1 month $50', 'Radio1', default = True),
+ sg.Radio('3 months $100', 'Radio1'),
+ sg.Radio('1 year $300', 'Radio1')],
+ [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]]
+
+window = sg.Window('Gym Membership').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[1]:
+ cost = 50
+ elif value[2]:
+ cost = 100
+ else:
+ cost = 300
+ if value[0]:
+ #apply discount
+ cost = cost*0.9
+
+ #format as currency $ symbol and 2 d.p. - make a string
+ result = str(' Cost: ' + '${:.2f}'.format(cost))
+ #put the result in Textbox
+ window.FindElement('result').Update(result)
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py
new file mode 100644
index 000000000..aa4d1038a
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py
@@ -0,0 +1,42 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+import os
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+#get pathname to current file
+dirname, filename = os.path.split(os.path.abspath(__file__))
+#add file name for image
+pathname = os.path.join(dirname ,'Gym_Logo.png')
+
+layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))],
+ [sg.Checkbox(' Student? 10% off', size = (25,1)),
+ sg.ReadButton('Display Cost', size = (14,1),button_color = ('Red', 'White'))],
+ [sg.Radio('1 month $50', 'Radio1', default = True),
+ sg.Radio('3 months $100', 'Radio1'),
+ sg.Radio('1 year $300', 'Radio1')],
+ [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]]
+
+window = sg.Window('Gym Membership').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[1]:
+ cost = 50
+ elif value[2]:
+ cost = 100
+ else:
+ cost = 300
+ if value[0]:
+ cost = cost*0.9
+
+ #format as currency $ symbol and 2 d.p. - make a string
+ result = str(' Cost: ' + '${:.2f}'.format(cost))
+ window.FindElement('result').Update(result)
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py
new file mode 100644
index 000000000..d1348a914
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py
@@ -0,0 +1,46 @@
+
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+
+#sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions (background_color = 'Grey',
+ element_background_color = 'Grey',
+ text_element_background_color = 'Grey',
+ font = ('Courier New', 12, 'bold'),
+ text_color = 'White',
+ input_text_color ='White',
+ button_color = ('Grey', 'White'))
+
+
+layout = [
+ [sg.Text('Enter and Add Data to Display', font = ('Calibri', 16,'bold'))],
+ [sg.Text('Race:', size = (5,1)), sg.InputText(size = (8,1)),
+ sg.Text('Club:', size = (5,1)), sg.InputText(size = (8,1))],
+ [sg.Text('Name:', size = (5,1)), sg.InputText(size = (8,1)),
+ sg.Text('Time:', size = (5,1)), sg.InputText(size = (8,1)),sg.Text(' '),
+ sg.ReadButton('Add Data', font = ('Calibri', 12, 'bold'))],
+ [sg.Text('_'*40)],
+ [sg.Text(' Race Club Name Time')],
+ [sg.Multiline(size =(44,6),key = '_multiline_')]
+ ]
+
+window = sg.Window('Enter & Display Data').Layout(layout)
+
+string = ''
+S=[]
+while True:
+
+ button, value = window.Read()
+ if button is not None:
+ #use string formatting - best way? plus Courier New font - non-proportional font
+ S = S + ['{:^9s}{:<11s}{:<10s}{:>8s}'.format(value[0],value[1],value[2],value[3])]
+ for s in S:
+ string = string + s + '\n'
+ window.FindElement('_multiline_').Update(string)
+ string =''
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py
new file mode 100644
index 000000000..77258ca82
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py
@@ -0,0 +1,55 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions (background_color = 'LightPink',
+ element_background_color = 'LightPink',
+ text_element_background_color = 'LightPink',
+ font = ('Calibri', 14, 'bold'),
+ text_color = 'Black',
+ input_text_color ='Black',
+ button_color = ('Black', 'White'))
+#use of Column to help with layout - vertical sliders take up space
+
+column1 = [
+ [sg.Text('Pick operation', size = (15,1), font = ('Calibri', 16, 'bold'))],
+ [sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (10,8))],
+ [sg.Text('', size =(1,4))]]
+column2 = [
+ [sg.ReadButton('Submit', font = ('Calibri', 16, 'bold'), size = (8, 1))],
+ [sg.Text('Result:', font = ('Calibri', 16, 'bold'))],[sg.InputText(size = (12,1), key = '_result_')]
+ ]
+
+
+layout = [
+ [sg.Text('Slider and Combo box demo', font = ('Calibri', 16,'bold'))],
+ [sg.Slider(range = (-9, 9),orientation = 'v', size = (5,20), default_value = 0),
+ sg.Slider(range = (-9, 9),orientation = 'v', size = (5, 20), default_value = 0),
+ sg.Text(' '), sg.Column(column1), sg.Column(column2)]]
+
+#added grab_anywhere to when moving slider, who window doesn't move.
+
+window = sg.Window('Enter & Display Data',grab_anywhere = False).Layout(layout)
+
+#Get selection from combo: value[2]
+#Slider values: value[0] and value[1]
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[2] == 'Add':
+ result = value[0] + value[1]
+ elif value[2] == 'Multiply':
+ result = value[0] * value[1]
+ elif value[2] == 'Subtract':
+ result = value[0] - value[1]
+ elif value[2] == 'Divide': #check for zero
+ if value[1] ==0:
+ sg.Popup('Second value can\'t be zero')
+ result = 'NA'
+ else:
+ result = value[0] / value[1]
+ window.FindElement('_result_').Update(result)
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py
new file mode 100644
index 000000000..8d696c312
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py
@@ -0,0 +1,43 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions(background_color = 'LightGreen',
+ element_background_color = 'LightGreen',
+ text_element_background_color = 'LightGreen',
+ font= ('Calibri', 12, 'bold'))
+
+layout = [
+ [sg.Text('Spinner and Combo box demo', font = ('Calibri', 14, 'bold'))],
+ [sg.Spin([sz for sz in range (-9,10)], size = (2,1),initial_value = 0),
+ sg.Spin([sz for sz in range (-9,10)], size = (2,1), initial_value = 0),
+ sg.Text('Pick operation ->', size = (15,1)),
+ sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (8,6))],
+ [sg.Text('Result: ')],[sg.InputText(size = (5,1), key = '_result_'),
+ sg.ReadButton('Calculate', button_color = ('Black', 'White'))]]
+
+window = sg.Window('Enter & Display Data', grab_anywhere= False).Layout(layout)
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ #convert returned values to integers
+ val = [int(value[0]), int(value[1])]
+ if value[2] == 'Add':
+ result = val[0] + val[1]
+ elif value[2] == 'Multiply':
+ result = val[0] * val[1]
+ elif value[2] == 'Subtract':
+ result = val[0] - val[1]
+ elif value[2] == 'Divide':
+ if val[1] ==0:
+ sg.Popup('Second value can\'t be zero')
+ result = 'NA'
+ else:
+ result = round( val[0] / val[1], 3)
+ window.FindElement('_result_').Update(result)
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py
new file mode 100644
index 000000000..293b69299
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py
@@ -0,0 +1,51 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+#sg.ChangeLookAndFeel('BlueMono')
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Calibri', 14, 'bold'),
+ text_color = 'Black',
+ input_text_color ='Black',
+ button_color = ('Black', 'White'))
+
+#use column feature with height listbox takes up
+column1 = [
+ [sg.Text('Add or Delete Items\nfrom a Listbox')],
+ [sg.InputText( size = (15,1), key = 'add'), sg.ReadButton('Add', size = (5,1))],
+ [sg.ReadButton('Delete selected entry', size = (18,1))]]
+
+#initial listbox entries
+List = ['Austalia', 'Canada', 'Greece']
+
+#add initial List to listbox
+layout = [
+ [sg.Listbox(values=[l for l in List], size = (20,8), key ='_listbox_'),
+ sg.Column(column1)]]
+
+window = sg.Window('Listbox').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #value[listbox] returns a list
+ #using value[listbox][0] gives the string
+ if button == 'Delete selected entry':
+ #ensure something is selected
+ if value['_listbox_'] == []:
+ sg.Popup('Error','You must select a Country')
+ else:
+ #find and remove this
+ List.remove(value['_listbox_'][0])
+ if button == 'Add':
+ #add string in add box to list
+ List.append(value['add'])
+ List.sort()
+ #update listbox
+ window.FindElement('_listbox_').Update(List)
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py
new file mode 100644
index 000000000..45bf802ad
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py
@@ -0,0 +1,90 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+
+sg.SetOptions(background_color = 'Grey',
+ element_background_color = 'Grey',
+ text_element_background_color = 'Grey',
+ font= ('Calibri', 14, 'bold'))
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'),
+ sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*35,font = ('Calibri', 16))],
+ [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#names for Demo, could be loaded from a file
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+#function to display list
+def display_list(list, display):
+ names = ''
+ for l in list: #add list elements with new line
+ names = names + l + '\n'
+ window.FindElement(display).Update(names)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']: #Check each value
+ found = True
+ window.FindElement('_display1_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ #Start with found is False
+ found = False
+ while lo <= hi:
+ #Start in middle
+ mid = (lo + hi) //2
+ #get the value from the search box
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.')
+ #If found display name and stop
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ #Search in top half
+ lo = mid + 1
+ else:
+ #Search in lower half
+ hi = mid - 1
+ #If we get to end - display not found
+ if not found:
+ window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found')
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ #show names - unordered and sorted
+ if button == 'Show Names':
+ display_list(names,'_display1_')
+ display_list(sorted_names, '_display2_')
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py
new file mode 100644
index 000000000..8c9171664
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py
@@ -0,0 +1,98 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'),
+ sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*35,font = ('Calibri', 16))],
+ [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', key = '_ls_',size = (11,1)), sg.ReadButton('Binary Search', key ='_bs_',size = (11,1))],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#finalize allows the disabling of the two buttons before .Read statement
+window.Finalize()
+window.FindElement('_ls_').Update(disabled = True)
+window.FindElement('_bs_').Update(disabled = True)
+
+#names for Demo, could be loaded from a file
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+#function to display list
+def display_list(list, display):
+ names = ''
+ #add list elements with new line
+ for l in list:
+ names = names + l + '\n'
+ window.FindElement(display).Update(names)
+ #enable buttons now data loaded
+ window.FindElement('_ls_').Update(disabled = False)
+ window.FindElement('_bs_').Update(disabled = False)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ #Check each value
+ if l == value['_linear_']:
+ found = True
+ window.FindElement('_display1_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ #Start with found is Flase
+ found = False
+ while lo <= hi:
+ #Start in middle
+ mid = (lo + hi) //2
+ #get the value from the search box
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.')
+ #If found display and stop
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ #Search in top half
+ lo = mid + 1
+ else:
+ #Search in lower half
+ hi = mid - 1
+ #If we get to end - display not found
+ if not found:
+ window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found')
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #show names - unordered and sorted
+ if button == 'Show Names':
+ display_list(names,'_display1_')
+ display_list(sorted_names, '_display2_')
+ if button == '_ls_':
+ linear_search()
+ if button == '_bs_':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py
new file mode 100644
index 000000000..65b3c3b4f
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py
@@ -0,0 +1,79 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions(background_color = 'Grey',
+ element_background_color = 'Grey',
+ text_element_background_color = 'Grey',
+ font= ('Calibri', 14, 'bold'))
+
+#names for Demo, could be loaded from a file
+
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+name = ''
+for l in names:
+ name = name + l + '\n'
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+sortname = ''
+for l in sorted_names:
+ sortname = sortname + l +'\n'
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold'))],
+[sg.Text(name,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'),
+ sg.Text(sortname,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*35,font = ('Calibri', 16))],
+ [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ sg.Popup('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ sg.Popup('Linear search\n' +(value['_linear_'] + ' was not found'))
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ sg.Popup('Binary search\n' + l[mid] + ' found.')
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ sg.Popup('Binary search\n' +(value['_binary_'] + ' was not found'))
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py
new file mode 100644
index 000000000..ea354d902
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py
@@ -0,0 +1,139 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOS
+
+import PySimpleGUI as sg
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+#setup column (called column1) of buttons to use in layout
+
+column1 = [[sg.ReadButton('Original list', size = (11,1))],
+ [sg.ReadButton('Default sort', size = (11,1))],
+ [sg.ReadButton('Sort: selection',size = (11,1))],
+ [sg.ReadButton('Sort: quick', size = (11,1))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*35,font = ('Calibri', 16))],
+ [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+#names for Demo, could be loaded from a file
+names= ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+#function to display list
+def display_list(list):
+ #store list in Multiline text globally
+ global list_displayed
+ list_displayed = list
+ display = ''
+ #add list elements with new line
+ for l in list:
+ display = display + l + '\n'
+ window.FindElement('_display_').Update(display)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort - See Janson Ch 7
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ #find smallest value
+ if l[j] < l[smallest]:
+ #swap it to front
+ smallest = j
+ #repeat from next position
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort - See Janson Ch 7
+def qsort_holder(names):
+ l = names[:]
+ #pass List, first and last
+ quick_sort(l, 0, len(l) -1)
+ display_list(l)
+#Quicksort is a partition sort
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ #continue splitting - sort small list
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ window.FindElement('_display_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l= list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display_').Update('Binary search\n' + l[mid] + ' found.')
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ window.FindElement('_display_').Update(value['_binary_'] + ' was \nNot found')
+
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py
new file mode 100644
index 000000000..b39be3bb4
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py
@@ -0,0 +1,137 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+sg.SetOptions(background_color = 'DarkGrey',
+ element_background_color = 'DarkGrey',
+ text_element_background_color = 'DarkGrey',
+ font= ('Calibri', 14, 'bold'))
+
+#setup column (called column1) of buttons to use in layout
+
+column1 = [[sg.ReadButton('Original list', size = (10,1))],
+ [sg.ReadButton('Default sort', size = (10,1))],
+ [sg.ReadButton('Sort: selection',size = (10,1))],
+ [sg.ReadButton('Sort: quick', size = (10,1))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*38,font = ('Calibri', 16))],
+ [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+names= ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+#function to display list
+def display_list(list):
+ global list_displayed
+ #store list in Multiline text globally
+ list_displayed = list
+ #add list elements with new line
+ values = [l for l in list]
+ window.FindElement('_display_').Update(values)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ if l[j] < l[smallest]:
+ smallest = j
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort
+def qsort_holder(names):
+ l = names[:]
+ quick_sort(l, 0, len(l) - 1)
+ display_list(l)
+
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ #Create list for display
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display_').Update(result)
+ break
+ if not found:
+ #Create list for display
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+#Binary Search
+def binary_search():
+ l = list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ #Create list for display
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display_').Update(result)
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ #Create list for display
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py
new file mode 100644
index 000000000..76118d8be
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py
@@ -0,0 +1,148 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import os
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+#get pathname to current file
+
+dirname, filename = os.path.split(os.path.abspath(__file__))
+pathname = os.path.join(dirname, 'Names.txt') #original data
+spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data
+
+#Get data from file
+names = [line.strip() for line in open(pathname)]
+
+column1 = [[sg.ReadButton('Original list', size = (11,1))],
+ [sg.ReadButton('Default sort', size = (11,1))],
+ [sg.ReadButton('Sort: selection',size = (11,1))],
+ [sg.ReadButton('Sort: quick', size = (11,1))],
+ [sg.Text('_________________',font = ('Calibri', 16))],
+ [sg.ReadButton('Save data\ndisplayed', size = (11,2))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*38,font = ('Calibri', 16))],
+ [sg.InputText(size = (11,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (12,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+#function to display list
+def display_list(list):
+ global list_displayed
+ #store list in Multiline text globally
+ list_displayed = list
+ #add list elements with new line
+ values = [l for l in list]
+ window.FindElement('_display_').Update(values)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ if l[j] < l[smallest]:
+ smallest = j
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort
+def qsort_holder(names):
+ l = names[:]
+ quick_sort(l, 0, len(l) - 1)
+ display_list(l)
+
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ #Create list for display
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display_').Update(result)
+ break
+ if not found:
+ #Create list for display
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+#Binary Search
+def binary_search():
+ l = list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ #Create list for display
+ found = True
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display_').Update(result)
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ #Create list for display
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ if button == 'Save data\ndisplayed':
+ f = open(spathname, 'w')
+ for name in list_displayed:
+ print (name, file = f)
+ f.close()
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py
new file mode 100644
index 000000000..e7ba23862
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py
@@ -0,0 +1,67 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import os
+
+#sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = os.path.join(dirname , 'results.txt' )
+
+ #needs validation and try/catch error checking, will crash if blank or text entry for marks
+
+ if button == '_save_':
+ #create dictionary index _m1_ ... _m4_
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+ total += float(value[index])
+ average = total/4
+ #open file and save
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+
+ #some error checking for missing file needed here
+
+ if button == '_display_':
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py
new file mode 100644
index 000000000..412bbb64b
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py
@@ -0,0 +1,72 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import os #to work with windows OS
+
+#sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = os.path.join(dirname , 'results.txt' )
+ #generic catch error - blanks or wrong data types
+ try:
+ if button == '_save_':
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+
+ #Check for values between 0 and 100
+ if float(value[index]) < 0 or float(value[index]) >100:
+ sg.Popup('Out of Range', 'Enter Marks between 0 and 100')
+ else:
+ total += float(value[index])
+ average = total/4
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+ except ValueError:
+ sg.Popup('Error','Check entries and try again')
+
+ if button == '_display_':
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ try:
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ except:
+ sg.PopupError('Error', 'Problem finding or reading file')
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py
new file mode 100644
index 000000000..b3d208a34
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py
@@ -0,0 +1,80 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import os #to work with windows OS
+
+#sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font= ('Calibri', 14, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = os.path.join(dirname , 'results.txt')
+ #generic catch error - blanks or wrong data types
+ try:
+ if button == '_save_':
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+
+ #Check for values between 0 and 100
+ if float(value[index]) < 0 or float(value[index]) >100:
+ sg.Popup('Out of Range', 'Enter Marks between 0 and 100')
+ else:
+ total += float(value[index])
+ average = total/4
+ #check location and file name for file, no_window so go straight to folder selection
+
+ foldername = sg.PopupGetFolder('', no_window=True)
+ filename = sg.PopupGetFile('Please enter a file name for your results')
+ pathname = os.path.join(foldername ,filename + '.txt')
+
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+ except ValueError:
+ sg.Popup('Error','Check entries and try again')
+
+ if button == '_display_':
+ #get pathname: folder and file
+ pathname = sg.PopupGetFile('file to open', no_window=True, file_types=(("text files","*.txt"),))
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ try:
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ except:
+ sg.PopupError('Error', 'Problem finding or reading file')
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py
new file mode 100644
index 000000000..c8b6b85c4
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py
@@ -0,0 +1,40 @@
+#matplotlib, pyplt and csv
+#Tony Crewe
+#Sep 2017 - updated Oct 2018 MacOs
+
+import matplotlib.pyplot as plt
+import csv
+from matplotlib.ticker import MaxNLocator
+
+
+x=[]
+y=[]
+
+with open('weight 2018.csv', 'r', encoding = 'utf-8-sig') as csvfile:
+ plots = csv.reader(csvfile)
+ for data in plots:
+ #get heading for x and y axes
+ var1 = (data[0])
+ var2 = (data[1])
+ break
+ for data in plots:
+ #get values - add to x list and y list
+ x.append(data[0])
+ y.append(float(data[1]))
+
+
+ax = plt.subplot(1,1,1)
+ax.set_ylim([82, 96])
+ax.xaxis.set_major_locator(MaxNLocator(10))
+ax.spines['right'].set_color('none')
+ax.spines['top'].set_color('none')
+
+plt.plot(x,y, label = 'data loaded\nfrom csv file')
+plt.axhline(y = 85.5, color = 'orange', linestyle = '--', label = 'target')
+plt.xlabel(var1)
+plt.ylabel(var2)
+plt.title('weight loss from\n first quarter 2018')
+
+
+plt.legend()
+plt.show()
diff --git a/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py
new file mode 100644
index 000000000..174303cda
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py
@@ -0,0 +1,69 @@
+#PySimple examples (v 3.9.3)
+#Tony Crewe
+#Oct 2018 MacOs
+
+#Based of Example program from MikeTheWatchGuy
+#https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+#sg.ChangeLookAndFeel('BrownBlue')
+sg.SetOptions(background_color = 'LightBlue',
+ element_background_color = 'LightBlue')
+
+def calc_ladder():
+
+ filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),))
+ #populate table with file contents
+ #Assume we know csv has heading in row 1
+ #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown
+ #data is a list of lists containing data about each team
+ #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W,
+ #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A
+ #no error checking or validation used.
+
+ #initialise variable
+ data = []
+ header_list = []
+ #read csv
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range (1):
+ #get headings
+ header = next(reader)
+ #read everything else into a list of rows
+ data = list(reader)
+ #add headings
+ header = header + ['%', 'Pts']
+ for i in range (len(data)):
+ #calculate % and format to 2 decimal places
+ percent = str('{:.2f}'.format(int(data[i][5])/int(data[i][6])*100))
+ data[i] = data[i] + [percent] #add to data
+ pts = int(data[i][2])*4 + int(data[i][4])*2
+ data[i] = data[i] + [pts] #add to data
+
+
+ #use Table (explore settings) and add to column layout
+ #
+ #------ With MacOs -- manually adjust col_widths, auto to False ------------
+ #
+ col_layout = [[sg.Table(values=data, headings=header,col_widths = (16, 4,4,4,4,6,6,7,4), auto_size_columns=False,
+ max_col_width = 30,justification='right', size=(None, len(data)))]]
+
+ layout = [[sg.Column(col_layout, size=(520,360), scrollable=True)],]
+
+ window = sg.Window('AFL Ladder',location = (500, 310), grab_anywhere = False).Layout(layout)
+ b, v = window.Read()
+
+slayout = [[sg.Text('Load AFL file to display results with points and percentage', font = ('Arial', 14, 'bold')),
+ sg.ReadButton('Load File', font = ('Arial', 14, 'bold'), size = (15,1))]]
+swindow = sg.Window('Load File', location = (500,250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ calc_ladder()
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py
new file mode 100644
index 000000000..4071b9717
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py
@@ -0,0 +1,77 @@
+#PySimple examples (v 3.9.3)
+#Tony Crewe
+#Oct 2018 MacOs
+
+#Based of Example program from MikeTheWatchGuy
+#https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+import operator
+
+#sg.ChangeLookAndFeel('Dark')
+sg.SetOptions(background_color = 'LightGrey',
+ element_background_color = 'LightGrey')
+
+def table_example():
+
+ filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),))
+ #populate table with file contents
+ #Assume we know csv has heading in row 1
+ #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown
+ #data is a list of lists containing data about each team
+ #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W,
+ #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A
+ #no error checking or validation used.
+
+ #initialise variables
+ data = []
+ header_list = []
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range (1):
+ header = next(reader)
+ data = list(reader)
+ header = header + ['%', 'Pts']
+ for i in range (len(data)):
+ #calculate %
+ percent = int(data[i][5])/int(data[i][6])*100
+ data[i] = data[i] + [percent]
+ pts = int(data[i][2])*4 + int(data[i][4])*2
+ data[i] = data[i] + [pts]
+ #sort data
+ #first by %
+
+ data.sort(key = operator.itemgetter(7), reverse = True)
+ #then by pts
+
+ data.sort(key = operator.itemgetter(8), reverse = True)
+
+ #and format string to 2 decimal places
+ for i in range(len(data)):
+ data[i][7] = str('{:.2f}'.format(data[i][7]))
+
+ #use Table (explore settings) and add to column layout
+ #
+ #------ With MacOs -- manually adjust col_widths, auto to False ------------
+ #
+ col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,7,4), auto_size_columns=False,
+ max_col_width = 30,justification='right', size=(None, len(data)))]]
+
+ layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],]
+
+ window = sg.Window('Ladder', location = (350, 310), grab_anywhere = False).Layout(layout)
+ b, v = window.Read()
+
+slayout = [[sg.Text(' Load AFL (csv) file to display sorted results.', font = ('Calibri', 16, 'bold')),
+ sg.ReadButton('Load File', font = ('Calibri', 16, 'bold'), button_color = ('Red', 'White'), size = (10,1))]]
+swindow = sg.Window('Load File', location = (350,250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ table_example()
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py
new file mode 100644
index 000000000..c2fe109b5
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py
@@ -0,0 +1,71 @@
+#PySimple examples (v 3.9.3)
+#Tony Crewe
+#Oct 2018 MacOs
+
+#Based of Example program from MikeTheWatchGuy
+#https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+import operator
+import os
+
+sg.SetOptions(background_color = 'Black',
+ element_background_color = 'Black',
+ font = ('Calibri', 16, 'bold'),
+ text_color = 'White')
+
+#get pathname to current file and add file name for image
+dirname, filename = os.path.split(os.path.abspath(__file__))
+
+pathname = os.path.join(dirname , 'AFL.png' )
+
+def table_example():
+
+ filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),))
+
+
+ data = []
+ header_list = []
+
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range (1):
+ header = next(reader)
+ data = list(reader)
+ header = header + ['%', 'Pts']
+ for i in range (len(data)):
+
+ percent = int(data[i][5])/int(data[i][6])*100
+ data[i] = data[i] + [percent]
+
+ pts = int(data[i][2])*4 + int(data[i][4])*2
+ data[i] = data[i] + [pts]
+
+ data.sort(key = operator.itemgetter(7), reverse = True)
+ data.sort(key = operator.itemgetter(8), reverse = True)
+
+ for i in range(len(data)):
+ data[i][7] = str('{:.2f}'.format(data[i][7]))
+
+ col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,6,4), auto_size_columns=False,
+ max_col_width = 30,justification='right', size=(None, len(data)))]]
+
+ layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],]
+
+ window = sg.Window('Table', no_titlebar = False, location = (350, 318), grab_anywhere = False).Layout(layout)
+ b, v = window.Read()
+
+slayout = [[sg.Image(pathname),sg.Text(' Load AFL (csv) file to display results. '),
+ sg.ReadButton('Load File', size = (10,1))]]
+swindow = sg.Window('Load File', location = (350,250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ table_example()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py
new file mode 100644
index 000000000..312af3b4a
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py
@@ -0,0 +1,52 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Sep 2018 MacOs
+
+import PySimpleGUI as sg
+
+#sg.ChangeLookAndFeel('SandyBeach')
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 14, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('Blue', 'White')
+ )
+
+layout0 = [[sg.ReadButton('Show/Hide window1'),sg.ReadButton('Show/Hide window2')]]
+
+layout1 =[[ sg.Text('window1')], [sg.Multiline( size = (35, 10))]]
+layout2 =[[ sg.Text('window2')], [sg.Multiline( size = (35, 10))]]
+window0 = sg.Window('Home Window', location = (200, 140)).Layout(layout0)
+
+window1 = sg.Window('Window1', location = (200, 200)).Layout(layout1).Finalize()
+window1.Hide()
+w1 = False
+
+window2 = sg.Window('Window2', location = (600, 200)).Layout(layout2).Finalize()
+window2.Hide()
+w2 = False
+
+while True:
+ button, v = window0.Read()
+ if button is not None:
+ if button =='Show/Hide window1':
+ if w1 == True:
+ window1.Hide()
+ w1 = False
+ else:
+ window1.UnHide()
+ w1=True
+ if button =='Show/Hide window2':
+ if w2 == True:
+ window2.Hide()
+ w2 = False
+ else:
+ window2.UnHide()
+ w2=True
+ else:
+ break
+
+
+
diff --git a/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py
new file mode 100644
index 000000000..7c4ec0f5a
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py
@@ -0,0 +1,22 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+
+tab1_layout = [[sg.Text('This is inside tab 1')]]
+
+tab2_layout = [[sg.Text('This is inside tab 2')]]
+
+layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout),
+ sg.Tab('Tab 2', tab2_layout)]])],
+ [sg.ReadButton('Read')]]
+
+window = sg.Window('Main Window').Layout(layout)
+
+while True:
+ b, v = window.Read()
+ if b is not None:
+ print(b,v)
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py
new file mode 100644
index 000000000..b69965e38
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py
@@ -0,0 +1,89 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018 MacOs
+
+import PySimpleGUI as sg
+import os
+
+#sg.ChangeLookAndFeel('BlueMono')
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 12, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('Blue', 'White'))
+
+#get pathname to current file
+
+dirname, filename = os.path.split(os.path.abspath(__file__))
+pathname = os.path.join(dirname , 'Names.txt' )
+
+#Get data from file
+names = [line.strip() for line in open(pathname)]
+sorted_names = names[:]
+sorted_names.sort()
+
+tab1_layout =[[sg.Text('Linear Search Demo', font =('Calibri', 14, 'bold'))],
+ [sg.Listbox(values =[n for n in names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display1_')],
+ [sg.Text('_'*25,font = ('Calibri', 12))],
+ [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))],
+ [sg.InputText(size = (15,1), key = '_linear_')],
+ [sg.ReadButton('Linear Search', font = ('Calibri', 14, 'bold'), size = (11,1))]]
+
+tab2_layout = [[sg.Text('Binary Search Demo', font =('Calibri', 14, 'bold'))],
+ [sg.Listbox(values =[n for n in sorted_names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*25,font = ('Calibri', 12))],
+ [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))],
+ [sg.InputText(size = (15,1), key = '_binary_')],
+ [sg.ReadButton('Binary Search',font = ('Calibri', 14, 'bold'), size = (11,1))]]
+
+layout = [
+ [sg.TabGroup([[sg.Tab('Linear Search', tab1_layout),sg.Tab('Binary Search', tab2_layout)]])]]
+
+window = sg.Window('Main Window').Layout(layout)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']: #Check each value
+ found = True
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display1_').Update(result)
+ break
+ if not found:
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display1_').Update(result)
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ found = True
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display2_').Update(result)
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display2_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
diff --git a/ProgrammingClassExamples/MacOS versions/AFL.png b/ProgrammingClassExamples/MacOS versions/AFL.png
new file mode 100644
index 000000000..ee3a35597
Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/AFL.png differ
diff --git a/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv
new file mode 100644
index 000000000..798296f6e
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv
@@ -0,0 +1,19 @@
+Team,P,W,L,D,F,A
+Adelaide Crows,22,12,10,0,1941,1865
+Brisbane Lions,22,5,17,0,1825,2049
+Carlton,22,2,20,0,1353,2282
+Collingwood,22,15,7,0,2046,1699
+Essendon,22,12,10,0,1932,1838
+Fremantle,22,8,14,0,1556,2041
+Geelong Cats,22,13,9,0,2045,1554
+Gold Coast Suns,22,4,18,0,1308,2182
+GWS Giants,22,13,8,1,1898,1661
+Hawthorn,22,15,7,0,1972,1642
+Melbourne,22,14,8,0,2299,1749
+North Melbourne,22,12,10,0,1950,1790
+Port Adelaide,22,12,10,0,1780,1654
+Richmond,22,18,4,0,2143,1574
+St Kilda,22,4,17,1,1606,2125
+Sydney Swans,22,14,8,0,1822,1664
+West Coast Eagles,22,16,6,0,2012,1657
+Western Bulldogs,22,8,14,0,1575,2037
diff --git a/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv
new file mode 100644
index 000000000..71cb8c18a
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv
@@ -0,0 +1,19 @@
+Team,P,W,L,D,F,A
+Richmond,22,18,4,0,2143,1574
+West Coast Eagles,22,16,6,0,2012,1657
+Collingwood,22,15,7,0,2046,1699
+Hawthorn,22,15,7,0,1972,1642
+Melbourne,22,14,8,0,2299,1749
+Sydney Swans,22,14,8,0,1822,1664
+GWS Giants,22,13,8,1,1898,1661
+Geelong Cats,22,13,9,0,2045,1554
+North Melbourne,22,12,10,0,1950,1790
+Port Adelaide,22,12,10,0,1780,1654
+Essendon,22,12,10,0,1932,1838
+Adelaide Crows,22,12,10,0,1941,1865
+Western Bulldogs,22,8,14,0,1575,2037
+Fremantle,22,8,14,0,1556,2041
+Brisbane Lions,22,5,17,0,1825,2049
+St Kilda,22,4,17,1,1606,2125
+Gold Coast Suns,22,4,18,0,1308,2182
+Carlton,22,2,20,0,1353,2282
diff --git a/ProgrammingClassExamples/MacOS versions/Gym_Logo.png b/ProgrammingClassExamples/MacOS versions/Gym_Logo.png
new file mode 100644
index 000000000..45bb5f7bc
Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/Gym_Logo.png differ
diff --git a/ProgrammingClassExamples/MacOS versions/Names(sorted).txt b/ProgrammingClassExamples/MacOS versions/Names(sorted).txt
new file mode 100644
index 000000000..eb2415c84
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/Names(sorted).txt
@@ -0,0 +1,10 @@
+Andrea
+Belinda
+Deborah
+Helen
+Jenny
+Kylie
+Meredith
+Pauline
+Roberta
+Wendy
diff --git a/ProgrammingClassExamples/MacOS versions/Names.txt b/ProgrammingClassExamples/MacOS versions/Names.txt
new file mode 100644
index 000000000..d1b9fd24d
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/Names.txt
@@ -0,0 +1,10 @@
+Roberta
+Kylie
+Jenny
+Helen
+Andrea
+Meredith
+Deborah
+Pauline
+Belinda
+Wendy
\ No newline at end of file
diff --git a/ProgrammingClassExamples/MacOS versions/Test.txt b/ProgrammingClassExamples/MacOS versions/Test.txt
new file mode 100644
index 000000000..6f15df0a6
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/Test.txt
@@ -0,0 +1,3 @@
+T
+202.0
+50.5
diff --git a/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt
new file mode 100644
index 000000000..5ee47eaf9
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt
@@ -0,0 +1,3 @@
+Tony
+158.0
+39.5
diff --git a/ProgrammingClassExamples/MacOS versions/default_icon.ico b/ProgrammingClassExamples/MacOS versions/default_icon.ico
new file mode 100644
index 000000000..1a41525ec
Binary files /dev/null and b/ProgrammingClassExamples/MacOS versions/default_icon.ico differ
diff --git a/ProgrammingClassExamples/MacOS versions/results.txt b/ProgrammingClassExamples/MacOS versions/results.txt
new file mode 100644
index 000000000..0d13392a0
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/results.txt
@@ -0,0 +1,3 @@
+Tony
+224.0
+56.0
diff --git a/ProgrammingClassExamples/MacOS versions/weight 2018.csv b/ProgrammingClassExamples/MacOS versions/weight 2018.csv
new file mode 100644
index 000000000..66e7c2d97
--- /dev/null
+++ b/ProgrammingClassExamples/MacOS versions/weight 2018.csv
@@ -0,0 +1,98 @@
+Date,Weight (kg)
+29-Dec,94.5
+30-Dec,94
+31-Dec,94
+1-Jan,93.5
+2-Jan,94.2
+3-Jan,94
+4-Jan,94
+5-Jan,93.4
+6-Jan,92.6
+7-Jan,93.1
+8-Jan,92.7
+9-Jan,92.5
+10-Jan,92.3
+11-Jan,92.1
+12-Jan,92.5
+13-Jan,92.6
+14-Jan,92.5
+15-Jan,92.1
+16-Jan,91.6
+17-Jan,91.3
+18-Jan,91.8
+19-Jan,91.7
+20-Jan,91.9
+21-Jan,91.8
+22-Jan,91.1
+23-Jan,90.7
+24-Jan,90.5
+25-Jan,90.5
+26-Jan,90.3
+27-Jan,90.1
+28-Jan,89.9
+29-Jan,90.2
+30-Jan,90.1
+31-Jan,89.9
+1-Feb,89.5
+2-Feb,89.1
+3-Feb,89.3
+4-Feb,89.4
+5-Feb,89.2
+6-Feb,88.2
+7-Feb,88.2
+8-Feb,88.3
+9-Feb,88.2
+10-Feb,89.1
+11-Feb,88.9
+12-Feb,88.6
+13-Feb,88.7
+14-Feb,88.5
+15-Feb,88.1
+16-Feb,87.8
+17-Feb,87.9
+18-Feb,88.1
+19-Feb,87.9
+20-Feb,87.6
+21-Feb,87.5
+22-Feb,87.3
+23-Feb,87
+24-Feb,87.5
+25-Feb,87.7
+26-Feb,87.4
+27-Feb,87.2
+28-Feb,86.9
+1-Mar,86.9
+2-Mar,86.9
+3-Mar,86.5
+4-Mar,86.8
+5-Mar,87
+6-Mar,86.9
+7-Mar,86.2
+8-Mar,86.4
+9-Mar,86.1
+10-Mar,86.7
+11-Mar,85.6
+12-Mar,85.8
+13-Mar,85.3
+14-Mar,85.1
+15-Mar,85.4
+16-Mar,84.5
+17-Mar,85.1
+18-Mar,84.8
+19-Mar,84.8
+20-Mar,84.8
+21-Mar,84.9
+22-Mar,85.5
+23-Mar,85.1
+24-Mar,85.5
+25-Mar,85.6
+26-Mar,85.9
+27-Mar,85.9
+28-Mar,85.5
+29-Mar,85.9
+30-Mar,85.5
+1-Apr,85.2
+2-Apr,84.8
+3-Apr,85.3
+4-Apr,85.4
+5-Apr,85.3
diff --git a/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py
new file mode 100644
index 000000000..9847f3be3
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py
@@ -0,0 +1,62 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+Adapted: From https://gitlab.com/lotspaih/PySimpleGUI/tree/master
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+"""
+
+#No exactly sure how all this works, but taken from example given as a template.
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code ----------------------
+#see https://matplotlib.org/
+fig = plt.figure()
+ax = fig.add_subplot(111)
+#x-values
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+#y-values
+y = np.sin(x)
+plt.plot(x,y)
+
+ax.set_title('sin(x)')
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py
new file mode 100644
index 000000000..4a7aade10
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py
@@ -0,0 +1,54 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+fig=plt.figure()
+ax = fig.add_subplot(111)
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+y= np.sin(x)
+plt.plot(x,y)
+
+ax.set_title('sin(x)')
+
+#centre bottom and left axes to zero
+
+ax.spines['left'].set_position('zero')
+ax.spines['right'].set_color('none')
+ax.spines['bottom'].set_position('zero')
+ax.spines['top'].set_color('none')
+
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes centred)', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py
new file mode 100644
index 000000000..d4f9ca2ef
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py
@@ -0,0 +1,68 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+"""
+Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
+
+Basic steps are:
+ * Create a Canvas Element
+ * Layout form
+ * Display form (NON BLOCKING)
+ * Draw plots onto convas
+ * Display form (BLOCKING)
+"""
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+fig=plt.figure()
+ax = fig.add_subplot(111)
+x = np.linspace(-np.pi*2, np.pi*2, 100)
+y= np.sin(x)
+plt.plot(x/np.pi,y)
+
+ax.set_title('sin(x)')
+#centre bottom and left axes to zero
+
+ax.spines['left'].set_position('zero')
+ax.spines['right'].set_color('none')
+ax.spines['bottom'].set_position('zero')
+ax.spines['top'].set_color('none')
+
+#Format axes - nicer eh!
+ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+
+#------------End Matplotlib code --------------------
+
+layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes pi format)', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+button, value = window.Read()
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py
new file mode 100644
index 000000000..b0bbc2f95
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py
@@ -0,0 +1,90 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(amp, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-np.pi*2, np.pi*2, 100)
+ if function == 'sine':
+ y= amp*np.sin(x)
+ ax.set_title('sin(x)')
+ else:
+ y=amp*np.cos(x)
+ ax.set_title('cos(x)')
+ plt.plot(x/np.pi,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+ #Format axes - nicer eh!
+ ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'sine'
+set_plot(amp, function)
+
+#------------End Matplotlib code --------------------
+
+#use Tabs - one for options, one for canvas to be displayed
+#set spinner for amplitude and combo for function type
+
+tab1_layout = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))],
+ [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'),
+ sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))],
+ [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))],
+ [sg.ReadButton('Redraw Plot')],
+ [sg.Text('', size = (2, 25))]]
+
+tab2_layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+layout = [[sg.TabGroup([[sg.Tab('Select options', tab1_layout), sg.Tab('Display Plot', tab2_layout)]])]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ amp = int(value['_spin_'])
+ function = value['_function_']
+ set_plot(amp,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py b/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py
new file mode 100644
index 000000000..f6d1a25ef
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py
@@ -0,0 +1,88 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(amp, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-np.pi*2, np.pi*2, 100)
+ if function == 'sine':
+ y= amp*np.sin(x)
+ ax.set_title('sin(x)')
+ else:
+ y=amp*np.cos(x)
+ ax.set_title('cos(x)')
+ plt.plot(x/np.pi,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+ #Format axes - nicer eh!
+ ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$'))
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'sine'
+set_plot(amp, function)
+
+#------------End Matplotlib code --------------------
+
+#using one window based on two columns instead of Tabs
+column1 = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))],
+ [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'),
+ sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))],
+ [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))],
+ [sg.ReadButton('Redraw Plot')],
+ [sg.Text('', size = (1, 27))]]
+
+column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]]
+
+layout = [[sg.Column(column1), sg.Column(column2)]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ amp = int(value['_spin_'])
+ function = value['_function_']
+ set_plot(amp,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py
new file mode 100644
index 000000000..b208bd76c
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py
@@ -0,0 +1,111 @@
+#matplotlib, numpy, pyplot
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+import matplotlib.pyplot as plt
+import matplotlib.ticker as ticker
+from matplotlib.backends.backend_tkagg import FigureCanvasAgg
+import matplotlib.backends.tkagg as tkagg
+import numpy as np
+import tkinter as tk
+
+sg.ChangeLookAndFeel('Black')
+sg.SetOptions(font = ('Calibri', 14, 'bold'))
+
+def draw_figure(canvas, figure, loc = (0,0)):
+
+ figure_canvas_agg = FigureCanvasAgg(figure)
+ figure_canvas_agg.draw()
+ figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds
+ figure_w, figure_h = int(figure_w), int(figure_h)
+ photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h)
+ canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo)
+ tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
+ return photo
+
+
+#------------ Matplotlib code --------------------
+
+def set_plot(a,b,c, function):
+ global figure_w, figure_h, fig
+ fig=plt.figure()
+ ax = fig.add_subplot(111)
+ x = np.linspace(-10, 10, 100)
+ if function == 'y = ax + b':
+ y= a*x + b
+ if a == 1:
+ a = ''
+ if a == -1:
+ a = '-'
+ title = str('y = ') + str(a) + 'x + ' + str(b)
+ ax.set_title(title)
+ else:
+ y = a*x**2 + b*x + c
+ #avoiding getting -1x or -1x**2 instead of -x for title
+ if a == 1:
+ a = ''
+ if a == -1:
+ a = '-'
+ if b == 1:
+ b = ''
+ if b == -1:
+ b = '-'
+ title = str('y = ') + str(a) + 'x**2 + ' + str(b) + 'x + ' + str(c)
+ ax.set_title(title)
+ plt.plot(x,y)
+
+
+ #centre bottom and left axes to zero
+
+ ax.spines['left'].set_position('zero')
+ ax.spines['right'].set_color('none')
+ ax.spines['bottom'].set_position('zero')
+ ax.spines['top'].set_color('none')
+
+
+ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
+amp = 1
+function = 'y = ax + b'
+set_plot(1,1,1, function)
+
+#------------End Matplotlib code --------------------
+
+#column 1 for function type and constant values ...
+
+column1 = [
+ [sg.Text('Select constants & function type', )],
+ [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'),
+ sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))],
+ [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'),
+ sg.Text('a', size = (3, 1)),
+ sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'),
+ sg.Text('b', size = (3, 1)),
+ sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'),
+ sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))],
+ [sg.ReadButton('Redraw Plot', button_color = ('White', 'Red'))],
+ [sg.Text('', size = (1, 14))]]
+
+column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')],
+ [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')],
+ [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1), button_color = ('White', 'Red'))]]
+
+layout = [[sg.Column(column1), sg.Column(column2)]]
+window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize()
+
+fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+while True:
+ button, value = window.Read()
+ if button == 'Redraw Plot':
+ a = int(value['_a_'])
+ b = int(value['_b_'])
+ c = int(value['_c_'])
+ function = value['_function_']
+ set_plot(a,b,c,function)
+ fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig)
+
+ if button is None:
+ break
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py
new file mode 100644
index 000000000..1b7b9ded7
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py
@@ -0,0 +1,36 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#layout, Text, Input,button on line below
+layout = [
+ [sg.Text('Celcius'), sg.InputText()],
+ [sg.Submit()],
+ ]
+
+#setup window with Title
+window = sg.Window('Temperature Converter').Layout(layout)
+
+#get value (part of a list)
+button, value = window.Read()
+if button is None:
+ #windows was closed without button being pressed
+ exit(0)
+
+#convert and create string
+fahrenheit = round(9/5*float(value[0]) +32, 1)
+result = 'Temperature in Fahrenheit is: ' + str(fahrenheit)
+#display in Popup
+sg.Popup('Result', result)
+
+
+
+
+
+
+
+
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py
new file mode 100644
index 000000000..2b65953fe
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py
@@ -0,0 +1,39 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#Set formatting options for all elements rather than individually.
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 10, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('White', 'Blue')
+ )
+#adjust widths
+layout = [
+ [sg.Text('Celcius', size =(12,1)), sg.InputText(size = (8,1))],
+ [sg.Submit()]
+ ]
+
+window = sg.Window('Converter').Layout(layout)
+button, value = window.Read()
+if button is None:
+ #windows was closed without button being pressed
+ exit(0)
+fahrenheit = round(9/5*float(value[0]) +32, 1)
+result = 'Temperature in Fahrenheit is: ' + str(fahrenheit)
+sg.Popup('Result',result)
+
+
+
+
+
+
+
+
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py
new file mode 100644
index 000000000..ee46d08f5
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py
@@ -0,0 +1,35 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 10, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('White', 'Blue')
+ )
+#update (via list) values and and display answers
+#value[0] is celcius input, value[1] is input to place result.
+#Use ReadButton with while true: - keeps window open.
+
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1))],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1))],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+#Return = button press
+window = sg.Window('Converter').Layout(layout)
+
+while True:
+ #get result
+ button, value = window.Read()
+ #break out of loop is button not pressed.
+ if button is not None:
+ fahrenheit = round(9/5*float(value[0]) +32, 1)
+ #put result in 2nd input box
+ window.FindElement(1).Update(fahrenheit)
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py
new file mode 100644
index 000000000..2aa09f44d
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py
@@ -0,0 +1,36 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (background_color = 'LightBlue',
+ element_background_color = 'LightBlue',
+ text_element_background_color = 'LightBlue',
+ font = ('Arial', 10, 'bold'),
+ text_color = 'Blue',
+ input_text_color ='Blue',
+ button_color = ('White', 'Blue')
+ )
+#name inputs (key) uses dictionary- easy to see updating of results
+#value[input] first input value te c...
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+
+window = sg.FlexForm('Temp Converter').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #catch program errors for text or blank entry:
+ try:
+ fahrenheit = round(9/5*float(value['_input_']) +32, 1)
+ #put result in text box
+ window.FindElement('_result_').Update(fahrenheit)
+ except ValueError:
+ sg.Popup('Error','Please try again')
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py
new file mode 100644
index 000000000..3db950a1b
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py
@@ -0,0 +1,34 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#Can use a variety of themes - plus individual options
+sg.ChangeLookAndFeel('SandyBeach')
+sg.SetOptions (font = ('Arial', 10, 'bold'))
+
+
+layout = [ [sg.Text('Enter a Temperature in Celcius')],
+ [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')],
+ [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')],
+ [sg.ReadButton('Submit', bind_return_key = True)]]
+
+window = sg.Window('Temp Converter').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #catch program errors for text, floats or blank entry:
+ #Also validation for range [0, 50]
+ try:
+ if float(value['_input_']) > 50 or float(value['_input_']) <0:
+ sg.Popup('Error','Out of range')
+ else:
+ fahrenheit = round(9/5*int(value['_input_']) +32, 1)
+ window.FindElement('_result_').Update(fahrenheit)
+ except ValueError:
+ sg.Popup('Error','Please try again')
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py
new file mode 100644
index 000000000..c5f9cacb4
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py
@@ -0,0 +1,44 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#Set colour scheme and font
+sg.ChangeLookAndFeel('GreenTan')
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+
+
+#One checkbox and three radio buttons (grouped as 'Radio1')
+#value[0] - checkbox, Value[1-3] radiobutton selection
+layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))],
+ [sg.Checkbox(' Student? 10% off', size = (25,1)),
+ sg.ReadButton('Display Cost', size = (14,1))],
+ [sg.Radio('1 month $50', 'Radio1', default = True),
+ sg.Radio('3 months $100', 'Radio1'),
+ sg.Radio('1 year $300', 'Radio1')],
+ [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]]
+
+window = sg.Window('Gym Membership').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[1]:
+ cost = 50
+ elif value[2]:
+ cost = 100
+ else:
+ cost = 300
+ if value[0]:
+ #apply discount
+ cost = cost*0.9
+
+ #format as currency $ symbol and 2 d.p. - make a string
+ result = str(' Cost: ' + '${:.2f}'.format(cost))
+ #put the result in Textbox
+ window.FindElement('result').Update(result)
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py
new file mode 100644
index 000000000..cf35f47d2
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py
@@ -0,0 +1,42 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+import os
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+#get pathname to current file
+dirname, filename = os.path.split(os.path.abspath(__file__))
+#add file name for image
+pathname = os.path.join(dirname ,'Gym_Logo.png')
+
+layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))],
+ [sg.Checkbox(' Student? 10% off', size = (25,1)),
+ sg.ReadButton('Display Cost', size = (14,1))],
+ [sg.Radio('1 month $50', 'Radio1', default = True),
+ sg.Radio('3 months $100', 'Radio1'),
+ sg.Radio('1 year $300', 'Radio1')],
+ [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]]
+
+window = sg.Window('Gym Membership').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[1]:
+ cost = 50
+ elif value[2]:
+ cost = 100
+ else:
+ cost = 300
+ if value[0]:
+ cost = cost*0.9
+
+ #format as currency $ symbol and 2 d.p. - make a string
+ result = str(' Cost: ' + '${:.2f}'.format(cost))
+ window.FindElement('result').Update(result)
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py b/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py
new file mode 100644
index 000000000..351f082d1
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py
@@ -0,0 +1,36 @@
+import PySimpleGUI as sg
+#pip install PyInstaller
+#windows command prompt pyinstaller -wF 2b_makewinexe_file.py
+#must CD to directory where py file is
+
+sg.ChangeLookAndFeel('GreenTan') #Set colour scheme
+sg.SetOptions (font =('Calibri',12,'bold') ) #and font
+
+form = sg.FlexForm('Gym Membership')
+
+
+layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))],
+ [sg.Checkbox('CGS student?', size = (22,1)), #value[0]
+ sg.ReadButton('Display Cost', size = (14,1))],
+ [sg.Radio('One Month', 'Radio1', default = True), #value[1]
+ sg.Radio('Three Month', 'Radio1'), #value[2]
+ sg.Radio('One Year', 'Radio1')], #value[3]
+ [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]]
+
+form.Layout(layout)
+while True:
+ button, value = form.Read()
+ if button is not None:
+ if value[1]:
+ cost = 50
+ elif value[2]:
+ cost = 100
+ else:
+ cost = 300
+ if value[0]:
+ cost = cost*0.9
+ result = str(' Cost: ' + '${:.2f}'.format(cost)) #format as currency - make a string
+ form.FindElement('result').Update(result) #put the result in Textbox
+
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py b/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py
new file mode 100644
index 000000000..1f6e50433
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py
@@ -0,0 +1,41 @@
+
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.ChangeLookAndFeel('GreenTan')
+
+sg.SetOptions(font = ('Courier New', 12))
+
+
+
+layout = [
+ [sg.Text('Enter and Add Data to Display', font = ('Calibri', 14,'bold'))],
+ [sg.Text('Race:', size = (5,1)), sg.InputText(size = (8,1)),
+ sg.Text('Club:', size = (5,1)), sg.InputText(size = (8,1))],
+ [sg.Text('Name:', size = (5,1)), sg.InputText(size = (8,1)),
+ sg.Text('Time:', size = (5,1)), sg.InputText(size = (8,1)),sg.Text(' '),
+ sg.ReadButton('Add Data', font = ('Calibri', 12, 'bold'))],
+ [sg.Text('_'*40)],
+ [sg.Text(' Race Club Name Time')],
+ [sg.Multiline(size =(40,6),key = '_multiline_')]
+ ]
+
+window = sg.Window('Enter & Display Data').Layout(layout)
+
+string = ''
+S=[]
+while True:
+
+ button, value = window.Read()
+ if button is not None:
+ #use string formatting - best way? plus Courier New font - non-proportional font
+ S = S + ['{:^9s}{:<11s}{:<10s}{:>8s}'.format(value[0],value[1],value[2],value[3])]
+ for s in S:
+ string = string + s + '\n'
+ window.FindElement('_multiline_').Update(string)
+ string =''
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py
new file mode 100644
index 000000000..ed19269f7
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py
@@ -0,0 +1,48 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+#use of Column to help with layout - vertical sliders take up space
+
+column1 = [
+ [sg.Text('Pick operation', size = (15,1), font = ('Calibri', 12, 'bold'))],
+ [sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (10,6))],
+ [sg.Text('', size =(1,4))]]
+column2 = [
+ [sg.ReadButton('Submit', font = ('Calibri', 12, 'bold'), button_color = ('White', 'Red'))],
+ [sg.Text('Result:', font = ('Calibri', 12, 'bold'))],[sg.InputText(size = (12,1), key = '_result_')]
+ ]
+
+
+layout = [
+ [sg.Text('Slider and Combo box demo', font = ('Calibri', 14,'bold'))],
+ [sg.Slider(range = (-9, 9),orientation = 'v', size = (5,20), default_value = 0),
+ sg.Slider(range = (-9, 9),orientation = 'v', size = (5, 20), default_value = 0),
+ sg.Text(' '), sg.Column(column1), sg.Column(column2)]]
+
+#added grab_anywhere to when moving slider, who window doesn't move.
+
+window = sg.Window('Enter & Display Data',grab_anywhere = False).Layout(layout)
+
+#Get selection from combo: value[2]
+#Slider values: value[0] and value[1]
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if value[2] == 'Add':
+ result = value[0] + value[1]
+ elif value[2] == 'Multiply':
+ result = value[0] * value[1]
+ elif value[2] == 'Subtract':
+ result = value[0] - value[1]
+ elif value[2] == 'Divide': #check for zero
+ if value[1] ==0:
+ sg.Popup('Second value can\'t be zero')
+ result = 'NA'
+ else:
+ result = value[0] / value[1]
+ window.FindElement('_result_').Update(result)
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py
new file mode 100644
index 000000000..47d8a1a61
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py
@@ -0,0 +1,39 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+sg.SetOptions(font= ('Calibri', 12, 'bold'))
+
+layout = [
+ [sg.Text('Spinner and Combo box demo', font = ('Calibri', 14, 'bold'))],
+ [sg.Spin([sz for sz in range (-9,10)], size = (2,1),initial_value = 0),
+ sg.Spin([sz for sz in range (-9,10)], size = (2,1), initial_value = 0),
+ sg.Text('Pick operation ->', size = (15,1)),
+ sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (8,6))],
+ [sg.Text('Result: ')],[sg.InputText(size = (5,1), key = '_result_'),
+ sg.ReadButton('Calculate', button_color = ('White', 'Red'))]]
+
+window = sg.Window('Enter & Display Data', grab_anywhere= False).Layout(layout)
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ #convert returned values to integers
+ val = [int(value[0]), int(value[1])]
+ if value[2] == 'Add':
+ result = val[0] + val[1]
+ elif value[2] == 'Multiply':
+ result = val[0] * val[1]
+ elif value[2] == 'Subtract':
+ result = val[0] - val[1]
+ elif value[2] == 'Divide':
+ if val[1] ==0:
+ sg.Popup('Second value can\'t be zero')
+ result = 'NA'
+ else:
+ result = round( val[0] / val[1], 3)
+ window.FindElement('_result_').Update(result)
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py
new file mode 100644
index 000000000..24833c78f
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py
@@ -0,0 +1,44 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.ChangeLookAndFeel('BlueMono')
+
+#use column feature with height listbox takes up
+column1 = [
+ [sg.Text('Add or Delete Items\nfrom a Listbox', font = ('Arial', 12, 'bold'))],
+ [sg.InputText( size = (15,1), key = 'add'), sg.ReadButton('Add')],
+ [sg.ReadButton('Delete selected entry')]]
+
+#initial listbox entries
+List = ['Austalia', 'Canada', 'Greece']
+
+#add initial List to listbox
+layout = [
+ [sg.Listbox(values=[l for l in List], size = (30,8), key ='_listbox_'),
+ sg.Column(column1)]]
+
+window = sg.Window('Listbox').Layout(layout)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #value[listbox] returns a list
+ #using value[listbox][0] gives the string
+ if button == 'Delete selected entry':
+ #ensure something is selected
+ if value['_listbox_'] == []:
+ sg.Popup('Error','You must select a Country')
+ else:
+ #find and remove this
+ List.remove(value['_listbox_'][0])
+ if button == 'Add':
+ #add string in add box to list
+ List.append(value['add'])
+ List.sort()
+ #update listbox
+ window.FindElement('_listbox_').Update(List)
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py b/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py
new file mode 100644
index 000000000..18bb76a28
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py
@@ -0,0 +1,86 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'),
+ sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1)), sg.ReadButton('Binary Search', size = (14,1))],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#names for Demo, could be loaded from a file
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+#function to display list
+def display_list(list, display):
+ names = ''
+ for l in list: #add list elements with new line
+ names = names + l + '\n'
+ window.FindElement(display).Update(names)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']: #Check each value
+ found = True
+ window.FindElement('_display1_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ #Start with found is False
+ found = False
+ while lo <= hi:
+ #Start in middle
+ mid = (lo + hi) //2
+ #get the value from the search box
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.')
+ #If found display name and stop
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ #Search in top half
+ lo = mid + 1
+ else:
+ #Search in lower half
+ hi = mid - 1
+ #If we get to end - display not found
+ if not found:
+ window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found')
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ #show names - unordered and sorted
+ if button == 'Show Names':
+ display_list(names,'_display1_')
+ display_list(sorted_names, '_display2_')
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py
new file mode 100644
index 000000000..f617e471b
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py
@@ -0,0 +1,95 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'),
+ sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1),key = '_ls_'), sg.ReadButton('Binary Search', size = (14,1),key='_bs_')],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#finalize allows the disabling of the two buttons before .Read statement
+window.Finalize()
+window.FindElement('_ls_').Update(disabled = True)
+window.FindElement('_bs_').Update(disabled = True)
+
+#names for Demo, could be loaded from a file
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+#function to display list
+def display_list(list, display):
+ names = ''
+ #add list elements with new line
+ for l in list:
+ names = names + l + '\n'
+ window.FindElement(display).Update(names)
+ #enable buttons now data loaded
+ window.FindElement('_ls_').Update(disabled = False)
+ window.FindElement('_bs_').Update(disabled = False)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ #Check each value
+ if l == value['_linear_']:
+ found = True
+ window.FindElement('_display1_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ #Start with found is Flase
+ found = False
+ while lo <= hi:
+ #Start in middle
+ mid = (lo + hi) //2
+ #get the value from the search box
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.')
+ #If found display and stop
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ #Search in top half
+ lo = mid + 1
+ else:
+ #Search in lower half
+ hi = mid - 1
+ #If we get to end - display not found
+ if not found:
+ window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found')
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ #show names - unordered and sorted
+ if button == 'Show Names':
+ display_list(names,'_display1_')
+ display_list(sorted_names, '_display2_')
+ if button == '_ls_':
+ linear_search()
+ if button == '_bs_':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py
new file mode 100644
index 000000000..89009642c
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py
@@ -0,0 +1,76 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+#names for Demo, could be loaded from a file
+
+names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+name = ''
+for l in names:
+ name = name + l + '\n'
+
+sorted_names = ['Andrea','Belinda','Deborah','Helen',
+ 'Jenny','Kylie','Meredith','Pauline',
+ 'Roberta','Wendy']
+
+sortname = ''
+for l in sorted_names:
+ sortname = sortname + l +'\n'
+
+layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold'))],
+[sg.Text(name, size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display1_'),
+ sg.Text(sortname, size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display2_')],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (14,1), key = '_linear_'), sg.InputText(size = (14,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1)), sg.ReadButton('Binary Search', size = (14,1))],
+ ]
+window = sg.Window('Search Demo').Layout(layout)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ sg.Popup('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ sg.Popup('Linear search\n' +(value['_linear_'] + ' was not found'))
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ sg.Popup('Binary search\n' + l[mid] + ' found.')
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ sg.Popup('Binary search\n' +(value['_binary_'] + ' was not found'))
+
+while True:
+ button, value = window.Read()
+
+ if button is not None:
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py
new file mode 100644
index 000000000..90a7f9af5
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py
@@ -0,0 +1,137 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+
+#setup column (called column1) of buttons to use in layout
+
+column1 = [[sg.ReadButton('Original list', size = (13,1))],
+ [sg.ReadButton('Default sort', size = (13,1))],
+ [sg.ReadButton('Sort: selection',size = (13,1))],
+ [sg.ReadButton('Sort: quick', size = (13,1))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+#names for Demo, could be loaded from a file
+names= ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+#function to display list
+def display_list(list):
+ #store list in Multiline text globally
+ global list_displayed
+ list_displayed = list
+ display = ''
+ #add list elements with new line
+ for l in list:
+ display = display + l + '\n'
+ window.FindElement('_display_').Update(display)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort - See Janson Ch 7
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ #find smallest value
+ if l[j] < l[smallest]:
+ #swap it to front
+ smallest = j
+ #repeat from next position
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort - See Janson Ch 7
+def qsort_holder(names):
+ l = names[:]
+ #pass List, first and last
+ quick_sort(l, 0, len(l) -1)
+ display_list(l)
+#Quicksort is a partition sort
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ #continue splitting - sort small list
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ window.FindElement('_display_').Update('Linear search\n' + l + ' found.')
+ break
+ if not found:
+ window.FindElement('_display_').Update(value['_linear_'] + ' was \nNot found')
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l= list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ window.FindElement('_display_').Update('Binary search\n' + l[mid] + ' found.')
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ window.FindElement('_display_').Update(value['_binary_'] + ' was \nNot found')
+
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py
new file mode 100644
index 000000000..09434f89d
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py
@@ -0,0 +1,132 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+column1 = [[sg.ReadButton('Original list', size = (13,1))],
+ [sg.ReadButton('Default sort', size = (13,1))],
+ [sg.ReadButton('Sort: selection',size = (13,1))],
+ [sg.ReadButton('Sort: quick', size = (13,1))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+names= ['Roberta', 'Kylie', 'Jenny', 'Helen',
+ 'Andrea', 'Meredith','Deborah','Pauline',
+ 'Belinda', 'Wendy']
+
+#function to display list
+def display_list(list):
+ global list_displayed
+ #store list in Multiline text globally
+ list_displayed = list
+ #add list elements with new line
+ values = [l for l in list]
+ window.FindElement('_display_').Update(values)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ if l[j] < l[smallest]:
+ smallest = j
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort
+def qsort_holder(names):
+ l = names[:]
+ quick_sort(l, 0, len(l) - 1)
+ display_list(l)
+
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ #Create list for display
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display_').Update(result)
+ break
+ if not found:
+ #Create list for display
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+#Binary Search
+def binary_search():
+ l = list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ #Create list for display
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display_').Update(result)
+ found = True
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ #Create list for display
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py
new file mode 100644
index 000000000..126dcfa07
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py
@@ -0,0 +1,145 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+import os
+
+sg.SetOptions (font =('Calibri',12,'bold'))
+
+#get pathname to current file
+
+dirname, filename = os.path.split(os.path.abspath(__file__))
+pathname = os.path.join(dirname, 'Names.txt') #original data
+spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data
+
+#Get data from file
+names = [line.strip() for line in open(pathname)]
+
+column1 = [[sg.ReadButton('Original list', size = (13,1))],
+ [sg.ReadButton('Default sort', size = (13,1))],
+ [sg.ReadButton('Sort: selection',size = (13,1))],
+ [sg.ReadButton('Sort: quick', size = (13,1))],
+ [sg.Text('______________',font = ('Calibri', 12))],
+ [sg.ReadButton('Save data\ndisplayed', size = (13,2))]]
+
+layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))],
+[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)],
+ [sg.Text('_'*32,font = ('Calibri', 12))],
+ [sg.InputText(size = (13,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (13,1), key = '_binary_')],
+ [sg.ReadButton('Linear Search', size = (13,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (13,1))],
+ ]
+
+window = sg.Window('Search and Sort Demo').Layout(layout)
+
+#function to display list
+def display_list(list):
+ global list_displayed
+ #store list in Multiline text globally
+ list_displayed = list
+ #add list elements with new line
+ values = [l for l in list]
+ window.FindElement('_display_').Update(values)
+
+#use inbuilt python sort
+def default(names):
+ l = names[:]
+ l.sort()
+ display_list(l)
+
+#Selection sort
+def sel_sort(names):
+ l = names[:]
+ for i in range(len(l)):
+ smallest = i
+ for j in range(i+1, len(l)):
+ if l[j] < l[smallest]:
+ smallest = j
+ l[smallest], l[i] = l[i], l[smallest]
+ display_list(l)
+
+#Quick sort
+def qsort_holder(names):
+ l = names[:]
+ quick_sort(l, 0, len(l) - 1)
+ display_list(l)
+
+def quick_sort(l, first, last):
+ if first >= last:
+ return l
+ pivot = l[first]
+ low = first
+ high = last
+ while low < high:
+ while l[high] > pivot:
+ high = high -1
+ while l[low] < pivot:
+ low = low + 1
+ if low <= high:
+ l[high], l[low] = l[low], l[high]
+ low = low + 1
+ high = high -1
+ quick_sort(l, first, low -1)
+ quick_sort(l, low, last)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']:
+ found = True
+ #Create list for display
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display_').Update(result)
+ break
+ if not found:
+ #Create list for display
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+#Binary Search
+def binary_search():
+ l = list_displayed[:]
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ #Create list for display
+ found = True
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display_').Update(result)
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ #Create list for display
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Original list':
+ display_list(names)
+ if button == 'Default sort':
+ default(names)
+ if button == 'Sort: selection':
+ sel_sort(names)
+ if button == 'Sort: quick':
+ qsort_holder(names)
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ if button == 'Save data\ndisplayed':
+ f = open(spathname, 'w')
+ for name in list_displayed:
+ print (name, file = f)
+ f.close()
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py
new file mode 100644
index 000000000..002599f17
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py
@@ -0,0 +1,63 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+import os #to work with windows OS
+
+sg.ChangeLookAndFeel('GreenTan')
+sg.SetOptions(font = ('Calibri', 12, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (28,4), key = '_multiline_')]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = os.path.join(dirname , 'results.txt' )
+
+ #needs validation and try/catch error checking, will crash if blank or text entry for marks
+
+ if button == '_save_':
+ #create dictionary index _m1_ ... _m4_
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+ total += float(value[index])
+ average = total/4
+ #open file and save
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+
+ #some error checking for missing file needed here
+
+ if button == '_display_':
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py
new file mode 100644
index 000000000..53bfb180d
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py
@@ -0,0 +1,68 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+import os #to work with windows OS
+
+sg.ChangeLookAndFeel('Dark')
+sg.SetOptions(font = ('Calibri', 12, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (28,4), key = '_multiline_')]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = os.path.join(dirname , 'results.txt' )
+ #generic catch error - blanks or wrong data types
+ try:
+ if button == '_save_':
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+
+ #Check for values between 0 and 100
+ if float(value[index]) < 0 or float(value[index]) >100:
+ sg.Popup('Out of Range', 'Enter Marks between 0 and 100')
+ else:
+ total += float(value[index])
+ average = total/4
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+ except ValueError:
+ sg.Popup('Error','Check entries and try again')
+
+ if button == '_display_':
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ try:
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ except:
+ sg.PopupError('Error', 'Problem finding or reading file')
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py
new file mode 100644
index 000000000..a4af2ca27
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py
@@ -0,0 +1,76 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+import os #to work with windows OS
+
+sg.ChangeLookAndFeel('BlueMono')
+sg.SetOptions(font = ('Calibri', 12, 'bold'))
+
+layout = [
+ [sg.Text('Enter a Name and four Marks')],
+ [sg.Text('Name:', size =(10,1)), sg.InputText(size = (12,1), key = '_name_')],
+ [sg.Text('Mark1:', size =(10,1)), sg.InputText(size = (6,1), key = '_m1_')],
+ [sg.Text('Mark2:', size =(10,1)), sg.InputText(size = (6,1), key = '_m2_')],
+ [sg.Text('Mark3:', size =(10,1)), sg.InputText(size = (6,1), key = '_m3_')],
+ [sg.Text('Mark4:', size =(10,1)), sg.InputText(size = (6,1), key = '_m4_')],
+ [sg.ReadButton('Save', size = (8,1),key = '_save_'), sg.Text('Press to Save to file')],
+ [sg.ReadButton('Display',size = (8,1), key = '_display_'), sg.Text('To retrieve and Display')],
+ [sg.Multiline(size = (28,4), key = '_multiline_')]]
+
+window = sg.Window('Simple Average Finder').Layout(layout)
+
+
+while True:
+ button, value = window.Read() #value is a dictionary holding name and marks (4)
+ if button is not None:
+ #initialise variables
+ total = 0.0
+ index = ''
+ name = value['_name_']
+ #get pathname to current file
+ dirname, filename = os.path.split(os.path.abspath(__file__))
+ #add desired file name for saving to path
+ pathname = dirname + '\\results.txt'
+ #generic catch error - blanks or wrong data types
+ try:
+ if button == '_save_':
+ for i in range (1,5):
+ index = '_m' + str(i) + '_'
+
+ #Check for values between 0 and 100
+ if float(value[index]) < 0 or float(value[index]) >100:
+ sg.Popup('Out of Range', 'Enter Marks between 0 and 100')
+ else:
+ total += float(value[index])
+ average = total/4
+ #check location and file name for file, no_window so go straight to folder selection
+
+ foldername = sg.PopupGetFolder('', no_window=True)
+ filename = sg.PopupGetFile('Please enter a file name for your results')
+ pathname = os.path.join(foldername ,filename + '.txt')
+
+ f = open(pathname, 'w')
+ print (name, file = f)
+ print (total, file = f)
+ print (average, file = f)
+ f.close()
+ except ValueError:
+ sg.Popup('Error','Check entries and try again')
+
+ if button == '_display_':
+ #get pathname: folder and file
+ pathname = sg.PopupGetFile('file to open', no_window=True, file_types=(("text files","*.txt"),))
+ #This loads the file line by line into a list called data.
+ #the strip() removes whitespaces from beginning and end of each line.
+ try:
+ data = [line.strip() for line in open(pathname)]
+ #create single string to display in multiline object.
+ string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2])
+ window.FindElement('_multiline_').Update(string)
+ except:
+ sg.PopupError('Error', 'Problem finding or reading file')
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py
new file mode 100644
index 000000000..d419d623f
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py
@@ -0,0 +1,40 @@
+#Matplotlib, pyplt and csv
+#Tony Crewe
+#Sep 2017 - updated Sep 2018
+
+import matplotlib.pyplot as plt
+import csv
+from matplotlib.ticker import MaxNLocator
+
+
+x=[]
+y=[]
+
+with open('weight 2018.csv', 'r', encoding = 'utf-8-sig') as csvfile:
+ plots = csv.reader(csvfile)
+ for data in plots:
+ #get heading for x and y axes
+ var1 = (data[0])
+ var2 = (data[1])
+ break
+ for data in plots:
+ #get values - add to x list and y list
+ x.append(data[0])
+ y.append(float(data[1]))
+
+
+ax = plt.subplot(1,1,1)
+ax.set_ylim([82, 96])
+ax.xaxis.set_major_locator(MaxNLocator(10))
+ax.spines['right'].set_color('none')
+ax.spines['top'].set_color('none')
+
+plt.plot(x,y, label = 'data loaded\nfrom csv file')
+plt.axhline(y = 85.5, color = 'orange', linestyle = '--', label = 'target')
+plt.xlabel(var1)
+plt.ylabel(var2)
+plt.title('weight loss from\n first quarter 2018')
+
+
+plt.legend()
+plt.show()
diff --git a/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py
new file mode 100644
index 000000000..880caee9e
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py
@@ -0,0 +1,67 @@
+# PySimple examples (v 3.9.3)
+# Tony Crewe
+# Sep 2018 - updated Oct 2018
+
+# Based of Example program from MikeTheWatchGuy
+# https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+
+sg.ChangeLookAndFeel('BrownBlue')
+
+
+def calc_ladder():
+ filename = sg.PopupGetFile('Get required file', no_window=True, file_types=(("CSV Files", "*.csv"),))
+ # populate table with file contents
+ # Assume we know csv has heading in row 1
+ # Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown
+ # data is a list of lists containing data about each team
+ # data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W,
+ # data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A
+ # no error checking or validation used.
+
+ # initialise variable
+ data = []
+ header_list = []
+ # read csv
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range(1):
+ # get headings
+ header = next(reader)
+ # read everything else into a list of rows
+ data = list(reader)
+ # add headings
+ header = header + ['%', 'Pts']
+ for i in range(len(data)):
+ # calculate % and format to 2 decimal places
+ percent = str('{:.2f}'.format(int(data[i][5]) / int(data[i][6]) * 100))
+ data[i] = data[i] + [percent] # add to data
+ pts = int(data[i][2]) * 4 + int(data[i][4]) * 2
+ data[i] = data[i] + [pts] # add to data
+
+ # use Table (explore settings) and add to column layout
+ col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True,
+ max_col_width=12, justification='right', background_color='White',
+ text_color='Black', alternating_row_color='LightBlue', size=(None, len(data)))]]
+
+ layout = [[sg.Column(col_layout, size=(500, 400), scrollable=True)], ]
+
+ window = sg.Window('Table', location=(700, 325), grab_anywhere=False).Layout(layout)
+ b, v = window.Read()
+
+
+slayout = [
+ [sg.Text('Load AFL file to display results with points and percentage'), sg.ReadButton('Load File', size=(20, 1))]]
+swindow = sg.Window('Load File', location=(700, 250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ calc_ladder()
+ else:
+ break
+
diff --git a/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py
new file mode 100644
index 000000000..1880145df
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py
@@ -0,0 +1,70 @@
+#PySimple examples (v 3.9.3)
+#Tony Crewe
+#Sep 2018 - updated Oct 2018
+
+#Based of Example program from MikeTheWatchGuy
+#https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+import operator
+
+sg.ChangeLookAndFeel('Dark')
+
+def table_example():
+
+ filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),))
+ #populate table with file contents
+ #Assume we know csv has heading in row 1
+ #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown
+ #data is a list of lists containing data about each team
+ #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W,
+ #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A
+ #no error checking or validation used.
+
+ #initialise variables
+ data = []
+ header_list = []
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range (1):
+ header = next(reader)
+ data = list(reader)
+ header = header + ['%', 'Pts']
+ for i in range (len(data)):
+ #calculate %
+ percent = int(data[i][5])/int(data[i][6])*100
+ data[i] = data[i] + [percent]
+ pts = int(data[i][2])*4 + int(data[i][4])*2
+ data[i] = data[i] + [pts]
+ #sort data
+ #first by %
+ data.sort(key = operator.itemgetter(7), reverse = True)
+ #then by pts
+ data.sort(key = operator.itemgetter(8), reverse = True)
+ #and format string to 2 decimal places
+ for i in range(len(data)):
+ data[i][7] = str('{:.2f}'.format(data[i][7]))
+ #use Table (explore settings) and add to column layout
+ col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True,
+ max_col_width = 12,justification='right', text_color = 'White',
+ alternating_row_color = 'Grey', size=(None, len(data)))]]
+ #experimented with size and location to get windows to fit :-)
+ #remove titlebar of main display window
+
+ layout = [[sg.Column(col_layout, size=(415,400), scrollable=True)],]
+ window = sg.Window('Table', location = (662, 320), no_titlebar=True, grab_anywhere=False).Layout(layout)
+ b, v = window.Read()
+
+slayout = [[sg.Text(' Load AFL (csv) file to display results.', font = ('Calibri', 14, 'bold') ),
+ sg.ReadButton('Load File', size = (14,1))]]
+swindow = sg.Window('Load File', location = (654,250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ table_example()
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py
new file mode 100644
index 000000000..1e3819d57
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py
@@ -0,0 +1,66 @@
+#PySimple examples (v 3.9.3)
+#Tony Crewe
+#Sep 2018 - updated Oct 2018
+
+#Based of Example program from MikeTheWatchGuy
+#https://gitlab.com/lotspaih/PySimpleGUI
+
+import sys
+import PySimpleGUI as sg
+import csv
+import operator
+import os
+
+sg.ChangeLookAndFeel('Dark')
+
+#get pathname to current file and add file name for image
+dirname, filename = os.path.split(os.path.abspath(__file__))
+
+pathname = os.path.join(dirname , 'AFL.png' )
+
+def table_example():
+
+ filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),))
+
+
+ data = []
+ header_list = []
+
+ with open(filename, "r") as infile:
+ reader = csv.reader(infile)
+ for i in range (1):
+ header = next(reader)
+ data = list(reader)
+ header = header + ['%', 'Pts']
+ for i in range (len(data)):
+
+ percent = int(data[i][5])/int(data[i][6])*100
+ data[i] = data[i] + [percent]
+ pts = int(data[i][2])*4 + int(data[i][4])*2
+ data[i] = data[i] + [pts]
+
+ data.sort(key = operator.itemgetter(7), reverse = True)
+ data.sort(key = operator.itemgetter(8), reverse = True)
+
+ for i in range(len(data)):
+ data[i][7] = str('{:.2f}'.format(data[i][7]))
+
+ col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True,
+ max_col_width = 12,justification='right', text_color = 'White',
+ alternating_row_color = 'Grey', size=(None, len(data)))]]
+
+ layout = [[sg.Column(col_layout, size=(443,400), scrollable=True)],]
+ window = sg.Window('Table', location = (662, 328), no_titlebar=True, grab_anywhere=False).Layout(layout)
+ b, v = window.Read()
+
+slayout = [[sg.Image(pathname),sg.Text('Load AFL data to display results.', font = ('Calibri', 14, 'bold') ),
+ sg.ReadButton('Load File', size = (14,1))]]
+swindow = sg.Window('Load File', location = (654,250)).Layout(slayout)
+
+while True:
+ button, value = swindow.Read()
+ if button is not None:
+ if button == 'Load File':
+ table_example()
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py b/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py
new file mode 100644
index 000000000..823e091cd
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py
@@ -0,0 +1,47 @@
+#PySimple examples (v 3.8)
+#Tony Crewe
+#Sep 2018
+
+import PySimpleGUI as sg
+
+sg.ChangeLookAndFeel('SandyBeach')
+sg.SetOptions (font = ('Calibri', 12, 'bold'))
+
+
+
+layout0 = [[sg.ReadButton('Show/Hide window1'),sg.ReadButton('Show/Hide window2')]]
+
+layout1 =[[ sg.Text('window1')], [sg.Multiline( size = (35, 10))]]
+layout2 =[[ sg.Text('window2')], [sg.Multiline( size = (35, 10))]]
+window0 = sg.Window('Home Window', location = (400, 150)).Layout(layout0)
+
+window1 = sg.Window('Window1', location = (400, 250)).Layout(layout1).Finalize()
+window1.Hide()
+w1 = False
+
+window2 = sg.Window('Window2', location = (800, 250)).Layout(layout2).Finalize()
+window2.Hide()
+w2 = False
+
+while True:
+ button, v = window0.Read()
+ if button is not None:
+ if button =='Show/Hide window1':
+ if w1 == True:
+ window1.Hide()
+ w1 = False
+ else:
+ window1.UnHide()
+ w1=True
+ if button =='Show/Hide window2':
+ if w2 == True:
+ window2.Hide()
+ w2 = False
+ else:
+ window2.UnHide()
+ w2=True
+ else:
+ break
+
+
+
diff --git a/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py
new file mode 100644
index 000000000..1ddcf009a
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py
@@ -0,0 +1,22 @@
+#PySimple examples (v 3.9)
+#Tony Crewe
+#Oct 2018
+
+import PySimpleGUI as sg
+
+tab1_layout = [[sg.Text('This is inside tab 1')]]
+
+tab2_layout = [[sg.Text('This is inside tab 2')]]
+
+layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout),
+ sg.Tab('Tab 2', tab2_layout)]])],
+ [sg.ReadButton('Read')]]
+
+window = sg.Window('Main Window').Layout(layout)
+
+while True:
+ b, v = window.Read()
+ if b is not None:
+ print(b,v)
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py
new file mode 100644
index 000000000..68829e85a
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py
@@ -0,0 +1,78 @@
+import PySimpleGUI as sg
+import os
+
+sg.ChangeLookAndFeel('BlueMono')
+
+#get pathname to current file
+
+dirname, filename = os.path.split(os.path.abspath(__file__))
+pathname = os.path.join(dirname , 'Names.txt')
+
+#Get data from file
+names = [line.strip() for line in open(pathname)]
+sorted_names = names[:]
+sorted_names.sort()
+
+tab1_layout =[[sg.Text('Linear Search Demo', font =('Calibri', 14, 'bold'))],
+ [sg.Listbox(values =[n for n in names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display1_')],
+ [sg.Text('_'*15,font = ('Calibri', 12))],
+ [sg.Text('Enter name to search for:')],
+ [sg.InputText(size = (18,1), key = '_linear_')],
+ [sg.ReadButton('Linear Search', size = (15,1))]]
+
+tab2_layout = [[sg.Text('Binary Search Demo', font =('Calibri', 14, 'bold'))],
+ [sg.Listbox(values =[n for n in sorted_names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display2_')],
+ [sg.Text('_'*18,font = ('Calibri', 12))],
+ [sg.Text('Enter name to search for:')],
+ [sg.InputText(size = (18,1), key = '_binary_')],
+ [sg.ReadButton('Binary Search', size = (15,1))]]
+
+layout = [
+ [sg.TabGroup([[sg.Tab('Linear Search', tab1_layout),sg.Tab('Binary Search', tab2_layout)]])]]
+
+window = sg.Window('Main Window').Layout(layout)
+
+#Linear Search - no need for Ordered list
+def linear_search():
+ l = names[:]
+ found = False
+ for l in l:
+ if l == value['_linear_']: #Check each value
+ found = True
+ result = ['Linear search', l + ' found']
+ window.FindElement('_display1_').Update(result)
+ break
+ if not found:
+ result = [value['_linear_'], 'was not found']
+ window.FindElement('_display1_').Update(result)
+
+#Binary Search - only works for ordered lists
+def binary_search():
+ l = sorted_names
+ lo = 0
+ hi = len(l)-1
+ found = False
+ while lo <= hi:
+ mid = (lo + hi) //2
+ if l[mid] == value['_binary_']:
+ found = True
+ result = ['Binary search', l[mid] + ' found.']
+ window.FindElement('_display2_').Update(result)
+ break
+ elif l[mid] < value['_binary_']:
+ lo = mid + 1
+ else:
+ hi = mid - 1
+ if not found:
+ result = [value['_binary_'], 'was not found']
+ window.FindElement('_display2_').Update(result)
+
+while True:
+ button, value = window.Read()
+ if button is not None:
+ if button == 'Linear Search':
+ linear_search()
+ if button == 'Binary Search':
+ binary_search()
+ else:
+ break
diff --git a/ProgrammingClassExamples/Win10 versions/AFL.png b/ProgrammingClassExamples/Win10 versions/AFL.png
new file mode 100644
index 000000000..ee3a35597
Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/AFL.png differ
diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv
new file mode 100644
index 000000000..798296f6e
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv
@@ -0,0 +1,19 @@
+Team,P,W,L,D,F,A
+Adelaide Crows,22,12,10,0,1941,1865
+Brisbane Lions,22,5,17,0,1825,2049
+Carlton,22,2,20,0,1353,2282
+Collingwood,22,15,7,0,2046,1699
+Essendon,22,12,10,0,1932,1838
+Fremantle,22,8,14,0,1556,2041
+Geelong Cats,22,13,9,0,2045,1554
+Gold Coast Suns,22,4,18,0,1308,2182
+GWS Giants,22,13,8,1,1898,1661
+Hawthorn,22,15,7,0,1972,1642
+Melbourne,22,14,8,0,2299,1749
+North Melbourne,22,12,10,0,1950,1790
+Port Adelaide,22,12,10,0,1780,1654
+Richmond,22,18,4,0,2143,1574
+St Kilda,22,4,17,1,1606,2125
+Sydney Swans,22,14,8,0,1822,1664
+West Coast Eagles,22,16,6,0,2012,1657
+Western Bulldogs,22,8,14,0,1575,2037
diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv
new file mode 100644
index 000000000..71cb8c18a
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv
@@ -0,0 +1,19 @@
+Team,P,W,L,D,F,A
+Richmond,22,18,4,0,2143,1574
+West Coast Eagles,22,16,6,0,2012,1657
+Collingwood,22,15,7,0,2046,1699
+Hawthorn,22,15,7,0,1972,1642
+Melbourne,22,14,8,0,2299,1749
+Sydney Swans,22,14,8,0,1822,1664
+GWS Giants,22,13,8,1,1898,1661
+Geelong Cats,22,13,9,0,2045,1554
+North Melbourne,22,12,10,0,1950,1790
+Port Adelaide,22,12,10,0,1780,1654
+Essendon,22,12,10,0,1932,1838
+Adelaide Crows,22,12,10,0,1941,1865
+Western Bulldogs,22,8,14,0,1575,2037
+Fremantle,22,8,14,0,1556,2041
+Brisbane Lions,22,5,17,0,1825,2049
+St Kilda,22,4,17,1,1606,2125
+Gold Coast Suns,22,4,18,0,1308,2182
+Carlton,22,2,20,0,1353,2282
diff --git a/ProgrammingClassExamples/Win10 versions/Gym_Logo.png b/ProgrammingClassExamples/Win10 versions/Gym_Logo.png
new file mode 100644
index 000000000..45bb5f7bc
Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/Gym_Logo.png differ
diff --git a/ProgrammingClassExamples/Win10 versions/Names.txt b/ProgrammingClassExamples/Win10 versions/Names.txt
new file mode 100644
index 000000000..d1b9fd24d
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/Names.txt
@@ -0,0 +1,10 @@
+Roberta
+Kylie
+Jenny
+Helen
+Andrea
+Meredith
+Deborah
+Pauline
+Belinda
+Wendy
\ No newline at end of file
diff --git a/ProgrammingClassExamples/Win10 versions/default_icon.ico b/ProgrammingClassExamples/Win10 versions/default_icon.ico
new file mode 100644
index 000000000..1a41525ec
Binary files /dev/null and b/ProgrammingClassExamples/Win10 versions/default_icon.ico differ
diff --git a/ProgrammingClassExamples/Win10 versions/weight 2018.csv b/ProgrammingClassExamples/Win10 versions/weight 2018.csv
new file mode 100644
index 000000000..66e7c2d97
--- /dev/null
+++ b/ProgrammingClassExamples/Win10 versions/weight 2018.csv
@@ -0,0 +1,98 @@
+Date,Weight (kg)
+29-Dec,94.5
+30-Dec,94
+31-Dec,94
+1-Jan,93.5
+2-Jan,94.2
+3-Jan,94
+4-Jan,94
+5-Jan,93.4
+6-Jan,92.6
+7-Jan,93.1
+8-Jan,92.7
+9-Jan,92.5
+10-Jan,92.3
+11-Jan,92.1
+12-Jan,92.5
+13-Jan,92.6
+14-Jan,92.5
+15-Jan,92.1
+16-Jan,91.6
+17-Jan,91.3
+18-Jan,91.8
+19-Jan,91.7
+20-Jan,91.9
+21-Jan,91.8
+22-Jan,91.1
+23-Jan,90.7
+24-Jan,90.5
+25-Jan,90.5
+26-Jan,90.3
+27-Jan,90.1
+28-Jan,89.9
+29-Jan,90.2
+30-Jan,90.1
+31-Jan,89.9
+1-Feb,89.5
+2-Feb,89.1
+3-Feb,89.3
+4-Feb,89.4
+5-Feb,89.2
+6-Feb,88.2
+7-Feb,88.2
+8-Feb,88.3
+9-Feb,88.2
+10-Feb,89.1
+11-Feb,88.9
+12-Feb,88.6
+13-Feb,88.7
+14-Feb,88.5
+15-Feb,88.1
+16-Feb,87.8
+17-Feb,87.9
+18-Feb,88.1
+19-Feb,87.9
+20-Feb,87.6
+21-Feb,87.5
+22-Feb,87.3
+23-Feb,87
+24-Feb,87.5
+25-Feb,87.7
+26-Feb,87.4
+27-Feb,87.2
+28-Feb,86.9
+1-Mar,86.9
+2-Mar,86.9
+3-Mar,86.5
+4-Mar,86.8
+5-Mar,87
+6-Mar,86.9
+7-Mar,86.2
+8-Mar,86.4
+9-Mar,86.1
+10-Mar,86.7
+11-Mar,85.6
+12-Mar,85.8
+13-Mar,85.3
+14-Mar,85.1
+15-Mar,85.4
+16-Mar,84.5
+17-Mar,85.1
+18-Mar,84.8
+19-Mar,84.8
+20-Mar,84.8
+21-Mar,84.9
+22-Mar,85.5
+23-Mar,85.1
+24-Mar,85.5
+25-Mar,85.6
+26-Mar,85.9
+27-Mar,85.9
+28-Mar,85.5
+29-Mar,85.9
+30-Mar,85.5
+1-Apr,85.2
+2-Apr,84.8
+3-Apr,85.3
+4-Apr,85.4
+5-Apr,85.3
diff --git a/PySimpleGUI.png b/PySimpleGUI.png
new file mode 100644
index 000000000..5e72ffcf3
Binary files /dev/null and b/PySimpleGUI.png differ
diff --git a/PySimpleGUI.py b/PySimpleGUI.py
new file mode 100644
index 000000000..59b9e04ad
--- /dev/null
+++ b/PySimpleGUI.py
@@ -0,0 +1,12266 @@
+#!/usr/bin/python3
+
+version = __version__ = "4.6.0 Released 11-Nov-2019"
+
+
+# 888888ba .d88888b oo dP .88888. dP dP dP
+# 88 `8b 88. "' 88 d8' `88 88 88 88
+# a88aaaa8P' dP dP `Y88888b. dP 88d8b.d8b. 88d888b. 88 .d8888b. 88 88 88 88
+# 88 88 88 `8b 88 88'`88'`88 88' `88 88 88ooood8 88 YP88 88 88 88
+# 88 88. .88 d8' .8P 88 88 88 88 88. .88 88 88. ... Y8. .88 Y8. .8P 88
+# dP `8888P88 Y88888P dP dP dP dP 88Y888P' dP `88888P' `88888' `Y88888P' dP
+# .88 88
+# .88 88
+# d8888P dP
+
+
+
+
+# __ __
+# / | / |
+# $$ | ______ ______ ______ $$ |
+# $$ | / \ / \ / \ $$ |
+# $$ | /$$$$$$ |/$$$$$$ | $$$$$$ |$$ |
+# $$ | $$ $$ |$$ | $$ | / $$ |$$ |
+# $$ |_____ $$$$$$$$/ $$ \__$$ |/$$$$$$$ |$$ |
+# $$ |$$ |$$ $$ |$$ $$ |$$ |
+# $$$$$$$$/ $$$$$$$/ $$$$$$$ | $$$$$$$/ $$/
+# / \__$$ |
+# $$ $$/
+# $$$$$$/
+
+
+"""
+Copyright 2018, 2019 PySimpleGUI.org
+
+OK, let's get the bullshit out of the way
+
+This software is available for your use under a MODIFIED LGPL3+ license
+
+This notice, these first 100 lines of code shall remain unchanged
+
+ # #
+ ## ## #### ##### # ###### # ###### #####
+ # # # # # # # # # # # # # #
+ # # # # # # # # ##### # ##### # #
+ # # # # # # # # # # # #
+ # # # # # # # # # # # #
+ # # #### ##### # # # ###### #####
+
+
+888 .d8888b. 8888888b. 888 .d8888b.
+888 d88P Y88b 888 Y88b 888 d88P Y88b
+888 888 888 888 888 888 .d88P
+888 888 888 d88P 888 8888" 888
+888 888 88888 8888888P" 888 "Y8b. 8888888
+888 888 888 888 888 888 888 888
+888 Y88b d88P 888 888 Y88b d88P
+88888888 "Y8888P88 888 88888888 "Y8888P"
+
+
+And just what is that? Well, it's LPGL3+ and these FOUR simple stipulations.
+1. These and all comments are to remain in this document
+2. You will not post this software in a repository or a location for others to download from:
+ A. Unless you have made 10 lines of changes
+ B. A notice is posted with the code that it is not the original code but instead derived from an original
+3. Forking is OK and does NOT require any changes as long as it is obvious forked and stated on the page
+ where your software is being hosted. For example, GitHub does a fantastic job of indicating if a repository
+ is the result of a fork.
+4. The "Official" version of PySimpleGUI and the associated documentation lives on two (and **only** two) places:
+ 1. GitHub - (http://www.PySimpleGUI.com) currently pointing at:
+ https://github.com/PySimpleGUI/PySimpleGUI
+ 2. PyPI - pip install PySimpleGUI is the customary way of obtaining the latest release
+
+ THE official documentation location is:
+ Read the Docs (via http://www.PySimpleGUI.org). Currently is pointed at:
+ https://pysimplegui.readthedocs.io/en/latest/
+ If you've obtained this software in any other way, then those listed here, then SUPPORT WILL NOT BE PROVIDED.
+
+-----------------------------------------------------------------------------------------------------------------
+
+How about having FUN with this package?? Terrible note to begin this journey of actually having fun making
+GUI based applications so I'll try to make it up to you.
+
+The first bit of good news for you is that literally 100s of pages of documentation await you. And nearly 200
+Demo Programs have been written as a "jump start" mechanism to get your running as quickly as possible.
+
+Some general bits of advice:
+Upgrade your software! pip install --upgrade --no-cache-dir PySimpleGUI
+If you're thinking of filing an Issue or posting a problem, Upgrade your software first
+There are constantly something new and interesting coming out of this project so stay current if you can
+
+The FASTEST WAY to learn PySimpleGUI is to begin to play with it, and to read the documentation.
+http://www.PySimpleGUI.org
+http://Cookbook.PySimpleGUI.org
+
+The User Manual and the Cookbook are both designed to paint some nice looking GUIs on your screen within 5 minutes of you deciding to PySimpleGUI out.
+
+"""
+
+
+# do the Python 2 or 3 check so the right tkinter stuff can get pulled in
+import sys
+if sys.version_info[0] >= 3:
+ import tkinter as tk
+ from tkinter import filedialog
+ from tkinter.colorchooser import askcolor
+ from tkinter import ttk
+ import tkinter.scrolledtext as tkst
+ import tkinter.font
+else: # Do NOT remove any of these regardless of what your IDE or lint says. They are transformed in the 3 to 2 process
+ import Tkinter as tk
+ import tkFileDialog
+ import ttk
+ import tkColorChooser
+ import tkFont
+ import ScrolledText
+
+import datetime
+import time
+import pickle
+import calendar
+import textwrap
+import inspect
+# from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments
+from random import randint
+import warnings
+
+g_time_start = 0
+g_time_end = 0
+g_time_delta = 0
+
+# These timer routines are to help you quickly time portions of code. Please this TimerStart call at the point
+# you want to start timing and the TimerStop at the end point. As you can see, TimerStop prints the time delta in ms.
+def TimerStart():
+ """ Time your code easily.... start the timer. """
+ global g_time_start
+
+ g_time_start = time.time()
+
+
+def TimerStop():
+ """ Time your code easily.... stop the timer and print the number of ms since the timer start """
+ global g_time_delta, g_time_end
+
+ g_time_end = time.time()
+ g_time_delta = g_time_end - g_time_start
+ print((g_time_delta * 1000))
+
+
+"""
+ Welcome to the "core" PySimpleGUI code....
+
+ It's a mess.... really... it's a mess internally... it's the external-facing interfaces that
+ are not a mess. The Elements and the methods for them are well-designed.
+ PEP8 - this code is far far from PEP8 compliant.
+ It was written PRIOR to learning that PEP8 existed.
+
+ I'll be honest.... started learning Python in Nov 2017, started writing PySimpleGUI in Feb 2018.
+ Released PySimpleGUI in July 2018. I knew so little about Python that my parameters were all named
+ using CamelCase. DOH! Someone on Reddit set me straight on that. So overnight I renamed all of the
+ parameters to lower case. Unfortunately, the internal naming conventions have been set. Mixing them
+ with PEP8 at this moment would be even MORE confusing.
+
+ Code I write now, outside PySimpleGUI, IS PEP8 compliant.
+
+ The variable and function naming in particular are not compliant. There is
+ liberal use of CamelVariableAndFunctionNames. If you've got a serious enough problem with this
+ that you'll pass on this package, then that's your right and I invite you to do so. However, if
+ perhaps you're a practical thinker where it's the results that matter, then you'll have no
+ trouble with this code base. There is consisency however.
+
+ I truly hope you get a lot of enjoyment out of using PySimpleGUI. It came from good intentions.
+"""
+
+# ----====----====----==== Constants the user CAN safely change ====----====----====----#
+
+# Base64 encoded GIF file
+DEFAULT_BASE64_ICON = b'R0lGODlhIQAgAPcAAAAAADBpmDBqmTFqmjJrmzJsnDNtnTRrmTZtmzZumzRtnTdunDRunTRunjVvnzdwnzhwnjlxnzVwoDZxoTdyojhzozl0ozh0pDp1pjp2pjp2pzx0oj12pD52pTt3qD54pjt4qDx4qDx5qTx5qj16qj57qz57rD58rT98rkB4pkJ7q0J9rEB9rkF+rkB+r0d9qkZ/rEl7o0h8p0x9pk5/p0l+qUB+sEyBrE2Crk2Er0KAsUKAskSCtEeEtUWEtkaGuEiHuEiHukiIu0qKu0mJvEmKvEqLvk2Nv1GErVGFr1SFrVGHslaHsFCItFSIs1COvlaPvFiJsVyRuWCNsWSPsWeQs2SQtGaRtW+Wt2qVuGmZv3GYuHSdv3ievXyfvV2XxGWZwmScx2mfyXafwHikyP7TPP/UO//UPP/UPf/UPv7UP//VQP/WQP/WQf/WQv/XQ//WRP7XSf/XSv/YRf/YRv/YR//YSP/YSf/YSv/ZS//aSv/aS/7YTv/aTP/aTf/bTv/bT//cT/7aUf/cUP/cUf/cUv/cU//dVP/dVf7dVv/eVv/eV//eWP/eWf/fWv/fW/7cX/7cYf7cZP7eZf7dav7eb//gW//gXP/gXf/gXv/gX//gYP/hYf/hYv/iYf/iYv7iZP7iZf/iZv/kZv7iaP/kaP/ka//ma//lbP/lbv/mbP/mbv7hdP7lcP/ncP/nc//ndv7gef7gev7iff7ke/7kfv7lf//ocf/ocv/odP/odv/peP/pe//ofIClw4Ory4GszoSszIqqxI+vyoSv0JGvx5OxyZSxyZSzzJi0y5m2zpC10pi715++16C6z6a/05/A2qHC3aXB2K3I3bLH2brP4P7jgv7jh/7mgf7lhP7mhf7liv/qgP7qh/7qiP7rjf7sjP7nkv7nlv7nmP7pkP7qkP7rkv7rlv7slP7sl/7qmv7rnv7snv7sn/7un/7sqv7vq/7vrf7wpv7wqf7wrv7wsv7wtv7ytv7zvP7zv8LU48LV5c3a5f70wP7z0AAAACH5BAEAAP8ALAAAAAAhACAAAAj/AP8JHEiwoMGDCA1uoYIF4bhK1vwlPOjlQICLApwVpFTGzBk1siYSrCLgoskFyQZKMsOypRyR/GKYnBkgQbF/s8603KnmWkIaNIMaw6lzZ8tYB2cIWMo0KIJj/7YV9XgGDRo14gpOIUBggNevXpkKGCDsXySradSoZcMmDsFnDxpEKEC3bl2uXCFQ+7emjV83bt7AgTNroJINAq0wWBxBgYHHdgt0+cdnMJw5c+jQqYNnoARkAx04kPEvS4PTqBswuPIPUp06duzcuYMHT55wAjkwEahsQgqBNSQIHy582D9BePTs2dOnjx8/f1gJ9GXhRpTqApFQoDChu3cOAps///9D/g+gQvYGjrlw4cU/fUnYX6hAn34HgZMABQo0iJB/Qoe8UxAXOQiEg3wIXvCBQLUU4mAhh0R4SCLqJOSEBhhqkAEGHIYgUDaGICIiIoossogj6yBUTQ4htNgiCCB4oIJAtJTIyI2MOOLIIxMtQQIJIwQZpAgwCKRNI43o6Igll1ySSTsI7dOECSaUYOWVKwhkiyVMYuJlJpp0IpA6oJRTkBQopHnCmmu2IBA2mmQi5yZ0fgJKPP+0IwoooZwzkDQ2uCCoCywUyoIW/5DDyaKefOLoJ6LU8w87pJgDTzqmDNSMDpzqYMOnn/7yTyiglBqKKKOMUopA7JgCy0DdeMEjUDM71GqrrcH8QwqqqpbiayqToqJKLwN5g45A0/TAw7LL2krGP634aoopp5yiiiqrZLuKK+jg444uBIHhw7g+MMsDFP/k4wq22rririu4xItLLriAUxAQ5ObrwzL/0PPKu7fIK3C8uxz0w8EIIwzMP/cM7HC88hxEzBBCBGGxxT8AwQzDujws7zcJQVMEEUKUbPITAt1D78OSivSFEUXEXATKA+HTscC80CPSQNGEccQRYhjUDzfxcjPPzkgnLVBAADs='
+
+DEFAULT_BASE64_LOADING_GIF = b'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'
+
+PSG_DEBUGGER_LOGO = b'R0lGODlhMgAtAPcAAAAAADD/2akK/4yz0pSxyZWyy5u3zZ24zpW30pG52J250J+60aC60KS90aDC3a3E163F2K3F2bPI2bvO3rzP3qvJ4LHN4rnR5P/zuf/zuv/0vP/0vsDS38XZ6cnb6f/xw//zwv/yxf/1w//zyP/1yf/2zP/3z//30wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAyAC0AAAj/AP8JHEiwoMGDCBMqXMiwoUOFAiJGXBigYoAPDxlK3CigwUGLIAOEyIiQI8cCBUOqJFnQpEkGA1XKZPlPgkuXBATK3JmRws2bB3TuXNmQw8+jQoeCbHj0qIGkSgNobNoUqlKIVJs++BfV4oiEWalaHVpyosCwJidw7Sr1YMQFBDn+y4qSbUW3AiDElXiWqoK1bPEKGLixr1jAXQ9GuGn4sN22Bl02roo4Kla+c8OOJbsQM9rNPJlORlr5asbPpTk/RP2YJGu7rjWnDm2RIQLZrSt3zgp6ZmqwmkHAng3ccWDEMe8Kpnw8JEHlkXnPdh6SxHPILaU/dp60LFUP07dfRq5aYntohAO0m+c+nvT6pVMPZ3jv8AJu8xktyNbw+ATJDtKFBx9NlA20gWU0DVQBYwZhsJMICRrkwEYJJGRCSBtEqGGCAQEAOw=='
+
+DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON
+
+DEFAULT_ELEMENT_SIZE = (45, 1) # In CHARACTERS
+DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS
+DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term
+DEFAULT_ELEMENT_PADDING = (5, 3) # Padding between elements (row, col) in pixels
+DEFAULT_AUTOSIZE_TEXT = True
+DEFAULT_AUTOSIZE_BUTTONS = True
+DEFAULT_FONT = ("Helvetica", 10)
+DEFAULT_TEXT_JUSTIFICATION = 'left'
+DEFAULT_BORDER_WIDTH = 1
+DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form
+DEFAULT_DEBUG_WINDOW_SIZE = (80, 20)
+DEFAULT_WINDOW_LOCATION = (None, None)
+MAX_SCROLLED_TEXT_BOX_HEIGHT = 50
+DEFAULT_TOOLTIP_TIME = 400
+DEFAULT_TOOLTIP_OFFSET = (0, -20)
+TOOLTIP_BACKGROUND_COLOR = "#ffffe0"
+#################### COLOR STUFF ####################
+BLUES = ("#082567", "#0A37A3", "#00345B")
+PURPLES = ("#480656", "#4F2398", "#380474")
+GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532")
+YELLOWS = ("#F3FB62", "#F0F595")
+TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA")
+NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]),
+ ('#000000', '#FFFFFF'),
+ ('#FFFFFF', '#000000'),
+ (YELLOWS[0], PURPLES[1]),
+ (YELLOWS[0], GREENS[3]),
+ (YELLOWS[0], BLUES[2]))
+
+COLOR_SYSTEM_DEFAULT = '1234567890' # Colors should never be this long
+if sys.platform == 'darwin':
+ DEFAULT_BUTTON_COLOR = COLOR_SYSTEM_DEFAULT # Foreground, Background (None, None) == System Default
+ OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = COLOR_SYSTEM_DEFAULT # Colors should never be this long
+else:
+ DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default
+OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long
+
+DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000")
+DEFAULT_BACKGROUND_COLOR = None
+DEFAULT_ELEMENT_BACKGROUND_COLOR = None
+DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
+DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None
+DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
+DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT
+DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
+DEFAULT_SCROLLBAR_COLOR = None
+# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[0]) # (Text, Background) or (Color "on", Color) as a way to remember
+# DEFAULT_BUTTON_COLOR = (GREENS[3], TANS[0]) # Foreground, Background (None, None) == System Default
+# DEFAULT_BUTTON_COLOR = (YELLOWS[0], GREENS[4]) # Foreground, Background (None, None) == System Default
+# DEFAULT_BUTTON_COLOR = ('white', 'black') # Foreground, Background (None, None) == System Default
+# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[2]) # Foreground, Background (None, None) == System Default
+# DEFAULT_PROGRESS_BAR_COLOR = (GREENS[2], GREENS[0]) # a nice green progress bar
+# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[1], BLUES[1]) # a nice green progress bar
+# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[0], BLUES[0]) # a nice green progress bar
+# DEFAULT_PROGRESS_BAR_COLOR = (PURPLES[1],PURPLES[0]) # a nice purple progress bar
+
+# A transparent button is simply one that matches the background
+TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0')
+# --------------------------------------------------------------------------------
+# Progress Bar Relief Choices
+RELIEF_RAISED = 'raised'
+RELIEF_SUNKEN = 'sunken'
+RELIEF_FLAT = 'flat'
+RELIEF_RIDGE = 'ridge'
+RELIEF_GROOVE = 'groove'
+RELIEF_SOLID = 'solid'
+
+DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar
+DEFAULT_PROGRESS_BAR_SIZE = (20, 20) # Size of Progress Bar (characters for length, pixels for width)
+DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1
+DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE
+PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative')
+DEFAULT_PROGRESS_BAR_STYLE = 'default'
+DEFAULT_METER_ORIENTATION = 'Horizontal'
+DEFAULT_SLIDER_ORIENTATION = 'vertical'
+DEFAULT_SLIDER_BORDER_WIDTH = 1
+DEFAULT_SLIDER_RELIEF = tk.FLAT
+DEFAULT_FRAME_RELIEF = tk.GROOVE
+
+DEFAULT_LISTBOX_SELECT_MODE = tk.SINGLE
+SELECT_MODE_MULTIPLE = tk.MULTIPLE
+LISTBOX_SELECT_MODE_MULTIPLE = 'multiple'
+SELECT_MODE_BROWSE = tk.BROWSE
+LISTBOX_SELECT_MODE_BROWSE = 'browse'
+SELECT_MODE_EXTENDED = tk.EXTENDED
+LISTBOX_SELECT_MODE_EXTENDED = 'extended'
+SELECT_MODE_SINGLE = tk.SINGLE
+LISTBOX_SELECT_MODE_SINGLE = 'single'
+
+TABLE_SELECT_MODE_NONE = tk.NONE
+TABLE_SELECT_MODE_BROWSE = tk.BROWSE
+TABLE_SELECT_MODE_EXTENDED = tk.EXTENDED
+DEFAULT_TABLE_SECECT_MODE = TABLE_SELECT_MODE_EXTENDED
+
+TITLE_LOCATION_TOP = tk.N
+TITLE_LOCATION_BOTTOM = tk.S
+TITLE_LOCATION_LEFT = tk.W
+TITLE_LOCATION_RIGHT = tk.E
+TITLE_LOCATION_TOP_LEFT = tk.NW
+TITLE_LOCATION_TOP_RIGHT = tk.NE
+TITLE_LOCATION_BOTTOM_LEFT = tk.SW
+TITLE_LOCATION_BOTTOM_RIGHT = tk.SE
+
+TEXT_LOCATION_TOP = tk.N
+TEXT_LOCATION_BOTTOM = tk.S
+TEXT_LOCATION_LEFT = tk.W
+TEXT_LOCATION_RIGHT = tk.E
+TEXT_LOCATION_TOP_LEFT = tk.NW
+TEXT_LOCATION_TOP_RIGHT = tk.NE
+TEXT_LOCATION_BOTTOM_LEFT = tk.SW
+TEXT_LOCATION_BOTTOM_RIGHT = tk.SE
+TEXT_LOCATION_CENTER = tk.CENTER
+
+
+THEME_DEFAULT = 'default'
+THEME_WINNATIVE = 'winnative'
+THEME_CLAM = 'clam'
+THEME_ALT = 'alt'
+THEME_CLASSIC = 'classic'
+THEME_VISTA = 'vista'
+THEME_XPNATIVE = 'xpnative'
+
+# DEFAULT_METER_ORIENTATION = 'Vertical'
+# ----====----====----==== Constants the user should NOT f-with ====----====----====----#
+ThisRow = 555666777 # magic number
+
+# DEFAULT_WINDOW_ICON = ''
+MESSAGE_BOX_LINE_WIDTH = 60
+
+# "Special" Key Values.. reserved
+# Key representing a Read timeout
+TIMEOUT_KEY = '__TIMEOUT__'
+# Key indicating should not create any return values for element
+WRITE_ONLY_KEY = '__WRITE ONLY__'
+
+MENU_DISABLED_CHARACTER = '!'
+MENU_KEY_SEPARATOR = '::'
+
+ENABLE_TK_WINDOWS = False
+
+# ====================================================================== #
+# One-liner functions that are handy as f_ck #
+# ====================================================================== #
+def RGB(red, green, blue):
+ """
+ Given integer values of Red, Green, Blue, return a color string "#RRGGBB"
+ :param red: (int) Red portion from 0 to 255
+ :param green: (int) Green portion from 0 to 255
+ :param blue: (int) Blue portion from 0 to 255
+ :return: (str) A single RGB String in the format "#RRGGBB" where each pair is a hex number.
+ """
+ return '#%02x%02x%02x' % (red, green, blue)
+
+
+# ====================================================================== #
+# Enums for types #
+# ====================================================================== #
+# ------------------------- Button types ------------------------- #
+# todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality
+# uncomment this line and indent to go back to using Enums
+BUTTON_TYPE_BROWSE_FOLDER = 1
+BUTTON_TYPE_BROWSE_FILE = 2
+BUTTON_TYPE_BROWSE_FILES = 21
+BUTTON_TYPE_SAVEAS_FILE = 3
+BUTTON_TYPE_CLOSES_WIN = 5
+BUTTON_TYPE_CLOSES_WIN_ONLY = 6
+BUTTON_TYPE_READ_FORM = 7
+BUTTON_TYPE_REALTIME = 9
+BUTTON_TYPE_CALENDAR_CHOOSER = 30
+BUTTON_TYPE_COLOR_CHOOSER = 40
+BUTTON_TYPE_SHOW_DEBUGGER = 50
+
+# ------------------------- Element types ------------------------- #
+
+ELEM_TYPE_TEXT = 'text'
+ELEM_TYPE_INPUT_TEXT = 'input'
+ELEM_TYPE_INPUT_COMBO = 'combo'
+ELEM_TYPE_INPUT_OPTION_MENU = 'option menu'
+ELEM_TYPE_INPUT_RADIO = 'radio'
+ELEM_TYPE_INPUT_MULTILINE = 'multiline'
+ELEM_TYPE_INPUT_CHECKBOX = 'checkbox'
+ELEM_TYPE_INPUT_SPIN = 'spind'
+ELEM_TYPE_BUTTON = 'button'
+ELEM_TYPE_IMAGE = 'image'
+ELEM_TYPE_CANVAS = 'canvas'
+ELEM_TYPE_FRAME = 'frame'
+ELEM_TYPE_GRAPH = 'graph'
+ELEM_TYPE_TAB = 'tab'
+ELEM_TYPE_TAB_GROUP = 'tabgroup'
+ELEM_TYPE_INPUT_SLIDER = 'slider'
+ELEM_TYPE_INPUT_LISTBOX = 'listbox'
+ELEM_TYPE_OUTPUT = 'output'
+ELEM_TYPE_COLUMN = 'column'
+ELEM_TYPE_MENUBAR = 'menubar'
+ELEM_TYPE_PROGRESS_BAR = 'progressbar'
+ELEM_TYPE_BLANK = 'blank'
+ELEM_TYPE_TABLE = 'table'
+ELEM_TYPE_TREE = 'tree'
+ELEM_TYPE_ERROR = 'error'
+ELEM_TYPE_SEPARATOR = 'separator'
+ELEM_TYPE_STATUSBAR = 'statusbar'
+ELEM_TYPE_PANE = 'pane'
+ELEM_TYPE_BUTTONMENU = 'buttonmenu'
+
+# STRETCH == ERROR ELEMENT as a filler
+
+# ------------------------- Popup Buttons Types ------------------------- #
+POPUP_BUTTONS_YES_NO = 1
+POPUP_BUTTONS_CANCELLED = 2
+POPUP_BUTTONS_ERROR = 3
+POPUP_BUTTONS_OK_CANCEL = 4
+POPUP_BUTTONS_OK = 0
+POPUP_BUTTONS_NO_BUTTONS = 5
+
+
+# ------------------------------------------------------------------------- #
+# ToolTip used by the Elements #
+# ------------------------------------------------------------------------- #
+
+class ToolTip:
+ """
+ Create a tooltip for a given widget
+ (inspired by https://stackoverflow.com/a/36221216)
+ This is an INTERNALLY USED only class. Users should not refer to this class at all.
+ """
+ def __init__(self, widget, text, timeout=DEFAULT_TOOLTIP_TIME):
+ """
+
+ :param widget: (widget type varies) The tkinter widget
+ :param text: (str) text for the tooltip. It can inslude \n
+ :param timeout: (int) Time in milliseconds that mouse must remain still before tip is shown
+
+ """
+ self.widget = widget
+ self.text = text
+ self.timeout = timeout
+ # self.wraplength = wraplength if wraplength else widget.winfo_screenwidth() // 2
+ self.tipwindow = None
+ self.id = None
+ self.x = self.y = 0
+ self.widget.bind("", self.enter)
+ self.widget.bind("", self.leave)
+ self.widget.bind("", self.leave)
+
+ def enter(self, event=None):
+ """
+ Called by tkinter when mouse enters a widget
+ :param event: from tkinter. Has x,y coordinates of mouse
+
+ """
+ self.x = event.x
+ self.y = event.y
+ self.schedule()
+
+ def leave(self, event=None):
+ """
+ Called by tktiner when mouse exits a widget
+ :param event: from tkinter. Event info that's not used by function.
+
+ """
+ self.unschedule()
+ self.hidetip()
+
+ def schedule(self):
+ """
+ Schedule a timer to time how long mouse is hovering
+ """
+ self.unschedule()
+ self.id = self.widget.after(self.timeout, self.showtip)
+
+ def unschedule(self):
+ """
+ Cancel timer used to time mouse hover
+ """
+ if self.id:
+ self.widget.after_cancel(self.id)
+ self.id = None
+
+ def showtip(self):
+ """
+ Creates a topoltip window with the tooltip text inside of it
+ """
+ if self.tipwindow:
+ return
+ x = self.widget.winfo_rootx() + self.x + DEFAULT_TOOLTIP_OFFSET[0]
+ y = self.widget.winfo_rooty() + self.y + DEFAULT_TOOLTIP_OFFSET[1]
+ self.tipwindow = tk.Toplevel(self.widget)
+ self.tipwindow.wm_overrideredirect(True)
+ self.tipwindow.wm_geometry("+%d+%d" % (x, y))
+ self.tipwindow.wm_attributes("-topmost", 1)
+
+ label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT,
+ background=TOOLTIP_BACKGROUND_COLOR, relief=tk.SOLID, borderwidth=1)
+ label.pack()
+
+ def hidetip(self):
+ """
+ Destroy the tooltip window
+ """
+ if self.tipwindow:
+ self.tipwindow.destroy()
+ self.tipwindow = None
+
+
+# ---------------------------------------------------------------------- #
+# Cascading structure.... Objects get larger #
+# Button #
+# Element #
+# Row #
+# Form #
+# ---------------------------------------------------------------------- #
+# ------------------------------------------------------------------------- #
+# Element CLASS #
+# ------------------------------------------------------------------------- #
+class Element():
+ """
+ The base class for all Elements.
+ Holds the basic description of an Element like size and colors
+ """
+ def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None):
+ """
+ Element base class. Only used internally. User will not create an Element object by itself
+
+ :param type: (int) (could be enum) The type of element. These constants all start with "ELEM_TYPE_"
+ :param size: Tuple[int, int] (width ,height ) w=characters-wide, h=rows-high
+ :param auto_size_text: (bool) True if the Widget should be shrunk to exactly fit the number of chars to show
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc (see docs for exact formats)
+ :param background_color: (str) color of background. Can be in #RRGGBB format or a color name "black"
+ :param text_color: (str) element's text color. Can be in #RRGGBB format or a color name "black"
+ :param key: (Any) Identifies an Element. Should be UNIQUE to this window.
+ :param pad: (int, int) or ((int,int),(int,int)) Amount of padding to put around element in pixels (left/right, top/bottom)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element (Default = True)
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+ self.Size = size
+ self.Type = type
+ self.AutoSizeText = auto_size_text
+ self.Pad = pad
+ self.Font = font
+
+ self.TKStringVar = None
+ self.TKIntVar = None
+ self.TKText = None
+ self.TKEntry = None
+ self.TKImage = None
+
+ self.ParentForm = None # type: Window
+ self.ParentContainer = None # will be a Form, Column, or Frame element
+ self.TextInputDefault = None
+ self.Position = (0, 0) # Default position Row 0, Col 0
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR
+ self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR
+ self.Key = key # dictionary key for return values
+ self.Tooltip = tooltip
+ self.TooltipObject = None
+ self.Visible = visible
+ self.TKRightClickMenu = None
+ self.Widget = None # Set when creating window. Has the main tkinter widget for element
+ self.Tearoff = False
+ self.ParentRowFrame = None # type tk.Frame
+ self.metadata = metadata # type: Any
+
+ def _RightClickMenuCallback(self, event):
+ """
+ Callback function that's called when a right click happens. Shows right click menu as result
+
+ :param event: information provided by tkinter about the event including x,y location of click
+
+ """
+ self.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0)
+ self.TKRightClickMenu.grab_release()
+
+ def _MenuItemChosenCallback(self, item_chosen): # TEXT Menu item callback
+ """
+ Callback function called when user chooses a menu item from menubar, Button Menu or right click menu
+
+ :param item_chosen: (str) String holding the value chosen.
+
+ """
+ # print('IN MENU ITEM CALLBACK', item_chosen)
+ self.MenuItemChosen = item_chosen.replace('&', '')
+ self.ParentForm.LastButtonClicked = self.MenuItemChosen
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def _FindReturnKeyBoundButton(self, form):
+ """
+ Searches for which Button has the flag Button.BindReturnKey set. It is called recursively when a
+ "Container Element" is encountered. Func has to walk entire window including these "sub-forms"
+
+ :param form: the Window object to search
+ :return: Union[Button, None] Button Object if a button is found, else None if no button found
+ """
+ for row in form.Rows:
+ for element in row:
+ if element.Type == ELEM_TYPE_BUTTON:
+ if element.BindReturnKey:
+ return element
+ if element.Type == ELEM_TYPE_COLUMN:
+ rc = self._FindReturnKeyBoundButton(element)
+ if rc is not None:
+ return rc
+ if element.Type == ELEM_TYPE_FRAME:
+ rc = self._FindReturnKeyBoundButton(element)
+ if rc is not None:
+ return rc
+ if element.Type == ELEM_TYPE_TAB_GROUP:
+ rc = self._FindReturnKeyBoundButton(element)
+ if rc is not None:
+ return rc
+ if element.Type == ELEM_TYPE_TAB:
+ rc = self._FindReturnKeyBoundButton(element)
+ if rc is not None:
+ return rc
+ if element.Type == ELEM_TYPE_PANE:
+ rc = self._FindReturnKeyBoundButton(element)
+ if rc is not None:
+ return rc
+ return None
+
+ def _TextClickedHandler(self, event):
+ """
+ Callback that's called when a text element is clicked on with events enabled on the Text Element.
+ Result is that control is returned back to user (quits mainloop).
+
+ :param event:
+
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = self.DisplayText
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def _ReturnKeyHandler(self, event):
+ """
+ Internal callback for the ENTER / RETURN key. Results in calling the ButtonCallBack for element that has the return key bound to it, just as if button was clicked.
+
+ :param event:
+
+ """
+ MyForm = self.ParentForm
+ button_element = self._FindReturnKeyBoundButton(MyForm)
+ if button_element is not None:
+ button_element.ButtonCallBack()
+
+ def _ListboxSelectHandler(self, event):
+ """
+ Internal callback function for when a listbox item is selected
+
+ :param event: Information from tkinter about the callback
+
+ """
+ # first, get the results table built
+ # modify the Results table in the parent FlexForm object
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def _ComboboxSelectHandler(self, event):
+ """
+ Internal callback function for when an entry is selected in a Combobox.
+ :param event: Event data from tkinter (not used)
+
+ """
+ # first, get the results table built
+ # modify the Results table in the parent FlexForm object
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def _RadioHandler(self):
+ """
+ Internal callback for when a radio button is selected and enable events was set for radio
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def _CheckboxHandler(self):
+ """
+ Internal callback for when a checkbnox is selected and enable events was set for checkbox
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def _TabGroupSelectHandler(self, event):
+ """
+ Internal callback for when a Tab is selected and enable events was set for TabGroup
+
+ :param event: Event data passed in by tkinter (not used)
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def _KeyboardHandler(self, event):
+ """
+ Internal callback for when a key is pressed andd return keyboard events was set for window
+
+ :param event: Event data passed in by tkinter (not used)
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def _ClickHandler(self, event):
+ """
+ Internal callback for when a mouse was clicked... I think.
+
+ :param event: Event data passed in by tkinter (not used)
+ """
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def ButtonReboundCallback(self, event):
+ """
+ Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal
+ callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button
+ callback function that is normally called.
+
+ :param event: (unknown) Not used in this function.
+ """
+ # print(f'Button callback event = {obj_to_string_single_obj(event)}')
+ try:
+ self.ButtonCallBack()
+ except:
+ print('** ButtonReboundCallback - warning your element does not have a ButtonCallBack method **')
+
+
+ def SetTooltip(self, tooltip_text):
+ """
+ Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip').
+
+ :param tooltip_text: (str) the text to show in tooltip.
+ """
+ self.TooltipObject = ToolTip(self.Widget, text=tooltip_text, timeout=DEFAULT_TOOLTIP_TIME)
+
+ def SetFocus(self, force=False):
+ """
+ Sets the current focus to be on this element
+
+ :param force: (bool) if True will call focus_force otherwise calls focus_set
+ """
+
+ try:
+ if force:
+ self.Widget.focus_force()
+ else:
+ self.Widget.focus_set()
+ except:
+ print('Was unable to set focus. The Widget passed in was perhaps not present in this element? Check your elements .Widget property')
+
+
+ def set_size(self, size=(None, None)):
+ """
+ Changes the size of an element to a specific size.
+ It's possible to specify None for one of sizes so that only 1 of the element's dimensions are changed.
+
+ :param size: Tuple[int, int] The size in characters, rows typically. In some cases they are pixels
+ """
+ try:
+ if size[0] != None:
+ self.Widget.config(width=size[0])
+ except:
+ print('Warning, error setting width on element with key=', self.Key)
+ try:
+ if size[1] != None:
+ self.Widget.config(height=size[1])
+ except:
+ print('Warning, error setting height on element with key=', self.Key)
+
+
+ def get_size(self):
+ """
+ Return the size of an element in Pixels. Care must be taken as some elements use characters to specify their size but will return pixels when calling this get_size method.
+ :return: Tuple[int, int] - Width, Height of the element
+ """
+ try:
+ w = self.Widget.winfo_width()
+ h = self.Widget.winfo_height()
+ except:
+ print('Warning, error getting size of element', self.Key)
+ w = h = None
+ return w,h
+
+
+ def hide_row(self):
+ """
+ Hide the entire row an Element is located on.
+ Use this if you must have all space removed when you are hiding an element, including the row container
+ """
+ try:
+ self.ParentRowFrame.pack_forget()
+ except:
+ print('Warning, error hiding element row for key =', self.Key)
+
+
+ def unhide_row(self):
+ """
+ Unhides (makes visible again) the row container that the Element is located on.
+ Note that it will re-appear at the bottom of the window / container, most likely.
+ """
+ try:
+ self.ParentRowFrame.pack()
+ except:
+ print('Warning, error hiding element row for key =', self.Key)
+
+ def expand(self, expand_x=False, expand_y=False):
+ """
+ Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions
+
+ :param expand_x: (Bool) If True Element will expand in the Horizontal directions
+ :param expand_y: (Bool) If True Element will expand in the Vertical directions
+ """
+
+ if expand_x and expand_y:
+ fill = tk.BOTH
+ elif expand_x:
+ fill = tk.X
+ elif expand_y:
+ fill = tk.Y
+ else:
+ return
+
+ self.Widget.pack(expand=True, fill=fill)
+ self.ParentRowFrame.pack(expand=True, fill=fill)
+
+
+ def __call__(self, *args, **kwargs):
+ """
+ Makes it possible to "call" an already existing element. When you do make the "call", it actually calls
+ the Update method for the element.
+ Example: If this text element was in yoiur layout:
+ sg.Text('foo', key='T')
+ Then you can call the Update method for that element by writing:
+ window.FindElement('T')('new text value')
+
+ :param args:
+ :param kwargs:
+ :return:
+ """
+ return self.Update(*args, **kwargs)
+
+ button_rebound_callback = ButtonReboundCallback
+ set_tooltip = SetTooltip
+ set_focus = SetFocus
+
+
+# ---------------------------------------------------------------------- #
+# Input Class #
+# ---------------------------------------------------------------------- #
+class InputText(Element):
+ """
+ Display a single text input field. Based on the tkinter Widget `Entry`
+ """
+ def __init__(self, default_text='', size=(None, None), disabled=False, password_char='',
+ justification=None, background_color=None, text_color=None, font=None, tooltip=None,
+ change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, pad=None,
+ right_click_menu=None, visible=True, metadata=None):
+ """
+
+ :param default_text: (str) Text initially shown in the input box as a default value(Default value = '')
+ :param size: Tuple[int, int] (width, height) w=characters-wide, h=rows-high
+ :param disabled: (bool) set disable state for element (Default = False)
+ :param password_char: (char) Password character if this is a password field (Default value = '')
+ :param justification: (str) justification for data display. Valid choices - left, right, center
+ :param background_color: (str) color of background in one of the color formats
+ :param text_color: (str) color of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param change_submits: (bool) * DEPRICATED DO NOT USE! Same as enable_events
+ :param enable_events: (bool) If True then changes to this element are immediately reported as an event. Use this instead of change_submits (Default = False)
+ :param do_not_clear: (bool) If False then the field will be set to blank after ANY event (button, any event) (Default = True)
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param focus: (bool) Determines if initial focus should go to this element.
+ :param pad: (int, int) or ((int, int), (int, int)) Tuple(s). Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below))
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element (Default = True)
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+ self.DefaultText = default_text
+ self.PasswordCharacter = password_char
+ bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+ self.Focus = focus
+ self.do_not_clear = do_not_clear
+ self.Justification = justification
+ self.Disabled = disabled
+ self.ChangeSubmits = change_submits or enable_events
+ self.RightClickMenu = right_click_menu
+ self.TKEntry = self.Widget = None # type: tk.Entry
+ super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad,
+ font=font, tooltip=tooltip, visible=visible, metadata=metadata)
+
+ def Update(self, value=None, disabled=None, select=None, visible=None,text_color=None, background_color=None, move_cursor_to='end'):
+ """
+ Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (str) new text to display as default text in Input field
+ :param disabled: (bool) disable or enable state of the element (sets Entry Widget to readonly or normal)
+ :param select: (bool) if True, then the text will be selected
+ :param visible: (bool) change visibility of element
+ :param text_color: (str) change color of text being typed
+ :param background_color: (str) change color of the background
+ :param move_cursor_to: Union[int, str] Moves the cursor to a particular offset. Defaults to 'end'
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if disabled is True:
+ self.TKEntry['state'] = 'readonly'
+ elif disabled is False:
+ self.TKEntry['state'] = 'normal'
+ if background_color is not None:
+ self.TKEntry.configure(background=background_color)
+ if text_color is not None:
+ self.TKEntry.configure(fg=text_color)
+ if value is not None:
+ try:
+ self.TKStringVar.set(value)
+ except:
+ pass
+ self.DefaultText = value
+ if move_cursor_to == 'end':
+ self.TKEntry.icursor(tk.END)
+ elif move_cursor_to is not None:
+ self.TKEntry.icursor(move_cursor_to)
+ if select:
+ self.TKEntry.select_range(0, 'end')
+ if visible is False:
+ self.TKEntry.pack_forget()
+ elif visible is True:
+ self.TKEntry.pack()
+
+ def Get(self):
+ """
+ Read and return the current value of the input element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :return: (str) current value of Input field or '' if error encountered
+ """
+ try:
+ text = self.TKStringVar.get()
+ except:
+ text = ''
+ return text
+
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ------------------------- INPUT TEXT Element lazy functions ------------------------- #
+In = InputText
+Input = InputText
+I = InputText
+
+
+# ---------------------------------------------------------------------- #
+# Combo #
+# ---------------------------------------------------------------------- #
+class Combo(Element):
+ """
+ ComboBox Element - A combination of a single-line input and a drop-down menu. User can type in their own value or choose from list.
+ """
+ def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None,
+ text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None,
+ tooltip=None, readonly=False, font=None, visible=True, metadata=None):
+ """
+ :param values: List[Any] values to choose. While displayed as text, the items returned are what the caller supplied, not text
+ :param default_value: (Any) Choice to be displayed as initial value. Must match one of values variable contents
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) True if element should be the same size as the contents
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param change_submits: (bool) DEPRICATED DO NOT USE. Use `enable_events` instead
+ :param enable_events: (bool) Turns on the element specific events. Combo event is when a choice is made
+ :param disabled: (bool) set disable state for element
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text that will appear when mouse hovers over this element
+ :param readonly: (bool) make element readonly (user can't change). True means user cannot change
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+ self.Values = values
+ self.DefaultValue = default_value
+ self.ChangeSubmits = change_submits or enable_events
+ self.Widget = self.TKCombo = None # type: ttk.Combobox
+ self.Disabled = disabled
+ self.Readonly = readonly
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+
+ super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg,
+ text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata)
+
+ def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None, visible=None):
+ """
+ Changes some of the settings for the Combo Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (Any) change which value is current selected hased on new list of previous list of choices
+ :param values: List[Any] change list of choices
+ :param set_to_index: (int) change selection to a particular choice starting with index = 0
+ :param disabled: (bool) disable or enable state of the element
+ :param readonly: (bool) if True make element readonly (user cannot change any choices)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if values is not None:
+ try:
+ self.TKCombo['values'] = values
+ self.TKCombo.current(0)
+ except:
+ pass
+ self.Values = values
+ if value is not None:
+ for index, v in enumerate(self.Values):
+ if v == value:
+ try:
+ self.TKCombo.current(index)
+ except:
+ pass
+ self.DefaultValue = value
+ break
+ if set_to_index is not None:
+ try:
+ self.TKCombo.current(set_to_index)
+ self.DefaultValue = self.Values[set_to_index]
+ except:
+ pass
+ if disabled == True:
+ self.TKCombo['state'] = 'disable'
+ elif disabled == False:
+ self.TKCombo['state'] = 'enable'
+ if readonly is not None:
+ self.Readonly = readonly
+ if self.Readonly:
+ self.TKCombo['state'] = 'readonly'
+ if font is not None:
+ self.TKCombo.configure(font=font)
+ if visible is False:
+ self.TKCombo.pack_forget()
+ elif visible is True:
+ self.TKCombo.pack()
+
+ def Get(self):
+ """
+ Returns the current (right now) value of the Combo. DO NOT USE THIS AS THE NORMAL WAY OF READING A COMBO!
+ You should be using values from your call to window.Read instead. Know what you're doing if you use it.
+
+ :return: Union[Any, None] Returns the value of what is currently chosen
+ """
+ try:
+ if self.TKCombo.current() == -1: # if the current value was not in the original list
+ value = self.TKCombo.get() # then get the value typed in by user
+ else:
+ value = self.Values[self.TKCombo.current()] # get value from original list given index
+ except:
+ value = None # only would happen if user closes window
+ return value
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+# ------------------------- INPUT COMBO Element lazy functions ------------------------- #
+InputCombo = Combo
+DropDown = InputCombo
+Drop = InputCombo
+DD = Combo
+
+# ---------------------------------------------------------------------- #
+# Option Menu #
+# ---------------------------------------------------------------------- #
+class OptionMenu(Element):
+ """
+ Option Menu is an Element available ONLY on the tkinter port of PySimpleGUI. It's is a widget that is unique
+ to tkinter. However, it looks much like a ComboBox. Instead of an arrow to click to pull down the list of
+ choices, another little graphic is shown on the widget to indicate where you click. After clicking to activate,
+ it looks like a Combo Box that you scroll to select a choice.
+ """
+ def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None,
+ background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None):
+ """
+ :param values: List[Any] Values to be displayed
+ :param default_value: (Any) the value to choose by default
+ :param size: Tuple[int, int] (width, height) size in characters (wide) and rows (high)
+ :param disabled: (bool) control enabled / disabled
+ :param auto_size_text: (bool) True if size of Element should match the contents of the items
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text that will appear when mouse hovers over this element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+ self.Values = values
+ self.DefaultValue = default_value
+ self.Widget = self.TKOptionMenu = None # type: tk.OptionMenu
+ self.Disabled = disabled
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+
+ super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=size, auto_size_text=auto_size_text, background_color=bg,
+ text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
+
+ def Update(self, value=None, values=None, disabled=None, visible=None):
+ """
+ Changes some of the settings for the OptionMenu Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (Any) the value to choose by default
+ :param values: List[Any] Values to be displayed
+ :param disabled: (bool) disable or enable state of the element
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if values is not None:
+ self.Values = values
+ self.TKOptionMenu['menu'].delete(0, 'end')
+
+ # Insert list of new options (tk._setit hooks them up to var)
+ self.TKStringVar.set(self.Values[0])
+ for new_value in self.Values:
+ self.TKOptionMenu['menu'].add_command(label=new_value, command=tk._setit(self.TKStringVar, new_value))
+
+ if self.Values is not None:
+ for index, v in enumerate(self.Values):
+ if v == value:
+ try:
+ self.TKStringVar.set(value)
+ except:
+ pass
+ self.DefaultValue = value
+ break
+ if disabled == True:
+ self.TKOptionMenu['state'] = 'disabled'
+ elif disabled == False:
+ self.TKOptionMenu['state'] = 'normal'
+ if visible is False:
+ self.TKOptionMenu.pack_forget()
+ elif visible is True:
+ self.TKOptionMenu.pack()
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ------------------------- OPTION MENU Element lazy functions ------------------------- #
+InputOptionMenu = OptionMenu
+
+# ---------------------------------------------------------------------- #
+# Listbox #
+# ---------------------------------------------------------------------- #
+class Listbox(Element):
+ """
+ A List Box. Provide a list of values for the user to choose one or more of. Returns a list of selected rows
+ when a window.Read() is executed.
+ """
+ def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False,
+ bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, no_scrollbar=False,
+ background_color=None, text_color=None, key=None, pad=None, tooltip=None, right_click_menu=None,
+ visible=True, metadata=None):
+ """
+ :param values: List[Any] list of values to display. Can be any type including mixed types as long as they have __str__ method
+ :param default_values: List[Any] which values should be initially selected
+ :param select_mode: [enum] Select modes are used to determine if only 1 item can be selected or multiple and how they can be selected. Valid choices begin with "LISTBOX_SELECT_MODE_" and include:
+ LISTBOX_SELECT_MODE_SINGLE
+ LISTBOX_SELECT_MODE_MULTIPLE
+ LISTBOX_SELECT_MODE_BROWSE
+ LISTBOX_SELECT_MODE_EXTENDED
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Listbox generates events when an item is clicked
+ :param bind_return_key: (bool) If True, then the return key will cause a the Listbox to generate an event
+ :param size: Tuple(int, int) (width, height) width = characters-wide, height = rows-high
+ :param disabled: (bool) set disable state for element
+ :param auto_size_text: (bool) True if element should be the same size as the contents
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+ self.Values = values
+ self.DefaultValues = default_values
+ self.TKListbox = None
+ self.ChangeSubmits = change_submits or enable_events
+ self.BindReturnKey = bind_return_key
+ self.Disabled = disabled
+ if select_mode == LISTBOX_SELECT_MODE_BROWSE:
+ self.SelectMode = SELECT_MODE_BROWSE
+ elif select_mode == LISTBOX_SELECT_MODE_EXTENDED:
+ self.SelectMode = SELECT_MODE_EXTENDED
+ elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE:
+ self.SelectMode = SELECT_MODE_MULTIPLE
+ elif select_mode == LISTBOX_SELECT_MODE_SINGLE:
+ self.SelectMode = SELECT_MODE_SINGLE
+ else:
+ self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+ self.RightClickMenu = right_click_menu
+ self.vsb = None # type: tk.Scrollbar
+ self.TKListbox = self.Widget = None # type: tk.Listbox
+ self.NoScrollbar = no_scrollbar
+ super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=size, auto_size_text=auto_size_text, font=font,
+ background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
+
+
+ def Update(self, values=None, disabled=None, set_to_index=None, scroll_to_index=None, visible=None):
+ """
+ Changes some of the settings for the Listbox Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param values: List[Any] new list of choices to be shown to user
+ :param disabled: (bool) disable or enable state of the element
+ :param set_to_index: Union[int, list, tuple] highlights the item(s) indicated. If parm is an int one entry will be set. If is a list, then each entry in list is highlighted
+ :param scroll_to_index: (int) scroll the listbox so that this index is the first shown
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if disabled == True:
+ self.TKListbox.configure(state='disabled')
+ elif disabled == False:
+ self.TKListbox.configure(state='normal')
+ if values is not None:
+ self.TKListbox.delete(0, 'end')
+ for item in values:
+ self.TKListbox.insert(tk.END, item)
+ self.TKListbox.selection_set(0, 0)
+ self.Values = values
+ if set_to_index is not None:
+ self.TKListbox.selection_clear(0, len(self.Values)) # clear all listbox selections
+ if type(set_to_index) in (tuple, list):
+ for i in set_to_index:
+ try:
+ self.TKListbox.selection_set(i, i)
+ except:
+ warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index))
+ else:
+ try:
+ self.TKListbox.selection_set(set_to_index, set_to_index)
+ except:
+ warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index))
+ if visible is False:
+ self.TKListbox.pack_forget()
+ if not self.NoScrollbar:
+ self.vsb.pack_forget()
+ elif visible is True:
+ self.TKListbox.pack()
+ if not self.NoScrollbar:
+ self.vsb.pack()
+ if scroll_to_index is not None and len(self.Values):
+ self.TKListbox.yview_moveto(scroll_to_index/len(self.Values))
+
+
+ def SetValue(self, values):
+ """
+ Set listbox highlighted choices
+
+ :param values: List[Any] new values to choose based on previously set values
+
+ """
+ for index, item in enumerate(self.Values):
+ try:
+ if item in values:
+ self.TKListbox.selection_set(index)
+ else:
+ self.TKListbox.selection_clear(index)
+ except:
+ pass
+ self.DefaultValues = values
+
+
+ def GetListValues(self):
+ # type: (Listbox) -> List[Any]
+ """
+ Returns list of Values provided by the user in the user's format
+
+ :return: List[Any]. List of values. Can be any / mixed types -> []
+ """
+ return self.Values
+
+
+ def GetIndexes(self):
+ """
+ Returns the items currently selected as a list of indexes
+
+ :return: List[int] A list of offsets into values that is currently selected
+ """
+ return self.TKListbox.curselection()
+
+
+ get_indexes = GetIndexes
+ get_list_values = GetListValues
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ set_value = SetValue
+ update = Update
+
+
+LBox = Listbox
+LB = Listbox
+
+# ---------------------------------------------------------------------- #
+# Radio #
+# ---------------------------------------------------------------------- #
+class Radio(Element):
+ """
+ Radio Button Element - Used in a group of other Radio Elements to provide user with ability to select only
+ 1 choice in a list of choices.
+ """
+ def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None,
+ background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None,
+ change_submits=False, enable_events=False, visible=True, metadata=None):
+ """
+
+ :param text: (str) Text to display next to button
+ :param group_id: (Any) Groups together multiple Radio Buttons. Any type works
+ :param default: (bool). Set to True for the one element of the group you want initially selected
+ :param disabled: (bool) set disable state
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) if True will size the element to match the length of the text
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Radio Button events happen when an item is selected
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.InitialState = default
+ self.Text = text
+ self.TKRadio = None
+ self.GroupID = group_id
+ self.Value = None
+ self.Disabled = disabled
+ self.TextColor = text_color or DEFAULT_TEXT_COLOR
+ self.ChangeSubmits = change_submits or enable_events
+ self.EncodedRadioValue = None
+ super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font,
+ background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
+ tooltip=tooltip, visible=visible, metadata=metadata)
+
+ def Update(self, value=None, disabled=None, visible=None):
+ """
+ Changes some of the settings for the Radio Button Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (bool) if True change to selected and set others in group to unselected
+ :param disabled: (bool) disable or enable state of the element
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ try:
+ if value:
+ self.TKIntVar.set(self.EncodedRadioValue)
+ except:
+ pass
+ self.InitialState = value
+ if disabled == True:
+ self.TKRadio['state'] = 'disabled'
+ elif disabled == False:
+ self.TKRadio['state'] = 'normal'
+ if visible is False:
+ self.TKRadio.pack_forget()
+ elif visible is True:
+ self.TKRadio.pack()
+
+ def ResetGroup(self):
+ """
+ Sets all Radio Buttons in the group to not selected
+ """
+ self.TKIntVar.set(0)
+
+ def Get(self):
+ # type: (Radio) -> bool
+ """
+ A snapshot of the value of Radio Button -> (bool)
+
+ :return: (bool) True if this radio button is selected
+ """
+ return self.TKIntVar.get() == self.EncodedRadioValue
+
+ get = Get
+ reset_group = ResetGroup
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+R = Radio
+Rad = Radio
+
+
+
+# ---------------------------------------------------------------------- #
+# Checkbox #
+# ---------------------------------------------------------------------- #
+class Checkbox(Element):
+ """
+ Checkbox Element - Displays a checkbox and text next to it
+ """
+ def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None,
+ text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None,
+ tooltip=None, visible=True, metadata=None):
+ """
+ :param text: (str) Text to display next to checkbox
+ :param default: (bool). Set to True if you want this checkbox initially checked
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) if True will size the element to match the length of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Checkbox events happen when an item changes
+ :param disabled: (bool) set disable state
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.Text = text
+ self.InitialState = default
+ self.Value = None
+ self.TKCheckbutton = self.Widget = None # type: tk.Checkbutton
+ self.Disabled = disabled
+ self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
+ self.ChangeSubmits = change_submits or enable_events
+
+ super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=size, auto_size_text=auto_size_text, font=font,
+ background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
+ tooltip=tooltip, visible=visible, metadata=metadata)
+
+ def Get(self):
+ # type: (Checkbox) -> bool
+ """
+ Return the current state of this checkbox
+
+ :return: (bool) Current state of checkbox
+ """
+ return self.TKIntVar.get()
+
+ def Update(self, value=None, disabled=None, visible=None):
+ """
+ Changes some of the settings for the Checkbox Element. Must call `Window.Read` or `Window.Finalize` prior.
+ Note that changing visibility may cause element to change locations when made visible after invisible
+
+ :param value: (bool) if True checks the checkbox, False clears it
+ :param disabled: (bool) disable or enable element
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ try:
+ self.TKIntVar.set(value)
+ self.InitialState = value
+ except:
+ print('Checkbox update failed')
+ if disabled == True:
+ self.TKCheckbutton.configure(state='disabled')
+ elif disabled == False:
+ self.TKCheckbutton.configure(state='normal')
+ if visible is False:
+ self.TKCheckbutton.pack_forget()
+ elif visible is True:
+ self.TKCheckbutton.pack()
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ------------------------- CHECKBOX Element lazy functions ------------------------- #
+CB = Checkbox
+CBox = Checkbox
+Check = Checkbox
+
+
+# ---------------------------------------------------------------------- #
+# Spin #
+# ---------------------------------------------------------------------- #
+
+class Spin(Element):
+ """
+ A spinner with up/down buttons and a single line of text. Choose 1 values from list
+ """
+
+ def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False,
+ size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None,
+ pad=None, tooltip=None, visible=True, metadata=None):
+ """
+
+ :param values: List[Any] List of valid values
+ :param initial_value: (Any) Initial item to show in window. Choose from list of values supplied
+ :param disabled: (bool) set disable state
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Spin events happen when an item changes
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) if True will size the element to match the length of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.Values = values
+ self.DefaultValue = initial_value
+ self.ChangeSubmits = change_submits or enable_events
+ self.TKSpinBox = self.Widget = None # type: tk.Spinbox
+ self.Disabled = disabled
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+
+ super().__init__(ELEM_TYPE_INPUT_SPIN, size, auto_size_text, font=font, background_color=bg, text_color=fg,
+ key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, value=None, values=None, disabled=None, visible=None):
+ """
+ Changes some of the settings for the Spin Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (Any) set the current value from list of choices
+ :param values: List[Any] set available choices
+ :param disabled: (bool) disable or enable state of the element
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if values != None:
+ old_value = self.TKStringVar.get()
+ self.Values = values
+ self.TKSpinBox.configure(values=values)
+ self.TKStringVar.set(old_value)
+ if value is not None:
+ try:
+ self.TKStringVar.set(value)
+ except:
+ pass
+ self.DefaultValue = value
+ if disabled is not None:
+ self.TKSpinBox.configure(state='disabled' if disabled else 'normal')
+ # if disabled == True:
+ # self.TKSpinBox.configure(state='disabled')
+ # elif disabled == False:
+ # self.TKSpinBox.configure(state='normal')
+ if visible is False:
+ self.TKSpinBox.pack_forget()
+ elif visible is True:
+ self.TKSpinBox.pack()
+
+
+ def _SpinChangedHandler(self, event):
+ """
+ Callback function. Used internally only. Called by tkinter when Spinbox Widget changes. Results in Window.Read() call returning
+
+ :param event: passed in from tkinter
+ """
+ # first, get the results table built
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def Get(self):
+ """
+ Return the current chosen value showing in spinbox.
+ This value will be the same as what was provided as list of choices. If list items are ints, then the
+ item returned will be an int (not a string)
+
+ :return: (Any) The currently visible entry
+ """
+ return self.TKStringVar.get()
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+
+# ---------------------------------------------------------------------- #
+# Multiline #
+# ---------------------------------------------------------------------- #
+class Multiline(Element):
+ """
+ Multiline Element - Display and/or read multiple lines of text. This is both an input and output element.
+ Other PySimpleGUI ports have a separate MultilineInput and MultilineOutput elements. May want to split this
+ one up in the future too.
+ """
+
+ def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None,
+ size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False,
+ enable_events=False, do_not_clear=True, key=None, focus=False, font=None, pad=None, tooltip=None,
+ right_click_menu=None, visible=True, metadata=None):
+ """
+
+ :param default_text: (str) Initial text to show
+ :param enter_submits: (bool) if True, the Window.Read call will return is enter key is pressed in this element
+ :param disabled: (bool) set disable state
+ :param autoscroll: (bool) If True the contents of the element will automatically scroll as more data added to the end
+ :param border_width: (int) width of border around element in pixels
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) if True will size the element to match the length of the text
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Spin events happen when an item changes
+ :param do_not_clear: if False the element will be cleared any time the Window.Read call returns
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param focus: (bool) if True initial focus will go to this element
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.DefaultText = default_text
+ self.EnterSubmits = enter_submits
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ self.Focus = focus
+ self.do_not_clear = do_not_clear
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+ self.Autoscroll = autoscroll
+ self.Disabled = disabled
+ self.ChangeSubmits = change_submits or enable_events
+ self.RightClickMenu = right_click_menu
+ self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
+ self.TKText = self.Widget = None # type: tkst.ScrolledText
+ super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg,
+ text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None,
+ visible=None, autoscroll=None):
+ """
+ Changes some of the settings for the Multiline Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (str) new text to display
+ :param disabled: (bool) disable or enable state of the element
+ :param append: (bool) if True then new value will be added onto the end of the current value. if False then contents will be replaced.
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param text_color: (str) color of the text
+ :param background_color: (str) color of background
+ :param visible: (bool) set visibility state of the element
+ :param autoscroll: (bool) if True then contents of element are scrolled down when new text is added to the end
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if autoscroll is not None:
+ self.Autoscroll = autoscroll
+ if value is not None:
+ if self.Disabled:
+ self.TKText.configure(state='normal')
+ try:
+ if not append:
+ self.TKText.delete('1.0', tk.END)
+ self.TKText.insert(tk.END, value)
+ except:
+ pass
+ if self.Disabled:
+ self.TKText.configure(state='disabled')
+ self.DefaultText = value
+ if self.Autoscroll:
+ self.TKText.see(tk.END)
+ if disabled == True:
+ self.TKText.configure(state='disabled')
+ elif disabled == False:
+ self.TKText.configure(state='normal')
+ if background_color is not None:
+ self.TKText.configure(background=background_color)
+ if text_color is not None:
+ self.TKText.configure(fg=text_color)
+ if font is not None:
+ self.TKText.configure(font=font)
+ if visible is False:
+ self.TKText.pack_forget()
+ elif visible is True:
+ self.TKText.pack()
+
+ def Get(self):
+ """
+ Return current contents of the Multiline Element
+
+ :return: (str) current contents of the Multiline Element (used as an input type of Multiline
+ """
+
+ return self.TKText.get(1.0, tk.END)
+
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+ML = Multiline
+MLine = Multiline
+
+
+# ---------------------------------------------------------------------- #
+# Text #
+# ---------------------------------------------------------------------- #
+class Text(Element):
+ """
+ Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars.
+ """
+ def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=False, enable_events=False,
+ relief=None, font=None, text_color=None, background_color=None, border_width=None, justification=None, pad=None, key=None, right_click_menu=None, tooltip=None, visible=True, metadata=None):
+ """
+ :param text: (str) The text to display. Can include /n to achieve multiple lines
+ :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high
+ :param auto_size_text: (bool) if True size of the Text Element will be sized to fit the string provided in 'text' parm
+ :param click_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Text events happen when the text is clicked
+ :param relief: (str/enum) relief style around the text. Values are same as progress meter relief values. Should be a constant that is defined at starting with "RELIEF_" - `RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID`
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param text_color: (str) color of the text
+ :param background_color: (str) color of background
+ :param border_width: (int) number of pixels for the border (if using a relief)
+ :param justification: (str) how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.DisplayText = str(text)
+ self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
+ self.Justification = justification
+ self.Relief = relief
+ self.ClickSubmits = click_submits or enable_events
+ if background_color is None:
+ bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
+ else:
+ bg = background_color
+ self.RightClickMenu = right_click_menu
+ self.TKRightClickMenu = None
+ self.BorderWidth = border_width
+
+ super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT,
+ text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+
+
+ def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None):
+ """
+ Changes some of the settings for the Text Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (str) new text to show
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param visible: (bool) set visibility state of the element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ self.DisplayText = value
+ stringvar = self.TKStringVar
+ stringvar.set(value)
+ if background_color is not None:
+ self.TKText.configure(background=background_color)
+ if text_color is not None:
+ self.TKText.configure(fg=text_color)
+ if font is not None:
+ self.TKText.configure(font=font)
+ if visible is False:
+ self.TKText.pack_forget()
+ elif visible is True:
+ self.TKText.pack()
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+
+# ------------------------- Text Element lazy functions ------------------------- #
+
+Txt = Text # type: Text
+T = Text # type: Text
+
+
+# ---------------------------------------------------------------------- #
+# StatusBar #
+# ---------------------------------------------------------------------- #
+class StatusBar(Element):
+ """
+ A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line
+ """
+ def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, enable_events=False,
+ relief=RELIEF_SUNKEN, font=None, text_color=None, background_color=None, justification=None, pad=None,
+ key=None, tooltip=None, visible=True, metadata=None):
+ """
+
+ :param text: (str) Text that is to be displayed in the widget
+ :param size: Tuple[(int), (int)] (w,h) w=characters-wide, h=rows-high
+ :param auto_size_text: (bool) True if size should fit the text length
+ :param click_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. StatusBar events occur when the bar is clicked
+ :param relief: (enum) relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param text_color: (str) color of the text
+ :param background_color: (str) color of background
+ :param justification: (str) how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.DisplayText = text
+ self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
+ self.Justification = justification
+ self.Relief = relief
+ self.ClickSubmits = click_submits or enable_events
+ if background_color is None:
+ bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
+ else:
+ bg = background_color
+ self.TKText = self.Widget = None # type: tk.Label
+ super().__init__(ELEM_TYPE_STATUSBAR, size=size, auto_size_text=auto_size_text, background_color=bg,
+ font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip,
+ visible=visible, metadata=metadata)
+ return
+
+
+ def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None):
+ """
+ Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior
+ :param value: (str) new text to show
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param visible: (bool) set visibility state of the element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ self.DisplayText = value
+ stringvar = self.TKStringVar
+ stringvar.set(value)
+ if background_color is not None:
+ self.TKText.configure(background=background_color)
+ if text_color is not None:
+ self.TKText.configure(fg=text_color)
+ if font is not None:
+ self.TKText.configure(font=font)
+ if visible is False:
+ self.TKText.pack_forget()
+ elif visible is True:
+ self.TKText.pack()
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+
+# ---------------------------------------------------------------------- #
+# TKProgressBar #
+# Emulate the TK ProgressBar using canvas and rectangles
+# ---------------------------------------------------------------------- #
+
+class TKProgressBar():
+ """ """
+ def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], style=DEFAULT_PROGRESS_BAR_STYLE,
+ relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH,
+ orientation='horizontal', BarColor=(None, None), key=None):
+ """
+
+ :param root: Union[tk.Tk, tk.TopLevel] The root window bar is to be shown in
+ :param max: (int) Maximum value the bar will be measuring
+ :param length: (int) length in pixels of the bar
+ :param width: (int) width in pixels of the bar
+ :param style: (str) Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'
+ :param relief: (str) relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF)
+ :param border_width: (int) The amount of pixels that go around the outside of the bar
+ :param orientation: (str) 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')
+ :param BarColor: Tuple[str, str] The 2 colors that make up a progress bar. One is the background, the other is the bar
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ """
+
+ self.Length = length
+ self.Width = width
+ self.Max = max
+ self.Orientation = orientation
+ self.Count = None
+ self.PriorCount = 0
+
+ if orientation[0].lower() == 'h':
+ s = ttk.Style()
+ s.theme_use(style)
+ if BarColor != COLOR_SYSTEM_DEFAULT:
+ s.configure(str(key) + "my.Horizontal.TProgressbar", background=BarColor[0], troughcolor=BarColor[1],
+ troughrelief=relief, borderwidth=border_width, thickness=width)
+ else:
+ s.configure(str(key) + "my.Horizontal.TProgressbar", troughrelief=relief, borderwidth=border_width,
+ thickness=width)
+
+ self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max,
+ style=str(key) + 'my.Horizontal.TProgressbar', length=length,
+ orient=tk.HORIZONTAL, mode='determinate')
+ else:
+ s = ttk.Style()
+ s.theme_use(style)
+ if BarColor != COLOR_SYSTEM_DEFAULT:
+ s.configure(str(length) + str(width) + "my.Vertical.TProgressbar", background=BarColor[0],
+ troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width)
+ else:
+ s.configure(str(length) + str(width) + "my.Vertical.TProgressbar", troughrelief=relief,
+ borderwidth=border_width, thickness=width)
+ self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max,
+ style=str(length) + str(width) + 'my.Vertical.TProgressbar',
+ length=length, orient=tk.VERTICAL, mode='determinate')
+
+ def Update(self, count=None, max=None):
+ """
+ Update the current value of the bar and/or update the maximum value the bar can reach
+
+ :param count: (int) current value
+ :param max: (int) the maximum value
+ """
+ if max is not None:
+ self.Max = max
+ try:
+ self.TKProgressBarForReal.config(maximum=max)
+ except:
+ return False
+ if count is not None and count > self.Max: return False
+ if count is not None:
+ try:
+ self.TKProgressBarForReal['value'] = count
+ except:
+ return False
+ return True
+
+
+# ---------------------------------------------------------------------- #
+# TKOutput #
+# New Type of TK Widget that's a Text Widget in disguise #
+# Note that it's inherited from the TKFrame class so that the #
+# Scroll bar will span the length of the frame #
+# ---------------------------------------------------------------------- #
+class TKOutput(tk.Frame):
+ """
+ tkinter style class. Inherits Frame class from tkinter. Adds a tk.Text and a scrollbar together.
+ Note - This is NOT a user controlled class. Users should NOT be directly using it unless making an extention
+ to PySimpleGUI by directly manipulating tkinter.
+ """
+ def __init__(self, parent, width, height, bd, background_color=None, text_color=None, font=None, pad=None):
+ """
+ :param parent: Union[tk.Tk, tk.Toplevel] The "Root" that the Widget will be in
+ :param width: (int) Width in characters
+ :param height: (int) height in rows
+ :param bd: (int) Border Depth. How many pixels of border to show
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ """
+ self.frame = tk.Frame(parent)
+ tk.Frame.__init__(self, self.frame)
+ self.output = tk.Text(self.frame, width=width, height=height, bd=bd, font=font)
+ if background_color and background_color != COLOR_SYSTEM_DEFAULT:
+ self.output.configure(background=background_color)
+ self.frame.configure(background=background_color)
+ if text_color and text_color != COLOR_SYSTEM_DEFAULT:
+ self.output.configure(fg=text_color)
+ self.vsb = tk.Scrollbar(self.frame, orient="vertical", command=self.output.yview)
+ self.output.configure(yscrollcommand=self.vsb.set)
+ self.output.pack(side="left", fill="both", expand=True)
+ self.vsb.pack(side="left", fill="y", expand=False)
+ self.frame.pack(side="left", padx=pad[0], pady=pad[1], expand=True, fill='y')
+ self.previous_stdout = sys.stdout
+ self.previous_stderr = sys.stderr
+
+ sys.stdout = self
+ sys.stderr = self
+ self.pack()
+
+ def write(self, txt):
+ """
+ Called by Python (not tkinter?) when stdout or stderr wants to write
+
+ :param txt: (str) text of output
+ """
+ try:
+ self.output.insert(tk.END, str(txt))
+ self.output.see(tk.END)
+ except:
+ pass
+
+ def Close(self):
+ """
+ Called when wanting to restore the old stdout/stderr
+ """
+ sys.stdout = self.previous_stdout
+ sys.stderr = self.previous_stderr
+
+ def flush(self):
+ """
+ This doesn't look right. This restores stdout and stderr to their old values
+ """
+ sys.stdout = self.previous_stdout
+ sys.stderr = self.previous_stderr
+
+ def __del__(self):
+ """
+ If this Widget is deleted, be sure and restore the old stdout, stderr
+ """
+ sys.stdout = self.previous_stdout
+ sys.stderr = self.previous_stderr
+
+
+# ---------------------------------------------------------------------- #
+# Output #
+# Routes stdout, stderr to a scrolled window #
+# ---------------------------------------------------------------------- #
+class Output(Element):
+ """
+ Output Element - a multi-lined text area where stdout and stderr are re-routed to.
+ """
+ def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None,
+ key=None, right_click_menu=None, visible=True, metadata=None):
+ """
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self._TKOut = self.Widget = None # type: TKOutput
+ bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
+ fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
+ self.RightClickMenu = right_click_menu
+
+ super().__init__(ELEM_TYPE_OUTPUT, size=size, background_color=bg, text_color=fg, pad=pad, font=font,
+ tooltip=tooltip, key=key, visible=visible, metadata=metadata)
+
+ @property
+ def TKOut(self):
+ """ """
+ if self._TKOut is None:
+ print('*** Did you forget to call Finalize()? Your code should look something like: ***')
+ print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
+ return self._TKOut
+
+ def Update(self, value=None, visible=None):
+ """
+ Changes some of the settings for the Output Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (str) string that will replace current contents of the output area
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ self._TKOut.output.delete('1.0', tk.END)
+ self._TKOut.output.insert(tk.END, value)
+ if visible is False:
+ self._TKOut.frame.pack_forget()
+ elif visible is True:
+ self._TKOut.frame.pack()
+
+ def Get(self):
+ """
+ Returns the current contents of the output. Similar to Get method other Elements
+ :return: (str) the current value of the output
+ """
+ return self._TKOut.output.get(1.0, tk.END)
+
+
+ def expand(self, expand_x=False, expand_y=False):
+ """
+ Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions
+
+ :param expand_x: (Bool) If True Element will expand in the Horizontal directions
+ :param expand_y: (Bool) If True Element will expand in the Vertical directions
+ """
+
+ if expand_x and expand_y:
+ fill = tk.BOTH
+ elif expand_x:
+ fill = tk.X
+ elif expand_y:
+ fill = tk.Y
+ else:
+ return
+
+ self._TKOut.output.pack(expand=True, fill=fill)
+ self._TKOut.frame.pack(expand=True, fill=fill)
+ self.ParentRowFrame.pack(expand=True, fill=fill)
+
+
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ tk_out = TKOut
+ update = Update
+
+
+# ---------------------------------------------------------------------- #
+# Button Class #
+# ---------------------------------------------------------------------- #
+class Button(Element):
+ """
+ Button Element - Defines all possible buttons. The shortcuts such as Submit, FileBrowse, ... each create a Button
+ """
+ def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None,
+ file_types=(("ALL Files", "*.*"),), initial_folder=None, disabled=False, change_submits=False,
+ enable_events=False, image_filename=None, image_data=None, image_size=(None, None),
+ image_subsample=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None,
+ font=None, bind_return_key=False, focus=False, pad=None, key=None, visible=True, metadata=None):
+ """
+ :param button_text: (str) Text to be displayed on the button
+ :param button_type: (int) You should NOT be setting this directly. ONLY the shortcut functions set this
+ :param target: Union[str, Tuple[int, int]] key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param file_types: Tuple[Tuple[str, str], ...] the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.*"),). Note - NOT SUPPORTED ON MAC
+ :param initial_folder: (str) starting path for folders and files
+ :param disabled: (bool) If True button will be created disabled
+ :param click_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. If this button is a target, should it generate an event when filled in
+ :param image_filename: (str) image filename if there is a button image. GIFs and PNGs only.
+ :param image_data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data
+ :param image_size: Tuple[int, int] Size of the image in pixels (width, height)
+ :param image_subsample: (int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
+ :param border_width: (int) width of border around button in pixels
+ :param size: Tuple[int, int] (width, height) of the button in characters wide, rows high
+ :param auto_size_button: (bool) if True the button size is sized to fit the text
+ :param button_color: Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green". Note - Does not always work on Macs
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param bind_return_key: (bool) If True the return key will cause this button to be pressed
+ :param focus: (bool) if True, initial focus will be put on this button
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.AutoSizeButton = auto_size_button
+ self.BType = button_type
+ self.FileTypes = file_types
+ self.Widget = self.TKButton = None # type: tk.Button
+ self.Target = target
+ self.ButtonText = str(button_text)
+ if sys.platform == 'darwin' and button_color is not None:
+ print('Button *** WARNING - Button colors are not supported on the Mac ***')
+ self.ButtonColor = DEFAULT_BUTTON_COLOR
+ else:
+ self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR
+ self.ImageFilename = image_filename
+ self.ImageData = image_data
+ self.ImageSize = image_size
+ self.ImageSubsample = image_subsample
+ self.UserData = None
+ self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
+ self.BindReturnKey = bind_return_key
+ self.Focus = focus
+ self.TKCal = None
+ self.CalendarCloseWhenChosen = None
+ self.DefaultDate_M_D_Y = (None, None, None)
+ self.InitialFolder = initial_folder
+ self.Disabled = disabled
+ self.ChangeSubmits = change_submits or enable_events
+ super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ # Realtime button release callback
+ def ButtonReleaseCallBack(self, parm):
+ """
+ Not a user callable function. Called by tkinter when a "realtime" button is released
+
+ :param parm: the event info from tkinter
+
+ """
+ self.LastButtonClickedWasRealtime = False
+ self.ParentForm.LastButtonClicked = None
+
+ # Realtime button callback
+ def ButtonPressCallBack(self, parm):
+ """
+ Not a user callable method. Callback called by tkinter when a "realtime" button is pressed
+
+ :param parm: Event info passed in by tkinter
+
+ """
+ self.ParentForm.LastButtonClickedWasRealtime = True
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = self.ButtonText
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick out of loop if read was called
+
+ # ------- Button Callback ------- #
+ def ButtonCallBack(self):
+ """
+ Not user callable! Called by tkinter when a button is clicked. This is where all the fun begins!
+ """
+ # global _my_windows
+
+ # print('Button callback')
+
+ # print(f'Parent = {self.ParentForm} Position = {self.Position}')
+ # Buttons modify targets or return from the form
+ # If modifying target, get the element object at the target and modify its StrVar
+ target = self.Target
+ target_element = None
+ if target[0] == ThisRow:
+ target = [self.Position[0], target[1]]
+ if target[1] < 0:
+ target[1] = self.Position[1] + target[1]
+ strvar = None
+ should_submit_window = False
+ if target == (None, None):
+ strvar = self.TKStringVar
+ else:
+ if not isinstance(target, str):
+ if target[0] < 0:
+ target = [self.Position[0] + target[0], target[1]]
+ target_element = self.ParentContainer._GetElementAtLocation(target)
+ else:
+ target_element = self.ParentForm.FindElement(target)
+ try:
+ strvar = target_element.TKStringVar
+ except:
+ pass
+ try:
+ if target_element.ChangeSubmits:
+ should_submit_window = True
+ except:
+ pass
+ filetypes = (("ALL Files", "*.*"),) if self.FileTypes is None else self.FileTypes
+ if self.BType == BUTTON_TYPE_BROWSE_FOLDER:
+ folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get folder' dialog box
+ if folder_name != '':
+ try:
+ strvar.set(folder_name)
+ self.TKStringVar.set(folder_name)
+ except:
+ pass
+ elif self.BType == BUTTON_TYPE_BROWSE_FILE:
+ if sys.platform == 'darwin':
+ file_name = tk.filedialog.askopenfilename(
+ initialdir=self.InitialFolder) # show the 'get file' dialog box
+ else:
+ file_name = tk.filedialog.askopenfilename(filetypes=filetypes,
+ initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box
+ if file_name != '':
+ strvar.set(file_name)
+ self.TKStringVar.set(file_name)
+ elif self.BType == BUTTON_TYPE_COLOR_CHOOSER:
+ color = tk.colorchooser.askcolor() # show the 'get file' dialog box
+ color = color[1] # save only the #RRGGBB portion
+ strvar.set(color)
+ self.TKStringVar.set(color)
+ elif self.BType == BUTTON_TYPE_BROWSE_FILES:
+ if sys.platform == 'darwin':
+ file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder)
+ else:
+ file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot)
+ if file_name != '':
+ file_name = ';'.join(file_name)
+ strvar.set(file_name)
+ self.TKStringVar.set(file_name)
+ elif self.BType == BUTTON_TYPE_SAVEAS_FILE:
+ if sys.platform == 'darwin':
+ file_name = tk.filedialog.asksaveasfilename(
+ initialdir=self.InitialFolder) # show the 'get file' dialog box
+ else:
+ file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes,
+ initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box
+ if file_name != '':
+ strvar.set(file_name)
+ self.TKStringVar.set(file_name)
+ elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window
+ # first, get the results table built
+ # modify the Results table in the parent FlexForm object
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = self.ButtonText
+ self.ParentForm.FormRemainedOpen = False
+ self.ParentForm._Close()
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+ if self.ParentForm.NonBlocking:
+ self.ParentForm.TKroot.destroy()
+ Window.DecrementOpenCount()
+ elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE
+ # first, get the results table built
+ # modify the Results table in the parent FlexForm object
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = self.ButtonText
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+ elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop
+ self.ParentForm._Close()
+ if self.ParentForm.NonBlocking:
+ self.ParentForm.TKroot.destroy()
+ Window.DecrementOpenCount()
+ elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window
+ should_submit_window = False
+ root = tk.Toplevel()
+ root.title('Calendar Chooser')
+ root.wm_attributes("-topmost", 1)
+ self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element,
+ close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y,
+ locale=self.CalendarLocale, format=self.CalendarFormat)
+ self.TKCal.pack(expand=1, fill='both')
+ root.update()
+
+ if type(Window.user_defined_icon) is bytes:
+ calendar_icon = tkinter.PhotoImage(data=Window.user_defined_icon)
+ else:
+ calendar_icon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
+ try:
+ root.tk.call('wm', 'iconphoto', root._w, calendar_icon)
+ except:
+ pass
+ elif self.BType == BUTTON_TYPE_SHOW_DEBUGGER:
+ if self.ParentForm.DebuggerEnabled:
+ _Debugger.debugger._build_floating_window()
+ # show_debugger_window()
+
+ if should_submit_window:
+ self.ParentForm.LastButtonClicked = target_element.Key
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ return
+
+ def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None,
+ visible=None, image_subsample=None, image_size=None):
+ """
+ Changes some of the settings for the Button Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param text: (str) sets button text
+ :param button_color: Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green"
+ :param disabled: (bool) disable or enable state of the element
+ :param image_data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data
+ :param image_filename: (str) image filename if there is a button image. GIFs and PNGs only.
+ :param visible: (bool) control visibility of element
+ :param image_subsample: (int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
+ :param image_size: Tuple[int, int] Size of the image in pixels (width, height)
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ try:
+ if text is not None:
+ self.TKButton.configure(text=text)
+ self.ButtonText = text
+ if sys.platform == 'darwin' and button_color != (None, None):
+ print('Button.Update *** WARNING - Button colors are not supported on the Mac***')
+ if button_color != (None, None):
+ self.TKButton.config(foreground=button_color[0], background=button_color[1], activebackground=button_color[1])
+ self.ButtonColor = button_color
+ except:
+ return
+ if disabled == True:
+ self.TKButton['state'] = 'disabled'
+ elif disabled == False:
+ self.TKButton['state'] = 'normal'
+ if image_data is not None:
+ image = tk.PhotoImage(data=image_data)
+ if image_size is not None:
+ width, height = image_size
+ else:
+ width, height = image.width(), image.height()
+ if image_subsample:
+ image = image.subsample(image_subsample)
+ self.TKButton.config(image=image, width=width, height=height)
+ self.TKButton.image = image
+ if image_filename is not None:
+ self.TKButton.config(highlightthickness=0)
+ image = tk.PhotoImage(file=image_filename)
+ if image_size is not None:
+ width, height = image_size
+ else:
+ width, height = image.width(), image.height()
+ if image_subsample:
+ image = image.subsample(image_subsample)
+ self.TKButton.config(image=image, width=width, height=height)
+ self.TKButton.image = image
+ if visible is False:
+ self.TKButton.pack_forget()
+ elif visible is True:
+ self.TKButton.pack()
+
+ def GetText(self):
+ """
+ Returns the current text shown on a button
+
+ :return: (str) The text currently displayed on the button
+ """
+ return self.ButtonText
+
+
+ def Click(self):
+ """
+ Generates a click of the button as if the user clicked the button
+ Calls the tkinter invoke method for the button
+ """
+ try:
+ self.TKButton.invoke()
+ except:
+ print('Exception clicking button')
+
+
+ click = Click
+ get_text = GetText
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ------------------------- Button lazy functions ------------------------- #
+B = Button
+Btn = Button
+
+
+# ---------------------------------------------------------------------- #
+# ButtonMenu Class #
+# ---------------------------------------------------------------------- #
+class ButtonMenu(Element):
+ """
+ The Button Menu Element. Creates a button that when clicked will show a menu similar to right click menu
+ """
+
+ def __init__(self, button_text, menu_def, tooltip=None, disabled=False,
+ image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None,
+ size=(None, None), auto_size_button=None, button_color=None, font=None, pad=None, key=None,
+ tearoff=False, visible=True, metadata=None):
+ """
+ :param button_text: (str) Text to be displayed on the button
+ :param menu_def: List[List[str]] A list of lists of Menu items to show when this element is clicked. See docs for format as they are the same for all menu types
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param disabled: (bool) If True button will be created disabled
+ :param image_filename: (str) image filename if there is a button image. GIFs and PNGs only.
+ :param image_data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data
+ :param image_size: Tuple[int, int] Size of the image in pixels (width, height)
+ :param image_subsample: (int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
+ :param border_width: (int) width of border around button in pixels
+ :param size: Tuple[int, int] (width, height) of the button in characters wide, rows high
+ :param auto_size_button: (bool) if True the button size is sized to fit the text
+ :param button_color: Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green"
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param tearoff: (bool) Determines if menus should allow them to be torn off
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.MenuDefinition = menu_def
+ self.AutoSizeButton = auto_size_button
+ self.ButtonText = button_text
+ self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR
+ self.TextColor = self.ButtonColor[0]
+ self.BackgroundColor = self.ButtonColor[1]
+ self.BorderWidth = border_width
+ self.ImageFilename = image_filename
+ self.ImageData = image_data
+ self.ImageSize = image_size
+ self.ImageSubsample = image_subsample
+ self.Disabled = disabled
+ self.IsButtonMenu = True
+ self.MenuItemChosen = None
+ self.Tearoff = tearoff
+ self.TKButtonMenu = None # type: tk.Menubutton
+ self.TKMenu = None # type: tk.Menu
+ # self.temp_size = size if size != (NONE, NONE) else
+
+ super().__init__(ELEM_TYPE_BUTTONMENU, size=size, font=font, pad=pad, key=key, tooltip=tooltip,
+ text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, metadata=metadata)
+ return
+
+ def _MenuItemChosenCallback(self, item_chosen): # ButtonMenu Menu Item Chosen Callback
+ """
+ Not a user callable function. Called by tkinter when an item is chosen from the menu.
+
+ :param item_chosen: (str) The menu item chosen.
+ """
+ # print('IN MENU ITEM CALLBACK', item_chosen)
+ self.MenuItemChosen = item_chosen.replace('&', '')
+ self.ParentForm.LastButtonClicked = self.Key
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+
+ def Update(self, menu_definition, visible=None):
+ """
+ Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param menu_definition: (List[List]) New menu definition (in menu definition format)
+ :param visible: (bool) control visibility of element
+ """
+
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ self.MenuDefinition = menu_definition
+ if menu_definition is not None:
+ self.TKMenu = tk.Menu(self.TKButtonMenu, tearoff=self.Tearoff) # create the menubar
+ AddMenuItem(self.TKMenu, menu_definition[1], self)
+ self.TKButtonMenu.configure(menu=self.TKMenu)
+ if visible is False:
+ self.TKButtonMenu.pack_forget()
+ elif visible is True:
+ self.TKButtonMenu.pack()
+
+ def Click(self):
+ """
+ Generates a click of the button as if the user clicked the button
+ Calls the tkinter invoke method for the button
+ """
+ try:
+ self.TKMenu.invoke(1)
+ except:
+ print('Exception clicking button')
+
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+BMenu = ButtonMenu
+
+
+# ---------------------------------------------------------------------- #
+# ProgreessBar #
+# ---------------------------------------------------------------------- #
+class ProgressBar(Element):
+ """
+ Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made
+ """
+ def __init__(self, max_value, orientation=None, size=(None, None), auto_size_text=None, bar_color=(None, None),
+ style=None, border_width=None, relief=None, key=None, pad=None, visible=True, metadata=None):
+ """
+ :param max_value: (int) max value of progressbar
+ :param orientation: (str) 'horizontal' or 'vertical'
+ :param size: Tuple[int, int] Size of the bar. If horizontal (chars wide, pixels high), vert (pixels wide, rows high)
+ :param auto_size_text: (bool) Not sure why this is here
+ :param bar_color: Tuple[str, str] The 2 colors that make up a progress bar. One is the background, the other is the bar
+ :param style: (str) Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'
+ :param border_width: (int) The amount of pixels that go around the outside of the bar
+ :param relief: (str) relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF)
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.MaxValue = max_value
+ self.TKProgressBar = None
+ self.Cancelled = False
+ self.NotRunning = True
+ self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION
+ self.BarColor = bar_color
+ self.BarStyle = style if style else DEFAULT_PROGRESS_BAR_STYLE
+ self.BorderWidth = border_width if border_width else DEFAULT_PROGRESS_BAR_BORDER_WIDTH
+ self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF
+ self.BarExpired = False
+ super().__init__(ELEM_TYPE_PROGRESS_BAR, size=size, auto_size_text=auto_size_text, key=key, pad=pad,
+ visible=visible, metadata=metadata)
+
+ # returns False if update failed
+ def UpdateBar(self, current_count, max=None):
+ """
+ Change what the bar shows by changing the current count and optionally the max count
+
+ :param current_count: (int) sets the current value
+ :param max: (int) changes the max value
+ """
+
+ if self.ParentForm.TKrootDestroyed:
+ return False
+ self.TKProgressBar.Update(current_count, max=max)
+ try:
+ self.ParentForm.TKroot.update()
+ except:
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ return False
+ return True
+
+
+ def Update(self, visible=None):
+ """
+ Changes some of the settings for the ProgressBar Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if visible is False:
+ self.TKProgressBar.TKProgressBarForReal.pack_forget()
+ elif visible is True:
+ self.TKProgressBar.TKProgressBarForReal.pack()
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+ update_bar = UpdateBar
+
+PBar = ProgressBar
+Prog = ProgressBar
+
+
+
+# ---------------------------------------------------------------------- #
+# Image #
+# ---------------------------------------------------------------------- #
+class Image(Element):
+ """
+ Image Element - show an image in the window. Should be a GIF or a PNG only
+ """
+
+ def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None,
+ tooltip=None, right_click_menu=None, visible=True, enable_events=False, metadata=None):
+ """
+ :param filename: (str) image filename if there is a button image. GIFs and PNGs only.
+ :param data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data
+ :param background_color: color of background
+ :param size: Tuple[int, int] (width, height) size of image in pixels
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param enable_events: (bool) Turns on the element specific events. For an Image element, the event is "image clicked"
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.Filename = filename
+ self.Data = data
+ self.tktext_label = None
+ self.BackgroundColor = background_color
+ if data is None and filename is None:
+ print('* Warning... no image specified in Image Element! *')
+ self.EnableEvents = enable_events
+ self.RightClickMenu = right_click_menu
+ self.AnimatedFrames = None
+ self.CurrentFrameNumber = 0
+ self.TotalAnimatedFrames = 0
+ self.LastFrameTime = 0
+ self.Source = filename if filename is not None else data
+
+ super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key,
+ tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, filename=None, data=None, size=(None, None), visible=None):
+ """
+ Changes some of the settings for the Image Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param filename: (str) filename to the new image to display.
+ :param data: Union[str, tkPhotoImage] Base64 encoded string OR a tk.PhotoImage object
+ :param size: Tuple[int,int] size of a image (w,h) w=characters-wide, h=rows-high
+ :param visible: (bool) control visibility of element
+ """
+
+ image = None
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if filename is not None:
+ image = tk.PhotoImage(file=filename)
+ elif data is not None:
+ # if type(data) is bytes:
+ try:
+ image = tk.PhotoImage(data=data)
+ except Exception as e:
+ image = data
+ # return # an error likely means the window has closed so exit
+ else:
+ return
+ if image is not None:
+ width, height = size[0] or image.width(), size[1] or image.height()
+ try: # sometimes crashes if user closed with X
+ self.tktext_label.configure(image=image, width=width, height=height)
+ except:
+ pass
+ self.tktext_label.image = image
+ if visible is False:
+ self.tktext_label.pack_forget()
+ elif visible is True:
+ self.tktext_label.pack()
+
+ def UpdateAnimation(self, source, time_between_frames=0):
+ """
+ Show an Animated GIF. Call the function as often as you like. The function will determine when to show the next frame and will automatically advance to the next frame at the right time.
+ NOTE - does NOT perform a sleep call to delay
+
+ :param source: Union[str,bytes] Filename or Base64 encoded string containing Animated GIF
+ :param time_between_frames: (int) Number of milliseconds to wait between showing frames
+ """
+
+ if self.Source != source:
+ self.AnimatedFrames = None
+ self.Source = source
+
+ if self.AnimatedFrames is None:
+ self.TotalAnimatedFrames = 0
+ self.AnimatedFrames = []
+ for i in range(1000):
+ if type(source) is not bytes:
+ try:
+ self.AnimatedFrames.append(tk.PhotoImage(file=source, format='gif -index %i' % (i)))
+ except:
+ break
+ else:
+ try:
+ self.AnimatedFrames.append(tk.PhotoImage(data=source, format='gif -index %i' % (i)))
+ except:
+ break
+ self.TotalAnimatedFrames += 1
+ self.LastFrameTime = time.time()
+ self.CurrentFrameNumber = 0
+ # show the frame
+
+ now = time.time()
+
+ if time_between_frames:
+ if (now - self.LastFrameTime) * 1000 > time_between_frames:
+ self.LastFrameTime = now
+ self.CurrentFrameNumber = self.CurrentFrameNumber + 1 if self.CurrentFrameNumber + 1 < self.TotalAnimatedFrames else 0
+ else: # don't reshow the frame again if not time for new frame
+ return
+ else:
+ self.CurrentFrameNumber = self.CurrentFrameNumber + 1 if self.CurrentFrameNumber + 1 < self.TotalAnimatedFrames else 0
+ image = self.AnimatedFrames[self.CurrentFrameNumber]
+ try: # needed in case the window was closed with an "X"
+ self.tktext_label.configure(image=image, width=image.width(), heigh=image.height())
+ except:
+ pass
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+ update_animation = UpdateAnimation
+
+
+# ---------------------------------------------------------------------- #
+# Canvas #
+# ---------------------------------------------------------------------- #
+class Canvas(Element):
+ """ """
+
+ def __init__(self, canvas=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None,
+ right_click_menu=None, visible=True, metadata=None):
+ """
+
+ :param canvas: (tk.Canvas) Your own tk.Canvas if you already created it. Leave blank to create a Canvas
+ :param background_color: (str) color of background
+ :param size: Tuple[int,int] (width in char, height in rows) size in pixels to make canvas
+ :param pad: Amount of padding to put around element
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self._TKCanvas = canvas
+ self.RightClickMenu = right_click_menu
+
+ super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=size, pad=pad, key=key,
+ tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ @property
+ def TKCanvas(self):
+ """ """
+ if self._TKCanvas is None:
+ print('*** Did you forget to call Finalize()? Your code should look something like: ***')
+ print('*** window = sg.Window("My Form", layout, finalize=True) ***')
+ return self._TKCanvas
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ tk_canvas = TKCanvas
+
+
+# ---------------------------------------------------------------------- #
+# Graph #
+# ---------------------------------------------------------------------- #
+class Graph(Element):
+ """
+ Creates an area for you to draw on. The MAGICAL property this Element has is that you interact
+ with the element using your own coordinate system. This is an important point!! YOU define where the location
+ is for (0,0). Want (0,0) to be in the middle of the graph like a math 4-quadrant graph? No problem! Set your
+ lower left corner to be (-100,-100) and your upper right to be (100,100) and you've got yourself a graph with
+ (0,0) at the center.
+ One of THE coolest of the Elements.
+ You can also use float values. To do so, be sure and set the float_values parameter.
+ Mouse click and drag events are possible and return the (x,y) coordinates of the mouse
+ Drawing primitives return an "id" that is referenced when you want to operation on that item (e.g. to erase it)
+ """
+
+ def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None,
+ change_submits=False, drag_submits=False, enable_events=False, key=None, tooltip=None,
+ right_click_menu=None, visible=True, float_values=False, metadata=None):
+ """
+ :param canvas_size: Tuple[int, int] (width, height) size of the canvas area in pixels
+ :param graph_bottom_left: Tuple[int, int] (x,y) The bottoms left corner of your coordinate system
+ :param graph_top_right: Tuple[int, int] (x,y) The top right corner of your coordinate system
+ :param background_color: (str) background color of the drawing area
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param change_submits: (bool) * DEPRICATED DO NOT USE! Same as enable_events
+ :param drag_submits: (bool) if True and Events are enabled for the Graph, will report Events any time the mouse moves while button down
+ :param enable_events: (bool) If True then clicks on the Graph are immediately reported as an event. Use this instead of change_submits
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element (Default = True)
+ :param float_values: (bool) If True x,y coordinates are returned as floats, not ints
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.CanvasSize = canvas_size
+ self.BottomLeft = graph_bottom_left
+ self.TopRight = graph_top_right
+ # self._TKCanvas = None # type: tk.Canvas
+ self._TKCanvas2 = self.Widget = None # type: tk.Canvas
+ self.ChangeSubmits = change_submits or enable_events
+ self.DragSubmits = drag_submits
+ self.ClickPosition = (None, None)
+ self.MouseButtonDown = False
+ self.Images = {}
+ self.RightClickMenu = right_click_menu
+ self.FloatValues = float_values
+
+ super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key,
+ tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def _convert_xy_to_canvas_xy(self, x_in, y_in):
+ """
+ Not user callable. Used to convert user's coordinates into the ones used by tkinter
+
+ :param x_in: Union[int, float] The x coordinate to convert
+ :param y_in: Union[int, float] The y coordinate to convert
+ :return: Tuple[int, int] The converted canvas coordinates
+ """
+ if None in (x_in, y_in):
+ return None, None
+ scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
+ scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
+ new_x = 0 + scale_x * (x_in - self.BottomLeft[0])
+ new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1])
+ return new_x, new_y
+
+ def _convert_canvas_xy_to_xy(self, x_in, y_in):
+ """
+ Not user callable. Used to convert tkinter Canvas coords into user's coordinates
+
+ :param x_in: (int) The x coordinate in canvas coordinates
+ :param y_in: (int) The y coordinate in canvas coordinates
+ :return: Union[Tuple[int, int], Tuple[float, float]] The converted USER coordinates
+ """
+ if None in (x_in, y_in):
+ return None, None
+ scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
+ scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
+
+ new_x = x_in / scale_x + self.BottomLeft[0]
+ new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1]
+ if self.FloatValues:
+ return new_x, new_y
+ else:
+ return int(new_x), int(new_y)
+
+ def DrawLine(self, point_from, point_to, color='black', width=1):
+ """
+ Draws a line from one point to another point using USER'S coordinates. Can set the color and width of line
+
+ :param point_from: Union[Tuple[int, int], Tuple[float, float]] Starting point for line
+ :param point_to: Union[Tuple[int, int], Tuple[float, float]] Ending point for line
+ :param color: (str) Color of the line
+ :param width: (int) width of line in pixels
+ :return: Union[int, None] id returned from tktiner or None if user closed the window. id is used when you
+ want to manipulate the line
+ """
+ if point_from == (None, None):
+ return
+ converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1])
+ converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # in case window was closed with an X
+ id = self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
+ except:
+ id = None
+ return id
+
+ def DrawPoint(self, point, size=2, color='black'):
+ """
+ Draws a "dot" at the point you specify using the USER'S coordinate system
+
+ :param point: Union [Tuple[int, int], Tuple[float, float]] Center location using USER'S coordinate system
+ :param size: Union[int, float] Radius? (Or is it the diameter?) in user's coordinate values.
+ :param color: (str) color of the point to draw
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the point
+ """
+ if point == (None, None):
+ return
+ converted_point = self._convert_xy_to_canvas_xy(point[0], point[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # needed in case window was closed with an X
+ id = self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size,
+ converted_point[0] + size, converted_point[1] + size, fill=color,
+ outline=color)
+ except:
+ id = None
+ return id
+
+ def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'):
+ """
+ Draws a circle, cenetered at the location provided. Can set the fill and outline colors
+
+ :param center_location: Union [Tuple[int, int], Tuple[float, float]] Center location using USER'S coordinate system
+ :param radius: Union[int, float] Radius in user's coordinate values.
+ :param fill_color: (str) color of the point to draw
+ :param line_color: (str) color of the outer line that goes around the circle (sorry, can't set thickness)
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the circle
+ """
+ if center_location == (None, None):
+ return
+ converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # needed in case the window was closed with an X
+ id = self._TKCanvas2.create_oval(converted_point[0] - radius, converted_point[1] - radius,
+ converted_point[0] + radius, converted_point[1] + radius, fill=fill_color,
+ outline=line_color)
+ except:
+ id = None
+ return id
+
+ def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None):
+ """
+ Draws an oval based on coordinates in user coordinate system. Provide the location of a "bounding rectangle"
+
+ :param top_left: Union[Tuple[int, int], Tuple[float, float]] the top left point of bounding rectangle
+ :param bottom_right: Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle
+ :param fill_color: (str) color of the interrior
+ :param line_color: (str) color of outline of oval
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the oval
+ """
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # in case windows close with X
+ id = self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
+ converted_bottom_right[1], fill=fill_color, outline=line_color)
+ except:
+ id = None
+
+ return id
+
+ def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'):
+ """
+ Draws different types of arcs. Uses a "bounding box" to define location
+
+ :param top_left: Union[Tuple[int, int], Tuple[float, float]] the top left point of bounding rectangle
+ :param bottom_right: Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle
+ :param extent: (float) Andle to end drawing. Used in conjunction with start_angle
+ :param start_angle: (float) Angle to begin drawing. Used in conjunction with extent
+ :param style: (str) Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last',
+ 'butt', 'projecting', 'round', 'bevel', 'miter'
+ :param arc_color: (str) color to draw arc with
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the arc
+ """
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
+ tkstyle = tk.PIESLICE if style is None else style
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # in case closed with X
+ id = self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
+ converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle,
+ outline=arc_color)
+ except:
+ id = None
+ return id
+
+ def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=None):
+ """
+ Draw a rectangle given 2 points. Can control the line and fill colors
+
+ :param top_left: Union[Tuple[int, int], Tuple[float, float]] the top left point of rectangle
+ :param bottom_right: Union[Tuple[int, int], Tuple[float, float]] the bottom right point of rectangle
+ :param fill_color: (str) color of the interior
+ :param line_color: (str) color of outline
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the rectangle
+ """
+
+ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
+ converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ if line_width is None:
+ line_width = 1
+ try: # in case closed with X
+ id = self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1],
+ converted_bottom_right[0],
+ converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width)
+ except:
+ id = None
+ return id
+
+ def DrawText(self, text, location, color='black', font=None, angle=0, text_location=TEXT_LOCATION_CENTER):
+ """
+ Draw some text on your graph. This is how you label graph number lines for example
+
+ :param text: (str) text to display
+ :param location: Union[Tuple[int, int], Tuple[float, float]] location to place first letter
+ :param color: (str) text color
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param angle: (float) Angle 0 to 360 to draw the text. Zero represents horizontal text
+ :param text_location: (enum) "anchor" location for the text. Values start with TEXT_LOCATION_
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the text
+ """
+ if location == (None, None):
+ return
+ converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # in case closed with X
+ id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color, angle=angle, anchor=text_location)
+ except:
+ id = None
+ return id
+
+ def DrawImage(self, filename=None, data=None, location=(None, None), color='black', font=None, angle=0):
+ """
+ Places an image onto your canvas. It's a really important method for this element as it enables so much
+
+ :param filename: (str) if image is in a file, path and filename for the image. (GIF and PNG only!)
+ :param data: Union[str, bytes] if image is in Base64 format or raw? format then use instead of filename
+ :param location: Union[Tuple[int, int], Tuple[float, float]] the (x,y) location to place image's top left corner
+ :param color: (str) text color
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param angle: (float) Angle 0 to 360 to draw the text. Zero represents horizontal text
+ :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the image
+ """
+ if location == (None, None):
+ return
+ if filename is not None:
+ image = tk.PhotoImage(file=filename)
+ elif data is not None:
+ # if type(data) is bytes:
+ try:
+ image = tk.PhotoImage(data=data)
+ except:
+ return None # an error likely means the window has closed so exit
+ converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ try: # in case closed with X
+ id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW)
+ self.Images[id] = image
+ except:
+ id = None
+ return id
+
+
+ def Erase(self):
+ """
+ Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText)
+ """
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ self.Images = {}
+ try: # in case window was closed with X
+ self._TKCanvas2.delete('all')
+ except:
+ pass
+
+
+ def DeleteFigure(self, id):
+ """
+ Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive
+
+ :param id: (int) the id returned to you when calling one of the drawing methods
+ """
+ try:
+ self._TKCanvas2.delete(id)
+ except:
+ print('DeleteFigure - bad ID {}'.format(id))
+ try:
+ del self.Images[id] # in case was an image. If wasn't an image, then will get exception
+ except: pass
+
+
+ def Update(self, background_color=None, visible=None):
+ """
+ Changes some of the settings for the Graph Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param background_color: color of background
+ :param visible: (bool) control visibility of element
+ """
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return
+ if background_color is not None and background_color != COLOR_SYSTEM_DEFAULT:
+ self._TKCanvas2.configure(background=background_color)
+ if visible is False:
+ self._TKCanvas2.pack_forget()
+ elif visible is True:
+ self._TKCanvas2.pack()
+
+
+ def Move(self, x_direction, y_direction):
+ """
+ Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system
+
+ :param x_direction: Union[int, float] how far to move in the "X" direction in your coordinates
+ :param y_direction: Union[int, float] how far to move in the "Y" direction in your coordinates
+ """
+ zero_converted = self._convert_xy_to_canvas_xy(0, 0)
+ shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
+ shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
+ if self._TKCanvas2 is None:
+ print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
+ print('Call Window.Finalize() prior to this operation')
+ return None
+ self._TKCanvas2.move('all', shift_amount[0], shift_amount[1])
+
+
+ def MoveFigure(self, figure, x_direction, y_direction):
+ """
+ Moves a previously drawn figure using a "delta" from current position
+
+ :param figure: (id) Previously obtained figure-id. These are returned from all Draw methods
+ :param x_direction: Union[int, float] delta to apply to position in the X direction
+ :param y_direction: Union[int, float] delta to apply to position in the Y direction
+ """
+ zero_converted = self._convert_xy_to_canvas_xy(0, 0)
+ shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
+ shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
+ if figure is None:
+ print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***')
+ print('Call Window.Finalize() prior to all graph operations')
+ return None
+ self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1])
+
+ def RelocateFigure(self, figure, x, y):
+ """
+ Move a previously made figure to an arbitrary (x,y) location. This differs from the Move methods because it
+ uses absolute coordinates versus relative for Move
+
+ :param figure: (id) Previously obtained figure-id. These are returned from all Draw methods
+ :param x: Union[int, float] location on X axis (in user coords) to move the upper left corner of the figure
+ :param y: Union[int, float] location on Y axis (in user coords) to move the upper left corner of the figure
+ """
+
+ zero_converted = self._convert_xy_to_canvas_xy(0, 0)
+ shift_converted = self._convert_xy_to_canvas_xy(x, y)
+ shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
+ if figure is None:
+ print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***')
+ print('Call Window.Finalize() prior to all graph operations')
+ return None
+ xy = self._TKCanvas2.coords(figure)
+ self._TKCanvas2.move(figure, shift_converted[0] - xy[0], shift_converted[1] - xy[1])
+
+
+ def SendFigureToBack(self, figure):
+ """
+ Changes Z-order of figures on the Graph. Sends the indicated figure to the back of all other drawn figures
+
+ :param figure: (int) value returned by tkinter when creating the figure / drawing
+ """
+ self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure
+
+
+ def BringFigureToFront(self, figure):
+ """
+ Changes Z-order of figures on the Graph. Brings the indicated figure to the front of all other drawn figures
+
+ :param figure: (int) value returned by tkinter when creating the figure / drawing
+ """
+ self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures
+
+
+
+ @property
+ def TKCanvas(self):
+ """ """
+ if self._TKCanvas2 is None:
+ print('*** Did you forget to call Finalize()? Your code should look something like: ***')
+ print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
+ return self._TKCanvas2
+
+ # button release callback
+ def ButtonReleaseCallBack(self, event):
+ """
+ Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
+
+ :param event: (event) event info from tkinter. Note not used in this method
+ """
+ if not self.DragSubmits: # only report mouse up for drag operations
+ return
+ self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
+ self.LastButtonClickedWasRealtime = not self.DragSubmits
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+ if self.DragSubmits:
+ self.ParentForm.LastButtonClicked += '+UP'
+ self.MouseButtonDown = False
+
+ # button callback
+ def ButtonPressCallBack(self, event):
+ """
+ Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
+
+ :param event: (event) event info from tkinter. Contains the x and y coordinates of a click
+ """
+
+ self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
+ self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick out of loop if read was called
+ self.MouseButtonDown = True
+
+ # button callback
+ def MotionCallBack(self, event):
+ """
+ Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved
+
+ :param event: (event) event info from tkinter. Contains the x and y coordinates of a mouse
+ """
+
+ if not self.MouseButtonDown:
+ return
+ self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
+ self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick out of loop if read was called
+
+ bring_figure_to_front = BringFigureToFront
+ button_press_call_back = ButtonPressCallBack
+ button_release_call_back = ButtonReleaseCallBack
+ delete_figure = DeleteFigure
+ draw_arc = DrawArc
+ draw_circle = DrawCircle
+ draw_image = DrawImage
+ draw_line = DrawLine
+ draw_oval = DrawOval
+ draw_point = DrawPoint
+ draw_rectangle = DrawRectangle
+ draw_text = DrawText
+ erase = Erase
+ motion_call_back = MotionCallBack
+ move = Move
+ move_figure = MoveFigure
+ relocate_figure = RelocateFigure
+ send_figure_to_back = SendFigureToBack
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ tk_canvas = TKCanvas
+ update = Update
+
+
+
+# ---------------------------------------------------------------------- #
+# Frame #
+# ---------------------------------------------------------------------- #
+class Frame(Element):
+ """
+ A Frame Element that contains other Elements. Encloses with a line around elements and a text label.
+ """
+
+ def __init__(self, title, layout, title_color=None, background_color=None, title_location=None,
+ relief=DEFAULT_FRAME_RELIEF, size=(None, None), font=None, pad=None, border_width=None, key=None,
+ tooltip=None, right_click_menu=None, visible=True, element_justification='left', metadata=None):
+ """
+ :param title: (str) text that is displayed as the Frame's "label" or title
+ :param layout: List[List[Elements]] The layout to put inside the Frame
+ :param title_color: (str) color of the title text
+ :param background_color: (str) background color of the Frame
+ :param title_location: (enum) location to place the text title. Choices include: TITLE_LOCATION_TOP TITLE_LOCATION_BOTTOM TITLE_LOCATION_LEFT TITLE_LOCATION_RIGHT TITLE_LOCATION_TOP_LEFT TITLE_LOCATION_TOP_RIGHT TITLE_LOCATION_BOTTOM_LEFT TITLE_LOCATION_BOTTOM_RIGHT
+ :param relief: (enum) relief style. Values are same as other elements with reliefs.
+ Choices include RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
+ :param size: Tuple[int, int] (width in characters, height in rows) (note this parameter may not always work)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param border_width: (int) width of border around element in pixels
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param element_justification: (str) All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.UseDictionary = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.ParentWindow = None
+ self.Rows = []
+ # self.ParentForm = None
+ self.TKFrame = None
+ self.Title = title
+ self.Relief = relief
+ self.TitleLocation = title_location
+ self.BorderWidth = border_width
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.RightClickMenu = right_click_menu
+ self.ContainerElemementNumber = Window.GetAContainerNumber()
+ self.ElementJustification = element_justification
+ self.Layout(layout)
+
+ super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=size,
+ font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def AddRow(self, *args):
+ """
+ Not recommended user call. Used to add rows of Elements to the Frame Element.
+
+ :param *args: List[Element] The list of elements for this row
+ """
+ NumRows = len(self.Rows) # number of existing rows is our row number
+ CurrentRowNumber = NumRows # this row's number
+ CurrentRow = [] # start with a blank row and build up
+ # ------------------------- Add the elements to a row ------------------------- #
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
+ element.Position = (CurrentRowNumber, i)
+ element.ParentContainer = self
+ CurrentRow.append(element)
+ if element.Key is not None:
+ self.UseDictionary = True
+ # ------------------------- Append the row to list of Rows ------------------------- #
+ self.Rows.append(CurrentRow)
+
+ def Layout(self, rows):
+ """
+ Can use like the Window.Layout method, but it's better to use the layout parameter when creating
+
+ :param rows: List[List[Element]] The rows of Elements
+ :return: (Frame) Used for chaining
+ """
+
+ for row in rows:
+ self.AddRow(*row)
+ return self
+
+ def _GetElementAtLocation(self, location):
+ """
+ Not user callable. Used to find the Element at a row, col position within the layout
+
+ :param location: Tuple[int, int] (row, column) position of the element to find in layout
+ :return: (Element) The element found at the location
+ """
+
+ (row_num, col_num) = location
+ row = self.Rows[row_num]
+ element = row[col_num]
+ return element
+
+ def Update(self, value=None, visible=None):
+ """
+ Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: (Any) New text value to show on frame
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if visible is False:
+ self.TKFrame.pack_forget()
+ elif visible is True:
+ self.TKFrame.pack()
+ if value is not None:
+ self.TKFrame.config(text=str(value))
+
+
+ add_row = AddRow
+ layout = Layout
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ---------------------------------------------------------------------- #
+# Vertical Separator #
+# ---------------------------------------------------------------------- #
+class VerticalSeparator(Element):
+ """
+ Vertical Separator Element draws a vertical line at the given location. It will span 1 "row". Usually paired with
+ Column Element if extra height is needed
+ """
+
+ def __init__(self, pad=None):
+ """
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ """
+
+ self.Orientation = 'vertical' # for now only vertical works
+
+ super().__init__(ELEM_TYPE_SEPARATOR, pad=pad)
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+
+VSeperator = VerticalSeparator
+VSep = VerticalSeparator
+
+# ---------------------------------------------------------------------- #
+# Tab #
+# ---------------------------------------------------------------------- #
+class Tab(Element):
+ """
+ Tab Element is another "Container" element that holds a layout and displays a tab with text. Used with TabGroup only
+ Tabs are never placed directly into a layout. They are always "Contained" in a TabGroup layout
+ """
+
+ def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, disabled=False,
+ border_width=None, key=None, tooltip=None, right_click_menu=None, visible=True, element_justification='left', metadata=None):
+ """
+ :param title: (str) text to show on the tab
+ :param layout: List[List[Element]] The element layout that will be shown in the tab
+ :param title_color: (str) color of the tab text (note not currently working on tkinter)
+ :param background_color: (str) color of background of the entire layout
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param disabled: (bool) If True button will be created disabled
+ :param border_width: (int) width of border around element in pixels
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param element_justification: (str) All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.UseDictionary = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.ParentWindow = None
+ self.Rows = []
+ self.TKFrame = None
+ self.Title = title
+ self.BorderWidth = border_width
+ self.Disabled = disabled
+ self.ParentNotebook = None
+ self.TabID = None
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.RightClickMenu = right_click_menu
+ self.ContainerElemementNumber = Window.GetAContainerNumber()
+ self.ElementJustification = element_justification
+
+ self.Layout(layout)
+
+ super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad,
+ key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def AddRow(self, *args):
+ """
+ Not recommended use call. Used to add rows of Elements to the Frame Element.
+
+ :param *args: List[Element] The list of elements for this row
+ """
+ NumRows = len(self.Rows) # number of existing rows is our row number
+ CurrentRowNumber = NumRows # this row's number
+ CurrentRow = [] # start with a blank row and build up
+ # ------------------------- Add the elements to a row ------------------------- #
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
+ element.Position = (CurrentRowNumber, i)
+ element.ParentContainer = self
+ CurrentRow.append(element)
+ if element.Key is not None:
+ self.UseDictionary = True
+ # ------------------------- Append the row to list of Rows ------------------------- #
+ self.Rows.append(CurrentRow)
+
+ def Layout(self, rows):
+ """
+ Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements
+
+ :param rows: List[List[Element]] The list of rows
+ :return: (Tab) used for chaining
+ """
+
+ for row in rows:
+ self.AddRow(*row)
+ return self
+
+ def Update(self, disabled=None, visible=None): # TODO Disable / enable of tabs is not complete
+ """
+ Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param disabled: (bool) disable or enable state of the element
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if disabled is None:
+ return
+ self.Disabled = disabled
+ state = 'disabled' if disabled is True else 'normal'
+ self.ParentNotebook.tab(self.TabID, state=state)
+ if visible is False:
+ self.ParentNotebook.pack_forget()
+ elif visible is True:
+ self.ParentNotebook.pack()
+ return self
+
+ def _GetElementAtLocation(self, location):
+ """
+ Not user callable. Used to find the Element at a row, col position within the layout
+
+ :param location: Tuple[int, int] (row, column) position of the element to find in layout
+ :return: (Element) The element found at the location
+ """
+
+ (row_num, col_num) = location
+ row = self.Rows[row_num]
+ element = row[col_num]
+ return element
+
+
+ def Select(self):
+ """
+ Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first!
+
+ """
+ # Use a try in case the window has been destoyed
+ try:
+ self.ParentNotebook.select(self.TabID)
+ except Exception as e:
+ print('Exception Selecting Tab {}'.format(e))
+
+ add_row = AddRow
+ layout = Layout
+ select = Select
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+# ---------------------------------------------------------------------- #
+# TabGroup #
+# ---------------------------------------------------------------------- #
+class TabGroup(Element):
+ """
+ TabGroup Element groups together your tabs into the group of tabs you see displayed in your window
+ """
+
+ def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None,
+ font=None, change_submits=False, enable_events=False, pad=None, border_width=None, theme=None,
+ key=None, tooltip=None, visible=True, metadata=None):
+ """
+ :param layout: List[List[Tab]] Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row
+ :param tab_location: (str) location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright
+ :param title_color: (str) color of text on tabs
+ :param selected_title_color: (str) color of tab when it is selected
+ :param background_color: (str) color of background of tabs
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param change_submits: (bool) * DEPRICATED DO NOT USE! Same as enable_events
+ :param enable_events: (bool) If True then switching tabs will generate an Event
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param border_width: (int) width of border around element in pixels
+ :param theme: (enum) tabs can be 'themed'. These are the choices (some may not work on your OS): THEME_DEFAULT THEME_WINNATIVE THEME_CLAM THEME_ALT THEME_CLASSIC THEME_VISTA THEME_XPNATIVE
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.UseDictionary = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.ParentWindow = None
+ self.SelectedTitleColor = selected_title_color
+ self.Rows = []
+ self.TKNotebook = None # type: ttk.Notebook
+ self.Widget = None # type: ttk.Notebook
+ self.TabCount = 0
+ self.BorderWidth = border_width
+ self.Theme = theme
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.ChangeSubmits = change_submits or enable_events
+ self.TabLocation = tab_location
+ self.ElementJustification = 'left'
+
+ self.Layout(layout)
+
+ super().__init__(ELEM_TYPE_TAB_GROUP, background_color=background_color, text_color=title_color, font=font,
+ pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def AddRow(self, *args):
+ """
+ Not recommended user call. Used to add rows of Elements to the Frame Element.
+
+ :param *args: List[Element] The list of elements for this row
+ """
+
+ NumRows = len(self.Rows) # number of existing rows is our row number
+ CurrentRowNumber = NumRows # this row's number
+ CurrentRow = [] # start with a blank row and build up
+ # ------------------------- Add the elements to a row ------------------------- #
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
+ element.Position = (CurrentRowNumber, i)
+ element.ParentContainer = self
+ CurrentRow.append(element)
+ if element.Key is not None:
+ self.UseDictionary = True
+ # ------------------------- Append the row to list of Rows ------------------------- #
+ self.Rows.append(CurrentRow)
+
+ def Layout(self, rows):
+ """
+ Can use like the Window.Layout method, but it's better to use the layout parameter when creating
+
+ :param rows: List[List[Element]] The rows of Elements
+ :return: (Frame) Used for chaining
+ """
+ for row in rows:
+ self.AddRow(*row)
+ return self
+
+ def _GetElementAtLocation(self, location):
+ """
+ Not user callable. Used to find the Element at a row, col position within the layout
+
+ :param location: Tuple[int, int] (row, column) position of the element to find in layout
+ :return: (Element) The element found at the location
+ """
+
+ (row_num, col_num) = location
+ row = self.Rows[row_num]
+ element = row[col_num]
+ return element
+
+ def FindKeyFromTabName(self, tab_name):
+ """
+ Searches through the layout to find the key that matches the text on the tab. Implies names should be unique
+
+ :param tab_name:
+ :return: Union[key, None] Returns the key or None if no key found
+ """
+ for row in self.Rows:
+ for element in row:
+ if element.Title == tab_name:
+ return element.Key
+ return None
+
+
+ def Get(self):
+ """
+ Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on
+ the tab if no key is defined. Returns None if an error occurs.
+ Note that this is exactly the same data that would be returned from a call to Window.Read. Are you sure you
+ are using this method correctly?
+
+ :return: Union[Any, None] The key of the currently selected tab or the tab's text if it has no key
+ """
+
+ try:
+ value = self.TKNotebook.tab(self.TKNotebook.index('current'))['text']
+ tab_key = self.FindKeyFromTabName(value)
+ if tab_key is not None:
+ value = tab_key
+ except:
+ value = None
+ return value
+
+ add_row = AddRow
+ find_key_from_tab_name = FindKeyFromTabName
+ get = Get
+ layout = Layout
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+
+
+
+# ---------------------------------------------------------------------- #
+# Slider #
+# ---------------------------------------------------------------------- #
+class Slider(Element):
+ """
+ A slider, horizontal or vertical
+ """
+
+ def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None,
+ disable_number_display=False, border_width=None, relief=None, change_submits=False,
+ enable_events=False, disabled=False, size=(None, None), font=None, background_color=None,
+ text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None):
+ """
+
+ :param range: Union[Tuple[int, int], Tuple[float, float]] slider's range (min value, max value)
+ :param default_value: Union[int, float] starting value for the slider
+ :param resolution: Union[int, float] the smallest amount the slider can be moved
+ :param tick_interval: Union[int, float] how often a visible tick should be shown next to slider
+ :param orientation: (str) 'horizontal' or 'vertical' ('h' or 'v' also work)
+ :param disable_number_display: (bool) if True no number will be displayed by the Slider Element
+ :param border_width: (int) width of border around element in pixels
+ :param relief: (enum) relief style.
+ RELIEF_RAISED
+ RELIEF_SUNKEN
+ RELIEF_FLAT
+ RELIEF_RIDGE
+ RELIEF_GROOVE
+ RELIEF_SOLID
+ :param change_submits: (bool) * DEPRICATED DO NOT USE! Same as enable_events
+ :param enable_events: (bool) If True then moving the slider will generate an Event
+ :param disabled: (bool) set disable state for element
+ :param size: Tuple[int, int] (width in characters, height in rows)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param background_color: (str) color of slider's background
+ :param text_color: (str) color of the slider's text
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.TKScale = self.Widget = None # type: tk.Scale
+ self.Range = (1, 10) if range == (None, None) else range
+ self.DefaultValue = self.Range[0] if default_value is None else default_value
+ self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION
+ self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH
+ self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF
+ self.Resolution = 1 if resolution is None else resolution
+ self.ChangeSubmits = change_submits or enable_events
+ self.Disabled = disabled
+ self.TickInterval = tick_interval
+ self.DisableNumericDisplay = disable_number_display
+ self.TroughColor = DEFAULT_SCROLLBAR_COLOR
+ temp_size = size
+ if temp_size == (None, None):
+ temp_size = (20, 20) if self.Orientation.startswith('h') else (8, 20)
+
+ super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color,
+ text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, value=None, range=(None, None), disabled=None, visible=None):
+ """
+ Changes some of the settings for the Slider Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param value: Union[int, float] sets current slider value
+ :param range: Union[Tuple[int, int], Tuple[float, float] Sets a new range for slider
+ :param disabled: (bool) disable or enable state of the element
+ :param visible: (bool) control visibility of element
+
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if value is not None:
+ try:
+ self.TKIntVar.set(value)
+ except:
+ pass
+ self.DefaultValue = value
+ if disabled == True:
+ self.TKScale['state'] = 'disabled'
+ elif disabled == False:
+ self.TKScale['state'] = 'normal'
+ if visible is False:
+ self.TKScale.pack_forget()
+ elif visible is True:
+ self.TKScale.pack()
+ if range != (None, None):
+ self.TKScale.config(from_=range[0], to_=range[1])
+
+
+
+ def _SliderChangedHandler(self, event):
+ """
+ Not user callable. Callback function for when slider is moved.
+
+ :param event: (event) the event data provided by tkinter. Unknown format. Not used.
+ """
+
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ---------------------------------------------------------------------- #
+# TkFixedFrame (Used by Column) #
+# ---------------------------------------------------------------------- #
+class TkFixedFrame(tk.Frame):
+ """
+ A tkinter frame that is used with Column Elements that do not have a scrollbar
+ """
+ def __init__(self, master, **kwargs):
+ """
+ :param master: (tk.Widget) The parent widget
+ :param **kwargs: The keyword args
+ """
+ tk.Frame.__init__(self, master, **kwargs)
+
+ self.canvas = tk.Canvas(self)
+
+ self.canvas.pack(side="left", fill="both", expand=True)
+
+ # reset the view
+ self.canvas.xview_moveto(0)
+ self.canvas.yview_moveto(0)
+
+ # create a frame inside the canvas which will be scrolled with it
+ self.TKFrame = tk.Frame(self.canvas, **kwargs)
+ self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw")
+ self.canvas.config(borderwidth=0, highlightthickness=0)
+ self.TKFrame.config(borderwidth=0, highlightthickness=0)
+ self.config(borderwidth=0, highlightthickness=0)
+
+
+# ---------------------------------------------------------------------- #
+# TkScrollableFrame (Used by Column) #
+# ---------------------------------------------------------------------- #
+class TkScrollableFrame(tk.Frame):
+ """
+ A frame with one or two scrollbars. Used to make Columns with scrollbars
+ """
+ def __init__(self, master, vertical_only, **kwargs):
+ """
+
+ :param master: (tk.Widget) The parent widget
+ :param vertical_only: (bool) if True the only a vertical scrollbar will be shown
+ :param **kwargs: The keyword parms
+ """
+ tk.Frame.__init__(self, master, **kwargs)
+ # create a canvas object and a vertical scrollbar for scrolling it
+ self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
+ self.vscrollbar.pack(side='right', fill="y", expand="false")
+
+ if not vertical_only:
+ self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
+ self.hscrollbar.pack(side='bottom', fill="x", expand="false")
+ self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, xscrollcommand=self.hscrollbar.set)
+ else:
+ self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set)
+
+ self.canvas.pack(side="left", fill="both", expand=True)
+
+ self.vscrollbar.config(command=self.canvas.yview)
+ if not vertical_only:
+ self.hscrollbar.config(command=self.canvas.xview)
+
+ # reset the view
+ self.canvas.xview_moveto(0)
+ self.canvas.yview_moveto(0)
+
+ # create a frame inside the canvas which will be scrolled with it
+ self.TKFrame = tk.Frame(self.canvas, **kwargs)
+ self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw")
+ self.canvas.config(borderwidth=0, highlightthickness=0)
+ self.TKFrame.config(borderwidth=0, highlightthickness=0)
+ self.config(borderwidth=0, highlightthickness=0)
+
+ # scrollbar = tk.Scrollbar(frame)
+ # scrollbar.pack(side=tk.RIGHT, fill='y')
+ # scrollbar.config(command=treeview.yview)
+ # self.vscrollbar.config(command=self.TKFrame.yview)
+ # self.TKFrame.configure(yscrollcommand=self.vscrollbar.set)
+
+ self.bind('', self.set_scrollregion)
+
+ self.canvas.bind("", self.yscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse!
+ self.canvas.bind("", self.xscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse!
+
+
+
+ # def _on_mousewheel(self, event):
+ # self.canv.yview_scroll(int(-1 * (event.delta / 120)), "units")
+
+
+ # self.bind_mouse_scroll(self.canvas, self.yscroll)
+ # if not vertical_only:
+ # self.bind_mouse_scroll(self.hscrollbar, self.xscroll)
+ # self.bind_mouse_scroll(self.vscrollbar, self.yscroll)
+ # self.bind_mouse_scroll(self.TKFrame, self.yscroll)
+ # self.bind_mouse_scroll(self, self.yscroll)
+
+ def resize_frame(self, e):
+ """
+
+ :param e:
+
+ """
+ self.canvas.itemconfig(self.frame_id, height=e.height, width=e.width)
+
+ def yscroll(self, event):
+ """
+
+ :param event:
+
+ """
+ if event.num == 5 or event.delta < 0:
+ self.canvas.yview_scroll(1, "unit")
+ elif event.num == 4 or event.delta > 0:
+ self.canvas.yview_scroll(-1, "unit")
+
+ def xscroll(self, event):
+ """
+
+ :param event:
+
+ """
+ if event.num == 5 or event.delta < 0:
+ self.canvas.xview_scroll(1, "unit")
+ elif event.num == 4 or event.delta > 0:
+ self.canvas.xview_scroll(-1, "unit")
+
+ def bind_mouse_scroll(self, parent, mode):
+ """
+
+ :param parent:
+ :param mode:
+
+ """
+ # ~~ Windows only
+ parent.bind("", mode)
+ # ~~ Unix only
+ parent.bind("", mode)
+ parent.bind("", mode)
+
+ def set_scrollregion(self, event=None):
+ """Set the scroll region on the canvas
+
+ :param event:
+
+ """
+ self.canvas.configure(scrollregion=self.canvas.bbox('all'))
+
+
+# ---------------------------------------------------------------------- #
+# Column #
+# ---------------------------------------------------------------------- #
+class Column(Element):
+ """
+ A container element that is used to create a layout within your window's layout
+ """
+
+ def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False,
+ vertical_scroll_only=False, right_click_menu=None, key=None, visible=True, justification='left', element_justification='left', metadata=None):
+ """
+ :param layout: List[List[Element]] Layout that will be shown in the Column container
+ :param background_color: (str) color of background of entire Column
+ :param size: Tuple[int, int] (width, height) size in pixels (doesn't work quite right, sometimes
+ only 1 dimension is set by tkinter
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param scrollable: (bool) if True then scrollbars will be added to the column
+ :param vertical_scroll_only: (bool) if Truen then no horizontal scrollbar will be shown
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param visible: (bool) set visibility state of the element
+ :param justification: (str) set justification for the Column itself. Note entire row containing the Column will be affected
+ :param element_justification: (str) All elements inside the Column will have this justification 'left', 'right', 'center' are valid values
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.UseDictionary = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.ParentWindow = None
+ self.ParentPanedWindow = None
+ self.Rows = []
+ self.TKFrame = None
+ self.TKColFrame = None
+ self.Scrollable = scrollable
+ self.VerticalScrollOnly = vertical_scroll_only
+ self.RightClickMenu = right_click_menu
+ bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.ContainerElemementNumber = Window.GetAContainerNumber()
+ self.ElementJustification = element_justification
+ self.Justification = justification
+ self.Layout(layout)
+
+ super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=size, pad=pad, key=key, visible=visible, metadata=metadata)
+ return
+
+ def AddRow(self, *args):
+ """
+ Not recommended user call. Used to add rows of Elements to the Column Element.
+
+ :param *args: List[Element] The list of elements for this row
+ """
+
+ NumRows = len(self.Rows) # number of existing rows is our row number
+ CurrentRowNumber = NumRows # this row's number
+ CurrentRow = [] # start with a blank row and build up
+ # ------------------------- Add the elements to a row ------------------------- #
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
+ element.Position = (CurrentRowNumber, i)
+ element.ParentContainer = self
+ CurrentRow.append(element)
+ if element.Key is not None:
+ self.UseDictionary = True
+ # ------------------------- Append the row to list of Rows ------------------------- #
+ self.Rows.append(CurrentRow)
+
+ def Layout(self, rows):
+ """
+ Can use like the Window.Layout method, but it's better to use the layout parameter when creating
+
+ :param rows: List[List[Element]] The rows of Elements
+ :return: (Column) Used for chaining
+ """
+
+ for row in rows:
+ self.AddRow(*row)
+ return self
+
+
+ def _GetElementAtLocation(self, location):
+ """
+ Not user callable. Used to find the Element at a row, col position within the layout
+
+ :param location: Tuple[int, int] (row, column) position of the element to find in layout
+ :return: (Element) The element found at the location
+ """
+
+ (row_num, col_num) = location
+ row = self.Rows[row_num]
+ element = row[col_num]
+ return element
+
+
+ def Update(self, visible=None):
+ """
+ Changes some of the settings for the Column Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if visible is False:
+ if self.TKColFrame:
+ self.TKColFrame.pack_forget()
+ if self.ParentPanedWindow:
+ self.ParentPanedWindow.remove(self.TKColFrame)
+ elif visible is True:
+ if self.TKColFrame:
+ self.TKColFrame.pack()
+ if self.ParentPanedWindow:
+ self.ParentPanedWindow.add(self.TKColFrame)
+
+ add_row = AddRow
+ layout = Layout
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+Col = Column
+
+# ---------------------------------------------------------------------- #
+# Pane #
+# ---------------------------------------------------------------------- #
+class Pane(Element):
+ """
+ A sliding Pane that is unique to tkinter. Uses Columns to create individual panes
+ """
+
+ def __init__(self, pane_list, background_color=None, size=(None, None), pad=None, orientation='vertical',
+ show_handle=True, relief=RELIEF_RAISED, handle_size=None, border_width=None, key=None, visible=True, metadata=None):
+ """
+ :param pane_list: List[Column] Must be a list of Column Elements. Each Column supplied becomes one pane that's shown
+ :param background_color: (str) color of background
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high How much room to reserve for the Pane
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param orientation: (str) 'horizontal' or 'vertical' or ('h' or 'v'). Direction the Pane should slide
+ :param show_handle: (bool) if True, the handle is drawn that makes it easier to grab and slide
+ :param relief: (enum) relief style. Values are same as other elements that use relief values.
+ RELIEF_RAISED
+ RELIEF_SUNKEN
+ RELIEF_FLAT
+ RELIEF_RIDGE
+ RELIEF_GROOVE
+ RELIEF_SOLID
+ :param handle_size: (int) Size of the handle in pixels
+ :param border_width: (int) width of border around element in pixels
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.UseDictionary = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.ParentWindow = None
+ self.Rows = []
+ self.TKFrame = None
+ self.PanedWindow = None
+ self.Orientation = orientation
+ self.PaneList = pane_list
+ self.ShowHandle = show_handle
+ self.Relief = relief
+ self.HandleSize = handle_size or 8
+ self.BorderDepth = border_width
+ bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+
+ self.Rows = [pane_list]
+
+ super().__init__(ELEM_TYPE_PANE, background_color=bg, size=size, pad=pad, key=key, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, visible=None):
+ """
+ Changes some of the settings for the Pane Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if visible is False:
+ self.PanedWindow.pack_forget()
+ elif visible is True:
+ self.PanedWindow.pack()
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ---------------------------------------------------------------------- #
+# Calendar #
+# ---------------------------------------------------------------------- #
+class TKCalendar(ttk.Frame):
+ """
+ This code was shamelessly lifted from moshekaplan's repository - moshekaplan/tkinter_components
+ NONE of this code is user callable. Stay away!
+ """
+ # XXX ToDo: cget and configure
+
+ datetime = calendar.datetime.datetime
+ timedelta = calendar.datetime.timedelta
+
+ def __init__(self, master=None, target_element=None, close_when_chosen=True, default_date=(None, None, None), **kw):
+ """WIDGET-SPECIFIC OPTIONS
+
+ locale, firstweekday, year, month, selectbackground,
+ selectforeground
+
+ :param master:
+ :param target_element:
+ :param close_when_chosen: (Default = True)
+ :param default_date: (Default = (None))
+ :param None:, None))
+ :param **kw:
+
+ """
+ self._TargetElement = target_element
+ default_mon, default_day, default_year = default_date
+ # remove custom options from kw before initializating ttk.Frame
+ fwday = kw.pop('firstweekday', calendar.MONDAY)
+ year = kw.pop('year', default_year or self.datetime.now().year)
+ month = kw.pop('month', default_mon or self.datetime.now().month)
+ locale = kw.pop('locale', None)
+ sel_bg = kw.pop('selectbackground', '#ecffc4')
+ sel_fg = kw.pop('selectforeground', '#05640e')
+ self.format = kw.pop('format')
+ if self.format is None:
+ self.format = '%Y-%m-%d %H:%M:%S'
+
+ self._date = self.datetime(year, month, default_day or 1)
+ self._selection = None # no date selected
+ self._master = master
+ self.close_when_chosen = close_when_chosen
+ ttk.Frame.__init__(self, master, **kw)
+
+ # instantiate proper calendar class
+ if locale is None:
+ self._cal = calendar.TextCalendar(fwday)
+ else:
+ self._cal = calendar.LocaleTextCalendar(fwday, locale)
+
+ self.__setup_styles() # creates custom styles
+ self.__place_widgets() # pack/grid used widgets
+ self.__config_calendar() # adjust calendar columns and setup tags
+ # configure a canvas, and proper bindings, for selecting dates
+ self.__setup_selection(sel_bg, sel_fg)
+
+ # store items ids, used for insertion later
+ self._items = [self._calendar.insert('', 'end', values='')
+ for _ in range(6)]
+ # insert dates in the currently empty calendar
+ self._build_calendar()
+
+ def __setitem__(self, item, value):
+ """
+
+ :param item:
+ :param value:
+
+ """
+ if item in ('year', 'month'):
+ raise AttributeError("attribute '%s' is not writeable" % item)
+ elif item == 'selectbackground':
+ self._canvas['background'] = value
+ elif item == 'selectforeground':
+ self._canvas.itemconfigure(self._canvas.text, item=value)
+ else:
+ ttk.Frame.__setitem__(self, item, value)
+
+ def __getitem__(self, item):
+ """
+
+ :param item:
+
+ """
+ if item in ('year', 'month'):
+ return getattr(self._date, item)
+ elif item == 'selectbackground':
+ return self._canvas['background']
+ elif item == 'selectforeground':
+ return self._canvas.itemcget(self._canvas.text, 'fill')
+ else:
+ r = ttk.tclobjs_to_py({item: ttk.Frame.__getitem__(self, item)})
+ return r[item]
+
+ def __setup_styles(self):
+ """ """
+ # custom ttk styles
+ style = ttk.Style(self.master)
+ arrow_layout = lambda dir: (
+ [('Button.focus', {'children': [('Button.%sarrow' % dir, None)]})]
+ )
+ style.layout('L.TButton', arrow_layout('left'))
+ style.layout('R.TButton', arrow_layout('right'))
+
+ def __place_widgets(self):
+ """ """
+ # header frame and its widgets
+ hframe = ttk.Frame(self)
+ lbtn = ttk.Button(hframe, style='L.TButton', command=self._prev_month)
+ rbtn = ttk.Button(hframe, style='R.TButton', command=self._next_month)
+ self._header = ttk.Label(hframe, width=15, anchor='center')
+ # the calendar
+ self._calendar = ttk.Treeview(self, show='', selectmode='none', height=7)
+
+ # pack the widgets
+ hframe.pack(in_=self, side='top', pady=4, anchor='center')
+ lbtn.grid(in_=hframe)
+ self._header.grid(in_=hframe, column=1, row=0, padx=12)
+ rbtn.grid(in_=hframe, column=2, row=0)
+ self._calendar.pack(in_=self, expand=1, fill='both', side='bottom')
+
+ def __config_calendar(self):
+ """ """
+ cols = self._cal.formatweekheader(3).split()
+ self._calendar['columns'] = cols
+ self._calendar.tag_configure('header', background='grey90')
+ self._calendar.insert('', 'end', values=cols, tag='header')
+ # adjust its columns width
+ font = tkinter.font.Font()
+ maxwidth = max(font.measure(col) for col in cols)
+ for col in cols:
+ self._calendar.column(col, width=maxwidth, minwidth=maxwidth,
+ anchor='e')
+
+ def __setup_selection(self, sel_bg, sel_fg):
+ """
+
+ :param sel_bg:
+ :param sel_fg:
+
+ """
+ self._font = tkinter.font.Font()
+ self._canvas = canvas = tk.Canvas(self._calendar,
+ background=sel_bg, borderwidth=0, highlightthickness=0)
+ canvas.text = canvas.create_text(0, 0, fill=sel_fg, anchor='w')
+
+ canvas.bind('', lambda evt: canvas.place_forget())
+ self._calendar.bind('', lambda evt: canvas.place_forget())
+ self._calendar.bind('', self._pressed)
+
+ def __minsize(self, evt):
+ """
+
+ :param evt:
+
+ """
+ width, height = self._calendar.master.geometry().split('x')
+ height = height[:height.index('+')]
+ self._calendar.master.minsize(width, height)
+
+ def _build_calendar(self):
+ """ """
+ year, month = self._date.year, self._date.month
+
+ # update header text (Month, YEAR)
+ header = self._cal.formatmonthname(year, month, 0)
+ self._header['text'] = header.title()
+
+ # update calendar shown dates
+ cal = self._cal.monthdayscalendar(year, month)
+ for indx, item in enumerate(self._items):
+ week = cal[indx] if indx < len(cal) else []
+ fmt_week = [('%02d' % day) if day else '' for day in week]
+ self._calendar.item(item, values=fmt_week)
+
+ def _show_selection(self, text, bbox):
+ """Configure canvas for a new selection.
+
+ :param text:
+ :param bbox:
+
+ """
+ x, y, width, height = bbox
+
+ textw = self._font.measure(text)
+
+ canvas = self._canvas
+ canvas.configure(width=width, height=height)
+ canvas.coords(canvas.text, width - textw, height / 2 - 1)
+ canvas.itemconfigure(canvas.text, text=text)
+ canvas.place(in_=self._calendar, x=x, y=y)
+
+ # Callbacks
+
+ def _pressed(self, evt):
+ """Clicked somewhere in the calendar.
+
+ :param evt:
+
+ """
+ x, y, widget = evt.x, evt.y, evt.widget
+ item = widget.identify_row(y)
+ column = widget.identify_column(x)
+
+ if not column or not item in self._items:
+ # clicked in the weekdays row or just outside the columns
+ return
+
+ item_values = widget.item(item)['values']
+ if not len(item_values): # row is empty for this month
+ return
+
+ text = item_values[int(column[1]) - 1]
+ if not text: # date is empty
+ return
+
+ bbox = widget.bbox(item, column)
+ if not bbox: # calendar not visible yet
+ return
+
+ # update and then show selection
+ text = '%02d' % text
+ self._selection = (text, item, column)
+ self._show_selection(text, bbox)
+ year, month = self._date.year, self._date.month
+ now = self.datetime.now()
+ try:
+ self._TargetElement.Update(
+ self.datetime(year, month, int(self._selection[0]), now.hour, now.minute, now.second).strftime(
+ self.format))
+ if self._TargetElement.ChangeSubmits:
+ self._TargetElement.ParentForm.LastButtonClicked = self._TargetElement.Key
+ self._TargetElement.ParentForm.FormRemainedOpen = True
+ self._TargetElement.ParentForm.TKroot.quit() # kick the users out of the mainloop
+ except:
+ pass
+ if self.close_when_chosen:
+ self._master.destroy()
+
+ def _prev_month(self):
+ """Updated calendar to show the previous month."""
+ self._canvas.place_forget()
+
+ self._date = self._date - self.timedelta(days=1)
+ self._date = self.datetime(self._date.year, self._date.month, 1)
+ self._build_calendar() # reconstuct calendar
+
+ def _next_month(self):
+ """Update calendar to show the next month."""
+ self._canvas.place_forget()
+
+ year, month = self._date.year, self._date.month
+ self._date = self._date + self.timedelta(
+ days=calendar.monthrange(year, month)[1] + 1)
+ self._date = self.datetime(self._date.year, self._date.month, 1)
+ self._build_calendar() # reconstruct calendar
+
+ # Properties
+
+ @property
+ def selection(self):
+ """ """
+ if not self._selection:
+ return None
+
+ year, month = self._date.year, self._date.month
+ return self.datetime(year, month, int(self._selection[0]))
+
+
+# ---------------------------------------------------------------------- #
+# Menu #
+# ---------------------------------------------------------------------- #
+class Menu(Element):
+ """
+ Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar.
+ Here is an example layout. The "&" are shortcut keys ALT+key.
+ Is a List of - "Item String" + List
+ Where Item String is what will be displayed on the Menubar itself.
+ The List that follows the item represents the items that are shown then Menu item is clicked
+ Notice how an "entry" in a mennu can be a list which means it branches out and shows another menu, etc. (resursive)
+ menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']],
+ ['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ],
+ ['&Debugger', ['Popout', 'Launch Debugger']],
+ ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']],
+ ['&Help', '&About...'], ]
+ Finally, "keys" can be added to entries so make them unique. The "Save" entry has a key associated with it. You
+ can see it has a "::" which signifies the beginning of a key. The user will not see the key portion when the
+ menu is shown. The key portion is returned as part of the event.
+ """
+
+ def __init__(self, menu_definition, background_color=None, size=(None, None), tearoff=False, pad=None, key=None,
+ visible=True, metadata=None):
+ """
+ :param menu_definition: List[List[Tuple[str, List[str]]]
+ :param background_color: (str) color of the background
+ :param size: Tuple[int, int] Not used in the tkinter port
+ :param tearoff: (bool) if True, then can tear the menu off from the window ans use as a floating window. Very cool effect
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.MenuDefinition = menu_definition
+ self.Widget = self.TKMenu = None # type: tk.Menu
+ self.Tearoff = tearoff
+ self.MenuItemChosen = None
+
+ super().__init__(ELEM_TYPE_MENUBAR, background_color=background_color, size=size, pad=pad, key=key,
+ visible=visible, metadata=metadata)
+ return
+
+ def _MenuItemChosenCallback(self, item_chosen): # Menu Menu Item Chosen Callback
+ """
+ Not user callable. Called when some end-point on the menu (an item) has been clicked. Send the information back to the application as an event. Before event can be sent
+
+ :param item_chosen: (str) the text that was clicked on / chosen from the menu
+ """
+ # print('IN MENU ITEM CALLBACK', item_chosen)
+ self.MenuItemChosen = item_chosen
+ self.ParentForm.LastButtonClicked = item_chosen
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit() # kick the users out of the mainloop
+
+ def Update(self, menu_definition=None, visible=None):
+ """
+ Update a menubar - can change the menu definition and visibility. The entire menu has to be specified
+
+ :param menu_definition: List[List[Tuple[str, List[str]]]
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if menu_definition is not None:
+ self.MenuDefinition = menu_definition
+ self.TKMenu = tk.Menu(self.ParentForm.TKroot, tearoff=self.Tearoff) # create the menubar
+ menubar = self.TKMenu
+ for menu_entry in menu_definition:
+ # print(f'Adding a Menubar ENTRY {menu_entry}')
+ baritem = tk.Menu(menubar, tearoff=self.Tearoff)
+ pos = menu_entry[0].find('&')
+ # print(pos)
+ if pos != -1:
+ if pos == 0 or menu_entry[0][pos - 1] != "\\":
+ menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:]
+ if menu_entry[0][0] == MENU_DISABLED_CHARACTER:
+ menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem, underline=pos)
+ menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled')
+ else:
+ menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos)
+
+ if len(menu_entry) > 1:
+ AddMenuItem(baritem, menu_entry[1], self)
+
+ if visible == False:
+ self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear
+ elif self.TKMenu is not None:
+ self.ParentForm.TKroot.configure(menu=self.TKMenu)
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+MenuBar = Menu # another name for Menu to make it clear it's the Menu Bar
+
+
+# ---------------------------------------------------------------------- #
+# Table #
+# ---------------------------------------------------------------------- #
+class Table(Element):
+ """ """
+
+ def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10,
+ auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None,
+ row_height=None, font=None, justification='right', text_color=None, background_color=None,
+ alternating_row_color=None, row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False,
+ size=(None, None), change_submits=False, enable_events=False, bind_return_key=False, pad=None,
+ key=None, tooltip=None, right_click_menu=None, visible=True, metadata=None):
+ """
+ :param values: List[List[Union[str, int, float]]]
+ :param headings: List[str] The headings to show on the top line
+ :param visible_column_map: List[bool] One entry for each column. False indicates the column is not shown
+ :param col_widths: List[int] Number of characters that each column will occupy
+ :param def_col_width: (int) Default column width in characters
+ :param auto_size_columns: (bool) if True columns will be sized automatically
+ :param max_col_width: (int) Maximum width for all columns in characters
+ :param select_mode: (enum) Select Mode. Valid values start with "TABLE_SELECT_MODE_". Valid values are:
+ TABLE_SELECT_MODE_NONE
+ TABLE_SELECT_MODE_BROWSE
+ TABLE_SELECT_MODE_EXTENDED
+ :param display_row_numbers: (bool) if True, the first column of the table will be the row #
+ :param num_rows: (int) The number of rows of the table to display at a time
+ :param row_height: (int) height of a single row in pixels
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param justification: (str) 'left', 'right', 'center' are valid choices
+ :param text_color: (str) color of the text
+ :param background_color: (str) color of background
+ :param alternating_row_color: (str) if set then every other row will have this color in the background.
+ :param row_colors:
+ :param vertical_scroll_only: (bool) if True only the vertical scrollbar will be visible
+ :param hide_vertical_scroll: (bool) if True vertical scrollbar will be hidden
+ :param size: Tuple[int, int] DO NOT USE! Use num_rows instead
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Table events happen when row is clicked
+ :param bind_return_key: (bool) if True, pressing return key will cause event coming from Table, ALSO a left button double click will generate an event if this parameter is True
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.Values = values
+ self.ColumnHeadings = headings
+ self.ColumnsToDisplay = visible_column_map
+ self.ColumnWidths = col_widths
+ self.MaxColumnWidth = max_col_width
+ self.DefaultColumnWidth = def_col_width
+ self.AutoSizeColumns = auto_size_columns
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.TextColor = text_color
+ self.Justification = justification
+ self.InitialState = None
+ self.SelectMode = select_mode
+ self.DisplayRowNumbers = display_row_numbers
+ self.NumRows = num_rows if num_rows is not None else size[1]
+ self.RowHeight = row_height
+ self.Widget = self.TKTreeview = None # type: ttk.Treeview
+ self.AlternatingRowColor = alternating_row_color
+ self.VerticalScrollOnly = vertical_scroll_only
+ self.HideVerticalScroll = hide_vertical_scroll
+ self.SelectedRows = []
+ self.ChangeSubmits = change_submits or enable_events
+ self.BindReturnKey = bind_return_key
+ self.StartingRowNumber = 0 # When displaying row numbers, where to start
+ self.RowHeaderText = 'Row'
+ self.RightClickMenu = right_click_menu
+ self.RowColors = row_colors
+ self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors
+ super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font,
+ size=size, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def Update(self, values=None, num_rows=None, visible=None, select_rows=None, alternating_row_color=None, row_colors=None):
+ """
+ Changes some of the settings for the Table Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param values: List[List[Union[str, int, float]]] A new 2-dimensional table to show
+ :param num_rows: (int) How many rows to display at a time
+ :param visible: (bool) if True then will be visible
+ :param select_rows: List[int] List of rows to select as if user did
+ :param alternating_row_color: (str) the color to make every other row
+ :param row_colors: List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if values is not None:
+ for id in self.tree_ids:
+ self.TKTreeview.item(id, tags=())
+ if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ self.TKTreeview.tag_configure(id, background=self.BackgroundColor)
+ else:
+ self.TKTreeview.tag_configure(id, background='#FFFFFF', foreground='#000000')
+ if self.TextColor is not None and self.TextColor != COLOR_SYSTEM_DEFAULT:
+ self.TKTreeview.tag_configure(id, foreground=self.TextColor)
+ else:
+ self.TKTreeview.tag_configure(id, foreground='#000000')
+
+ children = self.TKTreeview.get_children()
+ for i in children:
+ self.TKTreeview.detach(i)
+ self.TKTreeview.delete(i)
+ children = self.TKTreeview.get_children()
+
+ self.tree_ids =[]
+ for i, value in enumerate(values):
+ if self.DisplayRowNumbers:
+ value = [i + self.StartingRowNumber] + value
+ id = self.TKTreeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i)
+ if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ self.TKTreeview.tag_configure(id, background=self.BackgroundColor)
+ else:
+ self.TKTreeview.tag_configure(id, background='#FFFFFF')
+ self.tree_ids.append(id)
+ self.Values = values
+ self.SelectedRows = []
+ if visible is False:
+ self.TKTreeview.pack_forget()
+ elif visible is True:
+ self.TKTreeview.pack()
+ if num_rows is not None:
+ self.TKTreeview.config(height=num_rows)
+ if select_rows is not None:
+ rows_to_select = [i+1 for i in select_rows]
+ self.TKTreeview.selection_set(rows_to_select)
+
+ if alternating_row_color is not None: # alternating colors
+ self.AlternatingRowColor = alternating_row_color
+
+ if self.AlternatingRowColor is not None:
+ for row in range(0, len(self.Values), 2):
+ self.TKTreeview.tag_configure(row, background=self.AlternatingRowColor)
+ if row_colors is not None: # individual row colors
+ self.RowColors = row_colors
+ for row_def in self.RowColors:
+ if len(row_def) == 2: # only background is specified
+ self.TKTreeview.tag_configure(row_def[0], background=row_def[1])
+ else:
+ self.TKTreeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1])
+
+ def treeview_selected(self, event):
+ """
+ Not user callable. Callback function that is called when something is selected from Table.
+ Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read
+
+ :param event: (unknown) event information from tkinter
+ """
+ selections = self.TKTreeview.selection()
+ self.SelectedRows = [int(x) - 1 for x in selections]
+ if self.ChangeSubmits:
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def treeview_double_click(self, event):
+ """
+ Not user callable. Callback function that is called when something is selected from Table.
+ Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read
+
+ :param event: (unknown) event information from tkinter
+ """
+ selections = self.TKTreeview.selection()
+ self.SelectedRows = [int(x) - 1 for x in selections]
+ if self.BindReturnKey: # Signifies BOTH a return key AND a double click
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+ def Get(self):
+ """
+ Dummy function for tkinter port. In the Qt port you can read back the values in the table in case they were
+ edited. Don't know yet how to enable editing of a Tree in tkinter so just returning the values provided by
+ user when Table was created or Updated.
+
+ :return: List[List[Any]] the current table values (for now what was originally provided up updated)
+ """
+ return self.Values
+
+
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+ get = Get
+
+# ---------------------------------------------------------------------- #
+# Tree #
+# ---------------------------------------------------------------------- #
+class Tree(Element):
+ """
+ Tree Element - Presents data in a tree-like manner, much like a file/folder browser. Uses the TreeData class
+ to hold the user's data and pass to the element for display.
+ """
+
+ def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10,
+ def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False,
+ change_submits=False, enable_events=False, font=None, justification='right', text_color=None,
+ background_color=None, num_rows=None, row_height=None, pad=None, key=None, tooltip=None,
+ right_click_menu=None, visible=True, metadata=None):
+ """
+
+ :param data: (TreeData) The data represented using a PySimpleGUI provided TreeData class
+ :param headings: List[str] List of individual headings for each column
+ :param visible_column_map: List[bool] Determines if a column should be visible. If left empty, all columns will be shown
+ :param col_widths: List[int] List of column widths so that individual column widths can be controlled
+ :param col0_width: (int) Size of Column 0 which is where the row numbers will be optionally shown
+ :param def_col_width: (int) default column width
+ :param auto_size_columns: (bool) if True, the size of a column is determined using the contents of the column
+ :param max_col_width: (int) the maximum size a column can be
+ :param select_mode: (enum) Use same values as found on Table Element. Valid values include:
+ TABLE_SELECT_MODE_NONE
+ TABLE_SELECT_MODE_BROWSE
+ TABLE_SELECT_MODE_EXTENDED
+ :param show_expanded: (bool) if True then the tree will be initially shown with all nodes completely expanded
+ :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
+ :param enable_events: (bool) Turns on the element specific events. Tree events happen when row is clicked
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param justification: (str) 'left', 'right', 'center' are valid choices
+ :param text_color: (str) color of the text
+ :param background_color: (str) color of background
+ :param num_rows: (int) The number of rows of the table to display at a time
+ :param row_height: (int) height of a single row in pixels
+ :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param visible: (bool) set visibility state of the element
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.TreeData = data
+ self.ColumnHeadings = headings
+ self.ColumnsToDisplay = visible_column_map
+ self.ColumnWidths = col_widths
+ self.MaxColumnWidth = max_col_width
+ self.DefaultColumnWidth = def_col_width
+ self.AutoSizeColumns = auto_size_columns
+ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
+ self.TextColor = text_color
+ self.Justification = justification
+ self.InitialState = None
+ self.SelectMode = select_mode
+ self.ShowExpanded = show_expanded
+ self.NumRows = num_rows
+ self.Col0Width = col0_width
+ self.TKTreeview = None
+ self.SelectedRows = []
+ self.ChangeSubmits = change_submits or enable_events
+ self.RightClickMenu = right_click_menu
+ self.RowHeight = row_height
+ self.IconList = {}
+ self.IdToKey = {'':''}
+ self.KeyToID = {'':''}
+
+ super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad,
+ key=key, tooltip=tooltip, visible=visible, metadata=metadata)
+ return
+
+ def treeview_selected(self, event):
+ """
+ Not a user function. Callback function that happens when an item is selected from the tree. In this
+ method, it saves away the reported selections so they can be properly returned.
+
+ :param event: (Any) An event parameter passed in by tkinter. Not used
+ """
+
+ selections = self.TKTreeview.selection()
+ # self.SelectedRows = [x for x in selections]
+ self.SelectedRows = [self.IdToKey[x] for x in selections]
+ if self.ChangeSubmits:
+ MyForm = self.ParentForm
+ if self.Key is not None:
+ self.ParentForm.LastButtonClicked = self.Key
+ else:
+ self.ParentForm.LastButtonClicked = ''
+ self.ParentForm.FormRemainedOpen = True
+ if self.ParentForm.CurrentlyRunningMainloop:
+ self.ParentForm.TKroot.quit()
+
+
+ def add_treeview_data(self, node):
+ """
+ Not a user function. Recursive method that inserts tree data into the tkinter treeview widget.
+
+ :param node: (TreeData) The node to insert. Will insert all nodes from starting point downward, recursively
+ """
+ if node.key != '':
+ if node.icon:
+ try:
+ if type(node.icon) is bytes:
+ photo = tk.PhotoImage(data=node.icon)
+ else:
+ photo = tk.PhotoImage(file=node.icon)
+ node.photo = photo
+ id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text,
+ values=node.values, open=self.ShowExpanded, image=node.photo)
+ self.IdToKey[id] = node.key
+ self.KeyToID[node.key] = id
+ except:
+ self.photo = None
+ else:
+ id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text,
+ values=node.values, open=self.ShowExpanded)
+ self.IdToKey[id] = node.key
+ self.KeyToID[node.key] = id
+
+ for node in node.children:
+ self.add_treeview_data(node)
+
+
+ def Update(self, values=None, key=None, value=None, text=None, icon=None, visible=None):
+ """
+ Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior
+
+ :param values: (TreeData) Representation of the tree
+ :param key: (Any) identifies a particular item in tree to update
+ :param value: (Any) sets the node identified by key to a particular value
+ :param text: (str) sets the node identified by ket to this string
+ :param icon: Union[bytes, str] can be either a base64 icon or a filename for the icon
+ :param visible: (bool) control visibility of element
+ """
+ if self.Widget is None:
+ warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning)
+ return
+ if values is not None:
+ children = self.TKTreeview.get_children()
+ for i in children:
+ self.TKTreeview.detach(i)
+ self.TKTreeview.delete(i)
+ children = self.TKTreeview.get_children()
+ self.TreeData = values
+ self.IdToKey = {'': ''}
+ self.KeyToID = {'': ''}
+ self.add_treeview_data(self.TreeData.root_node)
+ self.SelectedRows = []
+ if key is not None:
+ for id in self.IdToKey.keys():
+ if key == self.IdToKey[id]:
+ break
+ else:
+ id = None
+ print('** Key not found **')
+ else:
+ id = None
+ if id:
+ # item = self.TKTreeview.item(id)
+ if value is not None:
+ self.TKTreeview.item(id, values=value)
+ if text is not None:
+ self.TKTreeview.item(id, text=text)
+ if icon is not None:
+ try:
+ if type(icon) is bytes:
+ photo = tk.PhotoImage(data=icon)
+ else:
+ photo = tk.PhotoImage(file=icon)
+ self.TKTreeview.item(id, image=photo)
+ self.IconList[key] = photo # save so that it's not deleted (save reference)
+ except:
+ pass
+ # item = self.TKTreeview.item(id)
+ if visible is False:
+ self.TKTreeview.pack_forget()
+ elif visible is True:
+ self.TKTreeview.pack()
+ return self
+
+
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+class TreeData(object):
+ """
+ Class that user fills in to represent their tree data. It's a very simple tree representation with a root "Node"
+ with possibly one or more children "Nodes". Each Node contains a key, text to display, list of values to display
+ and an icon. The entire tree is built using a single method, Insert. Nothing else is required to make the tree.
+ """
+ class Node(object):
+ """
+ Contains information about the individual node in the tree
+ """
+ def __init__(self, parent, key, text, values, icon=None):
+ """
+ :param parent: (TreeData.Node) The parent Node
+ :param key: (Any) Used to uniquely identify this node
+ :param text: (str) The text that is displayed at this node's location
+ :param values: List[Any] The list of values that are displayed at this node
+ :param icon: Union[str, bytes]
+ """
+
+ self.parent = parent # type: TreeData.Node
+ self.children = [] # type: List[TreeData.Node]
+ self.key = key # type: str
+ self.text = text # type: str
+ self.values = values # type: List[Any]
+ self.icon = icon # type: Union[str, bytes]
+
+ def _Add(self, node):
+ """
+
+ :param node:
+
+ """
+ self.children.append(node)
+
+ def __init__(self):
+ """
+ Instantiate the object, initializes the Tree Data, creates a root node for you
+ """
+ self.tree_dict = {} # type: Dict[str : TreeData.Node]
+ self.root_node = self.Node("", "", 'root', [], None) # The root node
+ self.tree_dict[""] = self.root_node # Start the tree out with the root node
+
+ def _AddNode(self, key, node):
+ """
+ Adds a node to tree dictionary (not user callable)
+
+ :param key: (str) Uniquely identifies this Node
+ :param node: (TreeData.Node) Node being added
+ """
+ self.tree_dict[key] = node
+
+ def Insert(self, parent, key, text, values, icon=None):
+ """
+ Inserts a node into the tree. This is how user builds their tree, by Inserting Nodes
+ This is the ONLY user callable method in the TreeData class
+
+ :param parent: (Node) the parent Node
+ :param key: (Any) Used to uniquely identify this node
+ :param text: (str) The text that is displayed at this node's location
+ :param values: List[Any] The list of values that are displayed at this node
+ :param icon: Union[str, bytes]
+ """
+
+ node = self.Node(parent, key, text, values, icon)
+ self.tree_dict[key] = node
+ parent_node = self.tree_dict[parent]
+ parent_node._Add(node)
+
+ def __repr__(self):
+ """
+ Converts the TreeData into a printable version, nicely formatted
+
+ :return: (str) A formatted, text version of the TreeData
+ """
+ return self._NodeStr(self.root_node, 1)
+
+ def _NodeStr(self, node, level):
+ """
+ Does the magic of converting the TreeData into a nicely formatted string version
+
+ :param node: (TreeData.Node) The node to begin printing the tree
+ :param level: (int) The indentation level for string formatting
+ """
+ return '\n'.join(
+ [str(node.key) + ' : ' + str(node.text)] +
+ [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children])
+
+ insert = Insert
+
+
+# ---------------------------------------------------------------------- #
+# Error Element #
+# ---------------------------------------------------------------------- #
+class ErrorElement(Element):
+ """
+ A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid
+ """
+ def __init__(self, key=None, metadata=None):
+ """
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ """
+ self.Key = key
+
+ super().__init__(ELEM_TYPE_ERROR, key=key, metadata=metadata)
+
+
+ def Update(self, silent_on_error=True, *args, **kwargs):
+ """
+ Update method for the Error Element, an element that should not be directly used by developer
+
+ :param silent_on_error: (bool) if False, then a Popup window will be shown
+ :param *args: (Any) meant to "soak up" any normal parameters passed in
+ :param **kwargs: (Any) meant to "soak up" any keyword parameters that were passed in
+ :return: (ErrorElement) returns 'self' so call can be chained
+ """
+ if not silent_on_error:
+ PopupError('Keyword error in Update',
+ 'You need to stop this madness and check your spelling',
+ 'Bad key = {}'.format(self.Key),
+ 'Your bad line of code may resemble this:',
+ 'window.FindElement("{}")'.format(self.Key))
+ return self
+
+ def Get(self):
+ """
+ One of the method names found in other Elements. Used here to return an error string in case it's called
+
+ :return: (str) A warning text string.
+ """
+ return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!'
+
+ get = Get
+ set_focus = Element.SetFocus
+ set_tooltip = Element.SetTooltip
+ update = Update
+
+
+# ---------------------------------------------------------------------- #
+# Stretch Element #
+# ---------------------------------------------------------------------- #
+# This is for source code compatibility with tkinter version. No tkinter equivalent
+Stretch = ErrorElement
+
+
+# ------------------------------------------------------------------------- #
+# Window CLASS #
+# ------------------------------------------------------------------------- #
+class Window:
+ """
+ Represents a single Window
+ """
+ NumOpenWindows = 0
+ user_defined_icon = None
+ hidden_master_root = None
+ animated_popup_dict = {}
+ container_element_counter = 0 # used to get a number of Container Elements (Frame, Column, Tab)
+ read_call_from_debugger = False
+
+ def __init__(self, title, layout=None, default_element_size=DEFAULT_ELEMENT_SIZE,
+ default_button_element_size=(None, None),
+ auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None),
+ element_padding=None, margins=(None, None), button_color=None, font=None,
+ progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False,
+ auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=None, force_toplevel=False,
+ alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False, disable_close=False,
+ disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=True,
+ finalize=False, element_justification='left', metadata=None):
+ """
+ :param title: (str) The title that will be displayed in the Titlebar and on the Taskbar
+ :param layout: List[List[Elements]] The layout for the window. Can also be specified in the Layout method
+ :param default_element_size: Tuple[int, int] (width, height) size in characters (wide) and rows (high) for all elements in this window
+ :param default_button_element_size: Tuple[int, int] (width, height) size in characters (wide) and rows (high) for all Button elements in this window
+ :param auto_size_text: (bool) True if Elements in Window should be sized to exactly fir the length of text
+ :param auto_size_buttons: (bool) True if Buttons in this Window should be sized to exactly fit the text on this.
+ :param location: Tuple[int, int] (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen.
+ :param size: Tuple[int, int] (width, height) size in pixels for this window. Normally the window is autosized to fit contents, not set to an absolute size by the user
+ :param element_padding: Tuple[int, int] or ((int, int),(int,int)) Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom))
+ :param margins: Tuple[int, int] (left/right, top/bottom) Amount of pixels to leave inside the window's frame around the edges before your elements are shown.
+ :param button_color: Tuple[str, str] (text color, button color) Default button colors for all buttons in the window
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param progress_bar_color: Tuple[str, str] (bar color, background color) Sets the default colors for all progress bars in the window
+ :param background_color: (str) color of background
+ :param border_depth: (int) Default border depth (width) for all elements in the window
+ :param auto_close: (bool) If True, the window will automatically close itself
+ :param auto_close_duration: (int) Number of seconds to wait before closing the window
+ :param icon: Union[str, str] Can be either a filename or Base64 value.
+ :param force_toplevel: (bool) If True will cause this window to skip the normal use of a hidden master window
+ :param alpha_channel: (float) Sets the opacity of the window. 0 = invisible 1 = completely visible. Values bewteen 0 & 1 will produce semi-transparent windows in SOME environments (The Raspberry Pi always has this value at 1 and cannot change.
+ :param return_keyboard_events: (bool) if True key presses on the keyboard will be returned as Events from Read calls
+ :param use_default_focus: (bool) If True will use the default focus algorithm to set the focus to the "Correct" element
+ :param text_justification: (str) Union ['left', 'right', 'center'] Default text justification for all Text Elements in window
+ :param no_titlebar: (bool) If true, no titlebar nor frame will be shown on window. This means you cannot minimize the window and it will not show up on the taskbar
+ :param grab_anywhere: (bool) If True can use mouse to click and drag to move the window. Almost every location of the window will work except input fields on some systems
+ :param keep_on_top: (bool) If True, window will be created on top of all other windows on screen. It can be bumped down if another window created with this parm
+ :param resizable: (bool) If True, allows the user to resize the window. Note the not all Elements will change size or location when resizing.
+ :param disable_close: (bool) If True, the X button in the top right corner of the window will no work. Use with caution and always give a way out toyour users
+ :param disable_minimize: (bool) if True the user won't be able to minimize window. Good for taking over entire screen and staying that way.
+ :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
+ :param transparent_color: (str) Any portion of the window that has this color will be completely transparent. You can even click through these spots to the window under this window.
+ :param debugger_enabled: (bool) If True then the internal debugger will be enabled
+ :param finalize: (bool) If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code
+ :param element_justification: (str) All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values
+ :param metadata: (Any) User metadata that can be set to ANYTHING
+ """
+
+ self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT
+ self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS
+ self.Title = str(title)
+ self.Rows = [] # a list of ELEMENTS for this row
+ self.DefaultElementSize = default_element_size
+ self.DefaultButtonElementSize = default_button_element_size if default_button_element_size != (
+ None, None) else DEFAULT_BUTTON_ELEMENT_SIZE
+ self.Location = location
+ self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR
+ self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR
+ self.ParentWindow = None
+ self.Font = font if font else DEFAULT_FONT
+ self.RadioDict = {}
+ self.BorderDepth = border_depth
+ if icon:
+ self.WindowIcon = icon
+ elif Window.user_defined_icon is not None:
+ self.WindowIcon = Window.user_defined_icon
+ else:
+ self.WindowIcon = DEFAULT_WINDOW_ICON
+ self.AutoClose = auto_close
+ self.NonBlocking = False
+ self.TKroot = None
+ self.TKrootDestroyed = False
+ self.CurrentlyRunningMainloop = False
+ self.FormRemainedOpen = False
+ self.TKAfterID = None
+ self.ProgressBarColor = progress_bar_color
+ self.AutoCloseDuration = auto_close_duration
+ self.RootNeedsDestroying = False
+ self.Shown = False
+ self.ReturnValues = None
+ self.ReturnValuesList = []
+ self.ReturnValuesDictionary = {}
+ self.DictionaryKeyCounter = 0
+ self.LastButtonClicked = None
+ self.LastButtonClickedWasRealtime = False
+ self.UseDictionary = False
+ self.UseDefaultFocus = use_default_focus
+ self.ReturnKeyboardEvents = return_keyboard_events
+ self.LastKeyboardEvent = None
+ self.TextJustification = text_justification
+ self.NoTitleBar = no_titlebar
+ self.GrabAnywhere = grab_anywhere
+ self.KeepOnTop = keep_on_top
+ self.ForceTopLevel = force_toplevel
+ self.Resizable = resizable
+ self._AlphaChannel = alpha_channel
+ self.Timeout = None
+ self.TimeoutKey = TIMEOUT_KEY
+ self.TimerCancelled = False
+ self.DisableClose = disable_close
+ self.DisableMinimize = disable_minimize
+ self._Hidden = False
+ self._Size = size
+ self.XFound = False
+ self.ElementPadding = element_padding or DEFAULT_ELEMENT_PADDING
+ self.RightClickMenu = right_click_menu
+ self.Margins = margins if margins != (None, None) else DEFAULT_MARGINS
+ self.ContainerElemementNumber = Window.GetAContainerNumber()
+ self.AllKeysDict = {}
+ self.TransparentColor = transparent_color
+ self.UniqueKeyCounter = 0
+ self.DebuggerEnabled = debugger_enabled
+ self.WasClosed = False
+ self.ElementJustification = element_justification
+ self.FocusSet = False
+ self.metadata = metadata
+ if layout is not None and type(layout) not in (list, tuple):
+ warnings.warn('Your layout is not a list or tuple... this is not good!')
+
+ if layout is not None:
+ self.Layout(layout)
+ if finalize:
+ self.Finalize()
+
+
+ @classmethod
+ def GetAContainerNumber(cls):
+ """
+ Not user callable!
+ :return: A simple counter that makes each container element unique
+ """
+ cls.container_element_counter += 1
+ return cls.container_element_counter
+
+ @classmethod
+ def IncrementOpenCount(self):
+ """
+ Not user callable! Increments the number of open windows
+ Note - there is a bug where this count easily gets out of sync. Issue has been opened already. No ill effects
+ """
+ self.NumOpenWindows += 1
+ # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows))
+
+ @classmethod
+ def DecrementOpenCount(self):
+ """
+ Not user callable! Decrements the number of open windows
+ """
+ self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
+ # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows))
+
+ @classmethod
+ def get_screen_size(self):
+ """
+ Returns the size of the "screen" as determined by tkinter. This can vary depending on your operating system and the number of monitors installed on your system. For Windows, the primary monitor's size is returns. On some multi-monitored Linux systems, the monitors are combined and the total size is reported as if one screen.
+
+ :return: Tuple[int, int] - Size of the screen in pixels as determined by tkinter
+ """
+ root = tk.Tk()
+ screen_width = root.winfo_screenwidth() # get window info to move to middle of screen
+ screen_height = root.winfo_screenheight()
+ root.destroy()
+ return screen_width, screen_height
+
+ # ------------------------- Add ONE Row to Form ------------------------- #
+ def AddRow(self, *args):
+ """
+ Adds a single row of elements to a window's self.Rows variables.
+ Generally speaking this is NOT how users should be building Window layouts.
+ Users, create a single layout (a list of lists) and pass as a parameter to Window object, or call Window.Layout(layout)
+
+ :param *args: List[Elements]
+ """
+ NumRows = len(self.Rows) # number of existing rows is our row number
+ CurrentRowNumber = NumRows # this row's number
+ CurrentRow = [] # start with a blank row and build up
+ # ------------------------- Add the elements to a row ------------------------- #
+ for i, element in enumerate(args): # Loop through list of elements and add them to the row
+ if type(element) == list:
+ PopupError('Error creating layout',
+ 'Layout has a LIST instead of an ELEMENT',
+ 'This means you have a badly placed ]',
+ 'The offensive list is:',
+ element,
+ 'This list will be stripped from your layout'
+ )
+ continue
+ elif callable(element) and not isinstance(element, Element):
+ PopupError('Error creating layout',
+ 'Layout has a FUNCTION instead of an ELEMENT',
+ 'This means you are missing () from your layout',
+ 'The offensive list is:',
+ element,
+ 'This item will be stripped from your layout')
+ continue
+ if element.ParentContainer is not None:
+ warnings.warn('*** YOU ARE ATTEMPTING TO RESUSE A LAYOUT! You must not attempt this kind of re-use ***', UserWarning)
+ PopupError('Error creating layout',
+ 'The layout specified has already been used',
+ 'You MUST start witha "clean", unused layout every time you create a window',
+ 'The offensive Element = ',
+ element,
+ 'and has a key = ', element.Key,
+ 'This item will be stripped from your layout')
+ continue
+ element.Position = (CurrentRowNumber, i)
+ element.ParentContainer = self
+ CurrentRow.append(element)
+ # ------------------------- Append the row to list of Rows ------------------------- #
+ self.Rows.append(CurrentRow)
+
+ # ------------------------- Add Multiple Rows to Form ------------------------- #
+ def AddRows(self, rows):
+ """
+ Loops through a list of lists of elements and adds each row, list, to the layout.
+ This is NOT the best way to go about creating a window. Sending the entire layout at one time and passing
+ it as a parameter to the Window call is better.
+
+ :param rows: List[List[Elements]] A list of a list of elements
+
+ """
+ for row in rows:
+ self.AddRow(*row)
+
+ def Layout(self, rows):
+ """
+ Second of two preferred ways of telling a Window what its layout is. The other way is to pass the layout as
+ a parameter to Window object. The parameter method is the currently preferred method. This call to Layout
+ has been removed from examples contained in documents and in the Demo Programs. Trying to remove this call
+ from history and replace with sending as a parameter to Window.
+
+ :param rows: List[List[Elements]] Your entire layout
+ :return: (Window} self so that you can chain method calls
+ """
+ self.AddRows(rows)
+ self._BuildKeyDict()
+ return self
+
+
+ def LayoutAndRead(self, rows, non_blocking=False):
+ """
+ Deprecated!! Now your layout your window's rows (layout) and then separately call Read.
+
+ :param rows: (List[List[Element]]) The layout of the window
+ :param non_blocking: (bool) if True the Read call will not block
+ """
+ raise DeprecationWarning(
+ 'LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()\nor window(title, layout).Read()')
+ # self.AddRows(rows)
+ # self._Show(non_blocking=non_blocking)
+ # return self.ReturnValues
+
+ def LayoutAndShow(self, rows):
+ """
+ Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read
+ :param rows:
+ """
+ raise DeprecationWarning('LayoutAndShow is no longer supported... ')
+
+
+ def _Show(self, non_blocking=False):
+ """
+ NOT TO BE CALLED BY USERS. INTERNAL ONLY!
+ It's this method that first shows the window to the user, collects results
+
+ :param non_blocking: (bool) if True, this is a non-blocking call
+ :return: Tuple[Any, Dict] The event, values turple that is returned from Read calls
+ """
+ self.Shown = True
+ # Compute num rows & num cols (it'll come in handy debugging)
+ self.NumRows = len(self.Rows)
+ self.NumCols = max(len(row) for row in self.Rows)
+ self.NonBlocking = non_blocking
+
+ # Search through entire form to see if any elements set the focus
+ # if not, then will set the focus to the first input element
+ found_focus = False
+ for row in self.Rows:
+ for element in row:
+ try:
+ if element.Focus:
+ found_focus = True
+ except:
+ pass
+ try:
+ if element.Key is not None:
+ self.UseDictionary = True
+ except:
+ pass
+
+ if not found_focus and self.UseDefaultFocus:
+ self.UseDefaultFocus = True
+ else:
+ self.UseDefaultFocus = False
+ # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ##
+ StartupTK(self)
+ # If a button or keyboard event happened but no results have been built, build the results
+ if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None:
+ return _BuildResults(self, False, self)
+ return self.ReturnValues
+
+ # ------------------------- SetIcon - set the window's fav icon ------------------------- #
+ def SetIcon(self, icon=None, pngbase64=None):
+ """
+ Sets the icon that is shown on the title bar and on the task bar. Can pass in:
+ * a filename which must be a .ICO icon file for windows
+ * a bytes object
+ * a BASE64 encoded file held in a variable
+
+ :param icon: (str) Filename or bytes object
+ :param pngbase64: (str) Base64 encoded GIF or PNG file
+ """
+ if type(icon) is bytes or pngbase64 is not None:
+ wicon = tkinter.PhotoImage(data=icon if icon is not None else pngbase64)
+ try:
+ self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
+ except:
+ wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
+ try:
+ self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
+ except:
+ pass
+ self.WindowIcon = wicon
+ return
+
+ try:
+ self.TKroot.iconbitmap(icon)
+ wicon = icon
+ except:
+ try:
+ wicon = tkinter.PhotoImage(file=icon)
+ self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
+ except:
+ try:
+ wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
+ try:
+ self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
+ except:
+ pass
+ except:
+ pass
+ self.WindowIcon = wicon
+
+
+ def _GetElementAtLocation(self, location):
+ """
+ Given a (row, col) location in a layout, return the element located at that position
+
+ :param location: Tuple[int, int] Return the element located at (row, col) in layout
+ :return: (Element) The Element located at that position in this window
+ """
+
+ (row_num, col_num) = location
+ row = self.Rows[row_num]
+ element = row[col_num]
+ return element
+
+ def _GetDefaultElementSize(self):
+ """
+ Returns the default elementSize
+
+ :return: Tuple[int, int] (width, height) of the default element size
+ """
+
+ return self.DefaultElementSize
+
+ def _AutoCloseAlarmCallback(self):
+ """
+ Function that's called by tkinter when autoclode timer expires. Closes the window
+
+ """
+ try:
+ window = self
+ if window:
+ if window.NonBlocking:
+ self.CloseNonBlockingForm()
+ else:
+ window._Close()
+ self.TKroot.quit()
+ self.RootNeedsDestroying = True
+ except:
+ pass
+
+ def _TimeoutAlarmCallback(self):
+ """
+ Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return
+ """
+ # first, get the results table built
+ # modify the Results table in the parent FlexForm object
+ # print('TIMEOUT CALLBACK')
+ if self.TimerCancelled:
+ # print('** timer was cancelled **')
+ return
+ self.LastButtonClicked = self.TimeoutKey
+ self.FormRemainedOpen = True
+ self.TKroot.quit() # kick the users out of the mainloop
+
+
+ def Read(self, timeout=None, timeout_key=TIMEOUT_KEY):
+ # type: (int, Any) -> Tuple[Any, Union[Dict, List]]
+ """
+ THE biggest deal method in the Window class! This is how you get all of your data from your Window.
+ Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key
+ if no other GUI events happen first.
+
+ :param timeout: (int) Milliseconds to wait until the Read will return IF no other GUI events happen first
+ :param timeout_key: (Any) The value that will be returned from the call if the timer expired
+ :return: Tuple[(Any), Union[Dict[Any:Any]], List[Any], None] (event, values)
+ (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window)
+ """
+ # ensure called only 1 time through a single read cycle
+ if not Window.read_call_from_debugger:
+ _refresh_debugger()
+ timeout = int(timeout) if timeout is not None else None
+ if timeout == 0: # timeout of zero runs the old readnonblocking
+ event, values = self._ReadNonBlocking()
+ if event is None:
+ event = timeout_key
+ if values is None:
+ event = None
+ return event, values # make event None if values was None and return
+ # Read with a timeout
+ self.Timeout = timeout
+ self.TimeoutKey = timeout_key
+ self.NonBlocking = False
+ if self.TKrootDestroyed:
+ return None, None
+ if not self.Shown:
+ self._Show()
+ else:
+ # if already have a button waiting, the return previously built results
+ if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime:
+ # print(f'*** Found previous clicked saved {self.LastButtonClicked}')
+ results = _BuildResults(self, False, self)
+ self.LastButtonClicked = None
+ return results
+ InitializeResults(self)
+ # if the last button clicked was realtime, emulate a read non-blocking
+ # the idea is to quickly return realtime buttons without any blocks until released
+ if self.LastButtonClickedWasRealtime:
+ self.LastButtonClickedWasRealtime = False # stops from generating events until something changes
+
+ # print(f'RTime down {self.LastButtonClicked}' )
+ try:
+ rc = self.TKroot.update()
+ except:
+ self.TKrootDestroyed = True
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ # print('ROOT Destroyed')
+ results = _BuildResults(self, False, self)
+ if results[0] != None and results[0] != timeout_key:
+ return results
+ else:
+ pass
+
+ # else:
+ # print("** REALTIME PROBLEM FOUND **", results)
+
+ if self.RootNeedsDestroying:
+ # print('*** DESTROYING really late***')
+ try:
+ self.TKroot.destroy()
+ except:
+ pass
+ # _my_windows.Decrement()
+ self.LastButtonClicked = None
+ return None, None
+
+ # normal read blocking code....
+ if timeout != None:
+ self.TimerCancelled = False
+ self.TKAfterID = self.TKroot.after(timeout, self._TimeoutAlarmCallback)
+ self.CurrentlyRunningMainloop = True
+ # print(f'In main {self.Title} {self.TKroot}')
+ # self.TKroot.protocol("WM_DESTROY_WINDOW", self._OnClosingCallback)
+ # self.TKroot.protocol("WM_DELETE_WINDOW", self._OnClosingCallback)
+ self.TKroot.mainloop()
+ # print('Out main')
+ self.CurrentlyRunningMainloop = False
+ # if self.LastButtonClicked != TIMEOUT_KEY:
+ # print(f'Window {self.Title} Last button clicked = {self.LastButtonClicked}')
+ try:
+ self.TKroot.after_cancel(self.TKAfterID)
+ del self.TKAfterID
+ except:
+ pass
+ # print('** tkafter cancel failed **')
+ self.TimerCancelled = True
+ if self.RootNeedsDestroying:
+ # print('*** DESTROYING LATE ***')
+ try:
+ self.TKroot.destroy()
+ except:
+ pass
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ self.LastButtonClicked = None
+ return None, None
+ # if form was closed with X
+ if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None:
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ # Determine return values
+ if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None:
+ results = _BuildResults(self, False, self)
+ if not self.LastButtonClickedWasRealtime:
+ self.LastButtonClicked = None
+ return results
+ else:
+ if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[
+ 0] is None: # Special Qt case because returning for no reason so fake timeout
+ self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
+ elif not self.XFound and self.ReturnValues[0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction
+ # print("*** Faking timeout ***")
+ self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
+ return self.ReturnValues
+
+
+ def _ReadNonBlocking(self):
+ """
+ Should be NEVER called directly by the user. The user can call Window.Read(timeout=0) to get same effect
+
+ :return: Tuple[(Any), Union[Dict[Any:Any], List[Any], None] (event, values)
+ (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window
+ """
+ if self.TKrootDestroyed:
+ try:
+ self.TKroot.quit()
+ self.TKroot.destroy()
+ except:
+ pass
+ # print('DESTROY FAILED')
+ return None, None
+ if not self.Shown:
+ self._Show(non_blocking=True)
+ try:
+ rc = self.TKroot.update()
+ except:
+ self.TKrootDestroyed = True
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ # print("read failed")
+ # return None, None
+ if self.RootNeedsDestroying:
+ # print('*** DESTROYING LATE ***', self.ReturnValues)
+ self.TKroot.destroy()
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ self.Values = None
+ self.LastButtonClicked = None
+ return None, None
+ return _BuildResults(self, False, self)
+
+
+ def Finalize(self):
+ """
+ Use this method to cause your layout to built into a real tkinter window. In reality this method is like
+ Read(timeout=0). It doesn't block and uses your layout to create tkinter widgets to represent the elements.
+ Lots of action!
+
+ :return: (Window) Returns 'self' so that method "Chaining" can happen (read up about it as it's very cool!)
+ """
+
+ if self.TKrootDestroyed:
+ return self
+ self.Read(timeout=1)
+ return self
+ # OLD CODE FOLLOWS
+ if not self.Shown:
+ self._Show(non_blocking=True)
+ try:
+ rc = self.TKroot.update()
+ except:
+ self.TKrootDestroyed = True
+ Window.DecrementOpenCount()
+ print('** Finalize failed **')
+ # _my_windows.Decrement()
+ # return None, None
+ return self
+
+
+ def Refresh(self):
+ """
+ Refreshes the window by calling tkroot.update(). Can sometimes get away with a refresh instead of a Read.
+ Use this call when you want something to appear in your Window immediately (as soon as this function is called).
+ Without this call your changes to a Window will not be visible to the user until the next Read call
+
+ :return: (Window) `self` so that method calls can be easily "chained"
+ """
+
+ if self.TKrootDestroyed:
+ return self
+ try:
+ rc = self.TKroot.update()
+ except:
+ pass
+ return self
+
+
+ def Fill(self, values_dict):
+ """
+ Fill in elements that are input fields with data based on a 'values dictionary'
+
+ :param values_dict: (Dict[Any:Any]) {Element key : value} pairs
+ :return: (Window) returns self so can be chained with other methods
+ """
+
+ FillFormWithValues(self, values_dict)
+ return self
+
+
+ def FindElement(self, key, silent_on_error=False):
+ """
+ Find element object associated with the provided key.
+ THIS METHOD IS NO LONGER NEEDED to be called by the user
+
+ You can perform the same operation by writing this statement:
+ element = window[key]
+
+ You can drop the entire "FindElement" function name and use [ ] instead.
+
+ Typically used in combination with a call to element's Update method (or any other element method!):
+ window[key].Update(new_value)
+
+ Versus the "old way"
+ window.FindElement(key).Update(new_value)
+
+ This call can be abbreviated to any of these:
+ FindElement == Element == Find
+ Rememeber that this call will return None if no match is found which may cause your code to crash if not
+ checked for.
+
+ :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element
+ :param silent_on_error: (bool) If True do not display popup nor print warning of key errors
+
+ :return: Union[Element, Error Element, None] Return value can be:
+ * the Element that matches the supplied key if found
+ * an Error Element if silent_on_error is False
+ * None if silent_on_error True
+ """
+ try:
+ element = self.AllKeysDict[key]
+ except KeyError:
+ element = None
+ if not silent_on_error:
+ warnings.warn(
+ '*** WARNING = FindElement did not find the key. Please check your key\'s spelling key = %s ***' % key, UserWarning)
+ PopupError('Keyword error in FindElement Call',
+ 'Bad key = {}'.format(key),
+ 'Your bad line of code may resemble this:',
+ 'window.FindElement("{}")'.format(key))
+ element = ErrorElement(key=key)
+ return element
+
+ Element = FindElement # Shortcut function
+ Find = FindElement # Shortcut function, most likely not used by many people.
+ Elem = FindElement # NEW for 2019! More laziness... Another shortcut
+
+ def FindElementWithFocus(self):
+ """
+ Returns the Element that currently has focus as reported by tkinter. If no element is found None is returned!
+ :return: Union[Element, None] An Element if one has been found with focus or None if no element found
+ """
+ element = _FindElementWithFocusInSubForm(self)
+ return element
+
+ def _BuildKeyDict(self):
+ """
+ Used internally only! Not user callable
+ Builds a dictionary containing all elements with keys for this window.
+ """
+ dict = {}
+ self.AllKeysDict = self._BuildKeyDictForWindow(self, self, dict)
+ # print(f'keys built = {self.AllKeysDict}')
+
+ def _BuildKeyDictForWindow(self, top_window, window, key_dict):
+ """
+ Loop through all Rows and all Container Elements for this window and create the keys for all of them.
+ Note that the calls are recursive as all pathes must be walked
+
+ :param top_window: (Window) The highest level of the window
+ :param window: Union[Column, Frame, TabGroup, Pane, Tab] The "sub-window" (container element) to be searched
+ :param key_dict: The dictionary as it currently stands.... used as part of recursive call
+ :return: (dict) Dictionary filled with all keys in the window
+ """
+ for row_num, row in enumerate(window.Rows):
+ for col_num, element in enumerate(row):
+ if element.Type == ELEM_TYPE_COLUMN:
+ key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
+ if element.Type == ELEM_TYPE_FRAME:
+ key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
+ if element.Type == ELEM_TYPE_TAB_GROUP:
+ key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
+ if element.Type == ELEM_TYPE_PANE:
+ key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
+ if element.Type == ELEM_TYPE_TAB:
+ key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
+ if element.Key is None: # if no key has been assigned.... create one for input elements
+ if element.Type == ELEM_TYPE_BUTTON:
+ element.Key = element.ButtonText
+ elif element.Type == ELEM_TYPE_TAB:
+ element.Key = element.Title
+ if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU, ELEM_TYPE_CANVAS,
+ ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE,
+ ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO,
+ ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN,
+ ELEM_TYPE_INPUT_RADIO, ELEM_TYPE_INPUT_TEXT):
+ element.Key = top_window.DictionaryKeyCounter
+ top_window.DictionaryKeyCounter += 1
+ if element.Key is not None:
+ if element.Key in key_dict.keys():
+ print('*** Duplicate key found in your layout {} ***'.format(
+ element.Key)) if element.Type != ELEM_TYPE_BUTTON else None
+ element.Key = str(element.Key) + str(self.UniqueKeyCounter)
+ self.UniqueKeyCounter += 1
+ print('*** Replaced new key with {} ***'.format(
+ element.Key)) if element.Type != ELEM_TYPE_BUTTON else None
+ key_dict[element.Key] = element
+ return key_dict
+
+ def SaveToDisk(self, filename):
+ """
+ Saves the values contained in each of the input areas of the form. Basically saves what would be returned
+ from a call to Read. It takes these results and saves them to disk using pickle
+
+ :param filename: (str) Filename to save the values to in pickled form
+ """
+ try:
+ event, values = _BuildResults(self, False, self)
+ remove_these = []
+ for key in values:
+ if self.Element(key).Type == ELEM_TYPE_BUTTON:
+ remove_these.append(key)
+ for key in remove_these:
+ del values[key]
+ with open(filename, 'wb') as sf:
+ pickle.dump(values, sf)
+ except:
+ print('*** Error saving Window contents to disk ***')
+
+ def LoadFromDisk(self, filename):
+ """
+ Restore values from a previous call to SaveToDisk which saves the returned values dictionary in Pickle format
+
+ :param filename: (str) Pickle Filename to load
+ """
+ try:
+ with open(filename, 'rb') as df:
+ self.Fill(pickle.load(df))
+ except:
+ print('*** Error loading form to disk ***')
+
+
+ def GetScreenDimensions(self):
+ """
+ Get the screen dimensions. NOTE - you must have a window already open for this to work (blame tkinter not me)
+
+ :return: Union[Tuple[None, None], Tuple[width, height]] Tuple containing width and height of screen in pixels
+ """
+ if self.TKrootDestroyed:
+ return Window.get_screen_size()
+ screen_width = self.TKroot.winfo_screenwidth() # get window info to move to middle of screen
+ screen_height = self.TKroot.winfo_screenheight()
+ return screen_width, screen_height
+
+ def Move(self, x, y):
+ """
+ Move the upper left corner of this window to the x,y coordinates provided
+ :param x: (int) x coordinate in pixels
+ :param y: (int) y coordinate in pixels
+ """
+ try:
+ self.TKroot.geometry("+%s+%s" % (x, y))
+ except:
+ pass
+
+ def Minimize(self):
+ """
+ Minimize this window to the task bar
+ """
+ self.TKroot.iconify()
+
+ def Maximize(self):
+ """
+ Maximize the window. This is done differently on a windows system versus a linux or mac one. For non-Windows
+ the root attribute '-fullscreen' is set to True. For Windows the "root" state is changed to "zoomed"
+ The reason for the difference is the title bar is removed in some cases when using fullscreen option
+ """
+ if sys.platform != 'linux':
+ self.TKroot.state('zoomed')
+ else:
+ self.TKroot.attributes('-fullscreen', True)
+ # this method removes the titlebar too
+ # self.TKroot.attributes('-fullscreen', True)
+
+ def Normal(self):
+ """
+ Restore a window to a non-maximized state. Does different things depending on platform. See Maximize for more.
+ """
+ if self.TKroot.state() == 'iconic':
+ self.TKroot.deiconify()
+ else:
+ if sys.platform != 'linux':
+ self.TKroot.state('normal')
+ else:
+ self.TKroot.attributes('-fullscreen', False)
+
+ def _StartMove(self, event):
+ """
+ Used by "Grab Anywhere" style windows. This function is bound to mouse-down. It marks the beginning of a drag.
+ :param event: (event) event information passed in by tkinter. Contains x,y position of mouse
+ """
+ try:
+ self.TKroot.x = event.x
+ self.TKroot.y = event.y
+ except:
+ pass
+ # print('Start move {},{}'.format(event.x,event.y))
+
+
+ def _StopMove(self, event):
+ """
+ Used by "Grab Anywhere" style windows. This function is bound to mouse-up. It marks the ending of a drag.
+ Sets the position of the window to this final x,y coordinates
+ :param event: (event) event information passed in by tkinter. Contains x,y position of mouse
+ """
+ try:
+ self.TKroot.x = None
+ self.TKroot.y = None
+ except:
+ pass
+ # print('-Stop- move {},{}'.format(event.x,event.y))
+
+ def _OnMotion(self, event):
+ """
+ Used by "Grab Anywhere" style windows. This function is bound to mouse motion. It actually moves the window
+ :param event: (event) event information passed in by tkinter. Contains x,y position of mouse
+ """
+ try:
+ deltax = event.x - self.TKroot.x
+ deltay = event.y - self.TKroot.y
+ x = self.TKroot.winfo_x() + deltax
+ y = self.TKroot.winfo_y() + deltay
+ self.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window
+ # print('{},{}'.format(x,y))
+ except:
+ pass
+
+
+ def _KeyboardCallback(self, event):
+ """
+ Window keyboard callback. Called by tkinter. Will kick user out of the tkinter event loop. Should only be
+ called if user has requested window level keyboard events
+
+ :param event: (event) object provided by tkinter that contains the key information
+ """
+ self.LastButtonClicked = None
+ self.FormRemainedOpen = True
+ if event.char != '':
+ self.LastKeyboardEvent = event.char
+ else:
+ self.LastKeyboardEvent = str(event.keysym) + ':' + str(event.keycode)
+ if not self.NonBlocking:
+ _BuildResults(self, False, self)
+ if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
+ self.TKroot.quit()
+
+ def _MouseWheelCallback(self, event):
+ """
+ Called by tkinter when a mouse wheel event has happened. Only called if keyboard events for the window
+ have been enabled
+
+ :param event: (event) object sent in by tkinter that has the wheel direction
+ """
+ self.LastButtonClicked = None
+ self.FormRemainedOpen = True
+ self.LastKeyboardEvent = 'MouseWheel:Down' if event.delta < 0 else 'MouseWheel:Up'
+ if not self.NonBlocking:
+ _BuildResults(self, False, self)
+ if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
+ self.TKroot.quit()
+
+ def _Close(self):
+ """
+ The internal close call that does the real work of building. This method basically sets up for closing
+ but doesn't destroy the window like the User's version of Close does
+ """
+ try:
+ self.TKroot.update()
+ except:
+ pass
+ if not self.NonBlocking:
+ _BuildResults(self, False, self)
+ if self.TKrootDestroyed:
+ return
+ self.TKrootDestroyed = True
+ self.RootNeedsDestroying = True
+ return
+
+ def Close(self):
+ """
+ Closes window. Users can safely call even if window has been destroyed. Should always call when done with
+ a window so that resources are properly freed up within your thread.
+ """
+ if self.TKrootDestroyed:
+ return
+ try:
+ self.TKroot.destroy()
+ Window.DecrementOpenCount()
+ except:
+ pass
+ # if down to 1 window, try and destroy the hidden window, if there is one
+ if Window.NumOpenWindows == 1:
+ try:
+ Window.hidden_master_root.destroy()
+ Window.NumOpenWindows = 0 # if no hidden window, then this won't execute
+ except:
+ pass
+ self.TKrootDestroyed = True
+ del self.TKroot
+ del self.Rows
+
+
+ # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
+ def _OnClosingCallback(self):
+ """
+ Internally used method ONLY. Not sure callable. tkinter calls this when the window is closed by clicking X
+ """
+ # global _my_windows
+ # print('Got closing callback', self.DisableClose)
+ if self.DisableClose:
+ return
+ self.XFound = True
+ if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
+ self.TKroot.quit() # kick the users out of the mainloop
+ self.TKroot.destroy() # kick the users out of the mainloop
+ self.RootNeedsDestroying = True
+ self.TKrootDestroyed = True
+ else:
+ self.TKroot.destroy() # kick the users out of the mainloop
+ self.RootNeedsDestroying = True
+ self.RootNeedsDestroying = True
+
+
+ def Disable(self):
+ """
+ Disables window from taking any input from the user
+ """
+ self.TKroot.attributes('-disabled', 1)
+ # self.TKroot.grab_set_global()
+
+ def Enable(self):
+ """
+ Re-enables window to take user input after having it be Disabled previously
+ """
+ self.TKroot.attributes('-disabled', 0)
+ # self.TKroot.grab_release()
+
+
+ def Hide(self):
+ """
+ Hides the window from the screen and the task bar
+ """
+ self._Hidden = True
+ self.TKroot.withdraw()
+
+ def UnHide(self):
+ """
+ Used to bring back a window that was previously hidden using the Hide method
+ """
+ if self._Hidden:
+ self.TKroot.deiconify()
+ self._Hidden = False
+
+
+ def Disappear(self):
+ """
+ Causes a window to "disappear" from the screen, but remain on the taskbar. It does this by turning the alpha
+ channel to 0. NOTE that on some platforms alpha is not supported. The window will remain showing on these
+ platforms. The Raspberry Pi for example does not have an alpha setting
+ """
+ self.TKroot.attributes('-alpha', 0)
+
+ def Reappear(self):
+ """
+ Causes a window previously made to "Disappear" (using that method). Does this by restoring the alpha channel
+ """
+ self.TKroot.attributes('-alpha', 255)
+
+ def SetAlpha(self, alpha):
+ """
+ Sets the Alpha Channel for a window. Values are between 0 and 1 where 0 is completely transparent
+
+ :param alpha: (float) 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through)
+ """
+ # Change the window's transparency
+ # :param alpha: From 0 to 1 with 0 being completely transparent
+ self._AlphaChannel = alpha
+ self.TKroot.attributes('-alpha', alpha)
+
+ @property
+ def AlphaChannel(self):
+ """
+ A property that changes the current alpha channel value (internal value)
+ :return: (float) the current alpha channel setting according to self, not read directly from tkinter
+ """
+ return self._AlphaChannel
+
+ @AlphaChannel.setter
+ def AlphaChannel(self, alpha):
+ """
+ The setter method for this "property".
+ Planning on depricating so that a Set call is always used by users. This is more in line with the SDK
+ :param alpha: (float) 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through)
+ """
+ self._AlphaChannel = alpha
+ self.TKroot.attributes('-alpha', alpha)
+
+
+ def BringToFront(self):
+ """
+ Brings this window to the top of all other windows (perhaps may not be brought before a window made to "stay
+ on top")
+ """
+ try:
+ self.TKroot.lift()
+ except:
+ pass
+
+ def CurrentLocation(self):
+ """
+ Get the current location of the window's top left corner
+
+ :return: Tuple[(int), (int)] The x and y location in tuple form (x,y)
+ """
+ return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y())
+
+
+ @property
+ def Size(self):
+ """
+ Return the current size of the window in pixels
+
+ :return: Tuple[(int), (int)] the (width, height) of the window
+ """
+ win_width = self.TKroot.winfo_width()
+ win_height = self.TKroot.winfo_height()
+ return win_width, win_height
+
+ @Size.setter
+ def Size(self, size):
+ """
+ Changes the size of the window, if possible
+
+ :param size: Tuple[int, int] (width, height) of the desired window size
+ """
+ try:
+ self.TKroot.geometry("%sx%s" % (size[0], size[1]))
+ self.TKroot.update_idletasks()
+ except:
+ pass
+
+ def VisibilityChanged(self):
+ """
+ Not used in tkinter, but supplied becuase it is used in Qt. Want to remain source code compatible so that if
+ you are making this call in your PySimpleGUIQt code, you can switch to PySimpleGUI and it will not complain
+ about a missing method. Just know that in this version of PySimpleGUI, it does nothing
+ """
+ # A dummy function. Needed in Qt but not tkinter
+ return
+
+
+ def SetTransparentColor(self, color):
+ """
+ Set the color that will be transparent in your window. Areas with this color will be SEE THROUGH.
+
+ :param color: (str) Color string that defines the transparent color
+ """
+ try:
+ self.TKroot.attributes('-transparentcolor', color)
+ except:
+ print('Transparent color not supported on this platform (windows only)')
+
+ def GrabAnyWhereOn(self):
+ """
+ Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
+ been Finalized or Read.
+ """
+ self.TKroot.bind("", self._StartMove)
+ self.TKroot.bind("", self._StopMove)
+ self.TKroot.bind("", self._OnMotion)
+
+ def GrabAnyWhereOff(self):
+ """
+ Turns off Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
+ been Finalized or Read.
+ """
+ self.TKroot.unbind("")
+ self.TKroot.unbind("")
+ self.TKroot.unbind("")
+
+
+ def _callback_main_debugger_window_create_keystroke(self, event):
+ """
+ Called when user presses the key that creates the main debugger window
+
+ :param event: (event) not used. Passed in event info
+ """
+ _Debugger.debugger._build_main_debugger_window()
+
+ def _callback_popout_window_create_keystroke(self, event):
+ """
+ Called when user presses the key that creates the floating debugger window
+
+ :param event: (event) not used. Passed in event info
+ """
+ _Debugger.debugger._build_floating_window()
+
+ def EnableDebugger(self):
+ """
+ Enables the internal debugger. By default, the debugger IS enabled
+ """
+ self.TKroot.bind('', self._callback_main_debugger_window_create_keystroke)
+ self.TKroot.bind('', self._callback_popout_window_create_keystroke)
+ self.DebuggerEnabled = True
+
+
+ def DisableDebugger(self):
+ """
+ Disable the internal debugger. By default the debugger is ENABLED
+ """
+ self.TKroot.unbind("")
+ self.TKroot.unbind("")
+ self.DebuggerEnabled = False
+
+
+ def VisibilityChanged(self):
+ """
+ This is a completely dummy method that does nothing. It is here so that PySimpleGUIQt programs can make this
+ call and then have that same source run on plain PySimpleGUI.
+ :return:
+ """
+ return
+
+
+
+ # def __enter__(self):
+ # """
+ # WAS used with context managers which are no longer needed nor advised. It is here for legacy support and
+ # am afraid of removing right now
+ # :return: (window)
+ # """
+ # return self
+
+ def __getitem__(self, key):
+ """
+ Returns Element that matches the passed in key.
+ This is "called" by writing code as thus:
+ window['element key'].Update
+
+ :param key: (Any) The key to find
+ :return: Union[Element, None] The element found or None if no element was found
+ """
+ try:
+ return self.FindElement(key)
+ except Exception as e:
+ warnings.warn('The key you passed in is no good. Key = {}*'.format(key))
+ return None
+
+
+ def __call__(self, *args, **kwargs):
+ """
+ Call window.Read but without having to type it out.
+ window() == window.Read()
+ window(timeout=50) == window.Read(timeout=50)
+
+ :param args:
+ :param kwargs:
+ :return: Tuple[Any, Dict[Any:Any]] The famous event, values that Read returns.
+ """
+ return self.Read(*args, **kwargs)
+
+
+ add_row = AddRow
+ add_rows = AddRows
+ alpha_channel = AlphaChannel
+ bring_to_front = BringToFront
+ close = Close
+ current_location = CurrentLocation
+ disable = Disable
+ disable_debugger = DisableDebugger
+ disappear = Disappear
+ elem = Elem
+ element = Element
+ enable = Enable
+ enable_debugger = EnableDebugger
+ fill = Fill
+ finalize = Finalize
+ find = Find
+ find_element = FindElement
+ find_element_with_focus = FindElementWithFocus
+ get_screen_dimensions = GetScreenDimensions
+ grab_any_where_off = GrabAnyWhereOff
+ grab_any_where_on = GrabAnyWhereOn
+ hide = Hide
+ layout = Layout
+ load_from_disk = LoadFromDisk
+ maximize = Maximize
+ minimize = Minimize
+ move = Move
+ normal = Normal
+ read = Read
+ reappear = Reappear
+ refresh = Refresh
+ save_to_disk = SaveToDisk
+ set_alpha = SetAlpha
+ set_icon = SetIcon
+ set_transparent_color = SetTransparentColor
+ size = Size
+ un_hide = UnHide
+ visibility_changed = VisibilityChanged
+
+ #
+ # def __exit__(self, *a):
+ # """
+ # WAS used with context managers which are no longer needed nor advised. It is here for legacy support and
+ # am afraid of removing right now
+ # :param *a: (?) Not sure what's passed in.
+ # :return: Always returns False which was needed for context manager to work
+ # """
+ # self.__del__()
+ # return False
+ #
+ # def __del__(self):
+ # """ """
+ # # print('DELETING WINDOW')
+ # for row in self.Rows:
+ # for element in row:
+ # element.__del__()
+# -------------------------------- PEP8-ify the Window Class USER Interfaces -------------------------------- #
+
+
+FlexForm = Window
+Window.CloseNonBlockingForm = Window.Close
+Window.CloseNonBlocking = Window.Close
+
+# ################################################################################
+# ################################################################################
+# END OF ELEMENT DEFINITIONS
+# ################################################################################
+# ################################################################################
+
+
+# =========================================================================== #
+# Button Lazy Functions so the caller doesn't have to define a bunch of stuff #
+# =========================================================================== #
+
+# ------------------------- A fake Element... the Pad Element ------------------------- #
+def Sizer(h_pixels=0, v_pixels=0):
+ """
+ "Pushes" out the size of whatever it is placed inside of. This includes Columns, Frames, Tabs and Windows
+
+ :param h_pixels: (int) number of horizontal pixels
+ :param v_pixels: (int) number of vertical pixels
+ :return: (Column) A column element that has a pad setting set according to parameters
+ """
+
+ return Column([[]], pad=((h_pixels,0),(v_pixels,0)))
+
+# ------------------------- FOLDER BROWSE Element lazy function ------------------------- #
+def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None),
+ auto_size_button=None, button_color=None, disabled=False, change_submits=False, enable_events=False,
+ font=None, pad=None, key=None, metadata=None):
+ """
+ :param button_text: text in the button (Default value = 'Browse')
+ :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
+ :param initial_folder: starting path for folders and files
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param change_submits: If True, pressing Enter key submits window (Default = False)
+ :param enable_events: Turns on the element specific events.(Default = False)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target,
+ initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button,
+ disabled=disabled, button_color=button_color, change_submits=change_submits,
+ enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- FILE BROWSE Element lazy function ------------------------- #
+def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None,
+ tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False,
+ enable_events=False, font=None, disabled=False,
+ pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Browse')
+ :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
+ :param file_types: (Default value = (("ALL Files", "*.*")))
+ :param initial_folder: starting path for folders and files
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param change_submits: If True, pressing Enter key submits window (Default = False)
+ :param enable_events: Turns on the element specific events.(Default = False)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param disabled: set disable state for element (Default = False)
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types,
+ initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button,
+ change_submits=change_submits, enable_events=enable_events, disabled=disabled,
+ button_color=button_color, font=font, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- #
+def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), disabled=False,
+ initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None,
+ change_submits=False, enable_events=False,
+ font=None, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Browse')
+ :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
+ :param file_types: (Default value = (("ALL Files", "*.*")))
+ :param disabled: set disable state for element (Default = False)
+ :param initial_folder: starting path for folders and files
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param change_submits: If True, pressing Enter key submits window (Default = False)
+ :param enable_events: Turns on the element specific events.(Default = False)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types,
+ initial_folder=initial_folder, change_submits=change_submits, enable_events=enable_events,
+ tooltip=tooltip, size=size, auto_size_button=auto_size_button,
+ disabled=disabled, button_color=button_color, font=font, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- FILE BROWSE Element lazy function ------------------------- #
+def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None,
+ disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None,
+ change_submits=False, enable_events=False, font=None,
+ pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Save As...')
+ :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
+ :param file_types: (Default value = (("ALL Files", "*.*")))
+ :param initial_folder: starting path for folders and files
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param change_submits: If True, pressing Enter key submits window (Default = False)
+ :param enable_events: Turns on the element specific events.(Default = False)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types,
+ initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled,
+ auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits,
+ enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- SAVE AS Element lazy function ------------------------- #
+def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None,
+ disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None,
+ change_submits=False, enable_events=False, font=None,
+ pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Save As...')
+ :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
+ :param file_types: (Default value = (("ALL Files", "*.*")))
+ :param initial_folder: starting path for folders and files
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param change_submits: If True, pressing Enter key submits window (Default = False)
+ :param enable_events: Turns on the element specific events.(Default = False)
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types,
+ initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled,
+ auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits,
+ enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- SAVE BUTTON Element lazy function ------------------------- #
+def Save(button_text='Save', size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True,
+ disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Save')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param bind_return_key: (Default = True)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- #
+def Submit(button_text='Submit', size=(None, None), auto_size_button=None, button_color=None, disabled=False,
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Submit')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = True)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- OPEN BUTTON Element lazy function ------------------------- #
+# ------------------------- OPEN BUTTON Element lazy function ------------------------- #
+def Open(button_text='Open', size=(None, None), auto_size_button=None, button_color=None, disabled=False,
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Open')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = True)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- OK BUTTON Element lazy function ------------------------- #
+def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color=None, disabled=False,
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'OK')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = True)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- YES BUTTON Element lazy function ------------------------- #
+def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color=None, disabled=False,
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Ok')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = True)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- CANCEL BUTTON Element lazy function ------------------------- #
+def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, button_color=None, disabled=False,
+ tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Cancel')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- QUIT BUTTON Element lazy function ------------------------- #
+def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
+ font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Quit')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- Exit BUTTON Element lazy function ------------------------- #
+def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
+ font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Exit')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- YES BUTTON Element lazy function ------------------------- #
+def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
+ font=None, bind_return_key=True, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Yes')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = True)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- NO BUTTON Element lazy function ------------------------- #
+def No(button_text='No', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
+ font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'No')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- NO BUTTON Element lazy function ------------------------- #
+def Help(button_text='Help', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None,
+ tooltip=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = 'Help')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param font: specifies the font family, size, etc
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- NO BUTTON Element lazy function ------------------------- #
+def Debug(button_text='', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None,
+ tooltip=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button (Default value = '')
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param font: specifies the font family, size, etc
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_SHOW_DEBUGGER, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=COLOR_SYSTEM_DEFAULT, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, image_data=PSG_DEBUGGER_LOGO,
+ image_subsample=4, border_width=0, metadata=metadata)
+
+
+# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
+def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
+ border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None,
+ font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: size of button image in pixels
+ :param image_subsample:amount to reduce the size of the image
+ :param border_width: width of border around element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param disabled: set disable state for element (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename,
+ image_data=image_data, image_size=image_size, image_subsample=image_subsample,
+ border_width=border_width, tooltip=tooltip, disabled=disabled, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- CLOSE BUTTON Element lazy function ------------------------- #
+def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
+ border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None,
+ bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: size of button image in pixels
+ :param image_subsample:amount to reduce the size of the image
+ :param border_width: width of border around element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param disabled: set disable state for element (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename,
+ image_data=image_data, image_size=image_size, image_subsample=image_subsample,
+ border_width=border_width, tooltip=tooltip, disabled=disabled, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+CButton = CloseButton
+
+
+# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
+def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
+ border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None,
+ bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: size of button image in pixels
+ :param image_subsample:amount to reduce the size of the image
+ :param border_width: width of border around element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param disabled: set disable state for element (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename,
+ image_data=image_data, image_size=image_size, image_subsample=image_subsample,
+ border_width=border_width, tooltip=tooltip, size=size, disabled=disabled,
+ auto_size_button=auto_size_button, button_color=button_color, font=font,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+ReadFormButton = ReadButton
+RButton = ReadFormButton
+
+
+# ------------------------- Realtime BUTTON Element lazy function ------------------------- #
+def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
+ border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None,
+ font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: size of button image in pixels
+ :param image_subsample:amount to reduce the size of the image
+ :param border_width: width of border around element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param font: specifies the font family, size, etc
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename,
+ image_data=image_data, image_size=image_size, image_subsample=image_subsample,
+ border_width=border_width, tooltip=tooltip, disabled=disabled, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- Dummy BUTTON Element lazy function ------------------------- #
+def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
+ border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None,
+ disabled=False, bind_return_key=False, focus=False, pad=None, key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: size of button image in pixels
+ :param image_subsample:amount to reduce the size of the image
+ :param border_width: width of border around element
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param font: specifies the font family, size, etc
+ :param disabled: set disable state for element (Default = False)
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename,
+ image_data=image_data, image_size=image_size, image_subsample=image_subsample,
+ border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button,
+ button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus,
+ pad=pad, key=key, metadata=metadata)
+
+
+# ------------------------- Calendar Chooser Button lazy function ------------------------- #
+def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None, None, None),
+ image_filename=None, image_data=None, image_size=(None, None),
+ image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None,
+ button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None,
+ key=None, locale=None, format=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param target:
+ :param close_when_date_chosen: (Default = True)
+ :param default_date_m_d_y: (Default = (None))
+ :param None:
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: (Default = (None))
+ :param image_subsample:amount to reduce the size of the image
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param border_width: width of border around element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :param locale:
+ :param format:
+ :return: (Button)
+ """
+ button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target,
+ image_filename=image_filename, image_data=image_data, image_size=image_size,
+ image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+ button.CalendarCloseWhenChosen = close_when_date_chosen
+ button.DefaultDate_M_D_Y = default_date_m_d_y
+ button.CalendarLocale = locale
+ button.CalendarFormat = format
+ return button
+
+
+# ------------------------- Calendar Chooser Button lazy function ------------------------- #
+def ColorChooserButton(button_text, target=(None, None), image_filename=None, image_data=None, image_size=(None, None),
+ image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None,
+ button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None,
+ key=None, metadata=None):
+ """
+
+ :param button_text: text in the button
+ :param target:
+ :param image_filename: image filename if there is a button image
+ :param image_data: in-RAM image to be displayed on button
+ :param image_size: (Default = (None))
+ :param image_subsample:amount to reduce the size of the image
+ :param tooltip: (str) text, that will appear when mouse hovers over the element
+ :param border_width: width of border around element
+ :param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
+ :param auto_size_button: True if button size is determined by button text
+ :param button_color: button color (foreground, background)
+ :param disabled: set disable state for element (Default = False)
+ :param font: specifies the font family, size, etc
+ :param bind_return_key: (Default = False)
+ :param focus: if focus should be set to this
+ :param pad: Amount of padding to put around element
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :return: (Button)
+ """
+ return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target,
+ image_filename=image_filename, image_data=image_data, image_size=image_size,
+ image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size,
+ auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
+ bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata)
+
+
+##################################### ----- RESULTS ------ ##################################################
+
+def AddToReturnDictionary(form, element, value):
+ """
+
+ :param form:
+ :param element:
+ :param value:
+
+ """
+ form.ReturnValuesDictionary[element.Key] = value
+ # if element.Key is None:
+ # form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value
+ # element.Key = form.DictionaryKeyCounter
+ # form.DictionaryKeyCounter += 1
+ # else:
+ # form.ReturnValuesDictionary[element.Key] = value
+
+
+def AddToReturnList(form, value):
+ """
+
+ :param form:
+ :param value:
+
+ """
+ form.ReturnValuesList.append(value)
+
+
+# ----------------------------------------------------------------------------#
+# ------- FUNCTION InitializeResults. Sets up form results matrix --------#
+def InitializeResults(form):
+ """
+
+ :param form:
+
+ """
+ _BuildResults(form, True, form)
+ return
+
+
+# ===== Radio Button RadVar encoding and decoding =====#
+# ===== The value is simply the row * 1000 + col =====#
+def DecodeRadioRowCol(RadValue):
+ """
+
+ :param RadValue:
+
+ """
+ container = RadValue // 100000
+ row = RadValue // 1000
+ col = RadValue % 1000
+ return container, row, col
+
+
+def EncodeRadioRowCol(container, row, col):
+ """
+
+ :param container:
+ :param row:
+ :param col:
+
+ """
+ RadValue = container * 100000 + row * 1000 + col
+ return RadValue
+
+
+
+# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- #
+# format of return values is
+# (Button Pressed, input_values)
+def _BuildResults(form, initialize_only, top_level_form):
+ """
+
+ :param form:
+ :param initialize_only:
+ :param top_level_form:
+
+ """
+ # Results for elements are:
+ # TEXT - Nothing
+ # INPUT - Read value from TK
+ # Button - Button Text and position as a Tuple
+
+ # Get the initialized results so we don't have to rebuild
+ form.DictionaryKeyCounter = 0
+ form.ReturnValuesDictionary = {}
+ form.ReturnValuesList = []
+ _BuildResultsForSubform(form, initialize_only, top_level_form)
+ if not top_level_form.LastButtonClickedWasRealtime:
+ top_level_form.LastButtonClicked = None
+ return form.ReturnValues
+
+
+def _BuildResultsForSubform(form, initialize_only, top_level_form):
+ """
+
+ :param form:
+ :param initialize_only:
+ :param top_level_form:
+
+ """
+ button_pressed_text = top_level_form.LastButtonClicked
+ for row_num, row in enumerate(form.Rows):
+ for col_num, element in enumerate(row):
+ if element.Key is not None and WRITE_ONLY_KEY in str(element.Key):
+ continue
+ value = None
+ if element.Type == ELEM_TYPE_COLUMN:
+ element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
+ element.ReturnValuesList = []
+ element.ReturnValuesDictionary = {}
+ _BuildResultsForSubform(element, initialize_only, top_level_form)
+ for item in element.ReturnValuesList:
+ AddToReturnList(top_level_form, item)
+ if element.UseDictionary:
+ top_level_form.UseDictionary = True
+ if element.ReturnValues[0] is not None: # if a button was clicked
+ button_pressed_text = element.ReturnValues[0]
+
+ if element.Type == ELEM_TYPE_FRAME:
+ element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
+ element.ReturnValuesList = []
+ element.ReturnValuesDictionary = {}
+ _BuildResultsForSubform(element, initialize_only, top_level_form)
+ for item in element.ReturnValuesList:
+ AddToReturnList(top_level_form, item)
+ if element.UseDictionary:
+ top_level_form.UseDictionary = True
+ if element.ReturnValues[0] is not None: # if a button was clicked
+ button_pressed_text = element.ReturnValues[0]
+
+ if element.Type == ELEM_TYPE_PANE:
+ element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
+ element.ReturnValuesList = []
+ element.ReturnValuesDictionary = {}
+ _BuildResultsForSubform(element, initialize_only, top_level_form)
+ for item in element.ReturnValuesList:
+ AddToReturnList(top_level_form, item)
+ if element.UseDictionary:
+ top_level_form.UseDictionary = True
+ if element.ReturnValues[0] is not None: # if a button was clicked
+ button_pressed_text = element.ReturnValues[0]
+
+ if element.Type == ELEM_TYPE_TAB_GROUP:
+ element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
+ element.ReturnValuesList = []
+ element.ReturnValuesDictionary = {}
+ _BuildResultsForSubform(element, initialize_only, top_level_form)
+ for item in element.ReturnValuesList:
+ AddToReturnList(top_level_form, item)
+ if element.UseDictionary:
+ top_level_form.UseDictionary = True
+ if element.ReturnValues[0] is not None: # if a button was clicked
+ button_pressed_text = element.ReturnValues[0]
+
+ if element.Type == ELEM_TYPE_TAB:
+ element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
+ element.ReturnValuesList = []
+ element.ReturnValuesDictionary = {}
+ _BuildResultsForSubform(element, initialize_only, top_level_form)
+ for item in element.ReturnValuesList:
+ AddToReturnList(top_level_form, item)
+ if element.UseDictionary:
+ top_level_form.UseDictionary = True
+ if element.ReturnValues[0] is not None: # if a button was clicked
+ button_pressed_text = element.ReturnValues[0]
+
+ if not initialize_only:
+ if element.Type == ELEM_TYPE_INPUT_TEXT:
+ try:
+ value = element.TKStringVar.get()
+ except:
+ value = ''
+ if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents:
+ element.TKStringVar.set('')
+ elif element.Type == ELEM_TYPE_INPUT_CHECKBOX:
+ value = element.TKIntVar.get()
+ value = (value != 0)
+ elif element.Type == ELEM_TYPE_INPUT_RADIO:
+ RadVar = element.TKIntVar.get()
+ this_rowcol = EncodeRadioRowCol(form.ContainerElemementNumber, row_num, col_num)
+ # this_rowcol = element.EncodedRadioValue # could use the saved one
+ value = RadVar == this_rowcol
+ elif element.Type == ELEM_TYPE_BUTTON:
+ if top_level_form.LastButtonClicked == element.ButtonText:
+ button_pressed_text = top_level_form.LastButtonClicked
+ if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons
+ top_level_form.LastButtonClicked = None
+ if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER:
+ try:
+ value = element.TKCal.selection
+ except:
+ value = None
+ else:
+ try:
+ value = element.TKStringVar.get()
+ except:
+ value = None
+ elif element.Type == ELEM_TYPE_INPUT_COMBO:
+ element = element # type: Combo
+ # value = element.TKStringVar.get()
+ try:
+ if element.TKCombo.current() == -1: # if the current value was not in the original list
+ value = element.TKCombo.get()
+ else:
+ value = element.Values[element.TKCombo.current()] # get value from original list given index
+ except:
+ value = '*Exception occurred*'
+ elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU:
+ value = element.TKStringVar.get()
+ elif element.Type == ELEM_TYPE_INPUT_LISTBOX:
+ try:
+ items = element.TKListbox.curselection()
+ value = [element.Values[int(item)] for item in items]
+ except:
+ value = ''
+ elif element.Type == ELEM_TYPE_INPUT_SPIN:
+ try:
+ value = element.TKStringVar.get()
+ for v in element.Values:
+ if str(v) == value:
+ value = v
+ break
+ except:
+ value = 0
+ elif element.Type == ELEM_TYPE_INPUT_SLIDER:
+ try:
+ value = float(element.TKScale.get())
+ except:
+ value = 0
+ elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
+ try:
+ value = element.TKText.get(1.0, tk.END)
+ if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents:
+ element.TKText.delete('1.0', tk.END)
+ except:
+ value = None
+ elif element.Type == ELEM_TYPE_TAB_GROUP:
+ try:
+ value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text']
+ tab_key = element.FindKeyFromTabName(value)
+ if tab_key is not None:
+ value = tab_key
+ except:
+ value = None
+ elif element.Type == ELEM_TYPE_TABLE:
+ value = element.SelectedRows
+ elif element.Type == ELEM_TYPE_TREE:
+ value = element.SelectedRows
+ elif element.Type == ELEM_TYPE_GRAPH:
+ value = element.ClickPosition
+ elif element.Type == ELEM_TYPE_MENUBAR:
+ if element.MenuItemChosen is not None:
+ button_pressed_text = top_level_form.LastButtonClicked = element.MenuItemChosen
+ value = element.MenuItemChosen
+ element.MenuItemChosen = None
+ elif element.Type == ELEM_TYPE_BUTTONMENU:
+ value = element.MenuItemChosen
+ element.MenuItemChosen = None
+
+ # if element.MenuItemChosen is not None:
+ # button_pressed_text = top_level_form.LastButtonClicked = element.MenuItemChosen
+ # value = element.MenuItemChosen
+ # element.MenuItemChosen = None
+ else:
+ value = None
+
+ # if an input type element, update the results
+ if element.Type != ELEM_TYPE_BUTTON and \
+ element.Type != ELEM_TYPE_TEXT and \
+ element.Type != ELEM_TYPE_IMAGE and \
+ element.Type != ELEM_TYPE_OUTPUT and \
+ element.Type != ELEM_TYPE_PROGRESS_BAR and \
+ element.Type != ELEM_TYPE_COLUMN and \
+ element.Type != ELEM_TYPE_FRAME \
+ and element.Type != ELEM_TYPE_TAB:
+ AddToReturnList(form, value)
+ AddToReturnDictionary(top_level_form, element, value)
+ elif (element.Type == ELEM_TYPE_BUTTON and
+ element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and
+ element.Target == (None, None)) or \
+ (element.Type == ELEM_TYPE_BUTTON and
+ element.BType == BUTTON_TYPE_COLOR_CHOOSER and
+ element.Target == (None, None)) or \
+ (element.Type == ELEM_TYPE_BUTTON
+ and element.Key is not None and
+ (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES,
+ BUTTON_TYPE_BROWSE_FOLDER))):
+ AddToReturnList(form, value)
+ AddToReturnDictionary(top_level_form, element, value)
+
+ # if this is a column, then will fail so need to wrap with tr
+ try:
+ if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None:
+ button_pressed_text = form.LastKeyboardEvent
+ form.LastKeyboardEvent = None
+ except:
+ pass
+
+ try:
+ form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included
+ except:
+ pass
+
+ if not form.UseDictionary:
+ form.ReturnValues = button_pressed_text, form.ReturnValuesList
+ else:
+ form.ReturnValues = button_pressed_text, form.ReturnValuesDictionary
+
+ return form.ReturnValues
+
+
+def FillFormWithValues(window, values_dict):
+ """
+ Fills a window with values provided in a values dictionary { element_key : new_value }
+
+ :param window: (Window) The window object to fill
+ :param values_dict: (Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call
+ """
+
+ for element_key in values_dict:
+ try:
+ window.AllKeysDict[element_key].Update(values_dict[element_key])
+ except Exception as e:
+ print('Problem filling form. Perhaps bad key? This is a suspected bad key: {}'.format(element_key))
+
+
+def _FindElementWithFocusInSubForm(form):
+ """
+ Searches through a "sub-form" (can be a window or container) for the current element with focus
+
+ :param form: a Window, Column, Frame, or TabGroup (container elements)
+ :return: Union[Element, None]
+ """
+ for row_num, row in enumerate(form.Rows):
+ for col_num, element in enumerate(row):
+ if element.Type == ELEM_TYPE_COLUMN:
+ matching_elem = _FindElementWithFocusInSubForm(element)
+ if matching_elem is not None:
+ return matching_elem
+ elif element.Type == ELEM_TYPE_FRAME:
+ matching_elem = _FindElementWithFocusInSubForm(element)
+ if matching_elem is not None:
+ return matching_elem
+ elif element.Type == ELEM_TYPE_TAB_GROUP:
+ matching_elem = _FindElementWithFocusInSubForm(element)
+ if matching_elem is not None:
+ return matching_elem
+ elif element.Type == ELEM_TYPE_TAB:
+ matching_elem = _FindElementWithFocusInSubForm(element)
+ if matching_elem is not None:
+ return matching_elem
+ elif element.Type == ELEM_TYPE_INPUT_TEXT:
+ if element.TKEntry is not None:
+ if element.TKEntry is element.TKEntry.focus_get():
+ return element
+ elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
+ if element.TKText is not None:
+ if element.TKText is element.TKText.focus_get():
+ return element
+ elif element.Type == ELEM_TYPE_BUTTON:
+ if element.TKButton is not None:
+ if element.TKButton is element.TKButton.focus_get():
+ return element
+ else: # The "Catch All" - if type isn't one of the above, try generic element.Widget
+ try:
+ if element.Widget is not None:
+ if element.Widget is element.Widget.focus_get():
+ return element
+ except:
+ return None
+
+ return None
+
+if sys.version_info[0] >= 3:
+ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False):
+ """
+ Only to be used internally. Not user callable
+ :param top_menu:
+ :param sub_menu_info:
+ :param element:
+ :param is_sub_menu: (Default = False)
+ :param skip: (Default = False)
+
+ """
+ return_val = None
+ if type(sub_menu_info) is str:
+ if not is_sub_menu and not skip:
+ # print(f'Adding command {sub_menu_info}')
+ pos = sub_menu_info.find('&')
+ if pos != -1:
+ if pos == 0 or sub_menu_info[pos - 1] != "\\":
+ sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
+ if sub_menu_info == '---':
+ top_menu.add('separator')
+ else:
+ try:
+ item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)]
+ except:
+ item_without_key = sub_menu_info
+
+ if item_without_key[0] == MENU_DISABLED_CHARACTER:
+ top_menu.add_command(label=item_without_key[len(MENU_DISABLED_CHARACTER):], underline=pos,
+ command=lambda: element._MenuItemChosenCallback(sub_menu_info))
+ top_menu.entryconfig(item_without_key[len(MENU_DISABLED_CHARACTER):], state='disabled')
+ else:
+ top_menu.add_command(label=item_without_key, underline=pos,
+ command=lambda: element._MenuItemChosenCallback(sub_menu_info))
+ else:
+ i = 0
+ while i < (len(sub_menu_info)):
+ item = sub_menu_info[i]
+ if i != len(sub_menu_info) - 1:
+ if type(sub_menu_info[i + 1]) == list:
+ new_menu = tk.Menu(top_menu, tearoff=element.Tearoff)
+ return_val = new_menu
+ pos = sub_menu_info[i].find('&')
+ if pos != -1:
+ if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
+ sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
+ if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER:
+ top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu,
+ underline=pos, state='disabled')
+ else:
+ top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
+ AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
+ i += 1 # skip the next one
+ else:
+ AddMenuItem(top_menu, item, element)
+ else:
+ AddMenuItem(top_menu, item, element)
+ i += 1
+ return return_val
+else:
+ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False):
+ """
+
+ :param top_menu:
+ :param sub_menu_info:
+ :param element:
+ :param is_sub_menu: (Default = False)
+ :param skip: (Default = False)
+
+ """
+ if not isinstance(sub_menu_info, list):
+ if not is_sub_menu and not skip:
+ # print(f'Adding command {sub_menu_info}')
+ pos = sub_menu_info.find('&')
+ if pos != -1:
+ if pos == 0 or sub_menu_info[pos - 1] != "\\":
+ sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
+ if sub_menu_info == '---':
+ top_menu.add('separator')
+ else:
+ try:
+ item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)]
+ except:
+ item_without_key = sub_menu_info
+
+ if item_without_key[0] == MENU_DISABLED_CHARACTER:
+ top_menu.add_command(label=item_without_key[len(MENU_DISABLED_CHARACTER):], underline=pos,
+ command=lambda: element._MenuItemChosenCallback(sub_menu_info))
+ top_menu.entryconfig(item_without_key[len(MENU_DISABLED_CHARACTER):], state='disabled')
+ else:
+ top_menu.add_command(label=item_without_key, underline=pos,
+ command=lambda: element._MenuItemChosenCallback(sub_menu_info))
+ else:
+ i = 0
+ while i < (len(sub_menu_info)):
+ item = sub_menu_info[i]
+ if i != len(sub_menu_info) - 1:
+ if isinstance(sub_menu_info[i + 1], list):
+ new_menu = tk.Menu(top_menu, tearoff=element.Tearoff)
+ pos = sub_menu_info[i].find('&')
+ if pos != -1:
+ if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
+ sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
+ if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER:
+ top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu,
+ underline=pos, state='disabled')
+ else:
+ top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
+ AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
+ i += 1 # skip the next one
+ else:
+ AddMenuItem(top_menu, item, element)
+ else:
+ AddMenuItem(top_menu, item, element)
+ i += 1
+
+# 888 888 d8b 888
+# 888 888 Y8P 888
+# 888 888 888
+# 888888 888 888 888 88888b. 888888 .d88b. 888d888
+# 888 888 .88P 888 888 "88b 888 d8P Y8b 888P"
+# 888 888888K 888 888 888 888 88888888 888
+# Y88b. 888 "88b 888 888 888 Y88b. Y8b. 888
+# "Y888 888 888 888 888 888 "Y888 "Y8888 888
+
+# My crappy tkinter code starts here
+
+"""
+ )
+ (
+ ,
+ ___)\
+ (_____)
+ (_______)
+
+"""
+
+
+# ======================== TK CODE STARTS HERE ========================================= #
+
+def PackFormIntoFrame(form, containing_frame, toplevel_form):
+ """
+
+ :param form:
+ :param containing_frame:
+ :param toplevel_form:
+
+ """
+ def CharWidthInPixels():
+ """ """
+ return tkinter.font.Font().measure('A') # single character width
+
+
+ border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH
+ # --------------------------------------------------------------------------- #
+ # **************** Use FlexForm to build the tkinter window ********** ----- #
+ # Building is done row by row. #
+ # --------------------------------------------------------------------------- #
+ ######################### LOOP THROUGH ROWS #########################
+ # *********** ------- Loop through ROWS ------- ***********#
+ for row_num, flex_row in enumerate(form.Rows):
+ ######################### LOOP THROUGH ELEMENTS ON ROW #########################
+ # *********** ------- Loop through ELEMENTS ------- ***********#
+ # *********** Make TK Row ***********#
+ tk_row_frame = tk.Frame(containing_frame)
+ row_should_expand = False
+ row_justify = form.ElementJustification
+ for col_num, element in enumerate(flex_row):
+ element.ParentRowFrame = tk_row_frame
+ element.ParentForm = toplevel_form # save the button's parent form object
+ if toplevel_form.Font and (element.Font == DEFAULT_FONT or not element.Font):
+ font = toplevel_form.Font
+ elif element.Font is not None:
+ font = element.Font
+ else:
+ font = DEFAULT_FONT
+ # ------- Determine Auto-Size setting on a cascading basis ------- #
+ if element.AutoSizeText is not None: # if element overide
+ auto_size_text = element.AutoSizeText
+ elif toplevel_form.AutoSizeText is not None: # if form override
+ auto_size_text = toplevel_form.AutoSizeText
+ else:
+ auto_size_text = DEFAULT_AUTOSIZE_TEXT
+ element_type = element.Type
+ # Set foreground color
+ text_color = element.TextColor
+ elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding
+ # Determine Element size
+ element_size = element.Size
+ if (element_size == (None, None) and element_type not in (
+ ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size
+ element_size = toplevel_form.DefaultElementSize
+ elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)):
+ element_size = toplevel_form.DefaultButtonElementSize
+ else:
+ auto_size_text = False # if user has specified a size then it shouldn't autosize
+ # ------------------------- COLUMN element ------------------------- #
+ if element_type == ELEM_TYPE_COLUMN:
+ element = element # type: Column
+ if element.Scrollable:
+ element.TKColFrame = TkScrollableFrame(tk_row_frame, element.VerticalScrollOnly) # do not use yet! not working
+ PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form)
+ element.TKColFrame.TKFrame.update()
+ if element.Size == (None, None): # if no size specified, use column width x column height/2
+ element.TKColFrame.canvas.config(width=element.TKColFrame.TKFrame.winfo_reqwidth(),
+ height=element.TKColFrame.TKFrame.winfo_reqheight() / 2)
+ else:
+ if None not in (element.Size[0], element.Size[1]):
+ element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1])
+ elif element.Size[1] is not None:
+ element.TKColFrame.canvas.config(height=element.Size[1])
+ elif element.Size[0] is not None:
+ element.TKColFrame.canvas.config(width=element.Size[0])
+
+ if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
+ element.TKColFrame.canvas.config(background=element.BackgroundColor)
+ element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0,
+ highlightthickness=0)
+ element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0,
+ highlightthickness=0)
+ else:
+ if element.Size != (None, None):
+ element.TKColFrame = TkFixedFrame(tk_row_frame)
+ PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form)
+ element.TKColFrame.TKFrame.update()
+ if None not in (element.Size[0], element.Size[1]):
+ element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1])
+ elif element.Size[1] is not None:
+ element.TKColFrame.canvas.config(height=element.Size[1])
+ elif element.Size[0] is not None:
+ element.TKColFrame.canvas.config(width=element.Size[0])
+ if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
+ element.TKColFrame.canvas.config(background=element.BackgroundColor)
+ element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0,
+ highlightthickness=0)
+ else:
+ element.TKColFrame = tk.Frame(tk_row_frame)
+ PackFormIntoFrame(element, element.TKColFrame, toplevel_form)
+ if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
+ element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0,
+ highlightthickness=0)
+ if element.Justification.lower().startswith('c'):
+ anchor=tk.N
+ side=tk.TOP
+ elif element.Justification.lower().startswith('r'):
+ anchor=tk.NE
+ side = tk.RIGHT
+ else:
+ anchor=tk.NW
+ side = tk.LEFT
+ # anchor=tk.NW
+ # side = tk.LEFT
+ row_justify = element.Justification
+ element.Widget = element.TKColFrame
+ element.TKColFrame.pack(side=side, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=False, fill=tk.NONE)
+ # element.TKColFrame.pack(side=side, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
+ if element.Visible is False:
+ element.TKColFrame.pack_forget()
+ # element.TKColFrame = element.TKColFrame
+ # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
+ # element.TKColFrame.configure(background=element.BackgroundColor,
+ # highlightbackground=element.BackgroundColor,
+ # highlightcolor=element.BackgroundColor)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKColFrame.bind('', element._RightClickMenuCallback)
+ # row_should_expand = True
+ # ------------------------- Pane element ------------------------- #
+ if element_type == ELEM_TYPE_PANE:
+ bd = element.BorderDepth if element.BorderDepth is not None else border_depth
+ element.PanedWindow = element.Widget = tk.PanedWindow(tk_row_frame,
+ orient=tk.VERTICAL if element.Orientation.startswith(
+ 'v') else tk.HORIZONTAL,
+ borderwidth=bd,
+ bd=bd,
+ )
+ if element.Relief is not None:
+ element.PanedWindow.configure(relief=element.Relief)
+ element.PanedWindow.configure(handlesize=element.HandleSize)
+ if element.ShowHandle:
+ element.PanedWindow.config(showhandle=True)
+ if element.Size != (None, None):
+ element.PanedWindow.config(width=element.Size[0], height=element.Size[1])
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.PanedWindow.configure(background=element.BackgroundColor)
+ for pane in element.PaneList:
+ pane.Widget = pane.TKColFrame = tk.Frame(element.PanedWindow)
+ pane.ParentPanedWindow = element.PanedWindow
+ PackFormIntoFrame(pane, pane.TKColFrame, toplevel_form)
+ if pane.Visible:
+ element.PanedWindow.add(pane.TKColFrame)
+ if pane.BackgroundColor != COLOR_SYSTEM_DEFAULT and pane.BackgroundColor is not None:
+ pane.TKColFrame.configure(background=pane.BackgroundColor,
+ highlightbackground=pane.BackgroundColor,
+ highlightcolor=pane.BackgroundColor)
+
+ element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
+ if element.Visible is False:
+ element.PanedWindow.pack_forget()
+ # ------------------------- TEXT element ------------------------- #
+ elif element_type == ELEM_TYPE_TEXT:
+ # auto_size_text = element.AutoSizeText
+ element = element # type: Text
+ display_text = element.DisplayText # text to display
+ if auto_size_text is False:
+ width, height = element_size
+ else:
+ lines = display_text.split('\n')
+ max_line_len = max([len(l) for l in lines])
+ num_lines = len(lines)
+ if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap
+ width = element_size[0]
+ else:
+ width = max_line_len
+ height = num_lines
+ # ---===--- LABEL widget create and place --- #
+ element = element # type: Text
+ bd = element.BorderWidth if element.BorderWidth is not None else border_depth
+ stringvar = tk.StringVar()
+ element.TKStringVar = stringvar
+ stringvar.set(str(display_text))
+ if auto_size_text:
+ width = 0
+ if element.Justification is not None:
+ justification = element.Justification
+ elif toplevel_form.TextJustification is not None:
+ justification = toplevel_form.TextJustification
+ else:
+ justification = DEFAULT_TEXT_JUSTIFICATION
+ justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT
+ anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
+
+ tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width,
+ height=height, justify=justify, bd=bd, font=font)
+ # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
+ wraplen = tktext_label.winfo_reqwidth() # width of widget in Pixels
+ if not auto_size_text and height == 1: # if just 1 line high, ensure no wrap happens
+ wraplen = 0
+ # print(f'Text wraplen = {wraplen} wxh = {width} x {height}')
+ # print(f'Len = {len(display_text)} Text = {str(display_text)}')
+ tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
+ if element.Relief is not None:
+ tktext_label.configure(relief=element.Relief)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ tktext_label.configure(background=element.BackgroundColor)
+ if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
+ tktext_label.configure(fg=element.TextColor)
+ tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ tktext_label.pack_forget()
+ element.TKText = tktext_label
+ if element.ClickSubmits:
+ tktext_label.bind('', element._TextClickedHandler)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ tktext_label.bind('', element._RightClickMenuCallback)
+ # ------------------------- BUTTON element ------------------------- #
+ elif element_type == ELEM_TYPE_BUTTON:
+ element = element # type: Button
+ stringvar = tk.StringVar()
+ element.TKStringVar = stringvar
+ element.Location = (row_num, col_num)
+ btext = element.ButtonText
+ btype = element.BType
+ if element.AutoSizeButton is not None:
+ auto_size = element.AutoSizeButton
+ else:
+ auto_size = toplevel_form.AutoSizeButtons
+ if auto_size is False or element.Size[0] is not None:
+ width, height = element_size
+ else:
+ width = 0
+ height = toplevel_form.DefaultButtonElementSize[1]
+ if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR:
+ bc = element.ButtonColor
+ elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR:
+ bc = toplevel_form.ButtonColor
+ else:
+ bc = DEFAULT_BUTTON_COLOR
+ bd = element.BorderWidth
+ if btype != BUTTON_TYPE_REALTIME:
+ tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height,
+ command=element.ButtonCallBack, justify=tk.LEFT,
+ bd=bd, font=font)
+ else:
+ tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height,
+ justify=tk.LEFT,
+ bd=bd, font=font)
+ tkbutton.bind('', element.ButtonReleaseCallBack)
+ tkbutton.bind('', element.ButtonPressCallBack)
+ if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT:
+ # if sys.platform.startswith('darwin'):
+ # print('*** USING MAC BUTTON COLORS ****', bc)
+ # tkbutton.config(foreground=bc[0], highlightbackground=bc[1],background=bc[1], activebackground=bc[1], highlightcolor=bc[1], activeforeground=bc[1], highlightthickness=-10, bd=0, relief='solid')
+ # else:
+ tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1])
+ elif bc[1] == COLOR_SYSTEM_DEFAULT:
+ tkbutton.config(foreground=bc[0])
+ if bd == 0 and not sys.platform.startswith('darwin'):
+ tkbutton.config(relief=tk.FLAT)
+ tkbutton.config(highlightthickness=0)
+ element.TKButton = tkbutton # not used yet but save the TK button in case
+ wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels
+ if element.ImageFilename: # if button has an image on it
+ tkbutton.config(highlightthickness=0)
+ photo = tk.PhotoImage(file=element.ImageFilename)
+ if element.ImageSubsample:
+ photo = photo.subsample(element.ImageSubsample)
+ if element.ImageSize != (None, None):
+ width, height = element.ImageSize
+ else:
+ width, height = photo.width(), photo.height()
+ tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
+ tkbutton.image = photo
+ if element.ImageData: # if button has an image on it
+ tkbutton.config(highlightthickness=0)
+ photo = tk.PhotoImage(data=element.ImageData)
+ if element.ImageSubsample:
+ photo = photo.subsample(element.ImageSubsample)
+ if element.ImageSize != (None, None):
+ width, height = element.ImageSize
+ else:
+ width, height = photo.width(), photo.height()
+ tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
+ tkbutton.image = photo
+ if width != 0:
+ tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget
+ tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ tkbutton.pack_forget()
+ if element.BindReturnKey:
+ element.TKButton.bind('', element._ReturnKeyHandler)
+ if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
+ toplevel_form.FocusSet = True
+ element.TKButton.bind('', element._ReturnKeyHandler)
+ element.TKButton.focus_set()
+ toplevel_form.TKroot.focus_force()
+ if element.Disabled == True:
+ element.TKButton['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- BUTTONMENU element ------------------------- #
+ elif element_type == ELEM_TYPE_BUTTONMENU:
+ element = element # type: ButtonMenu
+ element.Location = (row_num, col_num)
+ btext = element.ButtonText
+ if element.AutoSizeButton is not None:
+ auto_size = element.AutoSizeButton
+ else:
+ auto_size = toplevel_form.AutoSizeButtons
+ if auto_size is False or element.Size[0] is not None:
+ width, height = element_size
+ else:
+ width = 0
+ height = toplevel_form.DefaultButtonElementSize[1]
+ if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR:
+ bc = element.ButtonColor
+ elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR:
+ bc = toplevel_form.ButtonColor
+ else:
+ bc = DEFAULT_BUTTON_COLOR
+ bd = element.BorderWidth
+ tkbutton = element.Widget = tk.Menubutton(tk_row_frame, text=btext, width=width, height=height,
+ justify=tk.LEFT, bd=bd, font=font)
+ element.TKButtonMenu = tkbutton
+ if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT:
+ tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1])
+ elif bc[1] == COLOR_SYSTEM_DEFAULT:
+ tkbutton.config(foreground=bc[0])
+ if bd == 0:
+ tkbutton.config(relief=tk.FLAT)
+ tkbutton.config(highlightthickness=0)
+ element.TKButton = tkbutton # not used yet but save the TK button in case
+ wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels
+ if element.ImageFilename: # if button has an image on it
+ tkbutton.config(highlightthickness=0)
+ photo = tk.PhotoImage(file=element.ImageFilename)
+ if element.ImageSize != (None, None):
+ width, height = element.ImageSize
+ if element.ImageSubsample:
+ photo = photo.subsample(element.ImageSubsample)
+ else:
+ width, height = photo.width(), photo.height()
+ tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
+ tkbutton.image = photo
+ if element.ImageData: # if button has an image on it
+ tkbutton.config(highlightthickness=0)
+ photo = tk.PhotoImage(data=element.ImageData)
+ if element.ImageSize != (None, None):
+ width, height = element.ImageSize
+ if element.ImageSubsample:
+ photo = photo.subsample(element.ImageSubsample)
+ else:
+ width, height = photo.width(), photo.height()
+ tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
+ tkbutton.image = photo
+ if width != 0:
+ tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget
+ tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+
+ menu_def = element.MenuDefinition
+
+ top_menu = tk.Menu(tkbutton, tearoff=False)
+ AddMenuItem(top_menu, menu_def[1], element)
+
+ tkbutton.configure(menu=top_menu)
+ element.TKMenu = top_menu
+ if element.Visible is False:
+ tkbutton.pack_forget()
+ if element.Disabled == True:
+ element.TKButton['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+
+
+ # ------------------------- INPUT element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_TEXT:
+ element = element # type: InputText
+ default_text = element.DefaultText
+ element.TKStringVar = tk.StringVar()
+ element.TKStringVar.set(default_text)
+ show = element.PasswordCharacter if element.PasswordCharacter else ""
+ # bd = element.BorderDepth if element.BorderDepth is not None else border_depth
+ bd = border_depth
+ if element.Justification is not None:
+ justification = element.Justification
+ else:
+ justification = DEFAULT_TEXT_JUSTIFICATION
+ justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT
+ # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
+ element.TKEntry = element.Widget = tk.Entry(tk_row_frame, width=element_size[0],
+ textvariable=element.TKStringVar, bd=bd,
+ font=font, show=show, justify=justify)
+ if element.ChangeSubmits:
+ element.TKEntry.bind('', element._KeyboardHandler)
+ element.TKEntry.bind('', element._ReturnKeyHandler)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKEntry.configure(background=element.BackgroundColor)
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKEntry.configure(fg=text_color)
+ element.TKEntry.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=False, fill=tk.NONE)
+ if element.Visible is False:
+ element.TKEntry.pack_forget()
+ if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
+ toplevel_form.FocusSet = True
+ element.TKEntry.focus_set()
+ if element.Disabled:
+ element.TKEntry['state'] = 'readonly'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKEntry, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKEntry.bind('', element._RightClickMenuCallback)
+ # row_should_expand = True
+
+ # ------------------------- COMBOBOX element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_COMBO:
+ max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0
+ if auto_size_text is False:
+ width = element_size[0]
+ else:
+ width = max_line_len
+ element.TKStringVar = tk.StringVar()
+ style_name = 'TCombobox'
+ if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
+ # Creates 1 style per Text Color/ Background Color combination
+ style_name = element.TextColor + element.BackgroundColor + '.TCombobox'
+ # print(style_name)
+ combostyle = ttk.Style()
+
+ # Creates a unique name for each field element(Sure there is a better way to do this)
+
+ unique_field = str(element.Key) + '.TCombobox.field'
+
+ # Clones over the TCombobox.field element from the "alt" theme.
+ # This is what will allow us to change the background color without altering the whole programs theme
+
+ try: # if this element is in a window that's shown TWICE, will get an error here, so skip error
+ combostyle.element_create(unique_field, "from", "alt")
+ except:
+ pass
+
+ # Create widget layout using cloned "alt" field
+ combostyle.layout(style_name, [
+ (unique_field, {'children': [('Combobox.downarrow', {'side': 'right', 'sticky': 'ns'}),
+ ('Combobox.padding',
+ {'children': [('Combobox.focus',
+ {'children': [('Combobox.textarea',
+ {'sticky': 'nswe'})],
+ 'expand': '1',
+ 'sticky': 'nswe'})],
+ 'expand': '1',
+ 'sticky': 'nswe'})],
+ 'sticky': 'nswe'})])
+
+ # Copy default TCombobox settings
+ # Getting an error on this line of code
+ # combostyle.configure(style_name, *combostyle.configure("TCombobox"))
+
+ # Set individual widget options
+ combostyle.configure(style_name, foreground=element.TextColor)
+ combostyle.configure(style_name, selectbackground='gray70')
+ combostyle.configure(style_name, fieldbackground=element.BackgroundColor)
+ combostyle.configure(style_name, selectforeground=element.TextColor)
+
+ element.TKCombo = element.Widget = ttk.Combobox(tk_row_frame, width=width,
+ textvariable=element.TKStringVar, font=font,
+ style=style_name)
+ if element.Size[1] != 1 and element.Size[1] is not None:
+ element.TKCombo.configure(height=element.Size[1])
+ element.TKCombo['values'] = element.Values
+
+ element.TKCombo.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKCombo.pack_forget()
+ if element.DefaultValue is not None:
+ for i, v in enumerate(element.Values):
+ if v == element.DefaultValue:
+ element.TKCombo.current(i)
+ break
+ # elif element.Values:
+ # element.TKCombo.current(0)
+ if element.ChangeSubmits:
+ element.TKCombo.bind('<>', element._ComboboxSelectHandler)
+ if element.Readonly:
+ element.TKCombo['state'] = 'readonly'
+ if element.Disabled is True: # note overrides readonly if disabled
+ element.TKCombo['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- OPTION MENU Element (Like ComboBox but different) element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
+ max_line_len = max([len(str(l)) for l in element.Values])
+ if auto_size_text is False:
+ width = element_size[0]
+ else:
+ width = max_line_len
+ element.TKStringVar = tk.StringVar()
+ default = element.DefaultValue if element.DefaultValue else element.Values[0]
+ element.TKStringVar.set(default)
+ element.TKOptionMenu = element.Widget = tk.OptionMenu(tk_row_frame, element.TKStringVar,
+ *element.Values)
+ element.TKOptionMenu.config(highlightthickness=0, font=font, width=width)
+ element.TKOptionMenu.config(borderwidth=border_depth)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKOptionMenu.configure(background=element.BackgroundColor)
+ if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
+ element.TKOptionMenu.configure(fg=element.TextColor)
+ element.TKOptionMenu.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKOptionMenu.pack_forget()
+ if element.Disabled == True:
+ element.TKOptionMenu['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- LISTBOX element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_LISTBOX:
+ element = element # type: Listbox
+ max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0
+ if auto_size_text is False:
+ width = element_size[0]
+ else:
+ width = max_line_len
+ listbox_frame = tk.Frame(tk_row_frame)
+ element.TKStringVar = tk.StringVar()
+ element.TKListbox = element.Widget = tk.Listbox(listbox_frame, height=element_size[1], width=width,
+ selectmode=element.SelectMode, font=font,
+ exportselection=False)
+ for index, item in enumerate(element.Values):
+ element.TKListbox.insert(tk.END, item)
+ if element.DefaultValues is not None and item in element.DefaultValues:
+ element.TKListbox.selection_set(index)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKListbox.configure(background=element.BackgroundColor)
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKListbox.configure(fg=text_color)
+ if element.ChangeSubmits:
+ element.TKListbox.bind('<>', element._ListboxSelectHandler)
+ if not element.NoScrollbar:
+ element.vsb = tk.Scrollbar(listbox_frame, orient="vertical", command=element.TKListbox.yview)
+ element.TKListbox.configure(yscrollcommand=element.vsb.set)
+ element.vsb.pack(side=tk.RIGHT, fill='y')
+ listbox_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ element.TKListbox.pack(side=tk.LEFT)
+ if element.Visible is False:
+ listbox_frame.pack_forget()
+ element.vsb.pack_forget()
+ if element.BindReturnKey:
+ element.TKListbox.bind('', element._ListboxSelectHandler)
+ element.TKListbox.bind('', element._ListboxSelectHandler)
+ if element.Disabled == True:
+ element.TKListbox['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKListbox.bind('', element._RightClickMenuCallback)
+ # ------------------------- MULTILINE element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_MULTILINE:
+ element = element # type: Multiline
+ default_text = element.DefaultText
+ width, height = element_size
+ bd = element.BorderWidth
+ element.TKText = element.Widget = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height,
+ wrap='word', bd=bd, font=font,
+ relief=RELIEF_SUNKEN)
+ element.TKText.insert(1.0, default_text) # set the default text
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKText.configure(background=element.BackgroundColor)
+ if DEFAULT_SCROLLBAR_COLOR not in (None, COLOR_SYSTEM_DEFAULT):
+ element.TKText.vbar.config(troughcolor=DEFAULT_SCROLLBAR_COLOR)
+ element.TKText.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKText.pack_forget()
+ if element.ChangeSubmits:
+ element.TKText.bind('', element._KeyboardHandler)
+ if element.EnterSubmits:
+ element.TKText.bind('', element._ReturnKeyHandler)
+ if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
+ toplevel_form.FocusSet = True
+ element.TKText.focus_set()
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKText.configure(fg=text_color)
+ if element.Disabled == True:
+ element.TKText['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKText.bind('', element._RightClickMenuCallback)
+ # row_should_expand = True
+ # ------------------------- CHECKBOX element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_CHECKBOX:
+ width = 0 if auto_size_text else element_size[0]
+ default_value = element.InitialState
+ element.TKIntVar = tk.IntVar()
+ element.TKIntVar.set(default_value if default_value is not None else 0)
+ if element.ChangeSubmits:
+ element.TKCheckbutton = element.Widget = tk.Checkbutton(tk_row_frame, anchor=tk.NW,
+ text=element.Text, width=width,
+ variable=element.TKIntVar, bd=border_depth,
+ font=font,
+ command=element._CheckboxHandler)
+ else:
+ element.TKCheckbutton = element.Widget = tk.Checkbutton(tk_row_frame, anchor=tk.NW,
+ text=element.Text, width=width,
+ variable=element.TKIntVar, bd=border_depth,
+ font=font)
+ if element.Disabled:
+ element.TKCheckbutton.configure(state='disable')
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKCheckbutton.configure(background=element.BackgroundColor)
+ element.TKCheckbutton.configure(selectcolor=element.BackgroundColor)
+ element.TKCheckbutton.configure(activebackground=element.BackgroundColor)
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKCheckbutton.configure(fg=text_color)
+ element.TKCheckbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKCheckbutton.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- PROGRESS BAR element ------------------------- #
+ elif element_type == ELEM_TYPE_PROGRESS_BAR:
+ # save this form because it must be 'updated' (refreshed) solely for the purpose of updating bar
+ width = element_size[0]
+ fnt = tkinter.font.Font()
+ char_width = fnt.measure('A') # single character width
+ progress_length = width * char_width
+ progress_width = element_size[1]
+ direction = element.Orientation
+ if element.BarColor != (None, None): # if element has a bar color, use it
+ bar_color = element.BarColor
+ else:
+ bar_color = DEFAULT_PROGRESS_BAR_COLOR
+ element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width,
+ orientation=direction, BarColor=bar_color,
+ border_width=element.BorderWidth, relief=element.Relief,
+ style=element.BarStyle, key=element.Key)
+ element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKProgressBar.TKProgressBarForReal.pack_forget()
+ element.Widget = element.TKProgressBar.TKProgressBarForReal
+ # ------------------------- RADIO BUTTON element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_RADIO:
+ element = element # type: Radio
+ width = 0 if auto_size_text else element_size[0]
+ default_value = element.InitialState
+ ID = element.GroupID
+ # see if ID has already been placed
+ value = EncodeRadioRowCol(form.ContainerElemementNumber, row_num,
+ col_num) # value to set intvar to if this radio is selected
+ element.EncodedRadioValue = value
+ if ID in toplevel_form.RadioDict:
+ RadVar = toplevel_form.RadioDict[ID]
+ else:
+ RadVar = tk.IntVar()
+ toplevel_form.RadioDict[ID] = RadVar
+ element.TKIntVar = RadVar # store the RadVar in Radio object
+ if default_value: # if this radio is the one selected, set RadVar to match
+ element.TKIntVar.set(value)
+ if element.ChangeSubmits:
+ element.TKRadio = element.Widget = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text,
+ width=width,
+ variable=element.TKIntVar, value=value,
+ bd=border_depth, font=font,
+ command=element._RadioHandler)
+ else:
+ element.TKRadio = element.Widget = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text,
+ width=width,
+ variable=element.TKIntVar, value=value,
+ bd=border_depth, font=font)
+ if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
+ element.TKRadio.configure(background=element.BackgroundColor)
+ element.TKRadio.configure(selectcolor=element.BackgroundColor)
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKRadio.configure(fg=text_color)
+ if element.Disabled:
+ element.TKRadio['state'] = 'disabled'
+ element.TKRadio.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKRadio.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- SPIN element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_SPIN:
+ element = element # type: Spin
+ width, height = element_size
+ width = 0 if auto_size_text else element_size[0]
+ element.TKStringVar = tk.StringVar()
+ element.TKSpinBox = element.Widget = tk.Spinbox(tk_row_frame, values=element.Values,
+ textvariable=element.TKStringVar,
+ width=width, bd=border_depth)
+ element.TKStringVar.set(element.DefaultValue)
+ element.TKSpinBox.configure(font=font) # set wrap to width of widget
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element.TKSpinBox.configure(background=element.BackgroundColor)
+ element.TKSpinBox.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.TKSpinBox.pack_forget()
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKSpinBox.configure(fg=text_color)
+ if element.ChangeSubmits:
+ element.TKSpinBox.bind('', element._SpinChangedHandler)
+ if element.Disabled == True:
+ element.TKSpinBox['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- OUTPUT element ------------------------- #
+ elif element_type == ELEM_TYPE_OUTPUT:
+ width, height = element_size
+ element._TKOut = element.Widget = TKOutput(tk_row_frame, width=width, height=height, bd=border_depth,
+ background_color=element.BackgroundColor,
+ text_color=text_color, font=font,
+ pad=elementpad)
+ element._TKOut.output.configure(takefocus=0) # make it so that Output does not get focus
+ element._TKOut.pack(side=tk.LEFT, expand=False, fill=tk.NONE)
+ if element.Visible is False:
+ element._TKOut.frame.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element._TKOut, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element._TKOut.bind('', element._RightClickMenuCallback)
+ # row_should_expand = True
+ # ------------------------- IMAGE element ------------------------- #
+ elif element_type == ELEM_TYPE_IMAGE:
+ element = element # type: Image
+ if element.Filename is not None:
+ photo = tk.PhotoImage(file=element.Filename)
+ elif element.Data is not None:
+ photo = tk.PhotoImage(data=element.Data)
+ else:
+ photo = None
+ print('*ERROR laying out form.... Image Element has no image specified*')
+
+ if photo is not None:
+ if element_size == (
+ None, None) or element_size == None or element_size == toplevel_form.DefaultElementSize:
+ width, height = photo.width(), photo.height()
+ else:
+ width, height = element_size
+ if photo is not None:
+ element.tktext_label = element.Widget = tk.Label(tk_row_frame, image=photo, width=width,
+ height=height,
+ bd=border_depth)
+ else:
+ element.tktext_label = element.Widget = tk.Label(tk_row_frame, width=width, height=height,
+ bd=border_depth)
+
+ if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
+ element.tktext_label.config(background=element.BackgroundColor)
+
+ element.tktext_label.image = photo
+ # tktext_label.configure(anchor=tk.NW, image=photo)
+ element.tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element.tktext_label.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.EnableEvents:
+ element.tktext_label.bind('', element._ClickHandler)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.tktext_label.bind('', element._RightClickMenuCallback)
+ # ------------------------- Canvas element ------------------------- #
+ elif element_type == ELEM_TYPE_CANVAS:
+ width, height = element_size
+ if element._TKCanvas is None:
+ element._TKCanvas = element.Widget = tk.Canvas(tk_row_frame, width=width, height=height,
+ bd=border_depth)
+ else:
+ element._TKCanvas.master = tk_row_frame
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
+ element._TKCanvas.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ element._TKCanvas.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element._TKCanvas.bind('', element._RightClickMenuCallback)
+ # ------------------------- Graph element ------------------------- #
+ elif element_type == ELEM_TYPE_GRAPH:
+ element = element # type: Graph
+ width, height = element_size
+ # I don't know why TWO canvases were being defined, on inside the other. Was it so entire canvas can move?
+ # if element._TKCanvas is None:
+ # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
+ # else:
+ # element._TKCanvas.master = tk_row_frame
+ element._TKCanvas2 = element.Widget = tk.Canvas(tk_row_frame, width=width, height=height,
+ bd=border_depth)
+ element._TKCanvas2.pack(side=tk.LEFT)
+ element._TKCanvas2.addtag_all('mytag')
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0)
+ # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
+ element._TKCanvas2.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ # element._TKCanvas.pack_forget()
+ element._TKCanvas2.pack_forget()
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element._TKCanvas2, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.ChangeSubmits:
+ element._TKCanvas2.bind('', element.ButtonReleaseCallBack)
+ element._TKCanvas2.bind('', element.ButtonPressCallBack)
+ if element.DragSubmits:
+ element._TKCanvas2.bind('', element.MotionCallBack)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element._TKCanvas2.bind('', element._RightClickMenuCallback)
+ # ------------------------- MENUBAR element ------------------------- #
+ elif element_type == ELEM_TYPE_MENUBAR:
+ element = element # type: MenuBar
+ menu_def = element.MenuDefinition
+ element.TKMenu = element.Widget = tk.Menu(toplevel_form.TKroot,
+ tearoff=element.Tearoff) # create the menubar
+ menubar = element.TKMenu
+ for menu_entry in menu_def:
+ # print(f'Adding a Menubar ENTRY {menu_entry}')
+ baritem = tk.Menu(menubar, tearoff=element.Tearoff)
+ pos = menu_entry[0].find('&')
+ # print(pos)
+ if pos != -1:
+ if pos == 0 or menu_entry[0][pos - 1] != "\\":
+ menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:]
+ if menu_entry[0][0] == MENU_DISABLED_CHARACTER:
+ menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem,
+ underline=pos)
+ menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled')
+ else:
+ menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos)
+
+ if len(menu_entry) > 1:
+ AddMenuItem(baritem, menu_entry[1], element)
+ toplevel_form.TKroot.configure(menu=element.TKMenu)
+ # ------------------------- Frame element ------------------------- #
+ elif element_type == ELEM_TYPE_FRAME:
+ element = element # type: Frame
+ labeled_frame = element.Widget = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief)
+ element.TKFrame = labeled_frame
+ PackFormIntoFrame(element, labeled_frame, toplevel_form)
+ labeled_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.NONE, expand=False)
+ if element.Size != (None,None):
+ labeled_frame.config(width=element.Size[0], height=element.Size[1])
+ if not element.Visible:
+ labeled_frame.pack_forget()
+ if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
+ labeled_frame.configure(background=element.BackgroundColor,
+ highlightbackground=element.BackgroundColor,
+ highlightcolor=element.BackgroundColor)
+ if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
+ labeled_frame.configure(foreground=element.TextColor)
+ if font is not None:
+ labeled_frame.configure(font=font)
+ if element.TitleLocation is not None:
+ labeled_frame.configure(labelanchor=element.TitleLocation)
+ if element.BorderWidth is not None:
+ labeled_frame.configure(borderwidth=element.BorderWidth)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ labeled_frame.bind('', element._RightClickMenuCallback)
+ # row_should_expand=True
+ # ------------------------- Tab element ------------------------- #
+ elif element_type == ELEM_TYPE_TAB:
+ element = element # type: Tab
+ element.TKFrame = element.Widget = tk.Frame(form.TKNotebook)
+ PackFormIntoFrame(element, element.TKFrame, toplevel_form)
+ if element.Disabled:
+ form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled')
+ else:
+ form.TKNotebook.add(element.TKFrame, text=element.Title)
+ form.TKNotebook.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.NONE, expand=False)
+ element.ParentNotebook = form.TKNotebook
+ element.TabID = form.TabCount
+ form.TabCount += 1
+ if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
+ element.TKFrame.configure(background=element.BackgroundColor,
+ highlightbackground=element.BackgroundColor,
+ highlightcolor=element.BackgroundColor)
+ # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
+ # element.TKFrame.configure(foreground=element.TextColor)
+
+ # ttk.Style().configure("TNotebook", background='red')
+ # ttk.Style().map("TNotebook.Tab", background=[("selected", 'orange')],
+ # foreground=[("selected", 'green')])
+ # ttk.Style().configure("TNotebook.Tab", background='blue', foreground='yellow')
+
+ if element.BorderWidth is not None:
+ element.TKFrame.configure(borderwidth=element.BorderWidth)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKFrame.bind('', element._RightClickMenuCallback)
+ # row_should_expand = True
+ # ------------------------- TabGroup element ------------------------- #
+ elif element_type == ELEM_TYPE_TAB_GROUP:
+ element=element # type: TabGroup
+ custom_style = str(element.Key) + 'customtab.TNotebook'
+ style = ttk.Style(tk_row_frame)
+ if element.Theme is not None:
+ style.theme_use(element.Theme)
+ if element.TabLocation is not None:
+ position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn',
+ 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw',
+ 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'}
+ try:
+ tab_position = position_dict[element.TabLocation]
+ except:
+ tab_position = position_dict['top']
+ style.configure(custom_style, tabposition=tab_position)
+
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ style.configure(custom_style, background=element.BackgroundColor, foreground='purple')
+
+ # style.theme_create("yummy", parent="alt", settings={
+ # "TNotebook": {"configure": {"tabmargins": [2, 5, 2, 0]}},
+ # "TNotebook.Tab": {
+ # "configure": {"padding": [5, 1], "background": mygreen},
+ # "map": {"background": [("selected", myred)],
+ # "expand": [("selected", [1, 1, 1, 0])]}}})
+
+ # style.configure(custom_style+'.Tab', background='red')
+ if element.SelectedTitleColor != None:
+ style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)])
+ if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
+ style.configure(custom_style + '.Tab', foreground=element.TextColor)
+ # style.configure(custom_style, background='blue', foreground='yellow')
+
+ element.TKNotebook = element.Widget = ttk.Notebook(tk_row_frame, style=custom_style)
+
+ PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form)
+
+ if element.ChangeSubmits:
+ element.TKNotebook.bind('<>', element._TabGroupSelectHandler)
+ if element.BorderWidth is not None:
+ element.TKNotebook.configure(borderwidth=element.BorderWidth)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ # row_should_expand = True
+ # ------------------------- SLIDER element ------------------------- #
+ elif element_type == ELEM_TYPE_INPUT_SLIDER:
+ element = element # type: Slider
+ slider_length = element_size[0] * CharWidthInPixels()
+ slider_width = element_size[1]
+ element.TKIntVar = tk.IntVar()
+ element.TKIntVar.set(element.DefaultValue)
+ if element.Orientation[0] == 'v':
+ range_from = element.Range[1]
+ range_to = element.Range[0]
+ slider_length += DEFAULT_MARGINS[1] * (element_size[0] * 2) # add in the padding
+ else:
+ range_from = element.Range[0]
+ range_to = element.Range[1]
+ if element.ChangeSubmits:
+ tkscale = element.Widget = tk.Scale(tk_row_frame, orient=element.Orientation,
+ variable=element.TKIntVar,
+ from_=range_from, to_=range_to, resolution=element.Resolution,
+ length=slider_length, width=slider_width,
+ bd=element.BorderWidth,
+ relief=element.Relief, font=font,
+ tickinterval=element.TickInterval,
+ command=element._SliderChangedHandler)
+ else:
+ tkscale = element.Widget = tk.Scale(tk_row_frame, orient=element.Orientation,
+ variable=element.TKIntVar,
+ from_=range_from, to_=range_to, resolution=element.Resolution,
+ length=slider_length, width=slider_width,
+ bd=element.BorderWidth,
+ relief=element.Relief, font=font,
+ tickinterval=element.TickInterval)
+ tkscale.config(highlightthickness=0)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ tkscale.configure(background=element.BackgroundColor)
+ if element.TroughColor != COLOR_SYSTEM_DEFAULT:
+ tkscale.config(troughcolor=element.TroughColor)
+ if element.DisableNumericDisplay:
+ tkscale.config(showvalue=0)
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ tkscale.configure(fg=text_color)
+ tkscale.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
+ if element.Visible is False:
+ tkscale.pack_forget()
+ element.TKScale = tkscale
+ if element.Disabled == True:
+ element.TKScale['state'] = 'disabled'
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+ # ------------------------- TABLE element ------------------------- #
+ elif element_type == ELEM_TYPE_TABLE:
+ element = element # type: Table
+ frame = tk.Frame(tk_row_frame)
+ element.table_frame = frame
+ height = element.NumRows
+ if element.Justification == 'left':
+ anchor = tk.W
+ elif element.Justification == 'right':
+ anchor = tk.E
+ else:
+ anchor = tk.CENTER
+ column_widths = {}
+ for row in element.Values:
+ for i, col in enumerate(row):
+ col_width = min(len(str(col)), element.MaxColumnWidth)
+ try:
+ if col_width > column_widths[i]:
+ column_widths[i] = col_width
+ except:
+ column_widths[i] = col_width
+
+ if element.ColumnsToDisplay is None:
+ displaycolumns = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0]
+ else:
+ displaycolumns = []
+ for i, should_display in enumerate(element.ColumnsToDisplay):
+ if should_display:
+ if element.ColumnHeadings is not None:
+ displaycolumns.append(element.ColumnHeadings[i])
+ else:
+ displaycolumns.append(str(i))
+
+ column_headings = element.ColumnHeadings if element.ColumnHeadings is not None else displaycolumns
+ if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns
+ displaycolumns = [element.RowHeaderText, ] + displaycolumns
+ if column_headings is not None:
+ column_headings = [element.RowHeaderText, ] + element.ColumnHeadings
+ else:
+ column_headings = [element.RowHeaderText, ] + displaycolumns
+ element.TKTreeview = element.Widget = ttk.Treeview(frame, columns=column_headings,
+ displaycolumns=displaycolumns, show='headings',
+ height=height,
+ selectmode=element.SelectMode, )
+ treeview = element.TKTreeview
+ if element.DisplayRowNumbers:
+ treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading
+ treeview.column(element.RowHeaderText, width=50, minwidth=10, anchor=anchor, stretch=0)
+
+ headings = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0]
+ for i, heading in enumerate(headings):
+ treeview.heading(heading, text=heading)
+ if element.AutoSizeColumns:
+ width = max(column_widths[i], len(heading))
+ else:
+ try:
+ width = element.ColumnWidths[i]
+ except:
+ width = element.DefaultColumnWidth
+ treeview.column(heading, width=width * CharWidthInPixels(),minwidth=10, anchor=anchor, stretch=0)
+
+ # Insert values into the tree
+ for i, value in enumerate(element.Values):
+ if element.DisplayRowNumbers:
+ value = [i + element.StartingRowNumber] + value
+ id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i)
+ element.tree_ids.append(id)
+ if element.AlternatingRowColor is not None: # alternating colors
+ for row in range(0, len(element.Values), 2):
+ treeview.tag_configure(row, background=element.AlternatingRowColor)
+ if element.RowColors is not None: # individual row colors
+ for row_def in element.RowColors:
+ if len(row_def) == 2: # only background is specified
+ treeview.tag_configure(row_def[0], background=row_def[1])
+ else:
+ treeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1])
+
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ ttk.Style().configure("Treeview", background=element.BackgroundColor,
+ fieldbackground=element.BackgroundColor)
+ if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
+ ttk.Style().configure("Treeview", foreground=element.TextColor)
+ if element.RowHeight is not None:
+ ttk.Style().configure("Treeview", rowheight=element.RowHeight)
+ ttk.Style().configure("Treeview", font=font)
+ # scrollable_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
+ treeview.bind("<>", element.treeview_selected)
+ if element.BindReturnKey:
+ treeview.bind('', element.treeview_double_click)
+ treeview.bind('', element.treeview_double_click)
+
+ if not element.HideVerticalScroll:
+ scrollbar = tk.Scrollbar(frame)
+ scrollbar.pack(side=tk.RIGHT, fill='y')
+ scrollbar.config(command=treeview.yview)
+ treeview.configure(yscrollcommand=scrollbar.set)
+
+ if not element.VerticalScrollOnly:
+ hscrollbar = tk.Scrollbar(frame, orient=tk.HORIZONTAL)
+ hscrollbar.pack(side=tk.BOTTOM, fill='x')
+ hscrollbar.config(command=treeview.xview)
+ treeview.configure(xscrollcommand=hscrollbar.set)
+
+ element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both')
+ if element.Visible is False:
+ element.TKTreeview.pack_forget()
+ frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKTreeview.bind('', element._RightClickMenuCallback)
+ # ------------------------- Tree element ------------------------- #
+ elif element_type == ELEM_TYPE_TREE:
+ element = element # type: Tree
+ frame = tk.Frame(tk_row_frame)
+
+ height = element.NumRows
+ if element.Justification == 'left': # justification
+ anchor = tk.W
+ elif element.Justification == 'right':
+ anchor = tk.E
+ else:
+ anchor = tk.CENTER
+
+ if element.ColumnsToDisplay is None: # Which cols to display
+ displaycolumns = element.ColumnHeadings
+ else:
+ displaycolumns = []
+ for i, should_display in enumerate(element.ColumnsToDisplay):
+ if should_display:
+ displaycolumns.append(element.ColumnHeadings[i])
+ column_headings = element.ColumnHeadings
+ # ------------- GET THE TREEVIEW WIDGET -------------
+ element.TKTreeview = element.Widget = ttk.Treeview(frame, columns=column_headings,
+ displaycolumns=displaycolumns, show='tree headings',
+ height=height,
+ selectmode=element.SelectMode)
+ treeview = element.TKTreeview
+ for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings
+ treeview.heading(heading, text=heading)
+ if element.AutoSizeColumns:
+ width = min(element.MaxColumnWidth, len(heading) + 1)
+ else:
+ try:
+ width = element.ColumnWidths[i]
+ except:
+ width = element.DefaultColumnWidth
+ treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor)
+
+ def add_treeview_data(node):
+ """
+
+ :param node:
+
+ """
+ # print(f'Inserting {node.key} under parent {node.parent}')
+ if node.key != '':
+ if node.icon:
+ if type(node.icon) is bytes:
+ photo = tk.PhotoImage(data=node.icon)
+ else:
+ photo = tk.PhotoImage(file=node.icon)
+ node.photo = photo
+ id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values,
+ open=element.ShowExpanded, image=node.photo)
+ element.IdToKey[id] = node.key
+ element.KeyToID[node.key] = id
+ else:
+ id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values,
+ open=element.ShowExpanded)
+ element.IdToKey[id] = node.key
+ element.KeyToID[node.key] = id
+
+ for node in node.children:
+ add_treeview_data(node)
+
+ add_treeview_data(element.TreeData.root_node)
+ treeview.column('#0', width=element.Col0Width * CharWidthInPixels(), anchor=anchor)
+ # ----- configure colors -----
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ ttk.Style().configure("Treeview", background=element.BackgroundColor,
+ fieldbackground=element.BackgroundColor)
+ if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
+ ttk.Style().configure("Treeview", foreground=element.TextColor)
+
+ ttk.Style().configure("Treeview", font=font)
+ if element.RowHeight:
+ ttk.Style().configure("Treeview", rowheight=element.RowHeight)
+ scrollbar = tk.Scrollbar(frame)
+ scrollbar.pack(side=tk.RIGHT, fill='y')
+ scrollbar.config(command=treeview.yview)
+ treeview.configure(yscrollcommand=scrollbar.set)
+ element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both')
+ if element.Visible is False:
+ element.TKTreeview.pack_forget()
+ frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0)
+ treeview.bind("<>", element.treeview_selected)
+ if element.Tooltip is not None: # tooltip
+ element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip,
+ timeout=DEFAULT_TOOLTIP_TIME)
+ if element.RightClickMenu or toplevel_form.RightClickMenu:
+ menu = element.RightClickMenu or toplevel_form.RightClickMenu
+ top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False)
+ AddMenuItem(top_menu, menu[1], element)
+ element.TKRightClickMenu = top_menu
+ element.TKTreeview.bind('', element._RightClickMenuCallback)
+ # ------------------------- Separator element ------------------------- #
+ elif element_type == ELEM_TYPE_SEPARATOR:
+ element = element # type: VerticalSeparator
+ separator = element.Widget = ttk.Separator(tk_row_frame, orient=element.Orientation, )
+ separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill='both', expand=True)
+ # ------------------------- StatusBar element ------------------------- #
+ elif element_type == ELEM_TYPE_STATUSBAR:
+ # auto_size_text = element.AutoSizeText
+ display_text = element.DisplayText # text to display
+ if auto_size_text is False:
+ width, height = element_size
+ else:
+ lines = display_text.split('\n')
+ max_line_len = max([len(l) for l in lines])
+ num_lines = len(lines)
+ if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap
+ width = element_size[0]
+ else:
+ width = max_line_len
+ height = num_lines
+ # ---===--- LABEL widget create and place --- #
+ stringvar = tk.StringVar()
+ element.TKStringVar = stringvar
+ stringvar.set(display_text)
+ if auto_size_text:
+ width = 0
+ if element.Justification is not None:
+ justification = element.Justification
+ elif toplevel_form.TextJustification is not None:
+ justification = toplevel_form.TextJustification
+ else:
+ justification = DEFAULT_TEXT_JUSTIFICATION
+ justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT
+ anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
+ # tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height,
+ # justify=justify, bd=border_depth, font=font)
+ tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width,
+ height=height,
+ justify=justify, bd=border_depth, font=font)
+ # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
+ wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels
+ if not auto_size_text and height == 1:
+ wraplen = 0
+ # print("wraplen, width, height", wraplen, width, height)
+ tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
+ if element.Relief is not None:
+ tktext_label.configure(relief=element.Relief)
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ tktext_label.configure(background=element.BackgroundColor)
+ if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
+ tktext_label.configure(fg=element.TextColor)
+ tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.BOTH, expand=True)
+ if element.Visible is False:
+ tktext_label.pack_forget()
+ element.TKText = tktext_label
+ if element.ClickSubmits:
+ tktext_label.bind('', element._TextClickedHandler)
+ if element.Tooltip is not None:
+ element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
+
+ # ............................DONE WITH ROW pack the row of widgets ..........................#
+ # done with row, pack the row of widgets
+ # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0])
+
+ if row_justify.lower().startswith('c'):
+ anchor='n'
+ side=tk.CENTER
+ elif row_justify.lower().startswith('r'):
+ anchor='ne'
+ side = tk.RIGHT
+ elif row_justify.lower().startswith('l'):
+ anchor='nw'
+ side = tk.LEFT
+ elif toplevel_form.ElementJustification.lower().startswith('c'):
+ anchor = 'n'
+ side = tk.TOP
+ elif toplevel_form.ElementJustification.lower().startswith('r'):
+ anchor = 'ne'
+ side = tk.TOP
+ else:
+ anchor = 'nw'
+ side = tk.TOP
+
+ # row_should_expand = False
+
+ tk_row_frame.pack(side=tk.TOP, anchor=anchor, padx=toplevel_form.Margins[0],
+ expand=row_should_expand, fill=tk.BOTH if row_should_expand else tk.NONE)
+ if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ tk_row_frame.configure(background=form.BackgroundColor)
+ toplevel_form.TKroot.configure(padx=toplevel_form.Margins[0], pady=toplevel_form.Margins[1])
+ return
+
+
+def ConvertFlexToTK(MyFlexForm):
+ """
+
+ :param MyFlexForm:
+
+ """
+ MyFlexForm # type: Window
+ master = MyFlexForm.TKroot
+ master.title(MyFlexForm.Title)
+ InitializeResults(MyFlexForm)
+ try:
+ if MyFlexForm.NoTitleBar:
+ if sys.platform == 'linux':
+ MyFlexForm.TKroot.wm_attributes("-type", "splash")
+ else:
+ MyFlexForm.TKroot.wm_overrideredirect(True)
+ except:
+ pass
+ PackFormIntoFrame(MyFlexForm, master, MyFlexForm)
+ # ....................................... DONE creating and laying out window ..........................#
+ if MyFlexForm._Size != (None, None):
+ master.geometry("%sx%s" % (MyFlexForm._Size[0], MyFlexForm._Size[1]))
+ screen_width = master.winfo_screenwidth() # get window info to move to middle of screen
+ screen_height = master.winfo_screenheight()
+ if MyFlexForm.Location != (None, None):
+ x, y = MyFlexForm.Location
+ elif DEFAULT_WINDOW_LOCATION != (None, None):
+ x, y = DEFAULT_WINDOW_LOCATION
+ else:
+ master.update_idletasks() # don't forget to do updates or values are bad
+ win_width = master.winfo_width()
+ win_height = master.winfo_height()
+ x = screen_width / 2 - win_width / 2
+ y = screen_height / 2 - win_height / 2
+ if y + win_height > screen_height:
+ y = screen_height - win_height
+ if x + win_width > screen_width:
+ x = screen_width - win_width
+
+ move_string = '+%i+%i' % (int(x), int(y))
+ master.geometry(move_string)
+
+ master.update_idletasks() # don't forget
+
+ return
+
+
+# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----#
+def StartupTK(my_flex_form):
+ """
+ NOT user callable
+ Creates the window (for real) lays out all the elements, etc. It's a HUGE set of things it does. It's the basic
+ "porting layer" that will change depending on the GUI framework PySimpleGUI is running on top of.
+
+ :param my_flex_form: (Window):
+
+ """
+ my_flex_form = my_flex_form # type: Window
+ # global _my_windows
+ # ow = _my_windows.NumOpenWindows
+ ow = Window.NumOpenWindows
+ # print('Starting TK open Windows = {}'.format(ow))
+ if ENABLE_TK_WINDOWS:
+ root = tk.Tk()
+ elif not ow and not my_flex_form.ForceTopLevel:
+ # if first window being created, make a throwaway, hidden master root. This stops one user
+ # window from becoming the child of another user window. All windows are children of this
+ # hidden window
+ Window.IncrementOpenCount()
+ Window.hidden_master_root = tk.Tk()
+ Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really
+ Window.hidden_master_root.wm_overrideredirect(True)
+ Window.hidden_master_root.withdraw()
+ root = tk.Toplevel()
+ else:
+ root = tk.Toplevel()
+
+ if my_flex_form.DebuggerEnabled:
+ root.bind('', my_flex_form._callback_main_debugger_window_create_keystroke)
+ root.bind('', my_flex_form._callback_popout_window_create_keystroke)
+
+ # root.bind('', Debugger._build_main_debugger_window)
+ # root.bind('', Debugger._build_floating_window)
+ try:
+ root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
+ except:
+ pass
+ if my_flex_form.BackgroundColor is not None and my_flex_form.BackgroundColor != COLOR_SYSTEM_DEFAULT:
+ root.configure(background=my_flex_form.BackgroundColor)
+ Window.IncrementOpenCount()
+
+ my_flex_form.TKroot = root
+ # Make moveable window
+ if (my_flex_form.GrabAnywhere is not False and not (
+ my_flex_form.NonBlocking and my_flex_form.GrabAnywhere is not True)):
+ root.bind("", my_flex_form._StartMove)
+ root.bind("", my_flex_form._StopMove)
+ root.bind("", my_flex_form._OnMotion)
+
+ if not my_flex_form.Resizable:
+ root.resizable(False, False)
+
+ if my_flex_form.DisableMinimize:
+ root.attributes("-toolwindow", 1)
+
+ if my_flex_form.KeepOnTop:
+ root.wm_attributes("-topmost", 1)
+
+ if my_flex_form.TransparentColor is not None:
+ my_flex_form.SetTransparentColor(my_flex_form.TransparentColor)
+
+ # root.protocol("WM_DELETE_WINDOW", MyFlexForm.DestroyedCallback())
+ # root.bind('', MyFlexForm.DestroyedCallback())
+ ConvertFlexToTK(my_flex_form)
+
+ my_flex_form.SetIcon(my_flex_form.WindowIcon)
+
+ try:
+ root.attributes('-alpha',
+ 1 if my_flex_form.AlphaChannel is None else my_flex_form.AlphaChannel) # Make window visible again
+ except:
+ pass
+
+ if my_flex_form.ReturnKeyboardEvents and not my_flex_form.NonBlocking:
+ root.bind("", my_flex_form._KeyboardCallback)
+ root.bind("", my_flex_form._MouseWheelCallback)
+ elif my_flex_form.ReturnKeyboardEvents:
+ root.bind("", my_flex_form._KeyboardCallback)
+ root.bind("", my_flex_form._MouseWheelCallback)
+
+ if my_flex_form.AutoClose:
+ duration = DEFAULT_AUTOCLOSE_TIME if my_flex_form.AutoCloseDuration is None else my_flex_form.AutoCloseDuration
+ my_flex_form.TKAfterID = root.after(int(duration * 1000), my_flex_form._AutoCloseAlarmCallback)
+
+ if my_flex_form.Timeout != None:
+ my_flex_form.TKAfterID = root.after(int(my_flex_form.Timeout), my_flex_form._TimeoutAlarmCallback)
+ if my_flex_form.NonBlocking:
+ my_flex_form.TKroot.protocol("WM_DESTROY_WINDOW", my_flex_form._OnClosingCallback)
+ my_flex_form.TKroot.protocol("WM_DELETE_WINDOW", my_flex_form._OnClosingCallback)
+ else: # it's a blocking form
+ # print('..... CALLING MainLoop')
+ my_flex_form.CurrentlyRunningMainloop = True
+ my_flex_form.TKroot.protocol("WM_DESTROY_WINDOW", my_flex_form._OnClosingCallback)
+ my_flex_form.TKroot.protocol("WM_DELETE_WINDOW", my_flex_form._OnClosingCallback)
+ my_flex_form.TKroot.mainloop()
+ my_flex_form.CurrentlyRunningMainloop = False
+ my_flex_form.TimerCancelled = True
+ # print('..... BACK from MainLoop')
+ if not my_flex_form.FormRemainedOpen:
+ Window.DecrementOpenCount()
+ # _my_windows.Decrement()
+ if my_flex_form.RootNeedsDestroying:
+ try:
+ my_flex_form.TKroot.destroy()
+ except:
+ pass
+ my_flex_form.RootNeedsDestroying = False
+ return
+
+
+# ==============================_GetNumLinesNeeded ==#
+# Helper function for determining how to wrap text #
+# ===================================================#
+def _GetNumLinesNeeded(text, max_line_width):
+ """
+
+ :param text:
+ :param max_line_width:
+
+ """
+ if max_line_width == 0:
+ return 1
+ lines = text.split('\n')
+ num_lines = len(lines) # number of original lines of text
+ max_line_len = max([len(l) for l in lines]) # longest line
+ lines_used = []
+ for L in lines:
+ lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up
+ total_lines_needed = sum(lines_used)
+ return total_lines_needed
+
+
+# ============================== PROGRESS METER ========================================== #
+
+def ConvertArgsToSingleString(*args):
+ """
+
+ :param *args:
+
+ """
+ max_line_total, width_used, total_lines, = 0, 0, 0
+ single_line_message = ''
+ # loop through args and built a SINGLE string from them
+ for message in args:
+ # fancy code to check if string and convert if not is not need. Just always convert to string :-)
+ # if not isinstance(message, str): message = str(message)
+ message = str(message)
+ longest_line_len = max([len(l) for l in message.split('\n')])
+ width_used = max(longest_line_len, width_used)
+ max_line_total = max(max_line_total, width_used)
+ lines_needed = _GetNumLinesNeeded(message, width_used)
+ total_lines += lines_needed
+ single_line_message += message + '\n'
+ return single_line_message, width_used, total_lines
+
+
+METER_REASON_CANCELLED = 'cancelled'
+METER_REASON_CLOSED = 'closed'
+METER_REASON_REACHED_MAX = 'finished'
+METER_OK = True
+METER_STOPPED = False
+
+
+class QuickMeter(object):
+ """ """
+ active_meters = {}
+ exit_reasons = {}
+
+ def __init__(self, title, current_value, max_value, key, *args, orientation='v', bar_color=(None, None),
+ button_color=(None, None), size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False):
+ """
+
+ :param title: text to display in eleemnt
+ :param current_value: current value
+ :param max_value: max value of QuickMeter
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :param *args: stuff to output
+ :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')
+ :param bar_color: ???????????????????????????????????
+ :param button_color: button color (foreground, background)
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)
+ :param border_width: width of border around element
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+
+ """
+ self.start_time = datetime.datetime.utcnow()
+ self.key = key
+ self.orientation = orientation
+ self.bar_color = bar_color
+ self.size = size
+ self.grab_anywhere = grab_anywhere
+ self.button_color = button_color
+ self.border_width = border_width
+ self.title = title
+ self.current_value = current_value
+ self.max_value = max_value
+ self.close_reason = None
+ self.window = self.BuildWindow(*args)
+
+ def BuildWindow(self, *args):
+ """
+
+ :param *args:
+
+ """
+ layout = []
+ if self.orientation.lower().startswith('h'):
+ col = []
+ col += [[T(''.join(map(lambda x: str(x) + '\n', args)),
+ key='_OPTMSG_')]] ### convert all *args into one string that can be updated
+ col += [[T('', size=(30, 10), key='_STATS_')],
+ [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size,
+ bar_color=self.bar_color)],
+ [Cancel(button_color=self.button_color), Stretch()]]
+ layout = [Column(col)]
+ else:
+ col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size,
+ bar_color=self.bar_color)]]
+ col2 = []
+ col2 += [[T(''.join(map(lambda x: str(x) + '\n', args)),
+ key='_OPTMSG_')]] ### convert all *args into one string that can be updated
+ col2 += [[T('', size=(30, 10), key='_STATS_')],
+ [Cancel(button_color=self.button_color), Stretch()]]
+ layout = [Column(col), Column(col2)]
+ self.window = Window(self.title, grab_anywhere=self.grab_anywhere, border_depth=self.border_width)
+ self.window.Layout([layout]).Finalize()
+
+ return self.window
+
+ def UpdateMeter(self, current_value, max_value, *args): ### support for *args when updating
+ """
+
+ :param current_value:
+ :param max_value:
+ :param *args:
+
+ """
+ self.current_value = current_value
+ self.max_value = max_value
+ self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value)
+ self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats()))
+ self.window.Element('_OPTMSG_').Update(
+ value=''.join(map(lambda x: str(x) + '\n', args))) ### update the string with the args
+ event, values = self.window.Read(timeout=0)
+ if event in ('Cancel', None) or current_value >= max_value:
+ self.window.Close()
+ del (QuickMeter.active_meters[self.key])
+ QuickMeter.exit_reasons[
+ self.key] = METER_REASON_CANCELLED if event == 'Cancel' else METER_REASON_CLOSED if event is None else METER_REASON_REACHED_MAX
+ return QuickMeter.exit_reasons[self.key]
+ return METER_OK
+
+ def ComputeProgressStats(self):
+ """ """
+ utc = datetime.datetime.utcnow()
+ time_delta = utc - self.start_time
+ total_seconds = time_delta.total_seconds()
+ if not total_seconds:
+ total_seconds = 1
+ try:
+ time_per_item = total_seconds / self.current_value
+ except:
+ time_per_item = 1
+ seconds_remaining = (self.max_value - self.current_value) * time_per_item
+ time_remaining = str(datetime.timedelta(seconds=seconds_remaining))
+ time_remaining_short = (time_remaining).split(".")[0]
+ time_delta_short = str(time_delta).split(".")[0]
+ total_time = time_delta + datetime.timedelta(seconds=seconds_remaining)
+ total_time_short = str(total_time).split(".")[0]
+ self.stat_messages = [
+ '{} of {}'.format(self.current_value, self.max_value),
+ '{} %'.format(100 * self.current_value // self.max_value),
+ '',
+ ' {:6.2f} Iterations per Second'.format(self.current_value / total_seconds),
+ ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.current_value if self.current_value else 1)),
+ '',
+ '{} Elapsed Time'.format(time_delta_short),
+ '{} Time Remaining'.format(time_remaining_short),
+ '{} Estimated Total Time'.format(total_time_short)]
+ return self.stat_messages
+
+
+def OneLineProgressMeter(title, current_value, max_value, key, *args, orientation='v', bar_color=(None, None),
+ button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False):
+ """
+
+ :param title: text to display
+ :param current_value: current progressbar value
+ :param max_value: max value of progressbar
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+ :param *args: stuff to output.
+ :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')
+ :param bar_color:
+ :param button_color: button color (foreground, background)
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)
+ :param border_width: width of border around element
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+
+ """
+ if key not in QuickMeter.active_meters:
+ meter = QuickMeter(title, current_value, max_value, key, *args, orientation=orientation, bar_color=bar_color,
+ button_color=button_color, size=size, border_width=border_width, grab_anywhere=grab_anywhere)
+ QuickMeter.active_meters[key] = meter
+ else:
+ meter = QuickMeter.active_meters[key]
+
+ rc = meter.UpdateMeter(current_value, max_value, *args) ### pass the *args to to UpdateMeter function
+ OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter, 'exit_reasons', QuickMeter.exit_reasons)
+ return rc == METER_OK
+
+
+def OneLineProgressMeterCancel(key):
+ """
+
+ :param key: Used with window.FindElement and with return values to uniquely identify this element
+
+ """
+ try:
+ meter = QuickMeter.active_meters[key]
+ meter.window.Close()
+ del (QuickMeter.active_meters[key])
+ QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED
+ except: # meter is already deleted
+ return
+
+
+# input is #RRGGBB
+# output is #RRGGBB
+def GetComplimentaryHex(color):
+ """
+
+ :param color:
+
+ """
+ # strip the # from the beginning
+ color = color[1:]
+ # convert the string into hex
+ color = int(color, 16)
+ # invert the three bytes
+ # as good as substracting each of RGB component by 255(FF)
+ comp_color = 0xFFFFFF ^ color
+ # convert the color back to hex by prefixing a #
+ comp_color = "#%06X" % comp_color
+ return comp_color
+
+
+# ======================== EasyPrint =====#
+# ===================================================#
+class DebugWin():
+ """ """
+ debug_window = None
+
+ def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False,
+ grab_anywhere=False, keep_on_top=False, do_not_reroute_stdout=True):
+ """
+
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high
+ :param location: (Default = (None))
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param no_button: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param do_not_reroute_stdout: (Default = True)
+
+ """
+ # Show a form that's a running counter
+ self.size = size
+ self.location = location
+ self.font = font
+ self.no_titlebar = no_titlebar
+ self.no_button = no_button
+ self.grab_anywhere = grab_anywhere
+ self.keep_on_top = keep_on_top
+ self.do_not_reroute_stdout = do_not_reroute_stdout
+
+ win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE
+ self.window = Window('Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location,
+ font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top)
+ self.output_element = Multiline(size=win_size, autoscroll=True,
+ key='_MULTILINE_') if do_not_reroute_stdout else Output(size=win_size)
+
+ if no_button:
+ self.layout = [[self.output_element]]
+ else:
+ self.layout = [
+ [self.output_element],
+ [DummyButton('Quit'), Stretch()]
+ ]
+ self.window.AddRows(self.layout)
+ self.window.Read(timeout=0) # Show a non-blocking form, returns immediately
+ return
+
+ def Print(self, *args, end=None, sep=None):
+ """
+
+ :param *args:
+ :param end:
+ :param sep:
+
+ """
+ sepchar = sep if sep is not None else ' '
+ endchar = end if end is not None else '\n'
+
+ if self.window is None: # if window was destroyed alread re-open it
+ self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar,
+ no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top,
+ do_not_reroute_stdout=self.do_not_reroute_stdout)
+ event, values = self.window.Read(timeout=0)
+ if event == 'Quit' or event is None:
+ self.Close()
+ self.__init__(size=self.size, location=self.location, font=self.font, no_titlebar=self.no_titlebar,
+ no_button=self.no_button, grab_anywhere=self.grab_anywhere, keep_on_top=self.keep_on_top,
+ do_not_reroute_stdout=self.do_not_reroute_stdout)
+ if self.do_not_reroute_stdout:
+ outstring = ''
+ for arg in args:
+ outstring += str(arg) + sepchar
+ outstring += endchar
+ self.output_element.Update(outstring, append=True)
+ else:
+ print(*args, sep=sepchar, end=endchar)
+
+ def Close(self):
+ """ """
+ self.window.Close()
+ del self.window
+ self.window = None
+
+
+def PrintClose():
+ """ """
+ EasyPrintClose()
+
+
+def EasyPrint(*args, size=(None, None), end=None, sep=None, location=(None, None), font=None, no_titlebar=False,
+ no_button=False, grab_anywhere=False, keep_on_top=False, do_not_reroute_stdout=True):
+ """
+
+ :param *args:
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high
+ :param end:
+ :param sep:
+ :param location: (Default = (None))
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param no_button: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param do_not_reroute_stdout: (Default = True)
+
+ """
+ if DebugWin.debug_window is None:
+ DebugWin.debug_window = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar,
+ no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top,
+ do_not_reroute_stdout=do_not_reroute_stdout)
+ DebugWin.debug_window.Print(*args, end=end, sep=sep)
+
+
+Print = EasyPrint
+eprint = EasyPrint
+
+
+def EasyPrintClose():
+ """ """
+ if DebugWin.debug_window is not None:
+ DebugWin.debug_window.Close()
+ DebugWin.debug_window = None
+
+
+# ============================== SetGlobalIcon ======#
+# Sets the icon to be used by default #
+# ===================================================#
+def SetGlobalIcon(icon):
+ """
+ Sets the icon which will be used any time a window is created if an icon is not provided when the
+ window is created.
+
+ :param icon: Union[bytes, str] Either a Base64 byte string or a filename
+ """
+
+ Window.user_defined_icon = icon
+
+
+# ============================== SetOptions =========#
+# Sets the icon to be used by default #
+# ===================================================#
+def SetOptions(icon=None, button_color=None, element_size=(None, None), button_element_size=(None, None),
+ margins=(None, None),
+ element_padding=(None, None), auto_size_text=None, auto_size_buttons=None, font=None, border_width=None,
+ slider_border_width=None, slider_relief=None, slider_orientation=None,
+ autoclose_time=None, message_box_line_width=None,
+ progress_meter_border_depth=None, progress_meter_style=None,
+ progress_meter_relief=None, progress_meter_color=None, progress_meter_size=None,
+ text_justification=None, background_color=None, element_background_color=None,
+ text_element_background_color=None, input_elements_background_color=None, input_text_color=None,
+ scrollbar_color=None, text_color=None, element_text_color=None, debug_win_size=(None, None),
+ window_location=(None, None), error_button_color=(None, None), tooltip_time=None):
+ """
+
+ :param icon: filename of icon used for taskbar and title bar
+ :param button_color: button color (foreground, background)
+ :param element_size: Tuple[int, int] element size (width, height) in characters
+ :param button_element_size: Tuple[int, int]
+ :param margins: tkinter margins around outsize (Default = (None))
+ :param element_padding: (Default = (None))
+ :param auto_size_text: True if size should fit the text length
+ :param auto_size_buttons:
+ :param font: specifies the font family, size, etc
+ :param border_width: width of border around element
+ :param slider_border_width:
+ :param slider_relief:
+ :param slider_orientation:
+ :param autoclose_time:
+ :param message_box_line_width:
+ :param progress_meter_border_depth:
+ :param progress_meter_style:
+ :param progress_meter_relief:
+ :param progress_meter_color:
+ :param progress_meter_size: Tuple[int, int]
+ :param text_justification:
+ :param background_color: color of background
+ :param element_background_color:
+ :param text_element_background_color:
+ :param input_elements_background_color:
+ :param input_text_color:
+ :param scrollbar_color:
+ :param text_color: color of the text
+ :param element_text_color:
+ :param debug_win_size: Tuple[int, int] (Default = (None))
+ :param window_location: (Default = (None))
+ :param error_button_color: (Default = (None))
+ :param tooltip_time: time in milliseconds to wait before showing a tooltip. Default is 400ms
+
+ """
+ global DEFAULT_ELEMENT_SIZE
+ global DEFAULT_BUTTON_ELEMENT_SIZE
+ global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term
+ global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels
+ global DEFAULT_AUTOSIZE_TEXT
+ global DEFAULT_AUTOSIZE_BUTTONS
+ global DEFAULT_FONT
+ global DEFAULT_BORDER_WIDTH
+ global DEFAULT_AUTOCLOSE_TIME
+ global DEFAULT_BUTTON_COLOR
+ global MESSAGE_BOX_LINE_WIDTH
+ global DEFAULT_PROGRESS_BAR_BORDER_WIDTH
+ global DEFAULT_PROGRESS_BAR_STYLE
+ global DEFAULT_PROGRESS_BAR_RELIEF
+ global DEFAULT_PROGRESS_BAR_COLOR
+ global DEFAULT_PROGRESS_BAR_SIZE
+ global DEFAULT_TEXT_JUSTIFICATION
+ global DEFAULT_DEBUG_WINDOW_SIZE
+ global DEFAULT_SLIDER_BORDER_WIDTH
+ global DEFAULT_SLIDER_RELIEF
+ global DEFAULT_SLIDER_ORIENTATION
+ global DEFAULT_BACKGROUND_COLOR
+ global DEFAULT_INPUT_ELEMENTS_COLOR
+ global DEFAULT_ELEMENT_BACKGROUND_COLOR
+ global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
+ global DEFAULT_SCROLLBAR_COLOR
+ global DEFAULT_TEXT_COLOR
+ global DEFAULT_WINDOW_LOCATION
+ global DEFAULT_ELEMENT_TEXT_COLOR
+ global DEFAULT_INPUT_TEXT_COLOR
+ global DEFAULT_TOOLTIP_TIME
+ global DEFAULT_ERROR_BUTTON_COLOR
+ # global _my_windows
+
+ if icon:
+ Window.user_defined_icon = icon
+ # _my_windows.user_defined_icon = icon
+
+ if button_color != None:
+ DEFAULT_BUTTON_COLOR = button_color
+
+ if element_size != (None, None):
+ DEFAULT_ELEMENT_SIZE = element_size
+
+ if button_element_size != (None, None):
+ DEFAULT_BUTTON_ELEMENT_SIZE = button_element_size
+
+ if margins != (None, None):
+ DEFAULT_MARGINS = margins
+
+ if element_padding != (None, None):
+ DEFAULT_ELEMENT_PADDING = element_padding
+
+ if auto_size_text != None:
+ DEFAULT_AUTOSIZE_TEXT = auto_size_text
+
+ if auto_size_buttons != None:
+ DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons
+
+ if font != None:
+ DEFAULT_FONT = font
+
+ if border_width != None:
+ DEFAULT_BORDER_WIDTH = border_width
+
+ if autoclose_time != None:
+ DEFAULT_AUTOCLOSE_TIME = autoclose_time
+
+ if message_box_line_width != None:
+ MESSAGE_BOX_LINE_WIDTH = message_box_line_width
+
+ if progress_meter_border_depth != None:
+ DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth
+
+ if progress_meter_style != None:
+ DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style
+
+ if progress_meter_relief != None:
+ DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief
+
+ if progress_meter_color != None:
+ DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color
+
+ if progress_meter_size != None:
+ DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size
+
+ if slider_border_width != None:
+ DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width
+
+ if slider_orientation != None:
+ DEFAULT_SLIDER_ORIENTATION = slider_orientation
+
+ if slider_relief != None:
+ DEFAULT_SLIDER_RELIEF = slider_relief
+
+ if text_justification != None:
+ DEFAULT_TEXT_JUSTIFICATION = text_justification
+
+ if background_color != None:
+ DEFAULT_BACKGROUND_COLOR = background_color
+
+ if text_element_background_color != None:
+ DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color
+
+ if input_elements_background_color != None:
+ DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color
+
+ if element_background_color != None:
+ DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color
+
+ if window_location != (None, None):
+ DEFAULT_WINDOW_LOCATION = window_location
+
+ if debug_win_size != (None, None):
+ DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size
+
+ if text_color != None:
+ DEFAULT_TEXT_COLOR = text_color
+
+ if scrollbar_color != None:
+ DEFAULT_SCROLLBAR_COLOR = scrollbar_color
+
+ if element_text_color != None:
+ DEFAULT_ELEMENT_TEXT_COLOR = element_text_color
+
+ if input_text_color is not None:
+ DEFAULT_INPUT_TEXT_COLOR = input_text_color
+
+ if tooltip_time is not None:
+ DEFAULT_TOOLTIP_TIME = tooltip_time
+
+ if error_button_color != (None, None):
+ DEFAULT_ERROR_BUTTON_COLOR = error_button_color
+
+ return True
+
+
+#################### ChangeLookAndFeel #######################
+# Predefined settings that will change the colors and styles #
+# of the elements. #
+##############################################################
+LOOK_AND_FEEL_TABLE = { 'SystemDefault':
+ {'BACKGROUND': COLOR_SYSTEM_DEFAULT,
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': COLOR_SYSTEM_DEFAULT,
+ 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT,
+ 'SCROLL': COLOR_SYSTEM_DEFAULT,
+ 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR,
+ 'PROGRESS': COLOR_SYSTEM_DEFAULT,
+ 'BORDER': 1, 'SLIDER_DEPTH': 1,
+ 'PROGRESS_DEPTH': 0},
+
+ 'SystemDefaultForReal':
+ {'BACKGROUND': COLOR_SYSTEM_DEFAULT,
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': COLOR_SYSTEM_DEFAULT,
+ 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT,
+ 'SCROLL': COLOR_SYSTEM_DEFAULT,
+ 'BUTTON': COLOR_SYSTEM_DEFAULT,
+ 'PROGRESS': COLOR_SYSTEM_DEFAULT,
+ 'BORDER': 1, 'SLIDER_DEPTH': 1,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Material1': {'BACKGROUND': '#E3F2FD',
+ 'TEXT': '#000000',
+ 'INPUT': '#86A8FF',
+ 'TEXT_INPUT': '#000000',
+ 'SCROLL': '#86A8FF',
+ 'BUTTON': ('#FFFFFF', '#5079D3'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 0, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#FF0266',
+ 'ACCENT2': '#FF5C93',
+ 'ACCENT3': '#C5003C'},
+
+ 'Material2': {'BACKGROUND': '#FAFAFA',
+ 'TEXT': '#000000',
+ 'INPUT': '#004EA1',
+ 'TEXT_INPUT': '#FFFFFF',
+ 'SCROLL': '#5EA7FF',
+ 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 0, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#FF0266',
+ 'ACCENT2': '#FF5C93',
+ 'ACCENT3': '#C5003C'},
+
+ 'Reddit': {'BACKGROUND': '#ffffff',
+ 'TEXT': '#1a1a1b',
+ 'INPUT': '#dae0e6',
+ 'TEXT_INPUT': '#222222',
+ 'SCROLL': '#a5a4a4',
+ 'BUTTON': ('white', '#0079d3'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#ff5414',
+ 'ACCENT2': '#33a8ff',
+ 'ACCENT3': '#dbf0ff'},
+
+ 'Topanga': {'BACKGROUND': '#282923',
+ 'TEXT': '#E7DB74',
+ 'INPUT': '#393a32',
+ 'TEXT_INPUT': '#E7C855',
+ 'SCROLL': '#E7C855',
+ 'BUTTON': ('#E7C855', '#284B5A'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#c15226',
+ 'ACCENT2': '#7a4d5f',
+ 'ACCENT3': '#889743'},
+
+ 'GreenTan': {'BACKGROUND': '#9FB8AD',
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': '#F7F3EC', 'TEXT_INPUT': 'black',
+ 'SCROLL': '#F7F3EC',
+ 'BUTTON': ('white', '#475841'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Dark': {'BACKGROUND': '#404040',
+ 'TEXT': 'white',
+ 'INPUT': '#4D4D4D',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('white', '#004F00'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightGreen': {'BACKGROUND': '#B7CECE',
+ 'TEXT': 'black',
+ 'INPUT': '#FDFFF7',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#FDFFF7',
+ 'BUTTON': ('white', '#658268'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'ACCENT1': '#76506d',
+ 'ACCENT2': '#5148f1',
+ 'ACCENT3': '#0a1c84',
+ 'PROGRESS_DEPTH': 0},
+
+ 'Dark2': {'BACKGROUND': '#404040',
+ 'TEXT': 'white',
+ 'INPUT': 'white',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('white', '#004F00'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Black': {'BACKGROUND': 'black',
+ 'TEXT': 'white',
+ 'INPUT': '#4D4D4D',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('black', 'white'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Tan': {'BACKGROUND': '#fdf6e3',
+ 'TEXT': '#268bd1',
+ 'INPUT': '#eee8d5',
+ 'TEXT_INPUT': '#6c71c3',
+ 'SCROLL': '#eee8d5',
+ 'BUTTON': ('white', '#063542'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'TanBlue': {'BACKGROUND': '#e5dece',
+ 'TEXT': '#063289',
+ 'INPUT': '#f9f8f4',
+ 'TEXT_INPUT': '#242834',
+ 'SCROLL': '#eee8d5',
+ 'BUTTON': ('white', '#063289'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkTanBlue': {'BACKGROUND': '#242834',
+ 'TEXT': '#dfe6f8',
+ 'INPUT': '#97755c',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#a9afbb',
+ 'BUTTON': ('white', '#063289'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkAmber': {'BACKGROUND': '#2c2825',
+ 'TEXT': '#fdcb52',
+ 'INPUT': '#705e52',
+ 'TEXT_INPUT': '#fdcb52',
+ 'SCROLL': '#705e52',
+ 'BUTTON': ('black', '#fdcb52'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBlue': {'BACKGROUND': '#1a2835',
+ 'TEXT': '#d1ecff',
+ 'INPUT': '#335267',
+ 'TEXT_INPUT': '#acc2d0',
+ 'SCROLL': '#1b6497',
+ 'BUTTON': ('black', '#fafaf8'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Reds': {'BACKGROUND': '#280001',
+ 'TEXT': 'white',
+ 'INPUT': '#d8d584',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#763e00',
+ 'BUTTON': ('black', '#daad28'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Green': {'BACKGROUND': '#82a459',
+ 'TEXT': 'black',
+ 'INPUT': '#d8d584',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#e3ecf3',
+ 'BUTTON': ('white', '#517239'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'BluePurple': {'BACKGROUND': '#A5CADD',
+ 'TEXT': '#6E266E',
+ 'INPUT': '#E0F5FF',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#E0F5FF',
+ 'BUTTON': ('white', '#303952'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Purple': {'BACKGROUND': '#B0AAC2',
+ 'TEXT': 'black',
+ 'INPUT': '#F2EFE8',
+ 'SCROLL': '#F2EFE8',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#C2D4D8'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'BlueMono': {'BACKGROUND': '#AAB6D3',
+ 'TEXT': 'black',
+ 'INPUT': '#F1F4FC',
+ 'SCROLL': '#F1F4FC',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#7186C7'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'GreenMono': {'BACKGROUND': '#A8C1B4',
+ 'TEXT': 'black',
+ 'INPUT': '#DDE0DE',
+ 'SCROLL': '#E3E3E3',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#6D9F85'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'BrownBlue': {'BACKGROUND': '#64778d',
+ 'TEXT': 'white',
+ 'INPUT': '#f0f3f7',
+ 'SCROLL': '#A6B2BE',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#283b5b'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'BrightColors': {'BACKGROUND': '#b4ffb4',
+ 'TEXT': 'black',
+ 'INPUT': '#ffff64',
+ 'SCROLL': '#ffb482',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#ffa0dc'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'NeutralBlue': {'BACKGROUND': '#92aa9d',
+ 'TEXT': 'black',
+ 'INPUT': '#fcfff6',
+ 'SCROLL': '#fcfff6',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#d0dbbd'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Kayak': {'BACKGROUND': '#a7ad7f',
+ 'TEXT': 'black',
+ 'INPUT': '#e6d3a8',
+ 'SCROLL': '#e6d3a8',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#5d907d'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'SandyBeach': {'BACKGROUND': '#efeccb',
+ 'TEXT': '#012f2f',
+ 'INPUT': '#e6d3a8',
+ 'SCROLL': '#e6d3a8',
+ 'TEXT_INPUT': '#012f2f',
+ 'BUTTON': ('white', '#046380'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'TealMono': {'BACKGROUND': '#a8cfdd',
+ 'TEXT': 'black',
+ 'INPUT': '#dfedf2',
+ 'SCROLL': '#dfedf2',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#183440'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+################################## Renamed Original Themes ##################################
+'Default':
+ {'BACKGROUND': COLOR_SYSTEM_DEFAULT,
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': COLOR_SYSTEM_DEFAULT,
+ 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT,
+ 'SCROLL': COLOR_SYSTEM_DEFAULT,
+ 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR,
+ 'PROGRESS': COLOR_SYSTEM_DEFAULT,
+ 'BORDER': 1, 'SLIDER_DEPTH': 1,
+ 'PROGRESS_DEPTH': 0},
+
+ 'Default1':
+ {'BACKGROUND': COLOR_SYSTEM_DEFAULT,
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': COLOR_SYSTEM_DEFAULT,
+ 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT,
+ 'SCROLL': COLOR_SYSTEM_DEFAULT,
+ 'BUTTON': COLOR_SYSTEM_DEFAULT,
+ 'PROGRESS': COLOR_SYSTEM_DEFAULT,
+ 'BORDER': 1, 'SLIDER_DEPTH': 1,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBlue': {'BACKGROUND': '#E3F2FD',
+ 'TEXT': '#000000',
+ 'INPUT': '#86A8FF',
+ 'TEXT_INPUT': '#000000',
+ 'SCROLL': '#86A8FF',
+ 'BUTTON': ('#FFFFFF', '#5079D3'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 0, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#FF0266',
+ 'ACCENT2': '#FF5C93',
+ 'ACCENT3': '#C5003C'},
+
+ 'LightGrey': {'BACKGROUND': '#FAFAFA',
+ 'TEXT': '#000000',
+ 'INPUT': '#004EA1',
+ 'TEXT_INPUT': '#FFFFFF',
+ 'SCROLL': '#5EA7FF',
+ 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 0, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#FF0266',
+ 'ACCENT2': '#FF5C93',
+ 'ACCENT3': '#C5003C'},
+
+ 'LightGrey1': {'BACKGROUND': '#ffffff',
+ 'TEXT': '#1a1a1b',
+ 'INPUT': '#dae0e6',
+ 'TEXT_INPUT': '#222222',
+ 'SCROLL': '#a5a4a4',
+ 'BUTTON': ('white', '#0079d3'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#ff5414',
+ 'ACCENT2': '#33a8ff',
+ 'ACCENT3': '#dbf0ff'},
+
+ 'DarkBrown': {'BACKGROUND': '#282923',
+ 'TEXT': '#E7DB74',
+ 'INPUT': '#393a32',
+ 'TEXT_INPUT': '#E7C855',
+ 'SCROLL': '#E7C855',
+ 'BUTTON': ('#E7C855', '#284B5A'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'ACCENT1': '#c15226',
+ 'ACCENT2': '#7a4d5f',
+ 'ACCENT3': '#889743'},
+
+ 'LightGreen1': {'BACKGROUND': '#9FB8AD',
+ 'TEXT': COLOR_SYSTEM_DEFAULT,
+ 'INPUT': '#F7F3EC', 'TEXT_INPUT': 'black',
+ 'SCROLL': '#F7F3EC',
+ 'BUTTON': ('white', '#475841'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkGrey': {'BACKGROUND': '#404040',
+ 'TEXT': 'white',
+ 'INPUT': '#4D4D4D',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('white', '#004F00'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightGreen2': {'BACKGROUND': '#B7CECE',
+ 'TEXT': 'black',
+ 'INPUT': '#FDFFF7',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#FDFFF7',
+ 'BUTTON': ('white', '#658268'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'ACCENT1': '#76506d',
+ 'ACCENT2': '#5148f1',
+ 'ACCENT3': '#0a1c84',
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkGrey1': {'BACKGROUND': '#404040',
+ 'TEXT': 'white',
+ 'INPUT': 'white',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('white', '#004F00'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBlack': {'BACKGROUND': 'black',
+ 'TEXT': 'white',
+ 'INPUT': '#4D4D4D',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#707070',
+ 'BUTTON': ('black', 'white'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBrown': {'BACKGROUND': '#fdf6e3',
+ 'TEXT': '#268bd1',
+ 'INPUT': '#eee8d5',
+ 'TEXT_INPUT': '#6c71c3',
+ 'SCROLL': '#eee8d5',
+ 'BUTTON': ('white', '#063542'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBrown1': {'BACKGROUND': '#e5dece',
+ 'TEXT': '#063289',
+ 'INPUT': '#f9f8f4',
+ 'TEXT_INPUT': '#242834',
+ 'SCROLL': '#eee8d5',
+ 'BUTTON': ('white', '#063289'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBlue1': {'BACKGROUND': '#242834',
+ 'TEXT': '#dfe6f8',
+ 'INPUT': '#97755c',
+ 'TEXT_INPUT': 'white',
+ 'SCROLL': '#a9afbb',
+ 'BUTTON': ('white', '#063289'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBrown1': {'BACKGROUND': '#2c2825',
+ 'TEXT': '#fdcb52',
+ 'INPUT': '#705e52',
+ 'TEXT_INPUT': '#fdcb52',
+ 'SCROLL': '#705e52',
+ 'BUTTON': ('black', '#fdcb52'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBlue2': {'BACKGROUND': '#1a2835',
+ 'TEXT': '#d1ecff',
+ 'INPUT': '#335267',
+ 'TEXT_INPUT': '#acc2d0',
+ 'SCROLL': '#1b6497',
+ 'BUTTON': ('black', '#fafaf8'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBrown2': {'BACKGROUND': '#280001',
+ 'TEXT': 'white',
+ 'INPUT': '#d8d584',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#763e00',
+ 'BUTTON': ('black', '#daad28'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkGreen': {'BACKGROUND': '#82a459',
+ 'TEXT': 'black',
+ 'INPUT': '#d8d584',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#e3ecf3',
+ 'BUTTON': ('white', '#517239'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBlue1': {'BACKGROUND': '#A5CADD',
+ 'TEXT': '#6E266E',
+ 'INPUT': '#E0F5FF',
+ 'TEXT_INPUT': 'black',
+ 'SCROLL': '#E0F5FF',
+ 'BUTTON': ('white', '#303952'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightPurple': {'BACKGROUND': '#B0AAC2',
+ 'TEXT': 'black',
+ 'INPUT': '#F2EFE8',
+ 'SCROLL': '#F2EFE8',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#C2D4D8'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBlue2': {'BACKGROUND': '#AAB6D3',
+ 'TEXT': 'black',
+ 'INPUT': '#F1F4FC',
+ 'SCROLL': '#F1F4FC',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#7186C7'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightGreen3': {'BACKGROUND': '#A8C1B4',
+ 'TEXT': 'black',
+ 'INPUT': '#DDE0DE',
+ 'SCROLL': '#E3E3E3',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#6D9F85'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'DarkBlue3': {'BACKGROUND': '#64778d',
+ 'TEXT': 'white',
+ 'INPUT': '#f0f3f7',
+ 'SCROLL': '#A6B2BE',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#283b5b'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightGreen4': {'BACKGROUND': '#b4ffb4',
+ 'TEXT': 'black',
+ 'INPUT': '#ffff64',
+ 'SCROLL': '#ffb482',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#ffa0dc'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightGreen5': {'BACKGROUND': '#92aa9d',
+ 'TEXT': 'black',
+ 'INPUT': '#fcfff6',
+ 'SCROLL': '#fcfff6',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('black', '#d0dbbd'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBrown2': {'BACKGROUND': '#a7ad7f',
+ 'TEXT': 'black',
+ 'INPUT': '#e6d3a8',
+ 'SCROLL': '#e6d3a8',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#5d907d'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBrown3': {'BACKGROUND': '#efeccb',
+ 'TEXT': '#012f2f',
+ 'INPUT': '#e6d3a8',
+ 'SCROLL': '#e6d3a8',
+ 'TEXT_INPUT': '#012f2f',
+ 'BUTTON': ('white', '#046380'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1, 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+ 'LightBlue3': {'BACKGROUND': '#a8cfdd',
+ 'TEXT': 'black',
+ 'INPUT': '#dfedf2',
+ 'SCROLL': '#dfedf2',
+ 'TEXT_INPUT': 'black',
+ 'BUTTON': ('white', '#183440'),
+ 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0},
+
+
+################################## End Renamed Original Themes ##################################
+
+
+#
+ 'LightBrown4': {'BACKGROUND': '#d7c79e', 'TEXT': '#a35638', 'INPUT': '#9dab86', 'TEXT_INPUT': '#000000', 'SCROLL': '#a35638', 'BUTTON': ('white', '#a35638'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#a35638', '#9dab86', '#e08f62', '#d7c79e'], },
+ 'DarkTeal': {'BACKGROUND': '#003f5c', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', 'BUTTON': ('white', '#fb5b5a'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], },
+ 'DarkPurple': {'BACKGROUND': '#472b62', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', 'BUTTON': ('#FFFFFF', '#472b62'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], },
+ 'LightGreen6': {'BACKGROUND': '#eafbea', 'TEXT': '#1f6650', 'INPUT': '#6f9a8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#1f6650', 'BUTTON': ('white', '#1f6650'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#1f6650', '#6f9a8d', '#ea5e5e', '#eafbea'], },
+ 'DarkGrey2': {'BACKGROUND': '#2b2b28', 'TEXT': '#f8f8f8', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', 'BUTTON': ('#2b2b28', '#e3b04b'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#2b2b28', '#e3b04b', '#f1d6ab', '#f8f8f8'], },
+ 'LightBrown6': {'BACKGROUND': '#f9b282', 'TEXT': '#8f4426', 'INPUT': '#de6b35', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8f4426', 'BUTTON': ('white', '#8f4426'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#8f4426', '#de6b35', '#64ccda', '#f9b282'], },
+ 'DarkTeal1': {'BACKGROUND': '#396362', 'TEXT': '#ffe7d1', 'INPUT': '#f6c89f', 'TEXT_INPUT': '#000000', 'SCROLL': '#f6c89f',
+ 'BUTTON': ('#ffe7d1', '#4b8e8d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'],},
+ 'LightBrown7': {'BACKGROUND': '#f6c89f', 'TEXT': '#396362', 'INPUT': '#4b8e8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#396362',
+ 'BUTTON': ('white', '#396362'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'],},
+ 'DarkPurple1': {'BACKGROUND': '#0c093c', 'TEXT': '#fad6d6', 'INPUT': '#eea5f6', 'TEXT_INPUT': '#000000', 'SCROLL': '#eea5f6', 'BUTTON': ('#FFFFFF', '#df42d1'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#0c093c', '#df42d1', '#eea5f6', '#fad6d6'], },
+ 'DarkGrey3': {'BACKGROUND': '#211717', 'TEXT': '#dfddc7', 'INPUT': '#f58b54', 'TEXT_INPUT': '#000000', 'SCROLL': '#f58b54', 'BUTTON': ('#dfddc7', '#a34a28'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], },
+ 'LightBrown8': {'BACKGROUND': '#dfddc7', 'TEXT': '#211717', 'INPUT': '#a34a28', 'TEXT_INPUT': '#dfddc7', 'SCROLL': '#211717', 'BUTTON': ('#dfddc7', '#a34a28'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], },
+ 'DarkBlue4': {'BACKGROUND': '#494ca2', 'TEXT': '#e3e7f1', 'INPUT': '#c6cbef', 'TEXT_INPUT': '#000000', 'SCROLL': '#c6cbef', 'BUTTON': ('#FFFFFF', '#8186d5'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#494ca2', '#8186d5', '#c6cbef', '#e3e7f1'],},
+ 'LightBlue4': {'BACKGROUND': '#5c94bd', 'TEXT': '#470938', 'INPUT': '#1a3e59', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#470938', 'BUTTON': ('white', '#470938'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#470938', '#1a3e59', '#5c94bd', '#f2d6eb'],},
+ 'DarkTeal2': {'BACKGROUND': '#394a6d', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97',
+ 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'],},
+ 'DarkTeal3': {'BACKGROUND': '#3c9d9b', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97',
+ 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], },
+ 'DarkPurple5': {'BACKGROUND': '#730068', 'TEXT': '#f6f078', 'INPUT': '#01d28e', 'TEXT_INPUT': '#000000', 'SCROLL': '#01d28e', 'BUTTON': ('#f6f078', '#730068'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#730068', '#434982', '#01d28e', '#f6f078'],},
+ 'DarkPurple2': {'BACKGROUND': '#202060', 'TEXT': '#b030b0', 'INPUT': '#602080', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#602080', 'BUTTON': ('white', '#202040'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#202040', '#202060', '#602080', '#b030b0'], },
+ 'DarkBlue5': {'BACKGROUND': '#000272', 'TEXT': '#ff6363', 'INPUT': '#a32f80', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#a32f80', 'BUTTON': ('#FFFFFF', '#341677'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#000272', '#341677', '#a32f80', '#ff6363'], },
+ 'LightGrey2': {'BACKGROUND': '#f6f6f6', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', 'BUTTON': ('#420000', '#d4d7dd'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'],},
+ 'LightGrey3': {'BACKGROUND': '#eae9e9', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', 'BUTTON': ('#420000', '#d4d7dd'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], },
+ 'DarkBlue6': {'BACKGROUND': '#01024e', 'TEXT': '#ff6464', 'INPUT': '#8b4367', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8b4367', 'BUTTON': ('#FFFFFF', '#543864'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#01024e', '#543864', '#8b4367', '#ff6464'],},
+ 'DarkBlue7': {'BACKGROUND': '#241663', 'TEXT': '#eae7af', 'INPUT': '#a72693', 'TEXT_INPUT': '#eae7af', 'SCROLL': '#a72693', 'BUTTON': ('#eae7af', '#160f30'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#160f30', '#241663', '#a72693', '#eae7af'], },
+ 'LightBrown9': {'BACKGROUND': '#f6d365', 'TEXT': '#3a1f5d', 'INPUT': '#c83660', 'TEXT_INPUT': '#f6d365', 'SCROLL': '#3a1f5d', 'BUTTON': ('#f6d365', '#c83660'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#3a1f5d', '#c83660', '#e15249', '#f6d365'], },
+ 'DarkPurple3': {'BACKGROUND': '#6e2142', 'TEXT': '#ffd692', 'INPUT': '#e16363', 'TEXT_INPUT': '#ffd692', 'SCROLL': '#e16363', 'BUTTON': ('#ffd692', '#943855'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], },
+ 'LightBrown10': {'BACKGROUND': '#ffd692', 'TEXT': '#6e2142', 'INPUT': '#943855', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6e2142', 'BUTTON': ('white', '#6e2142'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'],},
+ 'DarkPurple4': {'BACKGROUND': '#200f21', 'TEXT': '#f638dc', 'INPUT': '#5a3d5c', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#5a3d5c', 'BUTTON': ('#FFFFFF', '#382039'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#200f21', '#382039', '#5a3d5c', '#f638dc'],},
+ 'LightBlue5': {'BACKGROUND': '#b2fcff', 'TEXT': '#3e64ff', 'INPUT': '#5edfff', 'TEXT_INPUT': '#000000', 'SCROLL': '#3e64ff', 'BUTTON': ('white', '#3e64ff'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#3e64ff', '#5edfff', '#b2fcff', '#ecfcff'], },
+ 'DarkTeal4': {'BACKGROUND': '#464159', 'TEXT': '#c7f0db', 'INPUT': '#8bbabb', 'TEXT_INPUT': '#000000', 'SCROLL': '#8bbabb',
+ 'BUTTON': ('#FFFFFF', '#6c7b95'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], },
+ 'LightTeal': {'BACKGROUND': '#c7f0db', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159',
+ 'BUTTON': ('white', '#464159'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'],},
+ 'DarkTeal5': {'BACKGROUND': '#8bbabb', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159',
+ 'BUTTON': ('#c7f0db', '#6c7b95'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], },
+ 'LightGrey4': {'BACKGROUND': '#faf5ef', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', 'BUTTON': ('#672f2f', '#99b19c'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], },
+ 'LightGreen7': {'BACKGROUND': '#99b19c', 'TEXT': '#faf5ef', 'INPUT': '#d7d1c9', 'TEXT_INPUT': '#000000', 'SCROLL': '#d7d1c9', 'BUTTON': ('#FFFFFF', '#99b19c'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'],},
+ 'LightGrey5': {'BACKGROUND': '#d7d1c9', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', 'BUTTON': ('white', '#672f2f'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], },
+ 'DarkBrown3': {'BACKGROUND': '#a0855b', 'TEXT': '#f9f6f2', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', 'BUTTON': ('white', '#38470b'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], },
+ 'LightBrown11': {'BACKGROUND': '#f1d6ab', 'TEXT': '#38470b', 'INPUT': '#a0855b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#38470b', 'BUTTON': ('#f9f6f2', '#a0855b'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'],},
+ 'DarkRed': {'BACKGROUND': '#83142c', 'TEXT': '#f9d276', 'INPUT': '#ad1d45', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#ad1d45', 'BUTTON': ('#f9d276', '#ad1d45'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#44000d', '#83142c', '#ad1d45', '#f9d276'], },
+ 'DarkTeal6': {'BACKGROUND': '#204969', 'TEXT': '#fff7f7', 'INPUT': '#dadada', 'TEXT_INPUT': '#000000', 'SCROLL': '#dadada',
+ 'BUTTON': ('black', '#fff7f7'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#204969', '#08ffc8', '#dadada', '#fff7f7'],},
+ 'DarkBrown4': {'BACKGROUND': '#252525', 'TEXT': '#ff0000', 'INPUT': '#af0404', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#af0404', 'BUTTON': ('white', '#252525'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#252525', '#414141', '#af0404', '#ff0000'], },
+ 'LightYellow': {'BACKGROUND': '#f4ff61', 'TEXT': '#27aa80', 'INPUT': '#32ff6a', 'TEXT_INPUT': '#000000', 'SCROLL': '#27aa80', 'BUTTON': ('#f4ff61', '#27aa80'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#27aa80', '#32ff6a', '#a8ff3e', '#f4ff61'],},
+ 'DarkGreen1': {'BACKGROUND': '#2b580c', 'TEXT': '#fdef96', 'INPUT': '#f7b71d', 'TEXT_INPUT': '#000000', 'SCROLL': '#f7b71d', 'BUTTON': ('#fdef96', '#2b580c'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#2b580c', '#afa939', '#f7b71d', '#fdef96'], },
+ 'LightGreen8': {'BACKGROUND': '#c8dad3', 'TEXT': '#63707e', 'INPUT': '#93b5b3', 'TEXT_INPUT': '#000000', 'SCROLL': '#63707e', 'BUTTON': ('white', '#63707e'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#63707e', '#93b5b3', '#c8dad3', '#f2f6f5'], },
+ 'DarkTeal7': {'BACKGROUND': '#248ea9', 'TEXT': '#fafdcb', 'INPUT': '#aee7e8', 'TEXT_INPUT': '#000000', 'SCROLL': '#aee7e8', 'BUTTON': ('black', '#fafdcb'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#248ea9', '#28c3d4', '#aee7e8', '#fafdcb'],},
+'DarkBlue8': {'BACKGROUND': '#454d66', 'TEXT': '#d9d872', 'INPUT': '#58b368', 'TEXT_INPUT': '#000000', 'SCROLL': '#58b368',
+ 'BUTTON': ('black', '#009975'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#009975', '#454d66', '#58b368', '#d9d872'], },
+ 'DarkBlue9': {'BACKGROUND': '#263859', 'TEXT': '#ff6768', 'INPUT': '#6b778d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6b778d', 'BUTTON': ('#ff6768', '#263859'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#17223b', '#263859', '#6b778d', '#ff6768'], },
+ 'DarkBlue10': {'BACKGROUND': '#0028ff', 'TEXT': '#f1f4df', 'INPUT': '#10eaf0', 'TEXT_INPUT': '#000000', 'SCROLL': '#10eaf0', 'BUTTON': ('#f1f4df', '#24009c'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#24009c', '#0028ff', '#10eaf0', '#f1f4df'],},
+ 'DarkBlue11': {'BACKGROUND': '#6384b3', 'TEXT': '#e6f0b6', 'INPUT': '#b8e9c0', 'TEXT_INPUT': '#000000', 'SCROLL': '#b8e9c0', 'BUTTON': ('#e6f0b6', '#684949'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#684949', '#6384b3', '#b8e9c0', '#e6f0b6'], },
+
+ 'DarkTeal8': {'BACKGROUND': '#71a0a5', 'TEXT': '#212121', 'INPUT': '#665c84', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#212121', 'BUTTON': ('#fab95b', '#665c84'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#212121', '#665c84', '#71a0a5', '#fab95b']},
+ 'DarkRed1': {'BACKGROUND': '#c10000', 'TEXT': '#eeeeee', 'INPUT': '#dedede', 'TEXT_INPUT': '#000000', 'SCROLL': '#dedede', 'BUTTON': ('#c10000', '#eeeeee'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#c10000', '#ff4949', '#dedede', '#eeeeee'],},
+ 'LightBrown5': {'BACKGROUND': '#fff591', 'TEXT': '#e41749', 'INPUT': '#f5587b', 'TEXT_INPUT': '#000000', 'SCROLL': '#e41749', 'BUTTON': ('#fff591', '#e41749'),
+ 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#e41749', '#f5587b', '#ff8a5c', '#fff591']}
+ }
+
+def ListOfLookAndFeelValues():
+ """
+ Get a list of the valid values to pass into your call to change_look_and_feel
+ :return: List[str] - list of valid string values
+ """
+ return list(LOOK_AND_FEEL_TABLE.keys())
+
+
+def ChangeLookAndFeel(index, force=False):
+ """
+ Change the "color scheme" of all future PySimpleGUI Windows.
+ The scheme are string names that specify a group of colors. Background colors, text colors, button colors.
+ There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel
+ The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE.
+ The original list was (prior to a major rework and renaming)... these names still work...
+ SystemDefault
+ SystemDefaultForRead
+ Material1
+ Material2
+ Reddit
+ Topanga
+ GreenTan
+ Dark
+ LightGreen
+ Dark2
+ Black
+ Tan
+ TanBlue
+ DarkTanBlue
+ DarkAmber
+ DarkBlue
+ Reds
+ Green
+ BluePurple
+ Purple
+ BlueMono
+ GreenMono
+ BrownBlue
+ BrightColors
+ NeutralBlue
+ Kayak
+ SandyBeach
+ TealMono
+
+ In Nov 2019 a new Theme Formula was devised to make choosing a theme easier:
+ The "Formula" is:
+ ["Dark" or "Light"] Color Number
+ Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black
+ The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example.
+ Default = The default settings (only button color is different than system default)
+ Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....)
+ :param index: (str) the name of the index into the Look and Feel table
+ :param force: (bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors
+ """
+
+ # if sys.platform.startswith('darwin') and not force:
+ # print('*** Changing look and feel is not supported on Mac platform ***')
+ # return
+
+ theme = index
+ # normalize available l&f values
+ lf_values = [item.lower() for item in list_of_look_and_feel_values()]
+
+ # option 1
+ opt1 = theme.replace(' ', '').lower()
+
+ # option 2 (reverse lookup)
+ optx = theme.lower().split(' ')
+ optx.reverse()
+ opt2 = ''.join(optx)
+
+ # search for valid l&f name
+ if opt1 in lf_values:
+ ix = lf_values.index(opt1)
+ elif opt2 in lf_values:
+ ix = lf_values.index(opt2)
+ else:
+ ix = randint(0,len(lf_values))
+ print('** Warning - {} Look and Feel value not valid. Change your ChangeLookAndFeel call. **'.format(index))
+ print('valid values are', list_of_look_and_feel_values())
+ print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix]))
+
+ selection = list_of_look_and_feel_values()[ix]
+
+ try:
+ colors = LOOK_AND_FEEL_TABLE[selection]
+
+ SetOptions(background_color=colors['BACKGROUND'],
+ text_element_background_color=colors['BACKGROUND'],
+ element_background_color=colors['BACKGROUND'],
+ text_color=colors['TEXT'],
+ input_elements_background_color=colors['INPUT'],
+ button_color=colors['BUTTON'] if not sys.platform.startswith('darwin') else None,
+ progress_meter_color=colors['PROGRESS'],
+ border_width=colors['BORDER'],
+ slider_border_width=colors['SLIDER_DEPTH'],
+ progress_meter_border_depth=colors['PROGRESS_DEPTH'],
+ scrollbar_color=(colors['SCROLL']),
+ element_text_color=colors['TEXT'],
+ input_text_color=colors['TEXT_INPUT'])
+ except: # most likely an index out of range
+ print('** Warning - Look and Feel value not valid. Change your ChangeLookAndFeel call. **')
+ print('valid values are', list_of_look_and_feel_values())
+
+
+def preview_all_look_and_feel_themes():
+ """
+ Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available.
+ They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves
+ """
+ web=False
+
+ WINDOW_BACKGROUND = 'lightblue'
+
+ def sample_layout():
+ return [[Text('Text element'), InputText('Input data here', size=(15, 1))],
+ [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(10, 15))]]
+
+ layout = [[Text('Here is a complete list of themes', font='Default 18', background_color=WINDOW_BACKGROUND)]]
+
+ names = list_of_look_and_feel_values()
+ names.sort()
+ row = []
+ for count, theme in enumerate(names):
+ change_look_and_feel(theme)
+ if not count % 9:
+ layout += [row]
+ row = []
+ row += [Frame(theme, sample_layout() if not web else [[T(theme)]] + sample_layout())]
+ if row:
+ layout += [row]
+
+ window = Window('Preview of all Look and Feel choices', layout, background_color=WINDOW_BACKGROUND)
+ window.read()
+ window.close()
+ del window
+
+
+# Converts an object's contents into a nice printable string. Great for dumping debug data
+def ObjToStringSingleObj(obj):
+ """
+ Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form
+ Returns only the top-most object's variables instead of drilling down to dispolay more
+ :param obj: (Any) The object to display
+ returns (str) Formatted output of the object's values
+ """
+ if obj is None:
+ return 'None'
+ return str(obj.__class__) + '\n' + '\n'.join(
+ (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__)))
+
+
+def ObjToString(obj, extra=' '):
+ """
+ Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form
+ :param obj: (Any) The object to display
+ :param extra: (Default value = ' ')
+ returns (str) Formatted output of the object's values
+ """
+ if obj is None:
+ return 'None'
+ return str(obj.__class__) + '\n' + '\n'.join(
+ (extra + (str(item) + ' = ' +
+ (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str(
+ obj.__dict__[item])))
+ for item in sorted(obj.__dict__)))
+
+
+def test_func(parm):
+ """
+
+ :param parm:
+ :return:
+ """
+ return 'my return'
+
+
+
+######
+# # #### ##### # # ##### ####
+# # # # # # # # # # #
+###### # # # # # # # # ####
+# # # ##### # # ##### #
+# # # # # # # # #
+# #### # #### # ####
+
+
+# ------------------------------------------------------------------------------------------------------------------ #
+# ===================================== Upper PySimpleGUI ======================================================== #
+# ------------------------------------------------------------------------------------------------------------------ #
+# ----------------------------------- The mighty Popup! ------------------------------------------------------------ #
+
+def Popup(*args, title=None, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK,
+ auto_close=False, auto_close_duration=None, custom_text=(None, None), non_blocking=False,
+ icon=None, line_width=None,
+ font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the
+ "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages.
+
+ :param *args: (Any) Variable number of your arguments. Load up the call with stuff to see!
+ :param title: (str) Optional title for the window. If none provided, the first arg will be used instead.
+ :param button_color: Tuple[str, str] Color of the buttons shown (text color, button color)
+ :param background_color: (str) Window's background color
+ :param text_color: (str) text color
+ :param button_type: (enum) NOT USER SET! Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). There are many Popup functions and they call Popup, changing this parameter to get the desired effect.
+ :param auto_close: (bool) If True the window will automatically close
+ :param auto_close_duration: (int) time in seconds to keep window open before closing it automatically
+ :param custom_text: Union[Tuple[str, str], str] A string or pair of strings that contain the text to display on the buttons
+ :param non_blocking: (bool) If True then will immediately return from the function without waiting for the user's input.
+ :param icon: Union[str, bytes] icon to display on the window. Same format as a Window call
+ :param line_width: (int) Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH
+ :param font: Union[str, tuple(font name, size, modifiers) specifies the font family, size, etc
+ :param no_titlebar: (bool) If True will not show the frame around the window and the titlebar across the top
+ :param grab_anywhere: (bool) If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too
+ :param location: Tuple[int, int] Location on screen to display the top left corner of window. Defaults to window centered on screen
+ :return: Union[str, None] Returns text of the button that was pressed. None will be returned if user closed window with X
+ """
+
+ if not args:
+ args_to_print = ['']
+ else:
+ args_to_print = args
+ if line_width != None:
+ local_line_width = line_width
+ else:
+ local_line_width = MESSAGE_BOX_LINE_WIDTH
+ _title = title if title is not None else args_to_print[0]
+ window = Window(_title, auto_size_text=True, background_color=background_color, button_color=button_color,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font,
+ no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+ max_line_total, total_lines = 0, 0
+ for message in args_to_print:
+ # fancy code to check if string and convert if not is not need. Just always convert to string :-)
+ # if not isinstance(message, str): message = str(message)
+ message = str(message)
+ if message.count('\n'):
+ message_wrapped = message
+ else:
+ message_wrapped = textwrap.fill(message, local_line_width)
+ message_wrapped_lines = message_wrapped.count('\n') + 1
+ longest_line_len = max([len(l) for l in message.split('\n')])
+ width_used = min(longest_line_len, local_line_width)
+ max_line_total = max(max_line_total, width_used)
+ # height = _GetNumLinesNeeded(message, width_used)
+ height = message_wrapped_lines
+ window.AddRow(
+ Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color))
+ total_lines += height
+
+ if non_blocking:
+ PopupButton = DummyButton # important to use or else button will close other windows too!
+ else:
+ PopupButton = CloseButton
+ # show either an OK or Yes/No depending on paramater
+ if custom_text != (None, None):
+ if type(custom_text) is not tuple:
+ window.AddRow(PopupButton(custom_text, size=(len(custom_text), 1), button_color=button_color, focus=True,
+ bind_return_key=True))
+ elif custom_text[1] is None:
+ window.AddRow(
+ PopupButton(custom_text[0], size=(len(custom_text[0]), 1), button_color=button_color, focus=True,
+ bind_return_key=True))
+ else:
+ window.AddRow(PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True,
+ size=(len(custom_text[0]), 1)),
+ PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[0]), 1)))
+ elif button_type is POPUP_BUTTONS_YES_NO:
+ window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3),
+ size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1)))
+ elif button_type is POPUP_BUTTONS_CANCELLED:
+ window.AddRow(
+ PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3)))
+ elif button_type is POPUP_BUTTONS_ERROR:
+ window.AddRow(PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True,
+ pad=((20, 0), 3)))
+ elif button_type is POPUP_BUTTONS_OK_CANCEL:
+ window.AddRow(PopupButton('OK', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True),
+ PopupButton('Cancel', size=(6, 1), button_color=button_color))
+ elif button_type is POPUP_BUTTONS_NO_BUTTONS:
+ pass
+ else:
+ window.AddRow(PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True,
+ pad=((20, 0), 3)))
+
+ if non_blocking:
+ button, values = window.Read(timeout=0)
+ else:
+ button, values = window.Read()
+
+ return button
+
+
+# ============================== MsgBox============#
+# Lazy function. Same as calling Popup with parms #
+# This function WILL Disappear perhaps today #
+# ==================================================#
+# MsgBox is the legacy call and should not be used any longer
+def MsgBox(*args):
+ """
+ Do not call this anymore it will raise exception. Use Popups instead
+ :param *args:
+
+ """
+ raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup')
+
+
+
+# ======================== Scrolled Text Box =====#
+# ===================================================#
+def PopupScrolled(*args, title=None, button_color=None, yes_no=False, auto_close=False, auto_close_duration=None, size=(None, None),
+ location=(None, None),non_blocking=False):
+ """
+ Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you
+ want, just like a print statement.
+
+ :param *args: (Any) Variable number of items to display
+ :param title: (str) Title to display in the window.
+ :param button_color: Tuple[str, str] button color (foreground, background)
+ :param yes_no: (bool) If True, displays Yes and No buttons instead of Ok
+ :param auto_close: (bool) if True window will close itself
+ :param auto_close_duration: Union[int, float] Older versions only accept int. Time in seconds until window will close
+ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high
+ :param location: Tuple[int, int] Location on the screen to place the upper left corner of the window
+ :param non_blocking: (bool) if True the call will immediately return rather than waiting on user input
+ :return: Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X
+ """
+ if not args: return
+ width, height = size
+ width = width if width else MESSAGE_BOX_LINE_WIDTH
+ window = Window(title=title or args[0], auto_size_text=True, button_color=button_color, auto_close=auto_close,
+ auto_close_duration=auto_close_duration, location=location, resizable=True)
+ max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0
+ complete_output = ''
+ for message in args:
+ # fancy code to check if string and convert if not is not need. Just always convert to string :-)
+ # if not isinstance(message, str): message = str(message)
+ message = str(message)
+ longest_line_len = max([len(l) for l in message.split('\n')])
+ width_used = min(longest_line_len, width)
+ max_line_total = max(max_line_total, width_used)
+ max_line_width = width
+ lines_needed = _GetNumLinesNeeded(message, width_used)
+ height_computed += lines_needed
+ complete_output += message + '\n'
+ total_lines += lines_needed
+ height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed
+ if height:
+ height_computed = height
+ window.AddRow(Multiline(complete_output, size=(max_line_width, height_computed)))
+ pad = max_line_total - 15 if max_line_total > 15 else 1
+ # show either an OK or Yes/No depending on paramater
+ button = DummyButton if non_blocking else CloseButton
+ if yes_no:
+ window.AddRow(Text('', size=(pad, 1), auto_size_text=False), button('Yes'), button('No'))
+ else:
+ window.AddRow(Text('', size=(pad, 1), auto_size_text=False),
+ button('OK', size=(5, 1), button_color=button_color))
+
+ if non_blocking:
+ button, values = window.Read(timeout=0)
+ else:
+ button, values = window.Read()
+ # window.Close()
+ return button
+
+
+ScrolledTextBox = PopupScrolled
+
+# ============================== sprint ======#
+# Is identical to the Scrolled Text Box #
+# Provides a crude 'print' mechanism but in a #
+# GUI environment #
+# This is in addition to the Print function #
+# which routes output to a "Debug Window" #
+# ============================================#
+sprint = ScrolledTextBox
+
+
+
+
+# --------------------------- PopupNoButtons ---------------------------
+def PopupNoButtons(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """Show a Popup but without any buttons
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=POPUP_BUTTONS_NO_BUTTONS,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupNonBlocking ---------------------------
+def PopupNonBlocking(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None,
+ text_color=None,
+ auto_close=False, auto_close_duration=None, non_blocking=True, icon=None,
+ line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False,
+ location=(None, None)):
+ """
+ Show Popup window and immediately return (does not block)
+
+ :param *args:
+ :param title:
+ :param button_type: (Default value = POPUP_BUTTONS_OK)
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = True)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=button_type,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+PopupNoWait = PopupNonBlocking
+
+
+# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup ---------------------------
+def PopupQuick(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None,
+ text_color=None,
+ auto_close=True, auto_close_duration=2, non_blocking=True, icon=None, line_width=None,
+ font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Show Popup box that doesn't block and closes itself
+
+ :param *args:
+ :param title:
+ :param button_type: (Default value = POPUP_BUTTONS_OK)
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = True)
+ :param auto_close_duration: (Default value = 2)
+ :param non_blocking: (Default = True)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+ :param location:
+
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=button_type,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons ---------------------------
+def PopupQuickMessage(*args, title=None, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None,
+ text_color=None,
+ auto_close=True, auto_close_duration=2, non_blocking=True, icon=None,
+ line_width=None,
+ font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Show Popup window with no titlebar, doesn't block, and auto closes itself.
+
+ :param *args:
+ :param title:
+ :param button_type: (Default value = POPUP_BUTTONS_NO_BUTTONS)
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = True)
+ :param auto_close_duration: (Default value = 2)
+ :param non_blocking: (Default = True)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = True)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=button_type,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupNoTitlebar ---------------------------
+def PopupNoTitlebar(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None,
+ text_color=None,
+ auto_close=False, auto_close_duration=None, non_blocking=False, icon=None,
+ line_width=None, font=None, grab_anywhere=True, keep_on_top=False, location=(None, None)):
+ """
+ Display a Popup without a titlebar. Enables grab anywhere so you can move it
+
+ :param *args:
+ :param title:
+ :param button_type: (Default value = POPUP_BUTTONS_OK)
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param grab_anywhere: (Default = True)
+ :param location: Location on screen to display
+ :param location:
+
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=button_type,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+PopupNoFrame = PopupNoTitlebar
+PopupNoBorder = PopupNoTitlebar
+PopupAnnoying = PopupNoTitlebar
+
+
+# --------------------------- PopupAutoClose ---------------------------
+def PopupAutoClose(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None,
+ text_color=None,
+ auto_close=True, auto_close_duration=None, non_blocking=False, icon=None,
+ line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False,
+ location=(None, None)):
+ """Popup that closes itself after some time period
+
+ :param *args:
+ :param title:
+ :param button_type: (Default value = POPUP_BUTTONS_OK)
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = True)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+
+ """
+ Popup(*args, title=title, button_color=button_color, background_color=background_color, text_color=text_color,
+ button_type=button_type,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
+ line_width=line_width,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+PopupTimed = PopupAutoClose
+
+
+# --------------------------- PopupError ---------------------------
+def PopupError(*args, title=None, button_color=(None, None), background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Popup with colored button and 'Error' as button text
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location: (Default = (None))
+ """
+ tbutton_color = DEFAULT_ERROR_BUTTON_COLOR if button_color == (None, None) else button_color
+ return Popup(*args, title=title, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color,
+ non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=tbutton_color,
+ auto_close=auto_close,
+ auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere,
+ keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupCancel ---------------------------
+def PopupCancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Display Popup with "cancelled" button text
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+
+ """
+ return Popup(*args, title=title, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color,
+ text_color=text_color,
+ non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close,
+ auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere,
+ keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupOK ---------------------------
+def PopupOK(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Display Popup with OK button only
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :param location:
+ """
+ return Popup(*args, title=title, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color,
+ non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close,
+ auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere,
+ keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupOKCancel ---------------------------
+def PopupOKCancel(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Display popup with OK and Cancel buttons
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :return: Union["OK", "Cancel", None]
+ """
+ return Popup(*args, title=title, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color,
+ text_color=text_color,
+ non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar,
+ grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+# --------------------------- PopupYesNo ---------------------------
+def PopupYesNo(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False,
+ auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None,
+ no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Display Popup with Yes and No buttons
+
+ :param *args:
+ :param title:
+ :param button_color: button color (foreground, background)
+ :param background_color: color of background
+ :param text_color: color of the text
+ :param auto_close: (Default = False)
+ :param auto_close_duration:
+ :param non_blocking: (Default = False)
+ :param icon: Icon to display
+ :param line_width: Width of lines in characters
+ :param font: specifies the font family, size, etc
+ :param no_titlebar: (Default = False)
+ :param grab_anywhere: If True can grab anywhere to move the window (Default = False)
+ :param location: Location on screen to display
+ :return: Union["Yes", "No", None]
+ """
+ return Popup(*args, title=title, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color,
+ text_color=text_color,
+ non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color,
+ auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar,
+ grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+
+##############################################################################
+# The PopupGet_____ functions - Will return user input #
+##############################################################################
+
+# --------------------------- PopupGetFolder ---------------------------
+
+
+def PopupGetFolder(message, title=None, default_path='', no_window=False, size=(None, None), button_color=None,
+ background_color=None, text_color=None, icon=None, font=None, no_titlebar=False,
+ grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None):
+ """
+ Display popup with text entry field and browse button so that a folder can be chosen.
+
+ :param message: (str) message displayed to user
+ :param title: (str) Window title
+ :param default_path: (str) path to display to user as starting point (filled into the input field)
+ :param no_window: (bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown
+ :param size: Tuple[int, int] (width, height) of the InputText Element
+ :param button_color: Tuple[str, str] Color of the button (text, background)
+ :param background_color: (str) background color of the entire window
+ :param text_color: (str) color of the message text
+ :param icon: Union[bytes, str] filename or base64 string to be used for the window's icon
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param no_titlebar: (bool) If True no titlebar will be shown
+ :param grab_anywhere: (bool) If True can click and drag anywhere in the window to move the window
+ :param keep_on_top: (bool) If True the window will remain above all current windows
+ :param location: Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window
+ :param initial_folder: (str) location in filesystem to begin browsing
+ :return: Union[str, None] string representing the path chosen, None if cancelled or window closed with X
+ """
+
+ # global _my_windows
+ if no_window:
+ if not Window.hidden_master_root:
+ # if first window being created, make a throwaway, hidden master root. This stops one user
+ # window from becoming the child of another user window. All windows are children of this
+ # hidden window
+ Window.IncrementOpenCount()
+ Window.hidden_master_root = tk.Tk()
+ Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really
+ Window.hidden_master_root.wm_overrideredirect(True)
+ Window.hidden_master_root.withdraw()
+ root = tk.Toplevel()
+
+ try:
+ root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
+ root.wm_overrideredirect(True)
+ root.withdraw()
+ except:
+ pass
+ folder_name = tk.filedialog.askdirectory() # show the 'get folder' dialog box
+
+ root.destroy()
+ if Window.NumOpenWindows == 1:
+ Window.NumOpenWindows = 0
+ Window.hidden_master_root.destroy()
+ Window.hidden_master_root = None
+
+ return folder_name
+
+ layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)],
+ [InputText(default_text=default_path, size=size, key='_INPUT_'),
+ FolderBrowse(initial_folder=initial_folder)],
+ [Button('Ok', size=(5, 1), bind_return_key=True), Button('Cancel', size=(5, 1))]]
+
+ window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color,
+ background_color=background_color,
+ font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top,
+ location=location)
+
+ button, values = window.Read()
+ window.Close()
+ if button != 'Ok':
+ return None
+ else:
+ return values['_INPUT_']
+
+
+# --------------------------- PopupGetFile ---------------------------
+
+def PopupGetFile(message, title=None, default_path='', default_extension='', save_as=False, multiple_files=False,
+ file_types=(("ALL Files", "*.*"),),
+ no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None,
+ icon=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False,
+ location=(None, None), initial_folder=None):
+ """
+ Display popup window with text entry field and browse button so that a file can be chosen by user.
+
+ :param message: (str) message displayed to user
+ :param title: (str) Window title
+ :param default_path: (str) path to display to user as starting point (filled into the input field)
+ :param default_extension: (str) If no extension entered by user, add this to filename (only used in saveas dialogs)
+ :param save_as: (bool) if True, the "save as" dialog is shown which will verify before overwriting
+ :param multiple_files: (bool) if True, then allows multiple files to be selected that are returned with ';' between each filename
+ :param file_types: Tuple[Tuple[str,str]] List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.*"),)
+ :param no_window: (bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown
+ :param size: Tuple[int, int] (width, height) of the InputText Element
+ :param button_color: Tuple[str, str] Color of the button (text, background)
+ :param background_color: (str) background color of the entire window
+ :param text_color: (str) color of the message text
+ :param icon: Union[bytes, str] filename or base64 string to be used for the window's icon
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param no_titlebar: (bool) If True no titlebar will be shown
+ :param grab_anywhere: (bool) If True can click and drag anywhere in the window to move the window
+ :param keep_on_top: (bool) If True the window will remain above all current windows
+ :param location: Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window
+ :param initial_folder: (str) location in filesystem to begin browsing
+ :return: Union[str, None] string representing the file(s) chosen, None if cancelled or window closed with X
+ """
+
+ if no_window:
+ if not Window.hidden_master_root:
+ # if first window being created, make a throwaway, hidden master root. This stops one user
+ # window from becoming the child of another user window. All windows are children of this
+ # hidden window
+ Window.IncrementOpenCount()
+ Window.hidden_master_root = tk.Tk()
+ Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really
+ Window.hidden_master_root.wm_overrideredirect(True)
+ Window.hidden_master_root.withdraw()
+ root = tk.Toplevel()
+
+ try:
+ root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
+ root.wm_overrideredirect(True)
+ root.withdraw()
+ except:
+ pass
+ # TODO - Macs will not like this code because of the filetypes being used. Need another Darwin check.
+ if save_as:
+ filename = tk.filedialog.asksaveasfilename(filetypes=file_types,
+ initialdir = initial_folder,
+ defaultextension=default_extension) # show the 'get file' dialog box
+ elif multiple_files:
+ filename = tk.filedialog.askopenfilenames(filetypes=file_types,
+ initialdir=initial_folder,
+ defaultextension=default_extension) # show the 'get file' dialog box
+ else:
+ filename = tk.filedialog.askopenfilename(filetypes=file_types,
+ initialdir=initial_folder,
+ defaultextension=default_extension) # show the 'get files' dialog box
+
+ root.destroy()
+ if Window.NumOpenWindows == 1:
+ Window.NumOpenWindows = 0
+ Window.hidden_master_root.destroy()
+ Window.hidden_master_root = None
+ if not multiple_files and type(filename) in (tuple, list):
+ if len(filename): # only if not 0 length, otherwise will get an error
+ filename = filename[0]
+ return filename
+
+ if save_as:
+ browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder)
+ elif multiple_files:
+ browse_button = FilesBrowse(file_types=file_types, initial_folder=initial_folder)
+ else:
+ browse_button = FileBrowse(file_types=file_types, initial_folder=initial_folder)
+
+ layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)],
+ [InputText(default_text=default_path, size=size, key='_INPUT_'), browse_button],
+ [Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]]
+
+ window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color,
+ font=font,
+ background_color=background_color,
+ no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
+
+ button, values = window.Read()
+ window.Close()
+ if button != 'Ok':
+ return None
+ else:
+ path = values['_INPUT_']
+ return path
+
+
+# --------------------------- PopupGetText ---------------------------
+
+def PopupGetText(message, title=None, default_text='', password_char='', size=(None, None), button_color=None,
+ background_color=None, text_color=None, icon=None, font=None, no_titlebar=False,
+ grab_anywhere=False, keep_on_top=False, location=(None, None)):
+ """
+ Display Popup with text entry field. Returns the text entered or None if closed / cancelled
+
+ :param message: (str) message displayed to user
+ :param title: (str) Window title
+ :param default_text: (str) default value to put into input area
+ :param password_char: (str) character to be shown instead of actually typed characters
+ :param size: Tuple[int, int] (width, height) of the InputText Element
+ :param button_color: Tuple[str, str] Color of the button (text, background)
+ :param background_color: (str) background color of the entire window
+ :param text_color: (str) color of the message text
+ :param icon: Union[bytes, str] filename or base64 string to be used for the window's icon
+ :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc
+ :param no_titlebar: (bool) If True no titlebar will be shown
+ :param grab_anywhere: (bool) If True can click and drag anywhere in the window to move the window
+ :param keep_on_top: (bool) If True the window will remain above all current windows
+ :param location: Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window
+ :return: Union[str, None] Text entered or None if window was closed or cancel button clicked
+ """
+
+ layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)],
+ [InputText(default_text=default_text, size=size, key='_INPUT_', password_char=password_char)],
+ [Button('Ok', size=(5, 1), bind_return_key=True), Button('Cancel', size=(5, 1))]]
+
+ window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color,
+ no_titlebar=no_titlebar,
+ background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top,
+ location=location)
+
+ button, values = window.Read()
+ window.Close()
+ if button != 'Ok':
+ return None
+ else:
+ path = values['_INPUT_']
+ return path
+
+
+# --------------------------- PopupAnimated ---------------------------
+
+def PopupAnimated(image_source, message=None, background_color=None, text_color=None, font=None, no_titlebar=True,
+ grab_anywhere=True, keep_on_top=True, location=(None, None), alpha_channel=None,
+ time_between_frames=0, transparent_color=None):
+ """
+ Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency
+ and the rate the frames of video is shown remains constant. Maybe your frames update every 30 ms but your
+ event loop is running every 10 ms. You don't have to worry about delaying, just call it every time through the
+ loop.
+
+ :param image_source: Union[str, bytes] Either a filename or a base64 string.
+ :param message: (str) An optional message to be shown with the animation
+ :param background_color: (str) color of background
+ :param text_color: (str) color of the text
+ :param font: Union[str, tuple) specifies the font family, size, etc
+ :param no_titlebar: (bool) If True then the titlebar and window frame will not be shown
+ :param grab_anywhere: (bool) If True then you can move the window just clicking anywhere on window, hold and drag
+ :param keep_on_top: (bool) If True then Window will remain on top of all other windows currently shownn
+ :param location: (int, int) (x,y) location on the screen to place the top left corner of your window. Default is to center on screen
+ :param alpha_channel: (float) Window transparency 0 = invisible 1 = completely visible. Values between are see through
+ :param time_between_frames: (int) Amount of time in milliseconds between each frame
+ :param transparent_color: (str) This color will be completely see-through in your window. Can even click through
+ """
+ if image_source is None:
+ for image in Window.animated_popup_dict:
+ window = Window.animated_popup_dict[image]
+ window.Close()
+ Window.animated_popup_dict = {}
+ return
+
+ if image_source not in Window.animated_popup_dict:
+ if type(image_source) is bytes or len(image_source) > 300:
+ layout = [[Image(data=image_source, background_color=background_color, key='_IMAGE_', )], ]
+ else:
+ layout = [[Image(filename=image_source, background_color=background_color, key='_IMAGE_', )], ]
+ if message:
+ layout.append([Text(message, background_color=background_color, text_color=text_color, font=font)])
+
+ window = Window('Animated GIF', layout, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere,
+ keep_on_top=keep_on_top, background_color=background_color, location=location,
+ alpha_channel=alpha_channel, element_padding=(0, 0), margins=(0, 0),
+ transparent_color=transparent_color).Finalize()
+ Window.animated_popup_dict[image_source] = window
+ else:
+ window = Window.animated_popup_dict[image_source]
+ window.Element('_IMAGE_').UpdateAnimation(image_source, time_between_frames=time_between_frames)
+
+ window.Refresh() # call refresh instead of Read to save significant CPU time
+
+
+#####################################################################################################
+# Debugger
+#####################################################################################################
+
+
+PSGDebugLogo = b'R0lGODlhMgAtAPcAAAAAADD/2akK/4yz0pSxyZWyy5u3zZ24zpW30pG52J250J+60aC60KS90aDC3a3E163F2K3F2bPI2bvO3rzP3qvJ4LHN4rnR5P/zuf/zuv/0vP/0vsDS38XZ6cnb6f/xw//zwv/yxf/1w//zyP/1yf/2zP/3z//30wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAyAC0AAAj/AP8JHEiwoMGDCBMqXMiwoUOFAiJGXBigYoAPDxlK3CigwUGLIAOEyIiQI8cCBUOqJFnQpEkGA1XKZPlPgkuXBATK3JmRws2bB3TuXNmQw8+jQoeCbHj0qIGkSgNobNoUqlKIVJs++BfV4oiEWalaHVpyosCwJidw7Sr1YMQFBDn+y4qSbUW3AiDElXiWqoK1bPEKGLixr1jAXQ9GuGn4sN22Bl02roo4Kla+c8OOJbsQM9rNPJlORlr5asbPpTk/RP2YJGu7rjWnDm2RIQLZrSt3zgp6ZmqwmkHAng3ccWDEMe8Kpnw8JEHlkXnPdh6SxHPILaU/dp60LFUP07dfRq5aYntohAO0m+c+nvT6pVMPZ3jv8AJu8xktyNbw+ATJDtKFBx9NlA20gWU0DVQBYwZhsJMICRrkwEYJJGRCSBtEqGGCAQEAOw=='
+
+red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+
+COLOR_SCHEME = 'LightGreen'
+
+WIDTH_VARIABLES = 23
+WIDTH_RESULTS = 46
+
+WIDTH_WATCHER_VARIABLES = 20
+WIDTH_WATCHER_RESULTS = 60
+
+WIDTH_LOCALS = 80
+NUM_AUTO_WATCH = 9
+
+MAX_LINES_PER_RESULT_FLOATING = 4
+MAX_LINES_PER_RESULT_MAIN = 3
+
+POPOUT_WINDOW_FONT = 'Sans 8'
+
+class _Debugger():
+ """ """
+
+ debugger = None
+
+ # # ######
+ ## ## ## # # # # # ###### ##### # # #### #### ###### #####
+ # # # # # # # ## # # # # # # # # # # # # # # #
+ # # # # # # # # # # # ##### ##### # # # # ##### # #
+ # # ###### # # # # # # # # # # # # ### # ### # #####
+ # # # # # # ## # # # # # # # # # # # # # #
+ # # # # # # # ###### ###### ##### #### #### #### ###### # #
+
+ def __init__(self):
+ """ """
+ self.watcher_window = None # type: Window
+ self.popout_window = None # type: Window
+ self.local_choices = {}
+ self.myrc = ''
+ self.custom_watch = ''
+ self.locals = {}
+ self.globals = {}
+ self.popout_choices = {}
+
+
+ # Includes the DUAL PANE (now 2 tabs)! Don't forget REPL is there too!
+ def _build_main_debugger_window(self, location=(None, None)):
+ """
+
+ :param location:
+
+ """
+ ChangeLookAndFeel(COLOR_SCHEME)
+
+ def InVar(key1):
+ """
+
+ :param key1:
+
+ """
+ row1 = [T(' '),
+ I(key=key1, size=(WIDTH_VARIABLES, 1)),
+ T('', key=key1 + 'CHANGED_', size=(WIDTH_RESULTS, 1)), B('Detail', key=key1 + 'DETAIL_'),
+ B('Obj', key=key1 + 'OBJ_'), ]
+ return row1
+
+ variables_frame = [InVar('_VAR0_'),
+ InVar('_VAR1_'),
+ InVar('_VAR2_'), ]
+
+ interactive_frame = [[T('>>> '), In(size=(83, 1), key='_REPL_',
+ tooltip='Type in any "expression" or "statement"\n and it will be disaplayed below.\nPress RETURN KEY instead of "Go"\nbutton for faster use'),
+ B('Go', bind_return_key=True, visible=True)],
+ [Multiline(size=(93, 26), key='_OUTPUT_', autoscroll=True, do_not_clear=True)], ]
+
+ autowatch_frame = [[Button('Choose Variables To Auto Watch', key='_LOCALS_'),
+ Button('Clear All Auto Watches'),
+ Button('Show All Variables', key='_SHOW_ALL_'),
+ Button('Locals', key='_ALL_LOCALS_'),
+ Button('Globals', key='_GLOBALS_'),
+ Button('Popout', key='_POPOUT_')]]
+
+ var_layout = []
+ for i in range(NUM_AUTO_WATCH):
+ var_layout.append([T('', size=(WIDTH_WATCHER_VARIABLES, 1), key='_WATCH%s_' % i),
+ T('', size=(WIDTH_WATCHER_RESULTS, MAX_LINES_PER_RESULT_MAIN), key='_WATCH%s_RESULT_' % i,
+ )])
+
+ col1 = [
+ # [Frame('Auto Watches', autowatch_frame+variable_values, title_color='blue')]
+ [Frame('Auto Watches', autowatch_frame+var_layout, title_color='blue')]
+ ]
+
+ col2 = [
+ [Frame('Variables or Expressions to Watch', variables_frame, title_color='blue'), ],
+ [Frame('REPL-Light - Press Enter To Execute Commands', interactive_frame, title_color='blue'), ]
+ ]
+
+ # Tab based layout
+ layout = [[TabGroup([[Tab('Variables', col1), Tab('REPL & Watches', col2)]])],
+ [Button('', image_data=red_x, key='_EXIT_', button_color=None),]]
+
+ # ------------------------------- Create main window -------------------------------
+ window = Window("PySimpleGUI Debugger", layout, icon=PSGDebugLogo, margins=(0, 0), location=location).Finalize()
+ window.Element('_VAR1_').SetFocus()
+ self.watcher_window = window
+ ChangeLookAndFeel('SystemDefault') # set look and feel to default before exiting
+ return window
+
+ # # ####### #
+ ## ## ## # # # # # # ###### # # ##### # #### #### #####
+ # # # # # # # ## # # # # # ## # # # # # # # # #
+ # # # # # # # # # ##### # # ##### # # # # # # # # # # #
+ # # ###### # # # # # # # # # # # # # # # # # #####
+ # # # # # # ## # # # # # ## # # # # # # #
+ # # # # # # # ####### ## ###### # # # ####### #### #### #
+
+ def _refresh_main_debugger_window(self, mylocals, myglobals):
+ """
+
+ :param mylocals:
+ :param myglobals:
+
+ """
+ if not self.watcher_window: # if there is no window setup, nothing to do
+ return False
+ event, values = self.watcher_window.Read(timeout=1)
+ if event in (None, 'Exit', '_EXIT_'): # EXIT BUTTON / X BUTTON
+ try:
+ self.watcher_window.Close()
+ except: pass
+ self.watcher_window = None
+ return False
+ # ------------------------------- Process events from REPL Tab -------------------------------
+ cmd = values['_REPL_'] # get the REPL entered
+ # BUTTON - GO (NOTE - This button is invisible!!)
+ if event == 'Go': # GO BUTTON
+ self.watcher_window.Element('_REPL_').Update('')
+ self.watcher_window.Element('_OUTPUT_').Update(">>> {}\n".format(cmd), append=True, autoscroll=True)
+
+ try:
+ result = eval('{}'.format(cmd), myglobals, mylocals)
+ except Exception as e:
+ if sys.version_info[0] < 3:
+ result = 'Not available in Python 2'
+ else:
+ try:
+ result = exec('{}'.format(cmd), myglobals, mylocals)
+ except Exception as e:
+ result = 'Exception {}\n'.format(e)
+
+ self.watcher_window.Element('_OUTPUT_').Update('{}\n'.format(result), append=True, autoscroll=True)
+ # BUTTON - DETAIL
+ elif event.endswith('_DETAIL_'): # DETAIL BUTTON
+ var = values['_VAR{}_'.format(event[4])]
+ try:
+ result = str(eval(str(var), myglobals, mylocals))
+ except:
+ result = ''
+ PopupScrolled(str(values['_VAR{}_'.format(event[4])]) + '\n' + result, title=var, non_blocking=True)
+ # BUTTON - OBJ
+ elif event.endswith('_OBJ_'): # OBJECT BUTTON
+ var = values['_VAR{}_'.format(event[4])]
+ try:
+ result = ObjToStringSingleObj(mylocals[var])
+ except Exception as e:
+ try:
+ result = eval('{}'.format(var), myglobals, mylocals)
+ result = ObjToStringSingleObj(result)
+ except Exception as e:
+ result = '{}\nError showing object {}'.format(e, var)
+ PopupScrolled(str(var) + '\n' + str(result), title=var, non_blocking=True)
+ # ------------------------------- Process Watch Tab -------------------------------
+ # BUTTON - Choose Locals to see
+ elif event == '_LOCALS_': # Show all locals BUTTON
+ self._choose_auto_watches(mylocals)
+ # BUTTON - Locals (quick popup)
+ elif event == '_ALL_LOCALS_':
+ self._display_all_vars(mylocals)
+ # BUTTON - Globals (quick popup)
+ elif event == '_GLOBALS_':
+ self._display_all_vars(myglobals)
+ # BUTTON - clear all
+ elif event == 'Clear All Auto Watches':
+ if PopupYesNo('Do you really want to clear all Auto-Watches?', 'Really Clear??') == 'Yes':
+ self.local_choices = {}
+ self.custom_watch = ''
+ # BUTTON - Popout
+ elif event == '_POPOUT_':
+ if not self.popout_window:
+ self._build_floating_window()
+ # BUTTON - Show All
+ elif event == '_SHOW_ALL_':
+ for key in self.locals:
+ self.local_choices[key] = not key.startswith('_')
+
+ # -------------------- Process the manual "watch list" ------------------
+ for i in range(3):
+ key = '_VAR{}_'.format(i)
+ out_key = '_VAR{}_CHANGED_'.format(i)
+ self.myrc = ''
+ if self.watcher_window.Element(key):
+ var = values[key]
+ try:
+ result = eval(str(var), myglobals, mylocals)
+ except:
+ result = ''
+ self.watcher_window.Element(out_key).Update(str(result))
+ else:
+ self.watcher_window.Element(out_key).Update('')
+
+ # -------------------- Process the automatic "watch list" ------------------
+ slot = 0
+ for key in self.local_choices:
+ if key == '_CUSTOM_WATCH_':
+ continue
+ if self.local_choices[key]:
+ self.watcher_window.Element('_WATCH{}_'.format(slot)).Update(key)
+ try:
+ self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot), silent_on_error=True).Update(mylocals[key])
+ except:
+ self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot)).Update('')
+ slot += 1
+
+ if slot + int(not self.custom_watch in (None, '')) >= NUM_AUTO_WATCH:
+ break
+ # If a custom watch was set, display that value in the window
+ if self.custom_watch:
+ self.watcher_window.Element('_WATCH{}_'.format(slot)).Update(self.custom_watch)
+ try:
+ self.myrc = eval(self.custom_watch, myglobals, mylocals)
+ except:
+ self.myrc = ''
+ self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot)).Update(self.myrc)
+ slot += 1
+ # blank out all of the slots not used (blank)
+ for i in range(slot, NUM_AUTO_WATCH):
+ self.watcher_window.Element('_WATCH{}_'.format(i)).Update('')
+ self.watcher_window.Element('_WATCH{}_RESULT_'.format(i)).Update('')
+
+ return True # return indicating the window stayed open
+
+ ###### # #
+ # # #### ##### # # ##### # # # # # # ##### #### # #
+ # # # # # # # # # # # # # # ## # # # # # # #
+ ###### # # # # # # # # # # # # # # # # # # # # #
+ # # # ##### # # ##### # # # # # # # # # # # # ## #
+ # # # # # # # # # # # # ## # # # # ## ##
+ # #### # #### # ## ## # # # ##### #### # #
+
+ ###### # # #
+ # # # # # # ##### #### # # # # # # ## ##### ####
+ # # # # ## ## # # # # # # # # # # # # # #
+ # # # # # ## # # # #### # # # # # # # # # # ####
+ # # # # # # ##### # ####### # # # # ###### ##### #
+ # # # # # # # # # # # # # # # # # # # # #
+ ###### #### # # # #### # # ###### ###### # # # # # ####
+ # displays them into a single text box
+
+ def _display_all_vars(self, dict):
+ """
+
+ :param dict:
+
+ """
+ num_cols = 3
+ output_text = ''
+ num_lines = 2
+ cur_col = 0
+ out_text = 'All of your Vars'
+ longest_line = max([len(key) for key in dict])
+ line = []
+ sorted_dict = {}
+ for key in sorted(dict.keys()):
+ sorted_dict[key] = dict[key]
+ for key in sorted_dict:
+ value = dict[key]
+ wrapped_list = textwrap.wrap(str(value), 60)
+ wrapped_text = '\n'.join(wrapped_list)
+ out_text += '{} - {}\n'.format(key, wrapped_text)
+ if cur_col + 1 == num_cols:
+ cur_col = 0
+ num_lines += len(wrapped_list)
+ else:
+ cur_col += 1
+ ScrolledTextBox(out_text, non_blocking=True)
+
+ ##### # #
+# # # # #### #### #### ###### # # # ## ##### #### # #
+# # # # # # # # # # # # # # # # # # #
+# ###### # # # # #### ##### # # # # # # # ######
+# # # # # # # # # # # # ###### # # # #
+# # # # # # # # # # # # # # # # # # # # #
+ ##### # # #### #### #### ###### ## ## # # # #### # #
+
+# # # #
+# # ## ##### # ## ##### # ###### #### # # # # # #
+# # # # # # # # # # # # # # # # # # ## #
+# # # # # # # # # ##### # ##### #### # # # # # # #
+ # # ###### ##### # ###### # # # # # # # # # # # #
+ # # # # # # # # # # # # # # # # # # # # ##
+ # # # # # # # # ##### ###### ###### #### ## ## # # #
+
+ def _choose_auto_watches(self, my_locals):
+ """
+
+ :param my_locals:
+
+ """
+ ChangeLookAndFeel(COLOR_SCHEME)
+ num_cols = 3
+ output_text = ''
+ num_lines = 2
+ cur_col = 0
+ layout = [[Text('Choose your "Auto Watch" variables', font='ANY 14', text_color='red')]]
+ longest_line = max([len(key) for key in my_locals])
+ line = []
+ sorted_dict = {}
+ for key in sorted(my_locals.keys()):
+ sorted_dict[key] = my_locals[key]
+ for key in sorted_dict:
+ line.append(CB(key, key=key, size=(longest_line, 1),
+ default=self.local_choices[key] if key in self.local_choices else False))
+ if cur_col + 1 == num_cols:
+ cur_col = 0
+ layout.append(line)
+ line = []
+ else:
+ cur_col += 1
+ if cur_col:
+ layout.append(line)
+
+ layout += [
+ [Text('Custom Watch (any expression)'), Input(default_text=self.custom_watch, size=(40, 1), key='_CUSTOM_WATCH_')]]
+ layout += [
+ [Ok(), Cancel(), Button('Clear All'), Button('Select [almost] All', key='_AUTO_SELECT_')]]
+
+ window = Window('All Locals', layout, icon=PSGDebugLogo).Finalize()
+
+ while True: # event loop
+ event, values = window.Read()
+ if event in (None, 'Cancel'):
+ break
+ elif event == 'Ok':
+ self.local_choices = values
+ self.custom_watch = values['_CUSTOM_WATCH_']
+ break
+ elif event == 'Clear All':
+ PopupQuickMessage('Cleared Auto Watches', auto_close=True, auto_close_duration=3, non_blocking=True,
+ text_color='red', font='ANY 18')
+ for key in sorted_dict:
+ window.Element(key).Update(False)
+ window.Element('_CUSTOM_WATCH_').Update('')
+ elif event == 'Select All':
+ for key in sorted_dict:
+ window.Element(key).Update(False)
+ elif event == '_AUTO_SELECT_':
+ for key in sorted_dict:
+ window.Element(key).Update(not key.startswith('_'))
+
+ # exited event loop
+ window.Close()
+ ChangeLookAndFeel('SystemDefault')
+
+ ###### #######
+ # # # # # # ##### # # #### ## ##### # # # ####
+ # # # # # # # # # # # # # # # # ## # # #
+ ###### # # # # # # ##### # # # # # # # # # # #
+ # # # # # # # # # # # # ###### # # # # # # ###
+ # # # # # # # # # # # # # # # # # ## # #
+ ###### #### # ###### ##### # ###### #### # # # # # # ####
+
+ # #
+ # # # # # # ##### #### # #
+ # # # # ## # # # # # # #
+ # # # # # # # # # # # # #
+ # # # # # # # # # # # # ## #
+ # # # # # ## # # # # ## ##
+ ## ## # # # ##### #### # #
+
+ def _build_floating_window(self, location=(None, None)):
+ """
+
+ :param location:
+
+ """
+ if self.popout_window: # if floating window already exists, close it first
+ self.popout_window.Close()
+ ChangeLookAndFeel('Topanga')
+ num_cols = 2
+ width_var = 15
+ width_value = 30
+ layout = []
+ line = []
+ col = 0
+ # self.popout_choices = self.local_choices
+ self.popout_choices = {}
+ if self.popout_choices == {}: # if nothing chosen, then choose all non-_ variables
+ for key in sorted(self.locals.keys()):
+ self.popout_choices[key] = not key.startswith('_')
+
+ width_var = max([len(key) for key in self.popout_choices])
+ for key in self.popout_choices:
+ if self.popout_choices[key] is True:
+ value = str(self.locals.get(key))
+ h = min(len(value)//width_value + 1, MAX_LINES_PER_RESULT_FLOATING)
+ line += [Text('{}'.format(key), size=(width_var, 1), font=POPOUT_WINDOW_FONT),
+ Text(' = ', font=POPOUT_WINDOW_FONT),
+ Text(value, key=key, size=(width_value, h), font=POPOUT_WINDOW_FONT)]
+ if col + 1 < num_cols:
+ line += [VerticalSeparator(), T(' ')]
+ col += 1
+ if col >= num_cols:
+ layout.append(line)
+ line = []
+ col = 0
+ if col != 0:
+ layout.append(line)
+ layout = [[Column(layout), Column(
+ [[Button('', key='_EXIT_', image_data=red_x, button_color=('#282923', '#282923'), border_width=0)]])]]
+
+ self.popout_window = Window('Floating', layout, alpha_channel=0, no_titlebar=True, grab_anywhere=True,
+ element_padding=(0, 0), margins=(0, 0), keep_on_top=True,
+ right_click_menu=['&Right', ['Debugger::RightClick', 'Exit::RightClick']], location=location ).Finalize()
+ if location == (None, None):
+ screen_size = self.popout_window.GetScreenDimensions()
+ self.popout_window.Move(screen_size[0] - self.popout_window.Size[0], 0)
+ self.popout_window.SetAlpha(1)
+
+ ChangeLookAndFeel('SystemDefault')
+ return True
+
+ ######
+ # # ###### ###### ##### ###### #### # #
+ # # # # # # # # # #
+ ###### ##### ##### # # ##### #### ######
+ # # # # ##### # # # #
+ # # # # # # # # # # #
+ # # ###### # # # ###### #### # #
+
+ #######
+ # # #### ## ##### # # # ####
+ # # # # # # # # ## # # #
+ ##### # # # # # # # # # # #
+ # # # # ###### # # # # # # ###
+ # # # # # # # # # ## # #
+ # ###### #### # # # # # # ####
+
+ # #
+ # # # # # # ##### #### # #
+ # # # # ## # # # # # # #
+ # # # # # # # # # # # # #
+ # # # # # # # # # # # # ## #
+ # # # # # ## # # # # ## ##
+ ## ## # # # ##### #### # #
+
+ def _refresh_floating_window(self):
+ """ """
+ if not self.popout_window:
+ return
+ for key in self.popout_choices:
+ if self.popout_choices[key] is True and key in self.locals:
+ if key is not None and self.popout_window is not None:
+ self.popout_window.Element(key, silent_on_error=True).Update(self.locals.get(key))
+ event, values = self.popout_window.Read(timeout=1)
+ if event in (None, '_EXIT_', 'Exit::RightClick'):
+ self.popout_window.Close()
+ self.popout_window = None
+ elif event == 'Debugger::RightClick':
+ show_debugger_window()
+
+
+# 888 888 .d8888b. d8888 888 888 888 888
+# 888 888 d88P Y88b d88888 888 888 888 888
+# 888 888 888 888 d88P888 888 888 888 888
+# 888 888 .d8888b .d88b. 888d888 888 d88P 888 888 888 8888b. 88888b. 888 .d88b.
+# 888 888 88K d8P Y8b 888P" 888 d88P 888 888 888 "88b 888 "88b 888 d8P Y8b
+# 888 888 "Y8888b. 88888888 888 888 888 d88P 888 888 888 .d888888 888 888 888 88888888
+# Y88b. .d88P X88 Y8b. 888 Y88b d88P d8888888888 888 888 888 888 888 d88P 888 Y8b.
+# "Y88888P" 88888P' "Y8888 888 "Y8888P" d88P 888 888 888 "Y888888 88888P" 888 "Y8888
+
+# 8888888888 888 d8b
+# 888 888 Y8P
+# 888 888
+# 8888888 888 888 88888b. .d8888b 888888 888 .d88b. 88888b. .d8888b
+# 888 888 888 888 "88b d88P" 888 888 d88""88b 888 "88b 88K
+# 888 888 888 888 888 888 888 888 888 888 888 888 "Y8888b.
+# 888 Y88b 888 888 888 Y88b. Y88b. 888 Y88..88P 888 888 X88
+# 888 "Y88888 888 888 "Y8888P "Y888 888 "Y88P" 888 888 88888P'
+
+
+
+
+def show_debugger_window(location=(None, None), *args):
+ """
+ Shows the large main debugger window
+ :param location: Tuple[int, int] Locations (x,y) on the screen to place upper left corner of the window
+ :param *args: Not used
+ """
+ if _Debugger.debugger is None:
+ _Debugger.debugger = _Debugger()
+ debugger = _Debugger.debugger
+ frame = inspect.currentframe()
+ prev_frame = inspect.currentframe().f_back
+ # frame, *others = inspect.stack()[1]
+ try:
+ debugger.locals = frame.f_back.f_locals
+ debugger.globals = frame.f_back.f_globals
+ finally:
+ del frame
+
+ if not debugger.watcher_window:
+ debugger.watcher_window = debugger._build_main_debugger_window(location=location)
+ return True
+
+
+def show_debugger_popout_window(location=(None, None), *args):
+ """
+ Shows the smaller "popout" window. Default location is the upper right corner of your screen
+
+ :param location: Tuple[int, int] Locations (x,y) on the screen to place upper left corner of the window
+ :param *args: Not used
+ """
+ if _Debugger.debugger is None:
+ _Debugger.debugger = _Debugger()
+ debugger = _Debugger.debugger
+ frame = inspect.currentframe()
+ prev_frame = inspect.currentframe().f_back
+ # frame = inspect.getframeinfo(prev_frame)
+ # frame, *others = inspect.stack()[1]
+ try:
+ debugger.locals = frame.f_back.f_locals
+ debugger.globals = frame.f_back.f_globals
+ finally:
+ del frame
+ if debugger.popout_window:
+ debugger.popout_window.Close()
+ debugger.popout_window = None
+ debugger._build_floating_window(location=location)
+
+
+def _refresh_debugger():
+ """
+ Refreshes the debugger windows. USERS should NOT be calling this function. Within PySimpleGUI it is called for the USER every time the Window.Read function is called.
+
+ :return: rc (bool) False if user closed the main debugger window.
+ """
+ if _Debugger.debugger is None:
+ _Debugger.debugger = _Debugger()
+ debugger = _Debugger.debugger
+ Window.read_call_from_debugger = True
+ # frame = inspect.currentframe()
+ frame = inspect.currentframe().f_back
+ # frame, *others = inspect.stack()[1]
+ try:
+ debugger.locals = frame.f_back.f_locals
+ debugger.globals = frame.f_back.f_globals
+ finally:
+ del frame
+ debugger._refresh_floating_window() if debugger.popout_window else None
+ rc = debugger._refresh_main_debugger_window(debugger.locals, debugger.globals) if debugger.watcher_window else False
+ Window.read_call_from_debugger = False
+ return rc
+
+
+
+# d8b
+# Y8P
+#
+# 88888b.d88b. 8888b. 888 88888b.
+# 888 "888 "88b "88b 888 888 "88b
+# 888 888 888 .d888888 888 888 888
+# 888 888 888 888 888 888 888 888
+# 888 888 888 "Y888888 888 888 888
+
+
+
+def main():
+ """
+ The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements.
+
+ :return:
+ """
+ from random import randint
+ # preview_all_look_and_feel_themes()
+ ChangeLookAndFeel('Light Green 1')
+ # ------ Menu Definition ------ #
+ menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']],
+ ['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ],
+ ['&Debugger', ['Popout', 'Launch Debugger']],
+ ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']],
+ ['&Help', '&About...'], ]
+
+ treedata = TreeData()
+
+ treedata.Insert("", '_A_', 'Tree Item 1', [1, 2, 3], )
+ treedata.Insert("", '_B_', 'B', [4, 5, 6], )
+ treedata.Insert("_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], )
+ treedata.Insert("", '_C_', 'C', [], )
+ treedata.Insert("_C_", '_C1_', 'C1', ['or'], )
+ treedata.Insert("_A_", '_A2_', 'Sub Item 2', [None, None])
+ treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep'])
+ treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all'])
+
+ for i in range(100):
+ treedata.Insert('_C_', i, i, [])
+
+ frame1 = [
+ [Input('Input Text', size=(25, 1)), ],
+ [Multiline(size=(30, 5), default_text='Multiline Input')],
+ ]
+
+ frame2 = [
+ [Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], select_mode=SELECT_MODE_EXTENDED, size=(20, 5), no_scrollbar=True)],
+ [Combo(['Combo item 1',2,3,4 ], size=(20, 3), default_value=2, readonly=True, text_color='red', background_color='red', key='_COMBO1_')],
+ # [Combo(['Combo item 1', 2,3,4], size=(20, 3), readonly=False, text_color='red', background_color='red', key='_COMBO2_')],
+ [Spin([1, 2, 3, 'a','b','c'], size=(4, 3))],
+ ]
+
+ frame3 = [
+ [Checkbox('Checkbox1', True), Checkbox('Checkbox1')],
+ [Radio('Radio Button1', 1), Radio('Radio Button2', 1, default=True, tooltip='Radio 2')],
+ [T('', size=(1, 4))],
+ ]
+
+ frame4 = [
+ [Slider(range=(0, 100), orientation='v', size=(7, 15), default_value=40),
+ Slider(range=(0, 100), orientation='h', size=(11, 15), default_value=40), ],
+ ]
+ matrix = [[str(x * y) for x in range(1,5)] for y in range(1,8)]
+
+ frame5 = [
+ [Table(values=matrix, headings=matrix[0],
+ auto_size_columns=False, display_row_numbers=True, change_submits=False, justification='right',
+ num_rows=10, alternating_row_color='lightblue', key='_table_', text_color='black',
+ col_widths=[5, 5, 5, 5], size=(400, 200)), T(' '),
+ Tree(data=treedata, headings=['col1', 'col2', 'col3'], change_submits=True, auto_size_columns=True,
+ num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, )],
+ ]
+
+ graph_elem = Graph((800, 150), (0, 0), (800, 300), key='+GRAPH+')
+
+ frame6 = [
+ [graph_elem],
+ ]
+
+ tab1 = Tab('Graph Number 1', frame6, tooltip='tab 1', )
+ tab2 = Tab('Graph Number 2', [[]],)
+
+ layout1 = [
+ [Image(data=DEFAULT_BASE64_ICON)],
+ [Text('You are running the py file itself', font='ANY 15', tooltip='My tooltip', key='_TEXT1_')],
+ [Text('You should be importing it rather than running it', font='ANY 15')],
+ [Frame('Input Text Group', frame1, title_color='red'),
+ Text('VERSION\n{}'.format(__version__), size=(18, 3), text_color='red', font='ANY 24'),
+ Image(data=DEFAULT_BASE64_LOADING_GIF, key='_IMAGE_'),
+ ],
+ [Frame('Multiple Choice Group', frame2, title_color='green'),
+ Frame('Binary Choice Group', frame3, title_color='purple', tooltip='Binary Choice'),
+ Frame('Variable Choice Group', frame4, title_color='blue')],
+ [Column([[Frame('Structured Data Group', frame5, title_color='red', element_justification='l')]]), ],
+ # [Frame('Graphing Group', frame6)],
+ [TabGroup([[tab1, tab2]],key='_TAB_GROUP_' )],
+ [ProgressBar(max_value=800, size=(60, 25), key='+PROGRESS+'), Button('Button'), B('Normal', metadata='my metadata'),
+ Button('Exit', tooltip='Exit button')],
+ ]
+
+ layout = [[Menu(menu_def, key='_MENU_')]] + layout1
+ window = Window('Window Title', layout,
+ font=('Helvetica', 13),
+ # background_color='black',
+ right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']],
+ # transparent_color= '#9FB8AD',
+ resizable=True,
+ keep_on_top=True,
+ element_justification='left',
+ metadata='My window metadata',
+ # icon=PSG_DEBUGGER_LOGO
+ )
+ # graph_elem.DrawCircle((200, 200), 50, 'blue')
+ i = 0
+ while True: # Event Loop
+ event, values = window.Read(timeout=20)
+ if event != TIMEOUT_KEY:
+ print(event, values)
+ if event is None or event == 'Exit':
+ break
+ if i < 800:
+ graph_elem.DrawLine((i, 0), (i, randint(0, 300)), width=1, color='#{:06x}'.format(randint(0, 0xffffff)))
+ else:
+ graph_elem.Move(-1, 0)
+ graph_elem.DrawLine((i, 0), (i, randint(0, 300)), width=1, color='#{:06x}'.format(randint(0, 0xffffff)))
+ window['+PROGRESS+'].UpdateBar(i % 800)
+ window.Element('_IMAGE_').UpdateAnimation(DEFAULT_BASE64_LOADING_GIF, time_between_frames=50)
+ i += 1
+ if event == 'Button':
+ window.Element('_TEXT1_').SetTooltip('NEW TEXT')
+ window.SetTransparentColor('#9FB8AD')
+ window.Element('_MENU_').Update(visible=True)
+ elif event == 'Normal':
+ window.Normal()
+ window.Element('_MENU_').Update(visible=False)
+ print()
+ elif event == 'Popout':
+ show_debugger_popout_window()
+ elif event == 'Launch Debugger':
+ show_debugger_window()
+ elif event == 'About...':
+ popup('About this program...')
+ window.Close()
+
+
+
+# ------------------------ PEP8-ify The SDK ------------------------#
+
+change_look_and_feel = ChangeLookAndFeel
+convert_args_to_single_string = ConvertArgsToSingleString
+convert_flex_to_tk = ConvertFlexToTK
+easy_print = EasyPrint
+easy_print_close = EasyPrintClose
+fill_form_with_values = FillFormWithValues
+get_complimentary_hex = GetComplimentaryHex
+list_of_look_and_feel_values = ListOfLookAndFeelValues
+obj_to_string = ObjToString
+obj_to_string_single_obj = ObjToStringSingleObj
+one_line_progress_meter = OneLineProgressMeter
+one_line_progress_meter_cancel = OneLineProgressMeterCancel
+popup = Popup
+popup_animated = PopupAnimated
+popup_annoying = PopupAnnoying
+popup_auto_close = PopupAutoClose
+popup_cancel = PopupCancel
+popup_error = PopupError
+popup_get_file = PopupGetFile
+popup_get_folder = PopupGetFolder
+popup_get_text = PopupGetText
+popup_no_border = PopupNoBorder
+popup_no_buttons = PopupNoButtons
+popup_no_frame = PopupNoFrame
+popup_no_titlebar = PopupNoTitlebar
+popup_no_wait = PopupNoWait
+popup_non_blocking = PopupNonBlocking
+popup_ok = PopupOK
+popup_ok_cancel = PopupOKCancel
+popup_quick = PopupQuick
+popup_quick_message = PopupQuickMessage
+popup_scrolled = PopupScrolled
+popup_timed = PopupTimed
+popup_yes_no = PopupYesNo
+sgprint = Print
+sgprint_close = PrintClose
+quit = Quit
+rgb = RGB
+set_global_icon = SetGlobalIcon
+set_options = SetOptions
+
+test = main
+
+# __all__ = ['** YOUR from PySimpleGUI import * HAS BEEN BLOCKED. YOU ARE NOT ALLOWED THIS KIND OF IMPORT WITH THIS LIBRARY **'] # do not allow import *
+
+# -------------------------------- ENTRY POINT IF RUN STANDALONE -------------------------------- #
+if __name__ == '__main__':
+ main()
+ exit(69)
diff --git a/PySimpleGUI/CONTRIBUTING.md b/PySimpleGUI/CONTRIBUTING.md
deleted file mode 100644
index cc30e198a..000000000
--- a/PySimpleGUI/CONTRIBUTING.md
+++ /dev/null
@@ -1,7 +0,0 @@
-## Contributing to PySimpleGUI
-
-We are happy to receive issues describing bug reports and feature requests! If your bug report relates to a security vulnerability, please do not file a public issue, and please instead reach out to us at issues@PySimpleGUI.com.
-
-We do not accept (and do not wish to receive) contributions of user-created or third-party code, including patches, pull requests, or code snippets incorporated into submitted issues. Please do not send us any such code! Bug reports and feature requests should not include any source code.
-
-If you nonetheless submit any user-created or third-party code to us, (1) you assign to us all rights and title in or relating to the code; and (2) to the extent any such assignment is not fully effective, you hereby grant to us a royalty-free, perpetual, irrevocable, worldwide, unlimited, sublicensable, transferrable license under all intellectual property rights embodied therein or relating thereto, to exploit the code in any manner we choose, including to incorporate the code into PySimpleGUI and to redistribute it under any terms at our discretion.
diff --git a/PySimpleGUI/LICENSE.txt b/PySimpleGUI/LICENSE.txt
deleted file mode 100644
index 153d416dc..000000000
--- a/PySimpleGUI/LICENSE.txt
+++ /dev/null
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
\ No newline at end of file
diff --git a/PySimpleGUI/PySimpleGUI.py b/PySimpleGUI/PySimpleGUI.py
deleted file mode 100644
index ed5fa59d8..000000000
--- a/PySimpleGUI/PySimpleGUI.py
+++ /dev/null
@@ -1,26087 +0,0 @@
-#!/usr/bin/python3
-
-
-
-# .oPYo. .oPYo. o 8 .oPYo. o o o .pPYo.
-# 8 8 8 8 8 8 8 8 8 8
-# o8YooP' o o `Yooo. o8 ooYoYo. .oPYo. 8 .oPYo. 8 8 8 8 8oPYo.
-# 8 8 8 `8 8 8' 8 8 8 8 8 8oooo8 8 oo 8 8 8 8' `8
-# 8 8 8 8 8 8 8 8 8 8 8 8. 8 8 8 8 8 8. .P
-# 8 `YooP8 `YooP' 8 8 8 8 8YooP' 8 `Yooo' `YooP8 `YooP' 8 `YooP'
-# :..::::::....8 :.....::....:..:..8 ....:..:.....::....8 :.....:..:::::.....:
-# ::::::::::ooP'.::::::::::::::::::8 :::::::::::::::::::8 ::::::::::::::::::::
-# ::::::::::...::::::::::::::::::::..:::::::::::::::::::..::::::::::::::::::::
-
-# Copyright 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026 PySimpleGUI(tm)
-
-
-# '##::::::::'######:::'########::'##::::::::'#######::
-# ##:::::::'##... ##:: ##.... ##: ##:::::::'##.... ##:
-# ##::::::: ##:::..::: ##:::: ##: ##:::::::..::::: ##:
-# ##::::::: ##::'####: ########:: ##::::::::'#######::
-# ##::::::: ##::: ##:: ##.....::: ##::::::::...... ##:
-# ##::::::: ##::: ##:: ##:::::::: ##:::::::'##:::: ##:
-# ########:. ######::: ##:::::::: ########:. #######::
-# ........:::......::::..:::::::::........:::.......:::
-# '##:::::::'####::'######::'########:'##::: ##::'######::'########:'########::
-# ##:::::::. ##::'##... ##: ##.....:: ###:: ##:'##... ##: ##.....:: ##.... ##:
-# ##:::::::: ##:: ##:::..:: ##::::::: ####: ##: ##:::..:: ##::::::: ##:::: ##:
-# ##:::::::: ##:: ##::::::: ######::: ## ## ##:. ######:: ######::: ##:::: ##:
-# ##:::::::: ##:: ##::::::: ##...:::: ##. ####::..... ##: ##...:::: ##:::: ##:
-# ##:::::::: ##:: ##::: ##: ##::::::: ##:. ###:'##::: ##: ##::::::: ##:::: ##:
-# ########:'####:. ######:: ########: ##::. ##:. ######:: ########: ########::
-# ........::....:::......:::........::..::::..:::......:::........::........:::
-
-
-"""
- April 2026
-
- This release of PSG 6 contains most of the features that were in version 5. Some of the features
- that were removed include the maintenance upgrades, online documenation, and other features that
- relied on infrastructure that is no longer available. I'm planning on porting these back into
- version 6.
-
- This code is licensed under an LGPL3 license. Applications that were released under PSG 5 are
- also going to be released using LGPL3.
-
- Several years of development went into the PSG5 product. Now that the commercialization effort
- is closed down, a question remained as to what to do with the code. The choices were to let it
- sit and go unused or release it under open soruce. The documentation and other repos under the
- PySimpleGUI account all use version 5. Since those will stick around, it made sense that people
- should be able to install a version that matched the other matierials.
-
- -mike
-
-"""
-
-version = "6.0.5"
-
-
-
-"""
-Changelog since last major release
-
-6.0 5-Apr-2026 Initial release
-6.0.1 8-Apr-2026 Emoji change to main window
-6.0.2 8-May-2026 Fixed bug in Window.settings_save. If a window is closed using "X" or terminated in a
- similiar way, then the value None is written to the settings file for all keys.
- The fix is to check if all values are None. If so, skip saving the values
-6.0.3 13-May-2026 Added ability to print or insert images into Multiline Element. Use parameter "image"
-6.0.4 13-May-2026 Added image_subsample parameter to the print functions/methods for multiline element
-6.0.5 15-May-2026 Added "upgrade to Maintenance Release" capability. It's much like the PSG 5 feature
- but uses GitHub as the location of release. Can be invoked from Home Window, or
- using the psgupgrade command.
-"""
-
-
-__version__ = version.split()[0] # For PEP 396 and PEP 345
-
-# The shortened version of version
-try:
- ver = version.split(' ')[0]
-except:
- ver = ''
-
-
-port = 'PySimpleGUI'
-
-import os
-import sys
-
-
-# all of the tkinter involved imports
-import tkinter as tk
-from tkinter import filedialog
-from tkinter.colorchooser import askcolor
-from tkinter import ttk
-# import tkinter.scrolledtext as tkst
-import tkinter.font
-
-# end of tkinter specific imports
-# get the tkinter detailed version
-tclversion_detailed = tkinter.Tcl().eval('info patchlevel')
-framework_version = tclversion_detailed
-
-import tempfile
-
-
-import time
-import pickle
-import calendar
-import datetime
-import textwrap
-
-import socket
-import hashlib
-import inspect
-import traceback
-import difflib
-import copy
-import pprint
-import platform
-import pydoc # for the built-in PSG SDK Help Window
-
-try: # Because Raspberry Pi is still on 3.4....it's not critical if this module isn't imported on the Pi
- from typing import List, Any, Union, Tuple, Dict, SupportsAbs, Optional # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments
-except:
- print('*** Skipping import of Typing module. "pip3 install typing" to remove this warning ***')
-import random
-import warnings
-from math import floor
-from math import fabs
-from functools import wraps
-
-try: # Because Raspberry Pi is still on 3.4....
- # from subprocess import run, PIPE, Popen
- import subprocess
-except Exception as e:
- print('** Import error {} **'.format(e))
-
-import threading
-import itertools
-import json
-import configparser
-import queue
-
-try:
- import webbrowser
-
- webbrowser_available = True
-except:
- webbrowser_available = False
-# used for github upgrades
-import urllib.request
-import urllib.error
-import urllib.parse
-# Need ssl so that network access using urllib doesn't get errors (was happening on the Mac)
-import ssl
-ssl._create_default_https_context = ssl._create_unverified_context
-
-# import re
-import ctypes
-
-pil_import_attempted = pil_imported = False
-
-warnings.simplefilter('always', UserWarning)
-
-g_time_start = 0
-g_time_end = 0
-g_time_delta = 0
-
-
-# These timer routines are to help you quickly time portions of code. Place the timer_start call at the point
-# you want to start timing and the timer_stop at the end point. The delta between the start and stop calls
-# is returned from calling timer_stop
-
-def timer_start():
- """
- Time your code easily.... starts the timer.
- Uses the time.time value, a technique known to not be terribly accurage, but tis' gclose enough for our purposes
- """
- global g_time_start
-
- g_time_start = time.time()
-
-
-def timer_stop():
- """
- Time your code easily.... stop the timer and print the number of MILLISECONDS since the timer start
-
- :return: delta in MILLISECONDS from timer_start was called
- :rtype: int
- """
- global g_time_delta, g_time_end
-
- g_time_end = time.time()
- g_time_delta = g_time_end - g_time_start
- return int(g_time_delta * 1000)
-
-
-def timer_stop_usec():
- """
- Time your code easily.... stop the timer and print the number of MICROSECONDS since the timer start
-
- :return: delta in MICROSECONDS from timer_start was called
- :rtype: int
- """
- global g_time_delta, g_time_end
-
- g_time_end = time.time()
- g_time_delta = g_time_end - g_time_start
- return int(g_time_delta * 1000000)
-
-
-
-def _timeit(func):
- """
- Put @_timeit as a decorator to a function to get the time spent in that function printed out
-
- :param func: Decorated function
- :type func:
- :return: Execution time for the decorated function
- :rtype:
- """
-
- @wraps(func)
- def wrapper(*args, **kwargs):
- start = time.time()
- result = func(*args, **kwargs)
- end = time.time()
- print('{} executed in {:.4f} seconds'.format(func.__name__, end - start))
- return result
-
- return wrapper
-
-
-_timeit_counter = 0
-MAX_TIMEIT_COUNT = 1000
-_timeit_total = 0
-
-
-def _timeit_summary(func):
- """
- Same as the timeit decorator except that the value is shown as an averave
- Put @_timeit_summary as a decorator to a function to get the time spent in that function printed out
-
- :param func: Decorated function
- :type func:
- :return: Execution time for the decorated function
- :rtype:
- """
-
- @wraps(func)
- def wrapper(*args, **kwargs):
- global _timeit_counter, _timeit_total
-
- start = time.time()
- result = func(*args, **kwargs)
- end = time.time()
- _timeit_counter += 1
- _timeit_total += end - start
- if _timeit_counter > MAX_TIMEIT_COUNT:
- print('{} executed in {:.4f} seconds'.format(func.__name__, _timeit_total / MAX_TIMEIT_COUNT))
- _timeit_counter = 0
- _timeit_total = 0
- return result
-
- return wrapper
-
-
-def formatted_datetime_now():
- """
- Returns a string with current date and time formatted YYYY-MM-DD HH:MM:SS for easy logging
-
- :return: String with date and time formatted YYYY-MM-DD HH:MM:SS
- :rtype: (str)
- """
- now = datetime.datetime.now()
- current_time = now.strftime("%Y-%m-%d %H:%M:%S")
- return current_time
-
-
-def running_linux():
- """
- Determines the OS is Linux by using sys.platform
-
- Returns True if Linux
-
- :return: True if sys.platform indicates running Linux
- :rtype: (bool)
- """
- return sys.platform.startswith('linux')
-
-
-def running_mac():
- """
- Determines the OS is Mac by using sys.platform
-
- Returns True if Mac
-
- :return: True if sys.platform indicates running Mac
- :rtype: (bool)
- """
- return sys.platform.startswith('darwin')
-
-
-def running_windows():
- """
- Determines the OS is Windows by using sys.platform
-
- Returns True if Windows
-
- :return: True if sys.platform indicates running Windows
- :rtype: (bool)
- """
- return sys.platform.startswith('win')
-
-
-def running_trinket():
- """
- A special case for Trinket. Checks both the OS and the number of environment variables
- Currently, Trinket only has ONE environment variable. This fact is used to figure out if Trinket is being used.
-
- Returns True if "Trinket" (in theory)
-
- :return: True if sys.platform indicates Linux and the number of environment variables is 1
- :rtype: (bool)
- """
- if sys.platform.startswith('linux') and socket.gethostname().startswith('pygame-'):
- return True
- return False
-
-
-def running_replit():
- """
- A special case for REPLIT. Checks both the OS and for the existance of the number of environment variable REPL_OWNER
- Currently, Trinket only has ONE environment variable. This fact is used to figure out if Trinket is being used.
-
- Returns True if running on "replit"
-
- :return: True if sys.platform indicates Linux and setting REPL_OWNER is found in the environment variables
- :rtype: (bool)
- """
- if 'REPL_OWNER' in os.environ and sys.platform.startswith('linux'):
- return True
- return False
-
-
-# Handy python statements to increment and decrement with wrapping that I don't want to forget
-# count = (count + (MAX - 1)) % MAX # Decrement - roll over to MAX from 0
-# count = (count + 1) % MAX # Increment to MAX then roll over to 0
-
-# ----====----====----==== Constants the user CAN safely change ====----====----====----#
-
-# Base64 encoded GIF file
-DEFAULT_BASE64_ICON = b'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'
-
-DEFAULT_BASE64_ICON_16_BY_16 = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAACmUlEQVR4nFWQS2icVRiGn++c8/+ZS2ZiJ4guQkGQULFgNS66cFMQ6wVR8EJFXBUKxVWpROOFEgXxAtqFSMGKXQiKurC2CeLKldZLxIobpQkEWy3SmcY680/m/8/5PhfTVvrsn5f3fQXADBHBAGx1x0E8e4icQvvPyOzaKH9j6bEy5fMgs6DH2fT7WNy1iZnIFdlsLuNM+oC6e5K+QstDHJ58fHnh2U+7Mz+4mmto0Tca1wllsUSzeoTed5WY4ViZ87SrT2hnD9ONMOWhn6AVIBZf33l88cOVf298W2TYtKiRdidnsHGEF3bvFwD7fcdepvxRejECl3DyKkmf0sxtd83gsfOfXX/syOle1nrZRoWaOABD3R2O8QlzlKZ4CRh/M/vzWyA/urrz2o0lccujr+z8fFUHqXBOPJoEHwLBbgoACBkOR6UR77bx220XgC38E6ObruXEv5ZfW3nwBmm4hpYpktUCqbpAPvH9OOAKAqhBkA5RE1MTAe2eeuDkix+vV9OHHQNV8R4Rw/snmN91fjzBcS2VJtq5h4vfPrR04L3l3q2HnRt01PD4LFKO9kE8879qyFXZTKkHR7r0ze4Tz7/zRff2N70vOppIZHmBpj2EsBPLfuXQlze7q9Uvk0wgU1nfmPnoq3O3LOQTo06qYiTLhWrzIMY91Jp7CVkTr/uv/QAQAUwZmquJKye10gR4yqGBWyDPttK/WFJv5SD9cQO1iGGAOUzxuW2bOb1u5fQijZZHSIDgw1ZGw5LaZE65eQ6Ro+OAJMqECEiGSCCYpI2ZaV7ffswVvXeptwPihVRBfTJHdZXM3c9L9/5x+QM9oYWuJeFscpzVQVpTcz9hSHzuvqephvM4/ych66LpfYaDu5i/+xcOmfsPXNAyV3hjwl8AAAAASUVORK5CYII='
-
-DEFAULT_BASE64_LOADING_GIF = b'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'
-
-PSG_DEBUGGER_LOGO = b'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'
-
-UDEMY_ICON = b'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'
-
-PSG6_LOGO = b'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'
-
-
-BLANK_BASE64 = b'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='
-
-DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON
-
-DEFAULT_ELEMENT_SIZE = (45, 1) # In CHARACTERS
-DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS
-DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term
-DEFAULT_ELEMENT_PADDING = (5, 3) # Padding between elements (row, col) in pixels
-DEFAULT_AUTOSIZE_TEXT = True
-DEFAULT_AUTOSIZE_BUTTONS = True
-DEFAULT_FONT = ("Helvetica", 10)
-DEFAULT_TEXT_JUSTIFICATION = 'left'
-DEFAULT_BORDER_WIDTH = 1
-DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form
-DEFAULT_DEBUG_WINDOW_SIZE = (80, 20)
-DEFAULT_WINDOW_LOCATION = (None, None)
-MAX_SCROLLED_TEXT_BOX_HEIGHT = 50
-DEFAULT_TOOLTIP_TIME = 400
-DEFAULT_TOOLTIP_OFFSET = (0, -20)
-DEFAULT_KEEP_ON_TOP = None
-DEFAULT_SCALING = None
-DEFAULT_ALPHA_CHANNEL = 1.0
-DEFAULT_HIDE_WINDOW_WHEN_CREATING = True
-TOOLTIP_BACKGROUND_COLOR = "#ffffe0"
-TOOLTIP_FONT = None
-DEFAULT_USE_BUTTON_SHORTCUTS = False
-DEFAULT_DICT_TO_STRING_WIDTH = 80
-#################### COLOR STUFF ####################
-BLUES = ("#082567", "#0A37A3", "#00345B")
-PURPLES = ("#480656", "#4F2398", "#380474")
-GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532")
-YELLOWS = ("#F3FB62", "#F0F595")
-TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA")
-NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]),
- ('#000000', '#FFFFFF'),
- ('#FFFFFF', '#000000'),
- (YELLOWS[0], PURPLES[1]),
- (YELLOWS[0], GREENS[3]),
- (YELLOWS[0], BLUES[2]))
-
-COLOR_SYSTEM_DEFAULT = '1234567890' # A Magic Number kind of signal to PySimpleGUI that the color should not be set at all
-DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default
-OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0])
-
-# The "default PySimpleGUI theme"
-OFFICIAL_PYSIMPLEGUI_THEME = CURRENT_LOOK_AND_FEEL = 'Dark Blue 3'
-
-DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000")
-DEFAULT_BACKGROUND_COLOR = None
-DEFAULT_ELEMENT_BACKGROUND_COLOR = None
-DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
-DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None
-DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
-DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT
-DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT
-DEFAULT_SCROLLBAR_COLOR = None
-
-
-
-# A transparent button is simply one that matches the background
-# TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing'
-
-
-# --------------------------------------------------------------------------------
-# Progress Bar Relief Choices
-RELIEF_RAISED = 'raised'
-RELIEF_SUNKEN = 'sunken'
-RELIEF_FLAT = 'flat'
-RELIEF_RIDGE = 'ridge'
-RELIEF_GROOVE = 'groove'
-RELIEF_SOLID = 'solid'
-RELIEF_LIST = (RELIEF_RAISED, RELIEF_FLAT, RELIEF_SUNKEN, RELIEF_RIDGE, RELIEF_SOLID, RELIEF_GROOVE)
-
-# These are the spepific themes that tkinter offers
-THEME_DEFAULT = 'default' # this is a TTK theme, not a PSG theme!!!
-THEME_WINNATIVE = 'winnative'
-THEME_CLAM = 'clam'
-THEME_ALT = 'alt'
-THEME_CLASSIC = 'classic'
-THEME_VISTA = 'vista'
-THEME_XPNATIVE = 'xpnative'
-
-# The theme to use by default for all windows
-DEFAULT_TTK_THEME = THEME_DEFAULT
-ttk_theme_in_use = None
-
-
-USE_TTK_BUTTONS = None
-
-DEFAULT_PROGRESS_BAR_COLOR = ("#01826B", '#D0D0D0') # a nice green progress bar
-DEFAULT_PROGRESS_BAR_COMPUTE = ('#000000', '#000000') # Means that the progress bar colors should be computed from other colors
-DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = ("#01826B", '#D0D0D0') # a nice green progress bar
-DEFAULT_PROGRESS_BAR_SIZE = (20, 20) # Size of Progress Bar (characters for length, pixels for width)
-DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1
-DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE
-# PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative')
-DEFAULT_PROGRESS_BAR_STYLE = DEFAULT_TTK_THEME
-DEFAULT_METER_ORIENTATION = 'Horizontal'
-DEFAULT_SLIDER_ORIENTATION = 'vertical'
-DEFAULT_SLIDER_BORDER_WIDTH = 1
-DEFAULT_SLIDER_RELIEF = tk.FLAT
-DEFAULT_FRAME_RELIEF = tk.GROOVE
-
-DEFAULT_LISTBOX_SELECT_MODE = tk.SINGLE
-SELECT_MODE_MULTIPLE = tk.MULTIPLE
-LISTBOX_SELECT_MODE_MULTIPLE = 'multiple'
-SELECT_MODE_BROWSE = tk.BROWSE
-LISTBOX_SELECT_MODE_BROWSE = 'browse'
-SELECT_MODE_EXTENDED = tk.EXTENDED
-LISTBOX_SELECT_MODE_EXTENDED = 'extended'
-SELECT_MODE_SINGLE = tk.SINGLE
-LISTBOX_SELECT_MODE_SINGLE = 'single'
-
-TABLE_SELECT_MODE_NONE = tk.NONE
-TABLE_SELECT_MODE_BROWSE = tk.BROWSE
-TABLE_SELECT_MODE_EXTENDED = tk.EXTENDED
-DEFAULT_TABLE_SELECT_MODE = TABLE_SELECT_MODE_EXTENDED
-TABLE_CLICKED_INDICATOR = '+CLICKED+' # Part of the tuple returned as an event when a Table element has click events enabled
-TABLE_EDITED_INDICATOR = '+EDITED+' # Part of the tuple returned as an event when a Table element has a cell edited
-DEFAULT_MODAL_WINDOWS_ENABLED = True
-DEFAULT_MODAL_WINDOWS_FORCED = False
-
-TAB_LOCATION_TOP = 'top'
-TAB_LOCATION_TOP_LEFT = 'topleft'
-TAB_LOCATION_TOP_RIGHT = 'topright'
-TAB_LOCATION_LEFT = 'left'
-TAB_LOCATION_LEFT_TOP = 'lefttop'
-TAB_LOCATION_LEFT_BOTTOM = 'leftbottom'
-TAB_LOCATION_RIGHT = 'right'
-TAB_LOCATION_RIGHT_TOP = 'righttop'
-TAB_LOCATION_RIGHT_BOTTOM = 'rightbottom'
-TAB_LOCATION_BOTTOM = 'bottom'
-TAB_LOCATION_BOTTOM_LEFT = 'bottomleft'
-TAB_LOCATION_BOTTOM_RIGHT = 'bottomright'
-
-TITLE_LOCATION_TOP = tk.N
-TITLE_LOCATION_BOTTOM = tk.S
-TITLE_LOCATION_LEFT = tk.W
-TITLE_LOCATION_RIGHT = tk.E
-TITLE_LOCATION_TOP_LEFT = tk.NW
-TITLE_LOCATION_TOP_RIGHT = tk.NE
-TITLE_LOCATION_BOTTOM_LEFT = tk.SW
-TITLE_LOCATION_BOTTOM_RIGHT = tk.SE
-
-TEXT_LOCATION_TOP = tk.N
-TEXT_LOCATION_BOTTOM = tk.S
-TEXT_LOCATION_LEFT = tk.W
-TEXT_LOCATION_RIGHT = tk.E
-TEXT_LOCATION_TOP_LEFT = tk.NW
-TEXT_LOCATION_TOP_RIGHT = tk.NE
-TEXT_LOCATION_BOTTOM_LEFT = tk.SW
-TEXT_LOCATION_BOTTOM_RIGHT = tk.SE
-TEXT_LOCATION_CENTER = tk.CENTER
-
-GRAB_ANYWHERE_IGNORE_THESE_WIDGETS = (ttk.Sizegrip, tk.Scale, ttk.Scrollbar, tk.Scrollbar, tk.Entry, tk.Text, tk.PanedWindow, tk.Listbox, tk.OptionMenu, ttk.Treeview)
-
-# ----====----====----==== Constants the user should NOT f-with ====----====----====----#
-ThisRow = 555666777 # magic number
-
-# DEFAULT_WINDOW_ICON = ''
-MESSAGE_BOX_LINE_WIDTH = 60
-
-# "Special" Key Values.. reserved
-# Key representing a Read timeout
-EVENT_TIMEOUT = TIMEOUT_EVENT = TIMEOUT_KEY = '__TIMEOUT__'
-EVENT_TIMER = TIMER_KEY = '__TIMER EVENT__'
-WIN_CLOSED = WINDOW_CLOSED = None
-WINDOW_CLOSE_ATTEMPTED_EVENT = WIN_X_EVENT = WIN_CLOSE_ATTEMPTED_EVENT = '-WINDOW CLOSE ATTEMPTED-'
-WINDOW_CONFIG_EVENT = '__WINDOW CONFIG__'
-TITLEBAR_MINIMIZE_KEY = '__TITLEBAR MINIMIZE__'
-TITLEBAR_MAXIMIZE_KEY = '__TITLEBAR MAXIMIZE__'
-TITLEBAR_CLOSE_KEY = '__TITLEBAR CLOSE__'
-TITLEBAR_IMAGE_KEY = '__TITLEBAR IMAGE__'
-TITLEBAR_TEXT_KEY = '__TITLEBAR TEXT__'
-TITLEBAR_KEY = '__TITLEBAR__'
-TITLEBAR_DO_NOT_USE_AN_ICON = '__TITLEBAR_NO_ICON__'
-
-
-# Key indicating should not create any return values for element
-WRITE_ONLY_KEY = '__WRITE ONLY__'
-
-MENU_DISABLED_CHARACTER = '!'
-MENU_SHORTCUT_CHARACTER = '&'
-MENU_KEY_SEPARATOR = '::'
-MENU_SEPARATOR_LINE = '---'
-MENU_RIGHT_CLICK_EDITME_EXIT = ['', ['Edit Me', 'Exit']]
-MENU_RIGHT_CLICK_EDITME_VER_EXIT = ['', ['Edit Me', 'Version', 'Exit']]
-MENU_RIGHT_CLICK_EDITME_VER_EXPLORER_EXIT = ['', ['Edit Me', 'Version', 'Show in Explorer', 'Exit']]
-MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT = ['', ['Edit Me', 'Version', 'File Location', 'Exit']]
-MENU_RIGHT_CLICK_EDITME_VER_SETTINGS_EXIT = ['', ['Edit Me', 'Settings', 'Version', 'Exit']]
-MENU_RIGHT_CLICK_EXIT = ['', ['Exit']]
-MENU_RIGHT_CLICK_DISABLED = ['', []]
-_MENU_RIGHT_CLICK_TABGROUP_DEFAULT = ['TABGROUP DEFAULT', []]
-ENABLE_TK_WINDOWS = False
-
-USE_CUSTOM_TITLEBAR = None
-CUSTOM_TITLEBAR_BACKGROUND_COLOR = None
-CUSTOM_TITLEBAR_TEXT_COLOR = None
-CUSTOM_TITLEBAR_ICON = None
-CUSTOM_TITLEBAR_FONT = None
-TITLEBAR_METADATA_MARKER = 'This window has a titlebar'
-
-CUSTOM_MENUBAR_METADATA_MARKER = 'This is a custom menubar'
-
-SUPPRESS_ERROR_POPUPS = False
-SUPPRESS_RAISE_KEY_ERRORS = True
-SUPPRESS_KEY_GUESSING = False
-SUPPRESS_WIDGET_NOT_FINALIZED_WARNINGS = False
-ENABLE_TREEVIEW_869_PATCH = True
-
-# These are now set based on the global settings file
-ENABLE_MAC_NOTITLEBAR_PATCH = False
-ENABLE_MAC_MODAL_DISABLE_PATCH = False
-ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR = True
-ENABLE_MAC_ALPHA_99_PATCH = False
-
-OLD_TABLE_TREE_SELECTED_ROW_COLORS = ('#FFFFFF', '#4A6984')
-ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS = ('SystemHighlightText', 'SystemHighlight')
-
-# Some handy unicode symbols
-SYMBOL_SQUARE = '█'
-SYMBOL_CIRCLE = '⚫'
-SYMBOL_CIRCLE_OUTLINE = '◯'
-SYMBOL_BULLET = '•'
-SYMBOL_UP = '▲'
-SYMBOL_RIGHT = '►'
-SYMBOL_LEFT = '◄'
-SYMBOL_DOWN = '▼'
-SYMBOL_X = '❎'
-SYMBOL_CHECK = '✅'
-SYMBOL_CHECK_SMALL = '✓'
-SYMBOL_X_SMALL = '✗'
-SYMBOL_BALLOT_X = '☒'
-SYMBOL_BALLOT_CHECK = '☑'
-SYMBOL_LEFT_DOUBLE = '«'
-SYMBOL_RIGHT_DOUBLE = '»'
-SYMBOL_LEFT_ARROWHEAD = '⮜'
-SYMBOL_RIGHT_ARROWHEAD = '⮞'
-SYMBOL_UP_ARROWHEAD = '⮝'
-SYMBOL_DOWN_ARROWHEAD = '⮟'
-SYMBOL_HOURGLASS = '⌛' if running_windows() or running_mac() else ''
-
-if sum([int(i) for i in tclversion_detailed.split('.')]) > 19:
- SYMBOL_TITLEBAR_MINIMIZE = '_'
- SYMBOL_TITLEBAR_MAXIMIZE = '◻'
- SYMBOL_TITLEBAR_CLOSE = 'X'
-else:
- SYMBOL_TITLEBAR_MINIMIZE = '_'
- SYMBOL_TITLEBAR_MAXIMIZE = 'O'
- SYMBOL_TITLEBAR_CLOSE = 'X'
-
-#################### PATHS for user_settings APIs ####################
-# These paths are passed to os.path.expanduser to get the default path for user_settings
-# They can be changed using set_options
-
-DEFAULT_USER_SETTINGS_WIN_PATH = r'~\AppData\Local\PySimpleGUI\settings'
-DEFAULT_USER_SETTINGS_LINUX_PATH = r'~/.config/PySimpleGUI/settings'
-DEFAULT_USER_SETTINGS_MAC_PATH = r'~/Library/Application Support/PySimpleGUI/settings'
-DEFAULT_USER_SETTINGS_TRINKET_PATH = r'.'
-DEFAULT_USER_SETTINGS_REPLIT_PATH = r'.'
-DEFAULT_USER_SETTINGS_UNKNOWN_OS_PATH = r'~/Library/Application Support/PySimpleGUI/settings'
-DEFAULT_USER_SETTINGS_PATH = None # value set by user to override all paths above
-DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH = None # location of the global PySimpleGUI settings
-DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME = '_PySimpleGUI_settings_global_.json' # location of the global PySimpleGUI settings
-
-
-
-# ====================================================================== #
-# One-liner functions that are handy as f_ck #
-# ====================================================================== #
-def rgb(red, green, blue):
- """
- Given integer values of Red, Green, Blue, return a color string "#RRGGBB"
- :param red: Red portion from 0 to 255
- :type red: (int)
- :param green: Green portion from 0 to 255
- :type green: (int)
- :param blue: Blue portion from 0 to 255
- :type blue: (int)
- :return: A single RGB String in the format "#RRGGBB" where each pair is a hex number.
- :rtype: (str)
- """
- red = min(int(red), 255) if red > 0 else 0
- blue = min(int(blue), 255) if blue > 0 else 0
- green = min(int(green), 255) if green > 0 else 0
- return '#%02x%02x%02x' % (red, green, blue)
-
-
-# ====================================================================== #
-# Enums for types #
-# ====================================================================== #
-# ------------------------- Button types ------------------------- #
-# uncomment this line and indent to go back to using Enums
-BUTTON_TYPE_BROWSE_FOLDER = 1
-BUTTON_TYPE_BROWSE_FILE = 2
-BUTTON_TYPE_BROWSE_FILES = 21
-BUTTON_TYPE_SAVEAS_FILE = 3
-BUTTON_TYPE_CLOSES_WIN = 5
-BUTTON_TYPE_CLOSES_WIN_ONLY = 6
-BUTTON_TYPE_READ_FORM = 7
-BUTTON_TYPE_REALTIME = 9
-BUTTON_TYPE_CALENDAR_CHOOSER = 30
-BUTTON_TYPE_COLOR_CHOOSER = 40
-BUTTON_TYPE_SHOW_DEBUGGER = 50
-
-BROWSE_FILES_DELIMITER = ';' # the delimiter to be used between each file in the returned string
-
-FILE_TYPES_ALL_FILES = (("ALL Files", "*.* *"),)
-
-BUTTON_DISABLED_MEANS_IGNORE = 'ignore'
-
-# ------------------------- Element types ------------------------- #
-
-ELEM_TYPE_TEXT = 'text'
-ELEM_TYPE_INPUT_TEXT = 'input'
-ELEM_TYPE_INPUT_COMBO = 'combo'
-ELEM_TYPE_INPUT_OPTION_MENU = 'option menu'
-ELEM_TYPE_INPUT_RADIO = 'radio'
-ELEM_TYPE_INPUT_MULTILINE = 'multiline'
-ELEM_TYPE_INPUT_CHECKBOX = 'checkbox'
-ELEM_TYPE_INPUT_SPIN = 'spind'
-ELEM_TYPE_BUTTON = 'button'
-ELEM_TYPE_IMAGE = 'image'
-ELEM_TYPE_CANVAS = 'canvas'
-ELEM_TYPE_FRAME = 'frame'
-ELEM_TYPE_GRAPH = 'graph'
-ELEM_TYPE_TAB = 'tab'
-ELEM_TYPE_TAB_GROUP = 'tabgroup'
-ELEM_TYPE_INPUT_SLIDER = 'slider'
-ELEM_TYPE_INPUT_LISTBOX = 'listbox'
-ELEM_TYPE_OUTPUT = 'output'
-ELEM_TYPE_COLUMN = 'column'
-ELEM_TYPE_MENUBAR = 'menubar'
-ELEM_TYPE_PROGRESS_BAR = 'progressbar'
-ELEM_TYPE_BLANK = 'blank'
-ELEM_TYPE_TABLE = 'table'
-ELEM_TYPE_TREE = 'tree'
-ELEM_TYPE_ERROR = 'error'
-ELEM_TYPE_SEPARATOR = 'separator'
-ELEM_TYPE_STATUSBAR = 'statusbar'
-ELEM_TYPE_PANE = 'pane'
-ELEM_TYPE_BUTTONMENU = 'buttonmenu'
-ELEM_TYPE_TITLEBAR = 'titlebar'
-ELEM_TYPE_SIZEGRIP = 'sizegrip'
-
-# STRETCH == ERROR ELEMENT as a filler
-
-# ------------------------- Popup Buttons Types ------------------------- #
-POPUP_BUTTONS_YES_NO = 1
-POPUP_BUTTONS_CANCELLED = 2
-POPUP_BUTTONS_ERROR = 3
-POPUP_BUTTONS_OK_CANCEL = 4
-POPUP_BUTTONS_OK = 0
-POPUP_BUTTONS_NO_BUTTONS = 5
-
-PSG_THEME_PART_BUTTON_TEXT = 'Button Text Color'
-PSG_THEME_PART_BUTTON_BACKGROUND = 'Button Background Color'
-PSG_THEME_PART_BACKGROUND = 'Background Color'
-PSG_THEME_PART_INPUT_BACKGROUND = 'Input Element Background Color'
-PSG_THEME_PART_INPUT_TEXT = 'Input Element Text Color'
-PSG_THEME_PART_TEXT = 'Text Color'
-PSG_THEME_PART_SLIDER = 'Slider Color'
-PSG_THEME_PART_LIST = [PSG_THEME_PART_BACKGROUND, PSG_THEME_PART_BUTTON_BACKGROUND, PSG_THEME_PART_BUTTON_TEXT, PSG_THEME_PART_INPUT_BACKGROUND, PSG_THEME_PART_INPUT_TEXT,
- PSG_THEME_PART_TEXT, PSG_THEME_PART_SLIDER]
-
-# theme_button
-
-TTK_SCROLLBAR_PART_TROUGH_COLOR = 'Trough Color'
-TTK_SCROLLBAR_PART_BACKGROUND_COLOR = 'Background Color'
-TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR = 'Arrow Button Arrow Color'
-TTK_SCROLLBAR_PART_FRAME_COLOR = 'Frame Color'
-TTK_SCROLLBAR_PART_SCROLL_WIDTH = 'Frame Width'
-TTK_SCROLLBAR_PART_ARROW_WIDTH = 'Arrow Width'
-TTK_SCROLLBAR_PART_RELIEF = 'Relief'
-TTK_SCROLLBAR_PART_LIST = [TTK_SCROLLBAR_PART_TROUGH_COLOR, TTK_SCROLLBAR_PART_BACKGROUND_COLOR, TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR,
- TTK_SCROLLBAR_PART_FRAME_COLOR, TTK_SCROLLBAR_PART_SCROLL_WIDTH, TTK_SCROLLBAR_PART_ARROW_WIDTH, TTK_SCROLLBAR_PART_RELIEF]
-TTK_SCROLLBAR_PART_THEME_BASED_LIST = [TTK_SCROLLBAR_PART_TROUGH_COLOR, TTK_SCROLLBAR_PART_BACKGROUND_COLOR, TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR,
- TTK_SCROLLBAR_PART_FRAME_COLOR]
-DEFAULT_TTK_PART_MAPPING_DICT = {TTK_SCROLLBAR_PART_TROUGH_COLOR: PSG_THEME_PART_SLIDER,
- TTK_SCROLLBAR_PART_BACKGROUND_COLOR: PSG_THEME_PART_BUTTON_BACKGROUND,
- TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR: PSG_THEME_PART_BUTTON_TEXT,
- TTK_SCROLLBAR_PART_FRAME_COLOR: PSG_THEME_PART_BACKGROUND,
- TTK_SCROLLBAR_PART_SCROLL_WIDTH: 12,
- TTK_SCROLLBAR_PART_ARROW_WIDTH: 12,
- TTK_SCROLLBAR_PART_RELIEF: RELIEF_RAISED}
-
-ttk_part_mapping_dict = copy.copy(DEFAULT_TTK_PART_MAPPING_DICT)
-
-
-# ------------------------- Web Destinations ------------------------- #
-URL_HOME = r'http://home.PySimpleGUI.com'
-URL_DOCS = r'http://docs.PySimpleGUI.com'
-URL_PSG_GITHUB_SOURCE = r'https://raw.githubusercontent.com/PySimpleGUI/PySimpleGUI/refs/heads/master/PySimpleGUI/PySimpleGUI.py'
-URL_PSG_GITHUB_SETUP_FILE = r'https://raw.githubusercontent.com/PySimpleGUI/PySimpleGUI/refs/heads/master/setup.py'
-URL_PSG_PIP_INSTALL_FROM_GITHUB = r'https://github.com/PySimpleGUI/PySimpleGUI/zipball/master'
-
-
-class TTKPartOverrides:
- """
- This class contains "overrides" to the defaults for ttk scrollbars that are defined in the global settings file.
- This class is used in every element, in the Window class and there's a global one that is used by set_options.
- """
-
- def __init__(self, sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None):
- self.sbar_trough_color = sbar_trough_color
- self.sbar_background_color = sbar_background_color
- self.sbar_arrow_color = sbar_arrow_color
- self.sbar_width = sbar_width
- self.sbar_arrow_width = sbar_arrow_width
- self.sbar_frame_color = sbar_frame_color
- self.sbar_relief = sbar_relief
-
-
-ttk_part_overrides_from_options = TTKPartOverrides()
-
-# ------------------------- tkinter BASIC cursors... there are some OS dependent ones too ------------------------- #
-TKINTER_CURSORS = ['X_cursor', 'arrow', 'based_arrow_down', 'based_arrow_up', 'boat',
- 'bogosity', 'bottom_left_corner', 'bottom_right_corner', 'bottom_side',
- 'bottom_tee', 'box_spiral', 'center_ptr', 'circle', 'clock',
- 'coffee_mug', 'cross', 'cross_reverse', 'crosshair', 'diamond_cross',
- 'dot', 'dotbox', 'double_arrow', 'draft_large', 'draft_small', 'draped_box',
- 'exchange', 'fleur', 'gobbler', 'gumby', 'hand1', 'hand2', 'heart',
- 'icon', 'iron_cross', 'left_ptr', 'left_side', 'left_tee', 'leftbutton',
- 'll_angle', 'lr_angle', 'man', 'middlebutton', 'mouse', 'pencil', 'pirate',
- 'plus', 'question_arrow', 'right_ptr', 'right_side', 'right_tee',
- 'rightbutton', 'rtl_logo', 'sailboat', 'sb_down_arrow', 'sb_h_double_arrow',
- 'sb_left_arrow', 'sb_right_arrow', 'sb_up_arrow', 'sb_v_double_arrow',
- 'shuttle', 'sizing', 'spider', 'spraycan', 'star', 'target', 'tcross',
- 'top_left_arrow', 'top_left_corner', 'top_right_corner', 'top_side', 'top_tee',
- 'trek', 'ul_angle', 'umbrella', 'ur_angle', 'watch', 'xterm']
-
-# ------------------------- tkinter key codes for bindings ------------------------- #
-
-# The keycode that when pressed will take a snapshot of the current window
-DEFAULT_WINDOW_SNAPSHOT_KEY_CODE = None
-DEFAULT_WINDOW_SNAPSHOT_KEY = '--SCREENSHOT THIS WINDOW--'
-
-tkinter_keysyms = (
-'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'minus', 'period', 'slash',
-'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
-'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e',
-'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'nobreakspace',
-'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar', 'section', 'diaeresis', 'copyright', 'ordfeminine', 'guillemotleft', 'notsign', 'hyphen', 'registered', 'macron',
-'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', 'masculine', 'guillemotright', 'onequarter',
-'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adiaeresis', 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Ediaeresis',
-'Igrave', 'Iacute', 'Icircumflex', 'Idiaeresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute', 'Ocircumflex', 'Otilde', 'Odiaeresis', 'multiply', 'Ooblique', 'Ugrave', 'Uacute',
-'Ucircumflex', 'Udiaeresis', 'Yacute', 'Thorn', 'ssharp', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adiaeresis', 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex',
-'ediaeresis', 'igrave', 'iacute', 'icircumflex', 'idiaeresis', 'eth', 'ntilde', 'ograve', 'oacute', 'ocircumflex', 'otilde', 'odiaeresis', 'division', 'oslash', 'ugrave', 'uacute',
-'ucircumflex', 'udiaeresis', 'yacute', 'thorn', 'ydiaeresis', 'Aogonek', 'breve', 'Lstroke', 'Lcaron', 'Sacute', 'Scaron', 'Scedilla', 'Tcaron', 'Zacute', 'Zcaron', 'Zabovedot',
-'aogonek', 'ogonek', 'lstroke', 'lcaron', 'sacute', 'caron', 'scaron', 'scedilla', 'tcaron', 'zacute', 'doubleacute', 'zcaron', 'zabovedot', 'Racute', 'Abreve', 'Cacute', 'Ccaron',
-'Eogonek', 'Ecaron', 'Dcaron', 'Nacute', 'Ncaron', 'Odoubleacute', 'Rcaron', 'Uring', 'Udoubleacute', 'Tcedilla', 'racute', 'abreve', 'cacute', 'ccaron', 'eogonek', 'ecaron',
-'dcaron', 'nacute', 'ncaron', 'odoubleacute', 'rcaron', 'uring', 'udoubleacute', 'tcedilla', 'abovedot',
-'leftradical', 'topleftradical', 'horizconnector', 'topintegral', 'botintegral', 'vertconnector', 'topleftsqbracket', 'botleftsqbracket', 'toprightsqbracket', 'botrightsqbracket',
-'topleftparens', 'botleftparens', 'toprightparens', 'botrightparens', 'leftmiddlecurlybrace', 'rightmiddlecurlybrace', 'topleftsummation', 'botleftsummation',
-'topvertsummationconnector', 'botvertsummationconnector', 'toprightsummation', 'botrightsummation', 'rightmiddlesummation', 'lessthanequal', 'notequal', 'greaterthanequal',
-'integral', 'therefore', 'variation', 'infinity', 'nabla', 'approximate', 'similarequal', 'ifonlyif', 'implies', 'identical', 'radical', 'includedin', 'includes', 'intersection',
-'union', 'logicaland', 'logicalor', 'partialderivative', 'function', 'leftarrow', 'uparrow', 'rightarrow', 'downarrow', 'blank', 'soliddiamond', 'checkerboard', 'ht', 'ff', 'cr',
-'lf', 'nl', 'vt', 'lowrightcorner', 'uprightcorner', 'upleftcorner', 'lowleftcorner', 'crossinglines', 'horizlinescan1', 'horizlinescan3', 'horizlinescan5', 'horizlinescan7',
-'horizlinescan9', 'leftt', 'rightt', 'bott', 'topt', 'vertbar', 'emspace', 'enspace', 'em3space', 'em4space', 'digitspace', 'punctspace', 'thinspace', 'hairspace', 'emdash',
-'endash', 'signifblank', 'ellipsis', 'doubbaselinedot', 'onethird', 'twothirds', 'onefifth', 'twofifths', 'threefifths', 'fourfifths', 'onesixth', 'fivesixths', 'careof',
-'figdash', 'leftanglebracket', 'decimalpoint', 'rightanglebracket', 'marker', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'trademark', 'signaturemark',
-'trademarkincircle', 'leftopentriangle', 'rightopentriangle', 'emopencircle', 'emopenrectangle', 'leftsinglequotemark', 'rightsinglequotemark', 'leftdoublequotemark',
-'rightdoublequotemark', 'prescription', 'minutes', 'seconds', 'latincross', 'hexagram', 'filledrectbullet', 'filledlefttribullet', 'filledrighttribullet', 'emfilledcircle',
-'emfilledrect', 'enopencircbullet', 'enopensquarebullet', 'openrectbullet', 'opentribulletup', 'opentribulletdown', 'openstar', 'enfilledcircbullet', 'enfilledsqbullet',
-'filledtribulletup', 'filledtribulletdown', 'leftpointer', 'rightpointer', 'club', 'diamond', 'heart', 'maltesecross', 'dagger', 'doubledagger', 'checkmark', 'ballotcross',
-'musicalsharp', 'musicalflat', 'malesymbol', 'femalesymbol', 'telephone', 'telephonerecorder', 'phonographcopyright', 'caret', 'singlelowquotemark', 'doublelowquotemark', 'cursor',
-'leftcaret', 'rightcaret', 'downcaret', 'upcaret', 'overbar', 'downtack', 'upshoe', 'downstile', 'underbar', 'jot', 'quad', 'uptack', 'circle', 'upstile', 'downshoe', 'rightshoe',
-'leftshoe', 'lefttack', 'righttack', 'BackSpace', 'Tab', 'Linefeed', 'Clear', 'Return', 'Pause', 'Scroll_Lock',
-'Sys_Req', 'Escape', 'Multi_key', 'Kanji', 'Home', 'Left', 'Up', 'Right', 'Down', 'Prior', 'Next', 'End', 'Begin', 'Win_L', 'Win_R', 'App', 'Select', 'Print', 'Execute', 'Insert',
-'Undo', 'Redo', 'Menu', 'Find', 'Cancel', 'Help', 'Break', 'Hebrew_switch', 'Num_Lock', 'KP_Space', 'KP_Tab', 'KP_Enter', 'KP_F1', 'KP_F2', 'KP_F3', 'KP_F4', 'KP_Multiply',
-'KP_Add', 'KP_Separator', 'KP_Subtract', 'KP_Decimal', 'KP_Divide', 'KP_0', 'KP_1', 'KP_2', 'KP_3', 'KP_4', 'KP_5', 'KP_6', 'KP_7', 'KP_8', 'KP_9', 'KP_Equal', 'F1', 'F2', 'F3',
-'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', 'L1', 'L2', 'L3', 'L4', 'L5', 'L6', 'L7', 'L8', 'L9', 'L10', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9', 'R10',
-'R11', 'R12', 'F33', 'R14', 'R15', 'Shift_L', 'Shift_R', 'Control_L', 'Control_R', 'Caps_Lock', 'Shift_Lock', 'Meta_L', 'Meta_R', 'Alt_L', 'Alt_R', 'Super_L', 'Super_R', 'Hyper_L',
-'Hyper_R', 'Delete')
-
-
-# ------------------------------------------------------------------------- #
-# ToolTip used by the Elements #
-# ------------------------------------------------------------------------- #
-
-class ToolTip:
- """
- Create a tooltip for a given widget
- (inspired by https://stackoverflow.com/a/36221216)
- This is an INTERNALLY USED only class. Users should not refer to this class at all.
- """
-
- def __init__(self, widget, text, timeout=DEFAULT_TOOLTIP_TIME):
- """
- :param widget: The tkinter widget
- :type widget: widget type varies
- :param text: text for the tooltip. It can inslude \n. If None tip won't be shown
- :type text: str | None
- :param timeout: Time in milliseconds that mouse must remain still before tip is shown
- :type timeout: (int)
- """
- self.widget = widget
- self.text = text # Set to None and tooltip will be not shown
- self.timeout = timeout
- # self.wraplength = wraplength if wraplength else widget.winfo_screenwidth() // 2
- self.tipwindow = None
- self.id = None
- self.x = self.y = 0
- self.widget.bind("", self.enter)
- self.widget.bind("", self.leave)
- self.widget.bind("", self.leave)
-
- def enter(self, event=None):
- """
- Called by tkinter when mouse enters a widget
- :param event: from tkinter. Has x,y coordinates of mouse
- :type event:
-
- """
- if self.text is None: # if tip is diabled
- return
- self.x = event.x
- self.y = event.y
- self.schedule()
-
- def leave(self, event=None):
- """
- Called by tktiner when mouse exits a widget
- :param event: from tkinter. Event info that's not used by function.
- :type event:
-
- """
- self.unschedule()
- self.hidetip()
-
- def schedule(self):
- """
- Schedule a timer to time how long mouse is hovering
- """
- self.unschedule()
- self.id = self.widget.after(self.timeout, self.showtip)
-
- def unschedule(self):
- """
- Cancel timer used to time mouse hover
- """
- if self.id:
- self.widget.after_cancel(self.id)
- self.id = None
-
- def showtip(self):
- """
- Creates a topoltip window with the tooltip text inside of it
- """
- if self.tipwindow:
- return
- x = self.widget.winfo_rootx() + self.x + DEFAULT_TOOLTIP_OFFSET[0]
- y = self.widget.winfo_rooty() + self.y + DEFAULT_TOOLTIP_OFFSET[1]
- self.tipwindow = tk.Toplevel(self.widget)
- # if not sys.platform.startswith('darwin'):
- try:
- self.tipwindow.wm_overrideredirect(True)
- # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH:
- if _mac_should_apply_notitlebar_patch():
- self.tipwindow.wm_overrideredirect(False)
- except Exception as e:
- print('* Error performing wm_overrideredirect in showtip *', e)
- self.tipwindow.wm_geometry("+%d+%d" % (x, y))
- self.tipwindow.wm_attributes("-topmost", 1)
-
- label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT,
- background=TOOLTIP_BACKGROUND_COLOR, relief=tk.SOLID, borderwidth=1)
- if TOOLTIP_FONT is not None:
- label.config(font=TOOLTIP_FONT)
- label.pack()
-
- def hidetip(self):
- """
- Destroy the tooltip window
- """
- if self.tipwindow:
- self.tipwindow.destroy()
- self.tipwindow = None
-
- def remove(self):
- """
- Removes a tooltip from a widget
- """
- self.text = None
-
-# ---------------------------------------------------------------------- #
-# Cascading structure.... Objects get larger #
-# Button #
-# Element #
-# Row #
-# Form #
-# ---------------------------------------------------------------------- #
-# ------------------------------------------------------------------------- #
-# Element CLASS #
-# ------------------------------------------------------------------------- #
-class Element:
- """ The base class for all Elements. Holds the basic description of an Element like size and colors """
-
- def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None,
- visible=True, metadata=None, sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None):
- """
- Element base class. Only used internally. User will not create an Element object by itself
-
- :param type: The type of element. These constants all start with "ELEM_TYPE_"
- :type type: (int) (could be enum)
- :param size: w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param auto_size_text: True if the Widget should be shrunk to exactly fit the number of chars to show
- :type auto_size_text: bool
- :param font: specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param background_color: color of background. Can be in #RRGGBB format or a color name "black"
- :type background_color: (str)
- :param text_color: element's text color. Can be in #RRGGBB format or a color name "black"
- :type text_color: (str)
- :param key: Identifies an Element. Should be UNIQUE to this window.
- :type key: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom). If an int is given, then auto-converted to tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param visible: set visibility state of the element (Default = True)
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- """
-
- if size is not None and size != (None, None):
- if isinstance(size, int):
- size = (size, 1)
- if isinstance(size, tuple) and len(size) == 1:
- size = (size[0], 1)
-
- if pad is not None and pad != (None, None):
- if isinstance(pad, int):
- pad = (pad, pad)
-
- self.Size = size
- self.Type = type
- self.AutoSizeText = auto_size_text
-
- self.Pad = pad
- self.Font = font
-
- self.TKStringVar = None
- self.TKIntVar = None
- self.TKText = None
- self.TKEntry = None
- self.TKImage = None
- self.ttk_style_name = '' # The ttk style name (if this is a ttk widget)
- self.ttk_style = None # The ttk Style object (if this is a ttk widget)
- self._metadata = None # type: Any
- if not hasattr(self, 'setting'):
- self.setting = None # If no setting has been set yet, set it to None
- # import re
- # import re
- self.ParentForm = None # type: Window | None
- self.ParentContainer = None # will be a Form, Column, or Frame element # UNBIND
- self.TextInputDefault = None
- self.Position = (0, 0) # Default position Row 0, Col 0
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR
- self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR
- self.Key = key # dictionary key for return values
- self.Tooltip = tooltip
- self.TooltipObject = None # type: ToolTip | None
- self._visible = visible
- self.TKRightClickMenu = None
- self.Widget = None # Set when creating window. Has the main tkinter widget for element
- self.Tearoff = False # needed because of right click menu code
- self.ParentRowFrame = None # type tk.Frame
- self.metadata = metadata
- self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier
- self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter
- # self.pad_used = (0, 0) # the amount of pad used when was inserted into the layout
- self._popup_menu_location = (None, None)
- self.pack_settings = None
- self.vsb_style_name = None # ttk style name used for the verical scrollbar if one is attached to element
- self.hsb_style_name = None # ttk style name used for the horizontal scrollbar if one is attached to element
- self.vsb_style = None # The ttk style used for the vertical scrollbar if one is attached to element
- self.hsb_style = None # The ttk style used for the horizontal scrollbar if one is attached to element
- self.hsb = None # The horizontal scrollbar if one is attached to element
- # The vertical scrollbar if one is attached to element
- self.vsb = None # type: ttk.Scrollbar | None
- self.font_used = None # Set to the font used when the element is created in the window
- ## TTK Scrollbar Settings
- self.ttk_part_overrides = TTKPartOverrides(sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color,
- sbar_width=sbar_width, sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
-
- PSG_THEME_PART_FUNC_MAP = {PSG_THEME_PART_BACKGROUND: theme_background_color,
- PSG_THEME_PART_BUTTON_BACKGROUND: theme_button_color_background,
- PSG_THEME_PART_BUTTON_TEXT: theme_button_color_text,
- PSG_THEME_PART_INPUT_BACKGROUND: theme_input_background_color,
- PSG_THEME_PART_INPUT_TEXT: theme_input_text_color,
- PSG_THEME_PART_TEXT: theme_text_color,
- PSG_THEME_PART_SLIDER: theme_slider_color}
-
- # class Theme_Parts():
- # PSG_THEME_PART_FUNC_MAP = {PSG_THEME_PART_BACKGROUND: theme_background_color,
- if sbar_trough_color is not None:
- self.scroll_trough_color = sbar_trough_color
- else:
- self.scroll_trough_color = PSG_THEME_PART_FUNC_MAP.get(ttk_part_mapping_dict[TTK_SCROLLBAR_PART_TROUGH_COLOR], ttk_part_mapping_dict[TTK_SCROLLBAR_PART_TROUGH_COLOR])
- if callable(self.scroll_trough_color):
- self.scroll_trough_color = self.scroll_trough_color()
-
- if sbar_background_color is not None:
- self.scroll_background_color = sbar_background_color
- else:
- self.scroll_background_color = PSG_THEME_PART_FUNC_MAP.get(ttk_part_mapping_dict[TTK_SCROLLBAR_PART_BACKGROUND_COLOR],
- ttk_part_mapping_dict[TTK_SCROLLBAR_PART_BACKGROUND_COLOR])
- if callable(self.scroll_background_color):
- self.scroll_background_color = self.scroll_background_color()
-
- if sbar_arrow_color is not None:
- self.scroll_arrow_color = sbar_arrow_color
- else:
- self.scroll_arrow_color = PSG_THEME_PART_FUNC_MAP.get(ttk_part_mapping_dict[TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR],
- ttk_part_mapping_dict[TTK_SCROLLBAR_PART_ARROW_BUTTON_ARROW_COLOR])
- if callable(self.scroll_arrow_color):
- self.scroll_arrow_color = self.scroll_arrow_color()
-
- if sbar_frame_color is not None:
- self.scroll_frame_color = sbar_frame_color
- else:
- self.scroll_frame_color = PSG_THEME_PART_FUNC_MAP.get(ttk_part_mapping_dict[TTK_SCROLLBAR_PART_FRAME_COLOR], ttk_part_mapping_dict[TTK_SCROLLBAR_PART_FRAME_COLOR])
- if callable(self.scroll_frame_color):
- self.scroll_frame_color = self.scroll_frame_color()
-
- if sbar_relief is not None:
- self.scroll_relief = sbar_relief
- else:
- self.scroll_relief = ttk_part_mapping_dict[TTK_SCROLLBAR_PART_RELIEF]
-
- if sbar_width is not None:
- self.scroll_width = sbar_width
- else:
- self.scroll_width = ttk_part_mapping_dict[TTK_SCROLLBAR_PART_SCROLL_WIDTH]
-
- if sbar_arrow_width is not None:
- self.scroll_arrow_width = sbar_arrow_width
- else:
- self.scroll_arrow_width = ttk_part_mapping_dict[TTK_SCROLLBAR_PART_ARROW_WIDTH]
-
- if not hasattr(self, 'DisabledTextColor'):
- self.DisabledTextColor = None
- if not hasattr(self, 'ItemFont'):
- self.ItemFont = None
- if not hasattr(self, 'RightClickMenu'):
- self.RightClickMenu = None
- if not hasattr(self, 'Disabled'):
- self.Disabled = None # in case the element hasn't defined this, add it here
-
- @property
- def visible(self):
- """
- Returns visibility state for the element. This is a READONLY property
- :return: Visibility state for element
- :rtype: (bool)
- """
- return self._visible
-
- @property
- def metadata(self):
- """
- Metadata is an Element property that you can use at any time to hold any value
- :return: the current metadata value
- :rtype: (Any)
- """
- return self._metadata
-
- @metadata.setter
- def metadata(self, value):
- """
- Metadata is an Element property that you can use at any time to hold any value
- :param value: Anything you want it to be
- :type value: (Any)
- """
- self._metadata = value
-
- @property
- def key(self):
- """
- Returns key for the element. This is a READONLY property.
- Keys can be any hashable object (basically anything except a list... tuples are ok, but not lists)
- :return: The window's Key
- :rtype: (Any)
- """
- return self.Key
-
- @property
- def widget(self):
- """
- Returns tkinter widget for the element. This is a READONLY property.
- The implementation is that the Widget member variable is returned. This is a backward compatible addition
- :return: The element's underlying tkinter widget
- :rtype: (tkinter.Widget)
- """
- return self.Widget
-
- def _RightClickMenuCallback(self, event):
- """
- Callback function that's called when a right click happens. Shows right click menu as result
-
- :param event: information provided by tkinter about the event including x,y location of click
- :type event:
-
- """
-
- if self.Type == ELEM_TYPE_TAB_GROUP:
- try:
- index = self.Widget.index('@{},{}'.format(event.x, event.y))
- tab = self.Widget.tab(index, 'text')
- key = self.find_key_from_tab_name(tab)
- tab_element = self.ParentForm.key_dict[key]
- if tab_element.RightClickMenu is None: # if this tab didn't explicitly have a menu, then don't show anything
- return
- tab_element.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0)
- self.TKRightClickMenu.grab_release()
- except:
- pass
- return
- self.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0)
- self.TKRightClickMenu.grab_release()
- if self.Type == ELEM_TYPE_GRAPH:
- self._update_position_for_returned_values(event)
- self.ParentForm._right_click_menu_element = self
-
- def _tearoff_menu_callback(self, parent, menu):
- """
- Callback function that's called when a right click menu is torn off.
- The reason for this function is to relocate the torn-off menu. It will default to 0,0 otherwise
- This callback moves the right click menu window to the location of the current window
-
- :param parent: information provided by tkinter - the parent of the Meny
- :type parent:
- :param menu: information provided by tkinter - the menu window
- :type menu:
-
- """
- if self._popup_menu_location == (None, None):
- winx, winy = self.ParentForm.current_location()
- else:
- winx, winy = self._popup_menu_location
- # self.ParentForm.TKroot.update()
- self.ParentForm.TKroot.tk.call('wm', 'geometry', menu, "+{}+{}".format(winx, winy))
-
- def _MenuItemChosenCallback(self, item_chosen): # TEXT Menu item callback
- """
- Callback function called when user chooses a menu item from menubar, Button Menu or right click menu
-
- :param item_chosen: String holding the value chosen.
- :type item_chosen: str
-
- """
- # print('IN MENU ITEM CALLBACK', item_chosen)
- self.MenuItemChosen = item_chosen
- self.ParentForm.LastButtonClicked = self.MenuItemChosen
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
- # Window._window_that_exited = self.ParentForm
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
-
- def _FindReturnKeyBoundButton(self, form):
- """
- Searches for which Button has the flag Button.BindReturnKey set. It is called recursively when a
- "Container Element" is encountered. Func has to walk entire window including these "sub-forms"
-
- :param form: the Window object to search
- :type form:
- :return: Button Object if a button is found, else None
- :rtype: Button | None
- """
- for row in form.Rows:
- for element in row:
- if element.Type == ELEM_TYPE_BUTTON:
- if element.BindReturnKey:
- return element
- if element.Type == ELEM_TYPE_COLUMN:
- rc = self._FindReturnKeyBoundButton(element)
- if rc is not None:
- return rc
- if element.Type == ELEM_TYPE_FRAME:
- rc = self._FindReturnKeyBoundButton(element)
- if rc is not None:
- return rc
- if element.Type == ELEM_TYPE_TAB_GROUP:
- rc = self._FindReturnKeyBoundButton(element)
- if rc is not None:
- return rc
- if element.Type == ELEM_TYPE_TAB:
- rc = self._FindReturnKeyBoundButton(element)
- if rc is not None:
- return rc
- if element.Type == ELEM_TYPE_PANE:
- rc = self._FindReturnKeyBoundButton(element)
- if rc is not None:
- return rc
- return None
-
- def _TextClickedHandler(self, event):
- """
- Callback that's called when a text element is clicked on with events enabled on the Text Element.
- Result is that control is returned back to user (quits mainloop).
-
- :param event:
- :type event:
-
- """
- # If this is a minimize button for a custom titlebar, then minimize the window
- if self.Key in (TITLEBAR_MINIMIZE_KEY, TITLEBAR_MAXIMIZE_KEY, TITLEBAR_CLOSE_KEY):
- self.ParentForm._custom_titlebar_callback(self.Key)
- self._generic_callback_handler(self.DisplayText)
- return
-
- def _ReturnKeyHandler(self, event):
- """
- Internal callback for the ENTER / RETURN key. Results in calling the ButtonCallBack for element that has the return key bound to it, just as if button was clicked.
-
- :param event:
- :type event:
-
- """
- # if the element is disabled, ignore the event
- if self.Disabled:
- return
-
- MyForm = self.ParentForm
- button_element = self._FindReturnKeyBoundButton(MyForm)
- if button_element is not None:
- # if the Button has been disabled, then don't perform the callback
- if button_element.Disabled:
- return
- button_element.ButtonCallBack()
-
- def _generic_callback_handler(self, alternative_to_key=None, force_key_to_be=None):
- """
- Peforms the actions that were in many of the callback functions previously. Combined so that it's
- easier to modify and is in 1 place now
-
- :param event: From tkinter and is not used
- :type event: Any
- :param alternate_to_key: If key is None, then use this value instead
- :type alternate_to_key: Any
- """
- if force_key_to_be is not None:
- self.ParentForm.LastButtonClicked = force_key_to_be
- elif self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = alternative_to_key
- self.ParentForm.FormRemainedOpen = True
-
- _exit_mainloop(self.ParentForm)
- # if self.ParentForm.CurrentlyRunningMainloop:
- # Window._window_that_exited = self.ParentForm
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
-
- def _ListboxSelectHandler(self, event):
- """
- Internal callback function for when a listbox item is selected
-
- :param event: Information from tkinter about the callback
- :type event:
-
- """
- self._generic_callback_handler('')
-
- def _ComboboxSelectHandler(self, event):
- """
- Internal callback function for when an entry is selected in a Combobox.
- :param event: Event data from tkinter (not used)
- :type event:
-
- """
- self._generic_callback_handler('')
-
-
-
- def _OptionMenuSelectHandler(self, var, index, mode):
- """
- Internal callback function for when an entry is selected in a OptionMenu.
- :param var: tkinter control variable
- :param index: index of var, '' if var is not a list
- :param mode: 'w' for 'write' here
- """
- self._generic_callback_handler('')
-
-
-
-
- def _SpinboxSelectHandler(self, event=None):
- """
- Internal callback function for when an entry is selected in a Spinbox.
- Note that the parm is optional because it's not used if arrows are used to change the value
- but if the return key is pressed, it will include the event parm
- :param event: Event data passed in by tkinter (not used)
- :type event:
- """
- self._generic_callback_handler('')
-
- def _RadioHandler(self):
- """
- Internal callback for when a radio button is selected and enable events was set for radio
- """
- self._generic_callback_handler('')
-
- def _CheckboxHandler(self):
- """
- Internal callback for when a checkbnox is selected and enable events was set for checkbox
- """
- self._generic_callback_handler('')
-
- def _TabGroupSelectHandler(self, event):
- """
- Internal callback for when a Tab is selected and enable events was set for TabGroup
-
- :param event: Event data passed in by tkinter (not used)
- :type event:
- """
- self._generic_callback_handler('')
-
- def _KeyboardHandler(self, event):
- """
- Internal callback for when a key is pressed andd return keyboard events was set for window
-
- :param event: Event data passed in by tkinter (not used)
- :type event:
- """
-
- # if the element is disabled, ignore the event
- if self.Disabled:
- return
- self._generic_callback_handler('')
-
- def _ClickHandler(self, event):
- """
- Internal callback for when a mouse was clicked... I think.
-
- :param event: Event data passed in by tkinter (not used)
- :type event:
- """
- self._generic_callback_handler('')
-
- def _this_elements_window_closed(self, quick_check=True):
- if self.ParentForm is not None:
- return self.ParentForm.is_closed(quick_check=quick_check)
-
- return True
-
- def _user_bind_callback(self, bind_string, event, propagate=True):
- """
- Used when user binds a tkinter event directly to an element
-
- :param bind_string: The event that was bound so can lookup the key modifier
- :type bind_string: (str)
- :param event: Event data passed in by tkinter (not used)
- :type event: (Any)
- :param propagate: If True then tkinter will be told to propagate the event to the element
- :type propagate: (bool)
- """
- key_suffix = self.user_bind_dict.get(bind_string, '')
- self.user_bind_event = event
- if self.Type == ELEM_TYPE_GRAPH:
- self._update_position_for_returned_values(event)
- if self.Key is not None:
- if isinstance(self.Key, str):
- key = self.Key + str(key_suffix)
- else:
- key = (self.Key, key_suffix) # old way (pre 2021) was to make a brand new tuple
- # key = self.Key + (key_suffix,) # in 2021 tried this. It will break existing applications though - if key is a tuple, add one more item
- else:
- key = bind_string
-
- self._generic_callback_handler(force_key_to_be=key)
-
- return 'break' if propagate is not True else None
-
- def bind(self, bind_string, key_modifier, propagate=True):
- """
- Used to add tkinter events to an Element.
- The tkinter specific data is in the Element's member variable user_bind_event
- :param bind_string: The string tkinter expected in its bind function
- :type bind_string: (str)
- :param key_modifier: Additional data to be added to the element's key when event is returned
- :type key_modifier: (str)
- :param propagate: If True then tkinter will be told to propagate the event to the element
- :type propagate: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- try:
- self.Widget.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt, propagate))
- except Exception as e:
- self.Widget.unbind_all(bind_string)
- return
-
- self.user_bind_dict[bind_string] = key_modifier
-
- def unbind(self, bind_string):
- """
- Removes a previously bound tkinter event from an Element.
- :param bind_string: The string tkinter expected in its bind function
- :type bind_string: (str)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
- self.Widget.unbind(bind_string)
- self.user_bind_dict.pop(bind_string, None)
-
- def set_tooltip(self, tooltip_text):
- """
- Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip').
-
- :param tooltip_text: the text to show in tooltip. If None then no tip will be shown
- :type tooltip_text: str | None
- """
-
- if self.TooltipObject:
- try:
- self.TooltipObject.leave()
- except:
- pass
-
- self.TooltipObject = ToolTip(self.Widget, text=tooltip_text, timeout=DEFAULT_TOOLTIP_TIME)
-
-
- def remove_tooltip(self):
- """
- Removes a previiously created tooltip for an element
-
- """
-
- if self.TooltipObject:
- try:
- self.TooltipObject.remove()
- except:
- pass
-
-
- def set_focus(self, force=False):
- """
- Sets the current focus to be on this element
-
- :param force: if True will call focus_force otherwise calls focus_set
- :type force: bool
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
- try:
- if force:
- self.Widget.focus_force()
- else:
- self.Widget.focus_set()
- except Exception as e:
- _error_popup_with_traceback("Exception blocking focus. Check your element's Widget", e)
-
- def block_focus(self, block=True):
- """
- Enable or disable the element from getting focus by using the keyboard.
- If the block parameter is True, then this element will not be given focus by using
- the keyboard to go from one element to another.
- You CAN click on the element and utilize it.
-
- :param block: if True the element will not get focus via the keyboard
- :type block: bool
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
- try:
- self.ParentForm.TKroot.focus_force()
- if block:
- self.Widget.configure(takefocus=0)
- else:
- self.Widget.configure(takefocus=1)
- except Exception as e:
- _error_popup_with_traceback("Exception blocking focus. Check your element's Widget", e)
-
- def get_next_focus(self):
- """
- Gets the next element that should get focus after this element.
-
- :return: Element that will get focus after this one
- :rtype: (Element)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return None
-
- try:
- next_widget_focus = self.widget.tk_focusNext()
- return self.ParentForm.widget_to_element(next_widget_focus)
- except Exception as e:
- _error_popup_with_traceback("Exception getting next focus. Check your element's Widget", e)
-
- def get_previous_focus(self):
- """
- Gets the element that should get focus previous to this element.
-
- :return: Element that should get the focus before this one
- :rtype: (Element)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return None
- try:
- next_widget_focus = self.widget.tk_focusPrev() # tkinter.Widget
- return self.ParentForm.widget_to_element(next_widget_focus)
- except Exception as e:
- _error_popup_with_traceback("Exception getting previous focus. Check your element's Widget", e)
-
- def set_size(self, size=(None, None)):
- """
- Changes the size of an element to a specific size.
- It's possible to specify None for one of sizes so that only 1 of the element's dimensions are changed.
-
- :param size: The size in characters, rows typically. In some cases they are pixels
- :type size: (int, int)
- """
- try:
- if size[0] != None:
- self.Widget.config(width=size[0])
- except:
- print('Warning, error setting width on element with key=', self.Key)
- try:
- if size[1] != None:
- self.Widget.config(height=size[1])
- except:
- try:
- self.Widget.config(length=size[1])
- except:
- print('Warning, error setting height on element with key=', self.Key)
-
- if self.Type == ELEM_TYPE_GRAPH:
- self.CanvasSize = size
-
- def get_size(self):
- """
- Return the size of an element in Pixels. Care must be taken as some elements use characters to specify their size but will return pixels when calling this get_size method.
- :return: width and height of the element
- :rtype: (int, int)
- """
- try:
- w = self.Widget.winfo_width()
- h = self.Widget.winfo_height()
- except:
- print('Warning, error getting size of element', self.Key)
- w = h = None
- return w, h
-
- def hide_row(self):
- """
- Hide the entire row an Element is located on.
- Use this if you must have all space removed when you are hiding an element, including the row container
- """
- try:
- self.ParentRowFrame.pack_forget()
- except:
- print('Warning, error hiding element row for key =', self.Key)
-
- def unhide_row(self):
- """
- Unhides (makes visible again) the row container that the Element is located on.
- Note that it will re-appear at the bottom of the window / container, most likely.
- """
- try:
- self.ParentRowFrame.pack()
- except:
- print('Warning, error hiding element row for key =', self.Key)
-
- def expand(self, expand_x=False, expand_y=False, expand_row=True):
- """
- Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions
-
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :param expand_row: If True the row containing the element will also expand. Without this your element is "trapped" within the row
- :type expand_row: (bool)
- """
- if expand_x and expand_y:
- fill = tk.BOTH
- elif expand_x:
- fill = tk.X
- elif expand_y:
- fill = tk.Y
- else:
- return
-
- if not self._widget_was_created():
- return
- self.Widget.pack(expand=True, fill=fill)
- self.ParentRowFrame.pack(expand=expand_row, fill=fill)
- if self.element_frame is not None:
- self.element_frame.pack(expand=True, fill=fill)
-
- def set_cursor(self, cursor=None, cursor_color=None):
- """
- Sets the cursor for the current Element.
- "Cursor" is used in 2 different ways in this call.
- For the parameter "cursor" it's actually the mouse pointer.
- If you do not want any mouse pointer, then use the string "none"
- For the parameter "cursor_color" it's the color of the beam used when typing into an input element
-
- :param cursor: The tkinter cursor name
- :type cursor: (str)
- :param cursor_color: color to set the "cursor" to
- :type cursor_color: (str)
- """
- if not self._widget_was_created():
- return
- if cursor is not None:
- try:
- self.Widget.config(cursor=cursor)
- except Exception as e:
- print('Warning bad cursor specified ', cursor)
- print(e)
- if cursor_color is not None:
- try:
- self.Widget.config(insertbackground=cursor_color)
- except Exception as e:
- print('Warning bad cursor color', cursor_color)
- print(e)
-
- def set_vscroll_position(self, percent_from_top):
- """
- Attempts to set the vertical scroll postition for an element's Widget
- :param percent_from_top: From 0 to 1.0, the percentage from the top to move scrollbar to
- :type percent_from_top: (float)
- """
- if self.Type == ELEM_TYPE_COLUMN and self.Scrollable:
- widget = self.widget.canvas # scrollable column is a special case
- else:
- widget = self.widget
-
- try:
- widget.yview_moveto(percent_from_top)
- except Exception as e:
- print('Warning setting the vertical scroll (yview_moveto failed)')
- print(e)
-
-
- def set_hscroll_position(self, percent_from_left):
- """
- Attempts to set the horizontal scroll postition for an element's Widget
- :param percent_from_left: From 0 to 1.0, the percentage from the left to move scrollbar to
- :type percent_from_left: (float)
- """
- if self.Type == ELEM_TYPE_COLUMN and self.Scrollable:
- widget = self.widget.canvas # scrollable column is a special case
- else:
- widget = self.widget
-
- try:
- widget.xview_moveto(percent_from_left)
- except Exception as e:
- print('Warning setting the horizontal scroll (xview_moveto failed)')
- print(e)
-
-
- def _widget_was_created(self):
- """
- Determines if a Widget was created for this element.
-
- :return: True if a Widget has been created previously (Widget is not None)
- :rtype: (bool)
- """
- if self.Widget is not None:
- return True
- else:
- if SUPPRESS_WIDGET_NOT_FINALIZED_WARNINGS:
- return False
-
- warnings.warn('You cannot Update element with key = {} until the window.read() is called or finalize=True when creating window'.format(self.Key), UserWarning)
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('Unable to complete operation on element with key {}'.format(self.Key),
- 'You cannot perform operations (such as calling update) on an Element until:',
- ' window.read() is called or finalize=True when Window created.',
- 'Adding a "finalize=True" parameter to your Window creation will likely fix this.',
- _create_error_message(),
- )
- return False
-
- def _grab_anywhere_on_using_control_key(self):
- """
- Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
- been Finalized or Read.
- """
- self.Widget.bind("", self.ParentForm._StartMove)
- self.Widget.bind("", self.ParentForm._StopMove)
- self.Widget.bind("", self.ParentForm._OnMotion)
-
- def _grab_anywhere_on(self):
- """
- Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
- been Finalized or Read.
- """
- self.Widget.bind("", self.ParentForm._StartMove)
- self.Widget.bind("", self.ParentForm._StopMove)
- self.Widget.bind("", self.ParentForm._OnMotion)
-
- def _grab_anywhere_off(self):
- """
- Turns off Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
- been Finalized or Read.
- """
- self.Widget.unbind("")
- self.Widget.unbind("")
- self.Widget.unbind("")
-
- def grab_anywhere_exclude(self):
- """
- Excludes this element from being used by the grab_anywhere feature
- Handy for elements like a Graph element when dragging is enabled. You want the Graph element to get the drag events instead of the window dragging.
- """
- self.ParentForm._grab_anywhere_ignore_these_list.append(self.Widget)
-
- def grab_anywhere_include(self):
- """
- Includes this element in the grab_anywhere feature
- This will allow you to make a Multline element drag a window for example
- """
- self.ParentForm._grab_anywhere_include_these_list.append(self.Widget)
-
-
- def set_right_click_menu(self, menu=None):
- """
- Sets a right click menu for an element.
- If a menu is already set for the element, it will call the tkinter destroy method to remove it
- :param menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type menu: List[List[ List[str] | str ]]
- """
- if menu == MENU_RIGHT_CLICK_DISABLED:
- return
- if menu is None:
- menu = self.ParentForm.RightClickMenu
- if menu is None:
- return
- if menu:
- # If previously had a menu destroy it
- if self.TKRightClickMenu:
- try:
- self.TKRightClickMenu.destroy() # just in case there's a problem let's not crash
- except:
- pass
- top_menu = tk.Menu(self.ParentForm.TKroot, tearoff=self.ParentForm.right_click_menu_tearoff, tearoffcommand=self._tearoff_menu_callback)
-
- if self.ParentForm.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(bg=self.ParentForm.right_click_menu_background_color)
- if self.ParentForm.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(fg=self.ParentForm.right_click_menu_text_color)
- if self.ParentForm.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(disabledforeground=self.ParentForm.right_click_menu_disabled_text_color)
- if self.ParentForm.right_click_menu_font is not None:
- top_menu.config(font=self.ParentForm.right_click_menu_font)
-
- if self.ParentForm.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activeforeground=self.ParentForm.right_click_menu_selected_colors[0])
- if self.ParentForm.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activebackground=self.ParentForm.right_click_menu_selected_colors[1])
- AddMenuItem(top_menu, menu[1], self, right_click_menu=True)
- self.TKRightClickMenu = top_menu
- if self.ParentForm.RightClickMenu: # if the top level has a right click menu, then setup a callback for the Window itself
- if self.ParentForm.TKRightClickMenu is None:
- self.ParentForm.TKRightClickMenu = top_menu
- if (running_mac()):
- self.ParentForm.TKroot.bind('', self.ParentForm._RightClickMenuCallback)
- else:
- self.ParentForm.TKroot.bind('', self.ParentForm._RightClickMenuCallback)
- if (running_mac()):
- self.Widget.bind('', self._RightClickMenuCallback)
- else:
- self.Widget.bind('', self._RightClickMenuCallback)
-
-
- def save_element_screenshot_to_disk(self, filename=None):
- """
- Saves an image of the PySimpleGUI window provided into the filename provided
-
- :param filename: Optional filename to save screenshot to. If not included, the User Settinds are used to get the filename
- :return: A PIL ImageGrab object that can be saved or manipulated
- :rtype: (PIL.ImageGrab | None)
- """
- global pil_import_attempted, pil_imported, PIL, ImageGrab, Image
-
- if not pil_import_attempted:
- try:
- import PIL as PIL
- from PIL import ImageGrab
- from PIL import Image
- pil_imported = True
- pil_import_attempted = True
- except:
- pil_imported = False
- pil_import_attempted = True
- print('FAILED TO IMPORT PIL!')
- return None
- try:
- # Add a little to the X direction if window has a titlebar
- rect = (
- self.widget.winfo_rootx(), self.widget.winfo_rooty(), self.widget.winfo_rootx() + self.widget.winfo_width(), self.widget.winfo_rooty() + self.widget.winfo_height())
-
- grab = ImageGrab.grab(bbox=rect)
- # Save the grabbed image to disk
- except Exception as e:
- # print(e)
- popup_error_with_traceback('Screen capture failure', 'Error happened while trying to save screencapture of an element', e)
- return None
-
- # return grab
- if filename is None:
- folder = pysimplegui_user_settings.get('-screenshots folder-', '')
- filename = pysimplegui_user_settings.get('-screenshots filename-', '')
- full_filename = os.path.join(folder, filename)
- else:
- full_filename = filename
- if full_filename:
- try:
- grab.save(full_filename)
- except Exception as e:
- popup_error_with_traceback('Screen capture failure', 'Error happened while trying to save screencapture', e)
- else:
- popup_error_with_traceback('Screen capture failure', 'You have attempted a screen capture but have not set up a good filename to save to')
- return grab
-
- def _pack_forget_save_settings(self, alternate_widget=None):
- """
- Performs a pack_forget which will make a widget invisible.
- This method saves the pack settings so that they can be restored if the element is made visible again
-
- :param alternate_widget: Widget to use that's different than the one defined in Element.Widget. These are usually Frame widgets
- :type alternate_widget: (tk.Widget)
- """
-
- if alternate_widget is not None and self.Widget is None:
- return
-
- widget = alternate_widget if alternate_widget is not None else self.Widget
- # if the widget is already invisible (i.e. not packed) then will get an error
- try:
- pack_settings = widget.pack_info()
- self.pack_settings = pack_settings
- widget.pack_forget()
- except:
- pass
-
- def _pack_restore_settings(self, alternate_widget=None):
- """
- Restores a previously packated widget which will make it visible again.
- If no settings were saved, then the widget is assumed to have not been unpacked and will not try to pack it again
-
- :param alternate_widget: Widget to use that's different than the one defined in Element.Widget. These are usually Frame widgets
- :type alternate_widget: (tk.Widget)
- """
-
- # if there are no saved pack settings, then assume it hasnb't been packaed before. The request will be ignored
- if self.pack_settings is None:
- return
-
- widget = alternate_widget if alternate_widget is not None else self.Widget
- if widget is not None:
- widget.pack(**self.pack_settings)
-
- def update(self, *args, **kwargs):
- """
- A dummy update call. This will only be called if an element hasn't implemented an update method
- It is provided here for docstring purposes. If you got here by browing code via PyCharm, know
- that this is not the function that will be called. Your actual element's update method will be called.
-
- If you call update, you must call window.refresh if you want the change to happen prior to your next
- window.read() call. Normally uou don't do this as the window.read call is likely going to happen next.
- """
- print('* Base Element Class update was called. Your element does not seem to have an update method')
-
- def __call__(self, *args, **kwargs):
- """
- Makes it possible to "call" an already existing element. When you do make the "call", it actually calls
- the Update method for the element.
- Example: If this text element was in yoiur layout:
- sg.Text('foo', key='T')
- Then you can call the Update method for that element by writing:
- window.find_element('T')('new text value')
- """
- return self.update(*args, **kwargs)
-
- SetTooltip = set_tooltip
- SetFocus = set_focus
-
-
-# ---------------------------------------------------------------------- #
-# Input Class #
-# ---------------------------------------------------------------------- #
-class Input(Element):
- """
- Display a single text input field. Based on the tkinter Widget `Entry`
- """
-
- def __init__(self, default_text='', size=(None, None), s=(None, None), disabled=False, password_char='', setting=None,
- justification=None, background_color=None, text_color=None, font=None, tooltip=None, border_width=None,
- change_submits=False, enable_events=False, do_not_clear=True, key=None, k=None, focus=False, pad=None, p=None,
- use_readonly_for_disable=True, readonly=False, disabled_readonly_background_color=None, disabled_readonly_text_color=None, selected_text_color=None,
- selected_background_color=None, expand_x=False, expand_y=False,
- right_click_menu=None, visible=True, metadata=None):
- """
- :param default_text: Text initially shown in the input box as a default value(Default value = ''). Will automatically be converted to string
- :type default_text: (Any)
- :param size: w=characters-wide, h=rows-high. If an int is supplied rather than a tuple, then a tuple is created width=int supplied and heigh=1
- :type size: (int, int) | (int, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param password_char: Password character if this is a password field (Default value = '')
- :type password_char: (char)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param justification: justification for data display. Valid choices - left, right, center
- :type justification: (str)
- :param background_color: color of background in one of the color formats
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param font: specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
- :type change_submits: (bool)
- :param enable_events: If True then changes to this element are immediately reported as an event. Use this instead of change_submits (Default = False)
- :type enable_events: (bool)
- :param do_not_clear: If False then the field will be set to blank after ANY event (button, any event) (Default = True)
- :type do_not_clear: (bool)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param focus: Determines if initial focus should go to this element.
- :type focus: (bool)
- :param pad: Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below)). If int is given, then converted to tuple (int, int) with the value provided duplicated
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param use_readonly_for_disable: If True (the default) tkinter state set to 'readonly'. Otherwise state set to 'disabled'
- :type use_readonly_for_disable: (bool)
- :param readonly: If True tkinter state set to 'readonly'. Use this in place of use_readonly_for_disable as another way of achieving readonly. Note cannot set BOTH readonly and disabled as tkinter only supplies a single flag
- :type readonly: (bool)
- :param disabled_readonly_background_color: If state is set to readonly or disabled, the color to use for the background
- :type disabled_readonly_background_color: (str)
- :param disabled_readonly_text_color: If state is set to readonly or disabled, the color to use for the text
- :type disabled_readonly_text_color: (str)
- :param selected_text_color: Color of text when it is selected (using mouse or control+A, etc)
- :type selected_text_color: (str)
- :param selected_background_color: Color of background when it is selected (using mouse or control+A, etc)
- :type selected_background_color: (str)
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param visible: set visibility state of the element (Default = True)
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.DefaultText = default_text if default_text is not None else ''
- self.PasswordCharacter = password_char
- bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- self.selected_text_color = selected_text_color
- self.selected_background_color = selected_background_color
- self.Focus = focus
- self.do_not_clear = do_not_clear
- self.Justification = justification
- self.Disabled = disabled
- self.ChangeSubmits = change_submits or enable_events
- self.RightClickMenu = right_click_menu
- self.UseReadonlyForDisable = use_readonly_for_disable
- self.disabled_readonly_background_color = disabled_readonly_background_color
- self.disabled_readonly_text_color = disabled_readonly_text_color
- self.ReadOnly = readonly
- self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
- self.TKEntry = self.Widget = None # type: tk.Entry
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- if setting is not None:
- self.setting = setting
- self.DefaultText = user_settings_get_entry(key, setting)
-
- super().__init__(ELEM_TYPE_INPUT_TEXT, size=sz, background_color=bg, text_color=fg, key=key, pad=pad,
- font=font, tooltip=tooltip, visible=visible, metadata=metadata)
-
- def update(self, value=None, disabled=None, select=None, visible=None, text_color=None, background_color=None, font=None, move_cursor_to='end', password_char=None, paste=None,
- readonly=None):
- """
- Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior.
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: new text to display as default text in Input field
- :type value: (str)
- :param disabled: disable or enable state of the element (sets Entry Widget to readonly or normal)
- :type disabled: (bool)
- :param select: if True, then the text will be selected
- :type select: (bool)
- :param visible: change visibility of element
- :type visible: (bool)
- :param text_color: change color of text being typed
- :type text_color: (str)
- :param background_color: change color of the background
- :type background_color: (str)
- :param font: specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param move_cursor_to: Moves the cursor to a particular offset. Defaults to 'end'
- :type move_cursor_to: int | str
- :param password_char: Password character if this is a password field
- :type password_char: str
- :param paste: If True "Pastes" the value into the element rather than replacing the entire element. If anything is selected it is replaced. The text is inserted at the current cursor location.
- :type paste: bool
- :param readonly: if True make element readonly (user cannot change any choices). Enables the element if either choice are made.
- :type readonly: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Input.update - The window was closed')
- return
-
- if background_color is not None:
- if _widget_set_bg_color(self.TKEntry, background_color): # set background using refactored function to check for errors, etc.
- self.BackgroundColor = background_color
- if text_color is not None:
- # self.TKEntry.configure(fg=text_color)
- if _widget_set_fg_color(self.TKEntry, text_color): # set foreground using refactored function to check for errors, etc.
- self.TextColor = text_color # save new color if all is OK
-
- if disabled is True:
- if self.UseReadonlyForDisable:
- _widget_set_fg_color(self.TKEntry, self.disabled_readonly_text_color)
- _widget_set_bg_color(self.TKEntry, self.disabled_readonly_background_color)
- self.TKEntry['state'] = 'readonly'
- else:
- self.TKEntry['state'] = 'disabled'
- self.Disabled = True
- elif disabled is False:
- self.TKEntry['state'] = 'normal'
- _widget_set_fg_color(self.TKEntry, self.TextColor)
- _widget_set_bg_color(self.TKEntry, self.BackgroundColor)
- # self.TKEntry.configure(fg=self.TextColor)
- self.Disabled = False
-
- if readonly is True:
- self.TKEntry['state'] = 'readonly'
- elif readonly is False:
- self.TKEntry['state'] = 'normal'
-
-
-
-
- if value is not None:
- if paste is not True:
- try:
- self.TKStringVar.set(value)
- except:
- pass
- self.DefaultText = value
- if paste is True:
- try:
- self.TKEntry.delete('sel.first', 'sel.last')
- except:
- pass
- self.TKEntry.insert("insert", value)
- if move_cursor_to == 'end':
- self.TKEntry.icursor(tk.END)
- elif move_cursor_to is not None:
- self.TKEntry.icursor(move_cursor_to)
- if select is True:
- self.TKEntry.select_range(0, 'end')
- elif select is False:
- self.TKEntry.select_clear()
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKEntry.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKEntry.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- # self.TKEntry.pack(padx=self.pad_used[0], pady=self.pad_used[1], in_=self.ParentRowFrame)
- if visible is not None:
- self._visible = visible
- if password_char is not None:
- self.TKEntry.configure(show=password_char)
- self.PasswordCharacter = password_char
- if font is not None:
- self.TKEntry.configure(font=font)
-
-
-
- def set_ibeam_color(self, ibeam_color=None):
- """
- Sets the color of the I-Beam that is used to "insert" characters. This is oftens called a "Cursor" by
- many users. To keep from being confused with tkinter's definition of cursor (the mouse pointer), the term
- ibeam is used in this case.
- :param ibeam_color: color to set the "I-Beam" used to indicate where characters will be inserted
- :type ibeam_color: (str)
- """
-
- if not self._widget_was_created():
- return
- if ibeam_color is not None:
- try:
- self.Widget.config(insertbackground=ibeam_color)
- except Exception as e:
- _error_popup_with_traceback('Error setting I-Beam color in set_ibeam_color',
- 'The element has a key:', self.Key,
- 'The color passed in was:', ibeam_color)
-
-
-
-
- def get(self):
- """
- Read and return the current value of the input element. Must call `Window.Read` or `Window.Finalize` prior
-
- :return: current value of Input field or '' if error encountered
- :rtype: (str)
- """
- try:
- text = self.TKStringVar.get()
- except:
- text = ''
- return text
-
- Get = get
- Update = update
-
-
-# ------------------------- INPUT TEXT Element lazy functions ------------------------- #
-In = Input
-InputText = Input
-I = Input
-
-
-# ---------------------------------------------------------------------- #
-# Combo #
-# ---------------------------------------------------------------------- #
-class Combo(Element):
- """
- ComboBox Element - A combination of a single-line input and a drop-down menu. User can type in their own value or choose from list.
- """
-
- def __init__(self, values, default_value=None, size=(None, None), s=(None, None), auto_size_text=None, background_color=None, text_color=None, button_background_color=None,
- button_arrow_color=None, bind_return_key=False, setting=None, change_submits=False, enable_events=False, enable_per_char_events=None, disabled=False,right_click_menu=None, key=None, k=None, pad=None,
- p=None, expand_x=False, expand_y=False, tooltip=None, readonly=False, font=None, visible=True, metadata=None):
- """
- :param values: values to choose. While displayed as text, the items returned are what the caller supplied, not text
- :type values: List[Any] or Tuple[Any]
- :param default_value: Choice to be displayed as initial value. Must match one of values variable contents
- :type default_value: (Any)
- :param size: width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list. If an Int is passed rather than a tuple, then height is auto-set to 1 and width is value of the int
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_text: True if element should be the same size as the contents
- :type auto_size_text: (bool)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param button_background_color: The color of the background of the button on the combo box
- :type button_background_color: (str)
- :param button_arrow_color: The color of the arrow on the button on the combo box
- :type button_arrow_color: (str)
- :param bind_return_key: If True, then the return key will cause a the Combo to generate an event when return key is pressed
- :type bind_return_key: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param change_submits: DEPRICATED DO NOT USE. Use `enable_events` instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Combo event is when a choice is made
- :type enable_events: (bool)
- :param enable_per_char_events: Enables generation of events for every character that's input. This is like the Input element's events
- :type enable_per_char_events: (bool)
- :param disabled: set disable state for element
- :type disabled: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param tooltip: text that will appear when mouse hovers over this element
- :type tooltip: (str)
- :param readonly: make element readonly (user can't change). True means user cannot change
- :type readonly: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.Values = values
- self.DefaultValue = default_value
- self.ChangeSubmits = change_submits or enable_events
- self.Widget = self.TKCombo = None # type: ttk.Combobox
- self.Disabled = disabled
- self.Readonly = readonly
- self.BindReturnKey = bind_return_key
- bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.RightClickMenu = right_click_menu
-
- if button_background_color is None:
- self.button_background_color = theme_button_color()[1]
- else:
- self.button_background_color = button_background_color
- if button_arrow_color is None:
- self.button_arrow_color = theme_button_color()[0]
- else:
- self.button_arrow_color = button_arrow_color
- self.enable_per_char_events = enable_per_char_events
- if setting is not None:
- self.setting = setting
- self.DefaultValue = user_settings_get_entry(key, setting)
-
- super().__init__(ELEM_TYPE_INPUT_COMBO, size=sz, auto_size_text=auto_size_text, background_color=bg,
- text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata)
-
- def update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None, visible=None, size=(None, None), select=None, text_color=None, background_color=None):
- """
- Changes some of the settings for the Combo Element. Must call `Window.Read` or `Window.Finalize` prior.
- Note that the state can be in 3 states only.... enabled, disabled, readonly even
- though more combinations are available. The easy way to remember is that if you
- change the readonly parameter then you are enabling the element.
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: change which value is current selected based on new list of previous list of choices
- :type value: (Any)
- :param values: change list of choices
- :type values: List[Any]
- :param set_to_index: change selection to a particular choice starting with index = 0
- :type set_to_index: (int)
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param readonly: if True make element readonly (user cannot change any choices). Enables the element if either choice are made.
- :type readonly: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param visible: control visibility of element
- :type visible: (bool)
- :param size: width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list
- :type size: (int, int)
- :param select: if True, then the text will be selected, if False then selection will be cleared
- :type select: (bool)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- """
- if size != (None, None):
- if isinstance(size, int):
- size = (size, 1)
- if isinstance(size, tuple) and len(size) == 1:
- size = (size[0], 1)
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Combo.update - The window was closed')
- return
-
- if values is not None:
- try:
- self.TKCombo['values'] = values
- # self.TKCombo.current(0) # don't set any value if a new set of values was made
- except:
- pass
- self.Values = values
- if value is None:
- self.TKCombo.set('')
- if size == (None, None):
- max_line_len = max([len(str(l)) for l in self.Values]) if len(self.Values) else 0
- if self.AutoSizeText is False:
- width = self.Size[0]
- else:
- width = max_line_len + 1
- self.TKCombo.configure(width=width)
- else:
- self.TKCombo.configure(height=size[1])
- self.TKCombo.configure(width=size[0])
- if value is not None:
- if value not in self.Values:
- self.TKCombo.set(value)
- else:
- for index, v in enumerate(self.Values):
- if v == value:
- try:
- self.TKCombo.current(index)
- except:
- pass
- self.DefaultValue = value
- break
- if set_to_index is not None:
- try:
- self.TKCombo.current(set_to_index)
- self.DefaultValue = self.Values[set_to_index]
- except:
- pass
- if readonly:
- self.Readonly = True
- self.TKCombo['state'] = 'readonly'
- elif readonly is False:
- self.Readonly = False
- self.TKCombo['state'] = 'enable'
- if disabled is True:
- self.TKCombo['state'] = 'disable'
- elif disabled is False and self.Readonly is True:
- self.TKCombo['state'] = 'readonly'
- elif disabled is False and self.Readonly is False:
- self.TKCombo['state'] = 'enable'
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- combostyle = self.ttk_style
- style_name = self.ttk_style_name
- if text_color is not None:
- combostyle.configure(style_name, foreground=text_color)
- combostyle.configure(style_name, selectforeground=text_color)
- combostyle.configure(style_name, insertcolor=text_color)
- combostyle.map(style_name, fieldforeground=[('readonly', text_color)])
- self.TextColor = text_color
- if background_color is not None:
- combostyle.configure(style_name, selectbackground=background_color)
- combostyle.map(style_name, fieldbackground=[('readonly', background_color)])
- combostyle.configure(style_name, fieldbackground=background_color)
- self.BackgroundColor = background_color
-
-
- if self.Readonly is True:
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, selectforeground=text_color)
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, selectbackground=background_color)
-
-
- if font is not None:
- self.Font = font
- self.TKCombo.configure(font=font)
- self._dropdown_newfont = tkinter.font.Font(font=font)
- self.ParentRowFrame.option_add("*TCombobox*Listbox*Font", self._dropdown_newfont)
-
-
- # make tcl call to deal with colors for the drop-down formatting
- try:
- if self.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT) and \
- self.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- self.Widget.tk.eval(
- '[ttk::combobox::PopdownWindow {}].f.l configure -foreground {} -background {} -selectforeground {} -selectbackground {} -font {}'.format(self.Widget, self.TextColor, self.BackgroundColor, self.BackgroundColor, self.TextColor, self._dropdown_newfont))
- except Exception as e:
- pass # going to let this one slide
-
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKCombo.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKCombo.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- if visible is not None:
- self._visible = visible
- if select is True:
- self.TKCombo.select_range(0, tk.END)
- elif select is False:
- self.TKCombo.select_clear()
-
-
- def get(self):
- """
- Returns the current (right now) value of the Combo. DO NOT USE THIS AS THE NORMAL WAY OF READING A COMBO!
- You should be using values from your call to window.read instead. Know what you're doing if you use it.
-
- :return: Returns the value of what is currently chosen
- :rtype: Any | None
- """
- try:
- if self.TKCombo.current() == -1: # if the current value was not in the original list
- value = self.TKCombo.get() # then get the value typed in by user
- else:
- value = self.Values[self.TKCombo.current()] # get value from original list given index
- except:
- value = None # only would happen if user closes window
- return value
-
- Get = get
- Update = update
-
-
-# ------------------------- INPUT COMBO Element lazy functions ------------------------- #
-InputCombo = Combo
-DropDown = InputCombo
-Drop = InputCombo
-DD = Combo
-
-
-# ---------------------------------------------------------------------- #
-# Option Menu #
-# ---------------------------------------------------------------------- #
-class OptionMenu(Element):
- """
- Option Menu is an Element available ONLY on the tkinter port of PySimpleGUI. It's is a widget that is unique
- to tkinter. However, it looks much like a ComboBox. Instead of an arrow to click to pull down the list of
- choices, another little graphic is shown on the widget to indicate where you click. After clicking to activate,
- it looks like a Combo Box that you scroll to select a choice.
- """
-
- def __init__(self, values, default_value=None, size=(None, None), s=(None, None), disabled=False, enable_events=False, auto_size_text=None, expand_x=False, expand_y=False,
- background_color=None, text_color=None, key=None, k=None, pad=None, p=None, tooltip=None, visible=True, metadata=None):
- """
- :param values: Values to be displayed
- :type values: List[Any] or Tuple[Any]
- :param default_value: the value to choose by default
- :type default_value: (Any)
- :param size: (width, height) size in characters (wide), height is ignored and present to be consistent with other elements
- :type size: (int, int) (width, UNUSED)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param disabled: control enabled / disabled
- :type disabled: (bool)
- :param enable_events: Turns on the element specific events. OptionMenu event is when a choice is made
- :type enable_events: (bool)
- :param auto_size_text: True if size of Element should match the contents of the items
- :type auto_size_text: (bool)
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text that will appear when mouse hovers over this element
- :type tooltip: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.Values = values
- self.DefaultValue = default_value
- self.Widget = self.TKOptionMenu = None # type: tk.OptionMenu
- self.Disabled = disabled
- bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.ChangeSubmits = enable_events
-
- super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=sz, auto_size_text=auto_size_text, background_color=bg,
- text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
-
- def update(self, value=None, values=None, disabled=None, visible=None, size=(None, None)):
- """
- Changes some of the settings for the OptionMenu Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: the value to choose by default
- :type value: (Any)
- :param values: Values to be displayed
- :type values: List[Any]
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- :param size: (width, height) size in characters (wide), height is ignored and present to be consistent with other elements
- :type size: (int, int) (width, UNUSED)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in OptionMenu.update - The window was closed')
- return
-
- if values is not None:
- self.Values = values
- self.TKOptionMenu['menu'].delete(0, 'end')
-
- # Insert list of new options (tk._setit hooks them up to var)
- # self.TKStringVar.set(self.Values[0])
- for new_value in self.Values:
- self.TKOptionMenu['menu'].add_command(label=new_value, command=tk._setit(self.TKStringVar, new_value))
- if value is None:
- self.TKStringVar.set('')
-
- if size == (None, None):
- max_line_len = max([len(str(l)) for l in self.Values]) if len(self.Values) else 0
- if self.AutoSizeText is False:
- width = self.Size[0]
- else:
- width = max_line_len + 1
- self.TKOptionMenu.configure(width=width)
- else:
- self.TKOptionMenu.configure(width=size[0])
-
- if value is not None:
- self.DefaultValue = value
- self.TKStringVar.set(value)
-
- if disabled is True:
- self.TKOptionMenu['state'] = 'disabled'
- elif disabled is False:
- self.TKOptionMenu['state'] = 'normal'
- self.Disabled = disabled if disabled is not None else self.Disabled
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKOptionMenu.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKOptionMenu.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- if visible is not None:
- self._visible = visible
-
- Update = update
-
-
-# ------------------------- OPTION MENU Element lazy functions ------------------------- #
-InputOptionMenu = OptionMenu
-
-
-# ---------------------------------------------------------------------- #
-# Listbox #
-# ---------------------------------------------------------------------- #
-class Listbox(Element):
- """
- A List Box. Provide a list of values for the user to choose one or more of. Returns a list of selected rows
- when a window.read() is executed.
- """
-
- def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False,
- bind_return_key=False, size=(None, None), s=(None, None), disabled=False, justification=None, auto_size_text=None, font=None, no_scrollbar=False,
- horizontal_scroll=False, setting=None,
- background_color=None, text_color=None, highlight_background_color=None, highlight_text_color=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None,
- key=None, k=None, pad=None, p=None, tooltip=None, expand_x=False, expand_y=False, right_click_menu=None, visible=True, metadata=None):
- """
- :param values: list of values to display. Can be any type including mixed types as long as they have __str__ method
- :type values: List[Any] or Tuple[Any]
- :param default_values: which values should be initially selected
- :type default_values: List[Any]
- :param select_mode: Select modes are used to determine if only 1 item can be selected or multiple and how they can be selected. Valid choices begin with "LISTBOX_SELECT_MODE_" and include: LISTBOX_SELECT_MODE_SINGLE LISTBOX_SELECT_MODE_MULTIPLE LISTBOX_SELECT_MODE_BROWSE LISTBOX_SELECT_MODE_EXTENDED
- :type select_mode: (str)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Listbox generates events when an item is clicked
- :type enable_events: (bool)
- :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event when return key is pressed
- :type bind_return_key: (bool)
- :param size: w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (int, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param disabled: set disable state for element
- :type disabled: (bool)
- :param justification: justification for items in listbox. Valid choices - left, right, center. Default is left. NOTE - on some older versions of tkinter, not available
- :type justification: (str)
- :param auto_size_text: True if element should be the same size as the contents
- :type auto_size_text: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param no_scrollbar: Controls if a scrollbar should be shown. If True, no scrollbar will be shown
- :type no_scrollbar: (bool)
- :param horizontal_scroll: Controls if a horizontal scrollbar should be shown. If True a horizontal scrollbar will be shown in addition to vertical
- :type horizontal_scroll: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param highlight_background_color: color of the background when an item is selected. Defaults to normal text color (a reverse look)
- :type highlight_background_color: (str)
- :param highlight_text_color: color of the text when an item is selected. Defaults to the normal background color (a rerverse look)
- :type highlight_text_color: (str)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- if values is None:
- _error_popup_with_traceback('Error in your Listbox definition - The values parameter cannot be None', 'Use an empty list if you want no values in your Listbox')
-
- self.Values = values
- self.DefaultValues = default_values
- self.TKListbox = None
- self.ChangeSubmits = change_submits or enable_events
- self.BindReturnKey = bind_return_key
- self.Disabled = disabled
- if select_mode == LISTBOX_SELECT_MODE_BROWSE:
- self.SelectMode = SELECT_MODE_BROWSE
- elif select_mode == LISTBOX_SELECT_MODE_EXTENDED:
- self.SelectMode = SELECT_MODE_EXTENDED
- elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE:
- self.SelectMode = SELECT_MODE_MULTIPLE
- elif select_mode == LISTBOX_SELECT_MODE_SINGLE:
- self.SelectMode = SELECT_MODE_SINGLE
- else:
- self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE
- bg = background_color if background_color is not None else theme_input_background_color()
- fg = text_color if text_color is not None else theme_input_text_color()
- self.HighlightBackgroundColor = highlight_background_color if highlight_background_color is not None else fg
- self.HighlightTextColor = highlight_text_color if highlight_text_color is not None else bg
- self.RightClickMenu = right_click_menu
- self.vsb = None # type: tk.Scrollbar or None
- self.hsb = None # type: tk.Scrollbar | None
- self.TKListbox = self.Widget = None # type: tk.Listbox
- self.element_frame = None # type: tk.Frame
- self.NoScrollbar = no_scrollbar
- self.HorizontalScroll = horizontal_scroll
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.justification = justification
- if setting is not None:
- self.setting = setting
- self.DefaultValues = user_settings_get_entry(key, setting)
-
-
- super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=sz, auto_size_text=auto_size_text, font=font,
- background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata,
- sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width,
- sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
-
-
- def update(self, values=None, disabled=None, set_to_index=None, scroll_to_index=None, select_mode=None, visible=None):
- """
- Changes some of the settings for the Listbox Element. Must call `Window.Read` or `Window.Finalize` prior
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param values: new list of choices to be shown to user
- :type values: List[Any]
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param set_to_index: highlights the item(s) indicated. If parm is an int one entry will be set. If is a list, then each entry in list is highlighted
- :type set_to_index: int | list | tuple
- :param scroll_to_index: scroll the listbox so that this index is the first shown
- :type scroll_to_index: (int)
- :param select_mode: changes the select mode according to tkinter's listbox widget
- :type select_mode: (str)
- :param visible: control visibility of element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Listbox.update - The window was closed')
- return
-
- if disabled is True:
- self.TKListbox.configure(state='disabled')
- elif disabled is False:
- self.TKListbox.configure(state='normal')
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if values is not None:
- self.TKListbox.delete(0, 'end')
- for item in list(values):
- self.TKListbox.insert(tk.END, item)
- # self.TKListbox.selection_set(0, 0)
- self.Values = list(values)
- if set_to_index is not None:
- self.TKListbox.selection_clear(0, len(self.Values)) # clear all listbox selections
- if type(set_to_index) in (tuple, list):
- for i in set_to_index:
- try:
- self.TKListbox.selection_set(i, i)
- except:
- warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index))
- else:
- try:
- self.TKListbox.selection_set(set_to_index, set_to_index)
- except:
- warnings.warn('* Listbox Update selection_set failed with index {}*'.format(set_to_index))
- if visible is False:
- self._pack_forget_save_settings(self.element_frame)
- elif visible is True:
- self._pack_restore_settings(self.element_frame)
- if scroll_to_index is not None and len(self.Values):
- self.TKListbox.yview_moveto(scroll_to_index / len(self.Values))
- if select_mode is not None:
- try:
- self.TKListbox.config(selectmode=select_mode)
- except:
- print('Listbox.update error trying to change mode to: ', select_mode)
- if visible is not None:
- self._visible = visible
-
- def set_value(self, values):
- """
- Set listbox highlighted choices
-
- :param values: new values to choose based on previously set values
- :type values: List[Any] | Tuple[Any]
-
- """
- for index, item in enumerate(self.Values):
- try:
- if item in values:
- self.TKListbox.selection_set(index)
- else:
- self.TKListbox.selection_clear(index)
- except:
- pass
- self.DefaultValues = values
-
- def get_list_values(self):
- # type: (Listbox) -> List[Any]
- """
- Returns list of Values provided by the user in the user's format
-
- :return: List of values. Can be any / mixed types -> []
- :rtype: List[Any]
- """
- return self.Values
-
- def get_indexes(self):
- """
- Returns the items currently selected as a list of indexes
-
- :return: A list of offsets into values that is currently selected
- :rtype: List[int]
- """
- return self.TKListbox.curselection()
-
- def get(self):
- """
- Returns the list of items currently selected in this listbox. It should be identical
- to the value you would receive when performing a window.read() call.
-
- :return: The list of currently selected items. The actual items are returned, not the indexes
- :rtype: List[Any]
- """
- try:
- items = self.TKListbox.curselection()
- value = [self.Values[int(item)] for item in items]
- except:
- value = []
- return value
-
-
-
-
- def select_index(self, index, highlight_text_color=None, highlight_background_color=None):
- """
- Selects an index while providing capability to setting the selected color for the index to specific text/background color
-
- :param index: specifies which item to change. index starts at 0 and goes to length of values list minus one
- :type index: (int)
- :param highlight_text_color: color of the text when this item is selected.
- :type highlight_text_color: (str)
- :param highlight_background_color: color of the background when this item is selected
- :type highlight_background_color: (str)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Listbox.select_item - The window was closed')
- return
-
- if index >= len(self.Values):
- _error_popup_with_traceback('Index {} is out of range for Listbox.select_index. Max allowed index is {}.'.format(index, len(self.Values)-1))
- return
-
- self.TKListbox.selection_set(index, index)
-
- if highlight_text_color is not None:
- self.widget.itemconfig(index, selectforeground=highlight_text_color)
- if highlight_background_color is not None:
- self.widget.itemconfig(index, selectbackground=highlight_background_color)
-
-
- def set_index_color(self, index, text_color=None, background_color=None, highlight_text_color=None, highlight_background_color=None):
- """
- Sets the color of a specific item without selecting it
-
- :param index: specifies which item to change. index starts at 0 and goes to length of values list minus one
- :type index: (int)
- :param text_color: color of the text for this item
- :type text_color: (str)
- :param background_color: color of the background for this item
- :type background_color: (str)
- :param highlight_text_color: color of the text when this item is selected.
- :type highlight_text_color: (str)
- :param highlight_background_color: color of the background when this item is selected
- :type highlight_background_color: (str)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Listbox.set_item_color - The window was closed')
- return
-
- if index >= len(self.Values):
- _error_popup_with_traceback('Index {} is out of range for Listbox.set_index_color. Max allowed index is {}.'.format(index, len(self.Values)-1))
- return
-
- if text_color is not None:
- self.widget.itemconfig(index, fg=text_color)
- if background_color is not None:
- self.widget.itemconfig(index, bg=background_color)
- if highlight_text_color is not None:
- self.widget.itemconfig(index, selectforeground=highlight_text_color)
- if highlight_background_color is not None:
- self.widget.itemconfig(index, selectbackground=highlight_background_color)
-
-
-
- GetIndexes = get_indexes
- GetListValues = get_list_values
- SetValue = set_value
- Update = update
-
-
-LBox = Listbox
-LB = Listbox
-
-
-# ---------------------------------------------------------------------- #
-# Radio #
-# ---------------------------------------------------------------------- #
-class Radio(Element):
- """
- Radio Button Element - Used in a group of other Radio Elements to provide user with ability to select only
- 1 choice in a list of choices.
- """
-
- def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), s=(None, None), auto_size_text=None, setting=None,
- background_color=None, text_color=None, circle_color=None, font=None, key=None, k=None, pad=None, p=None, tooltip=None,
- change_submits=False, enable_events=False, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param text: Text to display next to button
- :type text: (str)
- :param group_id: Groups together multiple Radio Buttons. Any type works
- :type group_id: (Any)
- :param default: Set to True for the one element of the group you want initially selected
- :type default: (bool)
- :param disabled: set disable state
- :type disabled: (bool)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_text: if True will size the element to match the length of the text
- :type auto_size_text: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param circle_color: color of background of the circle that has the dot selection indicator in it
- :type circle_color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Radio Button events happen when an item is selected
- :type enable_events: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.InitialState = default
- self.Text = text
- self.Widget = self.TKRadio = None # type: tk.Radiobutton
- self.GroupID = group_id
- self.Value = None
- self.Disabled = disabled
- self.TextColor = text_color if text_color else theme_text_color()
- self.RightClickMenu = right_click_menu
-
- if circle_color is None:
- # ---- compute color of circle background ---
- try: # something in here will fail if a color is not specified in Hex
- text_hsl = _hex_to_hsl(self.TextColor)
- background_hsl = _hex_to_hsl(background_color if background_color else theme_background_color())
- l_delta = abs(text_hsl[2] - background_hsl[2]) / 10
- if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta)
- else:
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta)
- self.CircleBackgroundColor = rgb(*bg_rbg)
- except:
- self.CircleBackgroundColor = background_color if background_color else theme_background_color()
- else:
- self.CircleBackgroundColor = circle_color
- self.ChangeSubmits = change_submits or enable_events
- self.EncodedRadioValue = None
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- if setting is not None:
- self.setting = bool(setting)
- self.InitialState = user_settings_get_entry(key, self.setting)
-
-
-
-
- super().__init__(ELEM_TYPE_INPUT_RADIO, size=sz, auto_size_text=auto_size_text, font=font,
- background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
- tooltip=tooltip, visible=visible, metadata=metadata)
-
- def update(self, value=None, text=None, background_color=None, text_color=None, circle_color=None, disabled=None, visible=None):
- """
- Changes some of the settings for the Radio Button Element. Must call `Window.read` or `Window.finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: if True change to selected and set others in group to unselected
- :type value: (bool)
- :param text: Text to display next to radio button
- :type text: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text. Note this also changes the color of the selection dot
- :type text_color: (str)
- :param circle_color: color of background of the circle that has the dot selection indicator in it
- :type circle_color: (str)
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Radio.update - The window was closed')
- return
-
- if value is not None:
- try:
- if value is True:
- self.TKIntVar.set(self.EncodedRadioValue)
- elif value is False:
- if self.TKIntVar.get() == self.EncodedRadioValue:
- self.TKIntVar.set(0)
- except:
- print('Error updating Radio')
- self.InitialState = value
- if text is not None:
- self.Text = str(text)
- self.TKRadio.configure(text=self.Text)
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKRadio.configure(background=background_color)
- self.BackgroundColor = background_color
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKRadio.configure(fg=text_color)
- self.TextColor = text_color
-
- if circle_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.CircleBackgroundColor = circle_color
- self.TKRadio.configure(selectcolor=self.CircleBackgroundColor) # The background of the radio button
- elif text_color or background_color:
- if self.TextColor not in (None, COLOR_SYSTEM_DEFAULT) and self.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT) and self.TextColor.startswith(
- '#') and self.BackgroundColor.startswith('#'):
- # ---- compute color of circle background ---
- text_hsl = _hex_to_hsl(self.TextColor)
- background_hsl = _hex_to_hsl(self.BackgroundColor if self.BackgroundColor else theme_background_color())
- l_delta = abs(text_hsl[2] - background_hsl[2]) / 10
- if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta)
- else:
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta)
- self.CircleBackgroundColor = rgb(*bg_rbg)
- self.TKRadio.configure(selectcolor=self.CircleBackgroundColor) # The background of the checkbox
-
- if disabled is True:
- self.TKRadio['state'] = 'disabled'
- elif disabled is False:
- self.TKRadio['state'] = 'normal'
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
- if visible is not None:
- self._visible = visible
-
- def reset_group(self):
- """
- Sets all Radio Buttons in the group to not selected
- """
- self.TKIntVar.set(0)
-
- def get(self):
- # type: (Radio) -> bool
- """
- A snapshot of the value of Radio Button -> (bool)
-
- :return: True if this radio button is selected
- :rtype: (bool)
- """
- return self.TKIntVar.get() == self.EncodedRadioValue
-
- Get = get
- ResetGroup = reset_group
- Update = update
-
-
-R = Radio
-Rad = Radio
-
-
-# ---------------------------------------------------------------------- #
-# Checkbox #
-# ---------------------------------------------------------------------- #
-class Checkbox(Element):
- """
- Checkbox Element - Displays a checkbox and text next to it
- """
-
- def __init__(self, text, default=False, size=(None, None), s=(None, None), auto_size_text=None, setting=None, font=None, background_color=None, text_color=None, checkbox_color=None, highlight_thickness=1, change_submits=False, enable_events=False, disabled=False, key=None, k=None, pad=None, p=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param text: Text to display next to checkbox
- :type text: (str)
- :param default: Set to True if you want this checkbox initially checked
- :type default: (bool)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_text: if True will size the element to match the length of the text
- :type auto_size_text: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param checkbox_color: color of background of the box that has the check mark in it. The checkmark is the same color as the text
- :type checkbox_color: (str)
- :param highlight_thickness: thickness of border around checkbox when gets focus
- :type highlight_thickness: (int)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Checkbox events happen when an item changes
- :type enable_events: (bool)
- :param disabled: set disable state
- :type disabled: (bool)
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.Text = text
- self.InitialState = bool(default)
- self.Value = None
- self.TKCheckbutton = self.Widget = None # type: tk.Checkbutton
- self.Disabled = disabled
- self.TextColor = text_color if text_color else theme_text_color()
- self.RightClickMenu = right_click_menu
- self.highlight_thickness = highlight_thickness
-
- # ---- compute color of circle background ---
- if checkbox_color is None:
- try: # something in here will fail if a color is not specified in Hex
- text_hsl = _hex_to_hsl(self.TextColor)
- background_hsl = _hex_to_hsl(background_color if background_color else theme_background_color())
- l_delta = abs(text_hsl[2] - background_hsl[2]) / 10
- if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta)
- else:
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta)
- self.CheckboxBackgroundColor = rgb(*bg_rbg)
- except:
- self.CheckboxBackgroundColor = background_color if background_color else theme_background_color()
- else:
- self.CheckboxBackgroundColor = checkbox_color
- self.ChangeSubmits = change_submits or enable_events
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- if setting is not None:
- self.setting = bool(setting)
- self.InitialState = user_settings_get_entry(key, self.setting)
-
-
- super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=sz, auto_size_text=auto_size_text, font=font,
- background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
- tooltip=tooltip, visible=visible, metadata=metadata)
-
- def get(self):
- # type: (Checkbox) -> bool
- """
- Return the current state of this checkbox
-
- :return: Current state of checkbox
- :rtype: (bool)
- """
- return self.TKIntVar.get() != 0
-
- def update(self, value=None, text=None, background_color=None, text_color=None, checkbox_color=None, disabled=None, visible=None):
- """
- Changes some of the settings for the Checkbox Element. Must call `Window.Read` or `Window.Finalize` prior.
- Note that changing visibility may cause element to change locations when made visible after invisible
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: if True checks the checkbox, False clears it
- :type value: (bool)
- :param text: Text to display next to checkbox
- :type text: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text. Note this also changes the color of the checkmark
- :type text_color: (str)
- :param disabled: disable or enable element
- :type disabled: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Checkbox.update - The window was closed')
- return
-
- if value is not None:
- value = bool(value)
- try:
- self.TKIntVar.set(value)
- self.InitialState = value
- except:
- print('Checkbox update failed')
- if disabled is True:
- self.TKCheckbutton.configure(state='disabled')
- elif disabled is False:
- self.TKCheckbutton.configure(state='normal')
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if text is not None:
- self.Text = str(text)
- self.TKCheckbutton.configure(text=self.Text)
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKCheckbutton.configure(background=background_color)
- self.BackgroundColor = background_color
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKCheckbutton.configure(fg=text_color)
- self.TextColor = text_color
- # Color the checkbox itself
- if checkbox_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.CheckboxBackgroundColor = checkbox_color
- self.TKCheckbutton.configure(selectcolor=self.CheckboxBackgroundColor) # The background of the checkbox
- elif text_color or background_color:
- if self.CheckboxBackgroundColor is not None and self.TextColor is not None and self.BackgroundColor is not None and self.TextColor.startswith(
- '#') and self.BackgroundColor.startswith('#'):
- # ---- compute color of checkbox background ---
- text_hsl = _hex_to_hsl(self.TextColor)
- background_hsl = _hex_to_hsl(self.BackgroundColor if self.BackgroundColor else theme_background_color())
- l_delta = abs(text_hsl[2] - background_hsl[2]) / 10
- if text_hsl[2] > background_hsl[2]: # if the text is "lighter" than the background then make background darker
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] - l_delta)
- else:
- bg_rbg = _hsl_to_rgb(background_hsl[0], background_hsl[1], background_hsl[2] + l_delta)
- self.CheckboxBackgroundColor = rgb(*bg_rbg)
- self.TKCheckbutton.configure(selectcolor=self.CheckboxBackgroundColor) # The background of the checkbox
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
-
- Get = get
- Update = update
-
-
-# ------------------------- CHECKBOX Element lazy functions ------------------------- #
-CB = Checkbox
-CBox = Checkbox
-Check = Checkbox
-
-
-# ---------------------------------------------------------------------- #
-# Spin #
-# ---------------------------------------------------------------------- #
-
-class Spin(Element):
- """
- A spinner with up/down buttons and a single line of text. Choose 1 values from list
- """
-
- def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, readonly=False, setting=None,
- size=(None, None), s=(None, None), auto_size_text=None, bind_return_key=None, font=None, background_color=None, text_color=None, key=None, k=None, pad=None,
- p=None, wrap=None,
- tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param values: List of valid values
- :type values: Tuple[Any] or List[Any]
- :param initial_value: Initial item to show in window. Choose from list of values supplied
- :type initial_value: (Any)
- :param disabled: set disable state
- :type disabled: (bool)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Spin events happen when an item changes
- :type enable_events: (bool)
- :param readonly: If True, then users cannot type in values. Only values from the values list are allowed.
- :type readonly: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_text: if True will size the element to match the length of the text
- :type auto_size_text: (bool)
- :param bind_return_key: If True, then the return key will cause a the element to generate an event when return key is pressed
- :type bind_return_key: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param wrap: Determines if the values should "Wrap". Default is False. If True, when reaching last value, will continue back to the first value.
- :type wrap: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.Values = values
- self.DefaultValue = initial_value
- self.ChangeSubmits = change_submits or enable_events
- self.TKSpinBox = self.Widget = None # type: tk.Spinbox
- self.Disabled = disabled
- self.Readonly = readonly
- self.RightClickMenu = right_click_menu
- self.BindReturnKey = bind_return_key
- self.wrap = wrap
-
- bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- if setting is not None:
- self.setting = setting
- self.DefaultValue = user_settings_get_entry(key, setting)
-
-
- super().__init__(ELEM_TYPE_INPUT_SPIN, size=sz, auto_size_text=auto_size_text, font=font, background_color=bg, text_color=fg,
- key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def update(self, value=None, values=None, disabled=None, readonly=None, visible=None):
- """
- Changes some of the settings for the Spin Element. Must call `Window.Read` or `Window.Finalize` prior
- Note that the state can be in 3 states only.... enabled, disabled, readonly even
- though more combinations are available. The easy way to remember is that if you
- change the readonly parameter then you are enabling the element.
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: set the current value from list of choices
- :type value: (Any)
- :param values: set available choices
- :type values: List[Any]
- :param disabled: disable. Note disabled and readonly cannot be mixed. It must be one OR the other
- :type disabled: (bool)
- :param readonly: make element readonly. Note disabled and readonly cannot be mixed. It must be one OR the other
- :type readonly: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Spin.update - The window was closed')
- return
-
- if values != None:
- old_value = self.TKStringVar.get()
- self.Values = values
- self.TKSpinBox.configure(values=values)
- self.TKStringVar.set(old_value)
- if value is not None:
- try:
- self.TKStringVar.set(value)
- self.DefaultValue = value
- except:
- pass
-
- if readonly is True:
- self.Readonly = True
- self.TKSpinBox['state'] = 'readonly'
- elif readonly is False:
- self.Readonly = False
- self.TKSpinBox['state'] = 'normal'
- if disabled is True:
- self.TKSpinBox['state'] = 'disable'
- elif disabled is False:
- if self.Readonly:
- self.TKSpinBox['state'] = 'readonly'
- else:
- self.TKSpinBox['state'] = 'normal'
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
- if visible is not None:
- self._visible = visible
-
- def _SpinChangedHandler(self, event):
- """
- Callback function. Used internally only. Called by tkinter when Spinbox Widget changes. Results in Window.Read() call returning
-
- :param event: passed in from tkinter
- :type event:
- """
- # first, get the results table built
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
- # if self.ParentForm.CurrentlyRunningMainloop:
- # Window._window_that_exited = self.ParentForm
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
-
-
-
-
- def set_ibeam_color(self, ibeam_color=None):
- """
- Sets the color of the I-Beam that is used to "insert" characters. This is oftens called a "Cursor" by
- many users. To keep from being confused with tkinter's definition of cursor (the mouse pointer), the term
- ibeam is used in this case.
- :param ibeam_color: color to set the "I-Beam" used to indicate where characters will be inserted
- :type ibeam_color: (str)
- """
-
- if not self._widget_was_created():
- return
- if ibeam_color is not None:
- try:
- self.Widget.config(insertbackground=ibeam_color)
- except Exception as e:
- _error_popup_with_traceback('Error setting I-Beam color in set_ibeam_color',
- 'The element has a key:', self.Key,
- 'The color passed in was:', ibeam_color)
-
-
-
- def get(self):
- """
- Return the current chosen value showing in spinbox.
- This value will be the same as what was provided as list of choices. If list items are ints, then the
- item returned will be an int (not a string)
-
- :return: The currently visible entry
- :rtype: (Any)
- """
- value = self.TKStringVar.get()
- for v in self.Values:
- if str(v) == value:
- value = v
- break
- return value
-
- Get = get
- Update = update
-
-
-Sp = Spin # type: Spin
-
-
-# ---------------------------------------------------------------------- #
-# Multiline #
-# ---------------------------------------------------------------------- #
-class Multiline(Element):
- """
- Multiline Element - Display and/or read multiple lines of text. This is both an input and output element.
- Other PySimpleGUI ports have a separate MultilineInput and MultilineOutput elements. May want to split this
- one up in the future too.
- """
-
- def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, autoscroll_only_at_bottom=False, border_width=None,
- size=(None, None), s=(None, None), setting=None, auto_size_text=None, background_color=None, text_color=None, selected_text_color=None, selected_background_color=None, horizontal_scroll=False, change_submits=False, enable_events=False, do_not_clear=True, key=None, k=None, write_only=False, auto_refresh=False, reroute_stdout=False, reroute_stderr=False, reroute_cprint=False, echo_stdout_stderr=False, focus=False, font=None, pad=None, p=None, tooltip=None, justification=None, no_scrollbar=False, wrap_lines=None, sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None, expand_x=False, expand_y=False, rstrip=True, right_click_menu=None, visible=True, metadata=None):
- """
- :param default_text: Initial text to show
- :type default_text: (Any)
- :param enter_submits: if True, the Window.read call will return is enter key is pressed in this element
- :type enter_submits: (bool)
- :param disabled: set disable state
- :type disabled: (bool)
- :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end
- :type autoscroll: (bool)
- :param autoscroll_only_at_bottom: If True the contents of the element will automatically scroll only if the scrollbar is at the bottom of the multiline
- :type autoscroll_only_at_bottom: (bool)
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int | (None, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int | (None, int)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param auto_size_text: if True will size the element to match the length of the text
- :type auto_size_text: (bool)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param selected_text_color: Color of text when it is selected (using mouse or control+A, etc)
- :type selected_text_color: (str)
- :param selected_background_color: Color of background when it is selected (using mouse or control+A, etc)
- :type selected_background_color: (str)
- :param horizontal_scroll: Controls if a horizontal scrollbar should be shown. If True a horizontal scrollbar will be shown in addition to vertical
- :type horizontal_scroll: (bool)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: If True then any key press that happens when the element has focus will generate an event.
- :type enable_events: (bool)
- :param do_not_clear: if False the element will be cleared any time the Window.read call returns
- :type do_not_clear: (bool)
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param write_only: If True then no entry will be added to the values dictionary when the window is read
- :type write_only: bool
- :param auto_refresh: If True then anytime the element is updated, the window will be refreshed so that the change is immediately displayed
- :type auto_refresh: (bool)
- :param reroute_stdout: If True then all output to stdout will be output to this element
- :type reroute_stdout: (bool)
- :param reroute_stderr: If True then all output to stderr will be output to this element
- :type reroute_stderr: (bool)
- :param reroute_cprint: If True your cprint calls will output to this element. It's the same as you calling cprint_set_output_destination
- :type reroute_cprint: (bool)
- :param echo_stdout_stderr: If True then output to stdout and stderr will be output to this element AND also to the normal console location
- :type echo_stdout_stderr: (bool)
- :param focus: if True initial focus will go to this element
- :type focus: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param justification: text justification. left, right, center. Can use single characters l, r, c.
- :type justification: (str)
- :param no_scrollbar: If False then a vertical scrollbar will be shown (the default)
- :type no_scrollbar: (bool)
- :param wrap_lines: If True, the lines will be wrapped automatically. Other parms affect this setting, but this one will override them all. Default is it does nothing and uses previous settings for wrapping.
- :type wrap_lines: (bool)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param rstrip: If True the value returned in will have whitespace stripped from the right side
- :type rstrip: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.DefaultText = str(default_text)
- self.EnterSubmits = enter_submits
- bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
- self.Focus = focus
- self.do_not_clear = do_not_clear
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
- self.selected_text_color = selected_text_color
- self.selected_background_color = selected_background_color
- self.Autoscroll = autoscroll
- self.Disabled = disabled
- self.ChangeSubmits = change_submits or enable_events
- self.RightClickMenu = right_click_menu
- self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
- self.TagCounter = 0
- self.TKText = self.Widget = None # type: tk.Text
- self.element_frame = None # type: tk.Frame
- self.HorizontalScroll = horizontal_scroll
- self.tags = set()
- self.WriteOnly = write_only
- self.AutoRefresh = auto_refresh
- key = key if key is not None else k
- self.reroute_cprint = reroute_cprint
- self.echo_stdout_stderr = echo_stdout_stderr
- self.Justification = 'left' if justification is None else justification
- self.justification_tag = self.just_center_tag = self.just_left_tag = self.just_right_tag = None
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.rstrip = rstrip
- self.wrap_lines = wrap_lines
- self.reroute_stdout = reroute_stdout
- self.reroute_stderr = reroute_stderr
- self.no_scrollbar = no_scrollbar
- self.hscrollbar = None # The horizontal scrollbar
- self.auto_scroll_only_at_bottom = autoscroll_only_at_bottom
- sz = size if size != (None, None) else s
- self.images_for_print = [] # holds a reference for images so that tkinter will render them correctly
- if setting is not None:
- self.setting = str(setting)
- self.DefaultText = user_settings_get_entry(key, self.setting)
-
- super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=sz, auto_size_text=auto_size_text, background_color=bg,
- text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata,
- sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width, sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
- return
-
- def update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None, text_color_for_value=None,
- background_color_for_value=None, visible=None, autoscroll=None, justification=None, font_for_value=None, image=None, image_subsample=None):
- """
- Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: new text to display
- :type value: (Any)
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param append: if True then new value will be added onto the end of the current value. if False then contents will be replaced.
- :type append: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the entire element
- :type font: (str or (str, int[, str]) or None)
- :param text_color: color of the text
- :type text_color: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color_for_value: color of the new text being added (the value paramter)
- :type text_color_for_value: (str)
- :param background_color_for_value: color of the new background of the text being added (the value paramter)
- :type background_color_for_value: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param autoscroll: if True then contents of element are scrolled down when new text is added to the end
- :type autoscroll: (bool)
- :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element
- :type justification: (str)
- :param font_for_value: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the value being updated
- :type font_for_value: str | (str, int)
- :param image: Insert this image inline with text. Can be Raw or Base64 representation of the image or filename of image
- :type image: (str | bytes)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- # _error_popup_with_traceback('Error in Multiline.update - The window was closed')
- return
-
- if autoscroll is not None:
- self.Autoscroll = autoscroll
- current_scroll_position = self.TKText.yview()[1]
-
- if justification is not None:
- if justification.startswith('l'):
- just_tag = 'left'
- if justification.startswith('r'):
- just_tag = 'right'
- if justification.startswith('c'):
- just_tag = 'center'
- else:
- just_tag = self.justification_tag
-
- starting_point = self.Widget.index(tk.INSERT)
- tag = None
- # First insert the text
- if value is not None:
- value = str(value)
- if background_color_for_value is not None or text_color_for_value is not None or font_for_value is not None:
- try:
- tag = 'Multiline(' + str(text_color_for_value) + ',' + str(background_color_for_value) + ',' + str(font_for_value) + ')'
- if tag not in self.tags:
- self.tags.add(tag)
- if background_color_for_value is not None:
- self.TKText.tag_configure(tag, background=background_color_for_value)
- if text_color_for_value is not None:
- self.TKText.tag_configure(tag, foreground=text_color_for_value)
- if font_for_value is not None:
- self.TKText.tag_configure(tag, font=font_for_value)
- except Exception as e:
- print('* Multiline.update - bad color likely specified:', e)
- if self.Disabled:
- self.TKText.configure(state='normal')
- try:
- if not append:
- self.TKText.delete('1.0', tk.END)
- if tag is not None or just_tag is not None:
- self.TKText.insert(tk.END, value, (just_tag, tag))
- else:
- self.TKText.insert(tk.END, value)
-
- # self.TKText.tag_add(just_tag, starting_point, starting_point)
-
- except Exception as e:
- print("* Error setting multiline *", e)
- if self.Disabled:
- self.TKText.configure(state='disabled')
- self.DefaultText = value
- # Insert an image
- if image is not None:
- try:
- if isinstance(image, bytes):
- self.tkimage = tk.PhotoImage(data=image)
- elif isinstance(image, str):
- self.tkimage = tk.PhotoImage(file=image)
- if image_subsample is not None:
- self.tkimage = self.tkimage.subsample(image_subsample)
- self.images_for_print.append(self.tkimage)
- self.widget.image_create(tk.END, image=self.tkimage)
- except Exception as e:
- print("* Error updating multiline with an image *", e)
-
- # if self.Autoscroll:
- # self.TKText.see(tk.END)
- if self.Autoscroll:
- if not self.auto_scroll_only_at_bottom or (self.auto_scroll_only_at_bottom and current_scroll_position == 1.0):
- self.TKText.see(tk.END)
- if disabled is True:
- self.TKText.configure(state='disabled')
- elif disabled is False:
- self.TKText.configure(state='normal')
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(background=background_color)
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(fg=text_color)
- if font is not None:
- self.TKText.configure(font=font)
-
- if visible is False:
- self._pack_forget_save_settings(alternate_widget=self.element_frame)
- # self.element_frame.pack_forget()
- elif visible is True:
- self._pack_restore_settings(alternate_widget=self.element_frame)
- # self.element_frame.pack(padx=self.pad_used[0], pady=self.pad_used[1])
-
- if self.AutoRefresh and self.ParentForm:
- try: # in case the window was destroyed
- self.ParentForm.refresh()
- except:
- pass
- if visible is not None:
- self._visible = visible
-
- def get(self):
- """
- Return current contents of the Multiline Element
-
- :return: current contents of the Multiline Element (used as an input type of Multiline
- :rtype: (str)
- """
- value = str(self.TKText.get(1.0, tk.END))
- if self.rstrip:
- return value.rstrip()
- return value
-
- def print(self, *args, end=None, sep=None, text_color=None, background_color=None, justification=None, font=None, colors=None, t=None, b=None, c=None,
- autoscroll=True, image=None, image_subsample=None):
- """
- Print like Python normally prints except route the output to a multiline element and also add colors if desired
-
- colors -(str, str) or str. A combined text/background color definition in a single parameter
-
- There are also "aliases" for text_color, background_color and colors (t, b, c)
- t - An alias for color of the text (makes for shorter calls)
- b - An alias for the background_color parameter
- c - (str, str) - "shorthand" way of specifying color. (foreground, backgrouned)
- c - str - can also be a string of the format "foreground on background" ("white on red")
-
- With the aliases it's possible to write the same print but in more compact ways:
- cprint('This will print white text on red background', c=('white', 'red'))
- cprint('This will print white text on red background', c='white on red')
- cprint('This will print white text on red background', text_color='white', background_color='red')
- cprint('This will print white text on red background', t='white', b='red')
-
- :param args: The arguments to print
- :type args: (Any)
- :param end: The end char to use just like print uses
- :type end: (str)
- :param sep: The separation character like print uses
- :type sep: (str)
- :param text_color: The color of the text
- :type text_color: (str)
- :param background_color: The background color of the line
- :type background_color: (str)
- :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element
- :type justification: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the args being printed
- :type font: (str or (str, int[, str]) or None)
- :param colors: Either a tuple or a string that has both the text and background colors. Or just the text color
- :type colors: (str) or (str, str)
- :param t: Color of the text
- :type t: (str)
- :param b: The background color of the line
- :type b: (str)
- :param c: Either a tuple or a string that has both the text and background colors or just tex color (same as the color parm)
- :type c: (str) or (str, str)
- :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end
- :type autoscroll: (bool)
- :param image: Insert this image inline with text. Can be Raw or Base64 representation of the image or filename of image
- :type image: (str | bytes)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- """
-
- kw_text_color = text_color or t
- kw_background_color = background_color or b
- dual_color = colors or c
- try:
- if isinstance(dual_color, tuple):
- kw_text_color = dual_color[0]
- kw_background_color = dual_color[1]
- elif isinstance(dual_color, str):
- if ' on ' in dual_color: # if has "on" in the string, then have both text and background
- kw_text_color = dual_color.split(' on ')[0]
- kw_background_color = dual_color.split(' on ')[1]
- else: # if no "on" then assume the color string is just the text color
- kw_text_color = dual_color
- except Exception as e:
- print('* multiline print warning * you messed up with color formatting', e)
- # NOTE - this is NOT calling a method, it's calling a function outside of this object
- _print_to_element(self, *args, end=end, sep=sep, text_color=kw_text_color, background_color=kw_background_color, justification=justification,
- autoscroll=autoscroll, font=font, image=image, image_subsample=image_subsample)
-
- def reroute_stdout_to_here(self):
- """
- Sends stdout (prints) to this element
- """
- # if nothing on the stack, then need to save the very first stdout
- if len(Window._rerouted_stdout_stack) == 0:
- Window._original_stdout = sys.stdout
- Window._rerouted_stdout_stack.insert(0, (self.ParentForm, self))
- sys.stdout = self
-
- def reroute_stderr_to_here(self):
- """
- Sends stderr to this element
- """
- if len(Window._rerouted_stderr_stack) == 0:
- Window._original_stderr = sys.stderr
- Window._rerouted_stderr_stack.insert(0, (self.ParentForm, self))
- sys.stderr = self
-
- def restore_stdout(self):
- """
- Restore a previously re-reouted stdout back to the original destination
- """
- Window._restore_stdout()
-
- def restore_stderr(self):
- """
- Restore a previously re-reouted stderr back to the original destination
- """
- Window._restore_stderr()
-
- def write(self, txt):
- """
- Called by Python (not tkinter?) when stdout or stderr wants to write
-
- :param txt: text of output
- :type txt: (str)
- """
- try:
- self.update(txt, append=True)
- # if need to echo, then send the same text to the destinatoin that isn't thesame as this one
- if self.echo_stdout_stderr:
- if sys.stdout != self:
- sys.stdout.write(txt)
- elif sys.stderr != self:
- sys.stderr.write(txt)
- except:
- pass
-
- def flush(self):
- """
- Flush parameter was passed into a print statement.
- For now doing nothing. Not sure what action should be taken to ensure a flush happens regardless.
- """
- # try:
- # self.previous_stdout.flush()
- # except:
- # pass
- return
-
-
-
-
-
- def set_ibeam_color(self, ibeam_color=None):
- """
- Sets the color of the I-Beam that is used to "insert" characters. This is oftens called a "Cursor" by
- many users. To keep from being confused with tkinter's definition of cursor (the mouse pointer), the term
- ibeam is used in this case.
- :param ibeam_color: color to set the "I-Beam" used to indicate where characters will be inserted
- :type ibeam_color: (str)
- """
-
- if not self._widget_was_created():
- return
- if ibeam_color is not None:
- try:
- self.Widget.config(insertbackground=ibeam_color)
- except Exception as e:
- _error_popup_with_traceback('Error setting I-Beam color in set_ibeam_color',
- 'The element has a key:', self.Key,
- 'The color passed in was:', ibeam_color)
-
-
-
- def __del__(self):
- """
- AT ONE TIME --- If this Widget is deleted, be sure and restore the old stdout, stderr
- Now the restore is done differently. Do not want to RELY on Python to call this method
- in order for stdout and stderr to be restored. Instead explicit restores are called.
-
- """
-
- return
-
- Get = get
- Update = update
-
-
-ML = Multiline
-MLine = Multiline
-
-
-# ---------------------------------------------------------------------- #
-# Text #
-# ---------------------------------------------------------------------- #
-class Text(Element):
- """
- Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars.
- """
-
- def __init__(self, text='', size=(None, None), s=(None, None), auto_size_text=None, click_submits=False, enable_events=False, relief=None, font=None,
- text_color=None, background_color=None, colors=(None,None), border_width=None, justification=None, pad=None, p=None, key=None, k=None, right_click_menu=None, expand_x=False,
- expand_y=False, grab=None, tooltip=None, visible=True, metadata=None):
- """
- :param text: The text to display. Can include /n to achieve multiple lines. Will convert (optional) parameter into a string
- :type text: Any
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (int, None) | (None, None) | (int, ) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (int, None) | (None, None) | (int, ) | int
- :param auto_size_text: if True size of the Text Element will be sized to fit the string provided in 'text' parm
- :type auto_size_text: (bool)
- :param click_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type click_submits: (bool)
- :param enable_events: Turns on the element specific events. Text events happen when the text is clicked
- :type enable_events: (bool)
- :param relief: relief style around the text. Values are same as progress meter relief values. Should be a constant that is defined at starting with RELIEF - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type relief: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param text_color: color of the text
- :type text_color: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param colors: Optional quick specification of both text and background colors in 1 parameter. If a single color specified, then assumed to be text_color
- :type colors: (str) or (str, str)
- :param border_width: number of pixels for the border (if using a relief)
- :type border_width: (int)
- :param justification: how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`
- :type justification: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str or int or tuple or object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param grab: If True can grab this element and move the window around. Default is False
- :type grab: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.DisplayText = str(text)
- tc = text_color if text_color else DEFAULT_TEXT_COLOR
- self.Justification = justification
- self.Relief = relief
- self.ClickSubmits = click_submits or enable_events
- if background_color is None:
- bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
- else:
- bg = background_color
-
- if colors != (None, None):
- dual_colors = _simplified_dual_color_to_tuple(colors)
- if dual_colors[0] is None and dual_colors[1] is not None: # if first entry is None, then use second as text color
- tc = dual_colors[1]
- else:
- tc = dual_colors[0]
- bg = dual_colors[1]
- self.TextColor = tc
- self.RightClickMenu = right_click_menu
- self.TKRightClickMenu = None
- self.BorderWidth = border_width
- self.Grab = grab
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_TEXT, auto_size_text=auto_size_text, size=sz, background_color=bg, font=font if font else DEFAULT_FONT,
- text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
-
- def update(self, value=None, background_color=None, text_color=None, font=None, visible=None):
- """
- Changes some of the settings for the Text Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: new text to show
- :type value: (Any)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param visible: set visibility state of the element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Text.update - The window was closed')
- return
-
- if value is not None:
- self.DisplayText = str(value)
- self.TKStringVar.set(str(value))
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(background=background_color)
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(fg=text_color)
- if font is not None:
- self.TKText.configure(font=font)
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKText.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKText.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- if visible is not None:
- self._visible = visible
-
- def get(self):
- """
- Gets the current value of the displayed text
-
- :return: The current value
- :rtype: (str)
- """
- try:
- text = self.TKStringVar.get()
- except:
- text = ''
- return text
-
- @classmethod
- def fonts_installed_list(cls):
- """
- Returns a list of strings that tkinter reports as the installed fonts
-
- :return: List of the installed font names
- :rtype: List[str]
- """
- # A window must exist before can perform this operation. Create the hidden master root if it doesn't exist
- _get_hidden_master_root()
-
- fonts = list(tkinter.font.families())
- fonts.sort()
-
- return fonts
-
- @classmethod
- def char_width_in_pixels(cls, font, character='W'):
- """
- Get the with of the character "W" in pixels for the font being passed in or
- the character of your choosing if "W" is not a good representative character.
- Cannot be used until a window has been created.
- If an error occurs, 0 will be returned
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured
- :type font: (str or (str, int[, str]) or None)
- :param character: specifies a SINGLE CHARACTER character to measure
- :type character: (str)
- :return: Width in pixels of "A"
- :rtype: (int)
- """
- # A window must exist before can perform this operation. Create the hidden master root if it doesn't exist
- _get_hidden_master_root()
-
- size = 0
- try:
- size = tkinter.font.Font(font=font).measure(character) # single character width
- except Exception as e:
- _error_popup_with_traceback('Exception retrieving char width in pixels', e)
-
- return size
-
- @classmethod
- def char_height_in_pixels(cls, font):
- """
- Get the height of a string if using the supplied font in pixels.
- Cannot be used until a window has been created.
- If an error occurs, 0 will be returned
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured
- :type font: (str or (str, int[, str]) or None)
- :return: Height in pixels of "A"
- :rtype: (int)
- """
-
- # A window must exist before can perform this operation. Create the hidden master root if it doesn't exist
- _get_hidden_master_root()
-
- size = 0
- try:
- size = tkinter.font.Font(font=font).metrics('linespace')
- except Exception as e:
- _error_popup_with_traceback('Exception retrieving char height in pixels', e)
-
- return size
-
- @classmethod
- def string_width_in_pixels(cls, font, string):
- """
- Get the with of the supplied string in pixels for the font being passed in.
- If an error occurs, 0 will be returned
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, to be measured
- :type font: (str or (str, int[, str]) or None)
- :param string: the string to measure
- :type string: str
- :return: Width in pixels of string
- :rtype: (int)
- """
-
- # A window must exist before can perform this operation. Create the hidden master root if it doesn't exist
- _get_hidden_master_root()
-
- size = 0
- try:
- size = tkinter.font.Font(font=font).measure(string) # string's width
- except Exception as e:
- _error_popup_with_traceback('Exception retrieving string width in pixels', e)
-
- return size
-
- def _print_to_element(self, *args, end=None, sep=None, text_color=None, background_color=None, autoscroll=None, justification=None, font=None, append=None):
- """
- Print like Python normally prints except route the output to a multiline element and also add colors if desired
-
- :param multiline_element: The multiline element to be output to
- :type multiline_element: (Multiline)
- :param args: The arguments to print
- :type args: List[Any]
- :param end: The end char to use just like print uses
- :type end: (str)
- :param sep: The separation character like print uses
- :type sep: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param background_color: The background color of the line
- :type background_color: (str)
- :param autoscroll: If True (the default), the element will scroll to bottom after updating
- :type autoscroll: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the value being updated
- :type font: str | (str, int)
- """
- end_str = str(end) if end is not None else '\n'
- sep_str = str(sep) if sep is not None else ' '
-
- outstring = ''
- num_args = len(args)
- for i, arg in enumerate(args):
- outstring += str(arg)
- if i != num_args - 1:
- outstring += sep_str
- outstring += end_str
- if append:
- outstring = self.get() + outstring
-
- self.update(outstring, text_color=text_color, background_color=background_color, font=font)
-
- try: # if the element is set to autorefresh, then refresh the parent window
- if self.AutoRefresh:
- self.ParentForm.refresh()
- except:
- pass
-
- def print(self, *args, end=None, sep=None, text_color=None, background_color=None, justification=None, font=None, colors=None, t=None, b=None, c=None, autoscroll=True,
- append=True):
- """
- Print like Python normally prints except route the output to a multiline element and also add colors if desired
-
- colors -(str, str) or str. A combined text/background color definition in a single parameter
-
- There are also "aliases" for text_color, background_color and colors (t, b, c)
- t - An alias for color of the text (makes for shorter calls)
- b - An alias for the background_color parameter
- c - (str, str) - "shorthand" way of specifying color. (foreground, backgrouned)
- c - str - can also be a string of the format "foreground on background" ("white on red")
-
- With the aliases it's possible to write the same print but in more compact ways:
- cprint('This will print white text on red background', c=('white', 'red'))
- cprint('This will print white text on red background', c='white on red')
- cprint('This will print white text on red background', text_color='white', background_color='red')
- cprint('This will print white text on red background', t='white', b='red')
-
- :param args: The arguments to print
- :type args: (Any)
- :param end: The end char to use just like print uses
- :type end: (str)
- :param sep: The separation character like print uses
- :type sep: (str)
- :param text_color: The color of the text
- :type text_color: (str)
- :param background_color: The background color of the line
- :type background_color: (str)
- :param justification: text justification. left, right, center. Can use single characters l, r, c. Sets only for this value, not entire element
- :type justification: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike for the args being printed
- :type font: (str or (str, int[, str]) or None)
- :param colors: Either a tuple or a string that has both the text and background colors. Or just the text color
- :type colors: (str) or (str, str)
- :param t: Color of the text
- :type t: (str)
- :param b: The background color of the line
- :type b: (str)
- :param c: Either a tuple or a string that has both the text and background colors or just tex color (same as the color parm)
- :type c: (str) or (str, str)
- :param autoscroll: If True the contents of the element will automatically scroll as more data added to the end
- :type autoscroll: (bool)
- :param append: If True the contents of the element will automatically scroll as more data added to the end
- :type append: (bool)
- """
-
- kw_text_color = text_color or t
- kw_background_color = background_color or b
- dual_color = colors or c
- try:
- if isinstance(dual_color, tuple):
- kw_text_color = dual_color[0]
- kw_background_color = dual_color[1]
- elif isinstance(dual_color, str):
- if ' on ' in dual_color: # if has "on" in the string, then have both text and background
- kw_text_color = dual_color.split(' on ')[0]
- kw_background_color = dual_color.split(' on ')[1]
- else: # if no "on" then assume the color string is just the text color
- kw_text_color = dual_color
- except Exception as e:
- print('* multiline print warning * you messed up with color formatting', e)
-
- self._print_to_element(*args, end=end, sep=sep, text_color=kw_text_color, background_color=kw_background_color, justification=justification, autoscroll=autoscroll,
- font=font, append=append)
-
- Get = get
- Update = update
-
-
-# ------------------------- Text Element lazy functions ------------------------- #
-
-Txt = Text # type: Text
-T = Text # type: Text
-
-
-# ---------------------------------------------------------------------- #
-# StatusBar #
-# ---------------------------------------------------------------------- #
-class StatusBar(Element):
- """
- A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line
- """
-
- def __init__(self, text, size=(None, None), s=(None, None), auto_size_text=None, click_submits=None, enable_events=False,
- relief=RELIEF_SUNKEN, font=None, text_color=None, background_color=None, justification=None, pad=None, p=None,
- key=None, k=None, right_click_menu=None, expand_x=False, expand_y=False, tooltip=None, visible=True, metadata=None):
- """
- :param text: Text that is to be displayed in the widget
- :type text: (str)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (int, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_text: True if size should fit the text length
- :type auto_size_text: (bool)
- :param click_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type click_submits: (bool)
- :param enable_events: Turns on the element specific events. StatusBar events occur when the bar is clicked
- :type enable_events: (bool)
- :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`
- :type relief: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param text_color: color of the text
- :type text_color: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param justification: how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`
- :type justification: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.DisplayText = text
- self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
- self.Justification = justification
- self.Relief = relief
- self.ClickSubmits = click_submits or enable_events
- if background_color is None:
- bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
- else:
- bg = background_color
- self.TKText = self.Widget = None # type: tk.Label
- key = key if key is not None else k
- self.RightClickMenu = right_click_menu
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_STATUSBAR, size=sz, auto_size_text=auto_size_text, background_color=bg,
- font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip,
- visible=visible, metadata=metadata)
- return
-
- def update(self, value=None, background_color=None, text_color=None, font=None, visible=None):
- """
- Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: new text to show
- :type value: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param visible: set visibility state of the element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in StatusBar.update - The window was closed')
- return
-
- if value is not None:
- self.DisplayText = value
- stringvar = self.TKStringVar
- stringvar.set(value)
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(background=background_color)
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKText.configure(fg=text_color)
- if font is not None:
- self.TKText.configure(font=font)
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKText.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKText.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- if visible is not None:
- self._visible = visible
-
- Update = update
-
-
-SBar = StatusBar
-
-
-# ---------------------------------------------------------------------- #
-# TKProgressBar #
-# Emulate the TK ProgressBar using canvas and rectangles
-# ---------------------------------------------------------------------- #
-
-class TKProgressBar():
- uniqueness_counter = 0
-
- def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], ttk_theme=DEFAULT_TTK_THEME, style_name='',
- relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH,
- orientation='horizontal', BarColor=(None, None), key=None):
- """
- :param root: The root window bar is to be shown in
- :type root: tk.Tk | tk.TopLevel
- :param max: Maximum value the bar will be measuring
- :type max: (int)
- :param length: length in pixels of the bar
- :type length: (int)
- :param width: width in pixels of the bar
- :type width: (int)
- :param style_name: Progress bar style to use. Set in the packer function
- :type style_name: (str)
- :param ttk_theme: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'
- :type ttk_theme: (str)
- :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF)
- :type relief: (str)
- :param border_width: The amount of pixels that go around the outside of the bar
- :type border_width: (int)
- :param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')
- :type orientation: (str)
- :param BarColor: The 2 colors that make up a progress bar. One is the background, the other is the bar
- :type BarColor: (str, str)
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- """
-
- self.Length = length
- self.Width = width
- self.Max = max
- self.Orientation = orientation
- self.Count = None
- self.PriorCount = 0
- self.style_name = style_name
-
- TKProgressBar.uniqueness_counter += 1
-
- if orientation.lower().startswith('h'):
- s = ttk.Style()
- _change_ttk_theme(s, ttk_theme)
-
- # self.style_name = str(key) + str(TKProgressBar.uniqueness_counter) + "my.Horizontal.TProgressbar"
- if BarColor != COLOR_SYSTEM_DEFAULT and BarColor[0] != COLOR_SYSTEM_DEFAULT:
- s.configure(self.style_name, background=BarColor[0], troughcolor=BarColor[1],
- troughrelief=relief, borderwidth=border_width, thickness=width)
- else:
- s.configure(self.style_name, troughrelief=relief, borderwidth=border_width, thickness=width)
-
- self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, style=self.style_name, length=length, orient=tk.HORIZONTAL, mode='determinate')
- else:
- s = ttk.Style()
- _change_ttk_theme(s, ttk_theme)
- # self.style_name = str(key) + str(TKProgressBar.uniqueness_counter) + "my.Vertical.TProgressbar"
- if BarColor != COLOR_SYSTEM_DEFAULT and BarColor[0] != COLOR_SYSTEM_DEFAULT:
-
- s.configure(self.style_name, background=BarColor[0],
- troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width)
- else:
- s.configure(self.style_name, troughrelief=relief, borderwidth=border_width, thickness=width)
-
- self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, style=self.style_name, length=length, orient=tk.VERTICAL, mode='determinate')
-
- def Update(self, count=None, max=None):
- """
- Update the current value of the bar and/or update the maximum value the bar can reach
- :param count: current value
- :type count: (int)
- :param max: the maximum value
- :type max: (int)
- """
- if max is not None:
- self.Max = max
- try:
- self.TKProgressBarForReal.config(maximum=max)
- except:
- return False
- if count is not None:
- try:
- self.TKProgressBarForReal['value'] = count
- except:
- return False
- return True
-
-
-# ---------------------------------------------------------------------- #
-# Output #
-# Routes stdout, stderr to a scrolled window #
-# ---------------------------------------------------------------------- #
-class Output(Multiline):
- """
- Output Element - a multi-lined text area to where stdout, stderr, cprint are rerouted.
-
- The Output Element is now based on the Multiline Element. When you make an Output Element, you're
- creating a Multiline Element with some specific settings set:
- auto_refresh = True
- auto_scroll = True
- reroute_stdout = True
- reroute_stderr = True
- reroute_cprint = True
- write_only = True
-
- If you choose to use a Multiline element to replace an Output element, be sure an turn on the write_only paramter in the Multiline
- so that an item is not included in the values dictionary on every window.read call
- """
-
- def __init__(self, size=(None, None), s=(None, None), background_color=None, text_color=None, pad=None, p=None, autoscroll_only_at_bottom=False, echo_stdout_stderr=False, font=None, tooltip=None,
- key=None, k=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None, wrap_lines=None, horizontal_scroll=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None):
- """
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param autoscroll_only_at_bottom: If True the contents of the element will automatically scroll only if the scrollbar is at the bottom of the multiline
- :type autoscroll_only_at_bottom: (bool)
- :param echo_stdout_stderr: If True then output to stdout will be output to this element AND also to the normal console location
- :type echo_stdout_stderr: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- :param wrap_lines: If True, the lines will be wrapped automatically. Other parms affect this setting, but this one will override them all. Default is it does nothing and uses previous settings for wrapping.
- :type wrap_lines: (bool)
- :param horizontal_scroll: Controls if a horizontal scrollbar should be shown. If True, then line wrapping will be off by default
- :type horizontal_scroll: (bool)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- """
-
-
- super().__init__(size=size, s=s, background_color=background_color, autoscroll_only_at_bottom=autoscroll_only_at_bottom, text_color=text_color, pad=pad, p=p, echo_stdout_stderr=echo_stdout_stderr, font=font, tooltip=tooltip, wrap_lines=wrap_lines, horizontal_scroll=horizontal_scroll, key=key, k=k, right_click_menu=right_click_menu, write_only=True, reroute_stdout=True, reroute_stderr=True, reroute_cprint=True, autoscroll=True, auto_refresh=True, expand_x=expand_x, expand_y=expand_y, visible=visible, metadata=metadata, sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width, sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
-
-
-
-# ---------------------------------------------------------------------- #
-# Button Class #
-# ---------------------------------------------------------------------- #
-class Button(Element):
- """
- Button Element - Defines all possible buttons. The shortcuts such as Submit, FileBrowse, ... each create a Button
- """
-
- def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None,
- file_types=FILE_TYPES_ALL_FILES, initial_folder=None, default_extension='', disabled=False, change_submits=False,
- enable_events=False, image_filename=None, image_data=None, image_size=(None, None),
- image_subsample=None, image_zoom=None, image_source=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- disabled_button_color=None,
- highlight_colors=None, mouseover_colors=(None, None), use_ttk_buttons=None, font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None,
- k=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param button_text: Text to be displayed on the button
- :type button_text: (str)
- :param button_type: You should NOT be setting this directly. ONLY the shortcut functions set this
- :type button_type: (int)
- :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button
- :type target: str | (int, int)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param file_types: the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.* *"),).
- :type file_types: Tuple[(str, str), ...]
- :param initial_folder: starting path for folders and files
- :type initial_folder: (str)
- :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs)
- :type default_extension: (str)
- :param disabled: If True button will be created disabled. If BUTTON_DISABLED_MEANS_IGNORE then the button will be ignored rather than disabled using tkinter
- :type disabled: (bool | str)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. If this button is a target, should it generate an event when filled in
- :type enable_events: (bool)
- :param image_source: Image to place on button. Use INSTEAD of the image_filename and image_data. Unifies these into 1 easier to use parm
- :type image_source: (str | bytes)
- :param image_filename: image filename if there is a button image. GIFs and PNGs only.
- :type image_filename: (str)
- :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data
- :type image_data: bytes | str
- :param image_size: Size of the image in pixels (width, height)
- :type image_size: (int, int)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
- :type image_zoom: (int)
- :param border_width: width of border around button in pixels
- :type border_width: (int)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int | None, int | None) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int | None, int | None) | (None, None) | int
- :param auto_size_button: if True the button size is sized to fit the text
- :type auto_size_button: (bool)
- :param button_color: Color of button. default is from theme or the window. Easy to remember which is which if you say "ON" between colors. "red" on "green". Normally a tuple, but can be a simplified-button-color-string "foreground on background". Can be a single color if want to set only the background.
- :type button_color: (str, str) | str
- :param disabled_button_color: colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color
- :type disabled_button_color: (str, str) | str
- :param highlight_colors: colors to use when button has focus (has focus, does not have focus). None will use colors based on theme. Only used by Linux and only for non-TTK button
- :type highlight_colors: (str, str)
- :param mouseover_colors: Important difference between Linux & Windows! Linux - Colors when mouse moved over button. Windows - colors when button is pressed. The default is to switch the text and background colors (an inverse effect)
- :type mouseover_colors: (str, str) | str
- :param use_ttk_buttons: True = use ttk buttons. False = do not use ttk buttons. None (Default) = use ttk buttons only if on a Mac and not with button images
- :type use_ttk_buttons: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: If True then pressing the return key in an Input or Multiline Element will cause this button to appear to be clicked (generates event with this button's key
- :type bind_return_key: (bool)
- :param focus: if True, initial focus will be put on this button
- :type focus: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.AutoSizeButton = auto_size_button
- self.BType = button_type
- if file_types is not None and len(file_types) == 2 and isinstance(file_types[0], str) and isinstance(file_types[1], str):
- warnings.warn('file_types parameter not correctly specified. This parameter is a LIST of TUPLES. You have passed (str,str) rather than ((str, str),). Fixing it for you this time.\nchanging {} to {}\nPlease correct your code'.format(file_types, ((file_types[0], file_types[1]),)), UserWarning)
- file_types = ((file_types[0], file_types[1]),)
- self.FileTypes = file_types
- self.Widget = self.TKButton = None # type: tk.Button
- self.Target = target
- self.ButtonText = str(button_text)
- self.RightClickMenu = right_click_menu
- self.ButtonColor = button_color_to_tuple(button_color)
-
- self.DisabledButtonColor = button_color_to_tuple(disabled_button_color) if disabled_button_color is not None else (None, None)
- if image_source is not None:
- if isinstance(image_source, bytes):
- image_data = image_source
- elif isinstance(image_source, str):
- image_filename = image_source
- self.ImageFilename = image_filename
- self.ImageData = image_data
- self.ImageSize = image_size
- self.ImageSubsample = image_subsample
- self.zoom = int(image_zoom) if image_zoom is not None else None
- self.UserData = None
- self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
- self.BindReturnKey = bind_return_key
- self.Focus = focus
- self.calendar_default_date_M_D_Y = (None, None, None)
- self.calendar_close_when_chosen = False
- self.calendar_locale = None
- self.calendar_format = None
- self.calendar_location = (None, None)
- self.calendar_no_titlebar = True
- self.calendar_begin_at_sunday_plus = 0
- self.calendar_month_names = None
- self.calendar_day_abbreviations = None
- self.calendar_title = ''
- self.calendar_selection = ''
- self.default_button = None
- self.InitialFolder = initial_folder
- self.DefaultExtension = default_extension
- self.Disabled = disabled
- self.ChangeSubmits = change_submits or enable_events
- self.UseTtkButtons = use_ttk_buttons
- self._files_delimiter = BROWSE_FILES_DELIMITER # used by the file browse button. used when multiple files are selected by user
- if use_ttk_buttons is None and running_mac():
- self.UseTtkButtons = True
- # if image_filename or image_data:
- # self.UseTtkButtons = False # if an image is to be displayed, then force the button to not be a TTK Button
- if key is None and k is None:
- _key = self.ButtonText
- if DEFAULT_USE_BUTTON_SHORTCUTS is True:
- pos = _key.find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or _key[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- _key = _key[:pos] + _key[pos + len(MENU_SHORTCUT_CHARACTER):]
- else:
- _key = _key.replace('\\'+MENU_SHORTCUT_CHARACTER, MENU_SHORTCUT_CHARACTER)
- else:
- _key = key if key is not None else k
- if highlight_colors is not None:
- self.HighlightColors = highlight_colors
- else:
- self.HighlightColors = self._compute_highlight_colors()
-
- if mouseover_colors != (None, None):
- self.MouseOverColors = button_color_to_tuple(mouseover_colors)
- elif button_color != None:
- self.MouseOverColors = (self.ButtonColor[1], self.ButtonColor[0])
- else:
- self.MouseOverColors = (theme_button_color()[1], theme_button_color()[0])
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- sz = size if size != (None, None) else s
- super().__init__(ELEM_TYPE_BUTTON, size=sz, font=font, pad=pad, key=_key, tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def _compute_highlight_colors(self):
- """
- Determines the color to use to indicate the button has focus. This setting is only used by Linux.
- :return: Pair of colors. (Highlight, Highlight Background)
- :rtype: (str, str)
- """
- highlight_color = highlight_background = COLOR_SYSTEM_DEFAULT
- if self.ButtonColor != COLOR_SYSTEM_DEFAULT and theme_background_color() != COLOR_SYSTEM_DEFAULT:
- highlight_background = theme_background_color()
- if self.ButtonColor != COLOR_SYSTEM_DEFAULT and self.ButtonColor[0] != COLOR_SYSTEM_DEFAULT:
- if self.ButtonColor[0] != theme_background_color():
- highlight_color = self.ButtonColor[0]
- else:
- highlight_color = 'red'
- return (highlight_color, highlight_background)
-
- # Realtime button release callback
-
- def ButtonReleaseCallBack(self, parm):
- """
- Not a user callable function. Called by tkinter when a "realtime" button is released
-
- :param parm: the event info from tkinter
- :type parm:
-
- """
- self.LastButtonClickedWasRealtime = False
- self.ParentForm.LastButtonClicked = None
-
- # Realtime button callback
- def ButtonPressCallBack(self, parm):
- """
- Not a user callable method. Callback called by tkinter when a "realtime" button is pressed
-
- :param parm: Event info passed in by tkinter
- :type parm:
-
- """
- self.ParentForm.LastButtonClickedWasRealtime = True
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = self.ButtonText
- # if self.ParentForm.CurrentlyRunningMainloop:
- # Window._window_that_exited = self.ParentForm
- # self.ParentForm.TKroot.quit() # kick out of loop if read was called
- _exit_mainloop(self.ParentForm)
-
- def _find_target(self):
- target = self.Target
- target_element = None
-
- if target[0] == ThisRow:
- target = [self.Position[0], target[1]]
- if target[1] < 0:
- target[1] = self.Position[1] + target[1]
- strvar = None
- should_submit_window = False
- if target == (None, None):
- strvar = self.TKStringVar
- else:
- # Need a try-block because if the target is not hashable, the "in" test will raise exception
- try:
- if target in self.ParentForm.AllKeysDict:
- target_element = self.ParentForm.AllKeysDict[target]
- except:
- pass
- # if target not found or the above try got exception, then keep looking....
- if target_element is None:
- if not isinstance(target, str):
- if target[0] < 0:
- target = [self.Position[0] + target[0], target[1]]
- target_element = self.ParentContainer._GetElementAtLocation(target)
- else:
- target_element = self.ParentForm.find_element(target)
- try:
- strvar = target_element.TKStringVar
- except:
- pass
- try:
- if target_element.ChangeSubmits:
- should_submit_window = True
- except:
- pass
- return target_element, strvar, should_submit_window
-
- # ------- Button Callback ------- #
- def ButtonCallBack(self):
- """
- Not user callable! Called by tkinter when a button is clicked. This is where all the fun begins!
- """
-
- if self.Disabled == BUTTON_DISABLED_MEANS_IGNORE:
- return
- target_element, strvar, should_submit_window = self._find_target()
-
- filetypes = FILE_TYPES_ALL_FILES if self.FileTypes is None else self.FileTypes
-
- if self.BType == BUTTON_TYPE_BROWSE_FOLDER:
- if running_mac(): # macs don't like seeing the parent window (go firgure)
- folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder) # show the 'get folder' dialog box
- else:
- folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get folder' dialog box
- if folder_name:
- try:
- strvar.set(folder_name)
- self.TKStringVar.set(folder_name)
- except:
- pass
- else: # if "cancel" button clicked, don't generate an event
- should_submit_window = False
- elif self.BType == BUTTON_TYPE_BROWSE_FILE:
- if running_mac():
- # Workaround for the "*.*" issue on Mac
- is_all = [(x, y) for (x, y) in filetypes if all(ch in '* .' for ch in y)]
- if not len(set(filetypes)) > 1 and (len(is_all) != 0 or filetypes == FILE_TYPES_ALL_FILES):
- file_name = tk.filedialog.askopenfilename(initialdir=self.InitialFolder)
- else:
- file_name = tk.filedialog.askopenfilename(initialdir=self.InitialFolder, filetypes=filetypes) # show the 'get file' dialog box
- # elif _mac_allow_filetypes():
- # file_name = tk.filedialog.askopenfilename(initialdir=self.InitialFolder, filetypes=filetypes) # show the 'get file' dialog box
- # else:
- # file_name = tk.filedialog.askopenfilename(initialdir=self.InitialFolder) # show the 'get file' dialog box
- else:
- file_name = tk.filedialog.askopenfilename(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box
-
- if file_name:
- strvar.set(file_name)
- self.TKStringVar.set(file_name)
- else: # if "cancel" button clicked, don't generate an event
- should_submit_window = False
- elif self.BType == BUTTON_TYPE_COLOR_CHOOSER:
- color = tk.colorchooser.askcolor(parent=self.ParentForm.TKroot, color=self.default_color) # show the 'get file' dialog box
- color = color[1] # save only the #RRGGBB portion
- if color is not None:
- strvar.set(color)
- self.TKStringVar.set(color)
- elif self.BType == BUTTON_TYPE_BROWSE_FILES:
- if running_mac():
- # Workaround for the "*.*" issue on Mac
- is_all = [(x, y) for (x, y) in filetypes if all(ch in '* .' for ch in y)]
- if not len(set(filetypes)) > 1 and (len(is_all) != 0 or filetypes == FILE_TYPES_ALL_FILES):
- file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder)
- else:
- file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder)
- else:
- file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot)
-
- if file_name:
- file_name = self._files_delimiter.join(file_name) # normally a ';'
- strvar.set(file_name)
- self.TKStringVar.set(file_name)
- else: # if "cancel" button clicked, don't generate an event
- should_submit_window = False
- elif self.BType == BUTTON_TYPE_SAVEAS_FILE:
- # show the 'get file' dialog box
- if running_mac():
- # Workaround for the "*.*" issue on Mac
- is_all = [(x, y) for (x, y) in filetypes if all(ch in '* .' for ch in y)]
- if not len(set(filetypes)) > 1 and (len(is_all) != 0 or filetypes == FILE_TYPES_ALL_FILES):
- file_name = tk.filedialog.asksaveasfilename(defaultextension=self.DefaultExtension, initialdir=self.InitialFolder)
- else:
- file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, defaultextension=self.DefaultExtension, initialdir=self.InitialFolder)
- else:
- file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, defaultextension=self.DefaultExtension, initialdir=self.InitialFolder,
- parent=self.ParentForm.TKroot)
-
- if file_name:
- strvar.set(file_name)
- self.TKStringVar.set(file_name)
- else: # if "cancel" button clicked, don't generate an event
- should_submit_window = False
- elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window
- # first, get the results table built
- # modify the Results table in the parent FlexForm object
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = self.ButtonText
- self.ParentForm.FormRemainedOpen = False
- self.ParentForm._Close()
- _exit_mainloop(self.ParentForm)
-
- if self.ParentForm.NonBlocking:
- self.ParentForm.TKroot.destroy()
- Window._DecrementOpenCount()
- elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE
- # This is a PLAIN BUTTON
- # first, get the results table built
- # modify the Results table in the parent FlexForm object
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = self.ButtonText
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
- elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop
- self.ParentForm._Close(without_event=True)
- self.ParentForm.TKroot.destroy() # close the window with tkinter
- Window._DecrementOpenCount()
- elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window
- # ------------ new chooser code -------------
- self.ParentForm.LastButtonClicked = self.Key # key should have been generated already if not set by user
- self.ParentForm.FormRemainedOpen = True
- should_submit_window = False
- _exit_mainloop(self.ParentForm)
-
- if should_submit_window:
- self.ParentForm.LastButtonClicked = target_element.Key
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
-
- return
-
- def update(self, text=None, button_color=(None, None), disabled=None, image_source=None, image_data=None, image_filename=None,
- visible=None, image_subsample=None, image_zoom=None, disabled_button_color=(None, None), image_size=None):
- """
- Changes some of the settings for the Button Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param text: sets button text
- :type text: (str)
- :param button_color: Color of button. default is from theme or the window. Easy to remember which is which if you say "ON" between colors. "red" on "green". Normally a tuple, but can be a simplified-button-color-string "foreground on background". Can be a single color if want to set only the background.
- :type button_color: (str, str) | str
- :param disabled: True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors)
- :type disabled: (bool | str)
- :param image_source: Image to place on button. Use INSTEAD of the image_filename and image_data. Unifies these into 1 easier to use parm
- :type image_source: (str | bytes)
- :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data
- :type image_data: bytes | str
- :param image_filename: image filename if there is a button image. GIFs and PNGs only.
- :type image_filename: (str)
- :param disabled_button_color: colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color
- :type disabled_button_color: (str, str)
- :param visible: control visibility of element
- :type visible: (bool)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
- :type image_zoom: (int)
- :param image_size: Size of the image in pixels (width, height)
- :type image_size: (int, int)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Button.update - The window was closed')
- return
-
- if image_source is not None:
- if isinstance(image_source, bytes):
- image_data = image_source
- elif isinstance(image_source, str):
- image_filename = image_source
-
- if self.UseTtkButtons:
- style_name = self.ttk_style_name # created when made initial window (in the pack)
- # style_name = str(self.Key) + 'custombutton.TButton'
- button_style = ttk.Style()
- if text is not None:
- btext = text
- if DEFAULT_USE_BUTTON_SHORTCUTS is True:
- pos = btext.find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or btext[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- btext = btext[:pos] + btext[pos + len(MENU_SHORTCUT_CHARACTER):]
- else:
- btext = btext.replace('\\'+MENU_SHORTCUT_CHARACTER, MENU_SHORTCUT_CHARACTER)
- pos = -1
- if pos != -1:
- self.TKButton.config(underline=pos)
- self.TKButton.configure(text=btext)
- self.ButtonText = text
- if button_color != (None, None) and button_color != COLOR_SYSTEM_DEFAULT:
- bc = button_color_to_tuple(button_color, self.ButtonColor)
- # if isinstance(button_color, str):
- # try:
- # button_color = button_color.split(' on ')
- # except Exception as e:
- # print('** Error in formatting your button color **', button_color, e)
- if self.UseTtkButtons:
- if bc[0] not in (None, COLOR_SYSTEM_DEFAULT):
- button_style.configure(style_name, foreground=bc[0])
- if bc[1] not in (None, COLOR_SYSTEM_DEFAULT):
- button_style.configure(style_name, background=bc[1])
- else:
- if bc[0] not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKButton.config(foreground=bc[0], activebackground=bc[0])
- if bc[1] not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKButton.config(background=bc[1], activeforeground=bc[1])
- self.ButtonColor = bc
- if disabled is True:
- self.TKButton['state'] = 'disabled'
- elif disabled is False:
- self.TKButton['state'] = 'normal'
- elif disabled == BUTTON_DISABLED_MEANS_IGNORE:
- self.TKButton['state'] = 'normal'
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if image_data is not None:
- image = tk.PhotoImage(data=image_data)
- if image_subsample:
- image = image.subsample(image_subsample)
- if image_zoom is not None:
- image = image.zoom(int(image_zoom))
- if image_size is not None:
- width, height = image_size
- else:
- width, height = image.width(), image.height()
- if self.UseTtkButtons:
- button_style.configure(style_name, image=image, width=width, height=height)
- else:
- self.TKButton.config(image=image, width=width, height=height)
- self.TKButton.image = image
- if image_filename is not None:
- image = tk.PhotoImage(file=image_filename)
- if image_subsample:
- image = image.subsample(image_subsample)
- if image_zoom is not None:
- image = image.zoom(int(image_zoom))
- if image_size is not None:
- width, height = image_size
- else:
- width, height = image.width(), image.height()
- if self.UseTtkButtons:
- button_style.configure(style_name, image=image, width=width, height=height)
- else:
- self.TKButton.config(highlightthickness=0, image=image, width=width, height=height)
- self.TKButton.image = image
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
- if disabled_button_color != (None, None) and disabled_button_color != COLOR_SYSTEM_DEFAULT:
- if not self.UseTtkButtons:
- self.TKButton['disabledforeground'] = disabled_button_color[0]
- else:
- if disabled_button_color[0] is not None:
- button_style.map(style_name, foreground=[('disabled', disabled_button_color[0])])
- if disabled_button_color[1] is not None:
- button_style.map(style_name, background=[('disabled', disabled_button_color[1])])
- self.DisabledButtonColor = (disabled_button_color[0] if disabled_button_color[0] is not None else self.DisabledButtonColor[0],
- disabled_button_color[1] if disabled_button_color[1] is not None else self.DisabledButtonColor[1])
-
- if visible is not None:
- self._visible = visible
-
- def get_text(self):
- """
- Returns the current text shown on a button
-
- :return: The text currently displayed on the button
- :rtype: (str)
- """
- return self.ButtonText
-
- def click(self):
- """
- Generates a click of the button as if the user clicked the button
- Calls the tkinter invoke method for the button
- """
- try:
- self.TKButton.invoke()
- except:
- print('Exception clicking button')
-
- Click = click
- GetText = get_text
- Update = update
-
-
-# ------------------------- Button lazy functions ------------------------- #
-B = Button
-Btn = Button
-
-
-# ---------------------------------------------------------------------- #
-# ButtonMenu Class #
-# ---------------------------------------------------------------------- #
-class ButtonMenu(Element):
- """
- The Button Menu Element. Creates a button that when clicked will show a menu similar to right click menu
- """
-
- def __init__(self, button_text, menu_def, tooltip=None, disabled=False, image_source=None,
- image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, image_zoom=None, border_width=None,
- size=(None, None), s=(None, None), auto_size_button=None, button_color=None, text_color=None, background_color=None, disabled_text_color=None,
- font=None, item_font=None, pad=None, p=None, expand_x=False, expand_y=False, key=None, k=None, tearoff=False, visible=True,
- metadata=None):
- """
- :param button_text: Text to be displayed on the button
- :type button_text: (str)
- :param menu_def: A list of lists of Menu items to show when this element is clicked. See docs for format as they are the same for all menu types
- :type menu_def: List[List[str]]
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param disabled: If True button will be created disabled
- :type disabled: (bool)
- :param image_source: Image to place on button. Use INSTEAD of the image_filename and image_data. Unifies these into 1 easier to use parm
- :type image_source: (str | bytes)
- :param image_filename: image filename if there is a button image. GIFs and PNGs only.
- :type image_filename: (str)
- :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data
- :type image_data: bytes | str
- :param image_size: Size of the image in pixels (width, height)
- :type image_size: (int, int)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
- :type image_zoom: (int)
- :param border_width: width of border around button in pixels
- :type border_width: (int)
- :param size: (w, h) w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1
- :type size: (int, int) | (None, None) | int
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: if True the button size is sized to fit the text
- :type auto_size_button: (bool)
- :param button_color: of button. Easy to remember which is which if you say "ON" between colors. "red" on "green"
- :type button_color: (str, str) | str
- :param background_color: color of the background
- :type background_color: (str)
- :param text_color: element's text color. Can be in #RRGGBB format or a color name "black"
- :type text_color: (str)
- :param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black"
- :type disabled_text_color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param item_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike, for the menu items
- :type item_font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tearoff: Determines if menus should allow them to be torn off
- :type tearoff: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.MenuDefinition = copy.deepcopy(menu_def)
-
- self.AutoSizeButton = auto_size_button
- self.ButtonText = button_text
- self.ButtonColor = button_color_to_tuple(button_color)
- # self.TextColor = self.ButtonColor[0]
- # self.BackgroundColor = self.ButtonColor[1]
- self.BackgroundColor = background_color if background_color is not None else theme_input_background_color()
- self.TextColor = text_color if text_color is not None else theme_input_text_color()
- self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT
- self.ItemFont = item_font
- self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
- if image_source is not None:
- if isinstance(image_source, str):
- image_filename = image_source
- elif isinstance(image_source, bytes):
- image_data = image_source
- else:
- warnings.warn('ButtonMenu element - image_source is not a valid type: {}'.format(type(image_source)), UserWarning)
-
- self.ImageFilename = image_filename
- self.ImageData = image_data
- self.ImageSize = image_size
- self.ImageSubsample = image_subsample
- self.zoom = int(image_zoom) if image_zoom is not None else None
- self.Disabled = disabled
- self.IsButtonMenu = True
- self.MenuItemChosen = None
- self.Widget = self.TKButtonMenu = None # type: tk.Menubutton
- self.TKMenu = None # type: tk.Menu
- self.part_of_custom_menubar = False
- self.custom_menubar_key = None
- # self.temp_size = size if size != (NONE, NONE) else
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_BUTTONMENU, size=sz, font=font, pad=pad, key=key, tooltip=tooltip,
- text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, metadata=metadata)
- self.Tearoff = tearoff
-
- def _MenuItemChosenCallback(self, item_chosen): # ButtonMenu Menu Item Chosen Callback
- """
- Not a user callable function. Called by tkinter when an item is chosen from the menu.
-
- :param item_chosen: The menu item chosen.
- :type item_chosen: (str)
- """
- # print('IN MENU ITEM CALLBACK', item_chosen)
- self.MenuItemChosen = item_chosen
- self.ParentForm.LastButtonClicked = self.Key
- self.ParentForm.FormRemainedOpen = True
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
- _exit_mainloop(self.ParentForm)
-
- def update(self, menu_definition=None, visible=None, image_source=None, image_size=(None, None), image_subsample=None, image_zoom=None, button_text=None, button_color=None):
- """
- Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param menu_definition: (New menu definition (in menu definition format)
- :type menu_definition: List[List]
- :param visible: control visibility of element
- :type visible: (bool)
- :param image_source: new image if image is to be changed. Can be a filename or a base64 encoded byte-string
- :type image_source: (str | bytes)
- :param image_size: Size of the image in pixels (width, height)
- :type image_size: (int, int)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
- :type image_zoom: (int)
- :param button_text: Text to be shown on the button
- :type button_text: (str)
- :param button_color: Normally a tuple, but can be a simplified-button-color-string "foreground on background". Can be a single color if want to set only the background.
- :type button_color: (str, str) | str
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in ButtonMenu.update - The window was closed')
- return
-
- if menu_definition is not None:
- self.MenuDefinition = copy.deepcopy(menu_definition)
- top_menu = self.TKMenu = tk.Menu(self.TKButtonMenu, tearoff=self.Tearoff, font=self.ItemFont, tearoffcommand=self._tearoff_menu_callback)
-
- if self.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(bg=self.BackgroundColor)
- if self.TextColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(fg=self.TextColor)
- if self.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(disabledforeground=self.DisabledTextColor)
- if self.ItemFont is not None:
- top_menu.config(font=self.ItemFont)
- AddMenuItem(self.TKMenu, self.MenuDefinition[1], self)
- self.TKButtonMenu.configure(menu=self.TKMenu)
- if image_source is not None:
- filename = data = None
- if image_source is not None:
- if isinstance(image_source, bytes):
- data = image_source
- elif isinstance(image_source, str):
- filename = image_source
- else:
- warnings.warn('ButtonMenu element - image_source is not a valid type: {}'.format(type(image_source)), UserWarning)
- image = None
- if filename is not None:
- image = tk.PhotoImage(file=filename)
- if image_subsample is not None:
- image = image.subsample(image_subsample)
- if image_zoom is not None:
- image = image.zoom(int(image_zoom))
- elif data is not None:
- # if type(data) is bytes:
- try:
- image = tk.PhotoImage(data=data)
- if image_subsample is not None:
- image = image.subsample(image_subsample)
- if image_zoom is not None:
- image = image.zoom(int(image_zoom))
- except Exception as e:
- image = data
-
- if image is not None:
- if type(image) is not bytes:
- width, height = image_size[0] if image_size[0] is not None else image.width(), image_size[1] if image_size[1] is not None else image.height()
- else:
- width, height = image_size
-
- self.TKButtonMenu.config(image=image, compound=tk.CENTER, width=width, height=height)
- self.TKButtonMenu.image = image
- if button_text is not None:
- self.TKButtonMenu.configure(text=button_text)
- self.ButtonText = button_text
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
- if visible is not None:
- self._visible = visible
- if button_color != (None, None) and button_color != COLOR_SYSTEM_DEFAULT:
- bc = button_color_to_tuple(button_color, self.ButtonColor)
- if bc[0] not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKButtonMenu.config(foreground=bc[0], activeforeground=bc[0])
- if bc[1] not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKButtonMenu.config(background=bc[1], activebackground=bc[1])
- self.ButtonColor = bc
-
- def click(self):
- """
- Generates a click of the button as if the user clicked the button
- Calls the tkinter invoke method for the button
- """
- try:
- self.TKMenu.invoke(1)
- except:
- print('Exception clicking button')
-
- Update = update
- Click = click
-
-
-BMenu = ButtonMenu
-BM = ButtonMenu
-
-
-# ---------------------------------------------------------------------- #
-# ProgreessBar #
-# ---------------------------------------------------------------------- #
-class ProgressBar(Element):
- """
- Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made
- """
-
- def __init__(self, max_value, orientation=None, size=(None, None), s=(None, None), size_px=(None, None), auto_size_text=None, bar_color=None, style=None, border_width=None,
- relief=None, key=None, k=None, pad=None, p=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param max_value: max value of progressbar
- :type max_value: (int)
- :param orientation: 'horizontal' or 'vertical'
- :type orientation: (str)
- :param size: Size of the bar. If horizontal (chars long, pixels wide), vert (chars high, pixels wide). Vert height measured using horizontal chars units.
- :type size: (int, int) | (int, None)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None)
- :param size_px: Size in pixels (length, width). Will be used in place of size parm if specified
- :type size_px: (int, int) | (None, None)
- :param auto_size_text: Not sure why this is here
- :type auto_size_text: (bool)
- :param bar_color: The 2 colors that make up a progress bar. Either a tuple of 2 strings or a string. Tuple - (bar, background). A string with 1 color changes the background of the bar only. A string with 2 colors separated by "on" like "red on blue" specifies a red bar on a blue background.
- :type bar_color: (str, str) or str
- :param style: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'
- :type style: (str)
- :param border_width: The amount of pixels that go around the outside of the bar
- :type border_width: (int)
- :param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = DEFAULT_PROGRESS_BAR_RELIEF)
- :type relief: (str)
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.MaxValue = max_value
- self.TKProgressBar = None # type: TKProgressBar
- self.Cancelled = False
- self.NotRunning = True
- self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION
- self.RightClickMenu = right_click_menu
- # Progress Bar colors can be a tuple (text, background) or a string with format "bar on background" - examples "red on white" or ("red", "white")
- if bar_color is None:
- bar_color = DEFAULT_PROGRESS_BAR_COLOR
- else:
- bar_color = _simplified_dual_color_to_tuple(bar_color, default=DEFAULT_PROGRESS_BAR_COLOR)
-
- self.BarColor = bar_color # should be a tuple at this point
- self.BarStyle = style if style else DEFAULT_TTK_THEME
- self.BorderWidth = border_width if border_width else DEFAULT_PROGRESS_BAR_BORDER_WIDTH
- self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF
- self.BarExpired = False
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.size_px = size_px
-
- super().__init__(ELEM_TYPE_PROGRESS_BAR, size=sz, auto_size_text=auto_size_text, key=key, pad=pad,
- visible=visible, metadata=metadata)
-
- # returns False if update failed
- def update_bar(self, current_count, max=None):
- """
- DEPRECATED BUT STILL USABLE - has been combined with the normal ProgressBar.update method.
- Change what the bar shows by changing the current count and optionally the max count
-
- :param current_count: sets the current value
- :type current_count: (int)
- :param max: changes the max value
- :type max: (int)
- """
-
- if self.ParentForm.TKrootDestroyed:
- return False
- self.TKProgressBar.Update(current_count, max=max)
- try:
- self.ParentForm.TKroot.update()
- except:
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- return False
- return True
-
- def update(self, current_count=None, max=None, bar_color=None, visible=None):
- """
- Changes some of the settings for the ProgressBar Element. Must call `Window.Read` or `Window.Finalize` prior
- Now has the ability to modify the count so that the update_bar method is not longer needed separately
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param current_count: sets the current value
- :type current_count: (int)
- :param max: changes the max value
- :type max: (int)
- :param bar_color: The 2 colors that make up a progress bar. Easy to remember which is which if you say "ON" between colors. "red" on "green".
- :type bar_color: (str, str) or str
- :param visible: control visibility of element
- :type visible: (bool)
- :return: Returns True if update was OK. False means something wrong with window or it was closed
- :rtype: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return False
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in ProgressBar.update - The window was closed')
- return
-
- if self.ParentForm.TKrootDestroyed:
- return False
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
- if bar_color is not None:
- bar_color = _simplified_dual_color_to_tuple(bar_color, default=DEFAULT_PROGRESS_BAR_COLOR)
- self.BarColor = bar_color
- style = ttk.Style()
- style.configure(self.ttk_style_name, background=bar_color[0], troughcolor=bar_color[1])
- if current_count is not None:
- self.TKProgressBar.Update(current_count, max=max)
-
- try:
- self.ParentForm.TKroot.update()
- except:
- # Window._DecrementOpenCount()
- # _my_windows.Decrement()
- return False
- return True
-
- Update = update
- UpdateBar = update_bar
-
-
-PBar = ProgressBar
-Prog = ProgressBar
-Progress = ProgressBar
-
-
-# ---------------------------------------------------------------------- #
-# Image #
-# ---------------------------------------------------------------------- #
-class Image(Element):
- """
- Image Element - show an image in the window. Should be a GIF or a PNG only
- """
-
- def __init__(self, source=None, filename=None, data=None, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, key=None, k=None, tooltip=None,
- subsample=None, zoom=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, enable_events=False, metadata=None):
- """
- :param source: A filename or a base64 bytes. Will automatically detect the type and fill in filename or data for you.
- :type source: str | bytes | None
- :param filename: image filename if there is a button image. GIFs and PNGs only.
- :type filename: str | None
- :param data: Raw or Base64 representation of the image to put on button. Choose either filename or data
- :type data: bytes | str | None
- :param background_color: color of background
- :type background_color:
- :param size: (width, height) size of image in pixels
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type subsample: (int)
- :param zoom: amount to increase the size of the image.
- :type zoom: (int)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param enable_events: Turns on the element specific events. For an Image element, the event is "image clicked"
- :type enable_events: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- if source is not None:
- if isinstance(source, bytes):
- data = source
- elif isinstance(source, str):
- filename = source
- else:
- warnings.warn('Image element - source is not a valid type: {}'.format(type(source)), UserWarning)
-
- self.Filename = filename
- self.Data = data
- self.Widget = self.tktext_label = None # type: tk.Label
- self.BackgroundColor = background_color
- if data is None and filename is None:
- self.Filename = ''
- self.EnableEvents = enable_events
- self.RightClickMenu = right_click_menu
- self.AnimatedFrames = None
- self.CurrentFrameNumber = 0
- self.TotalAnimatedFrames = 0
- self.LastFrameTime = 0
- self.ImageSubsample = subsample
- self.zoom = int(zoom) if zoom is not None else None
- self.frame_num = 0
- self.Source = filename if filename is not None else data
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_IMAGE, size=sz, background_color=background_color, pad=pad, key=key,
- tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def update(self, source=None, filename=None, data=None, size=(None, None), subsample=None, zoom=None, visible=None):
- """
- Changes some of the settings for the Image Element. Must call `Window.Read` or `Window.Finalize` prior.
- To clear an image that's been displayed, call with NONE of the options set. A blank update call will
- delete the previously shown image.
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param source: A filename or a base64 bytes. Will automatically detect the type and fill in filename or data for you.
- :type source: str | bytes | None
- :param filename: filename to the new image to display.
- :type filename: (str)
- :param data: Base64 encoded string OR a tk.PhotoImage object
- :type data: str | tkPhotoImage
- :param size: (width, height) size of image in pixels
- :type size: Tuple[int,int]
- :param subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type subsample: (int)
- :param zoom: amount to increase the size of the image
- :type zoom: (int)
- :param visible: control visibility of element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Image.update - The window was closed')
- return
-
- if source is not None:
- if isinstance(source, bytes):
- data = source
- elif isinstance(source, str):
- filename = source
- else:
- warnings.warn('Image element - source is not a valid type: {}'.format(type(source)), UserWarning)
-
- image = None
- if filename is not None:
- try:
- image = tk.PhotoImage(file=filename)
- if subsample is not None:
- image = image.subsample(subsample)
- if zoom is not None:
- image = image.zoom(int(zoom))
- except Exception as e:
- _error_popup_with_traceback('Exception updating Image element', e)
-
- elif data is not None:
- # if type(data) is bytes:
- try:
- image = tk.PhotoImage(data=data)
- if subsample is not None:
- image = image.subsample(subsample)
- if zoom is not None:
- image = image.zoom(int(zoom))
- except Exception as e:
- image = data
- # return # an error likely means the window has closed so exit
-
- if image is not None:
- self.tktext_label.configure(image='') # clear previous image
- if self.tktext_label.image is not None:
- del self.tktext_label.image
- if type(image) is not bytes:
- width, height = size[0] if size[0] is not None else image.width(), size[1] if size[1] is not None else image.height()
- else:
- width, height = size
- try: # sometimes crashes if user closed with X
- self.tktext_label.configure(image=image, width=width, height=height)
- except Exception as e:
- _error_popup_with_traceback('Exception updating Image element', e)
- self.tktext_label.image = image
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- # if everything is set to None, then delete the image
- if filename is None and image is None and visible is None and size == (None, None):
- # Using a try because the image may have been previously deleted and don't want an error if that's happened
- try:
- self.tktext_label.configure(image='', width=1, height=1, bd=0)
- self.tktext_label.image = None
- except:
- pass
-
- if visible is not None:
- self._visible = visible
-
- def update_animation(self, source, time_between_frames=0):
- """
- Show an Animated GIF. Call the function as often as you like. The function will determine when to show the next frame and will automatically advance to the next frame at the right time.
- NOTE - does NOT perform a sleep call to delay
- :param source: Filename or Base64 encoded string containing Animated GIF
- :type source: str | bytes | None
- :param time_between_frames: Number of milliseconds to wait between showing frames
- :type time_between_frames: (int)
- :return: True if worked OK, False if out of frames, None is window was closed
- :rtype: True | False | None
- """
-
- if self.Source != source:
- self.AnimatedFrames = None
- self.Source = source
-
- done = False
-
- if self.AnimatedFrames is None:
- self.TotalAnimatedFrames = 0
- self.AnimatedFrames = []
- # Load up to 1000 frames of animation. stops when a bad frame is returns by tkinter
- for i in range(1000):
- if type(source) is not bytes:
- try:
- self.AnimatedFrames.append(tk.PhotoImage(file=source, format='gif -index %i' % (i)))
- except Exception as e:
- break
- else:
- try:
- self.AnimatedFrames.append(tk.PhotoImage(data=source, format='gif -index %i' % (i)))
- except Exception as e:
- break
- self.TotalAnimatedFrames = len(self.AnimatedFrames)
- self.LastFrameTime = time.time()
- self.CurrentFrameNumber = -1 # start at -1 because it is incremented before every frame is shown
- # show the frame
-
- now = time.time()
-
- if time_between_frames:
- if self.CurrentFrameNumber+1 == self.TotalAnimatedFrames:
- done = True
- if (now - self.LastFrameTime) * 1000 > time_between_frames:
- self.LastFrameTime = now
- self.CurrentFrameNumber = (self.CurrentFrameNumber + 1) % self.TotalAnimatedFrames
- else: # don't reshow the frame again if not time for new frame
- return True
- else:
- self.CurrentFrameNumber = (self.CurrentFrameNumber + 1) % self.TotalAnimatedFrames
- image = self.AnimatedFrames[self.CurrentFrameNumber]
- try: # needed in case the window was closed with an "X"
- self.tktext_label.configure(image=image, width=image.width(), heigh=image.height())
- except Exception as e:
- print('Exception in update_animation', e)
- done = None
- return not done
-
-
- def update_animation_no_buffering(self, source, time_between_frames=0):
- """
- Show an Animated GIF. Call the function as often as you like. The function will determine when to show the next frame and will automatically advance to the next frame at the right time.
- NOTE - does NOT perform a sleep call to delay
-
- :param source: Filename or Base64 encoded string containing Animated GIF
- :type source: str | bytes
- :param time_between_frames: Number of milliseconds to wait between showing frames
- :type time_between_frames: (int)
- :return: True if worked OK, False if out of frames, None is window was closed
- :rtype: True | False | None
- """
-
- if self.Source != source:
- self.AnimatedFrames = None
- self.Source = source
- self.frame_num = 0
-
- now = time.time()
-
- if time_between_frames:
- if (now - self.LastFrameTime) * 1000 > time_between_frames:
- self.LastFrameTime = now
- else: # don't reshow the frame again if not time for new frame
- return True
-
- # read a frame
- done = False
- while True:
- if type(source) is not bytes:
- try:
- self.image = tk.PhotoImage(file=source, format='gif -index %i' % (self.frame_num))
- self.frame_num += 1
- except Exception as e:
- self.frame_num = 0
- done = True
- else:
- try:
- self.image = tk.PhotoImage(data=source, format='gif -index %i' % (self.frame_num))
- self.frame_num += 1
- except:
- self.frame_num = 0
- done = True
-
- if self.frame_num:
- break
-
- try: # needed in case the window was closed with an "X"
- self.tktext_label.configure(image=self.image, width=self.image.width(), heigh=self.image.height())
- except:
- done = None
- return not done
-
- Update = update
- UpdateAnimation = update_animation
-
-
-Im = Image
-
-
-# ---------------------------------------------------------------------- #
-# Canvas #
-# ---------------------------------------------------------------------- #
-class Canvas(Element):
-
- def __init__(self, canvas=None, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, key=None, k=None, tooltip=None,
- right_click_menu=None, expand_x=False, expand_y=False, visible=True, border_width=0, metadata=None):
- """
- :param canvas: Your own tk.Canvas if you already created it. Leave blank to create a Canvas
- :type canvas: (tk.Canvas)
- :param background_color: color of background
- :type background_color: (str)
- :param size: (width in char, height in rows) size in pixels to make canvas
- :type size: (int,int) | (None, None)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param border_width: width of border around element in pixels. Not normally used with Canvas element
- :type border_width: (int)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self._TKCanvas = self.Widget = canvas
- self.RightClickMenu = right_click_menu
- self.BorderWidth = border_width
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=sz, pad=pad, key=key,
- tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def update(self, background_color=None, visible=None):
- """
-
- :param background_color: color of background
- :type background_color: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Canvas.update - The window was closed')
- return
-
- if background_color not in (None, COLOR_SYSTEM_DEFAULT):
- self._TKCanvas.configure(background=background_color)
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
- if visible is not None:
- self._visible = visible
-
- @property
- def tk_canvas(self):
- """
- Returns the underlying tkiner Canvas widget
-
- :return: The tkinter canvas widget
- :rtype: (tk.Canvas)
- """
- if self._TKCanvas is None:
- print('*** Did you forget to call Finalize()? Your code should look something like: ***')
- print('*** window = sg.Window("My Form", layout, finalize=True) ***')
- return self._TKCanvas
-
- TKCanvas = tk_canvas
-
-
-# ---------------------------------------------------------------------- #
-# Graph #
-# ---------------------------------------------------------------------- #
-class Graph(Element):
- """
- Creates an area for you to draw on. The MAGICAL property this Element has is that you interact
- with the element using your own coordinate system. This is an important point!! YOU define where the location
- is for (0,0). Want (0,0) to be in the middle of the graph like a math 4-quadrant graph? No problem! Set your
- lower left corner to be (-100,-100) and your upper right to be (100,100) and you've got yourself a graph with
- (0,0) at the center.
- One of THE coolest of the Elements.
- You can also use float values. To do so, be sure and set the float_values parameter.
- Mouse click and drag events are possible and return the (x,y) coordinates of the mouse
- Drawing primitives return an "id" that is referenced when you want to operation on that item (e.g. to erase it)
- """
-
- def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, p=None,
- change_submits=False, drag_submits=False, enable_events=False, motion_events=False, key=None, k=None, tooltip=None,
- right_click_menu=None, expand_x=False, expand_y=False, visible=True, float_values=False, border_width=0, metadata=None):
- """
- :param canvas_size: size of the canvas area in pixels
- :type canvas_size: (int, int)
- :param graph_bottom_left: (x,y) The bottoms left corner of your coordinate system
- :type graph_bottom_left: (int, int)
- :param graph_top_right: (x,y) The top right corner of your coordinate system
- :type graph_top_right: (int, int)
- :param background_color: background color of the drawing area
- :type background_color: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
- :type change_submits: (bool)
- :param drag_submits: if True and Events are enabled for the Graph, will report Events any time the mouse moves while button down. When the mouse button is released, you'll get an event = graph key + '+UP' (if key is a string.. if not a string, it'll be made into a tuple)
- :type drag_submits: (bool)
- :param enable_events: If True then clicks on the Graph are immediately reported as an event. Use this instead of change_submits
- :type enable_events: (bool)
- :param motion_events: If True then if no button is down and the mouse is moved, an event is generated with key = graph key + '+MOVE' (if key is a string, it not a string then a tuple is returned)
- :type motion_events: (bool)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element (Default = True)
- :type visible: (bool)
- :param float_values: If True x,y coordinates are returned as floats, not ints
- :type float_values: (bool)
- :param border_width: width of border around element in pixels. Not normally used for Graph Elements
- :type border_width: (int)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.CanvasSize = canvas_size
- self.BottomLeft = graph_bottom_left
- self.TopRight = graph_top_right
- # self._TKCanvas = None # type: tk.Canvas
- self._TKCanvas2 = self.Widget = None # type: tk.Canvas
- self.ChangeSubmits = change_submits or enable_events
- self.DragSubmits = drag_submits
- self.ClickPosition = (None, None)
- self.MouseButtonDown = False
- self.Images = {}
- self.RightClickMenu = right_click_menu
- self.FloatValues = float_values
- self.BorderWidth = border_width
- key = key if key is not None else k
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.motion_events = motion_events
-
- super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key,
- tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def _convert_xy_to_canvas_xy(self, x_in, y_in):
- """
- Not user callable. Used to convert user's coordinates into the ones used by tkinter
- :param x_in: The x coordinate to convert
- :type x_in: int | float
- :param y_in: The y coordinate to convert
- :type y_in: int | float
- :return: (int, int) The converted canvas coordinates
- :rtype: (int, int)
- """
- if None in (x_in, y_in):
- return None, None
- try:
- scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
- scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
- except:
- scale_x = scale_y = 0
-
- new_x = 0 + scale_x * (x_in - self.BottomLeft[0])
- new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1])
- return new_x, new_y
-
- def _convert_canvas_xy_to_xy(self, x_in, y_in):
- """
- Not user callable. Used to convert tkinter Canvas coords into user's coordinates
-
- :param x_in: The x coordinate in canvas coordinates
- :type x_in: (int)
- :param y_in: (int) The y coordinate in canvas coordinates
- :type y_in:
- :return: The converted USER coordinates
- :rtype: (int, int) | Tuple[float, float]
- """
- if None in (x_in, y_in):
- return None, None
- scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
- scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
-
- new_x = x_in / scale_x + self.BottomLeft[0]
- new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1]
- if self.FloatValues:
- return new_x, new_y
- else:
- return floor(new_x), floor(new_y)
-
- def draw_line(self, point_from, point_to, color='black', width=1, arrow=None, arrow_shape=None):
- """
- Draws a line from one point to another point using USER'S coordinates. Can set the color and width of line
- :param point_from: Starting point for line
- :type point_from: (int, int) | Tuple[float, float]
- :param point_to: Ending point for line
- :type point_to: (int, int) | Tuple[float, float]
- :param color: Color of the line
- :type color: (str)
- :param width: width of line in pixels
- :type width: (int)
- :param arrow: Determines if an arrowhead will be added to the line. Literal string "first", "last", "both"
- :type arrow: (str)
- :param arrow_shape: Defines the shape of the arrowhead using a tuple with (length, width, thickness)
- :type arrow_shape: Tuple[float, float, float]
- :return: id returned from tktiner or None if user closed the window. id is used when you
- :rtype: int | None
- """
- if point_from == (None, None):
- return
- converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1])
- converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case window was closed with an X
- id = self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color, arrow=arrow, arrowshape=arrow_shape)
- except Exception as e:
- # print(e)
- id = None
- return id
-
-
- def draw_lines(self, points, color='black', width=1):
- """
- Draw a series of lines given list of points
-
- :param points: list of points that define the polygon
- :type points: List[(int, int) | Tuple[float, float]]
- :param color: Color of the line
- :type color: (str)
- :param width: width of line in pixels
- :type width: (int)
- :return: id returned from tktiner or None if user closed the window. id is used when you
- :rtype: int | None
- """
- converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points]
-
- try: # in case window was closed with an X
- id = self._TKCanvas2.create_line(*converted_points, width=width, fill=color)
- except:
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- id = None
- return id
-
- def draw_point(self, point, size=2, color='black'):
- """
- Draws a "dot" at the point you specify using the USER'S coordinate system
- :param point: Center location using USER'S coordinate system
- :type point: (int, int) | Tuple[float, float]
- :param size: Radius? (Or is it the diameter?) in user's coordinate values.
- :type size: int | float
- :param color: color of the point to draw
- :type color: (str)
- :return: id returned from tkinter that you'll need if you want to manipulate the point
- :rtype: int | None
- """
- if point == (None, None):
- return
- converted_point = self._convert_xy_to_canvas_xy(point[0], point[1])
- size_converted = self._convert_xy_to_canvas_xy(point[0] + size, point[1])
- size = size_converted[0] - converted_point[0]
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # needed in case window was closed with an X
- point1 = converted_point[0] - size // 2, converted_point[1] - size // 2
- point2 = converted_point[0] + size // 2, converted_point[1] + size // 2
- id = self._TKCanvas2.create_oval(point1[0], point1[1],
- point2[0], point2[1],
- width=0,
- fill=color,
- outline=color)
- except:
- id = None
- return id
-
- def draw_circle(self, center_location, radius, fill_color=None, line_color='black', line_width=1):
- """
- Draws a circle, cenetered at the location provided. Can set the fill and outline colors
- :param center_location: Center location using USER'S coordinate system
- :type center_location: (int, int) | Tuple[float, float]
- :param radius: Radius in user's coordinate values.
- :type radius: int | float
- :param fill_color: color of the point to draw
- :type fill_color: (str)
- :param line_color: color of the outer line that goes around the circle (sorry, can't set thickness)
- :type line_color: (str)
- :param line_width: width of the line around the circle, the outline, in pixels
- :type line_width: (int)
- :return: id returned from tkinter that you'll need if you want to manipulate the circle
- :rtype: int | None
- """
- if center_location == (None, None):
- return
- converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1])
- radius_converted = self._convert_xy_to_canvas_xy(center_location[0] + radius, center_location[1])
- radius = radius_converted[0] - converted_point[0]
- # radius = radius_converted[1]-5
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- # print('Oval parms', int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius),
- # int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius))
- try: # needed in case the window was closed with an X
- id = self._TKCanvas2.create_oval(int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius),
- int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius), fill=fill_color,
- outline=line_color, width=line_width)
- except:
- id = None
- return id
-
- def draw_oval(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=1):
- """
- Draws an oval based on coordinates in user coordinate system. Provide the location of a "bounding rectangle"
- :param top_left: the top left point of bounding rectangle
- :type top_left: (int, int) | Tuple[float, float]
- :param bottom_right: the bottom right point of bounding rectangle
- :type bottom_right: (int, int) | Tuple[float, float]
- :param fill_color: color of the interrior
- :type fill_color: (str)
- :param line_color: color of outline of oval
- :type line_color: (str)
- :param line_width: width of the line around the oval, the outline, in pixels
- :type line_width: (int)
- :return: id returned from tkinter that you'll need if you want to manipulate the oval
- :rtype: int | None
- """
- converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
- converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case windows close with X
- id = self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
- converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width)
- except:
- id = None
-
- return id
-
- def draw_arc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black', line_width=1, fill_color=None):
- """
- Draws different types of arcs. Uses a "bounding box" to define location
- :param top_left: the top left point of bounding rectangle
- :type top_left: (int, int) | Tuple[float, float]
- :param bottom_right: the bottom right point of bounding rectangle
- :type bottom_right: (int, int) | Tuple[float, float]
- :param extent: Andle to end drawing. Used in conjunction with start_angle
- :type extent: (float)
- :param start_angle: Angle to begin drawing. Used in conjunction with extent
- :type start_angle: (float)
- :param style: Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last', 'butt', 'projecting', 'round', 'bevel', 'miter'
- :type style: (str)
- :param arc_color: color to draw arc with
- :type arc_color: (str)
- :param fill_color: color to fill the area
- :type fill_color: (str)
- :return: id returned from tkinter that you'll need if you want to manipulate the arc
- :rtype: int | None
- """
- converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
- converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
- tkstyle = tk.PIESLICE if style is None else style
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case closed with X
- id = self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0],
- converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle,
- outline=arc_color, width=line_width, fill=fill_color)
- except Exception as e:
- print('Error encountered drawing arc.', e)
- id = None
- return id
-
- def draw_rectangle(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=None):
- """
- Draw a rectangle given 2 points. Can control the line and fill colors
-
- :param top_left: the top left point of rectangle
- :type top_left: (int, int) | Tuple[float, float]
- :param bottom_right: the bottom right point of rectangle
- :type bottom_right: (int, int) | Tuple[float, float]
- :param fill_color: color of the interior
- :type fill_color: (str)
- :param line_color: color of outline
- :type line_color: (str)
- :param line_width: width of the line in pixels
- :type line_width: (int)
- :return: int | None id returned from tkinter that you'll need if you want to manipulate the rectangle
- :rtype: int | None
- """
-
- converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1])
- converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- if line_width is None:
- line_width = 1
- try: # in case closed with X
- id = self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1],
- converted_bottom_right[0],
- converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width)
- except:
- id = None
- return id
-
- def draw_polygon(self, points, fill_color=None, line_color=None, line_width=None):
- """
- Draw a polygon given list of points
-
- :param points: list of points that define the polygon
- :type points: List[(int, int) | Tuple[float, float]]
- :param fill_color: color of the interior
- :type fill_color: (str)
- :param line_color: color of outline
- :type line_color: (str)
- :param line_width: width of the line in pixels
- :type line_width: (int)
- :return: id returned from tkinter that you'll need if you want to manipulate the rectangle
- :rtype: int | None
- """
-
- converted_points = [self._convert_xy_to_canvas_xy(point[0], point[1]) for point in points]
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case closed with X
- id = self._TKCanvas2.create_polygon(converted_points, fill=fill_color, outline=line_color, width=line_width)
- except:
- id = None
- return id
-
- def draw_text(self, text, location, color='black', font=None, angle=0, text_location=TEXT_LOCATION_CENTER):
- """
- Draw some text on your graph. This is how you label graph number lines for example
-
- :param text: text to display
- :type text: (Any)
- :param location: location to place first letter
- :type location: (int, int) | Tuple[float, float]
- :param color: text color
- :type color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param angle: Angle 0 to 360 to draw the text. Zero represents horizontal text
- :type angle: (float)
- :param text_location: "anchor" location for the text. Values start with TEXT_LOCATION_
- :type text_location: (str)
- :return: id returned from tkinter that you'll need if you want to manipulate the text
- :rtype: int | None
- """
- text = str(text)
- if location == (None, None):
- return
- converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case closed with X
- id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color, angle=angle, anchor=text_location)
- except:
- id = None
- return id
-
- def draw_image(self, filename=None, data=None, location=(None, None)):
- """
- Places an image onto your canvas. It's a really important method for this element as it enables so much
-
- :param filename: if image is in a file, path and filename for the image. (GIF and PNG only!)
- :type filename: (str)
- :param data: if image is in Base64 format or raw? format then use instead of filename
- :type data: str | bytes
- :param location: the (x,y) location to place image's top left corner
- :type location: (int, int) | Tuple[float, float]
- :return: id returned from tkinter that you'll need if you want to manipulate the image
- :rtype: int | None
- """
- if location == (None, None):
- return
- if filename is not None:
- image = tk.PhotoImage(file=filename)
- elif data is not None:
- # if type(data) is bytes:
- try:
- image = tk.PhotoImage(data=data)
- except:
- return None # an error likely means the window has closed so exit
- converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- try: # in case closed with X
- id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW)
- self.Images[id] = image
- except:
- id = None
- return id
-
- def erase(self):
- """
- Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText)
- """
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- self.Images = {}
- try: # in case window was closed with X
- self._TKCanvas2.delete('all')
- except:
- pass
-
- def delete_figure(self, id):
- """
- Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive
-
- :param id: the id returned to you when calling one of the drawing methods
- :type id: (int)
- """
- try:
- self._TKCanvas2.delete(id)
- except:
- print('DeleteFigure - bad ID {}'.format(id))
- try:
- del self.Images[id] # in case was an image. If wasn't an image, then will get exception
- except:
- pass
-
- def update(self, background_color=None, visible=None):
- """
- Changes some of the settings for the Graph Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param background_color: color of background
- :type background_color: ???
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Graph.update - The window was closed')
- return
-
- if background_color is not None and background_color != COLOR_SYSTEM_DEFAULT:
- self._TKCanvas2.configure(background=background_color)
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
-
- def move(self, x_direction, y_direction):
- """
- Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system
-
- :param x_direction: how far to move in the "X" direction in your coordinates
- :type x_direction: int | float
- :param y_direction: how far to move in the "Y" direction in your coordinates
- :type y_direction: int | float
- """
- zero_converted = self._convert_xy_to_canvas_xy(0, 0)
- shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
- shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
- if self._TKCanvas2 is None:
- print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
- print('Call Window.Finalize() prior to this operation')
- return None
- self._TKCanvas2.move('all', shift_amount[0], shift_amount[1])
-
- def move_figure(self, figure, x_direction, y_direction):
- """
- Moves a previously drawn figure using a "delta" from current position
-
- :param figure: Previously obtained figure-id. These are returned from all Draw methods
- :type figure: (id)
- :param x_direction: delta to apply to position in the X direction
- :type x_direction: int | float
- :param y_direction: delta to apply to position in the Y direction
- :type y_direction: int | float
- """
- zero_converted = self._convert_xy_to_canvas_xy(0, 0)
- shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction)
- shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
- if figure is None:
- print('* move_figure warning - your figure is None *')
- return None
- self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1])
-
- def relocate_figure(self, figure, x, y):
- """
- Move a previously made figure to an arbitrary (x,y) location. This differs from the Move methods because it
- uses absolute coordinates versus relative for Move
-
- :param figure: Previously obtained figure-id. These are returned from all Draw methods
- :type figure: (id)
- :param x: location on X axis (in user coords) to move the upper left corner of the figure
- :type x: int | float
- :param y: location on Y axis (in user coords) to move the upper left corner of the figure
- :type y: int | float
- """
-
- zero_converted = self._convert_xy_to_canvas_xy(0, 0)
- shift_converted = self._convert_xy_to_canvas_xy(x, y)
- shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1])
- if figure is None:
- print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***')
- print('Call Window.Finalize() prior to all graph operations')
- return None
- xy = self._TKCanvas2.coords(figure)
- self._TKCanvas2.move(figure, shift_converted[0] - xy[0], shift_converted[1] - xy[1])
-
- def send_figure_to_back(self, figure):
- """
- Changes Z-order of figures on the Graph. Sends the indicated figure to the back of all other drawn figures
-
- :param figure: value returned by tkinter when creating the figure / drawing
- :type figure: (int)
- """
- self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure
-
- def bring_figure_to_front(self, figure):
- """
- Changes Z-order of figures on the Graph. Brings the indicated figure to the front of all other drawn figures
-
- :param figure: value returned by tkinter when creating the figure / drawing
- :type figure: (int)
- """
- self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures
-
- def get_figures_at_location(self, location):
- """
- Returns a list of figures located at a particular x,y location within the Graph
-
- :param location: point to check
- :type location: (int, int) | Tuple[float, float]
- :return: a list of previously drawn "Figures" (returned from the drawing primitives)
- :rtype: List[int]
- """
- x, y = self._convert_xy_to_canvas_xy(location[0], location[1])
- ids = self.TKCanvas.find_overlapping(x, y, x, y)
- return ids
-
- def get_bounding_box(self, figure):
- """
- Given a figure, returns the upper left and lower right bounding box coordinates
-
- :param figure: a previously drawing figure
- :type figure: object
- :return: upper left x, upper left y, lower right x, lower right y
- :rtype: Tuple[int, int, int, int] | Tuple[float, float, float, float]
- """
- box = self.TKCanvas.bbox(figure)
- top_left = self._convert_canvas_xy_to_xy(box[0], box[1])
- bottom_right = self._convert_canvas_xy_to_xy(box[2], box[3])
- return top_left, bottom_right
-
- def change_coordinates(self, graph_bottom_left, graph_top_right):
- """
- Changes the corrdinate system to a new one. The same 2 points in space are used to define the coorinate
- system - the bottom left and the top right values of your graph.
-
- :param graph_bottom_left: The bottoms left corner of your coordinate system
- :type graph_bottom_left: (int, int) (x,y)
- :param graph_top_right: The top right corner of your coordinate system
- :type graph_top_right: (int, int) (x,y)
- """
- self.BottomLeft = graph_bottom_left
- self.TopRight = graph_top_right
-
- @property
- def tk_canvas(self):
- """
- Returns the underlying tkiner Canvas widget
-
- :return: The tkinter canvas widget
- :rtype: (tk.Canvas)
- """
- if self._TKCanvas2 is None:
- print('*** Did you forget to call Finalize()? Your code should look something like: ***')
- print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
- return self._TKCanvas2
-
- # button release callback
- def button_release_call_back(self, event):
- """
- Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
-
- :param event: (event) event info from tkinter. Note not used in this method
- :type event:
- """
- if not self.DragSubmits:
- return # only report mouse up for drag operations
- self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
- self.ParentForm.LastButtonClickedWasRealtime = False
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
- _exit_mainloop(self.ParentForm)
- if isinstance(self.ParentForm.LastButtonClicked, str):
- self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+UP'
- else:
- self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+UP')
- self.MouseButtonDown = False
-
- # button callback
- def button_press_call_back(self, event):
- """
- Not a user callable method. Used to get Graph click events. Called by tkinter when button is released
-
- :param event: (event) event info from tkinter. Contains the x and y coordinates of a click
- :type event:
- """
-
- self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
- self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit() # kick out of loop if read was called
- _exit_mainloop(self.ParentForm)
- self.MouseButtonDown = True
-
- def _update_position_for_returned_values(self, event):
- """
- Updates the variable that's used when the values dictionary is returned from a window read.
-
- Not called by the user. It's called from another method/function that tkinter calledback
-
- :param event: (event) event info from tkinter. Contains the x and y coordinates of a click
- :type event:
- """
- """
- Updates the variable that's used when the values dictionary is returned from a window read.
-
- Not called by the user. It's called from another method/function that tkinter calledback
-
- :param event: (event) event info from tkinter. Contains the x and y coordinates of a click
- :type event:
- """
-
- self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
-
- # button callback
- def motion_call_back(self, event):
- """
- Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved
-
- :param event: (event) event info from tkinter. Contains the x and y coordinates of a mouse
- :type event:
- """
-
- if not self.MouseButtonDown and not self.motion_events:
- return
- self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
- self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit() # kick out of loop if read was called
- if self.motion_events and not self.MouseButtonDown:
- if isinstance(self.ParentForm.LastButtonClicked, str):
- self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+MOVE'
- else:
- self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+MOVE')
- _exit_mainloop(self.ParentForm)
-
- BringFigureToFront = bring_figure_to_front
- ButtonPressCallBack = button_press_call_back
- ButtonReleaseCallBack = button_release_call_back
- DeleteFigure = delete_figure
- DrawArc = draw_arc
- DrawCircle = draw_circle
- DrawImage = draw_image
- DrawLine = draw_line
- DrawOval = draw_oval
- DrawPoint = draw_point
- DrawPolygon = draw_polygon
- DrawLines = draw_lines
- DrawRectangle = draw_rectangle
- DrawText = draw_text
- GetFiguresAtLocation = get_figures_at_location
- GetBoundingBox = get_bounding_box
- Erase = erase
- MotionCallBack = motion_call_back
- Move = move
- MoveFigure = move_figure
- RelocateFigure = relocate_figure
- SendFigureToBack = send_figure_to_back
- TKCanvas = tk_canvas
- Update = update
-
-
-G = Graph
-
-
-# ---------------------------------------------------------------------- #
-# Frame #
-# ---------------------------------------------------------------------- #
-class Frame(Element):
- """
- A Frame Element that contains other Elements. Encloses with a line around elements and a text label.
- """
-
- def __init__(self, title, layout, title_color=None, background_color=None, title_location=None,
- relief=DEFAULT_FRAME_RELIEF, size=(None, None), s=(None, None), font=None, pad=None, p=None, border_width=None, key=None, k=None,
- tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, grab=None, visible=True, element_justification='left', vertical_alignment=None,
- metadata=None):
- """
- :param title: text that is displayed as the Frame's "label" or title
- :type title: (str)
- :param layout: The layout to put inside the Frame
- :type layout: List[List[Elements]]
- :param title_color: color of the title text
- :type title_color: (str)
- :param background_color: background color of the Frame
- :type background_color: (str)
- :param title_location: location to place the text title. Choices include: TITLE_LOCATION_TOP TITLE_LOCATION_BOTTOM TITLE_LOCATION_LEFT TITLE_LOCATION_RIGHT TITLE_LOCATION_TOP_LEFT TITLE_LOCATION_TOP_RIGHT TITLE_LOCATION_BOTTOM_LEFT TITLE_LOCATION_BOTTOM_RIGHT
- :type title_location: (str)
- :param relief: relief style. Values are same as other elements with reliefs. Choices include RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
- :type relief: (str)
- :param size: (width, height) Sets an initial hard-coded size for the Frame. This used to be a problem, but was fixed in 4.53.0 and works better than Columns when using the size paramter
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param font: specifies the font family, size, etc. for the TITLE. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param grab: If True can grab this element and move the window around. Default is False
- :type grab: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param element_justification: All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values
- :type element_justification: (str)
- :param vertical_alignment: Place the Frame at the 'top', 'center', 'bottom' of the row (can also use t,c,r). Defaults to no setting (tkinter decides)
- :type vertical_alignment: (str)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.UseDictionary = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.ParentWindow = None
- self.Rows = []
- # self.ParentForm = None
- self.TKFrame = None
- self.Title = title
- self.Relief = relief
- self.TitleLocation = title_location
- self.BorderWidth = border_width
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self.RightClickMenu = right_click_menu
- self.ContainerElemementNumber = Window._GetAContainerNumber()
- self.ElementJustification = element_justification
- self.VerticalAlignment = vertical_alignment
- self.Widget = None # type: tk.LabelFrame
- self.Grab = grab
- self.Layout(layout)
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=sz,
- font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def add_row(self, *args):
- """
- Not recommended user call. Used to add rows of Elements to the Frame Element.
-
- :param *args: The list of elements for this row
- :type *args: List[Element]
- """
- NumRows = len(self.Rows) # number of existing rows is our row number
- CurrentRowNumber = NumRows # this row's number
- CurrentRow = [] # start with a blank row and build up
- # ------------------------- Add the elements to a row ------------------------- #
- for i, element in enumerate(args): # Loop through list of elements and add them to the row
- if isinstance(element, tuple) or isinstance(element, list):
- self.add_row(*element)
- continue
-
- if type(element) == list:
- PopupError('Error creating Frame layout',
- 'Layout has a LIST instead of an ELEMENT',
- 'This sometimes means you have a badly placed ]',
- 'The offensive list is:',
- element,
- 'This list will be stripped from your layout',
- keep_on_top=True
- )
- continue
- elif callable(element) and not isinstance(element, Element):
- PopupError('Error creating Frame layout',
- 'Layout has a FUNCTION instead of an ELEMENT',
- 'This likely means you are missing () from your layout',
- 'The offensive list is:',
- element,
- 'This item will be stripped from your layout',
- keep_on_top=True)
- continue
- if element.ParentContainer is not None:
- warnings.warn(
- '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
- UserWarning)
- _error_popup_with_traceback('Error creating Frame layout',
- 'The layout specified has already been used',
- 'You MUST start witha "clean", unused layout every time you create a window',
- 'The offensive Element = ',
- element,
- 'and has a key = ', element.Key,
- 'This item will be stripped from your layout',
- 'Hint - try printing your layout and matching the IDs "print(layout)"',
- )
- continue
- element.Position = (CurrentRowNumber, i)
- element.ParentContainer = self
- CurrentRow.append(element)
- if element.Key is not None:
- self.UseDictionary = True
- # ------------------------- Append the row to list of Rows ------------------------- #
- self.Rows.append(CurrentRow)
-
- def layout(self, rows):
- """
- Can use like the Window.Layout method, but it's better to use the layout parameter when creating
-
- :param rows: The rows of Elements
- :type rows: List[List[Element]]
- :return: Used for chaining
- :rtype: (Frame)
- """
-
- for row in rows:
- try:
- iter(row)
- except TypeError:
- PopupError('Error creating Frame layout',
- 'Your row is not an iterable (e.g. a list)',
- 'Instead of a list, the type found was {}'.format(type(row)),
- 'The offensive row = ',
- row,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- self.AddRow(*row)
- return self
-
- def _GetElementAtLocation(self, location):
- """
- Not user callable. Used to find the Element at a row, col position within the layout
-
- :param location: (row, column) position of the element to find in layout
- :type location: (int, int)
- :return: (Element) The element found at the location
- :rtype: (Element)
- """
-
- (row_num, col_num) = location
- row = self.Rows[row_num]
- element = row[col_num]
- return element
-
- def update(self, value=None, visible=None):
- """
- Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: New text value (Title) to show on frame
- :type value: (Any)
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Frame.update - The window was closed')
- return
-
- if visible is False:
- self._pack_forget_save_settings()
- # self.TKFrame.pack_forget()
- elif visible is True:
- self._pack_restore_settings()
- # self.TKFrame.pack(padx=self.pad_used[0], pady=self.pad_used[1])
- if value is not None:
- self.TKFrame.config(text=str(value))
- if visible is not None:
- self._visible = visible
-
- AddRow = add_row
- Layout = layout
- Update = update
-
-
-Fr = Frame
-
-
-# ---------------------------------------------------------------------- #
-# Vertical Separator #
-# ---------------------------------------------------------------------- #
-class VerticalSeparator(Element):
- """
- Vertical Separator Element draws a vertical line at the given location. It will span 1 "row". Usually paired with
- Column Element if extra height is needed
- """
-
- def __init__(self, color=None, pad=None, p=None, key=None, k=None):
- """
- :param color: Color of the line. Defaults to theme's text color. Can be name or #RRGGBB format
- :type color: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- """
- key = key if key is not None else k
- pad = pad if pad is not None else p
- self.expand_x = None
- self.expand_y = None
- self.Orientation = 'vertical' # for now only vertical works
- self.color = color if color is not None else theme_text_color()
- super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, key=key)
-
-
-VSeperator = VerticalSeparator
-VSeparator = VerticalSeparator
-VSep = VerticalSeparator
-VLine = VerticalSeparator
-VerticalLine = VerticalSeparator
-
-
-# ---------------------------------------------------------------------- #
-# Horizontal Separator #
-# ---------------------------------------------------------------------- #
-class HorizontalSeparator(Element):
- """
- Horizontal Separator Element draws a Horizontal line at the given location.
- """
-
- def __init__(self, color=None, pad=None, p=None, key=None, k=None):
- """
- :param color: Color of the line. Defaults to theme's text color. Can be name or #RRGGBB format
- :type color: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- """
-
- self.Orientation = 'horizontal' # for now only vertical works
- self.color = color if color is not None else theme_text_color()
- self.expand_x = True
- self.expand_y = None
- key = key if key is not None else k
- pad = pad if pad is not None else p
-
- super().__init__(ELEM_TYPE_SEPARATOR, pad=pad, key=key)
-
-
-HSeparator = HorizontalSeparator
-HSep = HorizontalSeparator
-HorizontalLine = HorizontalSeparator
-HLine = HorizontalSeparator
-Line = HorizontalSeparator
-
-
-# ---------------------------------------------------------------------- #
-# Sizegrip #
-# ---------------------------------------------------------------------- #
-class Sizegrip(Element):
- """
- Sizegrip element will be added to the bottom right corner of your window.
- It should be placed on the last row of your window along with any other elements on that row.
- The color will match the theme's background color.
- """
-
- def __init__(self, background_color=None, pad=None, p=(0, 0), key=None, k=None):
- """
- Sizegrip Element
- :param background_color: color to use for the background of the grip
- :type background_color: str
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- """
-
- bg = background_color if background_color is not None else theme_background_color()
- pad = pad if pad is not None else p
- key = key if key is not None else k
-
- super().__init__(ELEM_TYPE_SIZEGRIP, background_color=bg, key=key, pad=pad)
-
-
-SGrip = Sizegrip
-
-
-# ---------------------------------------------------------------------- #
-# Tab #
-# ---------------------------------------------------------------------- #
-class Tab(Element):
- """
- Tab Element is another "Container" element that holds a layout and displays a tab with text. Used with TabGroup only
- Tabs are never placed directly into a layout. They are always "Contained" in a TabGroup layout
- """
-
- def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, p=None, disabled=False,
- border_width=None, key=None, k=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, element_justification='left',
- image_source=None, image_subsample=None, image_zoom=None, metadata=None):
- """
- :param title: text to show on the tab
- :type title: (str)
- :param layout: The element layout that will be shown in the tab
- :type layout: List[List[Element]]
- :param title_color: color of the tab text (note not currently working on tkinter)
- :type title_color: (str)
- :param background_color: color of background of the entire layout
- :type background_color: (str)
- :param font: NOT USED in the tkinter port
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param disabled: If True button will be created disabled
- :type disabled: (bool)
- :param border_width: NOT USED in tkinter port
- :type border_width: (int)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param element_justification: All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values
- :type element_justification: (str)
- :param image_source: A filename or a base64 bytes of an image to place on the Tab
- :type image_source: str | bytes | None
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param image_zoom: amount to increase the size of the image. 2=twice size, 3=3 times, etc
- :type image_zoom: (int)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- filename = data = None
- if image_source is not None:
- if isinstance(image_source, bytes):
- data = image_source
- elif isinstance(image_source, str):
- filename = image_source
- else:
- warnings.warn('Image element - source is not a valid type: {}'.format(type(image_source)), UserWarning)
-
- self.Filename = filename
- self.Data = data
- self.ImageSubsample = image_subsample
- self.zoom = int(image_zoom) if image_zoom is not None else None
- self.UseDictionary = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.ParentWindow = None
- self.Rows = []
- self.TKFrame = None
- self.Widget = None # type: tk.Frame
- self.Title = title
- self.BorderWidth = border_width
- self.Disabled = disabled
- self.ParentNotebook = None
- self.TabID = None
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self.RightClickMenu = right_click_menu
- self.ContainerElemementNumber = Window._GetAContainerNumber()
- self.ElementJustification = element_justification
- key = key if key is not None else k
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- self.Layout(layout)
-
- super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, key=key, tooltip=tooltip,
- visible=visible, metadata=metadata)
- return
-
- def add_row(self, *args):
- """
- Not recommended use call. Used to add rows of Elements to the Frame Element.
-
- :param *args: The list of elements for this row
- :type *args: List[Element]
- """
- NumRows = len(self.Rows) # number of existing rows is our row number
- CurrentRowNumber = NumRows # this row's number
- CurrentRow = [] # start with a blank row and build up
- # ------------------------- Add the elements to a row ------------------------- #
- for i, element in enumerate(args): # Loop through list of elements and add them to the row
- if type(element) == list:
- popup_error_with_traceback('Error creating Tab layout',
- 'Layout has a LIST instead of an ELEMENT',
- 'This sometimes means you have a badly placed ]',
- 'The offensive list is:',
- element,
- 'This list will be stripped from your layout')
- continue
- elif callable(element) and not isinstance(element, Element):
- popup_error_with_traceback('Error creating Tab layout',
- 'Layout has a FUNCTION instead of an ELEMENT',
- 'This likely means you are missing () from your layout',
- 'The offensive list is:',
- element,
- 'This item will be stripped from your layout')
- continue
- if element.ParentContainer is not None:
- warnings.warn(
- '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
- UserWarning)
- popup_error_with_traceback('Error creating Tab layout',
- 'The layout specified has already been used',
- 'You MUST start witha "clean", unused layout every time you create a window',
- 'The offensive Element = ',
- element,
- 'and has a key = ', element.Key,
- 'This item will be stripped from your layout',
- 'Hint - try printing your layout and matching the IDs "print(layout)"')
- continue
- element.Position = (CurrentRowNumber, i)
- element.ParentContainer = self
- CurrentRow.append(element)
- if element.Key is not None:
- self.UseDictionary = True
- # ------------------------- Append the row to list of Rows ------------------------- #
- self.Rows.append(CurrentRow)
-
- def layout(self, rows):
- """
- Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements
-
- :param rows: List[List[Element]] The list of rows
- :type rows: List[List[Element]]
- :return: (Tab) used for chaining
- :rtype:
- """
-
- for row in rows:
- try:
- iter(row)
- except TypeError:
- PopupError('Error creating Tab layout',
- 'Your row is not an iterable (e.g. a list)',
- 'Instead of a list, the type found was {}'.format(type(row)),
- 'The offensive row = ',
- row,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- self.AddRow(*row)
- return self
-
- def update(self, title=None, disabled=None, visible=None):
- """
- Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param title: tab title
- :type title: (str)
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Tab.update - The window was closed')
- return
-
- state = 'normal'
- if disabled is not None:
- self.Disabled = disabled
- if disabled:
- state = 'disabled'
- if visible is False:
- state = 'hidden'
- if visible is not None:
- self._visible = visible
-
- self.ParentNotebook.tab(self.TabID, state=state)
-
- if title is not None:
- self.Title = str(title)
- self.ParentNotebook.tab(self.TabID, text=self.Title)
- # self.ParentNotebook.tab(self.ContainerElemementNumber-1, text=self.Title)
-
- # if visible is False:
- # self.ParentNotebook.pack_forget()
- # elif visible is True:
- # self.ParentNotebook.pack()
- return self
-
- def _GetElementAtLocation(self, location):
- """
- Not user callable. Used to find the Element at a row, col position within the layout
-
- :param location: (row, column) position of the element to find in layout
- :type location: (int, int)
- :return: The element found at the location
- :rtype: (Element)
- """
-
- (row_num, col_num) = location
- row = self.Rows[row_num]
- element = row[col_num]
- return element
-
- def select(self):
- """
- Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first!
-
- """
- # Use a try in case the window has been destoyed
- try:
- self.ParentNotebook.select(self.TabID)
- except Exception as e:
- print('Exception Selecting Tab {}'.format(e))
-
- AddRow = add_row
- Layout = layout
- Select = select
- Update = update
-
-
-# ---------------------------------------------------------------------- #
-# TabGroup #
-# ---------------------------------------------------------------------- #
-class TabGroup(Element):
- """
- TabGroup Element groups together your tabs into the group of tabs you see displayed in your window
- """
-
- def __init__(self, layout, tab_location=None, title_color=None, tab_background_color=None, selected_title_color=None, selected_background_color=None,
- background_color=None, focus_color=None, font=None, change_submits=False, enable_events=False, pad=None, p=None, border_width=None, tab_border_width=None,
- theme=None, key=None, k=None,
- size=(None, None), s=(None, None), tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param layout: Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row
- :type layout: List[List[Tab]]
- :param tab_location: location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright
- :type tab_location: (str)
- :param title_color: color of text on tabs
- :type title_color: (str)
- :param tab_background_color: color of all tabs that are not selected
- :type tab_background_color: (str)
- :param selected_title_color: color of tab text when it is selected
- :type selected_title_color: (str)
- :param selected_background_color: color of tab when it is selected
- :type selected_background_color: (str)
- :param background_color: color of background area that tabs are located on
- :type background_color: (str)
- :param focus_color: color of focus indicator on the tabs
- :type focus_color: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
- :type change_submits: (bool)
- :param enable_events: If True then switching tabs will generate an Event
- :type enable_events: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param tab_border_width: width of border around the tabs
- :type tab_border_width: (int)
- :param theme: DEPRICATED - You can only specify themes using set options or when window is created. It's not possible to do it on an element basis
- :type theme: (str)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param size: (width, height) w=pixels-wide, h=pixels-high. Either item in tuple can be None to indicate use the computed value and set only 1 direction
- :type size: (int|None, int|None)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int|None, int|None)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: DEPRECATED - Should you need to control visiblity for the TabGroup as a whole, place it into a Column element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.UseDictionary = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.ParentWindow = None
- self.SelectedTitleColor = selected_title_color if selected_title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT']
- self.SelectedBackgroundColor = selected_background_color if selected_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL][
- 'BACKGROUND']
- title_color = title_color if title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT']
- self.TabBackgroundColor = tab_background_color if tab_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT']
- self.Rows = []
- self.TKNotebook = None # type: ttk.Notebook
- self.Widget = None # type: ttk.Notebook
- self.tab_index_to_key = {} # has a list of the tabs in the notebook and their associated key
- self.TabCount = 0
- self.BorderWidth = border_width
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self.ChangeSubmits = change_submits or enable_events
- self.TabLocation = tab_location
- self.ElementJustification = 'left'
- self.RightClickMenu = right_click_menu
- self.TabBorderWidth = tab_border_width
- self.FocusColor = focus_color
-
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- self.Layout(layout)
-
- super().__init__(ELEM_TYPE_TAB_GROUP, size=sz, background_color=background_color, text_color=title_color, font=font,
- pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def add_row(self, *args):
- """
- Not recommended user call. Used to add rows of Elements to the Frame Element.
-
- :param *args: The list of elements for this row
- :type *args: List[Element]
- """
-
- NumRows = len(self.Rows) # number of existing rows is our row number
- CurrentRowNumber = NumRows # this row's number
- CurrentRow = [] # start with a blank row and build up
- # ------------------------- Add the elements to a row ------------------------- #
- for i, element in enumerate(args): # Loop through list of elements and add them to the row
- if type(element) == list:
- PopupError('Error creating Tab layout',
- 'Layout has a LIST instead of an ELEMENT',
- 'This sometimes means you have a badly placed ]',
- 'The offensive list is:',
- element,
- 'This list will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()
- )
- continue
- elif callable(element) and not isinstance(element, Element):
- PopupError('Error creating Tab layout',
- 'Layout has a FUNCTION instead of an ELEMENT',
- 'This likely means you are missing () from your layout',
- 'The offensive list is:',
- element,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- if element.ParentContainer is not None:
- warnings.warn(
- '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
- UserWarning)
- PopupError('Error creating Tab layout',
- 'The layout specified has already been used',
- 'You MUST start witha "clean", unused layout every time you create a window',
- 'The offensive Element = ',
- element,
- 'and has a key = ', element.Key,
- 'This item will be stripped from your layout',
- 'Hint - try printing your layout and matching the IDs "print(layout)"', keep_on_top=True, image=_random_error_emoji())
- continue
- element.Position = (CurrentRowNumber, i)
- element.ParentContainer = self
- CurrentRow.append(element)
- if element.Key is not None:
- self.UseDictionary = True
- # ------------------------- Append the row to list of Rows ------------------------- #
- self.Rows.append(CurrentRow)
-
- def layout(self, rows):
- """
- Can use like the Window.Layout method, but it's better to use the layout parameter when creating
-
- :param rows: The rows of Elements
- :type rows: List[List[Element]]
- :return: Used for chaining
- :rtype: (Frame)
- """
- for row in rows:
- try:
- iter(row)
- except TypeError:
- PopupError('Error creating Tab layout',
- 'Your row is not an iterable (e.g. a list)',
- 'Instead of a list, the type found was {}'.format(type(row)),
- 'The offensive row = ',
- row,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- self.AddRow(*row)
- return self
-
- def _GetElementAtLocation(self, location):
- """
- Not user callable. Used to find the Element at a row, col position within the layout
-
- :param location: (row, column) position of the element to find in layout
- :type location: (int, int)
- :return: The element found at the location
- :rtype: (Element)
- """
-
- (row_num, col_num) = location
- row = self.Rows[row_num]
- element = row[col_num]
- return element
-
- def find_key_from_tab_name(self, tab_name):
- """
- Searches through the layout to find the key that matches the text on the tab. Implies names should be unique
-
- :param tab_name: name of a tab
- :type tab_name: str
- :return: Returns the key or None if no key found
- :rtype: key | None
- """
- for row in self.Rows:
- for element in row:
- if element.Title == tab_name:
- return element.Key
- return None
-
-
- def find_currently_active_tab_key(self):
- """
- Returns the key for the currently active tab in this TabGroup
- :return: Returns the key or None of no key found
- :rtype: key | None
- """
- try:
- current_index = self.TKNotebook.index('current')
- key = self.tab_index_to_key.get(current_index, None)
- except:
- key = None
-
- return key
-
- def get(self):
- """
- Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on
- the tab if no key is defined. Returns None if an error occurs.
- Note that this is exactly the same data that would be returned from a call to Window.read. Are you sure you
- are using this method correctly?
-
- :return: The key of the currently selected tab or None if there is an error
- :rtype: Any | None
- """
-
- try:
- current_index = self.TKNotebook.index('current')
- key = self.tab_index_to_key.get(current_index, None)
- except:
- key = None
-
- return key
-
- def add_tab(self, tab_element):
- """
- Add a new tab to an existing TabGroup
- This call was written so that tabs can be added at runtime as your user performs operations.
- Your Window should already be created and finalized.
-
- :param tab_element: A Tab Element that has a layout in it
- :type tab_element: Tab
- """
-
- self.add_row(tab_element)
- tab_element.TKFrame = tab_element.Widget = tk.Frame(self.TKNotebook)
- form = self.ParentForm
- form._BuildKeyDictForWindow(form, tab_element, form.AllKeysDict)
- form.AllKeysDict[tab_element.Key] = tab_element
- # Pack the tab's layout into the tab. NOTE - This does NOT pack the Tab itself... for that see below...
- PackFormIntoFrame(tab_element, tab_element.TKFrame, self.ParentForm)
-
- # - This is below - Perform the same operation that is performed when a Tab is packed into the window.
- # If there's an image in the tab, then do the imagey-stuff
- # ------------------- start of imagey-stuff -------------------
- try:
- if tab_element.Filename is not None:
- photo = tk.PhotoImage(file=tab_element.Filename)
- elif tab_element.Data is not None:
- photo = tk.PhotoImage(data=tab_element.Data)
- else:
- photo = None
-
- if tab_element.ImageSubsample and photo is not None:
- photo = photo.subsample(tab_element.ImageSubsample)
- # print('*ERROR laying out form.... Image Element has no image specified*')
- except Exception as e:
- photo = None
- _error_popup_with_traceback('Your Window has an Tab Element with an IMAGE problem',
- 'The traceback will show you the Window with the problem layout',
- 'Look in this Window\'s layout for an Image tab_element that has a key of {}'.format(tab_element.Key),
- 'The error occuring is:', e)
-
- tab_element.photo = photo
- # add the label
- if photo is not None:
- width, height = photo.width(), photo.height()
- tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, image=photo, width=width, height=height, bd=0)
- else:
- tab_element.tktext_label = tk.Label(tab_element.ParentRowFrame, bd=0)
- # ------------------- end of imagey-stuff -------------------
-
- state = 'normal'
- if tab_element.Disabled:
- state = 'disabled'
- if tab_element.visible is False:
- state = 'hidden'
- if photo is not None:
- self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, compound=tk.LEFT, state=state, image=photo)
- else:
- self.TKNotebook.add(tab_element.TKFrame, text=tab_element.Title, state=state)
- tab_element.ParentNotebook = self.TKNotebook
- tab_element.TabID = self.TabCount
- tab_element.ParentForm = self.ParentForm
- self.TabCount += 1
- if tab_element.BackgroundColor != COLOR_SYSTEM_DEFAULT and tab_element.BackgroundColor is not None:
- tab_element.TKFrame.configure(background=tab_element.BackgroundColor, highlightbackground=tab_element.BackgroundColor,
- highlightcolor=tab_element.BackgroundColor)
- if tab_element.BorderWidth is not None:
- tab_element.TKFrame.configure(borderwidth=tab_element.BorderWidth)
- if tab_element.Tooltip is not None:
- tab_element.TooltipObject = ToolTip(tab_element.TKFrame, text=tab_element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu(tab_element, form)
-
- def update(self, visible=None):
- """
- Enables changing the visibility
-
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in TabGroup.update - The window was closed')
- return
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
-
- AddRow = add_row
- FindKeyFromTabName = find_key_from_tab_name
- Get = get
- Layout = layout
-
-
-# ---------------------------------------------------------------------- #
-# Slider #
-# ---------------------------------------------------------------------- #
-class Slider(Element):
- """
- A slider, horizontal or vertical
- """
-
- def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None,
- disable_number_display=False, setting=None, border_width=None, relief=None, change_submits=False,
- enable_events=False, disabled=False, size=(None, None), s=(None, None), font=None, background_color=None,
- text_color=None, trough_color=None, key=None, k=None, pad=None, p=None, expand_x=False, expand_y=False, tooltip=None, visible=True, metadata=None):
- """
- :param range: slider's range (min value, max value)
- :type range: (int, int) | Tuple[float, float]
- :param default_value: starting value for the slider
- :type default_value: int | float
- :param resolution: the smallest amount the slider can be moved
- :type resolution: int | float
- :param tick_interval: how often a visible tick should be shown next to slider
- :type tick_interval: int | float
- :param orientation: 'horizontal' or 'vertical' ('h' or 'v' also work)
- :type orientation: (str)
- :param disable_number_display: if True no number will be displayed by the Slider Element
- :type disable_number_display: (bool)
- :param setting: If not None, then this element will be saved in a settings file using the key for the element
- :type setting: (Any)
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param relief: relief style. Use constants - RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
- :type relief: str | None
- :param change_submits: * DEPRICATED DO NOT USE. Use `enable_events` instead
- :type change_submits: (bool)
- :param enable_events: If True then moving the slider will generate an Event
- :type enable_events: (bool)
- :param disabled: set disable state for element
- :type disabled: (bool)
- :param size: (l=length chars/rows, w=width pixels)
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param background_color: color of slider's background
- :type background_color: (str)
- :param text_color: color of the slider's text
- :type text_color: (str)
- :param trough_color: color of the slider's trough
- :type trough_color: (str)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.TKScale = self.Widget = None # type: tk.Scale
- self.Range = (1, 10) if range == (None, None) else range
- self.DefaultValue = self.Range[0] if default_value is None else default_value
- self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION
- self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH
- self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF
- self.Resolution = 1 if resolution is None else resolution
- self.ChangeSubmits = change_submits or enable_events
- self.Disabled = disabled
- self.TickInterval = tick_interval
- self.DisableNumericDisplay = disable_number_display
- self.TroughColor = trough_color or DEFAULT_SCROLLBAR_COLOR
- sz = size if size != (None, None) else s
- temp_size = sz
- if temp_size == (None, None):
- temp_size = (20, 20) if self.Orientation.startswith('h') else (8, 20)
- key = key if key is not None else k
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
- if setting is not None:
- self.setting = setting
- self.DefaultValue = user_settings_get_entry(key, setting)
-
- super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color,
- text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata)
- return
-
- def update(self, value=None, range=(None, None), disabled=None, visible=None):
- """
- Changes some of the settings for the Slider Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param value: sets current slider value
- :type value: int | float
- :param range: Sets a new range for slider
- :type range: (int, int) | Tuple[float, float
- :param disabled: disable or enable state of the element
- :type disabled: (bool)
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Slider.update - The window was closed')
- return
-
- if range != (None, None):
- self.TKScale.config(from_=range[0], to_=range[1])
- if value is not None:
- try:
- self.TKIntVar.set(value)
- except:
- pass
- self.DefaultValue = value
- if disabled is True:
- self.TKScale['state'] = 'disabled'
- elif disabled is False:
- self.TKScale['state'] = 'normal'
- self.Disabled = disabled if disabled is not None else self.Disabled
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
-
- def _SliderChangedHandler(self, event):
- """
- Not user callable. Callback function for when slider is moved.
-
- :param event: (event) the event data provided by tkinter. Unknown format. Not used.
- :type event:
- """
-
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
- _exit_mainloop(self.ParentForm)
-
- Update = update
-
-
-Sl = Slider
-
-
-# ---------------------------------------------------------------------- #
-# TkFixedFrame (Used by Column) #
-# ---------------------------------------------------------------------- #
-class TkFixedFrame(tk.Frame):
- """
- A tkinter frame that is used with Column Elements that do not have a scrollbar
- """
-
- def __init__(self, master, **kwargs):
- """
- :param master: The parent widget
- :type master: (tk.Widget)
- :param **kwargs: The keyword args
- :type **kwargs:
- """
- tk.Frame.__init__(self, master, **kwargs)
-
- self.canvas = tk.Canvas(self)
-
- self.canvas.pack(side="left", fill="both", expand=True)
-
- # reset the view
- self.canvas.xview_moveto(0)
- self.canvas.yview_moveto(0)
-
- # create a frame inside the canvas which will be scrolled with it
- self.TKFrame = tk.Frame(self.canvas, **kwargs)
- self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw")
- self.canvas.config(borderwidth=0, highlightthickness=0)
- self.TKFrame.config(borderwidth=0, highlightthickness=0)
- self.config(borderwidth=0, highlightthickness=0)
-
-
-# ---------------------------------------------------------------------- #
-# TkScrollableFrame (Used by Column) #
-# ---------------------------------------------------------------------- #
-class TkScrollableFrame(tk.Frame):
- """
- A frame with one or two scrollbars. Used to make Columns with scrollbars
- """
-
- def __init__(self, master, vertical_only, element, window, **kwargs):
- """
- :param master: The parent widget
- :type master: (tk.Widget)
- :param vertical_only: if True the only a vertical scrollbar will be shown
- :type vertical_only: (bool)
- :param element: The element containing this object
- :type element: (Column)
- """
- tk.Frame.__init__(self, master, **kwargs)
- # create a canvas object and a vertical scrollbar for scrolling it
-
- self.canvas = tk.Canvas(self)
- element.Widget = self.canvas
- # Okay, we're gonna make a list. Containing the y-min, x-min, y-max, and x-max of the frame
- element.element_frame = self
- _make_ttk_scrollbar(element, 'v', window)
- # element.vsb = tk.Scrollbar(self, orient=tk.VERTICAL)
- element.vsb.pack(side='right', fill="y", expand="false")
-
- if not vertical_only:
- _make_ttk_scrollbar(element, 'h', window)
- # self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
- element.hsb.pack(side='bottom', fill="x", expand="false")
- self.canvas.config(xscrollcommand=element.hsb.set)
- # self.canvas = tk.Canvas(self, )
- # else:
- # self.canvas = tk.Canvas(self)
-
- self.canvas.config(yscrollcommand=element.vsb.set)
- self.canvas.pack(side="left", fill="both", expand=True)
- # element.vsb.config(command=self.canvas.yview)
- element.vsb.config(command=self.yview_override)
- if not vertical_only:
- # element.hsb.config(command=self.canvas.xview)
- element.hsb.config(command=self.xview_override)
-
- # reset the view
- self.canvas.xview_moveto(0)
- self.canvas.yview_moveto(0)
-
- # create a frame inside the canvas which will be scrolled with it
- self.TKFrame = tk.Frame(self.canvas, **kwargs)
- self.frame_id = self.canvas.create_window(0, 0, window=self.TKFrame, anchor="nw")
- self.canvas.config(borderwidth=0, highlightthickness=0)
- self.TKFrame.config(borderwidth=0, highlightthickness=0)
- self.config(borderwidth=0, highlightthickness=0)
-
- # Canvas can be: master, canvas, TKFrame
-
- # Chr0nic
-
- # self.unhookMouseWheel(None)
- # self.TKFrame.bind("", self.hookMouseWheel)
- # self.TKFrame.bind("", self.unhookMouseWheel)
- # self.bind('', self.set_scrollregion)
-
- self.unhookMouseWheel(None)
- self.canvas.bind("", self.hookMouseWheel)
- self.canvas.bind("", self.unhookMouseWheel)
- self.bind('', self.set_scrollregion)
-
- # Chr0nic
- def hookMouseWheel(self, e):
- # print("enter")
- VarHolder.canvas_holder = self.canvas
- self.canvas.bind_all('<4>', self.yscroll, add='+')
- self.canvas.bind_all('<5>', self.yscroll, add='+')
- self.canvas.bind_all("", self.yscroll, add='+')
- self.canvas.bind_all("", self.xscroll, add='+')
-
- # Chr0nic
- def unhookMouseWheel(self, e):
- # print("leave")
- VarHolder.canvas_holder = None
- self.canvas.unbind_all('<4>')
- self.canvas.unbind_all('<5>')
- self.canvas.unbind_all("")
- self.canvas.unbind_all("")
-
- def resize_frame(self, e):
- self.canvas.itemconfig(self.frame_id, height=e.height, width=e.width)
-
- def yview_override(self, *args, **kwargs):
- if self.canvas.yview() == (0.0, 1.0):
- return
- self.canvas.yview(*args, **kwargs)
-
- def xview_override(self, *args, **kwargs):
- if self.canvas.xview() == (0.0, 1.0):
- return
- self.canvas.xview(*args, **kwargs)
-
-
- def yscroll(self, event):
- if self.canvas.yview() == (0.0, 1.0):
- return
- if event.num == 5 or event.delta < 0:
- self.canvas.yview_scroll(1, "unit")
- elif event.num == 4 or event.delta > 0:
- self.canvas.yview_scroll(-1, "unit")
-
- def xscroll(self, event):
- if self.canvas.xview() == (0.0, 1.0):
- return
- if event.num == 5 or event.delta < 0:
- self.canvas.xview_scroll(1, "unit")
- elif event.num == 4 or event.delta > 0:
- self.canvas.xview_scroll(-1, "unit")
-
- def bind_mouse_scroll(self, parent, mode):
- # ~~ Windows only
- parent.bind("", mode)
- # ~~ Unix only
- parent.bind("", mode)
- parent.bind("", mode)
-
- def set_scrollregion(self, event=None):
- """ Set the scroll region on the canvas """
- self.canvas.configure(scrollregion=self.canvas.bbox('all'))
-
-
-# ---------------------------------------------------------------------- #
-# Column #
-# ---------------------------------------------------------------------- #
-class Column(Element):
- """
- A container element that is used to create a layout within your window's layout
- """
-
- def __init__(self, layout, background_color=None, size=(None, None), s=(None, None), size_subsample_width=1, size_subsample_height=2, pad=None, p=None, scrollable=False,
- vertical_scroll_only=False, right_click_menu=None, key=None, k=None, visible=True, justification=None, element_justification=None,
- vertical_alignment=None, grab=None, expand_x=None, expand_y=None, metadata=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None,
- sbar_frame_color=None, sbar_relief=None):
- """
- :param layout: Layout that will be shown in the Column container
- :type layout: List[List[Element]]
- :param background_color: color of background of entire Column
- :type background_color: (str)
- :param size: (width, height) size in pixels (doesn't work quite right, sometimes only 1 dimension is set by tkinter. Use a Sizer Element to help set sizes
- :type size: (int | None, int | None)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int | None, int | None)
- :param size_subsample_width: Determines the size of a scrollable column width based on 1/size_subsample * required size. 1 = match the contents exactly, 2 = 1/2 contents size, 3 = 1/3. Can be a fraction to make larger than required.
- :type size_subsample_width: (float)
- :param size_subsample_height: Determines the size of a scrollable height based on 1/size_subsample * required size. 1 = match the contents exactly, 2 = 1/2 contents size, 3 = 1/3. Can be a fraction to make larger than required..
- :type size_subsample_height: (float)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param scrollable: if True then scrollbars will be added to the column. If you update the contents of a scrollable column, be sure and call Column.contents_changed also
- :type scrollable: (bool)
- :param vertical_scroll_only: if True then no horizontal scrollbar will be shown if a scrollable column
- :type vertical_scroll_only: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param justification: set justification for the Column itself. Note entire row containing the Column will be affected
- :type justification: (str)
- :param element_justification: All elements inside the Column will have this justification 'left', 'right', 'center' are valid values
- :type element_justification: (str)
- :param vertical_alignment: Place the column at the 'top', 'center', 'bottom' of the row (can also use t,c,r). Defaults to no setting (tkinter decides)
- :type vertical_alignment: (str)
- :param grab: If True can grab this element and move the window around. Default is False
- :type grab: (bool)
- :param expand_x: If True the column will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the column will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- """
-
- self.UseDictionary = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.ParentWindow = None
- self.ParentPanedWindow = None
- self.Rows = []
- self.TKFrame = None
- self.TKColFrame = None # type: tk.Frame
- self.Scrollable = scrollable
- self.VerticalScrollOnly = vertical_scroll_only
-
- self.RightClickMenu = right_click_menu
- bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self.ContainerElemementNumber = Window._GetAContainerNumber()
- self.ElementJustification = element_justification
- self.Justification = justification
- self.VerticalAlignment = vertical_alignment
- key = key if key is not None else k
- self.Grab = grab
- self.expand_x = expand_x
- self.expand_y = expand_y
- self.Layout(layout)
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.size_subsample_width = size_subsample_width
- self.size_subsample_height = size_subsample_height
-
- super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=sz, pad=pad, key=key, visible=visible, metadata=metadata,
- sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width,
- sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
- return
-
- def add_row(self, *args):
- """
- Not recommended user call. Used to add rows of Elements to the Column Element.
-
- :param *args: The list of elements for this row
- :type *args: List[Element]
- """
-
- NumRows = len(self.Rows) # number of existing rows is our row number
- CurrentRowNumber = NumRows # this row's number
- CurrentRow = [] # start with a blank row and build up
- # ------------------------- Add the elements to a row ------------------------- #
- for i, element in enumerate(args): # Loop through list of elements and add them to the row
- if type(element) == list:
- PopupError('Error creating Column layout',
- 'Layout has a LIST instead of an ELEMENT',
- 'This sometimes means you have a badly placed ]',
- 'The offensive list is:',
- element,
- 'This list will be stripped from your layout', keep_on_top=True, image=_random_error_emoji()
- )
- continue
- elif callable(element) and not isinstance(element, Element):
- PopupError('Error creating Column layout',
- 'Layout has a FUNCTION instead of an ELEMENT',
- 'This likely means you are missing () from your layout',
- 'The offensive list is:',
- element,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- if element.ParentContainer is not None:
- warnings.warn(
- '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
- UserWarning)
- PopupError('Error creating Column layout',
- 'The layout specified has already been used',
- 'You MUST start witha "clean", unused layout every time you create a window',
- 'The offensive Element = ',
- element,
- 'and has a key = ', element.Key,
- 'This item will be stripped from your layout',
- 'Hint - try printing your layout and matching the IDs "print(layout)"', keep_on_top=True, image=_random_error_emoji())
- continue
- element.Position = (CurrentRowNumber, i)
- element.ParentContainer = self
- CurrentRow.append(element)
- if element.Key is not None:
- self.UseDictionary = True
- # ------------------------- Append the row to list of Rows ------------------------- #
- self.Rows.append(CurrentRow)
-
- def layout(self, rows):
- """
- Can use like the Window.Layout method, but it's better to use the layout parameter when creating
-
- :param rows: The rows of Elements
- :type rows: List[List[Element]]
- :return: Used for chaining
- :rtype: (Column)
- """
-
- for row in rows:
- try:
- iter(row)
- except TypeError:
- PopupError('Error creating Column layout',
- 'Your row is not an iterable (e.g. a list)',
- 'Instead of a list, the type found was {}'.format(type(row)),
- 'The offensive row = ',
- row,
- 'This item will be stripped from your layout', keep_on_top=True, image=_random_error_emoji())
- continue
- self.AddRow(*row)
- return self
-
- def _GetElementAtLocation(self, location):
- """
- Not user callable. Used to find the Element at a row, col position within the layout
-
- :param location: (row, column) position of the element to find in layout
- :type location: (int, int)
- :return: The element found at the location
- :rtype: (Element)
- """
-
- (row_num, col_num) = location
- row = self.Rows[row_num]
- element = row[col_num]
- return element
-
- def update(self, visible=None):
- """
- Changes some of the settings for the Column Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Column.update - The window was closed')
- return
-
- if self.expand_x and self.expand_y:
- expand = tk.BOTH
- elif self.expand_x:
- expand = tk.X
- elif self.expand_y:
- expand = tk.Y
- else:
- expand = None
-
- if visible is False:
- if self.TKColFrame:
- self._pack_forget_save_settings()
- # self.TKColFrame.pack_forget()
- if self.ParentPanedWindow:
- self.ParentPanedWindow.remove(self.TKColFrame)
- elif visible is True:
- if self.TKColFrame:
- self._pack_restore_settings()
- # self.TKColFrame.pack(padx=self.pad_used[0], pady=self.pad_used[1], fill=expand)
- if self.ParentPanedWindow:
- self.ParentPanedWindow.add(self.TKColFrame)
- if visible is not None:
- self._visible = visible
-
- def contents_changed(self):
- """
- When a scrollable column has part of its layout changed by making elements visible or invisible or the
- layout is extended for the Column, then this method needs to be called so that the new scroll area
- is computed to match the new contents.
- """
- self.TKColFrame.canvas.config(scrollregion=self.TKColFrame.canvas.bbox('all'))
-
- AddRow = add_row
- Layout = layout
- Update = update
-
-
-Col = Column
-
-
-# ---------------------------------------------------------------------- #
-# Pane #
-# ---------------------------------------------------------------------- #
-class Pane(Element):
- """
- A sliding Pane that is unique to tkinter. Uses Columns to create individual panes
- """
-
- def __init__(self, pane_list, background_color=None, size=(None, None), s=(None, None), pad=None, p=None, orientation='vertical',
- show_handle=True, relief=RELIEF_RAISED, handle_size=None, border_width=None, key=None, k=None, expand_x=None, expand_y=None, visible=True, metadata=None):
- """
- :param pane_list: Must be a list of Column Elements. Each Column supplied becomes one pane that's shown
- :type pane_list: List[Column] | Tuple[Column]
- :param background_color: color of background
- :type background_color: (str)
- :param size: (width, height) w=characters-wide, h=rows-high How much room to reserve for the Pane
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param orientation: 'horizontal' or 'vertical' or ('h' or 'v'). Direction the Pane should slide
- :type orientation: (str)
- :param show_handle: if True, the handle is drawn that makes it easier to grab and slide
- :type show_handle: (bool)
- :param relief: relief style. Values are same as other elements that use relief values. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
- :type relief: (str)
- :param handle_size: Size of the handle in pixels
- :type handle_size: (int)
- :param border_width: width of border around element in pixels
- :type border_width: (int)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param expand_x: If True the column will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the column will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.UseDictionary = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.ParentWindow = None
- self.Rows = []
- self.TKFrame = None
- self.PanedWindow = None
- self.Orientation = orientation
- self.PaneList = pane_list
- self.ShowHandle = show_handle
- self.Relief = relief
- self.HandleSize = handle_size or 8
- self.BorderDepth = border_width
- bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
-
- self.Rows = [pane_list]
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_PANE, background_color=bg, size=sz, pad=pad, key=key, visible=visible, metadata=metadata)
- return
-
- def update(self, visible=None):
- """
- Changes some of the settings for the Pane Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Pane.update - The window was closed')
- return
-
- if visible is False:
- self._pack_forget_save_settings()
- elif visible is True:
- self._pack_restore_settings()
-
- if visible is not None:
- self._visible = visible
-
- Update = update
-
-
-# ---------------------------------------------------------------------- #
-# Menu #
-# ---------------------------------------------------------------------- #
-class Menu(Element):
- """
- Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar.
- Here is an example layout. The "&" are shortcut keys ALT+key.
- Is a List of - "Item String" + List
- Where Item String is what will be displayed on the Menubar itself.
- The List that follows the item represents the items that are shown then Menu item is clicked
- Notice how an "entry" in a mennu can be a list which means it branches out and shows another menu, etc. (resursive)
- menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']],
- ['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ],
- ['&Debugger', ['Popout', 'Launch Debugger']],
- ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']],
- ['&Help', '&About...'], ]
- Important Note! The colors, font, look of the Menubar itself cannot be changed, only the menus shown AFTER clicking the menubar
- can be changed. If you want to change the style/colors the Menubar, then you will have to use the MenubarCustom element.
- Finally, "keys" can be added to entries so make them unique. The "Save" entry has a key associated with it. You
- can see it has a "::" which signifies the beginning of a key. The user will not see the key portion when the
- menu is shown. The key portion is returned as part of the event.
- """
-
- def __init__(self, menu_definition, background_color=None, text_color=None, disabled_text_color=None, size=(None, None), s=(None, None), tearoff=False,
- font=None, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
- """
- :param menu_definition: The Menu definition specified using lists (docs explain the format)
- :type menu_definition: List[List[Tuple[str, List[str]]]
- :param background_color: color of the background of menus, NOT the Menubar
- :type background_color: (str)
- :param text_color: text color for menus, NOT the Menubar. Can be in #RRGGBB format or a color name "black".
- :type text_color: (str)
- :param disabled_text_color: color to use for text when item in submenu, not the menubar itself, is disabled. Can be in #RRGGBB format or a color name "black"
- :type disabled_text_color: (str)
- :param size: Not used in the tkinter port
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None)
- :param tearoff: if True, then can tear the menu off from the window ans use as a floating window. Very cool effect
- :type tearoff: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param font: specifies the font family, size, etc. of submenus. Does NOT apply to the Menubar itself. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.BackgroundColor = background_color if background_color is not None else theme_input_background_color()
- self.TextColor = text_color if text_color is not None else theme_input_text_color()
-
- self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT
- self.MenuDefinition = copy.deepcopy(menu_definition)
- self.Widget = self.TKMenu = None # type: tk.Menu
- self.MenuItemChosen = None
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
-
- super().__init__(ELEM_TYPE_MENUBAR, background_color=self.BackgroundColor, text_color=self.TextColor, size=sz, pad=pad, key=key, visible=visible,
- font=font, metadata=metadata)
- # super().__init__(ELEM_TYPE_MENUBAR, background_color=COLOR_SYSTEM_DEFAULT, text_color=COLOR_SYSTEM_DEFAULT, size=sz, pad=pad, key=key, visible=visible, font=None, metadata=metadata)
-
- self.Tearoff = tearoff
-
- return
-
- def _MenuItemChosenCallback(self, item_chosen): # Menu Menu Item Chosen Callback
- """
- Not user callable. Called when some end-point on the menu (an item) has been clicked. Send the information back to the application as an event. Before event can be sent
-
- :param item_chosen: the text that was clicked on / chosen from the menu
- :type item_chosen: (str)
- """
- # print('IN MENU ITEM CALLBACK', item_chosen)
- self.MenuItemChosen = item_chosen
- self.ParentForm.LastButtonClicked = item_chosen
- self.ParentForm.FormRemainedOpen = True
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit() # kick the users out of the mainloop
- _exit_mainloop(self.ParentForm)
-
- def update(self, menu_definition=None, visible=None):
- """
- Update a menubar - can change the menu definition and visibility. The entire menu has to be specified
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param menu_definition: The menu definition list
- :type menu_definition: List[List[Tuple[str, List[str]]]
- :param visible: control visibility of element
- :type visible: (bool)
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Menu.update - The window was closed')
- return
-
- if menu_definition is not None:
- self.MenuDefinition = copy.deepcopy(menu_definition)
- if self.TKMenu is None: # if no menu exists, make one
- self.TKMenu = tk.Menu(self.ParentForm.TKroot, tearoff=self.Tearoff, tearoffcommand=self._tearoff_menu_callback) # create the menubar
- menubar = self.TKMenu
- # Delete all the menu items (assuming 10000 should be a high enough number to cover them all)
- menubar.delete(0, 10000)
- self.Widget = self.TKMenu # same the new menu so user can access to extend PySimpleGUI
- for menu_entry in self.MenuDefinition:
- baritem = tk.Menu(menubar, tearoff=self.Tearoff, tearoffcommand=self._tearoff_menu_callback)
-
- if self.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(bg=self.BackgroundColor)
- if self.TextColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(fg=self.TextColor)
- if self.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(disabledforeground=self.DisabledTextColor)
- if self.Font is not None:
- baritem.config(font=self.Font)
-
- if self.Font is not None:
- baritem.config(font=self.Font)
- pos = menu_entry[0].find(MENU_SHORTCUT_CHARACTER)
- # print(pos)
- if pos != -1:
- if pos == 0 or menu_entry[0][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + len(MENU_SHORTCUT_CHARACTER):]
- if menu_entry[0][0] == MENU_DISABLED_CHARACTER:
- menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem, underline=pos)
- menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled')
- else:
- menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos)
-
- if len(menu_entry) > 1:
- AddMenuItem(baritem, menu_entry[1], self)
-
- if visible is False:
- self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear
- elif self.TKMenu is not None:
- self.ParentForm.TKroot.configure(menu=self.TKMenu)
- if visible is not None:
- self._visible = visible
-
- Update = update
-
-
-MenuBar = Menu # another name for Menu to make it clear it's the Menu Bar
-Menubar = Menu # another name for Menu to make it clear it's the Menu Bar
-
-
-# ---------------------------------------------------------------------- #
-# Table #
-# ---------------------------------------------------------------------- #
-class Table(Element):
-
- def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, cols_justification=None, def_col_width=10,
- auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, starting_row_number=0, num_rows=None,
- row_height=None, font=None, justification='right', text_color=None, background_color=None,
- alternating_row_color=None, selected_row_colors=(None, None), header_text_color=None, header_background_color=None, header_font=None, header_border_width=None,
- header_relief=None, enable_cell_editing=False, cell_edit_colors=(None, None), cell_edit_select_colors=(None, None),
- row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, border_width=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None,
- size=(None, None), s=(None, None), change_submits=False, enable_events=False, enable_click_events=False, right_click_selects=False, bind_return_key=False,
- pad=None, p=None,
- key=None, k=None, tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param values: Your table data represented as a 2-dimensions table... a list of rows, with each row representing a row in your table.
- :type values: List[List[str | int | float]]
- :param headings: The headings to show on the top line
- :type headings: List[str]
- :param visible_column_map: One entry for each column. False indicates the column is not shown
- :type visible_column_map: List[bool]
- :param col_widths: Number of characters that each column will occupy
- :type col_widths: List[int]
- :param cols_justification: Justification for EACH column. Is a list of strings with the value 'l', 'r', 'c' that indicates how the column will be justified. Either no columns should be set, or have to have one for every colun
- :type cols_justification: List[str] or Tuple[str] or None
- :param def_col_width: Default column width in characters
- :type def_col_width: (int)
- :param auto_size_columns: if True columns will be sized automatically
- :type auto_size_columns: (bool)
- :param max_col_width: Maximum width for all columns in characters
- :type max_col_width: (int)
- :param select_mode: Select Mode. Valid values start with "TABLE_SELECT_MODE_". Valid values are: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED
- :type select_mode: (str)
- :param display_row_numbers: if True, the first column of the table will be the row #
- :type display_row_numbers: (bool)
- :param starting_row_number: The row number to use for the first row. All following rows will be based on this starting value. Default is 0.
- :type starting_row_number: (int)
- :param num_rows: The number of rows of the table to display at a time
- :type num_rows: (int)
- :param row_height: height of a single row in pixels
- :type row_height: (int)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param justification: 'left', 'right', 'center' are valid choices
- :type justification: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param background_color: color of background
- :type background_color: (str)
- :param alternating_row_color: if set then every other row will have this color in the background.
- :type alternating_row_color: (str)
- :param selected_row_colors: Sets the text color and background color for a selected row. Same format as button colors - tuple ('red', 'yellow') or string 'red on yellow'. Defaults to theme's button color
- :type selected_row_colors: str or (str, str)
- :param header_text_color: sets the text color for the header
- :type header_text_color: (str)
- :param header_background_color: sets the background color for the header
- :type header_background_color: (str)
- :param header_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type header_font: (str or (str, int[, str]) or None)
- :param header_border_width: Border width for the header portion
- :type header_border_width: (int | None)
- :param header_relief: Relief style for the header. Values are same as other elements that use relief. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
- :type header_relief: (str | None)
- :param enable_cell_editing: If true, then if the cell is double-clicked, the value can be edited
- :type enable_cell_editing: (bool)
- :param cell_edit_colors: Sets the colors to use when editing a cell. Can be color string "foreground on background" or tuple (foreground, background). Defaults to swapping of table text and background colors
- :type cell_edit_colors: (str | (str, str))
- :param cell_edit_select_colors: Sets the select colors to use when editing a cell. Can be color string "foreground on background" or tuple (foreground, background). Uses system default if none are set
- :type cell_edit_select_colors: (str | (str, str))
- :param row_colors: list of tuples of (row, background color) OR (row, foreground color, background color). Sets the colors of listed rows to the color(s) provided (note the optional foreground color)
- :type row_colors: List[Tuple[int, str] | Tuple[Int, str, str]]
- :param vertical_scroll_only: if True only the vertical scrollbar will be visible
- :type vertical_scroll_only: (bool)
- :param hide_vertical_scroll: if True vertical scrollbar will be hidden
- :type hide_vertical_scroll: (bool)
- :param border_width: Border width/depth in pixels
- :type border_width: (int)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- :param size: DO NOT USE! Use num_rows instead
- :type size: (int, int)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Table events happen when row is clicked
- :type enable_events: (bool)
- :param enable_click_events: Turns on the element click events that will give you (row, col) click data when the table is clicked
- :type enable_click_events: (bool)
- :param right_click_selects: If True, then right clicking a row will select that row if multiple rows are not currently selected
- :type right_click_selects: (bool)
- :param bind_return_key: if True, pressing return key will cause event coming from Table, ALSO a left button double click will generate an event if this parameter is True
- :type bind_return_key: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.Values = values
- self.ColumnHeadings = headings
- self.ColumnsToDisplay = visible_column_map
- self.ColumnWidths = col_widths
- self.cols_justification = cols_justification
- self.MaxColumnWidth = max_col_width
- self.DefaultColumnWidth = def_col_width
- self.AutoSizeColumns = auto_size_columns
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- # self.TextColor = text_color
- self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR
- self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT']
- self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT']
- self.HeaderFont = header_font
- self.Justification = justification
- self.InitialState = None
- self.SelectMode = select_mode
- self.DisplayRowNumbers = display_row_numbers
- self.NumRows = num_rows if num_rows is not None else size[1]
- self.RowHeight = row_height
- self.Widget = self.TKTreeview = None # type: ttk.Treeview
- self.AlternatingRowColor = alternating_row_color
- self.VerticalScrollOnly = vertical_scroll_only
- self.HideVerticalScroll = hide_vertical_scroll
- self.SelectedRows = []
- self.ChangeSubmits = change_submits or enable_events
- self.BindReturnKey = bind_return_key
- self.StartingRowNumber = starting_row_number # When displaying row numbers, where to start
- self.RowHeaderText = 'Row'
- self.enable_click_events = enable_click_events
- self.right_click_selects = right_click_selects
- self.last_clicked_position = (None, None)
- self.HeaderBorderWidth = header_border_width
- self.BorderWidth = border_width
- self.HeaderRelief = header_relief
- self.table_ttk_style_name = None # the ttk style name for the Table itself
- self.enable_cell_editing = enable_cell_editing
- self.disabled_cells = None
- self.cell_edit_select_colors = cell_edit_select_colors
- if cell_edit_select_colors != (None, None):
- if isinstance(cell_edit_select_colors, str):
- try:
- self.cell_edit_select_colors = cell_edit_select_colors.split(' on ')
- except Exception as e:
- print('* Table Element Warning * you messed up with color formatting of Cell Edit Select Colors', e)
-
- self.cell_edit_colors = cell_edit_colors
- if cell_edit_colors != (None, None):
- if isinstance(cell_edit_colors, str):
- try:
- self.cell_edit_colors = cell_edit_colors.split(' on ')
- except Exception as e:
- print('* Table Element Warning * you messed up with color formatting of Cell Edit Colors', e)
- else:
- self.cell_edit_colors = (self.BackgroundColor, self.TextColor)
-
- if selected_row_colors == (None, None):
- # selected_row_colors = DEFAULT_TABLE_AND_TREE_SELECTED_ROW_COLORS
- selected_row_colors = theme_button_color()
- else:
- try:
- if isinstance(selected_row_colors, str):
- selected_row_colors = selected_row_colors.split(' on ')
- except Exception as e:
- print('* Table Element Warning * you messed up with color formatting of Selected Row Color', e)
- self.SelectedRowColors = selected_row_colors
-
- self.RightClickMenu = right_click_menu
- self.RowColors = row_colors
- self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors
- key = key if key is not None else k
- sz = size if size != (None, None) else s
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font,
- size=sz, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata,
- sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width,
- sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
- return
-
- def update(self, values=None, num_rows=None, visible=None, select_rows=None, alternating_row_color=None, row_colors=None):
- """
- Changes some of the settings for the Table Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param values: A new 2-dimensional table to show
- :type values: List[List[str | int | float]]
- :param num_rows: How many rows to display at a time
- :type num_rows: (int)
- :param visible: if True then will be visible
- :type visible: (bool)
- :param select_rows: List of rows to select as if user did
- :type select_rows: List[int]
- :param alternating_row_color: the color to make every other row
- :type alternating_row_color: (str)
- :param row_colors: list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)
- :type row_colors: List[Tuple[int, str] | Tuple[Int, str, str]]
- """
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Table.update - The window was closed')
- return
-
- if values is not None:
- for id in self.tree_ids:
- self.TKTreeview.item(id, tags=())
- if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- self.TKTreeview.tag_configure(id, background=self.BackgroundColor)
- else:
- self.TKTreeview.tag_configure(id, background='#FFFFFF', foreground='#000000')
- if self.TextColor is not None and self.TextColor != COLOR_SYSTEM_DEFAULT:
- self.TKTreeview.tag_configure(id, foreground=self.TextColor)
- else:
- self.TKTreeview.tag_configure(id, foreground='#000000')
-
- children = self.TKTreeview.get_children()
- for i in children:
- self.TKTreeview.detach(i)
- self.TKTreeview.delete(i)
- children = self.TKTreeview.get_children()
-
- self.tree_ids = []
- for i, value in enumerate(values):
- if self.DisplayRowNumbers:
- value = [i + self.StartingRowNumber] + value
- id = self.TKTreeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i)
- if self.BackgroundColor is not None and self.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- self.TKTreeview.tag_configure(id, background=self.BackgroundColor)
- else:
- self.TKTreeview.tag_configure(id, background='#FFFFFF')
- self.tree_ids.append(id)
- self.Values = values
- self.SelectedRows = []
- if visible is False:
- self._pack_forget_save_settings(self.element_frame)
- elif visible is True:
- self._pack_restore_settings(self.element_frame)
-
- if num_rows is not None:
- self.TKTreeview.config(height=num_rows)
- if select_rows is not None:
- rows_to_select = [i + 1 for i in select_rows]
- self.TKTreeview.selection_set(rows_to_select)
-
- if alternating_row_color is not None: # alternating colors
- self.AlternatingRowColor = alternating_row_color
-
- if self.AlternatingRowColor is not None:
- for row in range(0, len(self.Values), 2):
- self.TKTreeview.tag_configure(row, background=self.AlternatingRowColor)
- if row_colors is not None: # individual row colors
- self.RowColors = row_colors
- for row_def in self.RowColors:
- if len(row_def) == 2: # only background is specified
- self.TKTreeview.tag_configure(row_def[0], background=row_def[1])
- else:
- self.TKTreeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1])
- if visible is not None:
- self._visible = visible
-
- def _treeview_selected(self, event):
- """
- Not user callable. Callback function that is called when something is selected from Table.
- Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read
-
- :param event: event information from tkinter
- :type event: (unknown)
- """
- # print('**-- in treeview selected --**')
- selections = self.TKTreeview.selection()
- self.SelectedRows = [int(x) - 1 for x in selections]
- if self.ChangeSubmits:
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit()
- _exit_mainloop(self.ParentForm)
-
- def _treeview_double_click(self, event):
- """
- Not user callable. Callback function that is called when something is double-clicked to edit cell in table.
-
- :param event: event information from tkinter
- :type event: (unknown)
- """
-
- def on_focus_out(table, widget, event, item, column, value_type):
- # Update the Treeview with the new value
- # Make sure the value type matches what was previously there
- table_row = int(item) - 1
- table_col = int(column[1:]) - 1
- new_value = value_type(widget.entry.get())
- col_index = int(column[1:]) - 1
- current_values = list(widget.item(item, "values"))
- current_values[col_index] = new_value
- widget.item(item, values=current_values)
- table.Values[table_row][table_col] = new_value
- # Destroy the Entry widget
- if widget.entry:
- widget.entry.destroy()
- widget.entry = None
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = (self.Key, TABLE_EDITED_INDICATOR, (table_row, table_col))
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
-
- def on_escape(table, widget, event, item, column, value_type):
- if widget.entry:
- widget.entry.destroy()
- widget.entry = None
-
- if self.enable_cell_editing and not self.widget.entry: # if can edit and not already editing another cell
- region = self.widget.identify("region", event.x, event.y)
- if region == "cell":
- column = self.widget.identify_column(event.x)
- item = self.widget.identify_row(event.y)
- row = int(item) - 1
- col = int(column[1:]) - 1
- cell_box = self.widget.bbox(item, column)
- if self.disabled_cells is not None and (row, col) in self.disabled_cells:
- return
- if cell_box:
- self.widget.entry = tk.Entry(self.widget)
- self.widget.entry.config(justify=tk.RIGHT, font=self.font_used)
- if self.cell_edit_colors[0] not in (None, COLOR_SYSTEM_DEFAULT):
- self.widget.entry.config(foreground=self.cell_edit_colors[0])
- if self.cell_edit_colors[1] not in (None, COLOR_SYSTEM_DEFAULT):
- self.widget.entry.config(background=self.cell_edit_colors[1])
- if self.cell_edit_select_colors != (None, None):
- self.widget.entry.config(selectforeground=self.cell_edit_select_colors[0], selectbackground=self.cell_edit_select_colors[1])
-
- self.widget.entry.place(x=cell_box[0], y=cell_box[1], width=cell_box[2], height=cell_box[3])
- # Populate the entry with the current value
- value = self.widget.item(item, "values")[col]
- value_type = type(self.values[row][col])
- self.widget.entry.insert(0, value)
- self.widget.entry.select_range(0, tk.END)
- self.widget.entry.focus()
- # Bind events that end the edit. Either focus out or return key signals end of editing (may want to consider adding escape?)
- self.widget.entry.bind('', lambda e: on_focus_out(self, self.widget, e, item, column, value_type))
- self.widget.entry.bind('', lambda e: on_focus_out(self, self.widget, e, item, column, value_type))
- self.widget.entry.bind('', lambda e: on_escape(self, self.widget, e, item, column, value_type))
- selections = self.TKTreeview.selection()
- self.SelectedRows = [int(x) - 1 for x in selections]
- if self.BindReturnKey: # Signifies BOTH a return key AND a double click
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
-
- def _table_clicked(self, event):
- """
- Not user callable. Callback function that is called a click happens on a table.
- Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read
-
- :param event: event information from tkinter
- :type event: (unknown)
- """
- self.last_table_event = event
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
- # popup(obj_to_string_single_obj(event))
- try:
- region = self.Widget.identify('region', event.x, event.y)
- if region == 'heading':
- row = -1
- elif region == 'cell':
- row = int(self.Widget.identify_row(event.y))-1
- elif region == 'separator':
- row = None
- else:
- row = None
- col_identified = self.Widget.identify_column(event.x)
- if col_identified: # Sometimes tkinter returns a value of '' which would cause an error if cast to an int
- column = int(self.Widget.identify_column(event.x)[1:])-1-int(self.DisplayRowNumbers is True)
- else:
- column = None
- except Exception as e:
- warnings.warn('Error getting table click data for table with key= {}\nError: {}'.format(self.Key, e), UserWarning)
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('Unable to complete operation getting the clicked event for table with key {}'.format(self.Key), _create_error_message(), e, 'Event data:', obj_to_string_single_obj(event))
- row = column = None
-
- self.last_clicked_position = (row, column)
-
- # update the rows being selected if appropriate
- self.ParentForm.TKroot.update()
- # self.TKTreeview.()
- selections = self.TKTreeview.selection()
- if self.right_click_selects and len(selections) <= 1:
- if (event.num == 3 and not running_mac()) or (event.num == 2 and running_mac()):
- if row != -1 and row is not None:
- selections = [row+1]
- self.TKTreeview.selection_set(selections)
- # print(selections)
- self.SelectedRows = [int(x) - 1 for x in selections]
- # print('The new selected rows = ', self.SelectedRows)
- if self.enable_click_events is True:
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = (self.Key, TABLE_CLICKED_INDICATOR, (row, column))
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- _exit_mainloop(self.ParentForm)
-
-
- def disable_edit_for_cells(self, list_of_cells_to_disable=None):
- """
- Disable editing of cells for a Table. List of cells should be in the format of a list of (row, col) tuples
- :param: list_of_cells_to_disble
- :tupe: List[(int, int)] or None
- """
- self.disabled_cells = copy.deepcopy(list_of_cells_to_disable)
- print(f'Disabled Cells = {self.disabled_cells}')
-
- def get(self):
- """
- Get the selected rows using tktiner's selection method. Returns a list of the selected rows.
-
- :return: a list of the index of the selected rows (a list of ints)
- :rtype: List[int]
- """
-
- selections = self.TKTreeview.selection()
- selected_rows = [int(x) - 1 for x in selections]
- return selected_rows
-
- def get_last_clicked_position(self):
- """
- Returns a tuple with the row and column of the cell that was last clicked.
- Headers will have a row == -1 and the Row Number Column (if present) will have a column == -1
- :return: The (row,col) position of the last cell clicked in the table
- :rtype: (int | None, int | None)
- """
- return self.last_clicked_position
-
-
- @property
- def values(self):
- """
- Returns the table values as a list of lists
-
- :return: List of lists of table items
- :rtype: List[List[Any]]
- """
- return self.Values
-
-
- Update = update
- Get = get
-
-
-# ---------------------------------------------------------------------- #
-# Tree #
-# ---------------------------------------------------------------------- #
-class Tree(Element):
- """
- Tree Element - Presents data in a tree-like manner, much like a file/folder browser. Uses the TreeData class
- to hold the user's data and pass to the element for display.
- """
-
- def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, col0_heading='',
- def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False,
- change_submits=False, enable_events=False, click_toggles_select=None, font=None, justification='right', text_color=None, border_width=None,
- background_color=None, selected_row_colors=(None, None), header_text_color=None, header_background_color=None, header_font=None, header_border_width=None,
- header_relief=None, num_rows=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None,
- row_height=None, vertical_scroll_only=True, hide_vertical_scroll=False, pad=None, p=None, key=None, k=None, tooltip=None,
- right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
- """
- :param data: The data represented using a PySimpleGUI provided TreeData class
- :type data: (TreeData)
- :param headings: List of individual headings for each column
- :type headings: List[str]
- :param visible_column_map: Determines if a column should be visible. If left empty, all columns will be shown
- :type visible_column_map: List[bool]
- :param col_widths: List of column widths so that individual column widths can be controlled
- :type col_widths: List[int]
- :param col0_width: Size of Column 0 which is where the row numbers will be optionally shown
- :type col0_width: (int)
- :param col0_heading: Text to be shown in the header for the left-most column
- :type col0_heading: (str)
- :param def_col_width: default column width
- :type def_col_width: (int)
- :param auto_size_columns: if True, the size of a column is determined using the contents of the column
- :type auto_size_columns: (bool)
- :param max_col_width: the maximum size a column can be
- :type max_col_width: (int)
- :param select_mode: Use same values as found on Table Element. Valid values include: TABLE_SELECT_MODE_NONE TABLE_SELECT_MODE_BROWSE TABLE_SELECT_MODE_EXTENDED
- :type select_mode: (str)
- :param show_expanded: if True then the tree will be initially shown with all nodes completely expanded
- :type show_expanded: (bool)
- :param change_submits: DO NOT USE. Only listed for backwards compat - Use enable_events instead
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events. Tree events happen when row is clicked
- :type enable_events: (bool)
- :param click_toggles_select: If True then clicking a row will cause the selection for that row to toggle between selected and deselected
- :type click_toggles_select: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param justification: 'left', 'right', 'center' are valid choices
- :type justification: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param border_width: Border width/depth in pixels
- :type border_width: (int)
- :param background_color: color of background
- :type background_color: (str)
- :param selected_row_colors: Sets the text color and background color for a selected row. Same format as button colors - tuple ('red', 'yellow') or string 'red on yellow'. Defaults to theme's button color
- :type selected_row_colors: str or (str, str)
- :param header_text_color: sets the text color for the header
- :type header_text_color: (str)
- :param header_background_color: sets the background color for the header
- :type header_background_color: (str)
- :param header_font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type header_font: (str or (str, int[, str]) or None)
- :param header_border_width: Border width for the header portion
- :type header_border_width: (int | None)
- :param header_relief: Relief style for the header. Values are same as other elements that use relief. RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID
- :type header_relief: (str | None)
- :param num_rows: The number of rows of the table to display at a time
- :type num_rows: (int)
- :param row_height: height of a single row in pixels
- :type row_height: (int)
- :param vertical_scroll_only: if True only the vertical scrollbar will be visible
- :type vertical_scroll_only: (bool)
- :param hide_vertical_scroll: if True vertical scrollbar will be hidden
- :type hide_vertical_scroll: (bool)
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[str] | str]]
- :param expand_x: If True the element will automatically expand in the X direction to fill available space
- :type expand_x: (bool)
- :param expand_y: If True the element will automatically expand in the Y direction to fill available space
- :type expand_y: (bool)
- :param visible: set visibility state of the element
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self.image_dict = {}
-
- self.TreeData = data
- self.ColumnHeadings = headings
- self.ColumnsToDisplay = visible_column_map
- self.ColumnWidths = col_widths
- self.MaxColumnWidth = max_col_width
- self.DefaultColumnWidth = def_col_width
- self.AutoSizeColumns = auto_size_columns
- self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
- self.TextColor = text_color
- self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT']
- self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT']
- self.HeaderBorderWidth = header_border_width
- self.BorderWidth = border_width
- self.HeaderRelief = header_relief
- self.click_toggles_select = click_toggles_select
- if selected_row_colors == (None, None):
- # selected_row_colors = DEFAULT_TABLE_AND_TREE_SELECTED_ROW_COLORS
- selected_row_colors = theme_button_color()
- else:
- try:
- if isinstance(selected_row_colors, str):
- selected_row_colors = selected_row_colors.split(' on ')
- except Exception as e:
- print('* Table Element Warning * you messed up with color formatting of Selected Row Color', e)
- self.SelectedRowColors = selected_row_colors
-
- self.HeaderFont = header_font
- self.Justification = justification
- self.InitialState = None
- self.SelectMode = select_mode
- self.ShowExpanded = show_expanded
- self.NumRows = num_rows
- self.Col0Width = col0_width
- self.col0_heading = col0_heading
- self.TKTreeview = None # type: ttk.Treeview
- self.element_frame = None # type: tk.Frame
- self.VerticalScrollOnly = vertical_scroll_only
- self.HideVerticalScroll = hide_vertical_scroll
- self.SelectedRows = []
- self.ChangeSubmits = change_submits or enable_events
- self.RightClickMenu = right_click_menu
- self.RowHeight = row_height
- self.IconList = {}
- self.IdToKey = {'': ''}
- self.KeyToID = {'': ''}
- key = key if key is not None else k
- pad = pad if pad is not None else p
- self.expand_x = expand_x
- self.expand_y = expand_y
-
- super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, key=key, tooltip=tooltip,
- visible=visible, metadata=metadata,
- sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width,
- sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
- return
-
- def _treeview_selected(self, event):
- """
- Not a user function. Callback function that happens when an item is selected from the tree. In this
- method, it saves away the reported selections so they can be properly returned.
-
- :param event: An event parameter passed in by tkinter. Not used
- :type event: (Any)
- """
-
- selections = self.TKTreeview.selection()
- selected_rows = [self.IdToKey[x] for x in selections]
- if self.click_toggles_select:
- if set(self.SelectedRows) == set(selected_rows):
- for item in selections:
- self.TKTreeview.selection_remove(item)
- selections = []
- self.SelectedRows = [self.IdToKey[x] for x in selections]
-
- if self.ChangeSubmits:
- MyForm = self.ParentForm
- if self.Key is not None:
- self.ParentForm.LastButtonClicked = self.Key
- else:
- self.ParentForm.LastButtonClicked = ''
- self.ParentForm.FormRemainedOpen = True
- # if self.ParentForm.CurrentlyRunningMainloop:
- # self.ParentForm.TKroot.quit()
- _exit_mainloop(self.ParentForm)
-
- def add_treeview_data(self, node):
- """
- Not a user function. Recursive method that inserts tree data into the tkinter treeview widget.
-
- :param node: The node to insert. Will insert all nodes from starting point downward, recursively
- :type node: (TreeData)
- """
- if node.key != '':
- if node.icon:
- try:
- if node.icon not in self.image_dict:
- if type(node.icon) is bytes:
- photo = tk.PhotoImage(data=node.icon)
- else:
- photo = tk.PhotoImage(file=node.icon)
- self.image_dict[node.icon] = photo
- else:
- photo = self.image_dict.get(node.icon)
-
- node.photo = photo
- id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text,
- values=node.values, open=self.ShowExpanded, image=node.photo)
- self.IdToKey[id] = node.key
- self.KeyToID[node.key] = id
- except:
- self.photo = None
- else:
- id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text,
- values=node.values, open=self.ShowExpanded)
- self.IdToKey[id] = node.key
- self.KeyToID[node.key] = id
-
- for node in node.children:
- self.add_treeview_data(node)
-
- def update(self, values=None, key=None, value=None, text=None, icon=None, visible=None, expand_node=None):
- """
- Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior
-
- Changes will not be visible in your window until you call window.read or window.refresh.
-
- If you change visibility, your element may MOVE. If you want it to remain stationary, use the "layout helper"
- function "pin" to ensure your element is "pinned" to that location in your layout so that it returns there
- when made visible.
-
- :param values: Representation of the tree
- :type values: (TreeData)
- :param key: identifies a particular item in tree to update
- :type key: str | int | tuple | object
- :param value: sets the node identified by key to a particular value
- :type value: (Any)
- :param text: sets the node identified by key to this string
- :type text: (str)
- :param icon: can be either a base64 icon or a filename for the icon
- :type icon: bytes | str
- :param visible: control visibility of element
- :type visible: (bool)
- :param expand_node: if True the node specified by key parameter will be expanded
- :type expand_node: (bool)
- """
-
- if not self._widget_was_created(): # if widget hasn't been created yet, then don't allow
- return
-
- if self._this_elements_window_closed():
- _error_popup_with_traceback('Error in Tree.update - The window was closed')
- return
-
- if values is not None:
- children = self.TKTreeview.get_children()
- for i in children:
- self.TKTreeview.detach(i)
- self.TKTreeview.delete(i)
- children = self.TKTreeview.get_children()
- self.TreeData = values
- self.IdToKey = {'': ''}
- self.KeyToID = {'': ''}
- self.add_treeview_data(self.TreeData.root_node)
- self.SelectedRows = []
- if key is not None:
- for id in self.IdToKey.keys():
- if key == self.IdToKey[id]:
- break
- else:
- id = None
- print('** Key not found **')
- else:
- id = None
- if id:
- # item = self.TKTreeview.item(id)
- if value is not None:
- self.TKTreeview.item(id, values=value)
- if text is not None:
- self.TKTreeview.item(id, text=text)
- if icon is not None:
- try:
- if type(icon) is bytes:
- photo = tk.PhotoImage(data=icon)
- else:
- photo = tk.PhotoImage(file=icon)
- self.TKTreeview.item(id, image=photo)
- self.IconList[key] = photo # save so that it's not deleted (save reference)
- except:
- pass
- # item = self.TKTreeview.item(id)
- if visible is False:
- self._pack_forget_save_settings(self.element_frame)
- elif visible is True:
- self._pack_restore_settings(self.element_frame)
-
- if visible is not None:
- self._visible = visible
- if expand_node is not None:
- if id:
- self.TKTreeview.item(id, open=True if expand_node else False)
- return self
-
- Update = update
-
-
-class TreeData(object):
- """
- Class that user fills in to represent their tree data. It's a very simple tree representation with a root "Node"
- with possibly one or more children "Nodes". Each Node contains a key, text to display, list of values to display
- and an icon. The entire tree is built using a single method, Insert. Nothing else is required to make the tree.
- """
-
- class Node(object):
- """
- Contains information about the individual node in the tree
- """
-
- def __init__(self, parent, key, text, values, icon=None):
- """
- Represents a node within the TreeData class
-
- :param parent: The parent Node
- :type parent: (TreeData.Node)
- :param key: Used to uniquely identify this node
- :type key: str | int | tuple | object
- :param text: The text that is displayed at this node's location
- :type text: (str)
- :param values: The list of values that are displayed at this node
- :type values: List[Any]
- :param icon: just a icon
- :type icon: str | bytes
- """
-
- self.parent = parent # type: TreeData.Node
- self.children = [] # type: List[TreeData.Node]
- self.key = key # type: str
- self.text = text # type: str
- self.values = values # type: List[Any]
- self.icon = icon # type: str | bytes
-
- def _Add(self, node):
- self.children.append(node)
-
- def __init__(self):
- """
- Instantiate the object, initializes the Tree Data, creates a root node for you
- """
- self.tree_dict = {} # type: Dict[str, TreeData.Node]
- self.root_node = self.Node("", "", 'root', [], None) # The root node
- self.tree_dict[""] = self.root_node # Start the tree out with the root node
-
- def _AddNode(self, key, node):
- """
- Adds a node to tree dictionary (not user callable)
-
- :param key: Uniquely identifies this Node
- :type key: (str)
- :param node: Node being added
- :type node: (TreeData.Node)
- """
- self.tree_dict[key] = node
-
- def insert(self, parent, key, text, values, icon=None):
- """
- Inserts a node into the tree. This is how user builds their tree, by Inserting Nodes
- This is the ONLY user callable method in the TreeData class
-
- :param parent: the parent Node
- :type parent: (Node)
- :param key: Used to uniquely identify this node
- :type key: str | int | tuple | object
- :param text: The text that is displayed at this node's location
- :type text: (str)
- :param values: The list of values that are displayed at this node
- :type values: List[Any]
- :param icon: icon
- :type icon: str | bytes
- """
-
- node = self.Node(parent, key, text, values, icon)
- self.tree_dict[key] = node
- parent_node = self.tree_dict[parent]
- parent_node._Add(node)
-
- def __repr__(self):
- """
- Converts the TreeData into a printable version, nicely formatted
-
- :return: (str) A formatted, text version of the TreeData
- :rtype:
- """
- return self._NodeStr(self.root_node, 1)
-
- def _NodeStr(self, node, level):
- """
- Does the magic of converting the TreeData into a nicely formatted string version
-
- :param node: The node to begin printing the tree
- :type node: (TreeData.Node)
- :param level: The indentation level for string formatting
- :type level: (int)
- """
- return '\n'.join(
- [str(node.key) + ' : ' + str(node.text) + ' [ ' + ', '.join([str(v) for v in node.values]) + ' ]'] +
- [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children])
-
- Insert = insert
-
-
-# ---------------------------------------------------------------------- #
-# Error Element #
-# ---------------------------------------------------------------------- #
-class ErrorElement(Element):
- """
- A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid
- """
-
- def __init__(self, key=None, metadata=None):
- """
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key:
- """
- self.Key = key
-
- super().__init__(ELEM_TYPE_ERROR, key=key, metadata=metadata)
-
- def update(self, silent_on_error=True, *args, **kwargs):
- """
- Update method for the Error Element, an element that should not be directly used by developer
-
- :param silent_on_error: if False, then a Popup window will be shown
- :type silent_on_error: (bool)
- :param *args: meant to "soak up" any normal parameters passed in
- :type *args: (Any)
- :param **kwargs: meant to "soak up" any keyword parameters that were passed in
- :type **kwargs: (Any)
- :return: returns 'self' so call can be chained
- :rtype: (ErrorElement)
- """
- print('** Your update is being ignored because you supplied a bad key earlier **')
- return self
-
- def get(self):
- """
- One of the method names found in other Elements. Used here to return an error string in case it's called
-
- :return: A warning text string.
- :rtype: (str)
- """
- return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!'
-
- Get = get
- Update = update
-
-
-# ---------------------------------------------------------------------- #
-# Stretch Element #
-# ---------------------------------------------------------------------- #
-# This is for source code compatibility with tkinter version. No tkinter equivalent but you can fake it using a Text element that expands in the X direction
-def Push(background_color=None):
- """
- Acts like a Stretch element found in the Qt port.
- Used in a Horizontal fashion. Placing one on each side of an element will enter the element.
- Place one to the left and the element to the right will be right justified. See VStretch for vertical type
- :param background_color: color of background may be needed because of how this is implemented
- :type background_color: (str)
- :return: (Text)
- """
- return Text(font='_ 1', background_color=background_color, pad=(0, 0), expand_x=True)
-
-
-P = Push
-Stretch = Push
-
-
-def VPush(background_color=None):
- """
- Acts like a Stretch element found in the Qt port.
- Used in a Vertical fashion.
- :param background_color: color of background may be needed because of how this is implemented
- :type background_color: (str)
- :return: (Text)
- """
- return Text(font='_ 1', background_color=background_color, pad=(0, 0), expand_y=True)
-
-
-VStretch = VPush
-VP = VPush
-
-
-# ------------------------------------------------------------------------- #
-# _TimerPeriodic CLASS #
-# ------------------------------------------------------------------------- #
-
-class _TimerPeriodic:
- id_counter = 1
- # Dictionary containing the active timers. Format is {id : _TimerPeriodic object}
- active_timers = {} # type: dict[int:_TimerPeriodic]
-
- def __init__(self, window, frequency_ms, key=EVENT_TIMER, repeating=True):
- """
- :param window: The window to send events to
- :type window: Window
- :param frequency_ms: How often to send events in milliseconds
- :type frequency_ms: int
- :param repeating: If True then the timer will run, repeatedly sending events, until stopped
- :type repeating: bool
- """
- self.window = window
- self.frequency_ms = frequency_ms
- self.repeating = repeating
- self.key = key
- self.id = _TimerPeriodic.id_counter
- _TimerPeriodic.id_counter += 1
- self.start()
-
- @classmethod
- def stop_timer_with_id(cls, timer_id):
- """
- Not user callable!
- :return: A simple counter that makes each container element unique
- :rtype:
- """
- timer = cls.active_timers.get(timer_id, None)
- if timer is not None:
- timer.stop()
-
- @classmethod
- def stop_all_timers_for_window(cls, window):
- """
- Stops all timers for a given window
- :param window: The window to stop timers for
- :type window: Window
- """
- for timer in _TimerPeriodic.active_timers.values():
- if timer.window == window:
- timer.running = False
-
- @classmethod
- def get_all_timers_for_window(cls, window):
- """
- Returns a list of timer IDs for a given window
- :param window: The window to find timers for
- :type window: Window
- :return: List of timer IDs for the window
- :rtype: List[int]
- """
- timers = []
- for timer in _TimerPeriodic.active_timers.values():
- if timer.window == window:
- timers.append(timer.id)
-
- return timers
-
- def timer_thread(self):
- """
- The thread that sends events to the window. Runs either once or in a loop until timer is stopped
- """
-
- if not self.running: # if timer has been cancelled, abort
- del _TimerPeriodic.active_timers[self.id]
- return
- while True:
- time.sleep(self.frequency_ms / 1000)
- if not self.running: # if timer has been cancelled, abort
- del _TimerPeriodic.active_timers[self.id]
- return
- self.window.write_event_value(self.key, self.id)
-
- if not self.repeating: # if timer does not repeat, then exit thread
- del _TimerPeriodic.active_timers[self.id]
- return
-
- def start(self):
- """
- Starts a timer by starting a timer thread
- Adds timer to the list of active timers
- """
- self.running = True
- self.thread = threading.Thread(target=self.timer_thread, daemon=True)
- self.thread.start()
- _TimerPeriodic.active_timers[self.id] = self
-
- def stop(self):
- """
- Stops a timer
- """
- self.running = False
-
-
-# ------------------------------------------------------------------------- #
-# Window CLASS #
-# ------------------------------------------------------------------------- #
-class Window:
- """
- Represents a single Window
- """
- NumOpenWindows = 0
- _user_defined_icon = None
- hidden_master_root = None # type: tk.Tk
- _animated_popup_dict = {} # type: Dict
- _active_windows = {} # type: Dict[Window, tk.Tk()]
- _move_all_windows = False # if one window moved, they will move
- _window_that_exited = None # type: Window
- _root_running_mainloop = None # type: tk.Tk() # (may be the hidden root or a window's root)
- _timeout_key = None
- _TKAfterID = None # timer that is used to run reads with timeouts
- _window_running_mainloop = None # The window that is running the mainloop
- _container_element_counter = 0 # used to get a number of Container Elements (Frame, Column, Tab)
- _read_call_from_debugger = False
- _timeout_0_counter = 0 # when timeout=0 then go through each window one at a time
- _counter_for_ttk_widgets = 0
- _floating_debug_window_build_needed = False
- _main_debug_window_build_needed = False
- # rereouted stdout info. List of tuples (window, element, previous destination)
- _rerouted_stdout_stack = [] # type: List[Tuple[Window, Element]]
- _rerouted_stderr_stack = [] # type: List[Tuple[Window, Element]]
- _original_stdout = None
- _original_stderr = None
-
-
- def __init__(self, title, layout=None, default_element_size=None,
- default_button_element_size=(None, None),
- auto_size_text=None, auto_size_buttons=None, location=(None, None), relative_location=(None, None), auto_save_location=False, size=(None, None),
- element_padding=None, margins=(None, None), button_color=None, font=None,
- progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False,
- auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=None, force_toplevel=False,
- alpha_channel=None, return_keyboard_events=False, use_default_focus=True, text_justification=None,
- no_titlebar=False, grab_anywhere=False, grab_anywhere_using_control=True, keep_on_top=None, resizable=False, disable_close=False,
- disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=False,
- right_click_menu_background_color=None, right_click_menu_text_color=None, right_click_menu_disabled_text_color=None, right_click_menu_selected_colors=(None, None),
- right_click_menu_font=None, right_click_menu_tearoff=False,
- finalize=False, element_justification='left', ttk_theme=None, use_ttk_buttons=None, modal=False, enable_close_attempted_event=False,
- enable_window_config_events=False, repeating_timer_ms=None,
- titlebar_background_color=None, titlebar_text_color=None, titlebar_font=None, titlebar_icon=None,
- use_custom_titlebar=None, scaling=None,
- sbar_trough_color=None, sbar_background_color=None, sbar_arrow_color=None, sbar_width=None, sbar_arrow_width=None, sbar_frame_color=None, sbar_relief=None, watermark=None, print_event_values=None,
- metadata=None):
- """
- :param title: The title that will be displayed in the Titlebar and on the Taskbar
- :type title: (str)
- :param layout: The layout for the window. Can also be specified in the Layout method
- :type layout: List[List[Element]] | Tuple[Tuple[Element]]
- :param default_element_size: size in characters (wide) and rows (high) for all elements in this window
- :type default_element_size: (int, int) - (width, height)
- :param default_button_element_size: (width, height) size in characters (wide) and rows (high) for all Button elements in this window
- :type default_button_element_size: (int, int)
- :param auto_size_text: True if Elements in Window should be sized to exactly fir the length of text
- :type auto_size_text: (bool)
- :param auto_size_buttons: True if Buttons in this Window should be sized to exactly fit the text on this.
- :type auto_size_buttons: (bool)
- :param location: (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen. None will not set any location meaning the OS will decide
- :type location: (int, int) or (None, None) or None
- :param relative_location: (x,y) location relative to the default location of the window, in pixels. Normally the window centers. This location is relative to the location the window would be created. Note they can be negative.
- :type relative_location: (int, int)
- :param auto_save_location: If True the windows location will be automatically saved to a settings file and will be reloaded next time the program is run. Save happens when window close is detected
- :type auto_save_location: (bool)
- :param size: (width, height) size in pixels for this window. Normally the window is autosized to fit contents, not set to an absolute size by the user. Try not to set this value. You risk, the contents being cut off, etc. Let the layout determine the window size instead
- :type size: (int, int)
- :param element_padding: Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom)), or an int. If an int, then it's converted into a tuple (int, int)
- :type element_padding: (int, int) or ((int, int),(int,int)) or int
- :param margins: (left/right, top/bottom) Amount of pixels to leave inside the window's frame around the edges before your elements are shown.
- :type margins: (int, int)
- :param button_color: Default button colors for all buttons in the window
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param progress_bar_color: (bar color, background color) Sets the default colors for all progress bars in the window
- :type progress_bar_color: (str, str)
- :param background_color: color of background
- :type background_color: (str)
- :param border_depth: Default border depth (width) for all elements in the window
- :type border_depth: (int)
- :param auto_close: If True, the window will automatically close itself
- :type auto_close: (bool)
- :param auto_close_duration: Number of seconds to wait before closing the window
- :type auto_close_duration: (int)
- :param icon: Can be either a filename or Base64 value. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO. Most portable is to use a Base64 of a PNG file. This works universally across all OS's
- :type icon: (str | bytes)
- :param force_toplevel: If True will cause this window to skip the normal use of a hidden master window
- :type force_toplevel: (bool)
- :param alpha_channel: Sets the opacity of the window. 0 = invisible 1 = completely visible. Values bewteen 0 & 1 will produce semi-transparent windows in SOME environments (The Raspberry Pi always has this value at 1 and cannot change.
- :type alpha_channel: (float)
- :param return_keyboard_events: if True key presses on the keyboard will be returned as Events from Read calls
- :type return_keyboard_events: (bool)
- :param use_default_focus: If True will use the default focus algorithm to set the focus to the "Correct" element
- :type use_default_focus: (bool)
- :param text_justification: Default text justification for all Text Elements in window
- :type text_justification: 'left' | 'right' | 'center'
- :param no_titlebar: If true, no titlebar nor frame will be shown on window. This means you cannot minimize the window and it will not show up on the taskbar
- :type no_titlebar: (bool)
- :param grab_anywhere: If True can use mouse to click and drag to move the window. Almost every location of the window will work except input fields on some systems
- :type grab_anywhere: (bool)
- :param grab_anywhere_using_control: If True can use CONTROL key + left mouse mouse to click and drag to move the window. DEFAULT is TRUE. Unlike normal grab anywhere, it works on all elements.
- :type grab_anywhere_using_control: (bool)
- :param keep_on_top: If True, window will be created on top of all other windows on screen. It can be bumped down if another window created with this parm
- :type keep_on_top: (bool)
- :param resizable: If True, allows the user to resize the window. Note the not all Elements will change size or location when resizing.
- :type resizable: (bool)
- :param disable_close: If True, the X button in the top right corner of the window will no work. Use with caution and always give a way out toyour users
- :type disable_close: (bool)
- :param disable_minimize: if True the user won't be able to minimize window. Good for taking over entire screen and staying that way.
- :type disable_minimize: (bool)
- :param right_click_menu: A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.
- :type right_click_menu: List[List[ List[str] | str ]]
- :param transparent_color: Any portion of the window that has this color will be completely transparent. You can even click through these spots to the window under this window.
- :type transparent_color: (str)
- :param debugger_enabled: If True then the internal debugger will be enabled. Also controllable via the global settings. If global settings is true then will be enabled for all windows
- :type debugger_enabled: (bool)
- :param right_click_menu_background_color: Background color for right click menus
- :type right_click_menu_background_color: (str)
- :param right_click_menu_text_color: Text color for right click menus
- :type right_click_menu_text_color: (str)
- :param right_click_menu_disabled_text_color: Text color for disabled right click menu items
- :type right_click_menu_disabled_text_color: (str)
- :param right_click_menu_selected_colors: Text AND background colors for a selected item. Can be a Tuple OR a color string. simplified-button-color-string "foreground on background". Can be a single color if want to set only the background. Normally a tuple, but can be a simplified-dual-color-string "foreground on background". Can be a single color if want to set only the background.
- :type right_click_menu_selected_colors: (str, str) | str | Tuple
- :param right_click_menu_font: Font for right click menus
- :type right_click_menu_font: (str or (str, int[, str]) or None)
- :param right_click_menu_tearoff: If True then all right click menus can be torn off
- :type right_click_menu_tearoff: bool
- :param finalize: If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code
- :type finalize: (bool)
- :param element_justification: All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values
- :type element_justification: (str)
- :param ttk_theme: Set the tkinter ttk "theme" of the window. Default = DEFAULT_TTK_THEME. Sets all ttk widgets to this theme as their default
- :type ttk_theme: (str)
- :param use_ttk_buttons: Affects all buttons in window. True = use ttk buttons. False = do not use ttk buttons. None = use ttk buttons only if on a Mac
- :type use_ttk_buttons: (bool)
- :param modal: If True then this window will be the only window a user can interact with until it is closed
- :type modal: (bool)
- :param enable_close_attempted_event: If True then the window will not close when "X" clicked. Instead an event WINDOW_CLOSE_ATTEMPTED_EVENT if returned from window.read
- :type enable_close_attempted_event: (bool)
- :param enable_window_config_events: If True then window configuration events (resizing or moving the window) will return WINDOW_CONFIG_EVENT from window.read. Note you will get several when Window is created.
- :type enable_window_config_events: (bool)
- :param repeating_timer_ms: Causes a repeating timer to start when Window is created. The default EVENT_TIMER will be used for the timer event. Setting will cause window to be Finalized
- :type repeating_timer_ms: (int)
- :param titlebar_background_color: If custom titlebar indicated by use_custom_titlebar, then use this as background color
- :type titlebar_background_color: (str | None)
- :param titlebar_text_color: If custom titlebar indicated by use_custom_titlebar, then use this as text color
- :type titlebar_text_color: (str | None)
- :param titlebar_font: If custom titlebar indicated by use_custom_titlebar, then use this as title font
- :type titlebar_font: (str or (str, int[, str]) or None)
- :param titlebar_icon: If custom titlebar indicated by use_custom_titlebar, then use this as the icon (file or base64 bytes)
- :type titlebar_icon: (bytes | str)
- :param use_custom_titlebar: If True, then a custom titlebar will be used instead of the normal titlebar
- :type use_custom_titlebar: bool
- :param scaling: Apply scaling to the elements in the window. Can be set on a global basis using set_options
- :type scaling: float
- :param sbar_trough_color: Scrollbar color of the trough
- :type sbar_trough_color: (str)
- :param sbar_background_color: Scrollbar color of the background of the arrow buttons at the ends AND the color of the "thumb" (the thing you grab and slide). Switches to arrow color when mouse is over
- :type sbar_background_color: (str)
- :param sbar_arrow_color: Scrollbar color of the arrow at the ends of the scrollbar (it looks like a button). Switches to background color when mouse is over
- :type sbar_arrow_color: (str)
- :param sbar_width: Scrollbar width in pixels
- :type sbar_width: (int)
- :param sbar_arrow_width: Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar
- :type sbar_arrow_width: (int)
- :param sbar_frame_color: Scrollbar Color of frame around scrollbar (available only on some ttk themes)
- :type sbar_frame_color: (str)
- :param sbar_relief: Scrollbar relief that will be used for the "thumb" of the scrollbar (the thing you grab that slides). Should be a constant that is defined at starting with "RELIEF_" - RELIEF_RAISED, RELIEF_SUNKEN, RELIEF_FLAT, RELIEF_RIDGE, RELIEF_GROOVE, RELIEF_SOLID
- :type sbar_relief: (str)
- :param watermark: If True, then turns on watermarking temporarily for ALL windows created from this point forward. See global settings doc for more info
- :type watermark: bool
- :param print_event_values: If True then the event and values will be automatically printed when you call the window's read method. GREAT for debugging! Global setting also available to control this.
- :type print_event_values: bool
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
-
- self._metadata = None # type: Any
- self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT
- self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS
- self.Title = str(title)
- self.Rows = [] # a list of ELEMENTS for this row
- self.DefaultElementSize = default_element_size if default_element_size is not None else DEFAULT_ELEMENT_SIZE
- self.DefaultButtonElementSize = default_button_element_size if default_button_element_size != (
- None, None) else DEFAULT_BUTTON_ELEMENT_SIZE
- if DEFAULT_WINDOW_LOCATION != (None, None) and location == (None, None):
- self.Location = DEFAULT_WINDOW_LOCATION
- else:
- self.Location = location
- self.RelativeLoction = relative_location
- self.ButtonColor = button_color_to_tuple(button_color)
- self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR
- self.ParentWindow = None
- self.Font = font if font else DEFAULT_FONT
- self.RadioDict = {}
- self.BorderDepth = border_depth
- if icon:
- self.WindowIcon = icon
- elif Window._user_defined_icon is not None:
- self.WindowIcon = Window._user_defined_icon
- else:
- self.WindowIcon = DEFAULT_WINDOW_ICON
- self.AutoClose = auto_close
- self.NonBlocking = False
- self.TKroot = None # type: tk.Tk
- self.TKrootDestroyed = False
- self.CurrentlyRunningMainloop = False
- self.FormRemainedOpen = False
- self.TKAfterID = None
- self.ProgressBarColor = progress_bar_color
- self.AutoCloseDuration = auto_close_duration
- self.RootNeedsDestroying = False
- self.Shown = False
- self.ReturnValues = None
- self.ReturnValuesList = []
- self.ReturnValuesDictionary = {}
- self.DictionaryKeyCounter = 0
- self.LastButtonClicked = None
- self.LastButtonClickedWasRealtime = False
- self.UseDictionary = False
- self.UseDefaultFocus = use_default_focus
- self.ReturnKeyboardEvents = return_keyboard_events
- self.LastKeyboardEvent = None
- self.TextJustification = text_justification
- self.NoTitleBar = no_titlebar
- self.Grab = grab_anywhere
- self.GrabAnywhere = grab_anywhere
- self.GrabAnywhereUsingControlKey = grab_anywhere_using_control
- if keep_on_top is None and DEFAULT_KEEP_ON_TOP is not None:
- keep_on_top = DEFAULT_KEEP_ON_TOP
- elif keep_on_top is None:
- keep_on_top = False
- self.KeepOnTop = keep_on_top
- self.ForceTopLevel = force_toplevel
- self.Resizable = resizable
- self._AlphaChannel = alpha_channel if alpha_channel is not None else DEFAULT_ALPHA_CHANNEL
- self.Timeout = None
- self.TimeoutKey = TIMEOUT_KEY
- self.TimerCancelled = False
- self.DisableClose = disable_close
- self.DisableMinimize = disable_minimize
- self._Hidden = False
- self._Size = size
- self.XFound = False
- if element_padding is not None:
- if isinstance(element_padding, int):
- element_padding = (element_padding, element_padding)
-
- if element_padding is None:
- self.ElementPadding = DEFAULT_ELEMENT_PADDING
- else:
- self.ElementPadding = element_padding
- self.RightClickMenu = right_click_menu
- self.Margins = margins if margins != (None, None) else DEFAULT_MARGINS
- self.ContainerElemementNumber = Window._GetAContainerNumber()
- # The dictionary containing all elements and keys for the window
- # The keys are the keys for the elements and the values are the elements themselves.
- self.AllKeysDict = {}
- self.TransparentColor = transparent_color
- self.UniqueKeyCounter = 0
- if pysimplegui_user_settings.get('-enable debugger-', False) or debugger_enabled:
- self.DebuggerEnabled = True
- else:
- self.DebuggerEnabled = False
- self.WasClosed = False
- self.ElementJustification = element_justification
- self.FocusSet = False
- self.metadata = metadata
- self.TtkTheme = ttk_theme or DEFAULT_TTK_THEME
- self.UseTtkButtons = use_ttk_buttons if use_ttk_buttons is not None else USE_TTK_BUTTONS
- self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier
- self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter
- self.modal = modal
- self.thread_queue = None # type: queue.Queue
- self.thread_lock = None # type: threading.Lock
- self.thread_timer = None # type: tk.Misc
- self.thread_strvar = None # type: tk.StringVar
- self.read_closed_window_count = 0
- self.config_last_size = (None, None)
- self.config_last_location = (None, None)
- self.starting_window_position = (None, None)
- self.not_completed_initial_movement = True
- self.config_count = 0
- self.saw_00 = False
- self.maximized = False
- self._right_click_menu_element = None
- self.right_click_menu_background_color = right_click_menu_background_color if right_click_menu_background_color is not None else theme_input_background_color()
- self.right_click_menu_text_color = right_click_menu_text_color if right_click_menu_text_color is not None else theme_input_text_color()
- self.right_click_menu_disabled_text_color = right_click_menu_disabled_text_color if right_click_menu_disabled_text_color is not None else COLOR_SYSTEM_DEFAULT
- self.right_click_menu_font = right_click_menu_font if right_click_menu_font is not None else self.Font
- self.right_click_menu_tearoff = right_click_menu_tearoff
- self.auto_close_timer_needs_starting = False
- self.finalize_in_progress = False
- self.close_destroys_window = not enable_close_attempted_event if enable_close_attempted_event is not None else None
- self.enable_window_config_events = enable_window_config_events
- self.override_custom_titlebar = False
- self.use_custom_titlebar = use_custom_titlebar or theme_use_custom_titlebar()
- self.titlebar_background_color = titlebar_background_color
- self.titlebar_text_color = titlebar_text_color
- self.titlebar_font = titlebar_font
- self.titlebar_icon = titlebar_icon
- self.right_click_menu_selected_colors = _simplified_dual_color_to_tuple(right_click_menu_selected_colors,
- (self.right_click_menu_background_color, self.right_click_menu_text_color))
- self.TKRightClickMenu = None
- self._grab_anywhere_ignore_these_list = []
- self._grab_anywhere_include_these_list = []
- self._has_custom_titlebar = use_custom_titlebar
- self._mousex = self._mousey = 0
- self._startx = self._starty = 0
- self._last_location = (None, None) # used by a property
- self.auto_save_location = auto_save_location
- if auto_save_location is True:
- self.Location = user_settings_get_entry('-LAST WINDOW LOCATION-'+title, self.Location)
- self.scaling = scaling if scaling is not None else DEFAULT_SCALING
-
- if self.use_custom_titlebar:
- self.Margins = (0, 0)
- self.NoTitleBar = True
- self._mouse_offset_x = self._mouse_offset_y = 0
- self.watermark = watermark
- self.repeating_timer_ms = repeating_timer_ms
-
- # use the print event values setting if explicitly turned on or disable if explicitly turned off in this window
- if print_event_values is True or (pysimplegui_user_settings.get('-print event values-', False) and print_event_values is not False):
- self.print_event_values = True
- else:
- self.print_event_values = False
-
- self.ttk_part_overrides = TTKPartOverrides(sbar_trough_color=sbar_trough_color, sbar_background_color=sbar_background_color, sbar_arrow_color=sbar_arrow_color, sbar_width=sbar_width, sbar_arrow_width=sbar_arrow_width, sbar_frame_color=sbar_frame_color, sbar_relief=sbar_relief)
-
- if no_titlebar is True:
- self.override_custom_titlebar = True
-
- if layout is not None and type(layout) not in (list, tuple):
- warnings.warn('Your layout is not a list or tuple... this is not good!')
-
- if layout is not None:
- self.Layout(layout)
- if finalize or self.repeating_timer_ms:
- self.Finalize()
-
- if CURRENT_LOOK_AND_FEEL == 'Default':
- print("Window will be a boring gray. Try removing the theme call entirely\n",
- "You will get the default theme or the one set in global settings\n"
- "If you seriously want this gray window and no more nagging, add theme('DefaultNoMoreNagging') or theme('Gray Gray Gray') for completely gray/System Defaults")
-
- @classmethod
- def _GetAContainerNumber(cls):
- """
- Not user callable!
- :return: A simple counter that makes each container element unique
- :rtype:
- """
- cls._container_element_counter += 1
- return cls._container_element_counter
-
- @classmethod
- def _IncrementOpenCount(self):
- """
- Not user callable! Increments the number of open windows
- Note - there is a bug where this count easily gets out of sync. Issue has been opened already. No ill effects
- """
- self.NumOpenWindows += 1
- # print('+++++ INCREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows))
-
- @classmethod
- def _DecrementOpenCount(self):
- """
- Not user callable! Decrements the number of open windows
- """
- self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
- # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows))
-
- @classmethod
- def get_screen_size(self):
- """
- This is a "Class Method" meaning you call it by writing: width, height = Window.get_screen_size()
- Returns the size of the "screen" as determined by tkinter. This can vary depending on your operating system and the number of monitors installed on your system. For Windows, the primary monitor's size is returns. On some multi-monitored Linux systems, the monitors are combined and the total size is reported as if one screen.
-
- :return: Size of the screen in pixels as determined by tkinter
- :rtype: (int, int)
- """
- root = _get_hidden_master_root()
- screen_width = root.winfo_screenwidth()
- screen_height = root.winfo_screenheight()
- return screen_width, screen_height
-
- @property
- def metadata(self):
- """
- Metadata is available for all windows. You can set to any value.
- :return: the current metadata value
- :rtype: (Any)
- """
- return self._metadata
-
- @metadata.setter
- def metadata(self, value):
- """
- Metadata is available for all windows. You can set to any value.
- :param value: Anything you want it to be
- :type value: (Any)
- """
- self._metadata = value
-
-
- def last_location(self):
- """
- The last known location of the window (x,y). Set by config events from tkinter
- :return: The last location of the window
- :rtype: (int, int)
- """
- return self._last_location
-
-
- # ------------------------- Add ONE Row to Form ------------------------- #
- def add_row(self, *args):
- """
- Adds a single row of elements to a window's self.Rows variables.
- Generally speaking this is NOT how users should be building Window layouts.
- Users, create a single layout (a list of lists) and pass as a parameter to Window object, or call Window.Layout(layout)
-
- :param *args: List[Elements]
- :type *args:
- """
- NumRows = len(self.Rows) # number of existing rows is our row number
- CurrentRowNumber = NumRows # this row's number
- CurrentRow = [] # start with a blank row and build up
- # ------------------------- Add the elements to a row ------------------------- #
- for i, element in enumerate(args): # Loop through list of elements and add them to the row
-
- if isinstance(element, tuple) or isinstance(element, list):
- self.add_row(*element)
- continue
- _error_popup_with_traceback('Error creating Window layout',
- 'Layout has a LIST instead of an ELEMENT',
- 'This sometimes means you have a badly placed ]',
- 'The offensive list is:',
- element,
- 'This list will be stripped from your layout'
- )
- continue
- elif callable(element) and not isinstance(element, Element):
- _error_popup_with_traceback('Error creating Window layout',
- 'Layout has a FUNCTION instead of an ELEMENT',
- 'This likely means you are missing () from your layout',
- 'The offensive list is:',
- element,
- 'This item will be stripped from your layout')
- continue
- if element.ParentContainer is not None:
- warnings.warn(
- '*** YOU ARE ATTEMPTING TO REUSE AN ELEMENT IN YOUR LAYOUT! Once placed in a layout, an element cannot be used in another layout. ***',
- UserWarning)
- _error_popup_with_traceback('Error detected in layout - Contains an element that has already been used.',
- 'You have attempted to reuse an element in your layout.',
- "The layout specified has an element that's already been used.",
- 'You MUST start with a "clean", unused layout every time you create a window',
- 'The offensive Element = ',
- element,
- 'and has a key = ', element.Key,
- 'This item will be stripped from your layout',
- 'Hint - try printing your layout and matching the IDs "print(layout)"')
- continue
- element.Position = (CurrentRowNumber, i)
- element.ParentContainer = self
- CurrentRow.append(element)
- # if this element is a titlebar, then automatically set the window margins to (0,0) and turn off normal titlebar
- if element.metadata == TITLEBAR_METADATA_MARKER:
- self.Margins = (0, 0)
- self.NoTitleBar = True
- # ------------------------- Append the row to list of Rows ------------------------- #
- self.Rows.append(CurrentRow)
-
- # ------------------------- Add Multiple Rows to Form ------------------------- #
- def add_rows(self, rows):
- """
- Loops through a list of lists of elements and adds each row, list, to the layout.
- This is NOT the best way to go about creating a window. Sending the entire layout at one time and passing
- it as a parameter to the Window call is better.
-
- :param rows: A list of a list of elements
- :type rows: List[List[Elements]]
- """
- for row in rows:
- try:
- iter(row)
- except TypeError:
- _error_popup_with_traceback('Error Creating Window Layout', 'Error creating Window layout',
- 'Your row is not an iterable (e.g. a list)',
- 'Instead of a list, the type found was {}'.format(type(row)),
- 'The offensive row = ',
- row,
- 'This item will be stripped from your layout')
- continue
- self.add_row(*row)
-
-
- def layout(self, rows):
- """
- Second of two preferred ways of telling a Window what its layout is. The other way is to pass the layout as
- a parameter to Window object. The parameter method is the currently preferred method. This call to Layout
- has been removed from examples contained in documents and in the Demo Programs. Trying to remove this call
- from history and replace with sending as a parameter to Window.
-
- :param rows: Your entire layout
- :type rows: List[List[Elements]]
- :return: self so that you can chain method calls
- :rtype: (Window)
- """
- if self.use_custom_titlebar and not self.override_custom_titlebar:
- if self.titlebar_icon is not None:
- icon = self.titlebar_icon
- elif CUSTOM_TITLEBAR_ICON is not None:
- icon = CUSTOM_TITLEBAR_ICON
- elif self.titlebar_icon is not None:
- icon = self.titlebar_icon
- elif self.WindowIcon == DEFAULT_WINDOW_ICON:
- icon = DEFAULT_BASE64_ICON_16_BY_16
- else:
- icon = None
-
- new_rows = [[Titlebar(title=self.Title, icon=icon, text_color=self.titlebar_text_color, background_color=self.titlebar_background_color,
- font=self.titlebar_font)]] + rows
- else:
- new_rows = rows
- self.add_rows(new_rows)
- self._BuildKeyDict()
-
- if self._has_custom_titlebar_element():
- self.Margins = (0, 0)
- self.NoTitleBar = True
- self._has_custom_titlebar = True
- return self
-
- def extend_layout(self, container, rows):
- """
- Adds new rows to an existing container element inside of this window
- If the container is a scrollable Column, you need to also call the contents_changed() method
-
- :param container: The container Element the layout will be placed inside of
- :type container: Frame | Column | Tab
- :param rows: The layout to be added
- :type rows: (List[List[Element]])
- :return: (Window) self so could be chained
- :rtype: (Window)
- """
- column = Column(rows, pad=(0, 0), background_color=container.BackgroundColor)
- if self == container:
- frame = self.TKroot
- elif isinstance(container.Widget, TkScrollableFrame):
- frame = container.Widget.TKFrame
- else:
- frame = container.Widget
- PackFormIntoFrame(column, frame, self)
- # sg.PackFormIntoFrame(col, window.TKroot, window)
- self.AddRow(column)
- self.AllKeysDict = self._BuildKeyDictForWindow(self, column, self.AllKeysDict)
- return self
-
- def LayoutAndRead(self, rows, non_blocking=False):
- """
- Deprecated!! Now your layout your window's rows (layout) and then separately call Read.
-
- :param rows: The layout of the window
- :type rows: List[List[Element]]
- :param non_blocking: if True the Read call will not block
- :type non_blocking: (bool)
- """
- _error_popup_with_traceback('LayoutAndRead Depricated', 'Wow! You have been using PySimpleGUI for a very long time.',
- 'The Window.LayoutAndRead call is no longer supported')
-
- raise DeprecationWarning(
- 'LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()\nor window(title, layout).Read()')
- # self.AddRows(rows)
- # self._Show(non_blocking=non_blocking)
- # return self.ReturnValues
-
- def LayoutAndShow(self, rows):
- """
- Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read
- """
- raise DeprecationWarning('LayoutAndShow is no longer supported... ')
-
- def _Show(self, non_blocking=False):
- """
- NOT TO BE CALLED BY USERS. INTERNAL ONLY!
- It's this method that first shows the window to the user, collects results
-
- :param non_blocking: if True, this is a non-blocking call
- :type non_blocking: (bool)
- :return: Tuple[Any, Dict] The event, values turple that is returned from Read calls
- :rtype:
- """
- self.Shown = True
- # Compute num rows & num cols (it'll come in handy debugging)
- self.NumRows = len(self.Rows)
- self.NumCols = max(len(row) for row in self.Rows)
- self.NonBlocking = non_blocking
-
- # Search through entire form to see if any elements set the focus
- # if not, then will set the focus to the first input element
- found_focus = False
- for row in self.Rows:
- for element in row:
- try:
- if element.Focus:
- found_focus = True
- except:
- pass
- try:
- if element.Key is not None:
- self.UseDictionary = True
- except:
- pass
-
- if not found_focus and self.UseDefaultFocus:
- self.UseDefaultFocus = True
- else:
- self.UseDefaultFocus = False
- # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ##
- StartupTK(self)
- # If a button or keyboard event happened but no results have been built, build the results
- if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None:
- return _BuildResults(self, False, self)
- return self.ReturnValues
-
- # ------------------------- SetIcon - set the window's fav icon ------------------------- #
- def set_icon(self, icon=None, pngbase64=None):
- """
- Changes the icon that is shown on the title bar and on the task bar.
- NOTE - The file type is IMPORTANT and depends on the OS!
- Can pass in:
- * filename which must be a .ICO icon file for windows, PNG file for Linux
- * bytes object
- * BASE64 encoded file held in a variable
-
- :param icon: Filename or bytes object
- :type icon: (str)
- :param pngbase64: Base64 encoded image
- :type pngbase64: (bytes)
- """
- if type(icon) is bytes or pngbase64 is not None:
- wicon = tkinter.PhotoImage(data=icon if icon is not None else pngbase64)
- try:
- self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
- except:
- wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
- try:
- self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
- except:
- pass
- self.WindowIcon = wicon
- return
-
- wicon = icon
- try:
- self.TKroot.iconbitmap(icon)
- except:
- try:
- wicon = tkinter.PhotoImage(file=icon)
- self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
- except:
- try:
- wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON)
- try:
- self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon)
- except:
- pass
- except:
- pass
- self.WindowIcon = wicon
-
- def _GetElementAtLocation(self, location):
- """
- Given a (row, col) location in a layout, return the element located at that position
-
- :param location: (int, int) Return the element located at (row, col) in layout
- :type location:
- :return: (Element) The Element located at that position in this window
- :rtype:
- """
-
- (row_num, col_num) = location
- row = self.Rows[row_num]
- element = row[col_num]
- return element
-
- def _GetDefaultElementSize(self):
- """
- Returns the default elementSize
-
- :return: (width, height) of the default element size
- :rtype: (int, int)
- """
-
- return self.DefaultElementSize
-
- def _AutoCloseAlarmCallback(self):
- """
- Function that's called by tkinter when autoclode timer expires. Closes the window
-
- """
- try:
- window = self
- if window:
- if window.NonBlocking:
- self.Close()
- else:
- window._Close()
- self.TKroot.quit()
- self.RootNeedsDestroying = True
- except:
- pass
-
- def _TimeoutAlarmCallback(self):
- """
- Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return
- """
- # first, get the results table built
- # modify the Results table in the parent FlexForm object
- # print('TIMEOUT CALLBACK')
- if self.TimerCancelled:
- # print('** timer was cancelled **')
- return
- self.LastButtonClicked = self.TimeoutKey
- self.FormRemainedOpen = True
- self.TKroot.quit() # kick the users out of the mainloop
-
- def _calendar_chooser_button_clicked(self, elem):
- """
-
- :param elem:
- :type elem:
- :return:
- :rtype:
- """
- target_element, strvar, should_submit_window = elem._find_target()
-
- if elem.calendar_default_date_M_D_Y == (None, None, None):
- now = datetime.datetime.now()
- cur_month, cur_day, cur_year = now.month, now.day, now.year
- else:
- cur_month, cur_day, cur_year = elem.calendar_default_date_M_D_Y
-
- date_chosen = popup_get_date(start_mon=cur_month, start_day=cur_day, start_year=cur_year, close_when_chosen=elem.calendar_close_when_chosen,
- no_titlebar=elem.calendar_no_titlebar, begin_at_sunday_plus=elem.calendar_begin_at_sunday_plus,
- locale=elem.calendar_locale, location=elem.calendar_location, month_names=elem.calendar_month_names,
- day_abbreviations=elem.calendar_day_abbreviations, title=elem.calendar_title)
- if date_chosen is not None:
- month, day, year = date_chosen
- now = datetime.datetime.now()
- hour, minute, second = now.hour, now.minute, now.second
- try:
- date_string = calendar.datetime.datetime(year, month, day, hour, minute, second).strftime(elem.calendar_format)
- except Exception as e:
- print('Bad format string in calendar chooser button', e)
- date_string = 'Bad format string'
-
- if target_element is not None and target_element != elem:
- target_element.update(date_string)
- elif target_element == elem:
- elem.calendar_selection = date_string
-
- strvar.set(date_string)
- elem.TKStringVar.set(date_string)
- if should_submit_window:
- self.LastButtonClicked = target_element.Key
- results = _BuildResults(self, False, self)
- else:
- should_submit_window = False
- return should_submit_window
-
- # @_timeit_summary
- def read(self, timeout=None, timeout_key=TIMEOUT_KEY, close=False):
- """
- THE biggest deal method in the Window class! This is how you get all of your data from your Window.
- Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key
- if no other GUI events happen first.
-
- :param timeout: Milliseconds to wait until the Read will return IF no other GUI events happen first
- :type timeout: int|None
- :param timeout_key: The value that will be returned from the call if the timer expired
- :type timeout_key: (Any)
- :param close: if True the window will be closed prior to returning
- :type close: (bool)
- :return: (event, values)
- :rtype: Tuple[(Any), Dict[Any, Any], List[Any], None]
- """
-
- if Window._floating_debug_window_build_needed is True:
- Window._floating_debug_window_build_needed = False
- _Debugger.debugger._build_floating_window()
-
- if Window._main_debug_window_build_needed is True:
- Window._main_debug_window_build_needed = False
- _Debugger.debugger._build_main_debugger_window()
-
- # ensure called only 1 time through a single read cycle
- if not Window._read_call_from_debugger:
- _refresh_debugger()
-
- # if the user has not added timeout and a debug window is open, then set a timeout for them so the debugger continuously refreshes
- if _debugger_window_is_open() and not Window._read_call_from_debugger:
- if timeout is None or timeout > 3000:
- timeout = 200
-
- self._right_click_menu_element = None
-
- while True:
- Window._root_running_mainloop = self.TKroot
- results = self._read(timeout=timeout, timeout_key=timeout_key)
- if results is not None:
- if results[0] == DEFAULT_WINDOW_SNAPSHOT_KEY:
- self.save_window_screenshot_to_disk()
- popup_quick_message('Saved window screenshot to disk', background_color='#1c1e23', text_color='white', keep_on_top=True, font='_ 30')
- continue
- # Post processing for Calendar Chooser Button
- try:
- if results[0] == timeout_key: # if a timeout, then not a calendar button
- break
- elem = self.find_element(results[0], silent_on_error=True) # get the element that caused the event
- if elem.Type == ELEM_TYPE_BUTTON:
- if elem.BType == BUTTON_TYPE_CALENDAR_CHOOSER:
- if self._calendar_chooser_button_clicked(elem): # returns True if should break out
- # results[0] = self.LastButtonClicked
- results = self.ReturnValues
- break
- else:
- continue
- break
- except:
- break # wasn't a calendar button for sure
-
-
- if close:
- self.close()
-
- if self.print_event_values:
- try: # just in casee something weird about the results being printed
- if not (pysimplegui_user_settings.get('-do not print timeouts-', True) and results[0] == TIMEOUT_EVENT):
- if pysimplegui_user_settings.get('-format values dict-', True):
- print(f'{results[0]}\n {dict_to_string(results[1])}')
- else:
- print(f'{results[0]}\n {results[1]}')
- except Exception as e:
- pass
- return results
-
- # @_timeit
- def _read(self, timeout=None, timeout_key=TIMEOUT_KEY):
- """
- THE biggest deal method in the Window class! This is how you get all of your data from your Window.
- Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key
- if no other GUI events happen first.
-
- :param timeout: Milliseconds to wait until the Read will return IF no other GUI events happen first
- :type timeout: (int)
- :param timeout_key: The value that will be returned from the call if the timer expired
- :type timeout_key: (Any)`
- :return: (event, values) (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window)
- :rtype: Tuple[(Any), Dict[Any, Any], List[Any], None]
- """
-
- # if there are events in the thread event queue, then return those events before doing anything else.
- if self._queued_thread_event_available():
- self.ReturnValues = results = _BuildResults(self, False, self)
- return results
-
- if self.finalize_in_progress and self.auto_close_timer_needs_starting:
- self._start_autoclose_timer()
- self.auto_close_timer_needs_starting = False
-
- timeout = int(timeout) if timeout is not None else None
- if timeout == 0: # timeout of zero runs the old readnonblocking
- event, values = self._ReadNonBlocking()
- if event is None:
- event = timeout_key
- if values is None:
- event = None
- return event, values # make event None if values was None and return
- # Read with a timeout
- self.Timeout = timeout
- self.TimeoutKey = timeout_key
- self.NonBlocking = False
- if self.TKrootDestroyed:
- self.read_closed_window_count += 1
- if self.read_closed_window_count > 100:
- popup_error_with_traceback('Trying to read a closed window', 'You have tried 100 times to read a closed window.', 'You need to add a check for event == WIN_CLOSED',)
- return None, None
- if not self.Shown:
- self._Show()
- else:
- # if already have a button waiting, the return previously built results
- if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime:
- results = _BuildResults(self, False, self)
- self.LastButtonClicked = None
- return results
- InitializeResults(self)
-
- if self._queued_thread_event_available():
- self.ReturnValues = results = _BuildResults(self, False, self)
- return results
-
- # if the last button clicked was realtime, emulate a read non-blocking
- # the idea is to quickly return realtime buttons without any blocks until released
- if self.LastButtonClickedWasRealtime:
- # clear the realtime flag if the element is not a button element (for example a graph element that is dragging)
- if self.AllKeysDict.get(self.LastButtonClicked, None):
- if self.AllKeysDict.get(self.LastButtonClicked).Type != ELEM_TYPE_BUTTON:
- self.LastButtonClickedWasRealtime = False # stops from generating events until something changes
- else: # it is possible for the key to not be in the dicitonary because it has a modifier. If so, then clear the realtime button flag
- self.LastButtonClickedWasRealtime = False # stops from generating events until something changes
-
- try:
- rc = self.TKroot.update()
- except:
- self.TKrootDestroyed = True
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- # print('ROOT Destroyed')
- results = _BuildResults(self, False, self)
- if results[0] != None and results[0] != timeout_key:
- return results
- else:
- pass
-
- # else:
- # print("** REALTIME PROBLEM FOUND **", results)
-
- if self.RootNeedsDestroying:
- # print('*** DESTROYING really late***')
- try:
- self.TKroot.destroy()
- except:
- pass
- # _my_windows.Decrement()
- self.LastButtonClicked = None
- return None, None
-
- # normal read blocking code....
- if timeout != None:
- self.TimerCancelled = False
- self.TKAfterID = self.TKroot.after(timeout, self._TimeoutAlarmCallback)
- self.CurrentlyRunningMainloop = True
- # self.TKroot.protocol("WM_DESTROY_WINDOW", self._OnClosingCallback)
- # self.TKroot.protocol("WM_DELETE_WINDOW", self._OnClosingCallback)
- Window._window_running_mainloop = self
- try:
- Window._root_running_mainloop.mainloop()
- except:
- print('**** EXITING ****')
- exit(-1)
- # print('Out main')
- self.CurrentlyRunningMainloop = False
- # if self.LastButtonClicked != TIMEOUT_KEY:
- try:
- self.TKroot.after_cancel(self.TKAfterID)
- del self.TKAfterID
- except:
- pass
- # print('** tkafter cancel failed **')
- self.TimerCancelled = True
- if self.RootNeedsDestroying:
- # print('*** DESTROYING LATE ***')
- try:
- self.TKroot.destroy()
- except:
- pass
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- self.LastButtonClicked = None
- return None, None
- # if form was closed with X
- if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None:
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- # Determine return values
- if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None:
- results = _BuildResults(self, False, self)
- if not self.LastButtonClickedWasRealtime:
- self.LastButtonClicked = None
- return results
- else:
- if self._queued_thread_event_available():
- self.ReturnValues = results = _BuildResults(self, False, self)
- return results
- if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[
- 0] is None: # Special Qt case because returning for no reason so fake timeout
- self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
- elif not self.XFound and self.ReturnValues[0] is None: # Return a timeout event... can happen when autoclose used on another window
- # print("*** Faking timeout ***")
- self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
- return self.ReturnValues
-
- def _ReadNonBlocking(self):
- """
- Should be NEVER called directly by the user. The user can call Window.read(timeout=0) to get same effect
-
- :return: (event, values). (event or timeout_key or None, Dictionary of values or List of values from all elements in the Window)
- :rtype: Tuple[(Any), Dict[Any, Any] | List[Any] | None]
- """
- if self.TKrootDestroyed:
- try:
- self.TKroot.quit()
- self.TKroot.destroy()
- except:
- pass
- # print('DESTROY FAILED')
- return None, None
- if not self.Shown:
- self._Show(non_blocking=True)
- try:
- rc = self.TKroot.update()
- except:
- self.TKrootDestroyed = True
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- # print("read failed")
- # return None, None
- if self.RootNeedsDestroying:
- # print('*** DESTROYING LATE ***', self.ReturnValues)
- self.TKroot.destroy()
- Window._DecrementOpenCount()
- # _my_windows.Decrement()
- self.Values = None
- self.LastButtonClicked = None
- return None, None
- return _BuildResults(self, False, self)
-
- def _start_autoclose_timer(self):
- duration = DEFAULT_AUTOCLOSE_TIME if self.AutoCloseDuration is None else self.AutoCloseDuration
- self.TKAfterID = self.TKroot.after(int(duration * 1000), self._AutoCloseAlarmCallback)
-
- def finalize(self):
- """
- Use this method to cause your layout to built into a real tkinter window. In reality this method is like
- Read(timeout=0). It doesn't block and uses your layout to create tkinter widgets to represent the elements.
- Lots of action!
-
- :return: Returns 'self' so that method "Chaining" can happen (read up about it as it's very cool!)
- :rtype: (Window)
- """
-
- if self.TKrootDestroyed:
- return self
- self.finalize_in_progress = True
-
- self.Read(timeout=1)
-
- if self.AutoClose:
- self.auto_close_timer_needs_starting = True
- # add the window to the list of active windows
- Window._active_windows[self] = Window.hidden_master_root
- if self.repeating_timer_ms is not None:
- self.timer_start(self.repeating_timer_ms, repeating=True)
- return self
- # OLD CODE FOLLOWS
- if not self.Shown:
- self._Show(non_blocking=True)
- try:
- rc = self.TKroot.update()
- except:
- self.TKrootDestroyed = True
- Window._DecrementOpenCount()
- print('** Finalize failed **')
- # _my_windows.Decrement()
- # return None, None
- return self
-
- def refresh(self):
- """
- Refreshes the window by calling tkroot.update(). Can sometimes get away with a refresh instead of a Read.
- Use this call when you want something to appear in your Window immediately (as soon as this function is called).
- If you change an element in a window, your change will not be visible until the next call to Window.read
- or a call to Window.refresh()
-
- :return: `self` so that method calls can be easily "chained"
- :rtype: (Window)
- """
-
- if self.TKrootDestroyed:
- return self
- try:
- rc = self.TKroot.update()
- except:
- pass
- return self
-
- def fill(self, values_dict):
- """
- Fill in elements that are input fields with data based on a 'values dictionary'
-
- :param values_dict: pairs
- :type values_dict: (Dict[Any, Any]) - {Element_key : value}
- :return: returns self so can be chained with other methods
- :rtype: (Window)
- """
-
- FillFormWithValues(self, values_dict)
- return self
-
- def _find_closest_key(self, search_key):
- if not isinstance(search_key, str):
- search_key = str(search_key)
- matches = difflib.get_close_matches(search_key, [str(k) for k in self.AllKeysDict.keys()])
- if not len(matches):
- return None
- for k in self.AllKeysDict.keys():
- if matches[0] == str(k):
- return k
- return matches[0] if len(matches) else None
-
- def FindElement(self, key, silent_on_error=False):
- """
- ** Warning ** This call will eventually be depricated. **
-
- It is suggested that you modify your code to use the recommended window[key] lookup or the PEP8 compliant window.find_element(key)
-
- For now, you'll only see a message printed and the call will continue to funcation as before.
-
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param silent_on_error: If True do not display popup nor print warning of key errors
- :type silent_on_error: (bool)
- :return: Return value can be: the Element that matches the supplied key if found; an Error Element if silent_on_error is False; None if silent_on_error True;
- :rtype: Element | Error Element | None
- """
-
- warnings.warn('Use of FindElement is not recommended.\nEither switch to the recommended window[key] format\nor the PEP8 compliant find_element',
- UserWarning)
- print('** Warning - FindElement should not be used to look up elements. window[key] or window.find_element are recommended. **')
-
- return self.find_element(key, silent_on_error=silent_on_error)
-
- def find_element(self, key, silent_on_error=False, supress_guessing=None, supress_raise=None):
- """
- Find element object associated with the provided key.
- THIS METHOD IS NO LONGER NEEDED to be called by the user
-
- You can perform the same operation by writing this statement:
- element = window[key]
-
- You can drop the entire "find_element" function name and use [ ] instead.
-
- However, if you wish to perform a lookup without error checking, and don't have error popups turned
- off globally, you'll need to make this call so that you can disable error checks on this call.
-
- find_element is typically used in combination with a call to element's update method (or any other element method!):
- window[key].update(new_value)
-
- Versus the "old way"
- window.FindElement(key).Update(new_value)
-
- This call can be abbreviated to any of these:
- find_element = FindElement == Element == Find
- With find_element being the PEP8 compliant call that should be used.
-
- Rememeber that this call will return None if no match is found which may cause your code to crash if not
- checked for.
-
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param silent_on_error: If True do not display popup nor print warning of key errors
- :type silent_on_error: (bool)
- :param supress_guessing: Override for the global key guessing setting.
- :type supress_guessing: (bool | None)
- :param supress_raise: Override for the global setting that determines if a key error should raise an exception
- :type supress_raise: (bool | None)
- :return: Return value can be: the Element that matches the supplied key if found; an Error Element if silent_on_error is False; None if silent_on_error True
- :rtype: Element | ErrorElement | None
- """
-
- key_error = False
- closest_key = None
- supress_guessing = supress_guessing if supress_guessing is not None else SUPPRESS_KEY_GUESSING
- supress_raise = supress_raise if supress_raise is not None else SUPPRESS_RAISE_KEY_ERRORS
- try:
- element = self.AllKeysDict[key]
- except KeyError:
- key_error = True
- closest_key = self._find_closest_key(key)
- if not silent_on_error:
- print('** Error looking up your element using the key: ', key, 'The closest matching key: ', closest_key)
- _error_popup_with_traceback('Key Error', 'Problem finding your key ' + str(key), 'Closest match = ' + str(closest_key), emoji=EMOJI_BASE64_KEY)
- element = ErrorElement(key=key)
- else:
- element = None
- if not supress_raise:
- raise KeyError(key)
-
- if key_error:
- if not supress_guessing and closest_key is not None:
- element = self.AllKeysDict[closest_key]
-
- return element
-
- Element = find_element # Shortcut function
- Find = find_element # Shortcut function, most likely not used by many people.
- Elem = find_element # NEW for 2019! More laziness... Another shortcut
-
- def find_element_with_focus(self):
- """
- Returns the Element that currently has focus as reported by tkinter. If no element is found None is returned!
- :return: An Element if one has been found with focus or None if no element found
- :rtype: Element | None
- """
- element = _FindElementWithFocusInSubForm(self)
- return element
-
- def widget_to_element(self, widget):
- """
- Returns the element that matches a supplied tkinter widget.
- If no matching element is found, then None is returned.
-
-
- :return: Element that uses the specified widget
- :rtype: Element | None
- """
- if self.AllKeysDict is None or len(self.AllKeysDict) == 0:
- return None
- for key, element in self.AllKeysDict.items():
- if element.Widget == widget:
- return element
- return None
-
- def _BuildKeyDict(self):
- """
- Used internally only! Not user callable
- Builds a dictionary containing all elements with keys for this window.
- """
- dict = {}
- self.AllKeysDict = self._BuildKeyDictForWindow(self, self, dict)
-
- def _BuildKeyDictForWindow(self, top_window, window, key_dict):
- """
- Loop through all Rows and all Container Elements for this window and create the keys for all of them.
- Note that the calls are recursive as all pathes must be walked
-
- :param top_window: The highest level of the window
- :type top_window: (Window)
- :param window: The "sub-window" (container element) to be searched
- :type window: Column | Frame | TabGroup | Pane | Tab
- :param key_dict: The dictionary as it currently stands.... used as part of recursive call
- :type key_dict:
- :return: (dict) Dictionary filled with all keys in the window
- :rtype:
- """
- for row_num, row in enumerate(window.Rows):
- for col_num, element in enumerate(row):
- if element.Type == ELEM_TYPE_COLUMN:
- key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
- if element.Type == ELEM_TYPE_FRAME:
- key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
- if element.Type == ELEM_TYPE_TAB_GROUP:
- key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
- if element.Type == ELEM_TYPE_PANE:
- key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
- if element.Type == ELEM_TYPE_TAB:
- key_dict = self._BuildKeyDictForWindow(top_window, element, key_dict)
- if element.Key is None: # if no key has been assigned.... create one for input elements
- if element.Type == ELEM_TYPE_BUTTON:
- element.Key = element.ButtonText
- elif element.Type == ELEM_TYPE_TAB:
- element.Key = element.Title
- if element.Type in (ELEM_TYPE_MENUBAR, ELEM_TYPE_BUTTONMENU,
- ELEM_TYPE_INPUT_SLIDER, ELEM_TYPE_GRAPH, ELEM_TYPE_IMAGE,
- ELEM_TYPE_INPUT_CHECKBOX, ELEM_TYPE_INPUT_LISTBOX, ELEM_TYPE_INPUT_COMBO,
- ELEM_TYPE_INPUT_MULTILINE, ELEM_TYPE_INPUT_OPTION_MENU, ELEM_TYPE_INPUT_SPIN,
- ELEM_TYPE_INPUT_RADIO, ELEM_TYPE_INPUT_TEXT, ELEM_TYPE_PROGRESS_BAR,
- ELEM_TYPE_TABLE, ELEM_TYPE_TREE,
- ELEM_TYPE_TAB_GROUP, ELEM_TYPE_SEPARATOR):
- element.Key = top_window.DictionaryKeyCounter
- top_window.DictionaryKeyCounter += 1
- if element.Key is not None:
- if element.Key in key_dict.keys():
- if element.Type == ELEM_TYPE_BUTTON and WARN_DUPLICATE_BUTTON_KEY_ERRORS: # for Buttons see if should complain
- warnings.warn('*** Duplicate key found in your layout {} ***'.format(element.Key), UserWarning)
- warnings.warn('*** Replaced new key with {} ***'.format(str(element.Key) + str(self.UniqueKeyCounter)))
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('Duplicate key found in your layout', 'Dupliate key: {}'.format(element.Key),
- 'Is being replaced with: {}'.format(str(element.Key) + str(self.UniqueKeyCounter)),
- 'The line of code above shows you which layout, but does not tell you exactly where the element was defined',
- 'The element type is {}'.format(element.Type))
- element.Key = str(element.Key) + str(self.UniqueKeyCounter)
- self.UniqueKeyCounter += 1
- key_dict[element.Key] = element
- return key_dict
-
- def element_list(self):
- """
- Returns a list of all elements in the window
-
- :return: List of all elements in the window and container elements in the window
- :rtype: List[Element]
- """
- return self._build_element_list()
-
- def _build_element_list(self):
- """
- Used internally only! Not user callable
- Builds a dictionary containing all elements with keys for this window.
- """
- elem_list = []
- elem_list = self._build_element_list_for_form(self, self, elem_list)
- return elem_list
-
- def _build_element_list_for_form(self, top_window, window, elem_list):
- """
- Loop through all Rows and all Container Elements for this window and create a list
- Note that the calls are recursive as all pathes must be walked
-
- :param top_window: The highest level of the window
- :type top_window: (Window)
- :param window: The "sub-window" (container element) to be searched
- :type window: Column | Frame | TabGroup | Pane | Tab
- :param elem_list: The element list as it currently stands.... used as part of recursive call
- :type elem_list: ???
- :return: List of all elements in this sub-window
- :rtype: List[Element]
- """
- for row_num, row in enumerate(window.Rows):
- for col_num, element in enumerate(row):
- elem_list.append(element)
- if element.Type in (ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME, ELEM_TYPE_TAB_GROUP, ELEM_TYPE_PANE, ELEM_TYPE_TAB):
- elem_list = self._build_element_list_for_form(top_window, element, elem_list)
- return elem_list
-
-
- def settings_save(self, values):
- """
- Saves settings to settings file using the values dictionary that is passed in.
- If all of the values in the dictionary are None, then it will not be saved
- :param values: Dictionary of values to potentially save
- :type values: (Dict)
- """
- if values is None: # sometimes users may accidently pass in None, so just ignore it
- return
- # if all values in the value dictionary are None, then assume the windows was closed
- # and no values should be saved
- if all(v is None for v in values.values()):
- return
-
- for key, value in values.items():
- try:
- element = self.find_element(key)
- if element.setting is not None:
- user_settings_set_entry(key, value)
- except Exception as e:
- _error_popup_with_traceback('Error saving settings', e)
-
- def settings_restore(self):
- """
- Reads settings and sets the window's Elements to those values.
-
- TODO - NOTE - may have trouble on some elements due to how update calls work
-
- """
- for key in self.key_dict.keys():
- try:
- element = self.find_element(key)
- if element.setting is not None:
- value = user_settings_get_entry(key, '')
- element.update(value)
- except Exception as e:
- _error_popup_with_traceback('Error restoring settings', e)
-
-
- def save_to_disk(self, filename):
- """
- Saves the values contained in each of the input areas of the form. Basically saves what would be returned from a call to Read. It takes these results and saves them to disk using pickle.
- Note that every element in your layout that is to be saved must have a key assigned to it.
-
- :param filename: Filename to save the values to in pickled form
- :type filename: str
- """
- try:
- event, values = _BuildResults(self, False, self)
- remove_these = []
- for key in values:
- if self.Element(key).Type == ELEM_TYPE_BUTTON:
- remove_these.append(key)
- for key in remove_these:
- del values[key]
- with open(filename, 'wb') as sf:
- pickle.dump(values, sf)
- except:
- print('*** Error saving Window contents to disk ***')
-
- def load_from_disk(self, filename):
- """
- Restore values from a previous call to SaveToDisk which saves the returned values dictionary in Pickle format
-
- :param filename: Pickle Filename to load
- :type filename: (str)
- """
- try:
- with open(filename, 'rb') as df:
- self.Fill(pickle.load(df))
- except:
- print('*** Error loading form to disk ***')
-
- def get_screen_dimensions(self):
- """
- Get the screen dimensions. NOTE - you must have a window already open for this to work (blame tkinter not me)
-
- :return: Tuple containing width and height of screen in pixels
- :rtype: Tuple[None, None] | Tuple[width, height]
- """
-
- if self.TKrootDestroyed or self.TKroot is None:
- return Window.get_screen_size()
- screen_width = self.TKroot.winfo_screenwidth() # get window info to move to middle of screen
- screen_height = self.TKroot.winfo_screenheight()
- return screen_width, screen_height
-
- def move(self, x, y):
- """
- Move the upper left corner of this window to the x,y coordinates provided
- :param x: x coordinate in pixels
- :type x: (int)
- :param y: y coordinate in pixels
- :type y: (int)
- """
- try:
- self.TKroot.geometry("+%s+%s" % (x, y))
- self.config_last_location = (int(x), (int(y)))
-
- except:
- pass
-
- def move_to_center(self):
- """
- Recenter your window after it's been moved or the size changed.
-
- This is a conveinence method. There are no tkinter calls involved, only pure PySimpleGUI API calls.
- """
- if not self._is_window_created('tried Window.move_to_center'):
- return
- screen_width, screen_height = self.get_screen_dimensions()
- win_width, win_height = self.size
- x, y = (screen_width - win_width) // 2, (screen_height - win_height) // 2
- self.move(x, y)
-
- def minimize(self):
- """
- Minimize this window to the task bar
- """
- if not self._is_window_created('tried Window.minimize'):
- return
- if self.use_custom_titlebar is True:
- self._custom_titlebar_minimize()
- else:
- self.TKroot.iconify()
- self.maximized = False
-
- def maximize(self):
- """
- Maximize the window. This is done differently on a windows system versus a linux or mac one. For non-Windows
- the root attribute '-fullscreen' is set to True. For Windows the "root" state is changed to "zoomed"
- The reason for the difference is the title bar is removed in some cases when using fullscreen option
- """
-
- if not self._is_window_created('tried Window.maximize'):
- return
- if not running_linux():
- self.TKroot.state('zoomed')
- else:
- self.TKroot.attributes('-fullscreen', True)
- # this method removes the titlebar too
- # self.TKroot.attributes('-fullscreen', True)
- self.maximized = True
-
- def normal(self):
- """
- Restore a window to a non-maximized state. Does different things depending on platform. See Maximize for more.
- """
- if not self._is_window_created('tried Window.normal'):
- return
- if self.use_custom_titlebar:
- self._custom_titlebar_restore()
- else:
- if self.TKroot.state() == 'iconic':
- self.TKroot.deiconify()
- else:
- if not running_linux():
- self.TKroot.state('normal')
- else:
- self.TKroot.attributes('-fullscreen', False)
- self.maximized = False
-
- def _StartMoveUsingControlKey(self, event):
- """
- Used by "Grab Anywhere" style windows. This function is bound to mouse-down. It marks the beginning of a drag.
- :param event: event information passed in by tkinter. Contains x,y position of mouse
- :type event: (event)
- """
- self._start_move_save_offset(event)
- return
-
-
- def _StartMoveGrabAnywhere(self, event):
-
- """
- Used by "Grab Anywhere" style windows. This function is bound to mouse-down. It marks the beginning of a drag.
- :param event: event information passed in by tkinter. Contains x,y position of mouse
- :type event: (event)
- """
- if (isinstance(event.widget, GRAB_ANYWHERE_IGNORE_THESE_WIDGETS) or event.widget in self._grab_anywhere_ignore_these_list) and event.widget not in self._grab_anywhere_include_these_list:
- # print('Found widget to ignore in grab anywhere...')
- return
- self._start_move_save_offset(event)
-
- def _StartMove(self, event):
- self._start_move_save_offset(event)
- return
-
- def _StopMove(self, event):
- """
- Used by "Grab Anywhere" style windows. This function is bound to mouse-up. It marks the ending of a drag.
- Sets the position of the window to this final x,y coordinates
- :param event: event information passed in by tkinter. Contains x,y position of mouse
- :type event: (event)
- """
- return
-
- def _start_move_save_offset(self, event):
- self._mousex = event.x + event.widget.winfo_rootx()
- self._mousey = event.y + event.widget.winfo_rooty()
- geometry = self.TKroot.geometry()
- location = geometry[geometry.find('+') + 1:].split('+')
- self._startx = int(location[0])
- self._starty = int(location[1])
- self._mouse_offset_x = self._mousex - self._startx
- self._mouse_offset_y = self._mousey - self._starty
- # ------ Move All Windows code ------
- if Window._move_all_windows:
- # print('Moving all')
- for win in Window._active_windows:
- if win == self:
- continue
- geometry = win.TKroot.geometry()
- location = geometry[geometry.find('+') + 1:].split('+')
- _startx = int(location[0])
- _starty = int(location[1])
- win._mouse_offset_x = event.x_root - _startx
- win._mouse_offset_y = event.y_root - _starty
-
-
- def _OnMotionUsingControlKey(self, event):
- self._OnMotion(event)
-
-
- def _OnMotionGrabAnywhere(self, event):
-
- """
- Used by "Grab Anywhere" style windows. This function is bound to mouse motion. It actually moves the window
- :param event: event information passed in by tkinter. Contains x,y position of mouse
- :type event: (event)
- """
- if (isinstance(event.widget, GRAB_ANYWHERE_IGNORE_THESE_WIDGETS) or event.widget in self._grab_anywhere_ignore_these_list) and event.widget not in self._grab_anywhere_include_these_list:
- # print('Found widget to ignore in grab anywhere...')
- return
-
- self._OnMotion(event)
-
-
- def _OnMotion(self, event):
-
- self.TKroot.geometry(f"+{event.x_root-self._mouse_offset_x}+{event.y_root-self._mouse_offset_y}")
- # print(f"+{event.x_root}+{event.y_root}")
- # ------ Move All Windows code ------
- try:
- if Window._move_all_windows:
- for win in Window._active_windows:
- if win == self:
- continue
- win.TKroot.geometry(f"+{event.x_root-win._mouse_offset_x}+{event.y_root-win._mouse_offset_y}")
- except Exception as e:
- print('on motion error', e)
-
- def _focus_callback(self, event):
- print('Focus event = {} window = {}'.format(event, self.Title))
-
- def _config_callback(self, event):
- """
- Called when a config event happens for the window
-
- :param event: From tkinter and is not used
- :type event: Any
- """
- # do the location auto-save stuff. If the location changes, then the location is written to the settings file
- if self.auto_save_location:
- try:
- cur_location = self.current_location()
- old_location = self._last_location
- if None not in cur_location:
- self._last_location= cur_location
- if old_location != cur_location:
- self._auto_save_location()
- except Exception as e:
- pass
-
- if self.enable_window_config_events is True:
- self.LastButtonClicked = WINDOW_CONFIG_EVENT
- self.FormRemainedOpen = True
- self.user_bind_event = event
- _exit_mainloop(self)
-
- def _move_callback(self, event):
- """
- Called when a control + arrow key is pressed.
- This is a built-in window positioning key sequence
-
- :param event: From tkinter and is not used
- :type event: Any
- """
- if not self._is_window_created('Tried to move window using arrow keys'):
- return
- x,y = self.current_location()
- if event.keysym == 'Up':
- self.move(x, y-1)
- elif event.keysym == 'Down':
- self.move(x, y+1)
- elif event.keysym == 'Left':
- self.move(x-1, y)
- elif event.keysym == 'Right':
- self.move(x+1, y)
-
- """
- def _config_callback(self, event):
- new_x = event.x
- new_y = event.y
-
-
- if self.not_completed_initial_movement:
- if self.starting_window_position != (new_x, new_y):
- return
- self.not_completed_initial_movement = False
- return
-
- if not self.saw_00:
- if new_x == 0 and new_y == 0:
- self.saw_00 = True
-
- # self.config_count += 1
- # if self.config_count < 40:
- # return
-
- print('Move LOGIC')
-
- if self.config_last_size != (event.width, event.height):
- self.config_last_size = (event.width, event.height)
-
- if self.config_last_location[0] != new_x or self.config_last_location[1] != new_y:
- if self.config_last_location == (None, None):
- self.config_last_location = (new_x, new_y)
- return
-
- deltax = self.config_last_location[0] - event.x
- deltay = self.config_last_location[1] - event.y
- if deltax == 0 and deltay == 0:
- print('not moving so returning')
- return
- if Window._move_all_windows:
- print('checking all windows')
- for window in Window._active_windows:
- if window == self:
- continue
- x = window.TKroot.winfo_x() + deltax
- y = window.TKroot.winfo_y() + deltay
- # window.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window
- # window.config_last_location = (x,y)
- """
-
- def _KeyboardCallback(self, event):
- """
- Window keyboard callback. Called by tkinter. Will kick user out of the tkinter event loop. Should only be
- called if user has requested window level keyboard events
-
- :param event: object provided by tkinter that contains the key information
- :type event: (event)
- """
- self.LastButtonClicked = None
- self.FormRemainedOpen = True
- if event.char != '':
- self.LastKeyboardEvent = event.char
- else:
- self.LastKeyboardEvent = str(event.keysym) + ':' + str(event.keycode)
- # if not self.NonBlocking:
- # _BuildResults(self, False, self)
- _exit_mainloop(self)
-
- def _MouseWheelCallback(self, event):
- """
- Called by tkinter when a mouse wheel event has happened. Only called if keyboard events for the window
- have been enabled
-
- :param event: object sent in by tkinter that has the wheel direction
- :type event: (event)
- """
- self.LastButtonClicked = None
- self.FormRemainedOpen = True
- self.LastKeyboardEvent = 'MouseWheel:Down' if event.delta < 0 or event.num == 5 else 'MouseWheel:Up'
- # if not self.NonBlocking:
- # _BuildResults(self, False, self)
- _exit_mainloop(self)
-
- @property
- def right_click_menu_element(self):
- """
- The element that produced a right click meny event (if one did). If can't find the element, None is returned.
- :return: Element that generated a right click menu event. If one can't be found, then None is returned
- :rtype: (Element | None)
- """
- return self._right_click_menu_element
-
-
- def _Close(self, without_event=False):
- """
- The internal close call that does the real work of building. This method basically sets up for closing
- but doesn't destroy the window like the User's version of Close does
-
- :parm without_event: if True, then do not cause an event to be generated, "silently" close the window
- :type without_event: (bool)
- """
-
- try:
- self.TKroot.update()
- except:
- pass
-
- if not self.NonBlocking or not without_event:
- _BuildResults(self, False, self)
- if self.TKrootDestroyed:
- return
- self.TKrootDestroyed = True
- self.RootNeedsDestroying = True
- return
-
- def close(self):
- """
- Closes window. Users can safely call even if window has been destroyed. Should always call when done with
- a window so that resources are properly freed up within your thread.
- """
- self._auto_save_location()
-
- try:
- del Window._active_windows[self] # will only be in the list if window was explicitly finalized
- except:
- pass
-
- try:
- self.TKroot.update() # On Linux must call update if the user closed with X or else won't actually close the window
- except:
- pass
-
- self._restore_stdout()
- self._restore_stderr()
-
- _TimerPeriodic.stop_all_timers_for_window(self)
-
- if self.TKrootDestroyed:
- return
- try:
- self.TKroot.destroy()
- self.TKroot.update()
- Window._DecrementOpenCount()
- except:
- pass
- # if down to 1 window, try and destroy the hidden window, if there is one
- # if Window.NumOpenWindows == 1:
- # try:
- # Window.hidden_master_root.destroy()
- # Window.NumOpenWindows = 0 # if no hidden window, then this won't execute
- # except:
- # pass
- self.TKrootDestroyed = True
-
- # Free up anything that was held in the layout and the root variables
- self.Rows = None
- self.TKroot = None
-
- def is_closed(self, quick_check=None):
- """
- Returns True is the window is maybe closed. Can be difficult to tell sometimes
- NOTE - the call to TKroot.update was taking over 500 ms sometimes so added a flag to bypass the lengthy call.
- :param quick_quick: If True, then don't use the root.update call, only check the flags
- :type quick_check: bool
- :return: True if the window was closed or destroyed
- :rtype: (bool)
- """
-
- if self.TKrootDestroyed or self.TKroot is None:
- return True
-
- # if performing a quick check only, then skip calling tkinter for performance reasons
- if quick_check is True:
- return False
-
- # see if can do an update... if not, then it's been destroyed
- try:
- rc = self.TKroot.update()
- except:
- return True
- return False
-
- def _auto_save_location(self):
- """
- Internal function to save the location of the window in the settings file
- :return:
- """
- if self.auto_save_location:
- user_settings_set_entry('-LAST WINDOW LOCATION-'+self.Title, self._last_location)
-
-
-
- # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
- def _OnClosingCallback(self):
- """
- Internally used method ONLY. Not sure callable. tkinter calls this when the window is closed by clicking X
- """
- # global _my_windows
- # print('Got closing callback', self.DisableClose)
- if self.DisableClose:
- return
- self._auto_save_location()
- if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
- _exit_mainloop(self)
- if self.close_destroys_window:
- self.TKroot.destroy() # destroy this window
- self.TKrootDestroyed = True
- self.XFound = True
- else:
- self.LastButtonClicked = WINDOW_CLOSE_ATTEMPTED_EVENT
- elif Window._root_running_mainloop == Window.hidden_master_root:
- _exit_mainloop(self)
- else:
- if self.close_destroys_window:
- self.TKroot.destroy() # destroy this window
- self.XFound = True
- else:
- self.LastButtonClicked = WINDOW_CLOSE_ATTEMPTED_EVENT
- if self.close_destroys_window:
- self.RootNeedsDestroying = True
- self._restore_stdout()
- self._restore_stderr()
-
- def disable(self):
- """
- Disables window from taking any input from the user
- """
- if not self._is_window_created('tried Window.disable'):
- return
- self.TKroot.attributes('-disabled', 1)
- # self.TKroot.grab_set_global()
-
- def enable(self):
- """
- Re-enables window to take user input after having it be Disabled previously
- """
- if not self._is_window_created('tried Window.enable'):
- return
- self.TKroot.attributes('-disabled', 0)
- # self.TKroot.grab_release()
-
- def hide(self):
- """
- Hides the window from the screen and the task bar
- """
- if not self._is_window_created('tried Window.hide'):
- return
- self._Hidden = True
- self.TKroot.withdraw()
-
- def un_hide(self):
- """
- Used to bring back a window that was previously hidden using the Hide method
- """
- if not self._is_window_created('tried Window.un_hide'):
- return
- if self._Hidden:
- self.TKroot.deiconify()
- self._Hidden = False
-
- def is_hidden(self):
- """
- Returns True if the window is currently hidden
- :return: Returns True if the window is currently hidden
- :rtype: bool
- """
- return self._Hidden
-
- def disappear(self):
- """
- Causes a window to "disappear" from the screen, but remain on the taskbar. It does this by turning the alpha
- channel to 0. NOTE that on some platforms alpha is not supported. The window will remain showing on these
- platforms. The Raspberry Pi for example does not have an alpha setting
- """
- if not self._is_window_created('tried Window.disappear'):
- return
- self.TKroot.attributes('-alpha', 0)
-
- def reappear(self):
- """
- Causes a window previously made to "Disappear" (using that method). Does this by restoring the alpha channel
- """
- if not self._is_window_created('tried Window.reappear'):
- return
- self.TKroot.attributes('-alpha', 255)
-
- def set_alpha(self, alpha):
- """
- Sets the Alpha Channel for a window. Values are between 0 and 1 where 0 is completely transparent
-
- :param alpha: 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through)
- :type alpha: (float)
- """
- if not self._is_window_created('tried Window.set_alpha'):
- return
- self._AlphaChannel = alpha
- self.TKroot.attributes('-alpha', alpha)
-
- @property
- def alpha_channel(self):
- """
- A property that changes the current alpha channel value (internal value)
- :return: the current alpha channel setting according to self, not read directly from tkinter
- :rtype: (float)
- """
- return self._AlphaChannel
-
- @alpha_channel.setter
- def alpha_channel(self, alpha):
- """
- The setter method for this "property".
- Planning on depricating so that a Set call is always used by users. This is more in line with the SDK
- :param alpha: 0 to 1. 0 is completely transparent. 1 is completely visible and solid (can't see through)
- :type alpha: (float)
- """
- if not self._is_window_created('tried Window.alpha_channel'):
- return
- self._AlphaChannel = alpha
- self.TKroot.attributes('-alpha', alpha)
-
- def bring_to_front(self):
- """
- Brings this window to the top of all other windows (perhaps may not be brought before a window made to "stay
- on top")
- """
- if not self._is_window_created('tried Window.bring_to_front'):
- return
- if running_windows():
- try:
- self.TKroot.wm_attributes("-topmost", 0)
- self.TKroot.wm_attributes("-topmost", 1)
- if not self.KeepOnTop:
- self.TKroot.wm_attributes("-topmost", 0)
- except Exception as e:
- warnings.warn('Problem in Window.bring_to_front' + str(e), UserWarning)
- else:
- try:
- self.TKroot.lift()
- except:
- pass
-
- def send_to_back(self):
- """
- Pushes this window to the bottom of the stack of windows. It is the opposite of BringToFront
- """
- if not self._is_window_created('tried Window.send_to_back'):
- return
- try:
- self.TKroot.lower()
- except:
- pass
-
- def keep_on_top_set(self):
- """
- Sets keep_on_top after a window has been created. Effect is the same
- as if the window was created with this set. The Window is also brought
- to the front
- """
- if not self._is_window_created('tried Window.keep_on_top_set'):
- return
- self.KeepOnTop = True
- self.bring_to_front()
- try:
- self.TKroot.wm_attributes("-topmost", 1)
- except Exception as e:
- warnings.warn('Problem in Window.keep_on_top_set trying to set wm_attributes topmost' + str(e), UserWarning)
-
- def keep_on_top_clear(self):
- """
- Clears keep_on_top after a window has been created. Effect is the same
- as if the window was created with this set.
- """
- if not self._is_window_created('tried Window.keep_on_top_clear'):
- return
- self.KeepOnTop = False
- try:
- self.TKroot.wm_attributes("-topmost", 0)
- except Exception as e:
- warnings.warn('Problem in Window.keep_on_top_clear trying to clear wm_attributes topmost' + str(e), UserWarning)
-
- def current_location(self, more_accurate=False, without_titlebar=False):
- """
- Get the current location of the window's top left corner.
- Sometimes, depending on the environment, the value returned does not include the titlebar,etc
- A new option, more_accurate, can be used to get the theoretical upper leftmost corner of the window.
- The titlebar and menubar are crated by the OS. It gets really confusing when running in a webpage (repl, trinket)
- Thus, the values can appear top be "off" due to the sometimes unpredictable way the location is calculated.
- If without_titlebar is set then the location of the root x,y is used which should not include the titlebar but
- may be OS dependent.
-
- :param more_accurate: If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account
- :type more_accurate: (bool)
- :param without_titlebar: If True, return location of top left of main window area without the titlebar (may be OS dependent?)
- :type without_titlebar: (bool)
- :return: The x and y location in tuple form (x,y)
- :rtype: Tuple[(int | None), (int | None)]
- """
-
- if not self._is_window_created('tried Window.current_location'):
- return (None, None)
- try:
- if without_titlebar is True:
- x, y = self.TKroot.winfo_rootx(), self.TKroot.winfo_rooty()
- elif more_accurate:
- geometry = self.TKroot.geometry()
- location = geometry[geometry.find('+') + 1:].split('+')
- x, y = int(location[0]), int(location[1])
- else:
- x, y = int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y())
- except Exception as e:
- warnings.warn('Error in Window.current_location. Trouble getting x,y location\n' + str(e), UserWarning)
- x, y = (None, None)
- return (x,y)
-
- def current_size_accurate(self):
- """
- Get the current location of the window based on tkinter's geometry setting
-
- :return: The x and y size in tuple form (x,y)
- :rtype: Tuple[(int | None), (int | None)]
- """
-
- if not self._is_window_created('tried Window.current_location'):
- return (None, None)
- try:
- geometry = self.TKroot.geometry()
- geometry_tuple = geometry.split('+')
- window_size = geometry_tuple[0].split('x')
- x, y = int(window_size[0]), int(window_size[1])
- except Exception as e:
- warnings.warn('Error in Window.current_size_accurate. Trouble getting x,y size\n{} {}'.format(geometry, geometry_tuple) + str(e), UserWarning)
- x, y = (None, None)
- return (x,y)
-
- @property
- def size(self):
- """
- Return the current size of the window in pixels
-
- :return: (width, height) of the window
- :rtype: Tuple[(int), (int)] or Tuple[None, None]
- """
- if not self._is_window_created('Tried to use Window.size property'):
- return (None, None)
- win_width = self.TKroot.winfo_width()
- win_height = self.TKroot.winfo_height()
- return win_width, win_height
-
- @size.setter
- def size(self, size):
- """
- Changes the size of the window, if possible
-
- :param size: (width, height) of the desired window size
- :type size: (int, int)
- """
- try:
- self.TKroot.geometry("%sx%s" % (size[0], size[1]))
- self.TKroot.update_idletasks()
- except:
- pass
-
- def set_size(self, size):
- """
- Changes the size of the window, if possible. You can also use the Window.size prooerty
- to set/get the size.
-
- :param size: (width, height) of the desired window size
- :type size: (int, int)
- """
- if not self._is_window_created('Tried to change the size of the window prior to creation.'):
- return
- try:
- self.TKroot.geometry("%sx%s" % (size[0], size[1]))
- self.TKroot.update_idletasks()
- except:
- pass
-
- def set_min_size(self, size):
- """
- Changes the minimum size of the window. Note Window must be read or finalized first.
-
- :param size: (width, height) tuple (int, int) of the desired window size in pixels
- :type size: (int, int)
- """
- if not self._is_window_created('tried Window.set_min_size'):
- return
- self.TKroot.minsize(size[0], size[1])
- self.TKroot.update_idletasks()
-
- def set_resizable(self, x_axis_enable, y_axis_enable):
- """
- Changes if a window can be resized in either the X or the Y direction.
- Note Window must be read or finalized first.
-
- :param x_axis_enable: If True, the window can be changed in the X-axis direction. If False, it cannot
- :type x_axis_enable: (bool)
- :param y_axis_enable: If True, the window can be changed in the Y-axis direction. If False, it cannot
- :type y_axis_enable: (bool)
- """
-
- if not self._is_window_created('tried Window.set_resixable'):
- return
- try:
- self.TKroot.resizable(x_axis_enable, y_axis_enable)
- except Exception as e:
- _error_popup_with_traceback('Window.set_resizable - tkinter reported error', e)
-
- def visibility_changed(self):
- """
- When making an element in a column or someplace that has a scrollbar, then you'll want to call this function
- prior to the column's contents_changed() method.
- """
- self.refresh()
-
- def set_transparent_color(self, color):
- """
- Set the color that will be transparent in your window. Areas with this color will be SEE THROUGH.
-
- :param color: Color string that defines the transparent color
- :type color: (str)
- """
- if not self._is_window_created('tried Window.set_transparent_color'):
- return
- try:
- self.TKroot.attributes('-transparentcolor', color)
- self.TransparentColor = color
- except:
- print('Transparent color not supported on this platform (windows only)')
-
- def mouse_location(self):
- """
- Return the (x,y) location of the mouse relative to the entire screen. It's the same location that
- you would use to create a window, popup, etc.
-
- :return: The location of the mouse pointer
- :rtype: (int, int)
- """
- if not self._is_window_created('tried Window.mouse_location'):
- return (0, 0)
-
- return (self.TKroot.winfo_pointerx(), self.TKroot.winfo_pointery())
-
- def grab_any_where_on(self):
- """
- Turns on Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
- been Finalized or Read.
- """
- if not self._is_window_created('tried Window.grab_any_where_on'):
- return
- self.TKroot.bind("", self._StartMoveGrabAnywhere)
- self.TKroot.bind("", self._StopMove)
- self.TKroot.bind("", self._OnMotionGrabAnywhere)
-
- def grab_any_where_off(self):
- """
- Turns off Grab Anywhere functionality AFTER a window has been created. Don't try on a window that's not yet
- been Finalized or Read.
- """
- if not self._is_window_created('tried Window.grab_any_where_off'):
- return
- self.TKroot.unbind("")
- self.TKroot.unbind("")
- self.TKroot.unbind("")
-
- def _user_bind_callback(self, bind_string, event, propagate=True):
- """
- Used when user binds a tkinter event directly to an element
-
- :param bind_string: The event that was bound so can lookup the key modifier
- :type bind_string: (str)
- :param event: Event data passed in by tkinter (not used)
- :type event:
- :param propagate: If True then tkinter will be told to propagate the event
- :type propagate: (bool)
- """
- # print('bind callback', bind_string, event)
- key = self.user_bind_dict.get(bind_string, '')
- self.user_bind_event = event
- if key is not None:
- self.LastButtonClicked = key
- else:
- self.LastButtonClicked = bind_string
- self.FormRemainedOpen = True
- # if self.CurrentlyRunningMainloop:
- # self.TKroot.quit()
- _exit_mainloop(self)
- return 'break' if propagate is not True else None
-
- def bind(self, bind_string, key, propagate=True):
- """
- Used to add tkinter events to a Window.
- The tkinter specific data is in the Window's member variable user_bind_event
- :param bind_string: The string tkinter expected in its bind function
- :type bind_string: (str)
- :param key: The event that will be generated when the tkinter event occurs
- :type key: str | int | tuple | object
- :param propagate: If True then tkinter will be told to propagate the event
- :type propagate: (bool)
- """
- if not self._is_window_created('tried Window.bind'):
- return
- try:
- self.TKroot.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt, propagate))
- except Exception as e:
- self.TKroot.unbind_all(bind_string)
- return
- # _error_popup_with_traceback('Window.bind error', e)
- self.user_bind_dict[bind_string] = key
-
- def unbind(self, bind_string):
- """
- Used to remove tkinter events to a Window.
- This implementation removes ALL of the binds of the bind_string from the Window. If there
- are multiple binds for the Window itself, they will all be removed. This can be extended later if there
- is a need.
- :param bind_string: The string tkinter expected in its bind function
- :type bind_string: (str)
- """
- if not self._is_window_created('tried Window.unbind'):
- return
- self.TKroot.unbind(bind_string)
-
- def _callback_main_debugger_window_create_keystroke(self, event):
- """
- Called when user presses the key that creates the main debugger window
- March 2022 - now causes the user reads to return timeout events automatically
- :param event: (event) not used. Passed in event info
- :type event:
- """
- Window._main_debug_window_build_needed = True
- # exit the event loop in a way that resembles a timeout occurring
- self.LastButtonClicked = self.TimeoutKey
- self.FormRemainedOpen = True
- self.TKroot.quit() # kick the users out of the mainloop
-
- def _callback_popout_window_create_keystroke(self, event):
- """
- Called when user presses the key that creates the floating debugger window
- March 2022 - now causes the user reads to return timeout events automatically
- :param event: (event) not used. Passed in event info
- :type event:
- """
- Window._floating_debug_window_build_needed = True
- # exit the event loop in a way that resembles a timeout occurring
- self.LastButtonClicked = self.TimeoutKey
- self.FormRemainedOpen = True
- self.TKroot.quit() # kick the users out of the mainloop
-
- def enable_debugger(self):
- """
- Enables the internal debugger. By default, the debugger IS enabled
- """
- if not self._is_window_created('tried Window.enable_debugger'):
- return
- self.TKroot.bind('', self._callback_main_debugger_window_create_keystroke)
- self.TKroot.bind('', self._callback_popout_window_create_keystroke)
- self.DebuggerEnabled = True
-
- def disable_debugger(self):
- """
- Disable the internal debugger. By default the debugger is ENABLED
- """
- if not self._is_window_created('tried Window.disable_debugger'):
- return
- self.TKroot.unbind("")
- self.TKroot.unbind("")
- self.DebuggerEnabled = False
-
- def set_title(self, title):
- """
- Change the title of the window
-
- :param title: The string to set the title to
- :type title: (str)
- """
- if not self._is_window_created('tried Window.set_title'):
- return
- if self._has_custom_titlebar:
- try: # just in case something goes badly, don't crash
- self.find_element(TITLEBAR_TEXT_KEY).update(title)
- except:
- pass
- # even with custom titlebar, set the main window's title too so it'll match when minimized
- self.TKroot.wm_title(str(title))
-
- def make_modal(self):
- """
- Makes a window into a "Modal Window"
- This means user will not be able to interact with other windows until this one is closed
-
- NOTE - Sorry Mac users - you can't have modal windows.... lobby your tkinter Mac devs
- """
- if not self._is_window_created('tried Window.make_modal'):
- return
-
- if running_mac() and ENABLE_MAC_MODAL_DISABLE_PATCH:
- return
-
- # if modal windows have been disabled globally
- if not DEFAULT_MODAL_WINDOWS_ENABLED and not DEFAULT_MODAL_WINDOWS_FORCED:
- # if not DEFAULT_MODAL_WINDOWS_ENABLED:
- return
-
- try:
- self.TKroot.transient()
- self.TKroot.grab_set()
- self.TKroot.focus_force()
- except Exception as e:
- print('Exception trying to make modal', e)
-
- def force_focus(self):
- """
- Forces this window to take focus
- """
- if not self._is_window_created('tried Window.force_focus'):
- return
- self.TKroot.focus_force()
-
- def was_closed(self):
- """
- Returns True if the window was closed
-
- :return: True if the window is closed
- :rtype: bool
- """
- return self.TKrootDestroyed
-
- def set_cursor(self, cursor):
- """
- Sets the cursor for the window.
- If you do not want any mouse pointer, then use the string "none"
-
- :param cursor: The tkinter cursor name
- :type cursor: (str)
- """
-
- if not self._is_window_created('tried Window.set_cursor'):
- return
- try:
- self.TKroot.config(cursor=cursor)
- except Exception as e:
- print('Warning bad cursor specified ', cursor)
- print(e)
-
- def ding(self, display_number=0):
- """
- Make a "bell" sound. A capability provided by tkinter. Your window needs to be finalized prior to calling.
- Ring a display's bell is the tkinter description of the call.
- :param display_number: Passed to tkinter's bell method as parameter "displayof".
- :type display_number: int
- """
- if not self._is_window_created('tried Window.ding'):
- return
- try:
- self.TKroot.bell(display_number)
- except Exception as e:
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('Window.ding() - tkinter reported error from bell() call', e)
-
- def _window_tkvar_changed_callback(self, *args):
- """
- Internal callback function for when the thread
-
- :param event: Information from tkinter about the callback
- :type event:
-
- """
- # print('Thread callback info', threading.current_thread())
- # print(event)
- # trace_details = traceback.format_stack()
- # print(''.join(trace_details))
- # self.thread_lock.acquire()
- # if self.thread_timer:
- # self.TKroot.after_cancel(id=self.thread_timer)
- # self.thread_timer = None
- # self.thread_lock.release()
-
- if self._queued_thread_event_available():
- self.FormRemainedOpen = True
- _exit_mainloop(self)
-
- def _create_thread_queue(self):
- """
- Creates the queue used by threads to communicate with this window
- """
-
- if self.thread_queue is None:
- self.thread_queue = queue.Queue()
-
- if self.thread_lock is None:
- self.thread_lock = threading.Lock()
-
- if self.thread_strvar is None:
- self.thread_strvar = tk.StringVar()
- self.thread_strvar.trace_add("write", self._window_tkvar_changed_callback)
-
- def write_event_value(self, key, value):
- """
- Adds a key & value tuple to the queue that is used by threads to communicate with the window
-
- :param key: The key that will be returned as the event when reading the window
- :type key: Any
- :param value: The value that will be in the values dictionary
- :type value: Any
- """
-
- if self.thread_queue is None:
- print('*** Warning Window.write_event_value - no thread queue found ***')
- return
- # self.thread_lock.acquire() # first lock the critical section
- self.thread_queue.put(item=(key, value))
- self.TKroot.tk.willdispatch() # brilliant bit of code provided by Giuliano who I owe a million thank yous!
- self.thread_strvar.set('new item')
-
- # self.thread_queue.put(item=(key, value))
- # self.thread_strvar.set('new item')
- # March 28 2021 - finally found a solution! It needs a little more work and a lock
- # if no timer is running, then one should be started
- # if self.thread_timer is None:
- # print('Starting a timer')
- # self.thread_timer = self.TKroot.after(1, self._window_tkvar_changed_callback)
- # self.thread_lock.release()
-
- def _queued_thread_event_read(self):
- if self.thread_queue is None:
- return None
-
- try: # see if something has been posted to Queue
- message = self.thread_queue.get_nowait()
- except queue.Empty: # get_nowait() will get exception when Queue is empty
- return None
-
- return message
-
- def _queued_thread_event_available(self):
-
- if self.thread_queue is None:
- return False
- # self.thread_lock.acquire()
- qsize = self.thread_queue.qsize()
- if qsize == 0:
- self.thread_timer = None
- # self.thread_lock.release()
- return qsize != 0
-
- def _RightClickMenuCallback(self, event):
- """
- When a right click menu is specified for an entire window, then this callback catches right clicks
- that happen to the window itself, when there are no elements that are in that area.
-
- The only portion that is not currently covered correctly is the row frame itself. There will still
- be parts of the window, at the moment, that don't respond to a right click. It's getting there, bit
- by bit.
-
- Callback function that's called when a right click happens. Shows right click menu as result.
-
- :param event: information provided by tkinter about the event including x,y location of click
- :type event:
- """
- # if there are widgets under the mouse, then see if it's the root only. If not, then let the widget (element) show their menu instead
- x, y = self.TKroot.winfo_pointerxy()
- widget = self.TKroot.winfo_containing(x, y)
- if widget != self.TKroot:
- return
- self.TKRightClickMenu.tk_popup(event.x_root, event.y_root, 0)
- self.TKRightClickMenu.grab_release()
-
- def save_window_screenshot_to_disk(self, filename=None):
- """
- Saves an image of the PySimpleGUI window provided into the filename provided
-
- :param filename: Optional filename to save screenshot to. If not included, the User Settinds are used to get the filename
- :return: A PIL ImageGrab object that can be saved or manipulated
- :rtype: (PIL.ImageGrab | None)
- """
- global pil_import_attempted, pil_imported, PIL, ImageGrab, Image
-
- if not pil_import_attempted:
- try:
- import PIL as PIL
- from PIL import ImageGrab
- from PIL import Image
- pil_imported = True
- pil_import_attempted = True
- except:
- pil_imported = False
- pil_import_attempted = True
- print('FAILED TO IMPORT PIL!')
- return None
- try:
- # Get location of window to save
- pos = self.current_location()
- # Add a little to the X direction if window has a titlebar
- if not self.NoTitleBar:
- pos = (pos[0] + 7, pos[1])
- # Get size of wiondow
- size = self.current_size_accurate()
- # Get size of the titlebar
- titlebar_height = self.TKroot.winfo_rooty() - self.TKroot.winfo_y()
- # Add titlebar to size of window so that titlebar and window will be saved
- size = (size[0], size[1] + titlebar_height)
- if not self.NoTitleBar:
- size_adjustment = (2, 1)
- else:
- size_adjustment = (0, 0)
- # Make the "Bounding rectangle" used by PLK to do the screen grap "operation
- rect = (pos[0], pos[1], pos[0] + size[0] + size_adjustment[0], pos[1] + size[1] + size_adjustment[1])
- # Grab the image
- grab = ImageGrab.grab(bbox=rect)
- # Save the grabbed image to disk
- except Exception as e:
- # print(e)
- popup_error_with_traceback('Screen capture failure', 'Error happened while trying to save screencapture', e)
-
- return None
- # return grab
- if filename is None:
- folder = pysimplegui_user_settings.get('-screenshots folder-', '')
- filename = pysimplegui_user_settings.get('-screenshots filename-', '')
- full_filename = os.path.join(folder, filename)
- else:
- full_filename = filename
- if full_filename:
- try:
- grab.save(full_filename)
- except Exception as e:
- popup_error_with_traceback('Screen capture failure', 'Error happened while trying to save screencapture', e)
- else:
- popup_error_with_traceback('Screen capture failure', 'You have attempted a screen capture but have not set up a good filename to save to')
- return grab
-
- def start_thread(self, func, end_key=None):
- """
- Call your function that will take a long time to execute. When it's complete, send an event
- specified by the end_key.
-
- Starts a thread on your behalf.
-
- This is a way for you to "ease into" threading without learning the details of threading.
- Your function will run, and when it returns 2 things will happen:
- 1. The value you provide for end_key will be returned to you when you call window.read()
- 2. If your function returns a value, then the value returned will also be included in your windows.read call in the values dictionary
-
- IMPORTANT - This method uses THREADS... this means you CANNOT make any PySimpleGUI calls from
- the function you provide with the exception of one function, Window.write_event_value.
-
- :param func: A lambda or a function name with no parms
- :type func: Any
- :param end_key: Optional key that will be generated when the function returns
- :type end_key: (Any | None)
- :return: The id of the thread
- :rtype: threading.Thread
- """
-
- thread = threading.Thread(target=_long_func_thread, args=(self, end_key, func), daemon=True)
- thread.start()
- return thread
-
- @property
- def key_dict(self):
- """
- Returns a dictionary with all keys and their corresponding elements
- { key : Element }
- :return: Dictionary of keys and elements
- :rtype: Dict[Any, Element]
- """
- return self.AllKeysDict
-
- def key_is_good(self, key):
- """
- Checks to see if this is a good key for this window
- If there's an element with the key provided, then True is returned
- :param key: The key to check
- :type key: str | int | tuple | object
- :return: True if key is an element in this window
- :rtype: bool
- """
- if key in self.key_dict:
- return True
- return False
-
- def get_scaling(self):
- """
- Returns the current scaling value set for this window
-
- :return: Scaling according to tkinter. Returns DEFAULT_SCALING if error
- :rtype: float
- """
-
- if not self._is_window_created('Tried Window.set_scaling'):
- return DEFAULT_SCALING
- try:
- scaling = self.TKroot.tk.call('tk', 'scaling')
- except Exception as e:
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('Window.get_scaling() - tkinter reported error', e)
- scaling = DEFAULT_SCALING
-
- return scaling
-
- def _custom_titlebar_restore_callback(self, event):
- self._custom_titlebar_restore()
-
- def _custom_titlebar_restore(self):
- if running_linux():
- # if self._skip_first_restore_callback:
- # self._skip_first_restore_callback = False
- # return
- self.TKroot.unbind('')
- self.TKroot.deiconify()
-
- # self.ParentForm.TKroot.wm_overrideredirect(True)
- self.TKroot.wm_attributes("-type", 'dock')
-
- else:
- self.TKroot.unbind('')
- self.TKroot.wm_overrideredirect(True)
- if self.TKroot.state() == 'iconic':
- self.TKroot.deiconify()
- else:
- if not running_linux():
- self.TKroot.state('normal')
- else:
- self.TKroot.attributes('-fullscreen', False)
- self.maximized = False
-
- def _custom_titlebar_minimize(self):
- if running_linux():
- self.TKroot.wm_attributes("-type", "normal")
- # self.ParentForm.TKroot.state('icon')
- # return
- # self.ParentForm.maximize()
- self.TKroot.wm_overrideredirect(False)
- # self.ParentForm.minimize()
- # self.ParentForm.TKroot.wm_overrideredirect(False)
- self.TKroot.iconify()
- # self._skip_first_restore_callback = True
- self.TKroot.bind('', self._custom_titlebar_restore_callback)
- else:
- self.TKroot.wm_overrideredirect(False)
- self.TKroot.iconify()
- self.TKroot.bind('', self._custom_titlebar_restore_callback)
-
- def _custom_titlebar_callback(self, key):
- """
- One of the Custom Titlbar buttons was clicked
- :param key:
- :return:
- """
- if key == TITLEBAR_MINIMIZE_KEY:
- if not self.DisableMinimize:
- self._custom_titlebar_minimize()
- elif key == TITLEBAR_MAXIMIZE_KEY:
- if self.Resizable:
- if self.maximized:
- self.normal()
- else:
- self.maximize()
- elif key == TITLEBAR_CLOSE_KEY:
- if not self.DisableClose:
- self._OnClosingCallback()
-
- def timer_start(self, frequency_ms, key=EVENT_TIMER, repeating=True):
- """
- Starts a timer that gnerates Timer Events. The default is to repeat the timer events until timer is stopped.
- You can provide your own key or a default key will be used. The default key is defined
- with the constants EVENT_TIMER or TIMER_KEY. They both equal the same value.
- The values dictionary will contain the timer ID that is returned from this function.
-
- :param frequency_ms: How often to generate timer events in milliseconds
- :type frequency_ms: int
- :param key: Key to be returned as the timer event
- :type key: str | int | tuple | object
- :param repeating: If True then repeat timer events until timer is explicitly stopped
- :type repeating: bool
- :return: Timer ID for the timer
- :rtype: int
- """
- timer = _TimerPeriodic(self, frequency_ms=frequency_ms, key=key, repeating=repeating)
- return timer.id
-
- def timer_stop(self, timer_id):
- """
- Stops a timer with a given ID
-
- :param timer_id: Timer ID of timer to stop
- :type timer_id: int
- :return:
- """
- _TimerPeriodic.stop_timer_with_id(timer_id)
-
- def timer_stop_all(self):
- """
- Stops all timers for THIS window
- """
- _TimerPeriodic.stop_all_timers_for_window(self)
-
- def timer_get_active_timers(self):
- """
- Returns a list of currently active timers for a window
- :return: List of timers for the window
- :rtype: List[int]
- """
- return _TimerPeriodic.get_all_timers_for_window(self)
-
- @classmethod
- def _restore_stdout(cls):
- for item in cls._rerouted_stdout_stack:
- (window, element) = item # type: (Window, Element)
- if not window.is_closed():
- sys.stdout = element
- break
- cls._rerouted_stdout_stack = [item for item in cls._rerouted_stdout_stack if not item[0].is_closed()]
- if len(cls._rerouted_stdout_stack) == 0 and cls._original_stdout is not None:
- sys.stdout = cls._original_stdout
- # print('Restored stdout... new stack:', [item[0].Title for item in cls._rerouted_stdout_stack ])
-
- @classmethod
- def _restore_stderr(cls):
- for item in cls._rerouted_stderr_stack:
- (window, element) = item # type: (Window, Element)
- if not window.is_closed():
- sys.stderr = element
- break
- cls._rerouted_stderr_stack = [item for item in cls._rerouted_stderr_stack if not item[0].is_closed()]
- if len(cls._rerouted_stderr_stack) == 0 and cls._original_stderr is not None:
- sys.stderr = cls._original_stderr
- # print('Restored stderr... new stack:', [item[0].Title for item in cls._rerouted_stderr_stack ])
-
-
- def __getitem__(self, key):
- """
- Returns Element that matches the passed in key.
- This is "called" by writing code as thus:
- window['element key'].update
-
- :param key: The key to find
- :type key: str | int | tuple | object
- :return: The element found
- :rtype: Element | Input | Combo | OptionMenu | Listbox | Radio | Checkbox | Spin | Multiline | Text | StatusBar | Output | Button | ButtonMenu | ProgressBar | Image | Canvas | Graph | Frame | VerticalSeparator | HorizontalSeparator | Tab | TabGroup | Slider | Column | Pane | Menu | Table | Tree | ErrorElement | None
- """
-
- return self.find_element(key)
-
- def __call__(self, *args, **kwargs):
- """
- Call window.read but without having to type it out.
- window() == window.read()
- window(timeout=50) == window.read(timeout=50)
-
- :return: The famous event, values that read returns.
- :rtype: Tuple[Any, Dict[Any, Any]]
- """
- return self.read(*args, **kwargs)
-
- def _is_window_created(self, additional_message=''):
- msg = str(additional_message)
- if self.TKroot is None:
- warnings.warn(
- 'You cannot perform operations on a Window until it is read or finalized. Adding a "finalize=True" parameter to your Window creation will fix this. ' + msg,
- UserWarning)
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('You cannot perform operations on a Window until it is read or finalized.',
- 'Adding a "finalize=True" parameter to your Window creation will likely fix this', msg)
- return False
- return True
-
- def _has_custom_titlebar_element(self):
- for elem in self.AllKeysDict.values():
- if elem.Key in (TITLEBAR_MAXIMIZE_KEY, TITLEBAR_CLOSE_KEY, TITLEBAR_IMAGE_KEY):
- return True
- if elem.metadata == TITLEBAR_METADATA_MARKER:
- return True
- return False
-
- AddRow = add_row
- AddRows = add_rows
- AlphaChannel = alpha_channel
- BringToFront = bring_to_front
- Close = close
- CurrentLocation = current_location
- Disable = disable
- DisableDebugger = disable_debugger
- Disappear = disappear
- Enable = enable
- EnableDebugger = enable_debugger
- Fill = fill
- Finalize = finalize
- # FindElement = find_element
- FindElementWithFocus = find_element_with_focus
- GetScreenDimensions = get_screen_dimensions
- GrabAnyWhereOff = grab_any_where_off
- GrabAnyWhereOn = grab_any_where_on
- Hide = hide
- Layout = layout
- LoadFromDisk = load_from_disk
- Maximize = maximize
- Minimize = minimize
- Move = move
- Normal = normal
- Read = read
- Reappear = reappear
- Refresh = refresh
- SaveToDisk = save_to_disk
- SendToBack = send_to_back
- SetAlpha = set_alpha
- SetIcon = set_icon
- SetTransparentColor = set_transparent_color
- Size = size
- UnHide = un_hide
- VisibilityChanged = visibility_changed
- CloseNonBlocking = close
- CloseNonBlockingForm = close
- perform_long_operation = start_thread
-
-
-# -------------------------------- PEP8-ify the Window Class USER Interfaces -------------------------------- #
-
-
-FlexForm = Window
-
-
-def _long_func_thread(window, end_key, original_func):
- """
- Used to run long operations on the user's behalf. Called by the window object
-
- :param window: The window that will get the event
- :type window: (Window)
- :param end_key: The event that will be sent when function returns. If None then no event will be sent when exiting thread
- :type end_key: (Any|None)
- :param original_func: The user's function that is called. Can be a function with no arguments or a lambda experession
- :type original_func: (Any)
- """
-
- return_value = original_func()
- if end_key is not None:
- window.write_event_value(end_key, return_value)
-
-
-def _exit_mainloop(exiting_window):
- if exiting_window == Window._window_running_mainloop or Window._root_running_mainloop == Window.hidden_master_root:
- Window._window_that_exited = exiting_window
- if Window._root_running_mainloop is not None:
- Window._root_running_mainloop.quit()
- # print('** Exited window mainloop **')
-
-
-def _timeout_alarm_callback_hidden():
- """
- Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return
- """
-
- del Window._TKAfterID
-
- # first, get the results table built
- # modify the Results table in the parent FlexForm object
- # print('TIMEOUT CALLBACK')
- Window._root_running_mainloop.quit() # kick the users out of the mainloop
-
- # Get window that caused return
- Window._window_that_exited = None
-
-
-def read_all_windows(timeout=None, timeout_key=TIMEOUT_KEY):
- """
- Reads all windows that are "active" when the call is made. "Active" means that it's been finalized or read.
- If a window has not been finalized then it will not be considered an "active window"
-
- If any of the active windows returns a value then the window and its event and values
- are returned.
-
- If no windows are open, then the value (None, WIN_CLOSED, None) will be returned
- Since WIN_CLOSED is None, it means (None, None, None) is what's returned when no windows remain opened
-
- :param timeout: Time in milliseconds to delay before a returning a timeout event
- :type timeout: (int)
- :param timeout_key: Key to return when a timeout happens. Defaults to the standard TIMEOUT_KEY
- :type timeout_key: (Any)
- :return: A tuple with the (Window, event, values dictionary/list)
- :rtype: (Window, Any, Dict | List)
- """
-
- if len(Window._active_windows) == 0:
- return None, WIN_CLOSED, None
-
- # first see if any queued events are waiting for any of the windows
- for window in Window._active_windows.keys():
- if window._queued_thread_event_available():
- _BuildResults(window, False, window)
- event, values = window.ReturnValues
- return window, event, values
-
- Window._root_running_mainloop = Window.hidden_master_root
- Window._timeout_key = timeout_key
-
- if timeout == 0:
- window = list(Window._active_windows.keys())[Window._timeout_0_counter]
- event, values = window._ReadNonBlocking()
- if event is None:
- event = timeout_key
- if values is None:
- event = None
- Window._timeout_0_counter = (Window._timeout_0_counter + 1) % len(Window._active_windows)
- return window, event, values
-
- Window._timeout_0_counter = 0 # reset value if not reading with timeout 0 so ready next time needed
-
- # setup timeout timer
- if timeout != None:
- try:
- Window.hidden_master_root.after_cancel(Window._TKAfterID)
- del Window._TKAfterID
- except:
- pass
-
- Window._TKAfterID = Window.hidden_master_root.after(timeout, _timeout_alarm_callback_hidden)
-
- # ------------ Call Mainloop ------------
- Window._root_running_mainloop.mainloop()
-
- try:
- Window.hidden_master_root.after_cancel(Window._TKAfterID)
- del Window._TKAfterID
- except:
- pass
- # print('** tkafter cancel failed **')
-
- # Get window that caused return
-
- window = Window._window_that_exited
-
- if window is None:
- return None, timeout_key, None
-
- if window.XFound:
- event, values = None, None
- window.close()
- try:
- del Window._active_windows[window]
- except:
- pass
- # print('Error deleting window, but OK')
- else:
- _BuildResults(window, False, window)
- event, values = window.ReturnValues
-
- return window, event, values
-
-
-# MP""""""`MM dP
-# M mmmmm..M 88
-# M. `YM dP dP .d8888b. d8888P .d8888b. 88d8b.d8b.
-# MMMMMMM. M 88 88 Y8ooooo. 88 88ooood8 88'`88'`88
-# M. .MMM' M 88. .88 88 88 88. ... 88 88 88
-# Mb. .dM `8888P88 `88888P' dP `88888P' dP dP dP
-# MMMMMMMMMMM .88
-# d8888P
-# M""""""""M
-# Mmmm mmmM
-# MMMM MMMM 88d888b. .d8888b. dP dP
-# MMMM MMMM 88' `88 88' `88 88 88
-# MMMM MMMM 88 88. .88 88. .88
-# MMMM MMMM dP `88888P8 `8888P88
-# MMMMMMMMMM .88
-# d8888P
-
-# ------------------------------------------------------------------------- #
-# SystemTray - class for implementing a psyeudo tray #
-# ------------------------------------------------------------------------- #
-
-# -------------------------------- System Tray Begins Here -------------------------------- #
-# Feb 2020 - Just starting on this so code commented out for now. Basing on PySimpleGUIQt's implementation / call format
-
-
-# -------------------------------------------------------------------
-# fade in/out info and default window alpha
-SYSTEM_TRAY_WIN_MARGINS = 160, 60 # from right edge of screen, from bottom of screen
-SYSTEM_TRAY_MESSAGE_MAX_LINE_LENGTH = 50
-# colors
-SYSTEM_TRAY_MESSAGE_WIN_COLOR = "#282828"
-SYSTEM_TRAY_MESSAGE_TEXT_COLOR = "#ffffff"
-
-SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS = 3000 # how long to display the window
-SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION = 1000 # how long to fade in / fade out the window
-
-EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED = '__DOUBLE_CLICKED__'
-EVENT_SYSTEM_TRAY_ICON_ACTIVATED = '__ACTIVATED__'
-EVENT_SYSTEM_TRAY_MESSAGE_CLICKED = '__MESSAGE_CLICKED__'
-
-# Base64 Images to use as icons in the window
-_tray_icon_error = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAADlAAAA5QGP5Zs8AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAIpQTFRF////20lt30Bg30pg4FJc409g4FBe4E9f4U9f4U9g4U9f4E9g31Bf4E9f4E9f4E9f4E9f4E9f4FFh4Vdm4lhn42Bv5GNx5W575nJ/6HqH6HyI6YCM6YGM6YGN6oaR8Kev9MPI9cbM9snO9s3R+Nfb+dzg+d/i++vt/O7v/fb3/vj5//z8//7+////KofnuQAAABF0Uk5TAAcIGBktSYSXmMHI2uPy8/XVqDFbAAAA8UlEQVQ4y4VT15LCMBBTQkgPYem9d9D//x4P2I7vILN68kj2WtsAhyDO8rKuyzyLA3wjSnvi0Eujf3KY9OUP+kno651CvlB0Gr1byQ9UXff+py5SmRhhIS0oPj4SaUUCAJHxP9+tLb/ezU0uEYDUsCc+l5/T8smTIVMgsPXZkvepiMj0Tm5txQLENu7gSF7HIuMreRxYNkbmHI0u5Hk4PJOXkSMz5I3nyY08HMjbpOFylF5WswdJPmYeVaL28968yNfGZ2r9gvqFalJNUy2UWmq1Wa7di/3Kxl3tF1671YHRR04dWn3s9cXRV09f3vb1fwPD7z9j1WgeRgAAAABJRU5ErkJggg=='
-_tray_icon_success = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb4U/gAAAACXBIWXMAAAEKAAABCgEWpLzLAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAAAHJQTFRF////ZsxmbbZJYL9gZrtVar9VZsJcbMRYaMZVasFYaL9XbMFbasRZaMFZacRXa8NYasFaasJaasFZasJaasNZasNYasJYasJZasJZasJZasJZasJZasJYasJZasJZasJZasJZasJaasJZasJZasJZasJZ2IAizQAAACV0Uk5TAAUHCA8YGRobHSwtPEJJUVtghJeYrbDByNjZ2tvj6vLz9fb3/CyrN0oAAADnSURBVDjLjZPbWoUgFIQnbNPBIgNKiwwo5v1fsQvMvUXI5oqPf4DFOgCrhLKjC8GNVgnsJY3nKm9kgTsduVHU3SU/TdxpOp15P7OiuV/PVzk5L3d0ExuachyaTWkAkLFtiBKAqZHPh/yuAYSv8R7XE0l6AVXnwBNJUsE2+GMOzWL8k3OEW7a/q5wOIS9e7t5qnGExvF5Bvlc4w/LEM4Abt+d0S5BpAHD7seMcf7+ZHfclp10TlYZc2y2nOqc6OwruxUWx0rDjNJtyp6HkUW4bJn0VWdf/a7nDpj1u++PBOR694+Ftj/8PKNdnDLn/V8YAAAAASUVORK5CYII='
-_tray_icon_halt = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANswNuMPDO8HBO8FCe0HCu4IBu4IB+oLDeoLDu8JC+wKCu4JDO4LDOwKEe4OEO4OEeUQDewQDe0QDucVEuYcG+ccHOsQFuwWHe4fH/EGAvMEBfMFBvAHBPMGBfEGBvYCAfYDAvcDA/cDBPcDBfUDBvYEAPYEAfYEAvYEA/QGAPQGAfQGAvYEBPUEBvYFB/QGBPQGBfQHB/EFCvIHCPMHCfIHC/IFDfMHDPQGCPQGCfQGCvEIBPIIBfAIB/UIB/QICPYICfoBAPoBAfoBAvsBA/kCAPkCAfkCAvkCA/oBBPkCBPkCBfkCBvgCB/gEAPkEAfgEAvkEA/gGAfkGAvkEBPgEBfkEBv0AAP0AAfwAAvwAA/wCAPwCAfwCAvwCA/wABP0ABfwCBfwEAPwFA/ASD/ESFPAUEvAUE/EXFvAdH+kbIOobIeofIfEfIOcmKOohIukgJOggJesiKuwiKewoLe0tLO0oMOQ3OO43Oew4OfAhIPAhIfAiIPEiI+dDRe9ES+lQTOdSWupSUOhTUehSV+hUVu1QUO1RUe1SV+tTWe5SWOxXWOpYV+pZWelYXexaW+xaXO9aX+lZYeNhYOxjZ+lna+psbOttbehsbupscepucuxtcuxucep3fet7e+p/ffB6gOmKiu2Iie2Sk+2Qle2QluySlOyTleuYmvKFivCOjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIxGNZsAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAACVElEQVQ4T22S93PTMBhADQdl791SSsuRARTKKHsn+STZBptAi6zIacous+w9yyxl7z1T1h8ptHLhrrzLD5+/987R2XZElZ/39tZsbGg42NdvF4pqcGMs4XEcozAB/oQeu6wGr5fkAZcKOUIIRgQXR723wgaXt/NSgcwlO1r3oARkATfhbmNMMCnlMZdz5J8RN9fVhglS5JA/pJUOJiYXoShCkz/flheDvpzlBCBmya5KcDG1sMSB+r/VQtG+YoFXlwN0Us4yeBXujPmWCOqNlVwX5zHntLH5iQ420YiqX9pqTZFSCrBGBc+InBUDAsbwLRlMC40fGJT8YLRwfnhY3v6/AUtDc9m5z0tRJBOAvHUaFchdY6+zDzEghHv1tUnrNCaIOw84Q2WQmkeO/Xopj1xFBREFr8ZZjuRhA++PEB+t05ggwBucpbH8i/n5C1ZU0EEEmRZnSMxoIYcarKigA0Cb1zpHAyZnGj21xqICAA9dcvo4UgEdZ41FBZSTzEOn30f6QeE3Vhl0gLN+2RGDzZPMHLHKoAO3MFy+ix4sDxFlvMXfrdNgFezy7qrXPaaJg0u27j5nneKrCjJ4pf4e3m4DVMcjNNNKxWnpo6jtnfnkunExB4GbuGKk5FNanpB1nJCjCsThJPAAJ8lVdSF5sSrklM2ZqmYdiC40G7Dfnhp57ZsQz6c3hylEO6ZoZQJxqiVgbhoQK3T6AIgU4rbjxthAPF6NAwAOAcS+ixlp/WBFJRDi0fj2RtcjWRwif8Qdu/w3EKLcu3/YslnrZzwo24UQQvwFCrp/iM1NnHwAAAAASUVORK5CYII='
-_tray_icon_notallowed = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAPcICPcLC/cMDPcQEPcSEvcXF/cYGPcaGvcbG/ccHPgxMfgyMvg0NPg5Ofg6Ovg7O/hBQfhCQvlFRflGRvljY/pkZPplZfpnZ/p2dgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMgEwNYAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABE0lEQVQ4T4WT65bDIAiExWbbtN0m3Uua+P4P6g4jGtN4NvNL4DuCCC5WWobe++uwmEmtwNxJUTebcwWCt5jJBwsYcKf3NE4hTOOJxj1FEnBTz4NH6qH2jUcCGr/QLLpkQgHe/6VWJXVqFgBB4yI/KVCkBCoFgPrPHw0CWbwCL8RibBFwzQDQH62/QeAtHQBeADUIDbkF/UnmnkB1ixtERrN3xCgyuF5kMntHTCJXh2vyv+wIdMhvgTeCQJ0C2hBMgSKfZlM1wSLXZ5oqgs8sjSpaCQ2VVlfKhLU6fdZGSvyWz9JMb+NE4jt/Nwfm0yJZSkBpYDg7TcJGrjm0Z7jK0B6P/fHiHK8e9Pp/eSmuf1+vf4x/ralnCN9IrncAAAAASUVORK5CYII='
-_tray_icon_stop = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAANsAANsBAdsCAtwEBNwFBdwHB9wICNwLC90MDN0NDd0PD90REd0SEt4TE94UFN4WFt4XF94ZGeAjI+AlJeEnJ+EpKeEqKuErK+EsLOEuLuIvL+IyMuIzM+M1NeM2NuM3N+M6OuM8POQ9PeQ+PuQ/P+RAQOVISOVJSeVKSuZLS+ZOTuZQUOZRUedSUudVVehbW+lhYeljY+poaOtvb+twcOtxcetzc+t0dOx3d+x4eOx6eu19fe1+fu2AgO2Cgu6EhO6Ghu6Hh+6IiO6Jie+Kiu+Li++MjO+Nje+Oju+QkPCUlPCVlfKgoPKkpPKlpfKmpvOrq/SurvSxsfSysvW4uPW6uvW7u/W8vPa9vfa+vvbAwPbCwvfExPfFxffGxvfHx/fIyPfJyffKyvjLy/jNzfjQ0PjR0fnS0vnU1PnY2Pvg4Pvi4vvj4/vl5fvm5vzo6Pzr6/3u7v3v7/3x8f3z8/309P719f729v739/74+P75+f76+v77+//8/P/9/f/+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHCyoUAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABnUlEQVQ4T33S50PTQBgG8D6lzLbsIUv2kD0FFWTvPWTvISDIUBGV1ecvj+8luZTR9P1wSe755XK5O4+hK4gn5bc7DcMBz/InQoMXeVjY4FXuCAtEyLUwQcTcFgq45JYQ4JqbwhMtV8IjeUJDjQ+5paqCyG9srEsGgoUlpeXpIjxA1nfyi2+Jqmo7Q9JeV+ODerpvBQTM8/ySzQ3t+xxoL7h7nJve5jd85M7wJq9McHaT8o6TwBTfIIfHQGzoAZ/YiSTSq8D5dSDQVqFADrJ5KFMLPaKLHQiQMQoscClezdgCB4CXD/jM90izR8g85UaKA3YAn4AejhV189acA5LX+DVOg00gnvfoVX/BRQsgbplNGqzLusgIffx1tDchiyRgdRbVHNdgRRZHQD9H1asm+PMzYyYMtoBU/sYgRxxgrmGtBRL/cnf5RL4zzCEHZF2QE14LoOWf6B9vMcJBG/iBxKo8dVtYnyStv6yuUq7FLfmqTzbLEOFest1GNGEemCjCPnKuwjm0LsLMbRBJWLkGr4WdO+Cl0HkYPBc6N4z//HcQqVwcOuIAAAAASUVORK5CYII='
-_tray_icon_exclamation = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAN0zM900NN01Nd02Nt03N944ON45Od46Ot47O98/P99BQd9CQt9DQ+FPT+JSUuJTU+JUVOJVVeJWVuNbW+ReXuVjY+Zra+dxceh4eOl7e+l8fOl+ful/f+qBgeqCguqDg+qFheuJieuLi+yPj+yQkO2Wlu+cnO+hofGqqvGtrfre3vrf3/ri4vvn5/75+f76+v/+/v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMQ8SQkAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAABJElEQVQ4T4WS63KCMBBGsyBai62X0otY0aq90ZZa3v/dtpvsJwTijOfXt7tnILOJYY9tNonjNCtQOlqhuKKG0RrNVjgkmIHBHgMId+h7zHSiwg2a9FNVVYScupETmjkd67o+CWpYwft+R6CpCgeUlq5AOyf45+8JsRUKFI6eQLkI3n5CIREBUekLxGaLpATCymRISiAszARJCYSxiZGUQKDLQoqgnPnFhUPOTWeRoZD3FvVZlmVHkE2OEM9iV71GVoZDBGUpAg9QWN5/jx+Ilsi9hz0q4VHOWD+hEF70yc1QEr1a4Q0F0S3eJDfLuv8T4QEFXduZE1rj+et7g6hzCDxF08N+X4DAu+6lUSTnc5wE5tx73ckSTV8QVoux3N88Rykw/wP3i+vwPKk17AAAAABJRU5ErkJggg=='
-_tray_icon_none = None
-
-SYSTEM_TRAY_MESSAGE_ICON_INFORMATION = _tray_icon_success
-SYSTEM_TRAY_MESSAGE_ICON_WARNING = _tray_icon_exclamation
-SYSTEM_TRAY_MESSAGE_ICON_CRITICAL = _tray_icon_stop
-SYSTEM_TRAY_MESSAGE_ICON_NOICON = _tray_icon_none
-
-
-# ------------------------------------------------------------------------- #
-# Tray CLASS #
-# ------------------------------------------------------------------------- #
-class SystemTray:
- """
- A "Simulated System Tray" that duplicates the API calls available to PySimpleGUIWx and PySimpleGUIQt users.
-
- All of the functionality works. The icon is displayed ABOVE the system tray rather than inside of it.
- """
-
- def __init__(self, menu=None, filename=None, data=None, data_base64=None, tooltip=None, metadata=None):
- """
- SystemTray - create an icon in the system tray
- :param menu: Menu definition. Example - ['UNUSED', ['My', 'Simple', '---', 'Menu', 'Exit']]
- :type menu: List[List[List[str] or str]]
- :param filename: filename for icon
- :type filename: (str)
- :param data: in-ram image for icon (same as data_base64 parm)
- :type data: (bytes)
- :param data_base64: base-64 data for icon
- :type data_base64: (bytes)
- :param tooltip: tooltip string
- :type tooltip: (str)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- """
- self._metadata = None
- self.Menu = menu
- self.TrayIcon = None
- self.Shown = False
- self.MenuItemChosen = TIMEOUT_KEY
- self.metadata = metadata
- self.last_message_event = None
-
- screen_size = Window.get_screen_size()
-
- if filename:
- image_elem = Image(filename=filename, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-')
- elif data_base64:
- image_elem = Image(data=data_base64, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-')
- elif data:
- image_elem = Image(data=data, background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-')
- else:
- image_elem = Image(background_color='red', enable_events=True, tooltip=tooltip, key='-IMAGE-')
- layout = [
- [image_elem],
- ]
- self.window = Window('Window Title', layout, element_padding=(0, 0), margins=(0, 0), grab_anywhere=True, no_titlebar=True, transparent_color='red',
- keep_on_top=True, right_click_menu=menu, location=(screen_size[0] - 100, screen_size[1] - 100), finalize=True)
-
- self.window['-IMAGE-'].bind('', '+DOUBLE_CLICK')
-
- @property
- def metadata(self):
- """
- Metadata is an SystemTray property that you can use at any time to hold any value
- :return: the current metadata value
- :rtype: (Any)
- """
- return self._metadata
-
- @metadata.setter
- def metadata(self, value):
- """
- Metadata is an SystemTray property that you can use at any time to hold any value
- :param value: Anything you want it to be
- :type value: (Any)
- """
- self._metadata = value
-
- def read(self, timeout=None):
- """
- Reads the context menu
- :param timeout: Optional. Any value other than None indicates a non-blocking read
- :type timeout:
- :return:
- :rtype:
- """
- if self.last_message_event != TIMEOUT_KEY and self.last_message_event is not None:
- event = self.last_message_event
- self.last_message_event = None
- return event
- event, values = self.window.read(timeout=timeout)
- if event.endswith('DOUBLE_CLICK'):
- return EVENT_SYSTEM_TRAY_ICON_DOUBLE_CLICKED
- elif event == '-IMAGE-':
- return EVENT_SYSTEM_TRAY_ICON_ACTIVATED
-
- return event
-
- def hide(self):
- """
- Hides the icon
- """
- self.window.hide()
-
- def un_hide(self):
- """
- Restores a previously hidden icon
- """
- self.window.un_hide()
-
- def show_message(self, title, message, filename=None, data=None, data_base64=None, messageicon=None,
- time=(SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS)):
- """
- Shows a balloon above icon in system tray
- :param title: Title shown in balloon
- :type title: str
- :param message: Message to be displayed
- :type message: str
- :param filename: Optional icon filename
- :type filename: str
- :param data: Optional in-ram icon
- :type data: b''
- :param data_base64: Optional base64 icon
- :type data_base64: b''
- :param time: Amount of time to display message in milliseconds. If tuple, first item is fade in/out duration
- :type time: int | (int, int)
- :return: The event that happened during the display such as user clicked on message
- :rtype: Any
- """
-
- if isinstance(time, tuple):
- fade_duration, display_duration = time
- else:
- fade_duration = SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION
- display_duration = time
-
- user_icon = data_base64 or filename or data or messageicon
-
- event = self.notify(title, message, icon=user_icon, fade_in_duration=fade_duration, display_duration_in_ms=display_duration)
- self.last_message_event = event
- return event
-
- def close(self):
- """
- Close the system tray window
- """
- self.window.close()
-
- def update(self, menu=None, tooltip=None, filename=None, data=None, data_base64=None, ):
- """
- Updates the menu, tooltip or icon
- :param menu: menu defintion
- :type menu: ???
- :param tooltip: string representing tooltip
- :type tooltip: ???
- :param filename: icon filename
- :type filename: ???
- :param data: icon raw image
- :type data: ???
- :param data_base64: icon base 64 image
- :type data_base64: ???
- """
- # Menu
- if menu is not None:
- top_menu = tk.Menu(self.window.TKroot, tearoff=False)
- AddMenuItem(top_menu, menu[1], self.window['-IMAGE-'])
- self.window['-IMAGE-'].TKRightClickMenu = top_menu
-
- if filename:
- self.window['-IMAGE-'].update(filename=filename)
- elif data_base64:
- self.window['-IMAGE-'].update(data=data_base64)
- elif data:
- self.window['-IMAGE-'].update(data=data)
-
- if tooltip:
- self.window['-IMAGE-'].set_tooltip(tooltip)
-
- @classmethod
- def notify(cls, title, message, icon=_tray_icon_success, display_duration_in_ms=SYSTEM_TRAY_MESSAGE_DISPLAY_DURATION_IN_MILLISECONDS,
- fade_in_duration=SYSTEM_TRAY_MESSAGE_FADE_IN_DURATION, alpha=0.9, location=None):
- """
- Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message
- The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window.
- :param title: Text to be shown at the top of the window in a larger font
- :type title: (str)
- :param message: Text message that makes up the majority of the window
- :type message: (str)
- :param icon: A base64 encoded PNG/GIF image or PNG/GIF filename that will be displayed in the window
- :type icon: bytes | str
- :param display_duration_in_ms: Number of milliseconds to show the window
- :type display_duration_in_ms: (int)
- :param fade_in_duration: Number of milliseconds to fade window in and out
- :type fade_in_duration: (int)
- :param alpha: Alpha channel. 0 - invisible 1 - fully visible
- :type alpha: (float)
- :param location: Location on the screen to display the window
- :type location: (int, int)
- :return: (int) reason for returning
- :rtype: (int)
- """
-
- messages = message.split('\n')
- full_msg = ''
- for m in messages:
- m_wrap = textwrap.fill(m, SYSTEM_TRAY_MESSAGE_MAX_LINE_LENGTH)
- full_msg += m_wrap + '\n'
- message = full_msg[:-1]
-
- win_msg_lines = message.count("\n") + 1
- max_line = max(message.split('\n'))
-
- screen_res_x, screen_res_y = Window.get_screen_size()
- win_margin = SYSTEM_TRAY_WIN_MARGINS # distance from screen edges
- win_width, win_height = 364, 66 + (14.8 * win_msg_lines)
-
- layout = [[Graph(canvas_size=(win_width, win_height), graph_bottom_left=(0, win_height), graph_top_right=(win_width, 0), key="-GRAPH-",
- background_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR, enable_events=True)]]
-
- win_location = location if location is not None else (screen_res_x - win_width - win_margin[0], screen_res_y - win_height - win_margin[1])
- window = Window(title, layout, background_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR, no_titlebar=True,
- location=win_location, keep_on_top=True, alpha_channel=0, margins=(0, 0), element_padding=(0, 0), grab_anywhere=True, finalize=True)
-
- window["-GRAPH-"].draw_rectangle((win_width, win_height), (-win_width, -win_height), fill_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR,
- line_color=SYSTEM_TRAY_MESSAGE_WIN_COLOR)
- if type(icon) is bytes:
- window["-GRAPH-"].draw_image(data=icon, location=(20, 20))
- elif icon is not None:
- window["-GRAPH-"].draw_image(filename=icon, location=(20, 20))
- window["-GRAPH-"].draw_text(title, location=(64, 20), color=SYSTEM_TRAY_MESSAGE_TEXT_COLOR, font=("Helvetica", 12, "bold"),
- text_location=TEXT_LOCATION_TOP_LEFT)
- window["-GRAPH-"].draw_text(message, location=(64, 44), color=SYSTEM_TRAY_MESSAGE_TEXT_COLOR, font=("Helvetica", 9),
- text_location=TEXT_LOCATION_TOP_LEFT)
- window["-GRAPH-"].set_cursor('hand2')
-
- if fade_in_duration:
- for i in range(1, int(alpha * 100)): # fade in
- window.set_alpha(i / 100)
- event, values = window.read(timeout=fade_in_duration // 100)
- if event != TIMEOUT_KEY:
- window.set_alpha(1)
- break
- if event != TIMEOUT_KEY:
- window.close()
- return EVENT_SYSTEM_TRAY_MESSAGE_CLICKED if event == '-GRAPH-' else event
- event, values = window(timeout=display_duration_in_ms)
- if event == TIMEOUT_KEY:
- for i in range(int(alpha * 100), 1, -1): # fade out
- window.set_alpha(i / 100)
- event, values = window.read(timeout=fade_in_duration // 100)
- if event != TIMEOUT_KEY:
- break
- else:
- window.set_alpha(alpha)
- event, values = window(timeout=display_duration_in_ms)
- window.close()
-
- return EVENT_SYSTEM_TRAY_MESSAGE_CLICKED if event == '-GRAPH-' else event
-
- Close = close
- Hide = hide
- Read = read
- ShowMessage = show_message
- UnHide = un_hide
- Update = update
-
-
-# ################################################################################
-# ################################################################################
-# END OF ELEMENT DEFINITIONS
-# ################################################################################
-# ################################################################################
-
-
-# =========================================================================== #
-# Button Lazy Functions so the caller doesn't have to define a bunch of stuff #
-# =========================================================================== #
-
-# ------------------------- A fake Element... the Sizer Element ------------------------- #
-def Sizer(h_pixels=0, v_pixels=0):
- """
- "Pushes" out the size of whatever it is placed inside of. This includes Columns, Frames, Tabs and Windows
-
- :param h_pixels: number of horizontal pixels
- :type h_pixels: (int)
- :param v_pixels: number of vertical pixels
- :type v_pixels: (int)
- :return: (Canvas) A canvas element that has a pad setting set according to parameters
- :rtype: (Canvas)
- """
-
- return Canvas(size=(0, 0), pad=((h_pixels, 0), (v_pixels, 0)))
-
-def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None):
- """
- Pin's an element provided into a layout so that when it's made invisible and visible again, it will
- be in the correct place. Otherwise it will be placed at the end of its containing window/column.
-
- The element you want to pin is the element that you'll be making visibile/invisible.
-
- The pin helper function also causes containers to shrink to fit the contents correct after something inside
- has changed visiblity. Note that setting a hardcoded size on your window can impact this ability to shrink.
-
- :param elem: the element to put into the layout
- :type elem: Element
- :param vertical_alignment: Aligns elements vertically. 'top', 'center', 'bottom'. Can be shortened to 't', 'c', 'b'
- :type vertical_alignment: str | None
- :param shrink: If True, then the space will shrink down to a single pixel when hidden. False leaves the area large and blank
- :type shrink: bool
- :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_x: (bool)
- :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_y: (bool)
- :return: A column element containing the provided element
- :rtype: Column
- """
- if shrink:
- # return Column([[elem, Canvas(size=(0, 0),background_color=elem.BackgroundColor, pad=(0, 0))]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y)
- return Column([[elem, Column([[]], pad=(0, 0))]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y)
- else:
- return Column([[elem]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y)
-
-
-def vtop(elem_or_row, expand_x=None, expand_y=None, background_color=None):
- """
- Align an element or a row of elements to the top of the row that contains it
-
- :param elem_or_row: the element or row of elements
- :type elem_or_row: Element | List[Element] | Tuple[Element]
- :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_x: (bool)
- :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_y: (bool)
- :param background_color: Background color for container that is used by vtop to do the alignment
- :type background_color: str | None
- :return: A column element containing the provided element aligned to the top or list of elements (a row)
- :rtype: Column | List[Column]
- """
-
- if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple):
- return [Column([[e]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y, background_color=background_color) for e in elem_or_row]
-
- return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y, background_color=background_color)
-
-
-def vcenter(elem_or_row, expand_x=None, expand_y=None, background_color=None):
- """
- Align an element or a row of elements to the center of the row that contains it
-
- :param elem_or_row: the element or row of elements
- :type elem_or_row: Element | List[Element] | Tuple[Element]
- :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_x: (bool)
- :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_y: (bool)
- :param background_color: Background color for container that is used by vcenter to do the alignment
- :type background_color: str | None
- :return: A column element containing the provided element aligned to the center or list of elements (a row)
- :rtype: Column | List[Column]
- """
-
- if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple):
- return [Column([[e]], pad=(0, 0), vertical_alignment='center', expand_x=expand_x, expand_y=expand_y, background_color=background_color) for e in elem_or_row]
-
- return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='center', expand_x=expand_x, expand_y=expand_y, background_color=background_color)
-
-
-def vbottom(elem_or_row, expand_x=None, expand_y=None, background_color=None):
- """
- Align an element or a row of elements to the bottom of the row that contains it
-
- :param elem_or_row: the element or row of elements
- :type elem_or_row: Element | List[Element] | Tuple[Element]
- :param expand_x: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_x: (bool)
- :param expand_y: If True/False the value will be passed to the Column Elements used to make this feature
- :type expand_y: (bool)
- :param background_color: Background color for container that is used by vcenter to do the alignment
- :type background_color: str | None
- :return: A column element containing the provided element aligned to the bottom or list of elements (a row)
- :rtype: Column | List[Column]
- """
-
- if isinstance(elem_or_row, list) or isinstance(elem_or_row, tuple):
- return [Column([[e]], pad=(0, 0), vertical_alignment='bottom', expand_x=expand_x, expand_y=expand_y, background_color=background_color) for e in elem_or_row]
-
- return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='bottom', expand_x=expand_x, expand_y=expand_y, background_color=background_color)
-
-
-def Titlebar(title='', icon=None, text_color=None, background_color=None, font=None, key=None, k=None):
- """
- A custom titlebar that replaces the OS provided titlebar, thus giving you control
- the is not possible using the OS provided titlebar such as the color.
-
- NOTE LINUX USERS - at the moment the minimize function is not yet working. Windows users
- should have no problem and it should function as a normal window would.
-
- This titlebar is created from a row of elements that is then encapsulated into a
- one Column element which is what this Titlebar function returns to you.
-
- A custom titlebar removes the margins from your window. If you want the remainder
- of your Window to have margins, place the layout after the Titlebar into a Column and
- set the pad of that Column to the dimensions you would like your margins to have.
-
- The Titlebar is a COLUMN element. You can thus call the update method for the column and
- perform operations such as making the column visible/invisible
-
- :param icon: Can be either a filename or Base64 byte string of a PNG or GIF. This is used in an Image element to create the titlebar
- :type icon: str or bytes or None
- :param title: The "title" to show in the titlebar
- :type title: str
- :param text_color: Text color for titlebar
- :type text_color: str | None
- :param background_color: Background color for titlebar
- :type background_color: str | None
- :param font: Font to be used for the text and the symbols
- :type font: (str or (str, int[, str]) or None)
- :param key: Identifies an Element. Should be UNIQUE to this window.
- :type key: str | int | tuple | object | None
- :param k: Exactly the same as key. Choose one of them to use
- :type k: str | int | tuple | object | None
- :return: A single Column element that has eveything in 1 element
- :rtype: Column
- """
- bc = background_color or CUSTOM_TITLEBAR_BACKGROUND_COLOR or theme_button_color()[1]
- tc = text_color or CUSTOM_TITLEBAR_TEXT_COLOR or theme_button_color()[0]
- font = font or CUSTOM_TITLEBAR_FONT or ('Helvetica', 12)
- key = k or key
- if key is None:
- key = TITLEBAR_KEY
- if isinstance(icon, bytes):
- icon_and_text_portion = [Image(data=icon, background_color=bc, key=TITLEBAR_IMAGE_KEY)]
- elif icon == TITLEBAR_DO_NOT_USE_AN_ICON:
- icon_and_text_portion = []
- elif icon is not None:
- icon_and_text_portion = [Image(filename=icon, background_color=bc, key=TITLEBAR_IMAGE_KEY)]
- elif CUSTOM_TITLEBAR_ICON is not None:
- if isinstance(CUSTOM_TITLEBAR_ICON, bytes):
- icon_and_text_portion = [Image(data=CUSTOM_TITLEBAR_ICON, background_color=bc, key=TITLEBAR_IMAGE_KEY)]
- else:
- icon_and_text_portion = [Image(filename=CUSTOM_TITLEBAR_ICON, background_color=bc, key=TITLEBAR_IMAGE_KEY)]
- else:
- icon_and_text_portion = [Image(data=DEFAULT_BASE64_ICON_16_BY_16, background_color=bc, key=TITLEBAR_IMAGE_KEY)]
-
- icon_and_text_portion += [T(title, text_color=tc, background_color=bc, font=font, grab=True, key=TITLEBAR_TEXT_KEY)]
-
- return Column([[Column([icon_and_text_portion], pad=(0, 0), background_color=bc),
- Column([[T(SYMBOL_TITLEBAR_MINIMIZE, text_color=tc, background_color=bc, enable_events=True, font=font, key=TITLEBAR_MINIMIZE_KEY),
- Text(SYMBOL_TITLEBAR_MAXIMIZE, text_color=tc, background_color=bc, enable_events=True, font=font, key=TITLEBAR_MAXIMIZE_KEY),
- Text(SYMBOL_TITLEBAR_CLOSE, text_color=tc, background_color=bc, font=font, enable_events=True, key=TITLEBAR_CLOSE_KEY), ]],
- element_justification='r', expand_x=True, grab=True, pad=(0, 0), background_color=bc)]], expand_x=True, grab=True,
- background_color=bc, pad=(0, 0), metadata=TITLEBAR_METADATA_MARKER, key=key)
-
-
-def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font=None, tearoff=False, pad=0, p=None, background_color=None, text_color=None,
- bar_background_color=None, bar_text_color=None, key=None, k=None):
- """
- A custom Menubar that replaces the OS provided Menubar
-
- Why?
- Two reasons - 1. they look great (see custom titlebar) 2. if you have a custom titlebar, then you have to use a custom menubar if you want a menubar
-
- :param menu_definition: The Menu definition specified using lists (docs explain the format)
- :type menu_definition: List[List[Tuple[str, List[str]]]
- :param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black"
- :type disabled_text_color: (str)
- :param bar_font: specifies the font family, size to be used for the chars in the bar itself
- :type bar_font: (str or (str, int[, str]) or None)
- :param font: specifies the font family, size to be used for the menu items
- :type font: (str or (str, int[, str]) or None)
- :param tearoff: if True, then can tear the menu off from the window ans use as a floating window. Very cool effect
- :type tearoff: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int). TIP - 0 will make flush with titlebar
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param background_color: color to use for background of the menus that are displayed after making a section. Can be in #RRGGBB format or a color name "black". Defaults to the color of the bar text
- :type background_color: (str)
- :param text_color: color to use for the text of the many items in the displayed menus. Can be in #RRGGBB format or a color name "black". Defaults to the bar background
- :type text_color: (str)
- :param bar_background_color: color to use for the menubar. Can be in #RRGGBB format or a color name "black". Defaults to theme's button text color
- :type bar_background_color: (str)
- :param bar_text_color: color to use for the menu items text. Can be in #RRGGBB format or a color name "black". Defaults to theme's button background color
- :type bar_text_color: (str)
- :param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :returns: A Column element that has a series of ButtonMenu elements
- :rtype: Column
- """
-
- bar_bg = bar_background_color if bar_background_color is not None else theme_button_color()[0]
- bar_text = bar_text_color if bar_text_color is not None else theme_button_color()[1]
- menu_bg = background_color if background_color is not None else bar_text
- menu_text = text_color if text_color is not None else bar_bg
- pad = pad if pad is not None else p
-
- row = []
- for menu in menu_definition:
- text = menu[0]
- if MENU_SHORTCUT_CHARACTER in text:
- text = text.replace(MENU_SHORTCUT_CHARACTER, '')
- if text.startswith(MENU_DISABLED_CHARACTER):
- disabled = True
- text = text[len(MENU_DISABLED_CHARACTER):]
- else:
- disabled = False
-
- button_menu = ButtonMenu(text, menu, border_width=0, button_color=(bar_text, bar_bg), key=text, pad=(0, 0), disabled=disabled, font=bar_font,
- item_font=font, disabled_text_color=disabled_text_color, text_color=menu_text, background_color=menu_bg, tearoff=tearoff)
- button_menu.part_of_custom_menubar = True
- button_menu.custom_menubar_key = key if key is not None else k
- row += [button_menu]
- return Column([row], pad=pad, background_color=bar_bg, expand_x=True, key=key if key is not None else k)
-
-
-# ------------------------- FOLDER BROWSE Element lazy function ------------------------- #
-def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), s=(None, None),
- auto_size_button=None, button_color=None, disabled=False, change_submits=False, enable_events=False,
- font=None, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
- :param button_text: text in the button (Default value = 'Browse')
- :type button_text: (str)
- :param target: target for the button (Default value = (ThisRow, -1))
- :type target: str | (int, int)
- :param initial_folder: starting path for folders and files
- :type initial_folder: (str)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param change_submits: If True, pressing Enter key submits window (Default = False)
- :type enable_events: (bool)
- :param enable_events: Turns on the element specific events.(Default = False)
- :type enable_events: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: Used with window.find_element and with return values to uniquely identify this element
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: The Button created
- :rtype: (Button)
- """
-
- return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target,
- initial_folder=initial_folder, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button,
- disabled=disabled, button_color=button_color, change_submits=change_submits,
- enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- FILE BROWSE Element lazy function ------------------------- #
-def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None,
- tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, change_submits=False,
- enable_events=False, font=None, disabled=False,
- pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Browse')
- :type button_text: (str)
- :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
- :type target: str | (int, int)
- :param file_types: filter file types Default value = (("ALL Files", "*.* *"),).
- :type file_types: Tuple[(str, str), ...]
- :param initial_folder: starting path for folders and files
- :type initial_folder:
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param change_submits: If True, pressing Enter key submits window (Default = False)
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events.(Default = False)
- :type enable_events: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types,
- initial_folder=initial_folder, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button,
- change_submits=change_submits, enable_events=enable_events, disabled=disabled,
- button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- #
-def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, disabled=False,
- initial_folder=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- change_submits=False, enable_events=False,
- font=None, pad=None, p=None, key=None, k=None, visible=True, files_delimiter=BROWSE_FILES_DELIMITER, metadata=None, expand_x=False, expand_y=False):
- """
- Allows browsing of multiple files. File list is returned as a single list with the delimiter defined using the files_delimiter parameter.
-
- :param button_text: text in the button (Default value = 'Browse')
- :type button_text: (str)
- :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
- :type target: str | (int, int)
- :param file_types: Default value = (("ALL Files", "*.* *"),).
- :type file_types: Tuple[(str, str), ...]
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param initial_folder: starting path for folders and files
- :type initial_folder: (str)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param change_submits: If True, pressing Enter key submits window (Default = False)
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events.(Default = False)
- :type enable_events: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param files_delimiter: String to place between files when multiple files are selected. Normally a ;
- :type files_delimiter: str
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- button = Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types,
- initial_folder=initial_folder, change_submits=change_submits, enable_events=enable_events,
- tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button,
- disabled=disabled, button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
- button._files_delimiter = files_delimiter
- return button
-
-
-# ------------------------- FILE BROWSE Element lazy function ------------------------- #
-def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None,
- default_extension='', disabled=False, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- change_submits=False, enable_events=False, font=None,
- pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Save As...')
- :type button_text: (str)
- :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
- :type target: str | (int, int)
- :param file_types: Default value = (("ALL Files", "*.* *"),).
- :type file_types: Tuple[(str, str), ...]
- :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs)
- :type default_extension: (str)
- :param initial_folder: starting path for folders and files
- :type initial_folder: (str)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param change_submits: If True, pressing Enter key submits window (Default = False)
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events.(Default = False)
- :type enable_events: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool) :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types,
- initial_folder=initial_folder, default_extension=default_extension, tooltip=tooltip, size=size, s=s, disabled=disabled,
- auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits,
- enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- SAVE AS Element lazy function ------------------------- #
-def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_TYPES_ALL_FILES, initial_folder=None, default_extension='',
- disabled=False, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- change_submits=False, enable_events=False, font=None,
- pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Save As...')
- :type button_text: (str)
- :param target: key or (row,col) target for the button (Default value = (ThisRow, -1))
- :type target: str | (int, int)
- :param file_types: Default value = (("ALL Files", "*.* *"),).
- :type file_types: Tuple[(str, str), ...]
- :param default_extension: If no extension entered by user, add this to filename (only used in saveas dialogs)
- :type default_extension: (str)
- :param initial_folder: starting path for folders and files
- :type initial_folder: (str)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) or str
- :param change_submits: If True, pressing Enter key submits window (Default = False)
- :type change_submits: (bool)
- :param enable_events: Turns on the element specific events.(Default = False)
- :type enable_events: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types,
- initial_folder=initial_folder, default_extension=default_extension, tooltip=tooltip, size=size, s=s, disabled=disabled,
- auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits,
- enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- SAVE BUTTON Element lazy function ------------------------- #
-def Save(button_text='Save', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, bind_return_key=True,
- disabled=False, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Save')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- #
-def Submit(button_text='Submit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False,
- bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Submit')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- OPEN BUTTON Element lazy function ------------------------- #
-# ------------------------- OPEN BUTTON Element lazy function ------------------------- #
-def Open(button_text='Open', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False,
- bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Open')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- OK BUTTON Element lazy function ------------------------- #
-def OK(button_text='OK', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False,
- bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'OK')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- YES BUTTON Element lazy function ------------------------- #
-def Ok(button_text='Ok', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False,
- bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Ok')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- CANCEL BUTTON Element lazy function ------------------------- #
-def Cancel(button_text='Cancel', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False,
- tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Cancel')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- QUIT BUTTON Element lazy function ------------------------- #
-def Quit(button_text='Quit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
- font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Quit')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- Exit BUTTON Element lazy function ------------------------- #
-def Exit(button_text='Exit', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
- font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Exit')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- YES BUTTON Element lazy function ------------------------- #
-def Yes(button_text='Yes', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
- font=None, bind_return_key=True, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Yes')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = True) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- NO BUTTON Element lazy function ------------------------- #
-def No(button_text='No', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None,
- font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'No')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, then the return key will cause a the Listbox to generate an event
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- NO BUTTON Element lazy function ------------------------- #
-def Help(button_text='Help', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None,
- tooltip=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button (Default value = 'Help')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- NO BUTTON Element lazy function ------------------------- #
-def Debug(button_text='', size=(None, None), s=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None,
- tooltip=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
- This Button has been changed in how it works!!
- Your button has been replaced with a normal button that has the PySimpleGUI Debugger buggon logo on it.
- In your event loop, you will need to check for the event of this button and then call:
- show_debugger_popout_window()
- :param button_text: text in the button (Default value = '')
- :type button_text: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus:
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
-
- user_key = key if key is not None else k if k is not None else button_text
-
- return Button(button_text='', button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=theme_button_color(), font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=user_key, k=k, visible=visible, image_data=PSG_DEBUGGER_LOGO,
- image_subsample=2, border_width=0, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
-def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
- border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- font=None, bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None, expand_x=False, expand_y=False):
- """
- DEPIRCATED
-
- This Button should not be used.
-
- :param button_text: text in the button
- :type button_text: (str)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename,
- image_data=image_data, image_size=image_size, image_subsample=image_subsample,
- border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- CLOSE BUTTON Element lazy function ------------------------- #
-def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
- border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None,
- bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None, expand_x=False, expand_y=False):
- """
- DEPRICATED
-
- This button should not be used. Instead explicitly close your windows by calling window.close() or by using
- the close parameter in window.read
-
- :param button_text: text in the button
- :type button_text: (str)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename,
- image_data=image_data, image_size=image_size, image_subsample=image_subsample,
- border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-CButton = CloseButton
-
-
-# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
-def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
- border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None,
- bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None, expand_x=False, expand_y=False):
- """
- :param button_text: text in the button
- :type button_text: (str)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param focus: if focus should be set to this
- :type focus: idk_yetReally
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param border_width: width of border around element
- :type border_width: (int)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: Button created
- :rtype: (Button)
- """
-
- return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename,
- image_data=image_data, image_size=image_size, image_subsample=image_subsample,
- border_width=border_width, tooltip=tooltip, size=size, s=s, disabled=disabled,
- auto_size_button=auto_size_button, button_color=button_color, font=font,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-ReadFormButton = ReadButton
-RButton = ReadFormButton
-
-
-# ------------------------- Realtime BUTTON Element lazy function ------------------------- #
-def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
- border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None,
- font=None, disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button
- :type button_text: (str)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param border_width: width of border around element
- :type border_width: (int)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: Button created
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename,
- image_data=image_data, image_size=image_size, image_subsample=image_subsample,
- border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- Dummy BUTTON Element lazy function ------------------------- #
-def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None,
- border_width=None, tooltip=None, size=(None, None), s=(None, None), auto_size_button=None, button_color=None, font=None,
- disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
- This is a special type of Button.
-
- It will close the window but NOT send an event that the window has been closed.
-
- It's used in conjunction with non-blocking windows to silently close them. They are used to
- implement the non-blocking popup windows. They're also found in some Demo Programs, so look there for proper use.
-
- :param button_text: text in the button
- :type button_text: (str)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param border_width: width of border around element
- :type border_width: (int)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: if focus should be set to this
- :type focus: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, image_filename=image_filename,
- image_data=image_data, image_size=image_size, image_subsample=image_subsample,
- border_width=border_width, tooltip=tooltip, size=size, s=s, auto_size_button=auto_size_button,
- button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus,
- pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
-
-
-# ------------------------- Calendar Chooser Button lazy function ------------------------- #
-def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=True, default_date_m_d_y=(None, None, None),
- image_filename=None, image_data=None, image_size=(None, None),
- image_subsample=None, tooltip=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None,
- button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, p=None, enable_events=None,
- key=None, k=None, visible=True, locale=None, format='%Y-%m-%d %H:%M:%S', begin_at_sunday_plus=0, month_names=None, day_abbreviations=None,
- title='Choose Date',
- no_titlebar=True, location=(None, None), metadata=None, expand_x=False, expand_y=False):
- """
- Button that will show a calendar chooser window. Fills in the target element with result
-
- :param button_text: text in the button
- :type button_text: (str)
- :param target: Key or "coordinate" (see docs) of target element
- :type target: (int, int) | Any
- :param close_when_date_chosen: (Default = True)
- :type close_when_date_chosen: bool
- :param default_date_m_d_y: Beginning date to show
- :type default_date_m_d_y: (int, int or None, int)
- :param image_filename: image filename if there is a button image
- :type image_filename: image filename if there is a button image
- :param image_data: in-RAM image to be displayed on button
- :type image_data: in-RAM image to be displayed on button
- :param image_size: image size (O.K.)
- :type image_size: (Default = (None))
- :param image_subsample: amount to reduce the size of the image
- :type image_subsample: amount to reduce the size of the image
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param border_width: width of border around element
- :type border_width: width of border around element
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: bool
- :param focus: if focus should be set to this
- :type focus: bool
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param locale: defines the locale used to get day names
- :type locale: str
- :param format: formats result using this strftime format
- :type format: str
- :param begin_at_sunday_plus: Determines the left-most day in the display. 0=sunday, 1=monday, etc
- :type begin_at_sunday_plus: (int)
- :param month_names: optional list of month names to use (should be 12 items)
- :type month_names: List[str]
- :param day_abbreviations: optional list of abbreviations to display as the day of week
- :type day_abbreviations: List[str]
- :param title: Title shown on the date chooser window
- :type title: (str)
- :param no_titlebar: if True no titlebar will be shown on the date chooser window
- :type no_titlebar: bool
- :param location: Location on the screen (x,y) to show the calendar popup window
- :type location: (int, int)
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: Anything you want to store along with this button
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target,
- image_filename=image_filename, image_data=image_data, image_size=image_size,
- image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, enable_events=enable_events,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
- button.calendar_close_when_chosen = close_when_date_chosen
- button.calendar_default_date_M_D_Y = default_date_m_d_y
- button.calendar_locale = locale
- button.calendar_format = format
- button.calendar_no_titlebar = no_titlebar
- button.calendar_location = location
- button.calendar_begin_at_sunday_plus = begin_at_sunday_plus
- button.calendar_month_names = month_names
- button.calendar_day_abbreviations = day_abbreviations
- button.calendar_title = title
-
- return button
-
-
-# ------------------------- Calendar Chooser Button lazy function ------------------------- #
-def ColorChooserButton(button_text, target=(ThisRow, -1), image_filename=None, image_data=None, image_size=(None, None),
- image_subsample=None, tooltip=None, border_width=None, size=(None, None), s=(None, None), auto_size_button=None,
- button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, p=None,
- key=None, k=None, default_color=None, visible=True, metadata=None, expand_x=False, expand_y=False):
- """
-
- :param button_text: text in the button
- :type button_text: (str)
- :param target: key or (row,col) target for the button. Note that -1 for column means 1 element to the left of this one. The constant ThisRow is used to indicate the current row. The Button itself is a valid target for some types of button
- :type target: str | (int, int)
- :type image_filename: (str)
- :param image_filename: image filename if there is a button image. GIFs and PNGs only.
- :type image_filename: (str)
- :param image_data: Raw or Base64 representation of the image to put on button. Choose either filename or data
- :type image_data: bytes | str
- :param image_size: Size of the image in pixels (width, height)
- :type image_size: (int, int)
- :param image_subsample: amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc
- :type image_subsample: (int)
- :param tooltip: text, that will appear when mouse hovers over the element
- :type tooltip: (str)
- :param border_width: width of border around element
- :type border_width: (int)
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param s: Same as size parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, size will be used
- :type s: (int, int) | (None, None) | int
- :param auto_size_button: True if button size is determined by button text
- :type auto_size_button: (bool)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param disabled: set disable state for element (Default = False)
- :type disabled: (bool)
- :param font: specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike
- :type font: (str or (str, int[, str]) or None)
- :param bind_return_key: (Default = False) If True, this button will appear to be clicked when return key is pressed in other elements such as Input and elements with return key options
- :type bind_return_key: (bool)
- :param focus: Determines if initial focus should go to this element.
- :type focus: (bool)
- :param pad: Amount of padding to put around element in pixels (left/right, top/bottom) or ((left, right), (top, bottom)) or an int. If an int, then it's converted into a tuple (int, int)
- :type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param p: Same as pad parameter. It's an alias. If EITHER of them are set, then the one that's set will be used. If BOTH are set, pad will be used
- :type p: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int) | int
- :param key: key for uniquely identify this element (for window.find_element)
- :type key: str | int | tuple | object
- :param k: Same as the Key. You can use either k or key. Which ever is set will be used.
- :type k: str | int | tuple | object
- :param default_color: Color to be sent to tkinter to use as the default color
- :type default_color: str
- :param visible: set initial visibility state of the Button
- :type visible: (bool)
- :param metadata: User metadata that can be set to ANYTHING
- :type metadata: (Any)
- :param expand_x: If True Element will expand in the Horizontal directions
- :type expand_x: (bool)
- :param expand_y: If True Element will expand in the Vertical directions
- :type expand_y: (bool)
- :return: returns a button
- :rtype: (Button)
- """
- button = Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target,
- image_filename=image_filename, image_data=image_data, image_size=image_size,
- image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, s=s,
- auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
- bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata, expand_x=expand_x, expand_y=expand_y)
- button.default_color = default_color
- return button
-
-
-##################################### ----- BUTTON Functions ------ ##################################################
-
-def button_color_to_tuple(color_tuple_or_string, default=(None, None)):
- """
- Convert a color tuple or color string into 2 components and returns them as a tuple
- (Text Color, Button Background Color)
- If None is passed in as the first parameter, then the theme's button color is
- returned
-
- :param color_tuple_or_string: Button color - tuple or a simplied color string with word "on" between color
- :type color_tuple_or_string: str | (str, str)
- :param default: The 2 colors to use if there is a problem. Otherwise defaults to the theme's button color
- :type default: (str, str)
- :return: (str | (str, str)
- :rtype: str | (str, str)
- """
- if default == (None, None):
- color_tuple = _simplified_dual_color_to_tuple(color_tuple_or_string, default=theme_button_color())
- elif color_tuple_or_string == COLOR_SYSTEM_DEFAULT:
- color_tuple = (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT)
- else:
- color_tuple = _simplified_dual_color_to_tuple(color_tuple_or_string, default=default)
-
- return color_tuple
-
-
-def _simplified_dual_color_to_tuple(color_tuple_or_string, default=(None, None)):
- """
- Convert a color tuple or color string into 2 components and returns them as a tuple
- (Text Color, Button Background Color)
- If None is passed in as the first parameter, theme_
-
- :param color_tuple_or_string: Button color - tuple or a simplied color string with word "on" between color
- :type color_tuple_or_string: str | (str, str} | (None, None)
- :param default: The 2 colors to use if there is a problem. Otherwise defaults to the theme's button color
- :type default: (str, str)
- :return: (str | (str, str)
- :rtype: str | (str, str)
- """
- if color_tuple_or_string is None or color_tuple_or_string == (None, None):
- color_tuple_or_string = default
- if color_tuple_or_string == COLOR_SYSTEM_DEFAULT:
- return (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT)
- text_color = background_color = COLOR_SYSTEM_DEFAULT
- try:
- if isinstance(color_tuple_or_string, (tuple, list)):
- if len(color_tuple_or_string) >= 2:
- text_color = color_tuple_or_string[0] or default[0]
- background_color = color_tuple_or_string[1] or default[1]
- elif len(color_tuple_or_string) == 1:
- background_color = color_tuple_or_string[0] or default[1]
- elif isinstance(color_tuple_or_string, str):
- color_tuple_or_string = color_tuple_or_string.lower()
- split_colors = color_tuple_or_string.split(' on ')
- if len(split_colors) >= 2:
- text_color = split_colors[0].strip() or default[0]
- background_color = split_colors[1].strip() or default[1]
- elif len(split_colors) == 1:
- split_colors = color_tuple_or_string.split('on')
- if len(split_colors) == 1:
- text_color, background_color = default[0], split_colors[0].strip()
- else:
- split_colors = split_colors[0].strip(), split_colors[1].strip()
- text_color = split_colors[0] or default[0]
- background_color = split_colors[1] or default[1]
- # text_color, background_color = color_tuple_or_string, default[1]
- else:
- text_color, background_color = default
- else:
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('** Badly formatted dual-color... not a tuple nor string **', color_tuple_or_string)
- else:
- print('** Badly formatted dual-color... not a tuple nor string **', color_tuple_or_string)
- text_color, background_color = default
- except Exception as e:
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('** Badly formatted button color **', color_tuple_or_string, e)
- else:
- print('** Badly formatted button color... not a tuple nor string **', color_tuple_or_string, e)
- text_color, background_color = default
- if isinstance(text_color, int):
- text_color = "#%06X" % text_color
- if isinstance(background_color, int):
- background_color = "#%06X" % background_color
- # print('converted button color', color_tuple_or_string, 'to', (text_color, background_color))
-
- return (text_color, background_color)
-
-
-##################################### ----- RESULTS ------ ##################################################
-
-def AddToReturnDictionary(form, element, value):
- form.ReturnValuesDictionary[element.Key] = value
- # if element.Key is None:
- # form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value
- # element.Key = form.DictionaryKeyCounter
- # form.DictionaryKeyCounter += 1
- # else:
- # form.ReturnValuesDictionary[element.Key] = value
-
-
-def AddToReturnList(form, value):
- form.ReturnValuesList.append(value)
-
-
-# ----------------------------------------------------------------------------#
-# ------- FUNCTION InitializeResults. Sets up form results matrix --------#
-def InitializeResults(form):
- _BuildResults(form, True, form)
- return
-
-
-# ===== Radio Button RadVar encoding and decoding =====#
-# ===== The value is simply the row * 1000 + col =====#
-def DecodeRadioRowCol(RadValue):
- container = RadValue // 100000
- row = RadValue // 1000
- col = RadValue % 1000
- return container, row, col
-
-
-def EncodeRadioRowCol(container, row, col):
- RadValue = container * 100000 + row * 1000 + col
- return RadValue
-
-
-# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- #
-# format of return values is
-# (Button Pressed, input_values)
-def _BuildResults(form, initialize_only, top_level_form):
- # Results for elements are:
- # TEXT - Nothing
- # INPUT - Read value from TK
- # Button - Button Text and position as a Tuple
-
- # Get the initialized results so we don't have to rebuild
- # form.DictionaryKeyCounter = 0
- form.ReturnValuesDictionary = {}
- form.ReturnValuesList = []
- _BuildResultsForSubform(form, initialize_only, top_level_form)
- if not top_level_form.LastButtonClickedWasRealtime:
- top_level_form.LastButtonClicked = None
- return form.ReturnValues
-
-
-def _BuildResultsForSubform(form, initialize_only, top_level_form):
- event = top_level_form.LastButtonClicked
- for row_num, row in enumerate(form.Rows):
- for col_num, element in enumerate(row):
- if element.Key is not None and WRITE_ONLY_KEY in str(element.Key):
- continue
- value = None
- if element.Type == ELEM_TYPE_COLUMN:
- element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
- element.ReturnValuesList = []
- element.ReturnValuesDictionary = {}
- _BuildResultsForSubform(element, initialize_only, top_level_form)
- for item in element.ReturnValuesList:
- AddToReturnList(top_level_form, item)
- if element.UseDictionary:
- top_level_form.UseDictionary = True
- if element.ReturnValues[0] is not None: # if a button was clicked
- event = element.ReturnValues[0]
-
- if element.Type == ELEM_TYPE_FRAME:
- element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
- element.ReturnValuesList = []
- element.ReturnValuesDictionary = {}
- _BuildResultsForSubform(element, initialize_only, top_level_form)
- for item in element.ReturnValuesList:
- AddToReturnList(top_level_form, item)
- if element.UseDictionary:
- top_level_form.UseDictionary = True
- if element.ReturnValues[0] is not None: # if a button was clicked
- event = element.ReturnValues[0]
-
- if element.Type == ELEM_TYPE_PANE:
- element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
- element.ReturnValuesList = []
- element.ReturnValuesDictionary = {}
- _BuildResultsForSubform(element, initialize_only, top_level_form)
- for item in element.ReturnValuesList:
- AddToReturnList(top_level_form, item)
- if element.UseDictionary:
- top_level_form.UseDictionary = True
- if element.ReturnValues[0] is not None: # if a button was clicked
- event = element.ReturnValues[0]
-
- if element.Type == ELEM_TYPE_TAB_GROUP:
- element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
- element.ReturnValuesList = []
- element.ReturnValuesDictionary = {}
- _BuildResultsForSubform(element, initialize_only, top_level_form)
- for item in element.ReturnValuesList:
- AddToReturnList(top_level_form, item)
- if element.UseDictionary:
- top_level_form.UseDictionary = True
- if element.ReturnValues[0] is not None: # if a button was clicked
- event = element.ReturnValues[0]
-
- if element.Type == ELEM_TYPE_TAB:
- element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
- element.ReturnValuesList = []
- element.ReturnValuesDictionary = {}
- _BuildResultsForSubform(element, initialize_only, top_level_form)
- for item in element.ReturnValuesList:
- AddToReturnList(top_level_form, item)
- if element.UseDictionary:
- top_level_form.UseDictionary = True
- if element.ReturnValues[0] is not None: # if a button was clicked
- event = element.ReturnValues[0]
-
- if not initialize_only:
- if element.Type == ELEM_TYPE_INPUT_TEXT:
- try:
- value = element.TKStringVar.get()
- except:
- value = ''
- if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents:
- element.TKStringVar.set('')
- elif element.Type == ELEM_TYPE_INPUT_CHECKBOX:
- value = element.TKIntVar.get()
- value = (value != 0)
- elif element.Type == ELEM_TYPE_INPUT_RADIO:
- RadVar = element.TKIntVar.get()
- this_rowcol = EncodeRadioRowCol(form.ContainerElemementNumber, row_num, col_num)
- # this_rowcol = element.EncodedRadioValue # could use the saved one
- value = RadVar == this_rowcol
- elif element.Type == ELEM_TYPE_BUTTON:
- if top_level_form.LastButtonClicked == element.Key:
- event = top_level_form.LastButtonClicked
- if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons
- top_level_form.LastButtonClicked = None
- if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER:
- # value = None
- value = element.calendar_selection
- else:
- try:
- value = element.TKStringVar.get()
- except:
- value = None
- elif element.Type == ELEM_TYPE_INPUT_COMBO:
- element = element # type: Combo
- # value = element.TKStringVar.get()
- try:
- if element.TKCombo.current() == -1: # if the current value was not in the original list
- value = element.TKCombo.get()
- else:
- value = element.Values[element.TKCombo.current()] # get value from original list given index
- except:
- value = '*Exception occurred*'
- elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU:
- value = element.TKStringVar.get()
- elif element.Type == ELEM_TYPE_INPUT_LISTBOX:
- try:
- items = element.TKListbox.curselection()
- value = [element.Values[int(item)] for item in items]
- except Exception as e:
- value = ''
- elif element.Type == ELEM_TYPE_INPUT_SPIN:
- try:
- value = element.TKStringVar.get()
- for v in element.Values:
- if str(v) == value:
- value = v
- break
- except:
- value = 0
- elif element.Type == ELEM_TYPE_INPUT_SLIDER:
- try:
- value = float(element.TKScale.get())
- except:
- value = 0
- elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
- if element.WriteOnly: # if marked as "write only" when created, then don't include with the values being returned
- continue
- try:
- value = element.TKText.get(1.0, tk.END)
- if element.rstrip:
- value = value.rstrip()
- if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents:
- element.TKText.delete('1.0', tk.END)
- except:
- value = None
- elif element.Type == ELEM_TYPE_TAB_GROUP:
- try:
- value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text']
- tab_key = element.find_currently_active_tab_key()
- # tab_key = element.FindKeyFromTabName(value)
- if tab_key is not None:
- value = tab_key
- except:
- value = None
- elif element.Type == ELEM_TYPE_TABLE:
- value = element.SelectedRows
- elif element.Type == ELEM_TYPE_TREE:
- value = element.SelectedRows
- elif element.Type == ELEM_TYPE_GRAPH:
- value = element.ClickPosition
- elif element.Type == ELEM_TYPE_MENUBAR:
- if element.MenuItemChosen is not None:
- event = top_level_form.LastButtonClicked = element.MenuItemChosen
- value = element.MenuItemChosen
- element.MenuItemChosen = None
- elif element.Type == ELEM_TYPE_BUTTONMENU:
- element = element # type: ButtonMenu
- value = element.MenuItemChosen
- if element.part_of_custom_menubar:
- if element.MenuItemChosen is not None:
- value = event = element.MenuItemChosen
- top_level_form.LastButtonClicked = element.MenuItemChosen
- if element.custom_menubar_key is not None:
- top_level_form.ReturnValuesDictionary[element.custom_menubar_key] = value
- element.MenuItemChosen = None
- else:
- if element.custom_menubar_key not in top_level_form.ReturnValuesDictionary:
- top_level_form.ReturnValuesDictionary[element.custom_menubar_key] = None
- value = None
- else:
- element.MenuItemChosen = None
- else:
- value = None
-
- # if an input type element, update the results
- if element.Type not in (
- ELEM_TYPE_BUTTON, ELEM_TYPE_TEXT, ELEM_TYPE_IMAGE, ELEM_TYPE_OUTPUT, ELEM_TYPE_PROGRESS_BAR, ELEM_TYPE_COLUMN, ELEM_TYPE_FRAME, ELEM_TYPE_SEPARATOR,
- ELEM_TYPE_TAB):
- if not (element.Type == ELEM_TYPE_BUTTONMENU and element.part_of_custom_menubar):
- AddToReturnList(form, value)
- AddToReturnDictionary(top_level_form, element, value)
- elif (element.Type == ELEM_TYPE_BUTTON and
- element.BType == BUTTON_TYPE_COLOR_CHOOSER and
- element.Target == (None, None)) or \
- (element.Type == ELEM_TYPE_BUTTON
- and element.Key is not None and
- (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES,
- BUTTON_TYPE_BROWSE_FOLDER, BUTTON_TYPE_CALENDAR_CHOOSER))):
- AddToReturnList(form, value)
- AddToReturnDictionary(top_level_form, element, value)
-
- # if this is a column, then will fail so need to wrap with try
- try:
- if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None:
- event = form.LastKeyboardEvent
- form.LastKeyboardEvent = None
- except:
- pass
-
- try:
- form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included
- except:
- pass
-
- # if no event was found
- if not initialize_only and event is None and form == top_level_form:
- queued_event_value = form._queued_thread_event_read()
- if queued_event_value is not None:
- event, value = queued_event_value
- AddToReturnList(form, value)
- form.ReturnValuesDictionary[event] = value
-
- if not form.UseDictionary:
- form.ReturnValues = event, form.ReturnValuesList
- else:
- form.ReturnValues = event, form.ReturnValuesDictionary
-
- return form.ReturnValues
-
-
-def fill_form_with_values(window, values_dict):
- """
- Fills a window with values provided in a values dictionary { element_key : new_value }
-
- :param window: The window object to fill
- :type window: (Window)
- :param values_dict: A dictionary with element keys as key and value is values parm for Update call
- :type values_dict: (Dict[Any, Any])
- :return: None
- :rtype: None
- """
-
- for element_key in values_dict:
- try:
- window.AllKeysDict[element_key].Update(values_dict[element_key])
- except Exception as e:
- print('Problem filling form. Perhaps bad key? This is a suspected bad key: {}'.format(element_key))
-
-
-def _FindElementWithFocusInSubForm(form):
- """
- Searches through a "sub-form" (can be a window or container) for the current element with focus
-
- :param form: a Window, Column, Frame, or TabGroup (container elements)
- :type form: container elements
- :return: Element
- :rtype: Element | None
- """
- for row_num, row in enumerate(form.Rows):
- for col_num, element in enumerate(row):
- if element.Type == ELEM_TYPE_COLUMN:
- matching_elem = _FindElementWithFocusInSubForm(element)
- if matching_elem is not None:
- return matching_elem
- elif element.Type == ELEM_TYPE_FRAME:
- matching_elem = _FindElementWithFocusInSubForm(element)
- if matching_elem is not None:
- return matching_elem
- elif element.Type == ELEM_TYPE_TAB_GROUP:
- matching_elem = _FindElementWithFocusInSubForm(element)
- if matching_elem is not None:
- return matching_elem
- elif element.Type == ELEM_TYPE_TAB:
- matching_elem = _FindElementWithFocusInSubForm(element)
- if matching_elem is not None:
- return matching_elem
- elif element.Type == ELEM_TYPE_PANE:
- matching_elem = _FindElementWithFocusInSubForm(element)
- if matching_elem is not None:
- return matching_elem
- elif element.Type == ELEM_TYPE_INPUT_TEXT:
- if element.TKEntry is not None:
- if element.TKEntry is element.TKEntry.focus_get():
- return element
- elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
- if element.TKText is not None:
- if element.TKText is element.TKText.focus_get():
- return element
- elif element.Type == ELEM_TYPE_BUTTON:
- if element.TKButton is not None:
- if element.TKButton is element.TKButton.focus_get():
- return element
- else: # The "Catch All" - if type isn't one of the above, try generic element.Widget
- try:
- if element.Widget is not None:
- if element.Widget is element.Widget.focus_get():
- return element
- except:
- return None
-
- return None
-
-
-def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False, right_click_menu=False):
- """
- Only to be used internally. Not user callable
- :param top_menu: ???
- :type top_menu: ???
- :param sub_menu_info: ???
- :type sub_menu_info:
- :param element: ???
- :type element: idk_yetReally
- :param is_sub_menu: (Default = False)
- :type is_sub_menu: (bool)
- :param skip: (Default = False)
- :type skip: (bool)
-
- """
- return_val = None
- if type(sub_menu_info) is str:
- if not is_sub_menu and not skip:
- pos = sub_menu_info.find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or sub_menu_info[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + len(MENU_SHORTCUT_CHARACTER):]
- if sub_menu_info == '---':
- top_menu.add('separator')
- else:
- try:
- item_without_key = sub_menu_info[:sub_menu_info.index(MENU_KEY_SEPARATOR)]
- except:
- item_without_key = sub_menu_info
-
- if item_without_key[0] == MENU_DISABLED_CHARACTER:
- top_menu.add_command(label=item_without_key[len(MENU_DISABLED_CHARACTER):], underline=pos - 1,
- command=lambda: element._MenuItemChosenCallback(sub_menu_info))
- top_menu.entryconfig(item_without_key[len(MENU_DISABLED_CHARACTER):], state='disabled')
- else:
- top_menu.add_command(label=item_without_key, underline=pos,
- command=lambda: element._MenuItemChosenCallback(sub_menu_info))
- else:
- i = 0
- while i < (len(sub_menu_info)):
- item = sub_menu_info[i]
- if i != len(sub_menu_info) - 1:
- if type(sub_menu_info[i + 1]) == list:
- new_menu = tk.Menu(top_menu, tearoff=element.Tearoff)
- # if a right click menu, then get styling from the top-level window
- if right_click_menu:
- window = element.ParentForm
- if window.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(bg=window.right_click_menu_background_color)
- new_menu.config(activeforeground=window.right_click_menu_background_color)
- if window.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(fg=window.right_click_menu_text_color)
- new_menu.config(activebackground=window.right_click_menu_text_color)
- if window.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(disabledforeground=window.right_click_menu_disabled_text_color)
- if window.right_click_menu_font is not None:
- new_menu.config(font=window.right_click_menu_font)
- else:
- if element.Font is not None:
- new_menu.config(font=element.Font)
- if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(bg=element.BackgroundColor)
- new_menu.config(activeforeground=element.BackgroundColor)
- if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(fg=element.TextColor)
- new_menu.config(activebackground=element.TextColor)
- if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None):
- new_menu.config(disabledforeground=element.DisabledTextColor)
- if element.ItemFont is not None:
- new_menu.config(font=element.ItemFont)
- return_val = new_menu
- pos = sub_menu_info[i].find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or sub_menu_info[i][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + len(MENU_SHORTCUT_CHARACTER):]
- if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER:
- top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu,
- underline=pos, state='disabled')
- else:
- top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
- AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True, right_click_menu=right_click_menu)
- i += 1 # skip the next one
- else:
- AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu)
- else:
- AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu)
- i += 1
- return return_val
-
-
-# 888 888 d8b 888
-# 888 888 Y8P 888
-# 888 888 888
-# 888888 888 888 888 88888b. 888888 .d88b. 888d888
-# 888 888 .88P 888 888 "88b 888 d8P Y8b 888P"
-# 888 888888K 888 888 888 888 88888888 888
-# Y88b. 888 "88b 888 888 888 Y88b. Y8b. 888
-# "Y888 888 888 888 888 888 "Y888 "Y8888 888
-
-
-
-# Chr0nic || This is probably *very* bad practice. But it works. Simple, but it works...
-class VarHolder(object):
- canvas_holder = None
-
- def __init__(self):
- self.canvas_holder = None
-
-
-# Also, to get to the point in the code where each element's widget is created, look for element + "p lacement" (without the space)
-
-
-# ======================== TK CODE STARTS HERE ========================================= #
-
-def _widget_was_created(widget):
- """
- Determines if a Widget was created.
-
- :return: True if a Widget has been created previously (Widget is not None)
- :rtype: (bool)
- """
- if widget is not None:
- return True
- else:
- if SUPPRESS_WIDGET_NOT_FINALIZED_WARNINGS:
- return False
-
- warnings.warn('You cannot an operation on a tkinter widget is being attempted before the widget has been initialized', UserWarning)
- if not SUPPRESS_ERROR_POPUPS:
- _error_popup_with_traceback('tkinter widget not initialized error.',
- 'You cannot perform operations (such as calling update) on an Element until:',
- ' window.read() is called or finalize=True when Window created.',
- 'Adding a "finalize=True" parameter to your Window creation will likely fix this.',
- _create_error_message(),
- )
- return False
-
-
-def _widget_set_fg_color(widget, fg_color=None):
- """
- Sets the foreground color for a tkinter widget.
- :param widget: The tkinter widget (should be non-ttk) to change
- :type widget: tk.Widget
- :param fg_color: The new color. Note that the magic number COLOR_SYSTEM_DEFAULT means no color will be changed/set. Should be a color name or hex string
- :type fg_color: str
- :return: Returns True is the color was able to be changed (False returns on any kind of error)
- :rtype: bool
- """
-
- if fg_color is None or fg_color == COLOR_SYSTEM_DEFAULT:
- return False
-
- if not _widget_was_created(widget):
- return False
-
- try:
- widget.configure(fg=fg_color)
- except Exception as e:
- popup_error_with_traceback('Error setting tkinter widget foreground color',f'tkinter returned an error while attempting to set foreground color to "{fg_color}"',e)
- return False
- return True
-
-
-def _widget_set_bg_color(widget, bg_color=None):
- """
- Sets the background color for a tkinter widget.
- :param widget: The tkinter widget (should be non-ttk) to change
- :type widget: tk.Widget
- :param bg_color: The new color. Note that the magic number COLOR_SYSTEM_DEFAULT means no color will be changed/set
- :type bg_color: str
- :return: Returns True is the color was able to be changed (False returns on any kind of error)
- :rtype: bool
- """
-
-
- if bg_color is None or bg_color == COLOR_SYSTEM_DEFAULT:
- return False
-
- if not _widget_was_created(widget):
- return False
-
- try:
- widget.configure(bg=bg_color)
- except Exception as e:
- popup_error_with_traceback('Error setting tkinter widget background color',f'tkinter returned an error while attempting to set background color to "{bg_color}"', e)
- return False
-
- return True
-
-
-def _fixed_map(style, style_name, option, highlight_colors=(None, None)):
- # Fix for setting text colour for Tkinter 8.6.9
- # From: https://core.tcl.tk/tk/info/509cafafae
-
- default_map = [elm for elm in style.map("Treeview", query_opt=option) if '!' not in elm[0] and 'selected' not in elm[0]]
- custom_map = [elm for elm in style.map(style_name, query_opt=option) if '!' not in elm[0] and 'selected' not in elm[0]]
- if option == 'background':
- custom_map.append(('selected', highlight_colors[1] if highlight_colors[1] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[1]))
- elif option == 'foreground':
- custom_map.append(('selected', highlight_colors[0] if highlight_colors[0] is not None else ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS[0]))
-
- new_map = custom_map + default_map
- return new_map
-
-def _add_right_click_menu(element, toplevel_form):
- if element.RightClickMenu == MENU_RIGHT_CLICK_DISABLED:
- return
- if element.RightClickMenu or toplevel_form.RightClickMenu:
- menu = element.RightClickMenu or toplevel_form.RightClickMenu
- top_menu = tk.Menu(toplevel_form.TKroot, tearoff=toplevel_form.right_click_menu_tearoff, tearoffcommand=element._tearoff_menu_callback)
-
- if toplevel_form.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(bg=toplevel_form.right_click_menu_background_color)
- if toplevel_form.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(fg=toplevel_form.right_click_menu_text_color)
- if toplevel_form.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(disabledforeground=toplevel_form.right_click_menu_disabled_text_color)
- if toplevel_form.right_click_menu_font is not None:
- top_menu.config(font=toplevel_form.right_click_menu_font)
-
- if toplevel_form.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activeforeground=toplevel_form.right_click_menu_selected_colors[0])
- if toplevel_form.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activebackground=toplevel_form.right_click_menu_selected_colors[1])
- AddMenuItem(top_menu, menu[1], element, right_click_menu=True)
- element.TKRightClickMenu = top_menu
- if (running_mac()):
- element.Widget.bind('', element._RightClickMenuCallback)
- else:
- element.Widget.bind('', element._RightClickMenuCallback)
-
-
-def _change_ttk_theme(style, theme_name):
- global ttk_theme_in_use
- if theme_name not in style.theme_names():
- _error_popup_with_traceback('You are trying to use TTK theme "{}"'.format(theme_name),
- 'This is not legal for your system',
- 'The valid themes to choose from are: {}'.format(', '.join(style.theme_names())))
- return False
-
- style.theme_use(theme_name)
- ttk_theme_in_use = theme_name
- return True
-
-
-def _make_ttk_style_name(base_style, element, primary_style=False):
- Window._counter_for_ttk_widgets += 1
- style_name = str(Window._counter_for_ttk_widgets) + '___' + str(element.Key) + base_style
- if primary_style:
- element.ttk_style_name = style_name
- return style_name
-
-
-def _make_ttk_scrollbar(element, orientation, window):
- """
- Creates a ttk scrollbar for elements as they are being added to the layout
-
- :param element: The element
- :type element: (Element)
- :param orientation: The orientation vertical ('v') or horizontal ('h')
- :type orientation: (str)
- :param window: The window containing the scrollbar
- :type window: (Window)
- """
-
- style = ttk.Style()
- _change_ttk_theme(style, window.TtkTheme)
- if orientation[0].lower() == 'v':
- orient = 'vertical'
- style_name = _make_ttk_style_name('.Vertical.TScrollbar', element)
- # style_name_thumb = _make_ttk_style_name('.Vertical.TScrollbar.thumb', element)
- element.vsb_style = style
- element.vsb = ttk.Scrollbar(element.element_frame, orient=orient, command=element.Widget.yview, style=style_name)
- element.vsb_style_name = style_name
- else:
- orient = 'horizontal'
- style_name = _make_ttk_style_name('.Horizontal.TScrollbar', element)
- element.hsb_style = style
- element.hsb = ttk.Scrollbar(element.element_frame, orient=orient, command=element.Widget.xview, style=style_name)
- element.hsb_style_name = style_name
-
- # ------------------ Get the colors using heirarchy of element, window, options, settings ------------------
- # Trough Color
- if element.ttk_part_overrides.sbar_trough_color is not None:
- trough_color = element.ttk_part_overrides.sbar_trough_color
- elif window.ttk_part_overrides.sbar_trough_color is not None:
- trough_color = window.ttk_part_overrides.sbar_trough_color
- elif ttk_part_overrides_from_options.sbar_trough_color is not None:
- trough_color = ttk_part_overrides_from_options.sbar_trough_color
- else:
- trough_color = element.scroll_trough_color
- # Relief
- if element.ttk_part_overrides.sbar_relief is not None:
- scroll_relief = element.ttk_part_overrides.sbar_relief
- elif window.ttk_part_overrides.sbar_relief is not None:
- scroll_relief = window.ttk_part_overrides.sbar_relief
- elif ttk_part_overrides_from_options.sbar_relief is not None:
- scroll_relief = ttk_part_overrides_from_options.sbar_relief
- else:
- scroll_relief = element.scroll_relief
- # Frame Color
- if element.ttk_part_overrides.sbar_frame_color is not None:
- frame_color = element.ttk_part_overrides.sbar_frame_color
- elif window.ttk_part_overrides.sbar_frame_color is not None:
- frame_color = window.ttk_part_overrides.sbar_frame_color
- elif ttk_part_overrides_from_options.sbar_frame_color is not None:
- frame_color = ttk_part_overrides_from_options.sbar_frame_color
- else:
- frame_color = element.scroll_frame_color
- # Background Color
- if element.ttk_part_overrides.sbar_background_color is not None:
- background_color = element.ttk_part_overrides.sbar_background_color
- elif window.ttk_part_overrides.sbar_background_color is not None:
- background_color = window.ttk_part_overrides.sbar_background_color
- elif ttk_part_overrides_from_options.sbar_background_color is not None:
- background_color = ttk_part_overrides_from_options.sbar_background_color
- else:
- background_color = element.scroll_background_color
- # Arrow Color
- if element.ttk_part_overrides.sbar_arrow_color is not None:
- arrow_color = element.ttk_part_overrides.sbar_arrow_color
- elif window.ttk_part_overrides.sbar_arrow_color is not None:
- arrow_color = window.ttk_part_overrides.sbar_arrow_color
- elif ttk_part_overrides_from_options.sbar_arrow_color is not None:
- arrow_color = ttk_part_overrides_from_options.sbar_arrow_color
- else:
- arrow_color = element.scroll_arrow_color
- # Arrow Width
- if element.ttk_part_overrides.sbar_arrow_width is not None:
- arrow_width = element.ttk_part_overrides.sbar_arrow_width
- elif window.ttk_part_overrides.sbar_arrow_width is not None:
- arrow_width = window.ttk_part_overrides.sbar_arrow_width
- elif ttk_part_overrides_from_options.sbar_arrow_width is not None:
- arrow_width = ttk_part_overrides_from_options.sbar_arrow_width
- else:
- arrow_width = element.scroll_arrow_width
- # Scroll Width
- if element.ttk_part_overrides.sbar_width is not None:
- scroll_width = element.ttk_part_overrides.sbar_width
- elif window.ttk_part_overrides.sbar_width is not None:
- scroll_width = window.ttk_part_overrides.sbar_width
- elif ttk_part_overrides_from_options.sbar_width is not None:
- scroll_width = ttk_part_overrides_from_options.sbar_width
- else:
- scroll_width = element.scroll_width
-
- if trough_color not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, troughcolor=trough_color)
-
- if frame_color not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, framecolor=frame_color)
- if frame_color not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, bordercolor=frame_color)
-
- if (background_color not in (None, COLOR_SYSTEM_DEFAULT)) and \
- (arrow_color not in (None, COLOR_SYSTEM_DEFAULT)):
- style.map(style_name, background=[("selected", background_color), ('active', arrow_color), ('background', background_color), ('!focus', background_color)])
- if (background_color not in (None, COLOR_SYSTEM_DEFAULT)) and \
- (arrow_color not in (None, COLOR_SYSTEM_DEFAULT)):
- style.map(style_name, arrowcolor=[("selected", arrow_color), ('active', background_color), ('background', background_color),('!focus', arrow_color)])
-
- if scroll_width not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, width=scroll_width)
- if arrow_width not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, arrowsize=arrow_width)
-
- if scroll_relief not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, relief=scroll_relief)
-
-
-# @_timeit
-def PackFormIntoFrame(form, containing_frame, toplevel_form):
- """
-
- :param form: a window class
- :type form: (Window)
- :param containing_frame: ???
- :type containing_frame: ???
- :param toplevel_form: ???
- :type toplevel_form: (Window)
-
- """
-
- # Old bindings
- def yscroll_old(event):
- if VarHolder.canvas_holder is None:
- return
- if VarHolder.canvas_holder.yview() == (0.0, 1.0):
- return
- try:
- if event.num == 5 or event.delta < 0:
- VarHolder.canvas_holder.yview_scroll(1, "unit")
- elif event.num == 4 or event.delta > 0:
- VarHolder.canvas_holder.yview_scroll(-1, "unit")
- except:
- pass
-
- def xscroll_old(event):
- if VarHolder.canvas_holder is None:
- return
- if VarHolder.canvas_holder.xview() == (0.0, 1.0):
- return
- try:
- if event.num == 5 or event.delta < 0:
- VarHolder.canvas_holder.xview_scroll(1, "unit")
- elif event.num == 4 or event.delta > 0:
- VarHolder.canvas_holder.xview_scroll(-1, "unit")
- except:
- pass
-
- # Chr0nic
- def testMouseHook2(em):
- combo = em.TKCombo
- combo.unbind_class("TCombobox", "")
- combo.unbind_class("TCombobox", "")
- combo.unbind_class("TCombobox", "")
- containing_frame.unbind_all('<4>')
- containing_frame.unbind_all('<5>')
- containing_frame.unbind_all("")
- containing_frame.unbind_all("")
-
- # Chr0nic
- def testMouseUnhook2(em):
- containing_frame.bind_all('<4>', yscroll_old, add="+")
- containing_frame.bind_all('<5>', yscroll_old, add="+")
- containing_frame.bind_all("", yscroll_old, add="+")
- containing_frame.bind_all("", xscroll_old, add="+")
-
- # Chr0nic
- def testMouseHook(em):
- containing_frame.unbind_all('<4>')
- containing_frame.unbind_all('<5>')
- containing_frame.unbind_all("")
- containing_frame.unbind_all("")
-
- # Chr0nic
- def testMouseUnhook(em):
- containing_frame.bind_all('<4>', yscroll_old, add="+")
- containing_frame.bind_all('<5>', yscroll_old, add="+")
- containing_frame.bind_all("", yscroll_old, add="+")
- containing_frame.bind_all("", xscroll_old, add="+")
-
- def _char_width_in_pixels(font):
- return tkinter.font.Font(font=font).measure('A') # single character width
-
- def _char_height_in_pixels(font):
- return tkinter.font.Font(font=font).metrics('linespace')
-
- def _string_width_in_pixels(font, string):
- return tkinter.font.Font(font=font).measure(string) # single character width
-
-
- def _add_grab(element):
-
- try:
- if form.Grab is True or element.Grab is True:
- # if something already about to the button, then don't do the grab stuff
- if '' not in element.Widget.bind():
- element.Widget.bind("", toplevel_form._StartMoveGrabAnywhere)
- element.Widget.bind("", toplevel_form._StopMove)
- element.Widget.bind("", toplevel_form._OnMotionGrabAnywhere)
- element.ParentRowFrame.bind("", toplevel_form._StartMoveGrabAnywhere)
- element.ParentRowFrame.bind("", toplevel_form._StopMove)
- element.ParentRowFrame.bind("", toplevel_form._OnMotionGrabAnywhere)
- if element.Type == ELEM_TYPE_COLUMN:
- element.TKColFrame.canvas.bind("", toplevel_form._StartMoveGrabAnywhere)
- element.TKColFrame.canvas.bind("", toplevel_form._StopMove)
- element.TKColFrame.canvas.bind("", toplevel_form._OnMotionGrabAnywhere)
- except Exception as e:
- pass
- # print(e)
-
- def _add_right_click_menu_and_grab(element):
- if element.RightClickMenu == MENU_RIGHT_CLICK_DISABLED:
- return
- if element.Type == ELEM_TYPE_TAB_GROUP: # unless everything disabled, then need to always set a right click menu for tabgroups
- if toplevel_form.RightClickMenu == MENU_RIGHT_CLICK_DISABLED:
- return
- menu = _MENU_RIGHT_CLICK_TABGROUP_DEFAULT
- else:
- menu = element.RightClickMenu or form.RightClickMenu or toplevel_form.RightClickMenu
-
- if menu:
- top_menu = tk.Menu(toplevel_form.TKroot, tearoff=toplevel_form.right_click_menu_tearoff, tearoffcommand=element._tearoff_menu_callback)
-
- if toplevel_form.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(bg=toplevel_form.right_click_menu_background_color)
- if toplevel_form.right_click_menu_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(fg=toplevel_form.right_click_menu_text_color)
- if toplevel_form.right_click_menu_disabled_text_color not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(disabledforeground=toplevel_form.right_click_menu_disabled_text_color)
- if toplevel_form.right_click_menu_font is not None:
- top_menu.config(font=toplevel_form.right_click_menu_font)
-
- if toplevel_form.right_click_menu_selected_colors[0] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activeforeground=toplevel_form.right_click_menu_selected_colors[0])
- if toplevel_form.right_click_menu_selected_colors[1] not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(activebackground=toplevel_form.right_click_menu_selected_colors[1])
- AddMenuItem(top_menu, menu[1], element, right_click_menu=True)
- element.TKRightClickMenu = top_menu
- if toplevel_form.RightClickMenu: # if the top level has a right click menu, then setup a callback for the Window itself
- if toplevel_form.TKRightClickMenu is None:
- toplevel_form.TKRightClickMenu = top_menu
- if (running_mac()):
- toplevel_form.TKroot.bind('', toplevel_form._RightClickMenuCallback)
- else:
- toplevel_form.TKroot.bind('', toplevel_form._RightClickMenuCallback)
- if (running_mac()):
- element.Widget.bind('', element._RightClickMenuCallback)
- else:
- element.Widget.bind('', element._RightClickMenuCallback)
- try:
- if element.Type == ELEM_TYPE_COLUMN:
- element.TKColFrame.canvas.bind('', element._RightClickMenuCallback)
- except:
- pass
- _add_grab(element)
-
- def _add_expansion(element, row_should_expand, row_fill_direction):
- expand = True
- if element.expand_x and element.expand_y:
- fill = tk.BOTH
- row_fill_direction = tk.BOTH
- row_should_expand = True
- elif element.expand_x:
- fill = tk.X
- row_fill_direction = tk.X if row_fill_direction == tk.NONE else tk.BOTH if row_fill_direction == tk.Y else tk.X
- elif element.expand_y:
- fill = tk.Y
- row_fill_direction = tk.Y if row_fill_direction == tk.NONE else tk.BOTH if row_fill_direction == tk.X else tk.Y
- row_should_expand = True
- else:
- fill = tk.NONE
- expand = False
- return expand, fill, row_should_expand, row_fill_direction
-
- # --------------------------------------------------------------------------- #
- # **************** Use FlexForm to build the tkinter window ********** ----- #
- # Building is done row by row. #
- # WARNING - You can't use print in this function. If the user has rerouted #
- # stdout then there will be an error saying the window isn't finalized #
- # --------------------------------------------------------------------------- #
- ######################### LOOP THROUGH ROWS #########################
- # *********** ------- Loop through ROWS ------- ***********#
- for row_num, flex_row in enumerate(form.Rows):
- ######################### LOOP THROUGH ELEMENTS ON ROW #########################
- # *********** ------- Loop through ELEMENTS ------- ***********#
- # *********** Make TK Row ***********#
- tk_row_frame = tk.Frame(containing_frame)
- row_should_expand = False
- row_fill_direction = tk.NONE
-
- if form.ElementJustification is not None:
- row_justify = form.ElementJustification
- else:
- row_justify = 'l'
-
- for col_num, element in enumerate(flex_row):
- element.ParentRowFrame = tk_row_frame
- element.element_frame = None # for elements that have a scrollbar too
- element.ParentForm = toplevel_form # save the button's parent form object
- if toplevel_form.Font and (element.Font == DEFAULT_FONT or element.Font is None):
- font = toplevel_form.Font
- elif element.Font is not None:
- font = element.Font
- else:
- font = DEFAULT_FONT
- element.font_used = font
- # ------- Determine Auto-Size setting on a cascading basis ------- #
- if element.AutoSizeText is not None: # if element overide
- auto_size_text = element.AutoSizeText
- elif toplevel_form.AutoSizeText is not None: # if form override
- auto_size_text = toplevel_form.AutoSizeText
- else:
- auto_size_text = DEFAULT_AUTOSIZE_TEXT
- element_type = element.Type
- # Set foreground color
- text_color = element.TextColor
- elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding
- # element.pad_used = elementpad # store the value used back into the element
- # Determine Element size
- element_size = element.Size
- if (element_size == (None, None) and element_type not in (
- ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size
- element_size = toplevel_form.DefaultElementSize
- elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)):
- element_size = toplevel_form.DefaultButtonElementSize
- else:
- auto_size_text = False # if user has specified a size then it shouldn't autosize
-
- border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH
- try:
- if element.BorderWidth is not None:
- border_depth = element.BorderWidth
- except:
- pass
-
- # ------------------------- COLUMN placement element ------------------------- #
- if element_type == ELEM_TYPE_COLUMN:
- element = element # type: Column
- # ----------------------- SCROLLABLE Column ----------------------
- if element.Scrollable:
- element.Widget = element.TKColFrame = TkScrollableFrame(tk_row_frame, element.VerticalScrollOnly, element, toplevel_form) # do not use yet! not working
- PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form)
- element.TKColFrame.TKFrame.update()
- if element.Size == (None, None): # if no size specified, use column width x column height/2
- element.TKColFrame.canvas.config(width=element.TKColFrame.TKFrame.winfo_reqwidth() // element.size_subsample_width,
- height=element.TKColFrame.TKFrame.winfo_reqheight() // element.size_subsample_height)
- else:
- element.TKColFrame.canvas.config(width=element.TKColFrame.TKFrame.winfo_reqwidth() // element.size_subsample_width,
- height=element.TKColFrame.TKFrame.winfo_reqheight() // element.size_subsample_height)
- if None not in (element.Size[0], element.Size[1]):
- element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1])
- elif element.Size[1] is not None:
- element.TKColFrame.canvas.config(height=element.Size[1])
- elif element.Size[0] is not None:
- element.TKColFrame.canvas.config(width=element.Size[0])
- if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
- element.TKColFrame.canvas.config(background=element.BackgroundColor)
- element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0)
- element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0,
- highlightthickness=0)
- # ----------------------- PLAIN Column ----------------------
- else:
- if element.Size != (None, None):
- element.Widget = element.TKColFrame = TkFixedFrame(tk_row_frame)
- PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form)
- element.TKColFrame.TKFrame.update()
- if None not in (element.Size[0], element.Size[1]):
- element.TKColFrame.canvas.config(width=element.Size[0], height=element.Size[1])
- elif element.Size[1] is not None:
- element.TKColFrame.canvas.config(height=element.Size[1])
- elif element.Size[0] is not None:
- element.TKColFrame.canvas.config(width=element.Size[0])
- if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
- element.TKColFrame.canvas.config(background=element.BackgroundColor)
- element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0)
- else:
- element.Widget = element.TKColFrame = tk.Frame(tk_row_frame)
- PackFormIntoFrame(element, element.TKColFrame, toplevel_form)
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0)
-
- if element.Justification is None:
- pass
- elif element.Justification.lower().startswith('l'):
- row_justify = 'l'
- elif element.Justification.lower().startswith('c'):
- row_justify = 'c'
- elif element.Justification.lower().startswith('r'):
- row_justify = 'r'
-
- # anchor=tk.NW
- # side = tk.LEFT
- # row_justify = element.Justification
-
- # element.Widget = element.TKColFrame
-
- expand = True
- if element.expand_x and element.expand_y:
- fill = tk.BOTH
- row_fill_direction = tk.BOTH
- row_should_expand = True
- elif element.expand_x:
- fill = tk.X
- row_fill_direction = tk.X
- elif element.expand_y:
- fill = tk.Y
- row_fill_direction = tk.Y
- row_should_expand = True
- else:
- fill = tk.NONE
- expand = False
-
- if element.VerticalAlignment is not None:
- anchor = tk.CENTER # Default to center if a bad choice is made
-
- if element.VerticalAlignment.lower().startswith('t'):
- anchor = tk.N
- if element.VerticalAlignment.lower().startswith('c'):
- anchor = tk.CENTER
- if element.VerticalAlignment.lower().startswith('b'):
- anchor = tk.S
- element.TKColFrame.pack(side=tk.LEFT, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- else:
- element.TKColFrame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
-
- # element.TKColFrame.pack(side=side, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKColFrame.pack_forget()
-
- _add_right_click_menu_and_grab(element)
- # if element.Grab:
- # element._grab_anywhere_on()
- # row_should_expand = True
- # ------------------------- Pane placement element ------------------------- #
- if element_type == ELEM_TYPE_PANE:
- bd = element.BorderDepth if element.BorderDepth is not None else border_depth
- element.PanedWindow = element.Widget = tk.PanedWindow(tk_row_frame,
- orient=tk.VERTICAL if element.Orientation.startswith(
- 'v') else tk.HORIZONTAL,
- borderwidth=bd,
- bd=bd,
- )
- if element.Relief is not None:
- element.PanedWindow.configure(relief=element.Relief)
- element.PanedWindow.configure(handlesize=element.HandleSize)
- if element.ShowHandle:
- element.PanedWindow.config(showhandle=True)
- if element.Size != (None, None):
- element.PanedWindow.config(width=element.Size[0], height=element.Size[1])
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.PanedWindow.configure(background=element.BackgroundColor)
- for pane in element.PaneList:
- pane.Widget = pane.TKColFrame = tk.Frame(element.PanedWindow)
- pane.ParentPanedWindow = element.PanedWindow
- PackFormIntoFrame(pane, pane.TKColFrame, toplevel_form)
- if pane.visible:
- element.PanedWindow.add(pane.TKColFrame)
- if pane.BackgroundColor != COLOR_SYSTEM_DEFAULT and pane.BackgroundColor is not None:
- pane.TKColFrame.configure(background=pane.BackgroundColor,
- highlightbackground=pane.BackgroundColor,
- highlightcolor=pane.BackgroundColor)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- # element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.PanedWindow.pack_forget()
- # ------------------------- TEXT placement element ------------------------- #
- elif element_type == ELEM_TYPE_TEXT:
- # auto_size_text = element.AutoSizeText
- element = element # type: Text
- display_text = element.DisplayText # text to display
- if auto_size_text is False:
- width, height = element_size
- else:
- width, height = None, None
-
- # ---===--- LABEL widget create and place --- #
- element = element # type: Text
- bd = element.BorderWidth if element.BorderWidth is not None else border_depth
- stringvar = tk.StringVar()
- element.TKStringVar = stringvar
- stringvar.set(str(display_text))
- if auto_size_text:
- width = 0
- if element.Justification is not None:
- justification = element.Justification
- elif toplevel_form.TextJustification is not None:
- justification = toplevel_form.TextJustification
- else:
- justification = DEFAULT_TEXT_JUSTIFICATION
- justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT
- anchor = tk.NW if justification.startswith('l') else tk.N if justification.startswith('c') else tk.NE
- tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width,
- height=height, justify=justify, bd=bd, font=font)
- # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
- wraplen = tktext_label.winfo_reqwidth() # width of widget in Pixels
- if auto_size_text or (not auto_size_text and height == 1): # if just 1 line high, ensure no wrap happens
- wraplen = 0
- tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
- if element.Relief is not None:
- tktext_label.configure(relief=element.Relief)
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- tktext_label.configure(background=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
- tktext_label.configure(fg=element.TextColor)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # tktext_label.pack_forget()
- element.TKText = tktext_label
- if element.ClickSubmits:
- tktext_label.bind('', element._TextClickedHandler)
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
- if element.Grab:
- element._grab_anywhere_on()
- # ------------------------- BUTTON placement element non-ttk version ------------------------- #
- elif (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is False) or \
- (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is not True and toplevel_form.UseTtkButtons is not True):
- element = element # type: Button
- element.UseTtkButtons = False # indicate that ttk button was not used
- stringvar = tk.StringVar()
- element.TKStringVar = stringvar
- element.Location = (row_num, col_num)
- btext = element.ButtonText
- btype = element.BType
- if element.AutoSizeButton is not None:
- auto_size = element.AutoSizeButton
- else:
- auto_size = toplevel_form.AutoSizeButtons
- if auto_size is False or element.Size[0] is not None:
- width, height = element_size
- else:
- width = 0
- height = toplevel_form.DefaultButtonElementSize[1]
- if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR:
- bc = element.ButtonColor
- elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR:
- bc = toplevel_form.ButtonColor
- else:
- bc = DEFAULT_BUTTON_COLOR
-
- bd = element.BorderWidth
- pos = -1
- if DEFAULT_USE_BUTTON_SHORTCUTS is True:
- pos = btext.find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or btext[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- btext = btext[:pos] + btext[pos + len(MENU_SHORTCUT_CHARACTER):]
- else:
- btext = btext.replace('\\'+MENU_SHORTCUT_CHARACTER, MENU_SHORTCUT_CHARACTER)
- pos = -1
- tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.CENTER, bd=bd, font=font)
- if pos != -1:
- tkbutton.config(underline=pos)
- try:
- if btype != BUTTON_TYPE_REALTIME:
- tkbutton.config( command=element.ButtonCallBack)
-
- else:
- tkbutton.bind('', element.ButtonReleaseCallBack)
- tkbutton.bind('', element.ButtonPressCallBack)
- if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc:
- tkbutton.config(foreground=bc[0], background=bc[1])
- else:
- if bc[0] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(foreground=bc[0])
- if bc[1] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(background=bc[1])
- except Exception as e:
- _error_popup_with_traceback('Button has a problem....',
- 'The traceback information will not show the line in your layout with the problem, but it does tell you which window.',
- 'Error {}'.format(e),
- # 'Button Text: {}'.format(btext),
- # 'Button key: {}'.format(element.Key),
- # 'Color string: {}'.format(bc),
- "Parent Window's Title: {}".format(toplevel_form.Title))
-
- if bd == 0 and not running_mac():
- tkbutton.config(relief=tk.FLAT)
-
- element.TKButton = tkbutton # not used yet but save the TK button in case
- if elementpad[0] == 0 or elementpad[1] == 0:
- tkbutton.config(highlightthickness=0)
-
- ## -------------- TK Button With Image -------------- ##
- if element.ImageFilename: # if button has an image on it
- tkbutton.config(highlightthickness=0)
- try:
- photo = tk.PhotoImage(file=element.ImageFilename)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- except Exception as e:
- _error_popup_with_traceback('Button Element error {}'.format(e), 'Image filename: {}'.format(element.ImageFilename),
- 'NOTE - file format must be PNG or GIF!',
- 'Button element key: {}'.format(element.Key),
- "Parent Window's Title: {}".format(toplevel_form.Title))
- tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
- if element.ImageData: # if button has an image on it
- tkbutton.config(highlightthickness=0)
- try:
- photo = tk.PhotoImage(data=element.ImageData)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
- except Exception as e:
- _error_popup_with_traceback('Button Element error {}'.format(e),
- 'Problem using BASE64 Image data Image Susample',
- 'Buton element key: {}'.format(element.Key),
- "Parent Window's Title: {}".format(toplevel_form.Title))
-
- if width != 0:
- wraplen = width * _char_width_in_pixels(font)
- tkbutton.configure(wraplength=wraplen) # set wrap to width of widget
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
-
- tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # tkbutton.pack_forget()
- if element.BindReturnKey:
- element.TKButton.bind('', element._ReturnKeyHandler)
- if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
- toplevel_form.FocusSet = True
- element.TKButton.bind('', element._ReturnKeyHandler)
- element.TKButton.focus_set()
- toplevel_form.TKroot.focus_force()
- if element.Disabled is True:
- element.TKButton['state'] = 'disabled'
- if element.DisabledButtonColor != (None, None) and element.DisabledButtonColor != (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT):
- if element.DisabledButtonColor[0] not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKButton['disabledforeground'] = element.DisabledButtonColor[0]
- if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None):
- tkbutton.config(activebackground=element.MouseOverColors[1])
- if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None):
- tkbutton.config(activeforeground=element.MouseOverColors[0])
-
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- try:
- if element.HighlightColors[1] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(highlightbackground=element.HighlightColors[1])
- if element.HighlightColors[0] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(highlightcolor=element.HighlightColors[0])
- except Exception as e:
- _error_popup_with_traceback('Button Element error {}'.format(e),
- 'Button element key: {}'.format(element.Key),
- 'Button text: {}'.format(btext),
- 'Has a bad highlight color {}'.format(element.HighlightColors),
- "Parent Window's Title: {}".format(toplevel_form.Title))
- # print('Button with text: ', btext, 'has a bad highlight color', element.HighlightColors)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- BUTTON placement element ttk version ------------------------- #
- elif element_type == ELEM_TYPE_BUTTON:
- element = element # type: Button
- element.UseTtkButtons = True # indicate that ttk button was used
- stringvar = tk.StringVar()
- element.TKStringVar = stringvar
- element.Location = (row_num, col_num)
- btext = element.ButtonText
- pos = -1
- if DEFAULT_USE_BUTTON_SHORTCUTS is True:
- pos = btext.find(MENU_SHORTCUT_CHARACTER)
- if pos != -1:
- if pos < len(MENU_SHORTCUT_CHARACTER) or btext[pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- btext = btext[:pos] + btext[pos + len(MENU_SHORTCUT_CHARACTER):]
- else:
- btext = btext.replace('\\'+MENU_SHORTCUT_CHARACTER, MENU_SHORTCUT_CHARACTER)
- pos = -1
- btype = element.BType
- if element.AutoSizeButton is not None:
- auto_size = element.AutoSizeButton
- else:
- auto_size = toplevel_form.AutoSizeButtons
- if auto_size is False or element.Size[0] is not None:
- width, height = element_size
- else:
- width = 0
- height = toplevel_form.DefaultButtonElementSize[1]
- if element.ButtonColor != (None, None) and element.ButtonColor != COLOR_SYSTEM_DEFAULT:
- bc = element.ButtonColor
- elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != COLOR_SYSTEM_DEFAULT:
- bc = toplevel_form.ButtonColor
- else:
- bc = DEFAULT_BUTTON_COLOR
- bd = element.BorderWidth
- tkbutton = element.Widget = ttk.Button(tk_row_frame, text=btext, width=width)
- if pos != -1:
- tkbutton.config(underline=pos)
- if btype != BUTTON_TYPE_REALTIME:
- tkbutton.config(command=element.ButtonCallBack)
- else:
- tkbutton.bind('', element.ButtonReleaseCallBack)
- tkbutton.bind('', element.ButtonPressCallBack)
- style_name = _make_ttk_style_name('.TButton', element, primary_style=True)
- button_style = ttk.Style()
- element.ttk_style = button_style
- _change_ttk_theme(button_style, toplevel_form.TtkTheme)
- button_style.configure(style_name, font=font)
-
- if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc:
- button_style.configure(style_name, foreground=bc[0], background=bc[1])
- elif bc[0] != COLOR_SYSTEM_DEFAULT:
- button_style.configure(style_name, foreground=bc[0])
- elif bc[1] != COLOR_SYSTEM_DEFAULT:
- button_style.configure(style_name, background=bc[1])
-
- if bd == 0 and not running_mac():
- button_style.configure(style_name, relief=tk.FLAT)
- button_style.configure(style_name, borderwidth=0)
- else:
- button_style.configure(style_name, borderwidth=bd)
- button_style.configure(style_name, justify=tk.CENTER)
-
- if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None):
- button_style.map(style_name, background=[('active', element.MouseOverColors[1])])
- if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None):
- button_style.map(style_name, foreground=[('active', element.MouseOverColors[0])])
-
- if element.DisabledButtonColor[0] not in (COLOR_SYSTEM_DEFAULT, None):
- button_style.map(style_name, foreground=[('disabled', element.DisabledButtonColor[0])])
- if element.DisabledButtonColor[1] not in (COLOR_SYSTEM_DEFAULT, None):
- button_style.map(style_name, background=[('disabled', element.DisabledButtonColor[1])])
-
- if height > 1:
- button_style.configure(style_name, padding=height * _char_height_in_pixels(font)) # should this be height instead?
- if width != 0:
- wraplen = width * _char_width_in_pixels(font) # width of widget in Pixels
- button_style.configure(style_name, wraplength=wraplen) # set wrap to width of widget
-
- ## -------------- TTK Button With Image -------------- ##
- if element.ImageFilename: # if button has an image on it
- button_style.configure(style_name, borderwidth=0)
- # tkbutton.configure(highlightthickness=0)
- photo = tk.PhotoImage(file=element.ImageFilename)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
- if element.ImageData: # if button has an image on it
- # tkbutton.configure(highlightthickness=0)
- button_style.configure(style_name, borderwidth=0)
-
- photo = tk.PhotoImage(data=element.ImageData)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height)
- # tkbutton.configure(image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
-
- element.TKButton = tkbutton # not used yet but save the TK button in case
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # tkbutton.pack_forget()
- if element.BindReturnKey:
- element.TKButton.bind('', element._ReturnKeyHandler)
- if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
- toplevel_form.FocusSet = True
- element.TKButton.bind('', element._ReturnKeyHandler)
- element.TKButton.focus_set()
- toplevel_form.TKroot.focus_force()
- if element.Disabled is True:
- element.TKButton['state'] = 'disabled'
-
- tkbutton.configure(style=style_name) # IMPORTANT! Apply the style to the button!
- _add_right_click_menu_and_grab(element)
-
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- # ------------------------- BUTTONMENU placement element ------------------------- #
- elif element_type == ELEM_TYPE_BUTTONMENU:
- element = element # type: ButtonMenu
- element.Location = (row_num, col_num)
- btext = element.ButtonText
- if element.AutoSizeButton is not None:
- auto_size = element.AutoSizeButton
- else:
- auto_size = toplevel_form.AutoSizeButtons
- if auto_size is False or element.Size[0] is not None:
- width, height = element_size
- else:
- width = 0
- height = toplevel_form.DefaultButtonElementSize[1]
- if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR:
- bc = element.ButtonColor
- elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR:
- bc = toplevel_form.ButtonColor
- else:
- bc = DEFAULT_BUTTON_COLOR
- bd = element.BorderWidth
- if element.ItemFont is None:
- element.ItemFont = font
- tkbutton = element.Widget = tk.Menubutton(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, bd=bd, font=font)
- element.TKButtonMenu = tkbutton
- if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(foreground=bc[0], background=bc[1])
- tkbutton.config(activebackground=bc[0])
- tkbutton.config(activeforeground=bc[1])
- elif bc[0] != COLOR_SYSTEM_DEFAULT:
- tkbutton.config(foreground=bc[0])
- tkbutton.config(activebackground=bc[0])
- if bd == 0 and not running_mac():
- tkbutton.config(relief=RELIEF_FLAT)
- elif bd != 0:
- tkbutton.config(relief=RELIEF_RAISED)
-
- element.TKButton = tkbutton # not used yet but save the TK button in case
- wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels
- if element.ImageFilename: # if button has an image on it
- photo = tk.PhotoImage(file=element.ImageFilename)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
- if element.ImageData: # if button has an image on it
- photo = tk.PhotoImage(data=element.ImageData)
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- if element.ImageSize != (None, None):
- width, height = element.ImageSize
- else:
- width, height = photo.width(), photo.height()
- tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height)
- tkbutton.image = photo
- if width != 0:
- tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
-
- menu_def = element.MenuDefinition
-
- element.TKMenu = top_menu = tk.Menu(tkbutton, tearoff=element.Tearoff, font=element.ItemFont, tearoffcommand=element._tearoff_menu_callback)
-
- if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(bg=element.BackgroundColor)
- top_menu.config(activeforeground=element.BackgroundColor)
- if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(fg=element.TextColor)
- top_menu.config(activebackground=element.TextColor)
- if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None):
- top_menu.config(disabledforeground=element.DisabledTextColor)
- if element.ItemFont is not None:
- top_menu.config(font=element.ItemFont)
-
- AddMenuItem(top_menu, menu_def[1], element)
- if elementpad[0] == 0 or elementpad[1] == 0:
- tkbutton.config(highlightthickness=0)
- tkbutton.configure(menu=top_menu)
- element.TKMenu = top_menu
- if element.visible is False:
- element._pack_forget_save_settings()
- # tkbutton.pack_forget()
- if element.Disabled == True:
- element.TKButton['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
-
- # ------------------------- INPUT placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_TEXT:
- element = element # type: InputText
- default_text = element.DefaultText
- element.TKStringVar = tk.StringVar()
- element.TKStringVar.set(default_text)
- show = element.PasswordCharacter if element.PasswordCharacter else ""
- bd = border_depth
- if element.Justification is not None:
- justification = element.Justification
- else:
- justification = DEFAULT_TEXT_JUSTIFICATION
- justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT
- # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
- element.TKEntry = element.Widget = tk.Entry(tk_row_frame, width=element_size[0],
- textvariable=element.TKStringVar, bd=bd,
- font=font, show=show, justify=justify)
- if element.ChangeSubmits:
- element.TKEntry.bind('', element._KeyboardHandler)
- element.TKEntry.bind('', element._ReturnKeyHandler)
-
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKEntry.configure(background=element.BackgroundColor, selectforeground=element.BackgroundColor)
-
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- _widget_set_fg_color(element.TKEntry, text_color) # trying out the refactored color function... many places to change still
- element.TKEntry.configure(selectbackground=text_color)
- element.TKEntry.config(insertbackground=text_color)
- if element.selected_background_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKEntry.configure(selectbackground=element.selected_background_color)
- if element.selected_text_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKEntry.configure(selectforeground=element.selected_text_color)
- if element.disabled_readonly_background_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKEntry.config(readonlybackground=element.disabled_readonly_background_color)
- if element.disabled_readonly_text_color not in (None, COLOR_SYSTEM_DEFAULT) and element.Disabled:
- element.TKEntry.config(fg=element.disabled_readonly_text_color)
-
- element.Widget.config(highlightthickness=0)
- # element.pack_keywords = {'side':tk.LEFT, 'padx':elementpad[0], 'pady':elementpad[1], 'expand':False, 'fill':tk.NONE }
- # element.TKEntry.pack(**element.pack_keywords)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKEntry.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKEntry.pack_forget()
- if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
- toplevel_form.FocusSet = True
- element.TKEntry.focus_set()
- if element.Disabled:
- element.TKEntry['state'] = 'readonly' if element.UseReadonlyForDisable else 'disabled'
- if element.ReadOnly:
- element.TKEntry['state'] = 'readonly'
-
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKEntry, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # row_should_expand = True
-
- # ------------------------- COMBO placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_COMBO:
- element = element # type: Combo
- max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0
- if auto_size_text is False:
- width = element_size[0]
- else:
- width = max_line_len + 1
- element.TKStringVar = tk.StringVar()
- style_name = _make_ttk_style_name('.TCombobox', element, primary_style=True)
- combostyle = ttk.Style()
- element.ttk_style = combostyle
- _change_ttk_theme(combostyle, toplevel_form.TtkTheme)
-
- # Creates a unique name for each field element(Sure there is a better way to do this)
- # unique_field = _make_ttk_style_name('.TCombobox.field', element)
-
- # Set individual widget options
- try:
- if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, foreground=element.TextColor)
- combostyle.configure(style_name, selectbackground=element.TextColor)
- combostyle.configure(style_name, insertcolor=element.TextColor)
- combostyle.map(style_name, fieldforeground=[('readonly', element.TextColor)])
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, selectforeground=element.BackgroundColor)
- combostyle.map(style_name, fieldbackground=[('readonly', element.BackgroundColor)])
- combostyle.configure(style_name, fieldbackground=element.BackgroundColor)
-
- if element.button_arrow_color not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, arrowcolor=element.button_arrow_color)
- if element.button_background_color not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, background=element.button_background_color)
- if element.Readonly is True:
- if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, selectforeground=element.TextColor)
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
- combostyle.configure(style_name, selectbackground=element.BackgroundColor)
-
-
- except Exception as e:
- _error_popup_with_traceback('Combo Element error {}'.format(e),
- 'Combo element key: {}'.format(element.Key),
- 'One of your colors is bad. Check the text, background, button background and button arrow colors',
- "Parent Window's Title: {}".format(toplevel_form.Title))
-
- # Strange code that is needed to set the font for the drop-down list
- element._dropdown_newfont = tkinter.font.Font(font=font)
- tk_row_frame.option_add("*TCombobox*Listbox*Font", element._dropdown_newfont)
-
- element.TKCombo = element.Widget = ttk.Combobox(tk_row_frame, width=width, textvariable=element.TKStringVar, font=font, style=style_name)
-
- # make tcl call to deal with colors for the drop-down formatting
- try:
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT) and \
- element.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- element.Widget.tk.eval(
- '[ttk::combobox::PopdownWindow {}].f.l configure -foreground {} -background {} -selectforeground {} -selectbackground {}'.format(element.Widget, element.TextColor, element.BackgroundColor, element.BackgroundColor, element.TextColor))
- except Exception as e:
- pass # going to let this one slide
-
- # Chr0nic
- element.TKCombo.bind("", lambda event, em=element: testMouseHook2(em))
- element.TKCombo.bind("", lambda event, em=element: testMouseUnhook2(em))
-
- if toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet:
- toplevel_form.FocusSet = True
- element.TKCombo.focus_set()
-
- if element.Size[1] != 1 and element.Size[1] is not None:
- element.TKCombo.configure(height=element.Size[1])
- element.TKCombo['values'] = element.Values
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKCombo.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKCombo.pack_forget()
- if element.DefaultValue is not None:
- element.TKCombo.set(element.DefaultValue)
- # for i, v in enumerate(element.Values):
- # if v == element.DefaultValue:
- # element.TKCombo.current(i)
- # break
- # elif element.Values:
- # element.TKCombo.current(0)
- if element.ChangeSubmits:
- element.TKCombo.bind('<>', element._ComboboxSelectHandler)
- if element.BindReturnKey:
- element.TKCombo.bind('', element._ComboboxSelectHandler)
- if element.enable_per_char_events:
- element.TKCombo.bind('', element._KeyboardHandler)
- if element.Readonly:
- element.TKCombo['state'] = 'readonly'
- if element.Disabled is True: # note overrides readonly if disabled
- element.TKCombo['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- OPTIONMENU placement Element (Like ComboBox but different) element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
- element = element # type: OptionMenu
- max_line_len = max([len(str(l)) for l in element.Values])
- if auto_size_text is False:
- width = element_size[0]
- else:
- width = max_line_len
- element.TKStringVar = tk.StringVar()
- if element.DefaultValue:
- element.TKStringVar.set(element.DefaultValue)
- element.TKOptionMenu = element.Widget = tk.OptionMenu(tk_row_frame, element.TKStringVar, *element.Values)
- element.TKOptionMenu.config(highlightthickness=0, font=font, width=width)
- element.TKOptionMenu['menu'].config(font=font)
- element.TKOptionMenu.config(borderwidth=border_depth)
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKOptionMenu.configure(background=element.BackgroundColor)
- element.TKOptionMenu['menu'].config(background=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
- element.TKOptionMenu.configure(fg=element.TextColor)
- element.TKOptionMenu['menu'].config(fg=element.TextColor)
- if element.ChangeSubmits:
- element.TKStringVar.trace('w', element._OptionMenuSelectHandler)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKOptionMenu.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKOptionMenu.pack_forget()
- if element.Disabled == True:
- element.TKOptionMenu['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- # ------------------------- LISTBOX placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_LISTBOX:
- element = element # type: Listbox
- max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0
- if auto_size_text is False:
- width = element_size[0]
- else:
- width = max_line_len
- element_frame = tk.Frame(tk_row_frame)
- element.element_frame = element_frame
-
- justification = tk.LEFT
- if element.justification is not None:
- if element.justification.startswith('l'):
- justification = tk.LEFT
- elif element.justification.startswith('r'):
- justification = tk.RIGHT
- elif element.justification.startswith('c'):
- justification = tk.CENTER
-
- element.TKStringVar = tk.StringVar()
- element.TKListbox = element.Widget = tk.Listbox(element_frame, height=element_size[1], width=width,
- selectmode=element.SelectMode, font=font, exportselection=False)
- # On OLD versions of tkinter the justify option isn't available
- try:
- element.Widget.config(justify=justification)
- except:
- pass
-
- element.Widget.config(highlightthickness=0)
- for index, item in enumerate(element.Values):
- element.TKListbox.insert(tk.END, item)
- if element.DefaultValues is not None and item in element.DefaultValues:
- element.TKListbox.selection_set(index)
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKListbox.configure(background=element.BackgroundColor)
- if element.HighlightBackgroundColor is not None and element.HighlightBackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKListbox.config(selectbackground=element.HighlightBackgroundColor)
- if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
- element.TKListbox.configure(fg=text_color)
- if element.HighlightTextColor is not None and element.HighlightTextColor != COLOR_SYSTEM_DEFAULT:
- element.TKListbox.config(selectforeground=element.HighlightTextColor)
- if element.ChangeSubmits:
- element.TKListbox.bind('<>', element._ListboxSelectHandler)
-
- if not element.NoScrollbar:
- _make_ttk_scrollbar(element, 'v', toplevel_form)
- element.Widget.configure(yscrollcommand=element.vsb.set)
- element.vsb.pack(side=tk.RIGHT, fill='y')
-
- # Horizontal scrollbar
- if element.HorizontalScroll:
- _make_ttk_scrollbar(element, 'h', toplevel_form)
- element.hsb.pack(side=tk.BOTTOM, fill='x')
- element.Widget.configure(xscrollcommand=element.hsb.set)
-
- if not element.NoScrollbar or element.HorizontalScroll:
- # Chr0nic
- element.Widget.bind("", lambda event, em=element: testMouseHook(em))
- element.Widget.bind("", lambda event, em=element: testMouseUnhook(em))
-
-
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand)
- element.TKListbox.pack(side=tk.LEFT, fill=fill, expand=expand)
- if element.visible is False:
- element._pack_forget_save_settings(alternate_widget=element_frame)
- # element_frame.pack_forget()
- if element.BindReturnKey:
- element.TKListbox.bind('', element._ListboxSelectHandler)
- element.TKListbox.bind('', element._ListboxSelectHandler)
- if element.Disabled is True:
- element.TKListbox['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
- # ------------------------- MULTILINE placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_MULTILINE:
- element = element # type: Multiline
- width, height = element_size
- bd = element.BorderWidth
- element.element_frame = element_frame = tk.Frame(tk_row_frame)
-
- element.TKText = element.Widget = tk.Text(element_frame, width=width, height=height, bd=bd, font=font, relief=RELIEF_SUNKEN)
-
- if not element.no_scrollbar:
- _make_ttk_scrollbar(element, 'v', toplevel_form)
-
- element.Widget.configure(yscrollcommand=element.vsb.set)
- element.vsb.pack(side=tk.RIGHT, fill='y')
-
- # Horizontal scrollbar
- if element.HorizontalScroll:
- element.TKText.config(wrap='none')
- _make_ttk_scrollbar(element, 'h', toplevel_form)
- element.hsb.pack(side=tk.BOTTOM, fill='x')
- element.Widget.configure(xscrollcommand=element.hsb.set)
- else:
- element.TKText.config(wrap='word')
-
- if element.wrap_lines is True:
- element.TKText.config(wrap='word')
- elif element.wrap_lines is False:
- element.TKText.config(wrap='none')
-
- if not element.no_scrollbar or element.HorizontalScroll:
- # Chr0nic
- element.TKText.bind("", lambda event, em=element: testMouseHook(em))
- element.TKText.bind("", lambda event, em=element: testMouseUnhook(em))
-
- if element.DefaultText:
- element.TKText.insert(1.0, element.DefaultText) # set the default text
- element.TKText.config(highlightthickness=0)
- if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
- element.TKText.configure(fg=text_color, selectbackground=text_color)
- element.TKText.config(insertbackground=text_color)
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKText.configure(background=element.BackgroundColor, selectforeground=element.BackgroundColor)
- if element.selected_background_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKText.configure(selectbackground=element.selected_background_color)
- if element.selected_text_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKText.configure(selectforeground=element.selected_text_color)
- element.TKText.tag_configure("center", justify='center')
- element.TKText.tag_configure("left", justify='left')
- element.TKText.tag_configure("right", justify='right')
-
- if element.Justification.startswith('l'):
- element.TKText.tag_add("left", 1.0, "end")
- element.justification_tag = 'left'
- elif element.Justification.startswith('r'):
- element.TKText.tag_add("right", 1.0, "end")
- element.justification_tag = 'right'
- elif element.Justification.startswith('c'):
- element.TKText.tag_add("center", 1.0, "end")
- element.justification_tag = 'center'
- # if DEFAULT_SCROLLBAR_COLOR not in (None, COLOR_SYSTEM_DEFAULT): # only works on Linux so not including it
- # element.TKText.vbar.config(troughcolor=DEFAULT_SCROLLBAR_COLOR)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
-
- element.element_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand)
- element.Widget.pack(side=tk.LEFT, fill=fill, expand=expand)
-
- if element.visible is False:
- element._pack_forget_save_settings(alternate_widget=element_frame)
- # element.element_frame.pack_forget()
- else:
- # Chr0nic
- element.TKText.bind("", lambda event, em=element: testMouseHook(em))
- element.TKText.bind("", lambda event, em=element: testMouseUnhook(em))
- if element.ChangeSubmits:
- element.TKText.bind('', element._KeyboardHandler)
- if element.EnterSubmits:
- element.TKText.bind('', element._ReturnKeyHandler)
- if element.Focus is True or (toplevel_form.UseDefaultFocus and not toplevel_form.FocusSet):
- toplevel_form.FocusSet = True
- element.TKText.focus_set()
-
- if element.Disabled is True:
- element.TKText['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
-
- if element.reroute_cprint:
- cprint_set_output_destination(toplevel_form, element.Key)
-
- _add_right_click_menu_and_grab(element)
-
- if element.reroute_stdout:
- element.reroute_stdout_to_here()
- if element.reroute_stderr:
- element.reroute_stderr_to_here()
-
- # row_should_expand = True
- # ------------------------- CHECKBOX pleacement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_CHECKBOX:
- element = element # type: Checkbox
- width = 0 if auto_size_text else element_size[0]
- default_value = element.InitialState
- element.TKIntVar = tk.IntVar()
- element.TKIntVar.set(default_value if default_value is not None else 0)
-
- element.TKCheckbutton = element.Widget = tk.Checkbutton(tk_row_frame, anchor=tk.NW,
- text=element.Text, width=width,
- variable=element.TKIntVar, bd=border_depth,
- font=font)
- if element.ChangeSubmits:
- element.TKCheckbutton.configure(command=element._CheckboxHandler)
- if element.Disabled:
- element.TKCheckbutton.configure(state='disable')
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKCheckbutton.configure(background=element.BackgroundColor)
- element.TKCheckbutton.configure(selectcolor=element.CheckboxBackgroundColor) # The background of the checkbox
- element.TKCheckbutton.configure(activebackground=element.BackgroundColor)
- if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
- element.TKCheckbutton.configure(fg=text_color)
- element.TKCheckbutton.configure(activeforeground=element.TextColor)
-
- element.Widget.configure(highlightthickness=element.highlight_thickness)
- if element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKCheckbutton.config(highlightbackground=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT:
- element.TKCheckbutton.config(highlightcolor=element.TextColor)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKCheckbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKCheckbutton.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- PROGRESS placement element ------------------------- #
- elif element_type == ELEM_TYPE_PROGRESS_BAR:
- element = element # type: ProgressBar
- if element.size_px != (None, None):
- progress_length, progress_width = element.size_px
- else:
- width = element_size[0]
- fnt = tkinter.font.Font()
- char_width = fnt.measure('A') # single character width
- progress_length = width * char_width
- progress_width = element_size[1]
- direction = element.Orientation
- if element.BarColor != (None, None): # if element has a bar color, use it
- bar_color = element.BarColor
- else:
- bar_color = DEFAULT_PROGRESS_BAR_COLOR
- if element.Orientation.lower().startswith('h'):
- base_style_name = ".Horizontal.TProgressbar"
- else:
- base_style_name = ".Vertical.TProgressbar"
- style_name = _make_ttk_style_name(base_style_name, element, primary_style=True)
- element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width,
- orientation=direction, BarColor=bar_color,
- border_width=element.BorderWidth, relief=element.Relief,
- ttk_theme=toplevel_form.TtkTheme, key=element.Key, style_name=style_name)
- element.Widget = element.TKProgressBar.TKProgressBarForReal
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings(alternate_widget=element.TKProgressBar.TKProgressBarForReal)
- # element.TKProgressBar.TKProgressBarForReal.pack_forget()
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- RADIO placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_RADIO:
- element = element # type: Radio
- width = 0 if auto_size_text else element_size[0]
- default_value = element.InitialState
- ID = element.GroupID
- # see if ID has already been placed
- value = EncodeRadioRowCol(form.ContainerElemementNumber, row_num,
- col_num) # value to set intvar to if this radio is selected
- element.EncodedRadioValue = value
- if ID in toplevel_form.RadioDict:
- RadVar = toplevel_form.RadioDict[ID]
- else:
- RadVar = tk.IntVar()
- toplevel_form.RadioDict[ID] = RadVar
- element.TKIntVar = RadVar # store the RadVar in Radio object
- if default_value: # if this radio is the one selected, set RadVar to match
- element.TKIntVar.set(value)
- element.TKRadio = element.Widget = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text,
- width=width, variable=element.TKIntVar, value=value,
- bd=border_depth, font=font)
- if element.ChangeSubmits:
- element.TKRadio.configure(command=element._RadioHandler)
- if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
- element.TKRadio.configure(background=element.BackgroundColor)
- element.TKRadio.configure(selectcolor=element.CircleBackgroundColor)
- element.TKRadio.configure(activebackground=element.BackgroundColor)
- if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
- element.TKRadio.configure(fg=text_color)
- element.TKRadio.configure(activeforeground=text_color)
-
- element.Widget.configure(highlightthickness=1)
- if element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKRadio.config(highlightbackground=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT:
- element.TKRadio.config(highlightcolor=element.TextColor)
-
- if element.Disabled:
- element.TKRadio['state'] = 'disabled'
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKRadio.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKRadio.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- SPIN placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_SPIN:
- element = element # type: Spin
- width, height = element_size
- width = 0 if auto_size_text else element_size[0]
- element.TKStringVar = tk.StringVar()
- element.TKSpinBox = element.Widget = tk.Spinbox(tk_row_frame, values=element.Values, textvariable=element.TKStringVar, width=width, bd=border_depth)
- if element.DefaultValue is not None:
- element.TKStringVar.set(element.DefaultValue)
- element.TKSpinBox.configure(font=font) # set wrap to width of widget
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element.TKSpinBox.configure(background=element.BackgroundColor)
- element.TKSpinBox.configure(buttonbackground=element.BackgroundColor)
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- element.TKSpinBox.configure(fg=text_color)
- element.TKSpinBox.config(insertbackground=text_color)
- element.Widget.config(highlightthickness=0)
- if element.wrap is True:
- element.Widget.configure(wrap=True)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKSpinBox.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.TKSpinBox.pack_forget()
- if element.ChangeSubmits:
- element.TKSpinBox.configure(command=element._SpinboxSelectHandler)
- # element.TKSpinBox.bind('', element._SpinChangedHandler)
- # element.TKSpinBox.bind('', element._SpinChangedHandler)
- # element.TKSpinBox.bind('', element._SpinChangedHandler)
- if element.Readonly:
- element.TKSpinBox['state'] = 'readonly'
- if element.Disabled is True: # note overrides readonly if disabled
- element.TKSpinBox['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- if element.BindReturnKey:
- element.TKSpinBox.bind('', element._SpinboxSelectHandler)
- _add_right_click_menu_and_grab(element)
- # ------------------------- IMAGE placement element ------------------------- #
- elif element_type == ELEM_TYPE_IMAGE:
- element = element # type: Image
- try:
- if element.Filename is not None:
- photo = tk.PhotoImage(file=element.Filename)
- elif element.Data is not None:
- photo = tk.PhotoImage(data=element.Data)
- else:
- photo = None
-
- if photo is not None:
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
- # print('*ERROR laying out form.... Image Element has no image specified*')
- except Exception as e:
- photo = None
- _error_popup_with_traceback('Your Window has an Image Element with a problem',
- 'The traceback will show you the Window with the problem layout',
- 'Look in this Window\'s layout for an Image element that has a key of {}'.format(element.Key),
- 'The error occuring is:', e, emoji='')
-
- element.tktext_label = element.Widget = tk.Label(tk_row_frame, bd=0)
-
- if photo is not None:
- if element_size == (None, None) or element_size is None or element_size == toplevel_form.DefaultElementSize:
- width, height = photo.width(), photo.height()
- else:
- width, height = element_size
- element.tktext_label.config(image=photo, width=width, height=height)
-
- if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
- element.tktext_label.config(background=element.BackgroundColor)
-
- element.tktext_label.image = photo
- # tktext_label.configure(anchor=tk.NW, image=photo)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
-
- if element.visible is False:
- element._pack_forget_save_settings()
- # element.tktext_label.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- if element.EnableEvents and element.tktext_label is not None:
- element.tktext_label.bind('', element._ClickHandler)
-
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- Canvas placement element ------------------------- #
- elif element_type == ELEM_TYPE_CANVAS:
- element = element # type: Canvas
- width, height = element_size
- if element._TKCanvas is None:
- element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
- else:
- element._TKCanvas.master = tk_row_frame
- element.Widget = element._TKCanvas
-
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element._TKCanvas.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element._TKCanvas.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- Graph placement element ------------------------- #
- elif element_type == ELEM_TYPE_GRAPH:
- element = element # type: Graph
- width, height = element_size
- # I don't know why TWO canvases were being defined, on inside the other. Was it so entire canvas can move?
- # if element._TKCanvas is None:
- # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
- # else:
- # element._TKCanvas.master = tk_row_frame
- element._TKCanvas2 = element.Widget = tk.Canvas(tk_row_frame, width=width, height=height,
- bd=border_depth)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element._TKCanvas2.pack(side=tk.LEFT, expand=expand, fill=fill)
- element._TKCanvas2.addtag_all('mytag')
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0)
- # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
- element._TKCanvas2.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # element._TKCanvas2.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element._TKCanvas2, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- if element.ChangeSubmits:
- element._TKCanvas2.bind('', element.ButtonReleaseCallBack)
- element._TKCanvas2.bind('', element.ButtonPressCallBack)
- if element.DragSubmits:
- element._TKCanvas2.bind('', element.MotionCallBack)
- _add_right_click_menu_and_grab(element)
- # ------------------------- MENU placement element ------------------------- #
- elif element_type == ELEM_TYPE_MENUBAR:
- element = element # type: MenuBar
- menu_def = element.MenuDefinition
- element.TKMenu = element.Widget = tk.Menu(toplevel_form.TKroot, tearoff=element.Tearoff,
- tearoffcommand=element._tearoff_menu_callback) # create the menubar
- menubar = element.TKMenu
- if font is not None: # if a font is used, make sure it's saved in the element
- element.Font = font
- for menu_entry in menu_def:
- baritem = tk.Menu(menubar, tearoff=element.Tearoff, tearoffcommand=element._tearoff_menu_callback)
- if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(bg=element.BackgroundColor)
- baritem.config(activeforeground=element.BackgroundColor)
- if element.TextColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(fg=element.TextColor)
- baritem.config(activebackground=element.TextColor)
- if element.DisabledTextColor not in (COLOR_SYSTEM_DEFAULT, None):
- baritem.config(disabledforeground=element.DisabledTextColor)
- if font is not None:
- baritem.config(font=font)
- pos = menu_entry[0].find(MENU_SHORTCUT_CHARACTER)
- # print(pos)
- if pos != -1:
- if pos == 0 or menu_entry[0][pos - len(MENU_SHORTCUT_CHARACTER)] != "\\":
- menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:]
- if menu_entry[0][0] == MENU_DISABLED_CHARACTER:
- label = menu_entry[0][len(MENU_DISABLED_CHARACTER):]
- try:
- label_without_key = label[:label.index(MENU_KEY_SEPARATOR)]
- except:
- label_without_key = label
- menubar.add_cascade(label=label_without_key, menu=baritem, underline=pos - 1)
- menubar.entryconfig(label_without_key, state='disabled')
- else:
- label = menu_entry[0]
- try:
- label_without_key = label[:label.index(MENU_KEY_SEPARATOR)]
- except:
- label_without_key = label
- menubar.add_cascade(label=label_without_key, menu=baritem, underline=pos)
-
- if len(menu_entry) > 1:
- AddMenuItem(baritem, menu_entry[1], element)
- else:
- if menu_entry[0][0] != MENU_DISABLED_CHARACTER:
- # If there's a menu item key then need to remove before putting into the menu
- menubar.entryconfig(label_without_key, menu='', command=lambda el=element, item=label: el._MenuItemChosenCallback(item))
-
- toplevel_form.TKroot.configure(menu=element.TKMenu)
- # ------------------------- Frame placement element ------------------------- #
- elif element_type == ELEM_TYPE_FRAME:
- element = element # type: Frame
- labeled_frame = element.Widget = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief)
- element.TKFrame = labeled_frame
- PackFormIntoFrame(element, labeled_frame, toplevel_form)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- if element.VerticalAlignment is not None:
- anchor = tk.CENTER # Default to center if a bad choice is made
- if element.VerticalAlignment.lower().startswith('t'):
- anchor = tk.N
- if element.VerticalAlignment.lower().startswith('c'):
- anchor = tk.CENTER
- if element.VerticalAlignment.lower().startswith('b'):
- anchor = tk.S
- labeled_frame.pack(side=tk.LEFT, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- else:
- labeled_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
-
- if element.Size != (None, None):
- labeled_frame.config(width=element.Size[0], height=element.Size[1])
- labeled_frame.pack_propagate(0)
- if not element.visible:
- element._pack_forget_save_settings()
- # labeled_frame.pack_forget()
- if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
- labeled_frame.configure(background=element.BackgroundColor,
- highlightbackground=element.BackgroundColor,
- highlightcolor=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
- labeled_frame.configure(foreground=element.TextColor)
- if font is not None:
- labeled_frame.configure(font=font)
- if element.TitleLocation is not None:
- labeled_frame.configure(labelanchor=element.TitleLocation)
- if element.BorderWidth is not None:
- labeled_frame.configure(borderwidth=element.BorderWidth)
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
- # row_should_expand=True
- # ------------------------- Tab placement element ------------------------- #
- elif element_type == ELEM_TYPE_TAB:
- element = element # type: Tab
- form = form # type: TabGroup
- element.TKFrame = element.Widget = tk.Frame(form.TKNotebook)
- PackFormIntoFrame(element, element.TKFrame, toplevel_form)
- state = 'normal'
- if element.Disabled:
- state = 'disabled'
- if element.visible is False:
- state = 'hidden'
- # this code will add an image to the tab. Use it when adding the image on a tab enhancement
- try:
- if element.Filename is not None:
- photo = tk.PhotoImage(file=element.Filename)
- elif element.Data is not None:
- photo = tk.PhotoImage(data=element.Data)
- else:
- photo = None
-
- if element.ImageSubsample and photo is not None:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom and photo is not None:
- photo = photo.zoom(element.zoom)
- # print('*ERROR laying out form.... Image Element has no image specified*')
- except Exception as e:
- photo = None
- _error_popup_with_traceback('Your Window has an Tab Element with an IMAGE problem',
- 'The traceback will show you the Window with the problem layout',
- 'Look in this Window\'s layout for an Image element that has a key of {}'.format(element.Key),
- 'The error occuring is:', e)
-
- element.photo = photo
- if photo is not None:
- if element_size == (None, None) or element_size is None or element_size == toplevel_form.DefaultElementSize:
- width, height = photo.width(), photo.height()
- else:
- width, height = element_size
- element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, bd=0)
- else:
- element.tktext_label = tk.Label(tk_row_frame, bd=0)
- if photo is not None:
- form.TKNotebook.add(element.TKFrame, text=element.Title, compound=tk.LEFT, state=state,image=photo)
-
- # element.photo_image = tk.PhotoImage(data=DEFAULT_BASE64_ICON)
- # form.TKNotebook.add(element.TKFrame, text=element.Title, compound=tk.LEFT, state=state,image = element.photo_image)
-
- form.TKNotebook.add(element.TKFrame, text=element.Title, state=state)
- # July 28 2022 removing the expansion and pack as a test
- # expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- # form.TKNotebook.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand)
-
- element.ParentNotebook = form.TKNotebook
- element.TabID = form.TabCount
- form.tab_index_to_key[element.TabID] = element.key # has a list of the tabs in the notebook and their associated key
- form.TabCount += 1
- if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None):
- element.TKFrame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, highlightcolor=element.BackgroundColor)
-
- # if element.BorderWidth is not None:
- # element.TKFrame.configure(borderwidth=element.BorderWidth)
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
- # row_should_expand = True
- # ------------------------- TabGroup placement element ------------------------- #
- elif element_type == ELEM_TYPE_TAB_GROUP:
- element = element # type: TabGroup
- # custom_style = str(element.Key) + 'customtab.TNotebook'
- custom_style = _make_ttk_style_name('.TNotebook', element, primary_style=True)
- style = ttk.Style()
- _change_ttk_theme(style, toplevel_form.TtkTheme)
-
- if element.TabLocation is not None:
- position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn',
- 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw',
- 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'}
- try:
- tab_position = position_dict[element.TabLocation]
- except:
- tab_position = position_dict['top']
- style.configure(custom_style, tabposition=tab_position)
-
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- style.configure(custom_style, background=element.BackgroundColor)
-
- # FINALLY the proper styling to get tab colors!
- if element.SelectedTitleColor is not None and element.SelectedTitleColor != COLOR_SYSTEM_DEFAULT:
- style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)])
- if element.SelectedBackgroundColor is not None and element.SelectedBackgroundColor != COLOR_SYSTEM_DEFAULT:
- style.map(custom_style + '.Tab', background=[("selected", element.SelectedBackgroundColor)])
- if element.TabBackgroundColor is not None and element.TabBackgroundColor != COLOR_SYSTEM_DEFAULT:
- style.configure(custom_style + '.Tab', background=element.TabBackgroundColor)
- if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
- style.configure(custom_style + '.Tab', foreground=element.TextColor)
- if element.BorderWidth is not None:
- style.configure(custom_style, borderwidth=element.BorderWidth)
- if element.TabBorderWidth is not None:
- style.configure(custom_style + '.Tab', borderwidth=element.TabBorderWidth) # if ever want to get rid of border around the TABS themselves
- if element.FocusColor not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(custom_style + '.Tab', focuscolor=element.FocusColor)
-
- style.configure(custom_style + '.Tab', font=font)
- element.Style = style
- element.StyleName = custom_style
- element.TKNotebook = element.Widget = ttk.Notebook(tk_row_frame, style=custom_style)
-
- PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form)
-
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKNotebook.pack(anchor=tk.SW, side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=fill, expand=expand)
-
- if element.ChangeSubmits:
- element.TKNotebook.bind('<>', element._TabGroupSelectHandler)
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- if element.Size != (None, None):
- element.TKNotebook.configure(width=element.Size[0], height=element.Size[1])
- _add_right_click_menu_and_grab(element)
- if element.visible is False:
- element._pack_forget_save_settings()
- # row_should_expand = True
- # ------------------- SLIDER placement element ------------------------- #
- elif element_type == ELEM_TYPE_INPUT_SLIDER:
- element = element # type: Slider
- slider_length = element_size[0] * _char_width_in_pixels(font)
- slider_width = element_size[1]
- element.TKIntVar = tk.IntVar()
- element.TKIntVar.set(element.DefaultValue)
- if element.Orientation.startswith('v'):
- range_from = element.Range[1]
- range_to = element.Range[0]
- slider_length += DEFAULT_MARGINS[1] * (element_size[0] * 2) # add in the padding
- else:
- range_from = element.Range[0]
- range_to = element.Range[1]
- tkscale = element.Widget = tk.Scale(tk_row_frame, orient=element.Orientation,
- variable=element.TKIntVar,
- from_=range_from, to_=range_to, resolution=element.Resolution,
- length=slider_length, width=slider_width,
- bd=element.BorderWidth,
- relief=element.Relief, font=font,
- tickinterval=element.TickInterval)
- tkscale.config(highlightthickness=0)
- if element.ChangeSubmits:
- tkscale.config(command=element._SliderChangedHandler)
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
- tkscale.configure(background=element.BackgroundColor)
- if element.TroughColor != COLOR_SYSTEM_DEFAULT:
- tkscale.config(troughcolor=element.TroughColor)
- if element.DisableNumericDisplay:
- tkscale.config(showvalue=0)
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
- tkscale.configure(fg=text_color)
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- tkscale.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings()
- # tkscale.pack_forget()
- element.TKScale = tkscale
- if element.Disabled == True:
- element.TKScale['state'] = 'disabled'
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ------------------------- TABLE placement element ------------------------- #
- elif element_type == ELEM_TYPE_TABLE:
- element = element # type: Table
- element.element_frame = frame = tk.Frame(tk_row_frame)
- element.table_frame = frame
- height = element.NumRows
- if element.Justification.startswith('l'):
- anchor = tk.W
- elif element.Justification.startswith('r'):
- anchor = tk.E
- else:
- anchor = tk.CENTER
- column_widths = {}
- # create column width list
- for row in element.Values:
- for i, col in enumerate(row):
- col_width = min(len(str(col)), element.MaxColumnWidth)
- try:
- if col_width > column_widths[i]:
- column_widths[i] = col_width
- except:
- column_widths[i] = col_width
-
- if element.ColumnsToDisplay is None:
- displaycolumns = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0]
- else:
- displaycolumns = []
- for i, should_display in enumerate(element.ColumnsToDisplay):
- if should_display:
- if element.ColumnHeadings is not None:
- displaycolumns.append(element.ColumnHeadings[i])
- else:
- displaycolumns.append(str(i))
-
- column_headings = element.ColumnHeadings if element.ColumnHeadings is not None else displaycolumns
- if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns
- displaycolumns = [element.RowHeaderText, ] + displaycolumns
- if column_headings is not None:
- column_headings = [element.RowHeaderText, ] + element.ColumnHeadings
- else:
- column_headings = [element.RowHeaderText, ] + displaycolumns
- element.TKTreeview = element.Widget = ttk.Treeview(frame, columns=column_headings,
- displaycolumns=displaycolumns, show='headings',
- height=height,
- selectmode=element.SelectMode, )
- element.Widget.entry = None
- treeview = element.TKTreeview
- if element.DisplayRowNumbers:
- treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading
- row_number_header_width =_string_width_in_pixels(element.HeaderFont, element.RowHeaderText) + 10
- row_number_width = _string_width_in_pixels(font, str(len(element.Values))) + 10
- row_number_width = max(row_number_header_width, row_number_width)
- treeview.column(element.RowHeaderText, width=row_number_width, minwidth=10, anchor=anchor, stretch=0)
-
- headings = element.ColumnHeadings if element.ColumnHeadings is not None else element.Values[0]
- for i, heading in enumerate(headings):
- heading = str(heading)
- treeview.heading(heading, text=heading)
- if element.AutoSizeColumns:
- col_width = column_widths.get(i, len(heading)) # in case more headings than there are columns of data
- width = max(col_width * _char_width_in_pixels(font), len(heading)*_char_width_in_pixels(element.HeaderFont))
- else:
- try:
- width = element.ColumnWidths[i] * _char_width_in_pixels(font)
- except:
- width = element.DefaultColumnWidth * _char_width_in_pixels(font)
- if element.cols_justification is not None:
- try:
- if element.cols_justification[i].startswith('l'):
- col_anchor = tk.W
- elif element.cols_justification[i].startswith('r'):
- col_anchor = tk.E
- elif element.cols_justification[i].startswith('c'):
- col_anchor = tk.CENTER
- else:
- col_anchor = anchor
-
- except: # likely didn't specify enough entries (must be one per col)
- col_anchor = anchor
- else:
- col_anchor = anchor
- treeview.column(heading, width=width, minwidth=10, anchor=col_anchor, stretch=element.expand_x)
- # Insert values into the tree
- for i, value in enumerate(element.Values):
- if element.DisplayRowNumbers:
- value = [i + element.StartingRowNumber] + value
- id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i)
- element.tree_ids.append(id)
- if element.AlternatingRowColor not in (None, COLOR_SYSTEM_DEFAULT): # alternating colors
- for row in range(0, len(element.Values), 2):
- treeview.tag_configure(row, background=element.AlternatingRowColor)
- if element.RowColors is not None: # individual row colors
- for row_def in element.RowColors:
- if len(row_def) == 2: # only background is specified
- treeview.tag_configure(row_def[0], background=row_def[1])
- else:
- treeview.tag_configure(row_def[0], background=row_def[2], foreground=row_def[1])
- # ------ Do Styling of Colors -----
- # style_name = str(element.Key) + 'customtable.Treeview'
- style_name = _make_ttk_style_name( '.Treeview', element, primary_style=True)
- element.table_ttk_style_name = style_name
- table_style = ttk.Style()
- element.ttk_style = table_style
-
- _change_ttk_theme(table_style, toplevel_form.TtkTheme)
-
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- table_style.configure(style_name, background=element.BackgroundColor, fieldbackground=element.BackgroundColor, )
- if element.SelectedRowColors[1] is not None:
- table_style.map(style_name, background=_fixed_map(table_style, style_name, 'background', element.SelectedRowColors))
- if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
- table_style.configure(style_name, foreground=element.TextColor)
- if element.SelectedRowColors[0] is not None:
- table_style.map(style_name, foreground=_fixed_map(table_style, style_name, 'foreground', element.SelectedRowColors))
- if element.RowHeight is not None:
- table_style.configure(style_name, rowheight=element.RowHeight)
- else:
- table_style.configure(style_name, rowheight=_char_height_in_pixels(font))
- if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT:
- table_style.configure(style_name + '.Heading', foreground=element.HeaderTextColor)
- if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT:
- table_style.configure(style_name + '.Heading', background=element.HeaderBackgroundColor)
- if element.HeaderFont is not None:
- table_style.configure(style_name + '.Heading', font=element.HeaderFont)
- else:
- table_style.configure(style_name + '.Heading', font=font)
- if element.HeaderBorderWidth is not None:
- table_style.configure(style_name + '.Heading', borderwidth=element.HeaderBorderWidth)
- if element.HeaderRelief is not None:
- table_style.configure(style_name + '.Heading', relief=element.HeaderRelief)
- table_style.configure(style_name, font=font)
- if element.BorderWidth is not None:
- table_style.configure(style_name, borderwidth=element.BorderWidth)
-
- if element.HeaderBackgroundColor not in (None, COLOR_SYSTEM_DEFAULT) and element.HeaderTextColor not in (None, COLOR_SYSTEM_DEFAULT):
- table_style.map(style_name + ".Heading", background=[('pressed', '!focus', element.HeaderBackgroundColor),
- ('active', element.HeaderTextColor),])
- table_style.map(style_name + ".Heading", foreground=[('pressed', '!focus', element.HeaderTextColor),
- ('active', element.HeaderBackgroundColor),])
-
-
- treeview.configure(style=style_name)
- # scrollable_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both')
- if element.enable_click_events is True:
- treeview.bind('', element._table_clicked)
- if element.right_click_selects:
- if running_mac():
- treeview.bind('', element._table_clicked)
- else:
- treeview.bind('', element._table_clicked)
- treeview.bind("<>", element._treeview_selected)
- if element.BindReturnKey or element.enable_cell_editing:
- treeview.bind('', element._treeview_double_click)
- treeview.bind('', element._treeview_double_click)
-
- if not element.HideVerticalScroll:
- _make_ttk_scrollbar(element, 'v', toplevel_form)
-
- element.Widget.configure(yscrollcommand=element.vsb.set)
- element.vsb.pack(side=tk.RIGHT, fill='y')
-
- # Horizontal scrollbar
- if not element.VerticalScrollOnly:
- # element.Widget.config(wrap='none')
- _make_ttk_scrollbar(element, 'h', toplevel_form)
- element.hsb.pack(side=tk.BOTTOM, fill='x')
- element.Widget.configure(xscrollcommand=element.hsb.set)
-
- if not element.HideVerticalScroll or not element.VerticalScrollOnly:
- # Chr0nic
- element.Widget.bind("", lambda event, em=element: testMouseHook(em))
- element.Widget.bind("", lambda event, em=element: testMouseUnhook(em))
-
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKTreeview.pack(side=tk.LEFT, padx=0, pady=0, expand=expand, fill=fill)
- frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings(alternate_widget=element.element_frame) # seems like it should be the frame if following other elements conventions
- # element.TKTreeview.pack_forget()
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH:
- # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***')
- table_style.map(style_name,
- foreground=_fixed_map(table_style, style_name, 'foreground', element.SelectedRowColors),
- background=_fixed_map(table_style, style_name, 'background', element.SelectedRowColors))
- # ------------------------- Tree placement element ------------------------- #
- elif element_type == ELEM_TYPE_TREE:
- element = element # type: Tree
- element.element_frame = element_frame = tk.Frame(tk_row_frame)
-
- height = element.NumRows
- if element.Justification.startswith('l'): # justification
- anchor = tk.W
- elif element.Justification.startswith('r'):
- anchor = tk.E
- else:
- anchor = tk.CENTER
-
- if element.ColumnsToDisplay is None: # Which cols to display
- displaycolumns = element.ColumnHeadings
- else:
- displaycolumns = []
- for i, should_display in enumerate(element.ColumnsToDisplay):
- if should_display:
- displaycolumns.append(element.ColumnHeadings[i])
- column_headings = element.ColumnHeadings
- # ------------- GET THE TREEVIEW WIDGET -------------
- element.TKTreeview = element.Widget = ttk.Treeview(element_frame, columns=column_headings,
- displaycolumns=displaycolumns,
- show='tree headings' if column_headings is not None else 'tree',
- height=height,
- selectmode=element.SelectMode)
- treeview = element.TKTreeview
- max_widths = {}
- for key, node in element.TreeData.tree_dict.items():
- for i, value in enumerate(node.values):
- max_width = max_widths.get(i, 0)
- if len(str(value)) > max_width:
- max_widths[i] = len(str(value))
-
- if element.ColumnHeadings is not None:
- for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings
- treeview.heading(heading, text=heading)
- if element.AutoSizeColumns:
- max_width = max_widths.get(i, 0)
- max_width = max(max_width, len(heading))
- width = min(element.MaxColumnWidth, max_width+1)
- else:
- try:
- width = element.ColumnWidths[i]
- except:
- width = element.DefaultColumnWidth
- treeview.column(heading, width=width * _char_width_in_pixels(font) + 10, anchor=anchor)
-
- def add_treeview_data(node):
- """
-
- :param node:
- :type node:
-
- """
- if node.key != '':
- if node.icon:
- if node.icon not in element.image_dict:
- if type(node.icon) is bytes:
- photo = tk.PhotoImage(data=node.icon)
- else:
- photo = tk.PhotoImage(file=node.icon)
- element.image_dict[node.icon] = photo
- else:
- photo = element.image_dict.get(node.icon)
-
- node.photo = photo
- try:
- id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, open=element.ShowExpanded, image=node.photo)
- element.IdToKey[id] = node.key
- element.KeyToID[node.key] = id
- except Exception as e:
- print('Error inserting image into tree', e)
- else:
- id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, open=element.ShowExpanded)
- element.IdToKey[id] = node.key
- element.KeyToID[node.key] = id
-
- for node in node.children:
- add_treeview_data(node)
-
- add_treeview_data(element.TreeData.root_node)
- treeview.column('#0', width=element.Col0Width * _char_width_in_pixels(font), anchor=tk.W)
- treeview.heading('#0', text=element.col0_heading)
-
- # ----- configure colors -----
- # style_name = str(element.Key) + '.Treeview'
- style_name = _make_ttk_style_name('.Treeview', element, primary_style=True)
- tree_style = ttk.Style()
- _change_ttk_theme(tree_style, toplevel_form.TtkTheme)
-
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- tree_style.configure(style_name, background=element.BackgroundColor, fieldbackground=element.BackgroundColor)
- if element.SelectedRowColors[1] is not None:
- tree_style.map(style_name, background=_fixed_map(tree_style, style_name, 'background', element.SelectedRowColors))
- if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
- tree_style.configure(style_name, foreground=element.TextColor)
- if element.SelectedRowColors[0] is not None:
- tree_style.map(style_name, foreground=_fixed_map(tree_style, style_name, 'foreground', element.SelectedRowColors))
- if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT:
- tree_style.configure(style_name + '.Heading', foreground=element.HeaderTextColor)
- if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT:
- tree_style.configure(style_name + '.Heading', background=element.HeaderBackgroundColor)
- if element.HeaderFont is not None:
- tree_style.configure(style_name + '.Heading', font=element.HeaderFont)
- else:
- tree_style.configure(style_name + '.Heading', font=font)
- if element.HeaderBorderWidth is not None:
- tree_style.configure(style_name + '.Heading', borderwidth=element.HeaderBorderWidth)
- if element.HeaderRelief is not None:
- tree_style.configure(style_name + '.Heading', relief=element.HeaderRelief)
- tree_style.configure(style_name, font=font)
- if element.RowHeight:
- tree_style.configure(style_name, rowheight=element.RowHeight)
- else:
- tree_style.configure(style_name, rowheight=_char_height_in_pixels(font))
- if element.BorderWidth is not None:
- tree_style.configure(style_name, borderwidth=element.BorderWidth)
-
- treeview.configure(style=style_name) # IMPORTANT! Be sure and set the style name for this widget
-
- if not element.HideVerticalScroll:
- _make_ttk_scrollbar(element, 'v', toplevel_form)
-
- element.Widget.configure(yscrollcommand=element.vsb.set)
- element.vsb.pack(side=tk.RIGHT, fill='y')
-
- # Horizontal scrollbar
- if not element.VerticalScrollOnly:
- # element.Widget.config(wrap='none')
- _make_ttk_scrollbar(element, 'h', toplevel_form)
- element.hsb.pack(side=tk.BOTTOM, fill='x')
- element.Widget.configure(xscrollcommand=element.hsb.set)
-
- if not element.HideVerticalScroll or not element.VerticalScrollOnly:
- # Chr0nic
- element.Widget.bind("", lambda event, em=element: testMouseHook(em))
- element.Widget.bind("", lambda event, em=element: testMouseUnhook(em))
-
-
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
- element.TKTreeview.pack(side=tk.LEFT, padx=0, pady=0, expand=expand, fill=fill)
- element_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=expand, fill=fill)
- if element.visible is False:
- element._pack_forget_save_settings(alternate_widget=element.element_frame) # seems like it should be the frame if following other elements conventions
- # element.TKTreeview.pack_forget()
- treeview.bind("<>", element._treeview_selected)
- if element.Tooltip is not None: # tooltip
- element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip,
- timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- if tclversion_detailed == '8.6.9' and ENABLE_TREEVIEW_869_PATCH:
- # print('*** tk version 8.6.9 detected.... patching ttk treeview code ***')
- tree_style.map(style_name,
- foreground=_fixed_map(tree_style, style_name, 'foreground', element.SelectedRowColors),
- background=_fixed_map(tree_style, style_name, 'background', element.SelectedRowColors))
-
- # ------------------------- Separator placement element ------------------------- #
- elif element_type == ELEM_TYPE_SEPARATOR:
- element = element # type: VerticalSeparator
- # style_name = str(element.Key) + "Line.TSeparator"
- style_name = _make_ttk_style_name(".Line.TSeparator", element, primary_style=True)
- style = ttk.Style()
-
- _change_ttk_theme(style, toplevel_form.TtkTheme)
-
- if element.color not in (None, COLOR_SYSTEM_DEFAULT):
- style.configure(style_name, background=element.color)
- separator = element.Widget = ttk.Separator(tk_row_frame, orient=element.Orientation, )
-
- expand, fill, row_should_expand, row_fill_direction = _add_expansion(element, row_should_expand, row_fill_direction)
-
- if element.Orientation.startswith('h'):
- separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.X, expand=True)
- else:
- separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.Y, expand=False)
- element.Widget.configure(style=style_name) # IMPORTANT! Apply the style
- # ------------------------- SizeGrip placement element ------------------------- #
- elif element_type == ELEM_TYPE_SIZEGRIP:
- element = element # type: Sizegrip
- style_name = "Sizegrip.TSizegrip"
- style = ttk.Style()
-
- _change_ttk_theme(style, toplevel_form.TtkTheme)
-
- size_grip = element.Widget = ttk.Sizegrip(tk_row_frame)
- toplevel_form.sizegrip_widget = size_grip
- # if no size is specified, then use the background color for the window
- if element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- style.configure(style_name, background=element.BackgroundColor)
- else:
- style.configure(style_name, background=toplevel_form.TKroot['bg'])
- size_grip.configure(style=style_name)
-
- size_grip.pack(side=tk.BOTTOM, anchor='se', padx=elementpad[0], pady=elementpad[1], fill=tk.X, expand=True)
- # tricky part of sizegrip... it shouldn't cause the row to expand, but should expand and should add X axis if
- # not already filling in that direction. Otherwise, leaves things alone!
- # row_should_expand = True
- row_fill_direction = tk.BOTH if row_fill_direction in (tk.Y, tk.BOTH) else tk.X
- # ------------------------- StatusBar placement element ------------------------- #
- elif element_type == ELEM_TYPE_STATUSBAR:
- # auto_size_text = element.AutoSizeText
- display_text = element.DisplayText # text to display
- if auto_size_text is False:
- width, height = element_size
- else:
- lines = display_text.split('\n')
- max_line_len = max([len(l) for l in lines])
- num_lines = len(lines)
- if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap
- width = element_size[0]
- else:
- width = max_line_len
- height = num_lines
- # ---===--- LABEL widget create and place --- #
- stringvar = tk.StringVar()
- element.TKStringVar = stringvar
- stringvar.set(display_text)
- if auto_size_text:
- width = 0
- if element.Justification is not None:
- justification = element.Justification
- elif toplevel_form.TextJustification is not None:
- justification = toplevel_form.TextJustification
- else:
- justification = DEFAULT_TEXT_JUSTIFICATION
- justify = tk.LEFT if justification.startswith('l') else tk.CENTER if justification.startswith('c') else tk.RIGHT
- anchor = tk.NW if justification.startswith('l') else tk.N if justification.startswith('c') else tk.NE
- # tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height,
- # justify=justify, bd=border_depth, font=font)
- tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width,
- height=height,
- justify=justify, bd=border_depth, font=font)
- # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
- wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels
- if not auto_size_text and height == 1:
- wraplen = 0
- # print("wraplen, width, height", wraplen, width, height)
- tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
- if element.Relief is not None:
- tktext_label.configure(relief=element.Relief)
- if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- tktext_label.configure(background=element.BackgroundColor)
- if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
- tktext_label.configure(fg=element.TextColor)
- tktext_label.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.X, expand=True)
- row_fill_direction = tk.X
- if element.visible is False:
- element._pack_forget_save_settings()
- # tktext_label.pack_forget()
- element.TKText = tktext_label
- if element.ClickSubmits:
- tktext_label.bind('', element._TextClickedHandler)
- if element.Tooltip is not None:
- element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
- _add_right_click_menu_and_grab(element)
-
- # ............................DONE WITH ROW pack the row of widgets ..........................#
- # done with row, pack the row of widgets
- # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0])
-
- anchor = 'nw'
-
- if row_justify.lower().startswith('c'):
- anchor = 'n'
- side = tk.LEFT
- elif row_justify.lower().startswith('r'):
- anchor = 'ne'
- side = tk.RIGHT
- elif row_justify.lower().startswith('l'):
- anchor = 'nw'
- side = tk.LEFT
-
- tk_row_frame.pack(side=tk.TOP, anchor=anchor, padx=0, pady=0, expand=row_should_expand, fill=row_fill_direction)
- if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- tk_row_frame.configure(background=form.BackgroundColor)
-
- return
-
-
-def _get_hidden_master_root():
- """
- Creates the hidden master root window. This window is never visible and represents the overall "application"
- """
-
- # if one is already made, then skip making another
- if Window.hidden_master_root is None:
- Window._IncrementOpenCount()
- Window.hidden_master_root = tk.Tk()
- Window.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really
- # if not running_mac():
- try:
- Window.hidden_master_root.wm_overrideredirect(True)
- except Exception as e:
- if not running_mac():
- print('* Error performing wm_overrideredirect while hiding the hidden master root*', e)
- Window.hidden_master_root.withdraw()
- return Window.hidden_master_root
-
-
-def _no_titlebar_setup(window):
- """
- Does the operations required to turn off the titlebar for the window.
- The Raspberry Pi required the settings to be make after the window's creation.
- Calling twice seems to have had better overall results so that's what's currently done.
- The MAC has been the problem with this feature. It's been a chronic problem on the Mac.
- :param window: window to turn off the titlebar if indicated in the settings
- :type window: Window
- """
- try:
- if window.NoTitleBar:
- if running_linux():
- # window.TKroot.wm_attributes("-type", 'splash')
- window.TKroot.wm_attributes("-type", 'dock')
- else:
- window.TKroot.wm_overrideredirect(True)
- # Special case for Mac. Need to clear flag again if not tkinter version 8.6.10+
- # Previously restricted patch to only certain tkinter versions. Now use the patch setting exclusively regardless of tk ver
- # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH and (sum([int(i) for i in tclversion_detailed.split('.')]) < 24):
- # if running_mac() and ENABLE_MAC_NOTITLEBAR_PATCH:
- if _mac_should_apply_notitlebar_patch():
- print('* Applying Mac no_titlebar patch *')
- window.TKroot.wm_overrideredirect(False)
- except Exception as e:
- warnings.warn('** Problem setting no titlebar {} **'.format(e), UserWarning)
-
-
-# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----#
-def StartupTK(window):
- """
- NOT user callable
- Creates the window (for real) lays out all the elements, etc. It's a HUGE set of things it does. It's the basic
- "porting layer" that will change depending on the GUI framework PySimpleGUI is running on top of.
-
- :param window: you window object
- :type window: (Window)
-
- """
- window = window # type: Window
- # global _my_windows
- # ow = _my_windows.NumOpenWindows
- ow = Window.NumOpenWindows
- # print('Starting TK open Windows = {}'.format(ow))
- if ENABLE_TK_WINDOWS:
- root = tk.Tk()
- elif not ow and not window.ForceTopLevel:
- # if first window being created, make a throwaway, hidden master root. This stops one user
- # window from becoming the child of another user window. All windows are children of this hidden window
- _get_hidden_master_root()
- root = tk.Toplevel(class_=window.Title)
- else:
- root = tk.Toplevel(class_=window.Title)
- if window.DebuggerEnabled:
- root.bind('', window._callback_main_debugger_window_create_keystroke)
- root.bind('', window._callback_popout_window_create_keystroke)
-
- # If location is None, then there's no need to hide the window. Let it build where it is going to end up being.
- if DEFAULT_HIDE_WINDOW_WHEN_CREATING is True and window.Location is not None:
- try:
- if not running_mac() or \
- (running_mac() and not window.NoTitleBar) or \
- (running_mac() and window.NoTitleBar and not _mac_should_apply_notitlebar_patch()):
-
- root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
- except Exception as e:
- print('*** Exception setting alpha channel to zero while creating window ***', e)
-
- if window.BackgroundColor is not None and window.BackgroundColor != COLOR_SYSTEM_DEFAULT:
- root.configure(background=window.BackgroundColor)
- Window._IncrementOpenCount()
-
- window.TKroot = root
-
- window._create_thread_queue()
-
- # for the Raspberry Pi. Need to set the attributes here, prior to the building of the window
- # so going ahead and doing it for all platforms, in addition to doing it after the window is packed
- # 2023-April - this call seems to be causing problems on MacOS 13.2.1 Ventura. Input elements become non-responsive
- # if this call is made here and at the end of building the window
- if not running_mac():
- _no_titlebar_setup(window)
-
- if not window.Resizable:
- root.resizable(False, False)
-
- if window.DisableMinimize:
- root.attributes("-toolwindow", 1)
-
- if window.KeepOnTop:
- root.wm_attributes("-topmost", 1)
-
- if window.TransparentColor is not None:
- window.SetTransparentColor(window.TransparentColor)
-
- if window.scaling is not None:
- root.tk.call('tk', 'scaling', window.scaling)
-
- _convert_window_to_tk(window)
-
- # Make moveable window
- if (window.GrabAnywhere is not False and not (
- window.NonBlocking and window.GrabAnywhere is not True)):
- if not (ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR and running_mac() and not window.NoTitleBar):
- root.bind("", window._StartMoveGrabAnywhere)
- root.bind("", window._StopMove)
- root.bind("", window._OnMotionGrabAnywhere)
- if (window.GrabAnywhereUsingControlKey is not False and not (
- window.NonBlocking and window.GrabAnywhereUsingControlKey is not True)):
- root.bind("", window._StartMoveUsingControlKey)
- root.bind("", window._StopMove)
- root.bind("", window._OnMotionUsingControlKey)
- # also enable movement using Control + Arrow key
- root.bind("", window._move_callback)
- root.bind("", window._move_callback)
- root.bind("", window._move_callback)
- root.bind("", window._move_callback)
-
- window.set_icon(window.WindowIcon)
- try:
- alpha_channel = 1 if window.AlphaChannel is None else window.AlphaChannel
- root.attributes('-alpha', alpha_channel) # Make window visible again
- except Exception as e:
- print('**** Error setting Alpha Channel to {} after window was created ****'.format(alpha_channel), e)
- # pass
-
- if window.ReturnKeyboardEvents and not window.NonBlocking:
- root.bind("", window._KeyboardCallback)
- root.bind("", window._MouseWheelCallback)
- root.bind("", window._MouseWheelCallback)
- root.bind("", window._MouseWheelCallback)
- elif window.ReturnKeyboardEvents:
- root.bind("", window._KeyboardCallback)
- root.bind("", window._MouseWheelCallback)
- root.bind("