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 62688945..05026c02 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
@@ -60,13 +60,11 @@ Anything else you think would be helpful?
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. It is recommend you use the Demo Browser! Demos.PySimpleGUI.org
-- [ ] None of your GUI code was generated by an AI algorithm like GPT
+- [ ] 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
-- [ ] Have upgraded to the latest release of PySimpleGUI on PyPI (lastest official version)
- [ ] Tried using the PySimpleGUI.py file on GitHub. Your problem may have already been fixed but not released
#### Detailed Description
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/Chess/ChessPiecesArray.png b/Chess/ChessPiecesArray.png
new file mode 100644
index 00000000..101c0c9d
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 00000000..cf6cbc99
--- /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 00000000..279e0ce1
--- /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 00000000..453cb323
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 00000000..26dae01c
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 00000000..09ffa6d6
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 00000000..1dda9fbd
--- /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 00000000..6e6030b3
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 00000000..0d94a1c2
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 00000000..a4fe68c8
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 00000000..8e3d04e6
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 00000000..2d716b15
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 00000000..c52b6779
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 00000000..ab73bae6
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 00000000..945a4898
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 00000000..6662f323
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 00000000..e28cbb17
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 00000000..34da37f9
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 00000000..a4798350
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 00000000..a05034ab
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 00000000..54231369
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 00000000..afaab485
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 00000000..8b18a6f5
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 00000000..31522a36
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 00000000..c432d38a
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 00000000..e98fae2b
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 00000000..225f869e
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 00000000..d7341649
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 00000000..037f5100
--- /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 00000000..5003cd5f
--- /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 00000000..b9748e87
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 00000000..a805de49
Binary files /dev/null and b/Chess/rookw.png differ
diff --git a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py b/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py
index f7c4a84d..406ea19f 100644
--- a/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py
+++ b/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py
@@ -5,7 +5,7 @@ import warnings
import PySimpleGUI as sg
-__version__ = '1.12.2'
+__version__ = '1.7.0'
"""
PySimpleGUI Demo Program Browser
@@ -33,15 +33,9 @@ __version__ = '1.12.2'
Keeps a "history" of the previously chosen folders to easy switching between projects
- Versions:
- 1.8.0 - Addition of option to show ALL file types, not just Python files
- 1.12.0 - Fix for problem with spaces in filename and using an editor specified in the demo program settings
- 1.12.2 - Better error handling for no editor configured
Copyright 2021, 2022 PySimpleGUI.org
"""
-python_only = True
-
def get_file_list_dict():
"""
Returns dictionary of files
@@ -56,7 +50,7 @@ def get_file_list_dict():
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'):
+ 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
@@ -462,7 +456,7 @@ def make_window():
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.Listbox(values=get_file_list(), select_mode=sg.SELECT_MODE_EXTENDED, size=(50,20), bind_return_key=True, key='-DEMO LIST-')],
[sg.Text('Filter (F1):', tooltip=filter_tooltip), 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')],
@@ -474,7 +468,7 @@ def make_window():
[sg.Text('Find (F3):', 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, expand_x=True, expand_y=True, key=ML_KEY, reroute_stdout=True, echo_stdout_stderr=True, reroute_cprint=True)],
+ [sg.Multiline(size=(70, 21), write_only=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))],
@@ -485,8 +479,7 @@ def make_window():
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=not python_only, enable_events=True, k='-SHOW ALL FILES-'),
+ sg.CB('Wait for Runs to Complete', default=False, enable_events=True, k='-WAIT-')
]],
pad=(0,0), k='-OPTIONS BOTTOM-', expand_x=True, expand_y=False), expand_x=True, expand_y=False)
@@ -497,15 +490,16 @@ def make_window():
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()]]
+ [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, k='-PANE-')],
+ [options_at_bottom]]
# --------------------------------- 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)
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['-DEMO LIST-'].expand(True, True, True)
+ window[ML_KEY].expand(True, True, True)
+ window['-PANE-'].expand(True, True, True)
window.bind('', '-FOCUS FILTER-')
window.bind('', '-FOCUS FIND-')
@@ -527,12 +521,11 @@ def main():
The main program that contains the event loop.
It will call the make_window function to create the window.
"""
- global python_only
try:
version = sg.version
version_parts = version.split('.')
major_version, minor_version = int(version_parts[0]), int(version_parts[1])
- if major_version < 4 or (major_version== 4 and minor_version < 32):
+ if major_version < 4 or minor_version < 32:
sg.popup('Warning - Your PySimpleGUI version is less then 4.35.0',
'As a result, you will not be able to use the EDIT features of this program',
'Please upgrade to at least 4.35.0',
@@ -577,16 +570,16 @@ def main():
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')
+ # if line != 1:
+ if using_local_editor():
+ sg.execute_command_subprocess(editor_program, full_filename)
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}"')
+ try:
+ sg.execute_editor(full_filename, line_number=int(line))
+ except:
+ sg.execute_command_subprocess(editor_program, full_filename)
+ # else:
+ # sg.execute_editor(full_filename)
else:
sg.cprint('Editing canceled')
elif event == 'Run':
@@ -724,17 +717,6 @@ def main():
sg.clipboard_set(full_filename)
elif event == 'Version':
sg.popup_scrolled(sg.get_versions(), keep_on_top=True, non_blocking=True)
- elif event == '-SHOW ALL FILES-':
- python_only = not 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.close()
diff --git a/DemoPrograms/Demo_All_Elements.py b/DemoPrograms/Demo_All_Elements.py
index 4566c226..c9e8885b 100644
--- a/DemoPrograms/Demo_All_Elements.py
+++ b/DemoPrograms/Demo_All_Elements.py
@@ -11,7 +11,7 @@
Displays the values dictionary entry for each element
And more!
- Copyright 2021, 2022, 2023 PySimpleGUI
+ Copyright 2021 PySimpleGUI
"""
import PySimpleGUI as sg
@@ -36,7 +36,7 @@ def make_window(theme):
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.Combo(values=('Combo 1', 'Combo 2', 'Combo 3'), default_value='Combo 1', readonly=True, 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-')],
@@ -88,17 +88,20 @@ def make_window(theme):
]]
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 = 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,
+ # scaling=2.0,
+ )
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
+ window['-GIF-IMAGE-'].update_animation(sg.DEFAULT_BASE64_LOADING_GIF, time_between_frames=100)
if event not in (sg.TIMEOUT_EVENT, sg.WIN_CLOSED):
print('============ Event = ', event, ' ==============')
print('-------- Values Dictionary (key=value) --------')
@@ -107,9 +110,7 @@ def main():
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':
+ elif event == 'About':
print("[LOG] Clicked About!")
sg.popup('PySimpleGUI Demo All Elements',
'Right click anywhere to see right click menu',
@@ -150,7 +151,7 @@ def main():
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)
+ sg.popup(sg.get_versions(), keep_on_top=True)
window.close()
exit(0)
diff --git a/DemoPrograms/Demo_All_Elements_Simple.py b/DemoPrograms/Demo_All_Elements_Simple.py
index 7e28b293..fffe50ed 100644
--- a/DemoPrograms/Demo_All_Elements_Simple.py
+++ b/DemoPrograms/Demo_All_Elements_Simple.py
@@ -8,8 +8,7 @@ import PySimpleGUI as sg
Copyright 2022 PySimpleGUI
"""
-
-use_custom_titlebar = True if sg.running_trinket() else False
+use_custom_titlebar = False
def make_window(theme=None):
@@ -51,7 +50,7 @@ def make_window(theme=None):
[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))],
+ layout_r = [[name('Canvas'), sg.Canvas(background_color=sg.theme_button_color()[1], size=(125,50))],
[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)],
@@ -69,9 +68,9 @@ def make_window(theme=None):
# 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)]]
+ [sg.Checkbox('Use Custom Titlebar & Menubar', sg.theme_use_custom_titlebar(), enable_events=True, k='-USE CUSTOM TITLEBAR-')],
+ [sg.T('PySimpleGUI Elements - Use Combo to Change Themes', font='_ 18', justification='c', expand_x=True)],
+ [sg.Col(layout_l), sg.Col(layout_r)]]
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)
@@ -88,7 +87,8 @@ while True:
# sg.Print(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
-
+ if event == 'Edit Me':
+ sg.execute_editor(__file__)
if values['-COMBO-'] != sg.theme():
sg.theme(values['-COMBO-'])
window.close()
@@ -98,10 +98,8 @@ while True:
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)
+ sg.popup_scrolled(sg.get_versions(), __file__, keep_on_top=True, non_blocking=True)
window.close()
diff --git a/DemoPrograms/Demo_Bar_Chart.py b/DemoPrograms/Demo_Bar_Chart.py
index 81a772f9..51d8e1b0 100644
--- a/DemoPrograms/Demo_Bar_Chart.py
+++ b/DemoPrograms/Demo_Bar_Chart.py
@@ -1,21 +1,22 @@
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 2022 PySimpleGUI
-"""
-
+# Bars drawing in PySimpleGUI
+#
+# .--.
+# | |
+# .--.| |.--.
+# | || || |
+# | || || |
+# | || || |
+# .--.| || || |
+# .--.| || || || |.--.
+# | || || || || || |
+# | || || || || || |
+# .--.| || || || || || |.--.
+# | || || || || || || || |.--.
+# | || || || || || || || || |
+# '--''--''--''--''--''--''--''--''--'
BAR_WIDTH = 50 # width of each bar
@@ -37,13 +38,12 @@ while True:
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, GRAPH_SIZE[1])
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])
+ 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')
+ graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
# Normally at the top of the loop, but because we're drawing the graph first, making it at the bottom
event, values = window.read()
diff --git a/DemoPrograms/Demo_Button_Can_Button_Images.py b/DemoPrograms/Demo_Button_Can_Button_Images.py
deleted file mode 100644
index 83a9d75c..00000000
--- a/DemoPrograms/Demo_Button_Can_Button_Images.py
+++ /dev/null
@@ -1,49 +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 2022 PySimpleGUI
-"""
-
-
-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_Simulated_With_Highlighting_Using_Bind.py b/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py
deleted file mode 100644
index 5835af7e..00000000
--- a/DemoPrograms/Demo_Button_Simulated_With_Highlighting_Using_Bind.py
+++ /dev/null
@@ -1,79 +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 2022 PySimpleGUI.org
-"""
-
-# 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_Buttons_Base64_Simple.py b/DemoPrograms/Demo_Buttons_Base64_Simple.py
index afc4a920..87e893fd 100644
--- a/DemoPrograms/Demo_Buttons_Base64_Simple.py
+++ b/DemoPrograms/Demo_Buttons_Base64_Simple.py
@@ -1,12 +1,5 @@
+#!/usr/bin/env python
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 2022 PySimpleGUI
-"""
# First the button images
@@ -14,19 +7,24 @@ play = b'iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABmJLR0QA/wD/AP+gvaeTAAA
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')
+sg.theme('Light Green 3') # Set a color theme
+
+bg = sg.LOOK_AND_FEEL_TABLE[sg.CURRENT_LOOK_AND_FEEL]['BACKGROUND'] # Get the background for the current theme
# 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)] ]
+layout = [ [sg.Text('Your Application', font='Any 15')],
+ [sg.Text('Event = '), sg.Text(size=(12,1), key='-OUT-')],
+ [sg.Button(image_data=play, key='Play', border_width=0, button_color=(bg, bg)),
+ sg.Button(image_data=stop, key='Stop', button_color=(bg, bg), border_width=0),
+ sg.Button(image_data=eject, key='Exit', button_color=(bg, bg), border_width=0)] ]
# Create the window
-window = sg.Window('Simple Base64 Buttons', layout)
+window = sg.Window('Window Title', 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
+ if event in (sg.WIN_CLOSED, 'Exit'): # If the user exits
break
-window.close() # Exiting so clean up
+ window['-OUT-'].Update(event) # Output the event to the window
+window.close(); del window # Exiting so clean up
diff --git a/DemoPrograms/Demo_Buttons_Nice_Graphics.py b/DemoPrograms/Demo_Buttons_Nice_Graphics.py
index 45b3c915..3d372416 100644
--- a/DemoPrograms/Demo_Buttons_Nice_Graphics.py
+++ b/DemoPrograms/Demo_Buttons_Nice_Graphics.py
@@ -26,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()
diff --git a/DemoPrograms/Demo_CLI_or_GUI.py b/DemoPrograms/Demo_CLI_or_GUI.py
deleted file mode 100644
index 78996580..00000000
--- a/DemoPrograms/Demo_CLI_or_GUI.py
+++ /dev/null
@@ -1,26 +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 2022 PySimpleGUI
-"""
-
-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_Chat.py b/DemoPrograms/Demo_Chat.py
index d3b81381..76b9a635 100644
--- a/DemoPrograms/Demo_Chat.py
+++ b/DemoPrograms/Demo_Chat.py
@@ -4,28 +4,25 @@ import PySimpleGUI as sg
'''
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 2023 PySimpleGUI
-
'''
sg.theme('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'))],
- [sg.Multiline(size=(70, 5), enter_submits=True, key='-QUERY-', do_not_clear=False),
+ [sg.Multiline(size=(70, 5), enter_submits=False, 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', layout, font=('Helvetica', ' 13'), default_button_element_size=(8,2), use_default_focus=False)
while True: # The Event Loop
- event, values = window.read()
+ event, value = window.read()
if event in (sg.WIN_CLOSED, '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)
-window.close()
+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 a0205488..00000000
--- a/DemoPrograms/Demo_Checkboxes_Custom.py
+++ /dev/null
@@ -1,45 +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 2022 PySimpleGUI
-"""
-
-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
index 4cf359c3..99995ee8 100644
--- a/DemoPrograms/Demo_Class_Wrapper.py
+++ b/DemoPrograms/Demo_Class_Wrapper.py
@@ -4,38 +4,10 @@ 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 2022, 2023 PySimpleGUI
+ Copyright 2022 PySimpleGUI
"""
-'''
- 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):
@@ -63,41 +35,3 @@ class SampleGUI():
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_Cursor_Previewer.py b/DemoPrograms/Demo_Cursor_Previewer.py
deleted file mode 100644
index 70bcb33d..00000000
--- a/DemoPrograms/Demo_Cursor_Previewer.py
+++ /dev/null
@@ -1,48 +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 2022 PySimpleGUI
-
-"""
-
-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
index b1ffd018..e050022e 100644
--- a/DemoPrograms/Demo_Cursors.py
+++ b/DemoPrograms/Demo_Cursors.py
@@ -9,11 +9,11 @@ import webbrowser
If you want no cursor, set the cursor to the string 'none'.
- Copyright 2021, 2022 PySimpleGUI
+ Copyright 2021 PySimpleGUI
"""
# Here is a more complete list of cursors you can choose from
-cursors = sg.TKINTER_CURSORS
+cursors = ('X_cursor', 'no', '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','no','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','arrow','center_ptr','crosshair','fleur','ibeam','icon','sb_h_double_arrow','sb_v_double_arrow','watch','xterm','no','starting','size','size_ne_sw','size_ns','size_nw_se','size_we','uparrow','wait','arrow','cross','crosshair','ibeam','plus','watch','xterm')
sg.theme('Light Blue 2')
diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py
index c4748172..97b164ce 100644
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py
@@ -274,7 +274,7 @@ def main(location):
[sg.T(size=(5, 1), font='Any 20', justification='c', background_color='black', k='-gauge VALUE-')]]
- window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True)
+ window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
gauge = Gauge(pointer_color=sg.theme_text_color(), clock_color=sg.theme_text_color(), major_tick_color=sg.theme_text_color(),
minor_tick_color=sg.theme_input_background_color(), pointer_outer_color=sg.theme_text_color(), major_tick_start_radius=45,
@@ -298,8 +298,6 @@ def main(location):
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_Desktop_Widget_CPU_Square.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py
index 866b1bac..c4636477 100644
--- a/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py
+++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py
@@ -23,7 +23,7 @@ def main(location):
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)
+ window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
text_id2 = graph.draw_text(f'CPU', (GSIZE[0] // 2, GSIZE[1] // 4), font='Any 20', text_location=sg.TEXT_LOCATION_CENTER, color=sg.theme_button_color()[0])
@@ -46,8 +46,6 @@ def main(location):
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)
diff --git a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py b/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py
index 2e5f6bb0..8ee2c959 100644
--- a/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py
+++ b/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py
@@ -1,12 +1,8 @@
import PySimpleGUI as sg
import datetime
-import PIL
-from PIL import Image
+import PIL.Image, PIL.ImageTk
import random
import os
-import io
-import base64
-
"""
Another simple Desktop Widget using PySimpleGUI
@@ -20,76 +16,17 @@ import base64
* How long to show the image and if you wnt this time to vary semi-randomly
* Folder containing your images
- Copyright 2021, 2023 PySimpleGUI
+ Copyright 2021 PySimpleGUI
"""
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 convert_to_bytes(file_or_bytes, resize=None):
+ image = PIL.Image.open(file_or_bytes)
+ image.thumbnail(resize)
+ photo_img = PIL.ImageTk.PhotoImage(image)
+ return photo_img
def choose_theme(location):
@@ -106,15 +43,6 @@ def choose_theme(location):
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)
@@ -133,7 +61,7 @@ def make_window(location):
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)
+ 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)
return window
@@ -141,10 +69,11 @@ def make_window(location):
def main():
loc = sg.user_settings_get_entry('-location-', (None, None))
sg.theme(sg.user_settings_get_entry('-theme-', None))
+ window = make_window(loc)
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))
+ width, height = sg.user_settings_get_entry('-image size-', (400,300))
image_folder = sg.user_settings_get_entry('-image_folder-', None)
try:
@@ -153,26 +82,36 @@ def main():
image_folder = None
sg.user_settings_set_entry('-image_folder-', None)
- image_name = single_image = sg.user_settings_get_entry('-single image-', None)
+ 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:
+ while True:
+ images = None
+ image_folder = sg.popup_get_folder('Choose location of your images', location=window.current_location(), keep_on_top=True)
+ if image_folder is not None:
+ sg.user_settings_set_entry('-image_folder-', image_folder)
+ break
+ else:
+ if sg.popup_yes_no('No folder entered','Go you want to exit the program entirely?', keep_on_top=True) == 'Yes':
+ exit()
+ elif 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
+ # First update the status information
+ # for debugging show the last update date time
+ if single_image is None:
+ image_name =random.choice(images)
+ image_data = convert_to_bytes(os.path.join(image_folder, image_name), (width, height))
+ 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"))
# -------------- 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)
@@ -181,28 +120,6 @@ def main():
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':
@@ -258,15 +175,12 @@ def main():
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)
+ 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()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py
index 8728f238..747c550f 100644
--- a/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py
+++ b/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py
@@ -275,7 +275,7 @@ def main(location):
[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)
+ window = sg.Window('CPU Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, background_color='black', element_justification='c', finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
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,
@@ -290,7 +290,7 @@ def main(location):
if gauge.change():
new_angle = ram_percent*180/100
- window['-gauge VALUE-'].update(f'{ram_percent}%')
+ 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()
@@ -298,13 +298,10 @@ def main(location):
# 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
+ 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()
@@ -314,5 +311,5 @@ if __name__ == '__main__':
location = sys.argv[1].split(',')
location = (int(location[0]), int(location[1]))
else:
- location = sg.user_settings_get_entry('-location-', (None, None))
+ location = (None, None)
main(location)
diff --git a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py b/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py
index 440170df..3d1836b5 100644
--- a/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py
+++ b/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py
@@ -30,7 +30,7 @@ def main(location):
graph = sg.Graph(GSIZE, (0, 0), GSIZE, key='-GRAPH-', enable_events=True)
layout = [[graph]]
- window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, enable_close_attempted_event=True, keep_on_top=True)
+ window = sg.Window('RAM Usage Widget Square', layout, location=location, no_titlebar=True, grab_anywhere=True, margins=(0, 0), element_padding=(0, 0), alpha_channel=ALPHA, finalize=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, enable_close_attempted_event=True)
while True: # Event Loop
@@ -47,10 +47,8 @@ def main(location):
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':
+ 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)
graph.delete_figure(rect_id)
graph.delete_figure(text_id1)
diff --git a/DemoPrograms/Demo_Desktop_Widget_Timer_Using_Window_Timers.py b/DemoPrograms/Demo_Desktop_Widget_Timer_Using_Window_Timers.py
deleted file mode 100644
index 6d697ad8..00000000
--- a/DemoPrograms/Demo_Desktop_Widget_Timer_Using_Window_Timers.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import time
-
-"""
- Demo Program - Timer Desktop Widget using Window.timer_start and Window.timer_stop
-
- This is a re-implementation of the original timer desktop widget that used window.read timeouts as
- the means of getting timer events.
-
- This program uses the new Window.timer_start to get timer events. It is simpler because:
- There is only 1 call to window.read and it's in the standard location in the event loop
- The timer pause/run button uses the timer_start and timer_stop calls - perhaps more intuitive
-
- Note that this Demo Program requires PySimpleGUI 4.60.4.132 and greater
-
- Copyright 2022 PySimpleGUI
-"""
-
-
-def time_as_int():
- return int(round(time.time() * 100))
-
-
-# ---------------- Create Form ----------------
-sg.theme('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),
- finalize=True,
- element_justification='c',
- right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT)
-
-current_time, paused_time, paused = 0, 0, False
-start_time = time_as_int()
-timer_id = window.timer_start(10)
-
-while True:
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'): # ALWAYS give a way out of program
- break
- # --------- Handle events --------
- if event == '-RUN-PAUSE-':
- paused = not paused
- if paused:
- window.timer_stop(timer_id)
- paused_time = time_as_int()
- else:
- timer_id = window.timer_start(10)
- start_time = start_time + time_as_int() - paused_time
- window['-RUN-PAUSE-'].update('Run' if paused else 'Pause')
- elif event == sg.EVENT_TIMER:
- current_time = time_as_int() - start_time
- if event == '-RESET-':
- current_time = 0
- start_time = paused_time = time_as_int()
- elif event == 'Edit Me':
- sg.execute_editor(__file__)
- # --------- Display timer_id in window --------
- window['text'].update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
- (current_time // 100) % 60,
- current_time % 100))
-window.close()
diff --git a/DemoPrograms/Demo_Desktop_Widget_Weather.py b/DemoPrograms/Demo_Desktop_Widget_Weather.py
index a6c2c0ff..3d0dd389 100644
--- a/DemoPrograms/Demo_Desktop_Widget_Weather.py
+++ b/DemoPrograms/Demo_Desktop_Widget_Weather.py
@@ -75,9 +75,8 @@ def change_settings(settings, window_location=(None, None)):
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('-location-', nearest_postal), size=(15, 1), key='-LOCATION-')],
+ [sg.I(settings.get('-country-', 'US'), size=(15, 1), key='-COUNTRY-')],
[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)], ]
@@ -97,7 +96,6 @@ def change_settings(settings, window_location=(None, None)):
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-']
@@ -188,42 +186,43 @@ def metric_row(metric):
sg.Text(APP_DATA[metric], font=('Arial', 10, 'bold'), pad=(0, 0), size=(9, 1), key=metric)]
-def create_window(win_location, settings):
+def create_window(win_location):
""" 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['City'], font=('Arial Rounded MT Bold', 18), pad=((10, 0), (50, 0)), size=(18, 1), background_color=BG_COLOR, text_color=TXT_COLOR, key='City')],
[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')
+ col2 = sg.Column(
+ [[sg.Text('×', font=('Arial Black', 16), pad=(0, 0), justification='right', background_color=BG_COLOR, text_color=TXT_COLOR, enable_events=True, key='-QUIT-')],
+ [sg.Image(data=APP_DATA['Icon'], pad=((5, 10), (0, 0)), 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')
+ 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')
+ top_col = sg.Column([[col1, col2]], pad=(0, 0), background_color=BG_COLOR, key='TopCOL')
- bot_col = sg.Column([[col3, col4]],
- pad=(0, 0), background_color=BG_COLOR, key='BotCOL')
+ 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')
+ 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)]]
+ [sg.Text(f'{sg.ver} {sg.framework_version} {sys.version}', font=('Arial', 8), background_color=BG_COLOR, text_color=TXT_COLOR, pad=(0,0))]]
window = sg.Window(layout=layout, title='Weather Widget', margins=(0, 0), finalize=True, location=win_location,
element_justification='center', keep_on_top=True, no_titlebar=True, grab_anywhere=True, alpha_channel=ALPHA,
@@ -278,36 +277,28 @@ def main(refresh_rate, win_location):
sg.popup_error('Having trouble with location. Your location: ', location)
exit()
- window = create_window(win_location, settings)
-
+ window = create_window(win_location)
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)
+ if event == '-CHANGE-':
+ x, y = window.current_location()
+ settings = change_settings(settings, (x + 200, y+50))
+ elif event == '-REFRESH-':
+ sg.popup_quick_message('Refreshing...', keep_on_top=True, background_color='red', text_color='white',
+ auto_close_duration=3, non_blocking=False, location=(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
+ update_weather()
+ update_metrics(window)
window.close()
diff --git a/DemoPrograms/Demo_Dispatchers.py b/DemoPrograms/Demo_Dispatchers.py
index 2084e9b3..7b9e3987 100644
--- a/DemoPrograms/Demo_Dispatchers.py
+++ b/DemoPrograms/Demo_Dispatchers.py
@@ -12,7 +12,6 @@
* 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
@@ -23,7 +22,7 @@
event loop rather than functions, then do it in the event loop.
http://www.PySimpleGUI.org
- Copyright 2021, 2022, 2023 PySimpleGUI
+ Copyright 2021 PySimpleGUI
"""
import PySimpleGUI as sg
@@ -77,7 +76,7 @@ def main():
[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')]]
+ sg.Button('Tuple', key=(1,2)), sg.Button('Bad')]]
window = sg.Window('Dispatchers', layout, font='Default 16', keep_on_top=True)
diff --git a/DemoPrograms/Demo_Edit_Me_Option.py b/DemoPrograms/Demo_Edit_Me_Option.py
index b5e4be90..c05130f1 100644
--- a/DemoPrograms/Demo_Edit_Me_Option.py
+++ b/DemoPrograms/Demo_Edit_Me_Option.py
@@ -1,7 +1,7 @@
import PySimpleGUI as sg
"""
- Demo "Edit Me" (and Version)
+ Demo "Edit Me"
More and more of these Demos are getting an "Edit me" option added.
@@ -12,26 +12,26 @@ import PySimpleGUI as sg
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 need to do 2 things to make this work:
+ 1. Add a right click menu - requires you to add 1 parameter to your Window creation
+ 2. Add 1 if statement to your event loop.
+
You will need to have first set up your editor by using the menu in sg.main()
- Copyright 2021, 2022, 2023 PySimpleGUI.org
+ Copyright 2021 PySimpleGUI.org
"""
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)
+window = sg.Window('Edit Me Right Click Menu Demo', layout, right_click_menu=[[''], ['Edit Me', '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)
+ sg.execute_editor(__file__)
window.close()
diff --git a/DemoPrograms/Demo_Email_Send.py b/DemoPrograms/Demo_Email_Send.py
index 70515de7..9d443f3a 100644
--- a/DemoPrograms/Demo_Email_Send.py
+++ b/DemoPrograms/Demo_Email_Send.py
@@ -1,36 +1,38 @@
import PySimpleGUI as sg
+# import PySimpleGUIWeb as sg
+# import PySimpleGUIWx as sg
+# import PySimpleGUIQt as sg
'''
- Learn how to send emails from PySimpleGUI using the smtplib and email modules
-
- The GUI portion is simple
-
+ Copyright 2019 PySimpleGUI.org
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 2019, 2022 PySimpleGUI
-
'''
-# 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):
+def send_an_email(from_address, to_address, subject, message_text, user, password):
+ # SMTP Servers for popular free services... add your own if needed. Format is: address, port
+ google_smtp_server = 'smtp.gmail.com', 587
+ microsoft_smtp_server = 'smtp.office365.com', 587
+ yahoo_smtp_server = 'smtp.mail.yahoo.com', 587 # or port 465
+
+ # open the email server connection
+ if 'gmail' in user:
+ smtp_host, smtp_port = google_smtp_server
+ elif 'hotmail' in user or 'live' in user:
+ smtp_host, smtp_port = microsoft_smtp_server
+ elif 'yahoo' in user:
+ smtp_host, smtp_port = yahoo_smtp_server
+ else:
+ sg.popup('Username does not contain a supported email provider')
+ return
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
+ server.login(user=user, password=password)
# create the email message headers and set the payload
msg = EmailMessage()
@@ -40,15 +42,9 @@ def send_an_email(from_address, to_address, subject, message_text, user, passwor
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.send_message(msg)
server.close()
- sg.popup('Email sent successfully!', image=sg.EMOJI_BASE64_HAPPY_JOY)
'''
important notes about using gmail
@@ -65,47 +61,33 @@ def send_an_email(from_address, to_address, subject, message_text, user, passwor
'''
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('User:', size=(8,1)), sg.Input(key='-USER-', size=(35,1))],
[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:
+ while True: # Event Loop
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
if event == 'Send':
- if values['-SMTP HOST-']:
+ if sg.__name__ != 'PySimpleGUIWeb': # auto close popups not yet supported in PySimpleGUIWeb
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
+ 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-'])
window.close()
-if __name__ == '__main__':
- main()
\ No newline at end of file
+main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py b/DemoPrograms/Demo_Emoji_Toolbar_PIL.py
index dd0cecee..0a462226 100644
--- a/DemoPrograms/Demo_Emoji_Toolbar_PIL.py
+++ b/DemoPrograms/Demo_Emoji_Toolbar_PIL.py
@@ -31,7 +31,6 @@ import sys
"""
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
@@ -92,7 +91,7 @@ def convert_to_bytes(file_or_bytes, resize=None, fill=False):
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)
+ img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS)
if fill:
if resize is not None:
img = make_square(img, resize[0])
@@ -122,27 +121,25 @@ 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)
+ :param emoji_names:
+ :type emoji_names:
+ :param file_dict:
+ :type file_dict:
+ :return:
+ :rtype:
+ """
+ button_row1 = [sg.Button(image_data=all_emojis[i][2], border_width=0, tooltip=all_emojis[i][0], key=all_emojis[i], ) for i in range(len(all_emojis) // 2)]
+ button_row2 = [sg.B(image_data=all_emojis[i][2], border_width=0, tooltip=all_emojis[i][0], key=all_emojis[i], ) for i in
+ range(len(all_emojis) // 2, len(all_emojis))]
+ 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 = [sg.vbottom(button_row1 + size_col)]
+ layout += [button_row2]
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)
+ right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_EXIT, keep_on_top=True, button_color='black', location=location)
'''
@@ -167,8 +164,6 @@ def main(location=(None, None)):
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:
@@ -312,79 +307,11 @@ if __name__ == '__main__':
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+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjBBNjk1MDcyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjBBNjk1MDYyOUM1MTFFRDk0OEJBMDM2NDEwQkM3RDQiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsEtZvMAACKCSURBVHja7F0HlFTXef7e9LazvcPSYalGgDACJIQAEzVsbEtWJEtKIstdseP4xImVxO34xEV2fFxOIsmW5ahEjiXLiiSrOaiBMKL3DgJ22TpbZmZnZ3dm3sv/3/em7szbmd0Z2AVdzuXNzrxy3/3uX+9//yspioJsiiRJuBhlXTn4wZOoTteOXGupVlOtpFpKTXPT0U2v4sz2vnRNPx18dE0vHbupdlJto9pK9YxWT1I99ZoHEYzRIo0lAAksIx0WUF1K9Uqqi+ixjdREe+q5RjqzmGCrqoBSSSA7CTqrBXBqZ/LfZlP8/DBB4Pern4MDQCAI9BOEHR4o7R1AjxdSOJwW6DA9/zB93E91G9V3qe4iUAffB1AFrY4ON1P9ED1iDTWnOPpbTRWhuAiYPQOorwEqygEXAWOxMIAGhpEaZlBPlgdG3RZZBgZDBG6AyLELaG4BTpwGtu8G3juXTL3Uzjfo42tU/5fAPHlZAUiguehwO9VPUF3Nt2eKWrmM/lgBzJxKfLGU4DFZCS3ilhbC2FqrVhOhaKIfI0RO/r1AHxFG/wlACRe0oxjcXh/x0/eAzUSHf3oTGIjT4HaqT1F9jMDsuGQBJOCm0eFv6VZ/Q491OYjd3bYRWLVcpTbJVAQ4GqnOAuxTVfCiFMZlsJ2k1g6qu6j3zl109uUhKn2HoHv8d1C6e0UXDdJ7PUk//YSA3HvJAEjAsdLxDbrFvfQ4Q3UllA1/AWndNUBJFekiRcQnnQsJtMlDL2ZKY9B6adgHT41JRaKPWO4bW4DnXyEKPRP7+mmq9xOQx8YtgJpS8hW69Dv0GOv0KSrFrVxmhqGU+KV7uUpp6UrgOIFGfMq3u+DsMZ9lJ9HdY78HDh0SslKm9/4Jff0vBGRgXAFI4M2hS35Nt19aVgrlntshrb3OCalsLZEdkZ7RNfQihYRK71ZSCUk/GDiP8VrayCh5/c/AH18im6RFAHmS+uFuAnHLuACQwLtVA8+x/jrg839thr2egCtdT8DZ02gIpNP3ELV1vaqyzHFeuEsPnyUdi8yUt94GXiVdlXqPqfGrBOK/j2kACbyv0uGHdjuUf/gipBWrZpKGcicpJFVp3jSiAud58ZIALrH09pEJ0qx+bqLj409C6e0RTomfsyJHQCpjDkAC7x/p8G8ltU7ly/dXSXXzPwZr6TUIwYxByYIwTOIzH9v7e7Gl/T20DcoYgBU9KBH38Esu8bsMA7zCwUK6C2yicvFKbvFbusLn8L2GK2ZqhUNHJJUoPeJoIVs9ep4LfmpVmJ4sw614xXduaqGVnuhEn/jdqgygCD5xDVdfhxfGoBdFEbqfz4sXn/Sg/Rg7fvArqvfmA8S8AUjgfYYO/2lbvEB59xubpdtritDoSMMtqT7nAV4hOaHg8iomJYS1v9yIyIsv8p8/JAD/YUwASOBdQz9vMkydZjjwo23SPQ3lqLMMPS9Ej/oPEuoHA7hsi1Xux+oH1iLyzjv8550E4uMXFUACr4R+OijbXXWnH9mGm6fOwew0lBehx/yMwDt8GYMXLaWhNiz+0hLF0NLELrkFo3HFGfLQnh9SI+oi3/4RJlanB48Ls8z3wVNLt7kard94RFIgcW89PJp7jQpAoj6eMbjHtHo1ts38ND5cnqHBIbKJui98R7FiUYxeUcdaOVC9Dspd9/DH1dSPt1wUFkoPflmRDOvPPL4TUycsxMfLZaG5cWXtjLU2CxnnW9pOoMl7Vmht3KkORdXSStAT0+ZYu7Mr/eI61hJZs5OgxDq/SPHBmGZaju9jGcXMDmu8fgx1KhB1oFdSJ0Z8pFtG6On9sAstV1wjqddEtWfWmMVbEVHx5z56A/6bj83BYvTT9z5jCfyGYvjpOChZUTLYhkV3T4cp6D9KMMwhVirnrBiNgvrm0WH93DkG/Ma2AZVFX4FZTsM/w91Y3/11Tf8cg5ohwREdSENklaLDNnJQoY+10SBIER+Dkk0A+sbiMHZsxiyoU2rPXTAAqXyR/7vlhjDqHDzFk0H4eV7OGrwIEVh/UJ2TC1ENBtWJWHYWM6PgCdcBbdovIqvnphaey5OH6VxXmnl7G5mPJqNmJ5IGbTGrn50OdfKYZ05MJnXSWJybQ8/ZLUMBtChBlIdbsXIRGMBof14YAHk+jzjqXRVlwFVLmAdemQERarV3a3zUESib/wy8uxs410w/+ajD+9W5tr5xqODYbSq4DDLX+lrgivnAdVergMdMB0vme1RXAzNmAsePYS3168xcZy9GSoE3cZjD9WtJCzLSUHV9IIM/aXNspvy1N4FfPkYKTS8umRLlAP4+9chTSW/TAH2Y3vOTpJZ87CbqH1ITrWb9+1y5RADIhSe4v3MhABRa0wqOXLFPJw0nQwt73hbU9VNSlP/4p0x6sFEoDGIos9pi1MIkqCoG9cjnCLEjPkcVZyn2fUwsSUO/Sy+/ZEiyPOQ7UVN/lyOCf0viKGu/qd/xb5J2TAWWQdx3EPjnrxC7HKaXZ0zn6ANxm8IDSGTuoH66kdnFlAYWEnPSn9h3hARZu3iRRPDI4Ee4rB6yoxiKyXLJUKMUCcEQ8MLU3QJDn6oUbdsFfO+nBOLf61/LMnUOdeP+fZhL/Tud2OiJQtqBy3lyVsg+IQhmZmCfb2PPAeCZFxJcaZWTMDB5ISLuynEJnjIQhBzog9zPNSD+Vljbog5RSJREisox0DAPg3UzxCQgly3vAq++nhwhl67MnhX7uLbQhvy1/N/C+TzsqFW2CWmUF9JO/Hvw6FMJ1gRRXbhi4vimMlJP5T4fIl0eqp0Id7Yj3N6CUGszIt4ela3y6xdXI1QdjzR47HfEIoeZzGmYlNy/hQTwOhZD8xpZvZqggjiE+rbi9JkwDh3VRi5RW6hq0vjnk/TiprJKQiOl20heyj4vwh2tULTg0nBpLWSbaux3esgWPK5/6/JSNRKPCHd1wQAk/myiByyaNllVoWFryKh9vvlOAkEWVyVHl43nQkqWsbgsPYsldhrxtKt2kQZitOzOIkZt6lRBxFXUzw2FosBZ0eAk1RqtSaNbv0cGXxve2poAoLsCl1Ix2B2QLOllOFOgYKdMmCQTo7Jw7z7VEaFX6utjHxcWCsAr+L8YgNa6oWeQ4X7mHNCkxSQpZluMlVxKxeguyfibHPBDiURIsTEh4iiJmRYnhtEtq6uS+7kQZoSwGaZExZm5KnX4Ab7t2LkvkfrKL0iHymYrAtVT0Ed1kFj2AFE9fyebrGS3hYXtZiY13+L1wNZ1Hs7Wk+IYs/1yVWisNlJqzKoWmsZPqpCmKrnckOn9jX2qT5XlYGNj5ntWxhnV3EIByCuEUFejEa8pZRT2keUa6cPuRACdpQUDbaCkGh0L16Fr1jL4Js4VIz4nIzjQi5KTu1B+8E2UH9oMQyi39RUGhxOR3vSOcDYzDARgxFmCqJvjxDDTtkVF6rqPwUERwV4QAKex8lLGuJmKeUXDEO2THdJ7D0aHqYEMdnfegfPXzcS5NX8Fz+yVMRkzkhJ2FKNz/mpRTf0+1Gz7Aya8+SRP72RHhXYnvXN6ABVCQWikJEJYjEihIDo6SMJ4Abdb3zfa1KQSSt4BpL6aVlsdvTKlFZGgWGhy5Li6fEuMQgYvj9pnxOrE6Ru/gNYlN6UFjtmkxdsBW3crAeKHMeiDcZCMb5NZNbTp+sGiMkG5g0XJrD1sL0LTtXei9YMfwZQXf4bqnS8N3x+kkbJtqIQGMxj+/WK9B1Ohqac1RoWLdCRcBbHRc+fgJk209DUPuvMGIN3Qyku/yqIc0ZgyJ0OGO8vAQwm+9IijOG/g9VdOwsG7v4dg+YSYv9LVfAzFp3fT8Shc54/D5mka6uPMJDMJ1EDNdPhrp8PXMAe905YgWFojgDz+8a/T34sx45nvCxeZLog2mw6ANKidRZCd1A8agGfP6gNYXBT7yIKqO58UKERsaVTspYbG+94Vh6MnEv2eRXkCrwH7PvMLhG0OlB15B5V7XkXp8e0kw7wjNwXCIbiaDotas/159TkVE+CZdy2x1OvQfsV6AtON2Y/9k+q8znQfUmbYiE87SAhAI4162Rbvh6Zm/XYlsFfWEA/nE0BhM5SVxCR4AqkFgMARlUWcThiBeTAfwnSPI3/5TdS98zRq3n0OZn/hgmvsnU2Y8Mbjovomzkbzyk/g1M1fwrTnfqzjXtOZK5IVYkpEwRabULCkSBitraqdb8ggWZyuJArMqwwUY6PIlYaF+naKMHmesG1pi9p/1py1wnTFN2k+5v/yy6OitpGUonOH0fjf3yQg5wjKZHDTk6BRyEK2+zIpM0JOkvyVSOvl0zweMhkqMwyi+ERwSb4BFHzAZk0H4I4Ye4jGSMkWR146svTo1otqsBedOzT8SUyFmQDU5KNsdcAQUGezeU1+JgAtcYK259sTI2jPZosxf419+kh4qJpLa3tCwy02XC5F0uE0UQAT+6OrS38s5EKBuQAoEHM5Ysxfc53tiHkzWjsuUwB1IpyisxNsC0ZLt44YT3CxOvINYIpKaYzLP614EkaWYrJeNgBCT9azxsITvuZ4f/h8Wd3Vkm8AUxpNLDrUrWaIiDpivIkAmi8fCjQM043EodiREAMwj0shR6cm+nchMcLVm9CwxAZf+gjqu/NE9HvCgA7kMYQyFwoc6m7gBAQJJalhBsP7AMYRTHIphkIXB0ABTyg6KclLovuTJ7jCkSTVDO+XoTbjcAAmLFXpyTeAnBwunp2Ip45SFggEB3IYlZdT0VAR8a/IaDIiqX953U2eARTwDEYf4B8a5GG1vI/ViFhsitIa7eF8KzHCeomGkYvUIKlGaOLd2AE8UlcayQtvwxz01U5HxOKAtbcdJSd3FtQPmlbouyvhm9CIiM1Fz/bAfeYgjAN9ur2u+1oax7LpmMjB/riGkW8APcOpwEn2rCJr4eeyFjafXelqXI5TN90XnzZKYEPVu17ClD/+ouB+0UDVZNGGnhlLkwGIhMQ84eRXHhKz+Ula5jDQISEE36jD9/r7k/s7nyy0K9VUGGLpuxJfVmXhHOCTbTm/4lYcuvv7Q8HT2FDb4huw5/MPCcooVGHQ9n7h4SHgRU2j1qUbsOeLDyOYEDKoK9S0tnNcTrTYHVkB2JlvAMWI6NbRjdxFKQBysrBAX3YdN20xTt34xWHPC5bX4/Ad3ylInGmwrE7cOzKMG5DBO3zX92K2rjJMvKBY3RyJn+PQcVMncLj8UuBrHgxQOzydOo7Y8oT4JY4BibIXDvAZrrx3w+ezFva+hrnonLcq7wCeWfcpRKzZzaL01UxF65U3ahQ4jGFHNrGUEDBVpBMT0xMnkKZ8UyCz8TOdOtmFaqoTAVQbzI7eTDPWMbZRMUEEKuVSOj6wNq/gyWYbPDkOio6FH1KvHcy8Rl/S5L9hMK70lekE6jGHo3HsI4Lx5R1AHhVeH6SBDO2tSQgTlQZVZh4N+tGjwkD1tJw7nGNA86q4VDZAznHFFA86hVmjngw0W5L6QwBYpqNodAtCyTqbba4AioCJ5gyZICcl6B6GYF8MQDFKE1bvDB39lhFRTF4p0GIfQRusUAb0Y0mj729IMD+qMuhgfCuNhZ4sFIBivVFza/ofeZ14NOyQZSArMpLFGhP0EV/69dXWnvacO8/a05ZXAC0+z4iuGU7LNmgTfJIWa8octbpah32qH48XFMBzOpFV0xM4GzeaZWBUDsh+rxpql2p+nMtgIOuU0mPb8goghyTaultyuqb42HZ9CmTzgUPwB4Mxs4rBy2QWJ8zUHy4UgCL07PTZzCfMTYj9N2pLjSWbxp44VUhX55D1BPxy9W8/lXUjjAMB1Gx7Nu9aaN3m3+Z0fs1LD+mzT+Y+BKIxEFctJ+ksHOvoSCaUvANImtF5ak9HYuhgauE0G7GbawAaEi1XWUa4sw3KYPLInfjGE3CfOZBVO2Y88z2Y+/Kf7qL2z38QayWyKfUvPwzHsZ36nauFmEX7QXAoHX2tqSk6zLGnUBTIesiu861JHoOkMnmiuqOKqsgQCw2H1JGYOD+ogRjp9qgslbNAkC0199dfRfmhtzO76kgxanziX1Cx//WCeGE4gJcDefXawG2tf/4XmPDf3x3WeyYGLqfpj3IiSV3EmamcPSfOOZWtCSH6ZATvuZPatP4o6UkL56Vl+1i2BHhlk8bufJ1ipSqv5JH9Ce1i1yAnDGBPjcT2olnIy5k//xy8jcvQ8cENCNTNQMTugoUUlhKSNzXv/i/M/d6RTxazFszxKeLhiuqvpcEkfJniMw0kslln/uyz6JmzEm3LN6Jv8nyEHW6YezrgPrIV1X/6LzjOHRl+MFjtYv7P6O+OyT9mn5kc2T296sIXKjtyeaWRACgWT+8/nB5ALtdclQCgt0MF0OlKBjCpY9XlyVHZ6NrxmqjpSihhhGflThNO9dxf0r39ZVFHWoyuotgAjpb58zOf39yU3L8FY6FUOLOXcuCwvhyM5iPj3CnCpGAKs9nzx+8UlRUPWy9CXmcOt2ftk2cfjN7OGGdasEDHlRjfMOStggJI/LmXGrP/4BESXxk8Mpw0jvOFxf7uVg1Ho7v4spipN2jLr029HbEppJkz0ifZi5Zjx1QXGn3cV2gKZDHy8iDpJnt1lMab1yewE15axSmqzBaYKqpiduGlh5wBxrIKGDROY0ywK5d9MPNlHE/L4fbUr6/mmjN0pHMyIu36thSNu8cfD3pit9qCOXE7z3L+mGBprJGaqmpVarxUItcMEgwk88z0XlHN09x+OuY+KyGCnDUr8+Un41tCvZDzo0fY5C1E7j2cRirRvekNkHJDNuIpGnjdxAw+sTGBCkkW2E7tgrG3XfAKQ1ExzDX16ohle2m8sVZJTXRgLC2DuZreo7hUzSHj74L1vT0weeLuqmtX6b/evn0xqf5Srs0YUdAKb0m6rhy/6+rGvbv3A4s04cxpFRlQBo8rL2C65aPA089qoZGkzDAlKh1nRPKfMFUxYqnyQkg27uWBAToGxbIsKMrYAoxEgHCNERcxJNi2PHVm7O6AicydxFkHLitXAEuvzHxbdl6fVF3Xb1C/tl0QALXyBNV7N70dBzA1rSL3/6LFQGk58CyB2KFp1PzCps5zoioWOyKuMsjOEsiOIlV74008FXVxpDAvtCP4yDaVUmCgOH6TtWazVk0WdSFnlIxIFBh4/T0Z6AaiuOjMS5J/l6yIDTcD84ZJGHIwvnptRPtHjDjpOVGggXflMpsw6ckHIXE4RZCI5uB76a9njX7vXmATKcmdOpMPss0plmbzgkjxmY5D8oLy/Bsn0mEwZTWHp5JoOojBE833qQgZFX8HSaUcniWP5h/lz6xYcdKC1Eg6uo9hIACJQGKZZuj3CQ9TJu7gchPLvFqlOvMwqwu4qQ/8O1Fht9jStZY1/AtGgawtEYg/J230gd+T6P2rvwRsFtWECEfSKmi44gp67xIjXnzHiLAngnCPTCwzuSN4NKeOaJHtiSiVl6yJlb+cukN8tqhxKaORn5obT7j8BvyqzUocgmcQDMQOU1li2sFtkmAqNcBcZsCyRQpWzMtuv8MDRH3d6gzEr0cC3mhZKJcHqe++9swLqLjxQ5AqiVUWE8F4dCIo/EEJRgdXE6wTgTpHBNNdYZwiTezM2fQLP7hTjRxjk2nGibP+aqlERKbfKBUlUq5mj4mEBawNcxwLAxfJfXNJK4m/Bmr7lCnETRQjjveYEt4vOyuAJcLLr8R2yf7+SAEYFYA0avxEhfeTQf8Qp1X+9tdI3hXpAziQEv/D5sbKuaqwZ67E68fPkxbLyQBaWtVjz3CrBDj18SBVBPMuElmW1dQAtTXasVadUY9aQHtIZBxPWOMTynI8bHo9Rn0/on48e1EA1ApvpXbHtp1Y9ewfgY03qMrMYIYXSVV03HYlyRHOiW64LkjwG/KcKU928spWjhnp1irvC88Uy9HiAyPYhZxlFO83zx4SPnK+Tk6jwjErJaVq8JFjmCC1YkeyCDBmYZgdO0Eq55vifU/QoP32aDp/1ABqsvCT1JjdD/4GFRxSMZlYy3lPJgCTX9hsyo5l8civrc18Dus1fX3Je0sk7ithU+dWxRJmjiBnwEx5GL6pvgirWV8pZI7yxBMiPzvveP2J0e6tmw8KZBCbCMSN1KjXvvtjWO//O0j2UnVzjtRS5kp+wcE8rZVjJdKd/7Rsw5bUmN7U90ssLSQaHnlUNXGp8J66u0Y9gPL1ItSYzTSiNpIMGPjWA1D2ZshQO6Es+QV7AuPbud3dl9z+ieXpAeRUk//5EBRi+3zC56i/fpuP5+fVGUmNeplAXEe1+4mngKf+Z+hiGKdNQX1ZnDTPdI5vf+jZhPa76N3qSpPZDlPbC6Qb/PpRoXkyc2e2+WDe3LD5fiGNEnkrl01MhT/9GZSdu5NXYC2eGv+jrUeCxz8+qZAVtZNt8S68YkokZpKKnayP0Pv/HMqWLUL+7qfvllD/PJ1Xx1EB95HnN/sSXfZNeoSbVe81a4HZjaq8euR1C9p71XvOb4jg5sXhcQfg5iNGvHVYVSOcVgWfXTcIs1FNKfl/ZCacPSOAY2WFk619k9eX5N3zVygAE4DkOORv0OWf5lkWhxPK8mWQaiZJeOGARSg6fOs7VobQUCGPG/C6iGv8apMFIc3rtH5+CMF2GVu2QiH7jjuLO5ZjJe8n4E4XzHVbaAATgOR45C/QbT5HjxSpK8vrJZRPNiJIujjT392rQkl24Vgt7Ix47C2LWM/ulGT0NstoPSVHbdk+er9H6ONPCLhThW7LBQMwAUh28a5h459uuYHZqxDG9G3dBAkNNaQI1ANVBHFxibpo9GJPFbIixt4g9hKxKXC2ReIYTiUcVCQNtCC9B6kqQrN8noDrv1Btu+AApoDJzkqeLeN1WivpEVdSc5KSvLGLs6IMEntG2M5jQNko5+k4PrKRz6F67P7kV7HbUts9dOKANUOepGA3KH/m7BocZ8wbTnJlhwDvbcjeHl5OxxkjU+4ZoHtyVO8W1tv4WAj5NuYBTAMoP4QTfnPA4myqHIgwjR7NAel11NQLGUwj86pueib7KVmGHdEqRwId4UntscDOxxSAWWi1vAKRs5WzDOVVdpyUmwMwOd5rOdWbI65yKJbMifZ49kGEdajhkRz4yZYqT+VwRBi7zflHdgS2E0hjXjU2YZwULVqrVavpAP6yALCkGpGizCsoeXJWA3Av3fO7GOflUkpoJmSnMkzIohKfI7wk9gMaNyxUozIOVOSF7IupViM5hymv+5kg9mnS24aVF5v0iwlLjtA5mPALyzSeoePlzRzevokotOt9AEcPGrvlPk71Vqoz8/fmafbbTZ6dZ0B5hcfvuRKY7e8DmD1oTGG3aKCJNb8cdOSoaYC9eiKs5VUw2V1kO448ORu/dw8Zd729yaEoJg7SDQUht59DqOV01AZh+fsG1d9RfY7AbLnsACRQbJoBP02TVw6tsiE/qMnjaZoJUaGCZlIcNRMlZ/1U2GsbYChAFuAgGX6dnZ0Ip0nWw2F3psgg5A4Cs/lUNDc4dxh7WDgg8IzGxsOaNsu8uV9jxTsI6J2XBIAE3gYioEcjEYgMKWYzZIcdMs/Gc5A2d8vAAAwcHiFrvlHXpEaUL1yumxE+bwYfPbSrqwt+v19H21MgndiBcK+acI+3B2C/rtmorjrkf+wQ6AuIGGXRWfTOW+mdb+UJ73FrRvC22gTIMzOmwvipTwKNM8TLG6IaMIcg7k1IqtFNHO3Vl3kP9mMCwAuiihsMqKiogMPhENQop8k+KHe1QiHwPvZRYhHzYvtnSG4HpBkpqd04dzgvO3jwN/jgoOpeWzFuzQgC71s2Gww/ePCz0oK7dsCyhNCZ8i1inGq8OceR1pTF/Z2lxWpAkxyRIYcGL6g8YQDr6+tht6dZxxhWYz8WfiC++QlzkNo0+1vyEvMb1gL33QsDUeByGsTXj0sKpIbzXp+33X33dINt5tdIKpBuEhqqmddXqCCeJtWgt0+NPDMYDTDaHLjQxUh8r7q6Gl6vF93d3fFUkloCPHZqc9TcJDJiyt36jvY1VwP/9VtE2jvxdYxg4cpYoMAvc5jdjff+I6Hzr2nBi3UcnefQHNHtpLBbiwoboSQPszzb7XajtraW5LWmOGlJ8KLZGoscw8+S8O+3bICROPJKGsxLxxUFUoNdJFruvX59scFaTILv9KezUO01ADt4c7SSrJ/lsodx7YIWTK31wd9vxtZDVTh8bujehSccE3DIORntllIBYM2AByt69qM8lD6q3WKxCBBZLgY0uRjddSXbhVMfuhb41ROIBPpxH/1553iiwLvonZ23/s1NwMmvZrXZcDSquaWN1HdXdhQ4a0Iv/vWOPbhhaRMaJ/ZiycxO3PeRQ9i44kxsDihgtOKFyhXYVLYYrdbyGPXx5+eqrsZZW7WuglNcrC5GNdksBKb6/WCWbm6e7vqLNTASNd6mTWqPDwBJOblv1nQo1a6jZB1tz+qa/gF1Hm4gqMBcNPzmyVfNbsd9Hz5MFDg0uHTdovO4c+0J6ncFO92NOG9Nv5d9WDLi1fKlOGPPvF1flI3KFqdg79G2Zls2rI9xu3vGBYA00paTedB483oiAl92aU+YJfUPqrPegn259QG8Zn4bAXRSAJSpLJvdgc/ccBTL/IdRFvLqysPXyq4UrDUTFbJywztxnm1W6TqQwzIM3vX7ivlQaFB/RpvzHPMUeA+p2jLni8naI6ItyI0uAjXrAMjA3HZtduEm86d042/X78OHu7agJOzXBfFP5UsERWaSh5Ldhf4+RYRYBHKcf79+DSQa1Dwxfd2YBlBTXm6/7moYbDlsYObXokh47YDV5czoNqsoDuL21SdzalMUxBs978AuZ+55v9GBA66pmdmoXZ2BYi7BAy6cw5z88ivFIhqe5f/UWKfAj5DyYrt+TW4XebUlHueaSIFxV2Q87+p5bSRfh7LNI6R1/vOji/DLl2ZCVqS0IN62+Biu6tFPqHfUOSkzgNqewG3aSnZfDstS+PJ1q4R7dSMP8jELIImKu+uqIc+antt13Bm80KW5WYGltCrjeQ2V6Vd5bj5QjS6fFbtOlOO8x5FR6ZkWaIZJyUw6XpMjM4BGE0xOBw0yrc05xp5x8iMa3MyXPjomAaSRVUUNXLPmmtzuy/KEA3xFshs6Wksz7wvhtKfX31fMbRf2IJsVNaWBDMqIEts9JVOxyCFdTTRsK8Hp91QK9+aWoxY8qHlw0yC/c6xS4IfZE796ZW4X9Wi6RYuWWkUPwExldkMPfvCp7fjSxkNpWSyXnccrhDkR1tlZbWKwPaOLjbVRyVmMLo+iLioNqbIwRyo00CBfTYO9ZMwBaDTgY5MboEyoy+26bi2J4anTJGZKitUcLHkuJ1uK8D9bp2Fz6Qcy267EWhd7j+jbg06135ubk9uebVm1XGjbPIJuGFMAsmCmcb/uqiW52TlsEEdNiGMnJFjSbbszynK23YmfPj8Pz5WuQI8ps/6wqns3isN9+gA6XDCaTcRGNQBz3E510kQ16pyI+a/HGgV+mvPfLFucI/VpHcAejgDZWLaK2ryCxwrNTwi8Z90rMhrqQs3v2S8UHH1NkuWgBNlZiqPHkgdgLoUGOTu6r6NBbxlLAH6BkwXwhG22RWSl0PzInPCNZ/3tVfV5Be+BP8zH086rM7rSuCztPYRZfWfRYy7KAkAqZOa0tqhZdrl05pjhZekisaaf+/7vxwSANJLKSMZP5eyEuURe8Nxf1Cl86DDZyRVVeZN/J88X4Qe/X5AVeI0EHju7/1B5tS6LNUWzIhSrStapU3EA5RwWVc1rjPXTHaN9z/8XYAAv7VrsTjk4MQAAAABJRU5ErkJggg==')
-
-
- e_wizard = ('wizard', b'iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAYAAADG4PRLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODU2RDE3MTgyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODU2RDE3MTcyOUM1MTFFREI0MDFFNTFCRjJGMTE0MUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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')
-
-
- e_jedi = ('jedi',b'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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/eHBhY2tldCBlbmQ9InIiPz57Dg6vAAAm0UlEQVR42ux9CXxU1fX/9703e2ayrwSSsO/7IoLKpqKi4o5bhVptrZW2Wlza36/aVtu6/m1/tbUWWypaURFRxAVBQUAFZGnYIYQl+56ZLJPJzLz3/ufcmYQskw0CScCbz/1M5s2bN+/e7z3nfM+5594n6bqOUEWSJHSzIlMdQnUK1aEmSRqkAH3oPm2arofT3VbTcacGlPp1PU8FdtP7/Qi85qGHl5ZwMnTz+2bQZhsk6TYCaK6PgBrscKhz4uMxPDxcSbXZYDMaIVHjymtqUOb1iprr8eg7KivVr8vLDW6/HxZJOuHV9dUE7rt0vY1UNZwjReqmEmin+hOzJD0oyXLCwr59tdtSU+VhBBwIIE9FBTwuF7zV1fDX1kIjkELdf62iYI/bjU1U17vd/n1er4GuWUQD4W+E4F/ptJKeLoHdDUDWCPeTxD3Z22q1/33sWHlmWhp0Aq2yoABVxcXwezynfPETPh/eJ9DfqKz0V2iaTi18mdTtb+mjsu8APP0yluzaW+Em04C3J02SZ/TtK6SsPCsLNeXlnfpDpE7xflUV/uR0+ss1zavq+q9IIv/SnVVrdwZQIkP3ML3+8bFBg6TfTJwoscSVZmbCXXZmBcNDbV9C6vgvTqdGhGhnja7fSoczvwOw/cVmlKQ3rAbDdV9OmyaNSU4WEld+4gR07ewJw3FSrQ+VlGgHvF4P2cd5dGj1dwC2XSJIZX4+wOEY8/Xllyt2kwmF+/ejxunskg4itwPPkMSzRJINfpSAfPY7AFsH7+vJMTGD1xJ4IAnI37PntAhKZ5X3yDY+VlKi0/29QCr24e8ADKE2qXM2E3ij1s2erWjkv+Xt3h3SFeiq8jm5HfcXF+tG4FkC8bHuDKB8tv1OsnmvDXI4RrHk6eTDtQQeqTAUqSpqWrjxM1lm2Wz4S1ycVKvrj5A6ffA7R/7kaPmfcKPxyWNz50oOsnk5O3aICMp/iXXu48/NZsRRjaV7iiFQ0whAmyx3Wecsq6zEE6WlOtGpWfR2/fmuQqfQFTftnT1bNtIIf237dqwjP89hseAm8vlm0jErOeq1ZIPOZKmhgVHl9yHSZIaxHYPjlyUl+KC6upJ8x0H0tuB8BZDt3qHbUlKSD1VXS0cJpB8NHox7BgyAg5x0V04OVJLCs1W8mgq+B6OsIIUGTkMg+TPuErOiiPekRnFtXp6a5/dvIHV+6fkIoJmutFKRpCtjSD3+7+jR+MGgQVBpZJcePSpimV1RNGr3ZpcTWcSAL7XbEW+xQg62ubDGDQOBGmO2iPd76B5vzM9nVXonvX3zfAJwCEneB3EWy4BbU1LkJyZMgI3JycGDZzzK0q5Oobq7sgJvkzReSwCOdNgRZjCK4+nkj0YbDOhjD4NEf7+n+yWbWEqsNIU+dp8PAM4mqVv5s/79zc9MniwbqDMYtKIDB6DSqO9OJaOqEk+7KjDbZMQ0uwMJVitKSOrWVbgwiWx0Gh2rpH6alpOjkhp9Ug0EwM9pN+JauvBHr02YYH3hoosEeBX5+cJZ727gcRlAAP0qIhwfkh1eWVGB7OoqRJO6TyU1usZdg+MEcDj9f19EBFvGRQhMd3WLciYAnEIXXfHehRcqdwwfLg44s7JQfOgQ0AU+Xbt8Kap9w+z4JdnCdTTAPiCVmksgxtDA4w5K93iEXbzd4QABaKVDPzhXAYwhR/3DF0eNUuYSy+RSkZcnyEp3L0xgUgnEh6wWLK/1YkN1tSAyk40GrPH6UEz+KiN3i8OhWCXpZ+ckgATeS9NiYyMWjhkjDCgHposzMtBTShhJXByRmJ8TiC/WeJBHKpUbkkhAHlBVlNV6cBNJKdnBvnR48rkG4EieinmNVKdEDWa/jmcXuqvabHEQ0r33J0s3iwjNX0jquAwzKNjq88NDIA41mdDfaFSp4246pwAk2/Dz+SkpWq/oaPG+hCSvs51zjo2mEzv8kjp2Lee50OtB+g21kwaJT9NQ7Q+QrJsJqMOqhiq6tpnksJC8QL8W+J3LbDbFLEk3dwcAOysrzUBuxy0/HzRIhC/YXeD8lY74YxkExF7OKiOQnNSRFVQ5oM3/H/b7kU/HvaoaWmpIYhKpTibmeH1YGIZT54eFCJOxBJnouBzCReJBcILYZt1gsNA5V9N1ttNvh9P/WoMxMo3cjL+7XOwPcs06FwAcSw23j0hIEG/K2klaOKXhP5WVWEqEIbdBRMZms0Gmjq4KxkWHE5u9d/p0jB49Gr1790ZcXByioqLgcrlw/PhxbN26FR9++CGWk4+5kqRSpU6PVBQ9SpalOALWQdciiYFMx6NlCSPMFkyi34gnm8e4VPm8KKLveZtkAVxGanQxMdA0WUGEfBL0UTRQaKTqasAOnhMAXjA+Kko1GI0KS197AtIr6ZynCAAX0faZM2fijwsW4OKLL0ZKSooAr64wSBERES1eZ9y4cbjhhhvwzDPPYNOmTfjd736HjIwMLTw8XLKQE24hoNw8YcyEqqgIxaWl0ImgyHTdkUYj5pB9G09AhgpbRBLoPkJ4KwE/jdioEpRcHgyDTSZ1v9c7id6+cy4AOHB6dLRonSs3N+QJHBTeSKN8BQG3xePR3GR/WZo+WLoU06ZNa/HCrYHXtPAAWLt2bau2vZqkfe/evVi9ejXeeP11/OHECfQjIG8ngMYZmneHncBiNfozYqYNNS8BaMj0+UbWdjFJ6xQSQyNy6MiICJknZmsaxDgrSSXxnNoNhYUYnZ2NH5MErCPyoVut0tSpU7F9+/ZWwTsjrgLZyAsuuABPPvkkMo4cwZIlS0B6GU+5a/C4pxYnmqjRtKA2iGIV3ADB1ICTP/CcYKF0kchoMvjVrJ5oRLqoE14klXUROfG/pmM11EGLHnlEjPr8/Hy2bdLGjRuFLetS9UMgLCDVfejwYfz1r39FgcOBX1S78SoBWR2UrBGGwLRSDrWpIYC96bteXU/uchrKHR6qdqRYJenQhosv1vMmT9Z/GxOjRxiNOrFSfd68eTpJmd5TitPp1BctWqQbiABxG+63WvQlDjt3hv4A/b8xPk4/kpYm6tLERD1IoMO7FKfTAJCl9yKqvyLjXpbmcOjkBItGESnR09PT9Z5a9uzZo19CA5Lb4jAYdGacN5hNjQBck5xcB+CQrgTwVKaTHFR/Qernfr/fH8fnDR06VNRhw4YJmzZr1iz09ML9sn79eqxc+T6WLXsTpWQKRhGrnU9q9mpitpxsNSZLeBAzqG44G/fTGSr0cgKO19rp1113nf7ee+/p1DD9XC5er1dfu+4Lfcm/l+pXXXmVkLpUi0V/OT6ec0c5ne62nqBCbVT/wdchSVO3bNmin0+FNI2+9vP1+rK339XfXr5Cv/aaawWQdlnm0NAj3V2FxhmNxvU+n2/4I8Qk2VE2m80430ptbS0+W/sFqt2BbIrSkmL8dOFP+N8MTdNG0Ku3K1RoWwAaSWVuURRlzIoVK+Q5c+Z0i86kDoM/RFzURA75mSxFRcX4YsPGBqB6cM/dC6Cq6nLqR1alancD8OdUXyTwRLiqMwo1VoziWvK1GAQ1CISRl0o3PI9A8vLCzsoqEROtpOqm73m9vvrvhCoWixkOuwPR0VGIoZqQmAAz+aidVdZ/uQmFhUX172vc1bjnB9/nQbUEgZl6vdsASJ16dNKkSX03b958Wj/udLpw/EQWCgoK4aqo6LCfeTqF2xEbG4O01BSk9OktBsrplCOZR7F9x65GxypcTtz3o3u5Xbxs+4GzCWBrsdBEsnt9b7rpplNWcyeyspFxJBNlZeXoqsINLy4uEXXnrnT06Z2M3lQT4uNOCUwOkDct4RGR+PP/vcQ2kY1iNtVnWnHBYoLOfynV4tO1na0CKGKBaWkduqDH48Gx4yeQkZEJd3BGu7sUVr2sCbiyZMbERBOQ8QJMllK5Han2bnfoNsXFJ+Cxx36FZ599+ikavEvp0Fi63tUE+Ch6tZM5SKUa2fA7xC18NIi+oj5bTG/fPhUb2hqAYkY2Ly+vxZHNdqmcpKucVGQFqUaXq6KepfUER72kpFTUffsPiLhoEtnLPqRmk3slcec2+w7b5EOHW87xGT9xIl/XQKCkc5CDzI86fvx4JTY2FomJiSLYkZSUBBPZZJ4mO3TokHHlypXTly9fPo1+/9fEdHl18O4OmYhWbKBEFy285ppr4shhrz9eQAacVWNeXr6g1udi4Q7u368vhg4ZJP7nPuL27krfTYSqutXv/uDu+Rg2dKi+bNkyacCAAe2zq0eO4J577lGJa5CSUK+lQ2s6i4W+QCPxwaysLCk8PALbvt2Bog6kSvT0wv5uVGQEysudqG1nfs/dC76HW+bdhn8v+WeH1fu9996LpUuXeul/3o1qx+mSGC4v0cUefO21pRg0ZBh8ZyCrmu2OrmsoKy0VM+aVVZVwOByw2+0IC7PDarUKKTAYyM2QJdEQv189KwCyhilo4DK0aY8MCmrI7kcHE7s6UlhlL168GNnZ2YZNmza9T789rs6MnaoN5HKMLrzu008/ndW3/8BOy2Bje1NYmI+1a9bgo49WEyB+AlJCpM0AE5keL+Hj8emoqfW36FTxxGxcPM8nSsJ/1OnPU+MRJOr6G27EtGnTYaNzVPXs7Xbhrg6o15TUNAF+RyNWDOJ//vMfec6cq5P27Nm9jq4xlQ5XnaoNrFfr9P+r77y7UnT0qUqZ3+/Dvr17sHz5O8g4fFhMjkaZZEQpKmKIzTsMCJmX4tc53Q8iN4Vrw/da8L0YFMEv89tyzQAngc9uwg033ohZsy5DFEnFmZbcTz76EF988Tmee+FPmDhhnLCjp1I+/2IDHnjgfvVoZuZKIk43n44N5BJBIyPnwYd+YR8/YVKHpOxo5hGspwatW7dWgG81mxBlVhAdZkVUmAUGxQCdqTtv9cOqtOEUlqQATaa0dLnJMQ7mampTay/yxTw+P0pcxJKr3KJymTVzFq6Zex16Jfc+5cHYYntJem6ddxNuv+N7uGrO1UJDXDZreki/sa3C/mrm0aO4bd7NbBtn06HPTnd52WP0/o+vv/EmFEPbzm91dRUee2QRXM5yhFNDImJiRXISN6orCtvusrIyUZ1OpyAMo0ePwc233IKBgwZD004vMsSq7+k/PIndu3dj2iXTcPe9P0JxcREiw+2YP39+h6/39TdbkZWdg682b9RfXfyPL8kszDhdAGmAKZ8SmZj5yj9elYym0Lqdv/H3l1/Chg0bkGBRkDZsBIw2R3dy/lBbUgRnOfmu5JBX1HrhJXBjY+Nw2+23Y8LESUSabK3GWpsWI2maF194DunbtuLB8HA8QwNkyNBhqPHWinxVzl/tKBtd9eHHgvVqqh/fu/N2v6ZpZp2Z3mkAKCJGBOI7LNJ33HEnLp99BWy2MKGKCgry8C7Ztq+++goxYQakKn6E90qFP7ZP9/MNeCajKJ+0rBoIRnhqA2CSyuXIEav+K664AhdfMh0pKalCutQQ236xyszJycJvHv81jPS9J4gtX05g7aeOv5dcrYHk1HOeaqiAQGtl/4GD2L1nXz2rvfnG64UZo3utOF0AMcoBE41Nd5XVoJwoOmlDLGTbLp2ahquGHsZ7bwUk0TNgInRj+1mYJyoJReNmwxPdi+yahrD8DMTvXAODp4O7VpA9rUgdGbyOH47sA7CU5jTG0FMDtbQ5Q/eFhcNJTLIyPwtOap4vSHqSEhMxbvwE9OvfX+zhdvDgAXz55ZciA/wyIkp3UPs5f5Q3RujrCMf9VVWYct99+P3vf8/RFgwOLrVrq7CPvX7DpnrC4vd5sWD+92pJaCydsmNvggl8J8orz/phS56CfH0mwmxm9O0TC0PZcvzrr4cFeJotvEPglQ2dioO3/RZak+9kz7gLI/61SIDZLhofn4qDd/xevDYssXs3YODyP0DxBuKYssUKjSMsTZxzk7+WCE4yTLIbsrMQvYhEpg4FjhcUIDdvNdYfMECRdcRFqOhPt1ph4JR7g0jd5w6mnkaGy4lMcl3mBlMmOYTWXju9afM3jdjmoYMHmUl/25pK72hm9hAaaHqfZEiGpN5IiAqqSJ2Ga8U2bE8P6nFHTLsv6HVE49C8x5uBJxplj8aBO36H8S/eBUltPYigmizY9/3nURvZvMNKRkwX9m/Im4+fdG3sDqhlpY1NJPluOkkV379CAJbnAw/cLQhynVNTf+5zL0AtlJOlHTWSvDU/D78NsyGcpJMXx7DKrQsztjezvLra3ShQwhrwtaX/VonArGjVResggAPiYuAXua7GBkm51fuIcVYh81hQRdki233BwonXQDXbWlatMb1ROnRqO65zbUjw6kEcOQPVSSdjk7LF1hCZkyDWVEO1RQh3hffey84JfT0SVNldXiz99ulnMfG6G/DDqmo8SxLtJBXemz5PT0/vUMf61cZuTS2p+bzcXD64tDMB7Nu7V1BqjbEnj1ZsQfreoAtGboZmab+74Bwwoc1zXP3Ht62GB1/QLlXdYIhDNjf30dg+gvxNzRpgzy0ttKKBLJm0GomjLTfedDP+/NLLiJ11ORYSKUonUrNq1ar61VXtKU2D5KtWfcB6899oYzvoDgFoMiI1JioYMFGCGzWoNEyr9iAj2FDN2rFE5erE/m0TnOikNs+pTBnRto2Ma2wbpRAA6kQcmKnWtSOnBQkkjwFWg6QePxZoeCQx0Dvumo+X/7kEP334UaSmpeG5555rdz/k5Daetjt86KBGtm/r6cZCm4TEkBRd59YoQSmr+i+3+iSAlvbvwKErRviDI91WdBxpn/wNURnbxbGisbORNWuBUK/+NiRaM1rq1bDs8yBpy/uIPLJd2NDC8VfC1W9s0KY29smkUP4sh+jIh6trR24LT5xw0G3Lmq4+8fj/yktff1PyBSM7HL5jxsq+4Ouv/Qv//e9/MWbMmFbvn6fncnIar+qqqKiQ0Y78mg4BSCoyysHtkgyBUJcY+tvES5390zugPjVDINko/MQeDF+yCEptIORlrCpD8qZliD74Ffbc8yfIauthL00JNMNUUYwR/3xIDIa6Er/zExRcMBdH5j5EN9fYn5M4pYLdpSYUXW8AoMvFs/C86LTxb1pJeDWV3CpV/XLFiuUXXzv3+kbajBep/vC+n2Dvvv0YOmxYs8QqZpY8TZV59JjIYGjOStsX6usogFa+8XrwVNLx7oOopBdXZbAzze0HUKmthqmyFENf/2U9eI06qTgLI199EDmX3NrWnZHk1dIgeLgReHUlcesHkPw+lA9qHsuVeJVuk2kyVqN6eGQgRkugl5SAnPrG36ubaLCqtU+9tezNtTwD0nTmg5mkgdj1B6s+Qq9eSYgId4iAOufnlLWxE39paQl3cmmbWrGDQQxr4MaDX6vcKQLHpQ3MrG7oWArfkDefgLHa1eLn1uIT6Lf6pdZHoacafT95GWEFLW84n7DjY6R8sTQkgM0pYQDQOl/WFSIGUpcPNTEC+0wm05rXifK33G+aUJH79h8UKRltgcfRoKAbsr9TAWwY7Qgo6oD6LC5rAF4H91gLP57eLkltqyR9s6LNc2yFISil3DzUpQcd57rBWBECQOUk7mbq7Ps++fhjf0525yyXP3RwP89isCrJ7HQAFTkYtvbRKKo5EhD3OgCNnZdAe9ZKqEw0PWAv6iSworLNqxz3+/13PvrIIj0/L/c0b0fCU0/+TicHvl0b6p36LDuzzyBJqs+0kw09Dj+plVRCPShm7cyOfJdU5byHFz3k+3DV+5rB0LEgNqvNzCOHcdedtzPB+XvQB+xcEsPqvN5OV57Mual7WoAuKz1PAiG1yNjqTEWoUKT3ZEJewwddLKfO3/feindfJWJz4bRp0/2XTJtmiImJDSw9dzlxJCND3bptq5514oQhLi5OTUhI0LKyspXCwgKZ1OZRUse/QiBHtPNZqKKgmqTNTjy7Xn221MCeU05tMrfBDFPTIO1+Un+cVTZh/fovrvnmm68nKoqSIAa/qhbSZ9xxe9l3z8rKiqLKEQO2sun02f6O3oehg4M1kGytNY7in5xo13sefK094kdv+bMaj+Br2mclaIlhbefqOcMPM+moDSytrGqZUkvBaITuqek5CLYEILPp4GeWEAEbHsikkSq6nIN15GRSlXnOEC5beDB6xhOook9q2pde7wuLOKuNVc1h0Jrk9OitRHnqprBsISZLOIOQAHT2KABJwLKLS5svwIgOzh5JvoBl18kR1v1tJwG7E/rjyA2P1sdDz5iQkTuQN/UWHLn+YchN7ytUdhrvi0YSWNee8BC3V+4UFiO7RwFIJbuwuDmASQn1HFWMWo4xahWuNi8WcXSnmIjdvmiZ6GDN2LlLtzmt4vgV9+HbR99F1sz5SPv05aacWkzgNo/OGIMDMmC/QiVaO8uJyvm6/lmDHXUjjpEEGtk0NHSfYqIDdsJDA1byVBOAJqjUQpm4tmRqHZT+7z+P3ff9DUevXig6OWHHR4hL/xz23EOn1CCvIwZlwy4Ss/BOnkckSeJIDge5zc7Cxvi1sDiH71/ye2kwBsCNCZFgUFgkdsM83tMAPEx2UCooBnolNLb3/dKIP1Ofy9RZkj0wW686y2CIS2w1vMZxzJGLf4Z9C55FVe+hyL34NlHNriJEHd4m8mHC8jLETIOpyimmi+rUYm1EPLzhcaSK+6I6qT9caaNRE9c46swB8aFv/E/IILfmDk0gedDJwWSqMLJ/kZHNeU9RCVhMD/Y4AFnzZ2VDaggglyEDggC6KyBFJwsLz1F+BlGJaj1HxljtxKhXHkDWZfcg96JbRECAwSmYePUpN0zxetBr81vos/51snvNVxaJGYcW2DLP1MvBrLXk3qHtH1sL+vdQVwPYIRu4thRuswnZR0IojjHBCXFZzCzokIMp5TzK1fLSNvfO5k7mCd3x/+9OJG5bVZ9B1tFiKzqBtDWvYMKzNyF17T9Dgsd0WtxTSOkzicEnVwcI5oB+zc8pKhJKhbnAgZ4mgfCr2HY4E32axqBGDxftpr7xCynUrUTZg6t1GESdJEKiYyIPhTdYlZWQqpVzOAesfA79PvwzXP3HoSJ1FKp6DRAJS5zBVhdvZVWqkPo1OwtgLckhm3kQEcf3NMsB1XntBCfxcriICItOzFJj57oF/0+me2T7V6dCQ63RLCjgRaA4vDoPtT0OQOqHr/YewHUkUIaG/W+1AuNGAd/uIiDJXmmJA4jNkRoNJsfyq15ZAa2yge+ryASkQTAiSVB3OQBq8MLh5WsQvn1N6843R0v0wCtHVfyB7acCwGlax4JDnOhkC4PiLKhnn0kh0nEyM8V+7pu6QxziVKYPNldVw5CdB6Q02S1zxkV1AJbAl9APcpgDqqsVX1elTle93SYIx+DxYFJcgUWdo0aGYLnkRh47AZk3IO4OAJ7KdNIuEiz3jhDzsFMnkQ2yQtBvxVUsAJRMPWOOkLWF7IiAXFNZrz7Hh8hm5Cy1IIHZ0CMBJCKjkrR8vGU7tAZ2USy25HyZ2TOCzJJsEa/dM8QmUMeEh5447RbIkdoMs5O7kyTUuLE4kGA0aCAQG4I884NoTEYcpH7I7akSyHbw/fR9kOpmqmtJrew5SqOTmPcVlwaceolYpPnoThjIeVYIQGNCL+FOSBZri1NwZw80zgk1Q4mMgoHvi16VqjJYju6qZ58zZjT/GpvXnbvgJzW6vLuMv1OdQv+AzcGXX8N8zWxeahWQwsJgrs7dC4A3lnEuiRfGgiMwkBOthsdCc8RAjY4RPcipeyJ9j2dGRez0DE4qMknivdjYQacqokMkbcyWldIsoe6loLvBSVvXzQXSUptf5kSWyI/hPlvWbRTIqT4A8sp4/Kd3Mua98jwUvsKuJguImKlv2gx89TXv9tDwwrJIW+cVTJx7yWn4utEiGKMIgnP4ihkrvQrqL5ikFmCVwVyVwGz5SbYq0iJEVSApgcpZR+J/nuvi48I1qIZE9k0AV1MhjFk9IaavTCCbN2M6L0gJ3eblK6Dv24vdq/Mx5mwD1SnLy5r4g88fz8Lt33wLTCHyYiGu4mngM7MffxmpU0cfBZ9tluErV8mF0KD5NepAl6gnJUSBZrYJIDmRSDcFX0ndcvY2r7eoz4QL2TpNECfO/QQH0/0eAqtWBKNFrXXXxzUbCabCq5RkGKJkjCdIrp7Y8tRSSalQn6Q68HR3MuGnDCAZ8V1XJeLDv7+GK8ePpj5wAPkhghtunwRDtCzqyBQVYxP9OEE84dhx3sYLECmSJAnM/lDTevqXXpc0xeISlMi6Ocj2FF7PwMv1UlOAfv2A3BoFXx4IXLO2lZl5HvyrVkMzGpDp83Xtk1o6DUAu1JgfF5ci45WlMPxoQWgAGzxyCHHhOkjtijp1SpAAkXotLAyEp3hTQwaUY42ci8mBnIZrMOvBagE0ztHlyVdWgVGRVKMClddaMnDs4jQstXl6I5BaKt9uB45ksLnBXTRwtXMGQKbSl8XgrtWfYTnPCY4lG+JqEuC3mPSQYNYVJg2ctt40db1eVfsDaxPYpgajYeBlA0ychHmTA+qagevo7pGWBi6q1RQawUNk21d+AJ1u/XFq75bu5gWddiInNepdAnHR4tfx/I0VvGNf4xBnQsTJjvH4Ou4/sFSx6gs/A4/XqGwQL4+PaA7g7r3AW29Do4G3ZE0xnuqObmyneNcE4gv08sP3VkF/6x3iKg2kMDlaQ12Oa4FT6laNL3CebH6/+JOakdX2J5+Sr7BMxPheIPN4b3eNIHVaKjWBuJgkcd+BA3j70GEkXnkFDGPHiKgFRhF52XlMwbEiGVUeCXZL10c+OUF5f04AwNQ4DTEOXdjBvfsEeP7KCrB8fv+zEqxANy6n7Ae2VAhEzhJ9mIjiY+QFKJdcBMPgYRKWbTHC7ZUwNk3FlWP9Xd7wbUcUrNtjEGs9bp3sRVG2jo2b4CstFY8JXExSxzavqLsAdbo7NZ0KkJxXcR8Ri4VEPOJ69ZP8jmTFUKXLmD7cj+F9uo7M5ZbJeH+bAWGKBm+xph0/oHEY1E2gLabu+D8C7lh3k7SzDmADIFlPzaDL3Ujq9NpaL5J5RXRyIrQ+fWCMiwV42bad/EiezbHbOrxCrcXC7JUX3rBLwq4J7yqSlQ1/Vi7ZucCmTKVk49b4VbEWYQ0B1223IO4yAEMAylFGXio7kQAdQz8z3OtDIt1GPaMwmeG3maFx3DvMJmakjDoCO4M6wvTAqmh6X+WW6jeqIyn38bMlOWOaQJOJiBgaNo1+q4i+d5gG0E4EdsPdSoAdQg8p3QbAFkBlnsqbvHCqRmSTKp6WptkizGL7Eg6bcdw0uEUlJ98qlSKC8CcEdrjl6QRX8JUrb1OQS2B50YNLtwawTYBjJY83aYBZjUho7gfVVMIcWOWbSiBl4RwtnR7MPoOSOJrqcAQekCHGEt29WeF0xRDr2KSTWWf30/cL6mIG7OZR/YZALcQ5XLpcAqnTOXV7Fv3gzfSbN+qa5pBkRZVNZrX+RnTd2Cqz4TaYLCpkg6C2uuqXtJpKBX6fJCmGdHr/Fh1eTmBmnmsSeFYAJJA4EGYNVpYOZnszJVm+idjItbqu2cxRcWpY7/6KLSkFRkdkh3+D9y0tKSlBw/V4RvINpOpy+LIzVK2yXJEUJUNX1dfpI34QRm7QxiJoK93d2U6edQBnx+FWixlPEyNMQTCJgjgH77gh2CbPCJmsFt3ab4xk790firVztmPmJ8iUl5c3a7CBI+nF2TAUHkRNTcAHDe4SKdWdyrt7EFtdQ/f8YwIz77wFkCRuJjnwnz74Y6txzBg7LEoZ+XeqmPDdeyywOJIXir79Dmm55IthTx3UqY3lbRtZGps+WcZyeCMun+7BsOGBvJ048j8HJAdSBTn+mZsPLFsJddduHKzxYOTa0u6z5LglnM5Iqhh1zgsLH7rQeOnCVYgdPh/2lGs45VlM3/RNoo6LBhLiAX7sg+bv/LAa71fGG61GNlmVohEJSiUvNIIUejL9fkpCvY8IOymAwQOARxcSkZIwkA7P7Qm2sdMBJOm7SNUwYtadi4B984Cs54GS93nZrvg8hjqvV3CnyrwCCUb7mVncyRqEAeSHTRmCuzEZrFaUlQXmAVMIQFMIDs6pkbdeR9rdit+clwBSwx+ef/dI2Vi1nnRZ6K0uOXuBa0mpCoP9zC6z5v08e/XqJV69hjCR29LW8yc504608HAajGO7O4CGTpa+RDI7c2Ze2ltG7sst2yjSmrzWXqKONNha354yzOLHzDH5iLLXYldmDPYcO7llZIatDw6H9UGVYkOypwiTXftg0Jv7ivzkGN49sNzoIKkvpN9vPZDO6nTmRZA2fgNSI7jjvAGQNNWPhwyEP1Zaq0BvOc/TXctPgSZwosJI1bWsBNISq/Cjqw4hIizA7icPLcb69CS8uzEN66InINN2cnGGy94XheZozCn+BhateUyaH6AFi11socxzgZyMbG4lBWPulVA+34SbaVAuJDJTds6rUGooP0ph4fVXkWOut05M3B7eYp/IRiubow/u7cKD1++rB6+uzBidjwWzM5AYQj2XGiPwcdyFUEMMCgGg1Y7yMk2wTncb27cM7Aek9oZGpvT754sNnE1sLuzCia2fxKOfJTAnj5wwe0LIc1Liq3H/NQdhNIRWdRMHleClaR9jSsXeZp+VEIg7w5s/p4EfwMEbnRuNipD+ynasH+XBSKTmp+cFgDYr7rtiJhG7NrZLqwxuIXPsuARzVGzIc+ZMym4EXvrRaPxrzUDyI09efGTfcjw+8guk1eQ3+/4ee38SHTmke2EMtyO/gBz+tnewxCVThI/Yi7TL+HMaQGqgvdaLK2Zd3Pa5nHbIG7S7ylUCMD7kOb1iGm8UtO9EJHYcjkVpReMdL0b3L0Oqp6B5WE1SRA0FoMcYjaxsSdjA2ja2smGXYuokSGYT5p/rEnhVQhw03qmi9WgCsc8qID+PmB4RGLmF/UWbBoHmTTuG39y1C8mxjYHNKgpDmbF5vqHD74ZJ84UEUA+LxKGMwA+Ut70PKC69BAqR2NvOaQBJff78kgvR5krOqprAKibe49vUyoOxZKmxoxZ43E1j1pFbYsMfN0/BPnvzXQimOPe0GKGhkUPSr4k0C2c7HuswdpS45xjSMpO6I4Cn7UZQwyxR4UgekayUIUdqthm0xw8lv1KzF1TDUQF7tW61VZa7PVZjfBrv1xxyq4js4rDJ+WW2Fu+twm2s/suW8Vk7LQMG9fIUN9KVg9zZmaRW81sA0Ga1O8ZZB6bGHsiuNJXUGvT8XJcSafD6+kTIFTFWqaap9Gt0/5dNVWM+3ajPobfbuhuA/1+AAQCr3yoPAG6yvQAAAABJRU5ErkJggg==')
-
- 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+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI3VDA4OjI3OjA1KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yN1QwOTozMzowOCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjhFREY5RkMzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjhFREY5RkQzRTBDMTFFREEyOUJCRjFCOTY3MzMyREUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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')
-
- 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_jedi, 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)
+ all_emojis = (e_happy, e_stare, e_laugh, e_joy, e_idea, e_relief, e_wink, e_thumb, e_love, e_clap, e_fingers_crossed, e_pray, e_smile, e_guess, e_dream, e_python_hearts, e_psg_hero,
+ e_grimace, e_weary, e_think, e_frust, e_dead, e_gasp, e_cry, e_no_speak, e_no_hear, e_no_see, e_zipped_shut, e_ponder, e_palm, e_eyebrow, e_not_understand)
# Build the "all_emojis" data structure. Converts the all_emojis tuple from 1 size to having 3 sizes
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 07c0b207..00000000
--- a/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py
+++ /dev/null
@@ -1,60 +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 2022 PySimpleGUI
-"""
-
-
-
-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_Fonts_Using_pyglet.py b/DemoPrograms/Demo_Fonts_Using_pyglet.py
index ba2b4051..d43db734 100644
--- a/DemoPrograms/Demo_Fonts_Using_pyglet.py
+++ b/DemoPrograms/Demo_Fonts_Using_pyglet.py
@@ -1,6 +1,5 @@
import pyglet
import PySimpleGUI as sg
-import os
"""
Demo - Using pyglet to get custom fonts into PySimpleGUI
@@ -18,11 +17,8 @@ import os
http://scripts.sil.org/OFL
"""
-font_file = os.path.join(os.path.dirname(__file__), "OpenFlame.ttf")
+pyglet.font.add_file(r".\OpenFlame.ttf")
-pyglet.font.add_file(font_file)
-
-# sg.execute_command_subprocess(font_file)
font1 = ("Open Flame", 40) # Note - use the font "face name" not the filename when specifying the font
font2 = ("Courier New", 40)
font3 = ("Helvetica", 40)
diff --git a/DemoPrograms/Demo_Frame_For_Screen_Captures.py b/DemoPrograms/Demo_Frame_For_Screen_Captures.py
deleted file mode 100644
index 53c13d69..00000000
--- a/DemoPrograms/Demo_Frame_For_Screen_Captures.py
+++ /dev/null
@@ -1,47 +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 2022 PySimpleGUI.org
-"""
-
-
-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_Graph_Drag_Rectangle_Super_Simple.py b/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py
deleted file mode 100644
index 43c2dcb6..00000000
--- a/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py
+++ /dev/null
@@ -1,44 +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 2022 PySimpleGUI
-"""
-
-
-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_And_Dragging_Figures.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
index 3afcff8e..b3c1affe 100644
--- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
+++ b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py
@@ -1,4 +1,5 @@
import PySimpleGUI as sg
+from PIL import ImageGrab
"""
Demo - Drawing and moving demo
@@ -6,9 +7,22 @@ import PySimpleGUI as sg
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 2020, 2021, 2022, 2023 PySimpleGUI.org
+ Copyright 2020 PySimpleGUI.org
"""
+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')
@@ -24,6 +38,7 @@ def main():
[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(
@@ -34,19 +49,20 @@ def main():
enable_events=True,
background_color='lightblue',
drag_submits=True,
- motion_events=True,
- right_click_menu=[[''],['Erase item','Send to back']]
+ 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 = window["-GRAPH-"] # type: sg.Graph
graph.draw_image(data=logo200, location=(0,400))
+
dragging = False
start_point = end_point = prior_rect = None
- crosshair_lines = []
+ # graph.bind('', '+RIGHT+')
+
while True:
event, values = window.read()
print(event, values)
@@ -57,14 +73,7 @@ def main():
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.endswith('+MOVE'):
- window["-INFO-"].update(value=f"mouse {values['-GRAPH-']}")
- # Delete crosshairs if any exists
- if len(crosshair_lines):
- for fig in crosshair_lines:
- graph.delete_figure(fig)
- crosshair_lines = []
- window.refresh()
+
if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
x, y = values["-GRAPH-"]
if not dragging:
@@ -105,28 +114,25 @@ def main():
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
+ 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+'): # Right click
- # window["-INFO-"].update(value=f"Right clicked location {values['-GRAPH-']}")
- # elif event.endswith('+MOTION+'): # Right click
- # window["-INFO-"].update(value=f"mouse freely moving {values['-GRAPH-']}")
- elif event == 'Send to back': # Right clicked menu item
- figures = graph.get_figures_at_location(values["-GRAPH-"]) # get items in front-to-back order
- if figures: # make sure at least 1 item found
- graph.send_figure_to_back(figures[-1]) # get the last item which will be the top-most
+ 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):
- figures = graph.get_figures_at_location(values['-GRAPH-'])
- if figures:
- graph.delete_figure(figures[-1]) # delete the one on top
- location = values['-GRAPH-']
- crosshair_lines = [graph.draw_line((location[0], 0), (location[0], 800), color='red'),
- graph.draw_line((0, location[1]), (800, location[1]), color='red')]
+ drag_figures = graph.get_figures_at_location(values['-GRAPH-'])
+ for figure in drag_figures:
+ graph.delete_figure(figure)
window.close()
diff --git a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py b/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py
deleted file mode 100644
index f12c6213..00000000
--- a/DemoPrograms/Demo_Graph_Elem_CPU_Meter.py
+++ /dev/null
@@ -1,156 +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 2023 PySimpleGUI
-"""
-
-# --- 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
index 4a38454f..115f72c5 100644
--- a/DemoPrograms/Demo_Graph_Elem_Image_Album.py
+++ b/DemoPrograms/Demo_Graph_Elem_Image_Album.py
@@ -44,7 +44,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
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)
+ img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format="PNG")
del img
diff --git a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
index a1889d08..0f8daed6 100644
--- a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
+++ b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py
@@ -1,30 +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, 2019, 2020, 2021, 2022 PySimpleGUI
-
-"""
+# 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():
@@ -32,45 +13,44 @@ 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),
+sg.theme('DarkAmber')
+
+# 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)]]
+ [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-')]]
-window = sg.Window('Graph of Sine Function', layout, finalize=True)
-
-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:
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_Window_Resize.py b/DemoPrograms/Demo_Graph_Window_Resize.py
deleted file mode 100644
index b571c774..00000000
--- a/DemoPrograms/Demo_Graph_Window_Resize.py
+++ /dev/null
@@ -1,45 +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 2022 PySimpleGUI
-"""
-
-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_Image_Elem_Image_Viewer_PIL_Based.py b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py
index 9585b96c..715bb351 100644
--- a/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py
+++ b/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py
@@ -45,7 +45,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
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)
+ img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS)
with io.BytesIO() as bio:
img.save(bio, format="PNG")
del img
diff --git a/DemoPrograms/Demo_Image_From_URL.py b/DemoPrograms/Demo_Image_From_URL.py
deleted file mode 100644
index 4999b35f..00000000
--- a/DemoPrograms/Demo_Image_From_URL.py
+++ /dev/null
@@ -1,32 +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 2022 PySimpleGUI.org
-"""
-
-
-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_Resize_and_Base64_Encode.pyw b/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw
index f1a00789..7775f61b 100644
--- a/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw
+++ b/DemoPrograms/Demo_Image_Resize_and_Base64_Encode.pyw
@@ -1,5 +1,6 @@
import PySimpleGUI as sg
from PIL import Image
+import PIL
import os
import base64
import io
@@ -24,19 +25,12 @@ import webbrowser
Copyright 2021 PySimpleGUI
"""
-version = '1.6.0'
+version = '1.3.1'
__version__ = version.split()[0]
'''
Change log
- 1.6.0 12-July-2022
- Fixed output filename to match the size indicated under the filename.
- 1.5.4 10-May-2022
- Had to mess around with the entry point due to setuptools
- 1.5.0 10-May-2022
- Moved icon to bottom of file and called set_global_icon so all windows in this application (including popups) will use this icon
- 1.4.0 16-Nov-2021
- Explicitly set the settings filename. I'm still learning about these PyPI .EXE releases. Need to be explicit rather than default
+
1.3.1 16-Nov-2021
Added correct readme to PyPI
1.3.0 16-Nov-2021
@@ -55,7 +49,7 @@ def resize(input_file, size, output_file=None, encode_format='PNG'):
new_width, new_height = size
if new_width != width or new_height != height: # if the requested size is different than original size
scale = min(new_height / height, new_width / width)
- resized_image = image.resize((int(width * scale), int(height * scale)), Image.LANCZOS)
+ resized_image = image.resize((int(width * scale), int(height * scale)), Image.ANTIALIAS)
else:
resized_image = image
@@ -71,6 +65,7 @@ def resize(input_file, size, output_file=None, encode_format='PNG'):
def main():
+ image_resize_icon = b'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'
def update_outfilename():
infile = values['-IN-']
@@ -81,12 +76,8 @@ def main():
window['-ORIG WIDTH-'].update(image.size[0])
if not values['-WIDTH-']:
window['-WIDTH-'].update(image.size[0])
- else:
- width = values['-WIDTH-']
if not values['-HEIGHT-']:
window['-HEIGHT-'].update(image.size[1])
- else:
- height = values['-HEIGHT-']
window['-ORIG HEIGHT-'].update(image.size[1])
infilename = os.path.basename(infile)
@@ -97,7 +88,7 @@ def main():
outfileext = 'jpg'
else:
outfileext = infileext[1:] # strip off the .
- outfile = f'{infilenameonly}_{width}x{height}.{outfileext}'
+ outfile = f'{infilenameonly}{width}x{height}.{outfileext}'
outfullfilename = os.path.join(os.path.dirname(infile), outfile)
if values['-DO NOT SAVE-']:
@@ -113,9 +104,6 @@ def main():
# window['-HEIGHT-'].update('')
window['-NEW FILENAME-'].update()
- sg.user_settings_filename(filename='psgresizer.json')
-
-
format_list = ('', 'PNG', 'JPEG', 'BMP', 'ICO', 'GIF', 'TIFF')
new_format_layout = [
[sg.Combo(format_list, default_value=sg.user_settings_get_entry('-new format-', ''), readonly=True, enable_events=True, key='-NEW FORMAT-')]]
@@ -124,8 +112,8 @@ def main():
[sg.Frame('Input Filename', [[sg.Input(key='-IN-', enable_events=True, s=80), sg.FileBrowse(), ],
[sg.T('Original size'), sg.T(k='-ORIG WIDTH-'), sg.T('X'), sg.T(k='-ORIG HEIGHT-')]])],
[sg.Frame('Output Filename', [[sg.In(k='-NEW FILENAME-', s=80), sg.FileBrowse(), ],
- [sg.In(default_text=sg.user_settings_get_entry('-width-', ''), s=4, k='-WIDTH-', enable_events=True), sg.T('X'),
- sg.In(default_text=sg.user_settings_get_entry('-height-', ''), s=4, k='-HEIGHT-', enable_events=True)]])],
+ [sg.In(default_text=sg.user_settings_get_entry('-width-', ''), s=4, k='-WIDTH-'), sg.T('X'),
+ sg.In(default_text=sg.user_settings_get_entry('-height-', ''), s=4, k='-HEIGHT-')]])],
[sg.Frame('Convert To New Format', new_format_layout)],
[sg.CBox('Encode to Base64 and leave on Clipboard', k='-BASE64-', default=sg.user_settings_get_entry('-base64-', True))],
# [sg.CBox('Use PNG for all Base64 Encoding', default=True, k='-PNG CONVERT-')],
@@ -140,7 +128,7 @@ def main():
sg.T('A PySimpleGUI Application - Go to PySimpleGUI home', font='_ 8', enable_events=True, k='-PYSIMPLEGUI-')],
]
- window = sg.Window('Resize Image', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT,
+ window = sg.Window('Resize Image', layout, icon=image_resize_icon, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_LOC_EXIT,
enable_close_attempted_event=True, finalize=True)
window['-PSGRESIZER-'].set_cursor('hand1')
window['-PYSIMPLEGUI-'].set_cursor('hand1')
@@ -194,8 +182,6 @@ def main():
webbrowser.open_new_tab(r'http://www.PySimpleGUI.com')
elif event == '-PSGRESIZER-':
webbrowser.open_new_tab(r'https://github.com/PySimpleGUI/psgresizer')
- elif event in ('-WIDTH-', '-HEIGHT-'):
- update_outfilename()
if event != sg.WIN_CLOSED:
sg.user_settings_set_entry('-autoclose-', values['-AUTOCLOSE-'])
@@ -207,11 +193,5 @@ def main():
window.close()
-def main_entry_point():
- image_resize_icon = b'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'
-
- sg.set_global_icon(image_resize_icon)
- main()
-
if __name__ == '__main__':
- main_entry_point()
+ main()
\ No newline at end of file
diff --git a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py b/DemoPrograms/Demo_Image_Viewer_Thumbnails.py
index d7f77498..c766fed2 100644
--- a/DemoPrograms/Demo_Image_Viewer_Thumbnails.py
+++ b/DemoPrograms/Demo_Image_Viewer_Thumbnails.py
@@ -56,7 +56,7 @@ def convert_to_bytes(file_or_bytes, resize=None, fill=False):
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)
+ img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS)
if fill:
img = make_square(img, THUMBNAIL_SIZE[0])
with io.BytesIO() as bio:
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 6e5684cd..00000000
--- a/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py
+++ /dev/null
@@ -1,31 +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 2022 PySimpleGUI.org
-"""
-
-
-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_Invisible_Elements_Pinning.py b/DemoPrograms/Demo_Invisible_Elements_Pinning.py
index 6216f975..8e4fae74 100644
--- a/DemoPrograms/Demo_Invisible_Elements_Pinning.py
+++ b/DemoPrograms/Demo_Invisible_Elements_Pinning.py
@@ -19,12 +19,13 @@ import PySimpleGUI as sg
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 2020, 2022 PySimpleGUI.org
+ Copyright 2020 PySimpleGUI.org
"""
-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')],
+
+layout = [ [sg.Text('Hide Button or Input. Button3 hides Input. Buttons 1 & 2 hide Button 2')],
+ [sg.pin(sg.Input(key='-IN-'))],
+ [sg.pin(sg.Button('Button1')), sg.pin(sg.Button('Button2')), sg.B('Button3')],
]
window = sg.Window('Visible / Invisible Element Demo', layout)
@@ -39,6 +40,7 @@ while True: # Event Loop
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)
+ if event == 'Button3':
+ window['-IN-'].update(visible=toggle_in)
+ toggle_in = not toggle_in
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 a25bae40..00000000
--- a/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py
+++ /dev/null
@@ -1,65 +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 2022 PySimpleGUI
-"""
-
-
-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_Listbox_Using_Objects.py b/DemoPrograms/Demo_Listbox_Using_Objects.py
deleted file mode 100644
index 8fca4a0d..00000000
--- a/DemoPrograms/Demo_Listbox_Using_Objects.py
+++ /dev/null
@@ -1,43 +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 2022 PySimpleGUI
-"""
-
-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_Matplotlib_Browser.py b/DemoPrograms/Demo_Matplotlib_Browser.py
index 064f57f4..85c51c48 100644
--- a/DemoPrograms/Demo_Matplotlib_Browser.py
+++ b/DemoPrograms/Demo_Matplotlib_Browser.py
@@ -824,26 +824,15 @@ def AxesGrid():
# 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. #
@@ -884,9 +873,6 @@ while True:
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 66d3e611..6344e89d 100644
--- a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py
+++ b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py
@@ -837,23 +837,14 @@ def AxesGrid():
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')
@@ -890,11 +881,13 @@ layout = [[sg.Text('Matplotlib Plot Test', font=('ANY 18'))],
[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'):
@@ -909,8 +902,6 @@ while True:
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_Grid_of_Graphs_Using_PIL.py b/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py
index 09097450..f42f26ee 100644
--- a/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py
+++ b/DemoPrograms/Demo_Matplotlib_Grid_of_Graphs_Using_PIL.py
@@ -890,7 +890,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
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)
+ img = img.resize((int(cur_width*scale), int(cur_height*scale)), PIL.Image.ANTIALIAS)
with io.BytesIO() as bio:
img.save(bio, format="PNG")
del img
diff --git a/DemoPrograms/Demo_Menubar_Custom.py b/DemoPrograms/Demo_Menubar_Custom.py
index 3d3761c7..e905e86e 100644
--- a/DemoPrograms/Demo_Menubar_Custom.py
+++ b/DemoPrograms/Demo_Menubar_Custom.py
@@ -39,7 +39,7 @@ def main():
# sg.theme('black')
menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
- ['&Edit', ['Edit Me', 'Special', 'Normal',['Normal1', 'Normal2'] , 'Undo']],
+ ['&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...']], ]
@@ -47,7 +47,7 @@ def main():
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)
+ window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True, keep_on_top=True)
# ------ Event Loop ------ #
while True:
@@ -66,10 +66,8 @@ def main():
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':
+ elif event == '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)
diff --git a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py b/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py
index 99e98431..b188c48a 100644
--- a/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py
+++ b/DemoPrograms/Demo_Menubar_Custom_and_Traditional.py
@@ -51,8 +51,10 @@ def Menubar(menu_def, text_color, background_color, pad=(0, 0)):
def main():
sg.theme('dark green 7')
+ sg.theme('dark amber')
+ # sg.theme('dark purple 3')
- menu_def = [['&File', ['&Open & Ctrl-O', '&Save & Ctrl-S', '&Properties', 'E&xit']],
+ 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']],
@@ -76,13 +78,13 @@ def main():
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)
+ window = sg.Window("Custom Titlebar and Menu", layout, use_custom_titlebar=True, finalize=True)
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)
+ window2 = sg.Window("Traditional Titlebar and Menu", layout2, finalize=True, location=(win_loc[0]-window.size[0]-40, win_loc[1]))
- 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)
+ window3 = sg.Window("Output Window", layout3, finalize=True, location=(win_loc[0]-window.size[0]//1.5, win_loc[1]+window.size[1]+30), use_custom_titlebar=True)
# ------ Event Loop ------ #
@@ -95,11 +97,7 @@ def main():
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')
diff --git a/DemoPrograms/Demo_Menus.py b/DemoPrograms/Demo_Menus.py
index 20305fd5..cc545376 100644
--- a/DemoPrograms/Demo_Menus.py
+++ b/DemoPrograms/Demo_Menus.py
@@ -1,13 +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, 2019, 2020, 2021, 2022 PySimpleGUI
+ 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
"""
@@ -27,22 +24,20 @@ def test_menus():
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 Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
+ ['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ],
['&Toolbar', ['---', 'Command &1', 'Command &2',
'---', 'Command &3', 'Command &4']],
- ['&Help', ['&About...']]
- ]
+ ['&Help', '&About...'], ]
right_click_menu = ['Unused', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']]
# ------ GUI Defintion ------ #
layout = [
- [sg.Menu(menu_def, tearoff=True, font='_ 12', key='-MENUBAR-')],
+ [sg.Menu(menu_def, tearoff=False, pad=(200, 1))],
[sg.Text('Right click me for a right click menu example')],
[sg.Output(size=(60, 20))],
- [sg.ButtonMenu('ButtonMenu', right_click_menu, key='-BMENU-', text_color='red', disabled_text_color='green'), sg.Button('Plain Button')],
+ [sg.ButtonMenu('ButtonMenu', right_click_menu, key='-BMENU-'), sg.Button('Plain Button')],
]
window = sg.Window("Windows-like program",
@@ -60,7 +55,8 @@ def test_menus():
# ------ 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 Version', sg.version, 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 29d597e4..00000000
--- a/DemoPrograms/Demo_Multi_Window_read_all_windows.py
+++ /dev/null
@@ -1,46 +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 2022 PySimpleGUI
-"""
-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_Multithreaded_DataPump.py b/DemoPrograms/Demo_Multithreaded_DataPump.py
deleted file mode 100644
index 55c96653..00000000
--- a/DemoPrograms/Demo_Multithreaded_DataPump.py
+++ /dev/null
@@ -1,142 +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 2022 PySimpleGUI
-"""
-
-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 4b9742c3..00000000
--- a/DemoPrograms/Demo_Multithreaded_Delegate_Appear_To_Make_PSG_Calls_From_Thread.py
+++ /dev/null
@@ -1,151 +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 2022 PySimpleGUI
-"""
-
-
-# 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_Long_Tasks.py b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
index 8f4a97e7..0ec1a2f9 100644
--- a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
+++ b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py
@@ -1,23 +1,25 @@
#!/usr/bin/python3
+import threading
import time
import PySimpleGUI as sg
"""
- 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.
+ July 2020 - Note that this program has been updated to use the new Window.write_event_value method.
+ This method has not yet been ported to the other PySimpleGUI ports and is thus limited to the tkinter ports for now.
- 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 2022 PySimpleGUI
+ Internally to PySimpleGUI, 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.
+
+
+ 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
"""
@@ -26,12 +28,12 @@ def long_operation_thread(seconds, window):
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
+ window.write_event_value('-THREAD-', '** DONE **') # put a message into queue for GUI
def the_gui():
@@ -45,7 +47,7 @@ def the_gui():
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')], ]
@@ -56,14 +58,14 @@ def the_gui():
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
- elif event == 'Do Long Task':
+ elif event.startswith('Do'):
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-'))
+ threading.Thread(target=long_operation_thread, args=(seconds, window,), daemon=True).start()
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])
+ elif event == '-THREAD-':
+ print('Got a message back from the thread: ', values[event])
# if user exits the window, then close the window and exit the GUI func
window.close()
diff --git a/DemoPrograms/Demo_Multithreaded_ProgressBar.py b/DemoPrograms/Demo_Multithreaded_ProgressBar.py
index 051ad2d1..f9e41834 100644
--- a/DemoPrograms/Demo_Multithreaded_ProgressBar.py
+++ b/DemoPrograms/Demo_Multithreaded_ProgressBar.py
@@ -1,4 +1,5 @@
import PySimpleGUI as sg
+import threading
import random
import time
@@ -13,46 +14,37 @@ import time
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 2021, 2022 PySimpleGUI
+ Copyright 2021 PySimpleGUI
"""
-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-
+ Once a second wakes and sends a new event and associated value to the window
"""
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
+ window.write_event_value(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
+ window.write_event_value(DL_COUNT_KEY, i) # Data sent is a tuple of thread name and counter
+ window.write_event_value(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-')],
+ layout = [ [sg.Text('My Window')],
+ [sg.ProgressBar(100, 'h', size=(30,20), k='-PROGRESS-')],
[sg.Button('Go'), sg.Button('Exit')] ]
- window = sg.Window('Window Title', layout, finalize=True, relative_location=(0, -300))
+ window = sg.Window('Window Title', layout, finalize=True)
+ window.read(timeout=0)
+ window.move(window.current_location()[0], window.current_location()[1]-300)
downloading, max_value = False, 0
while True: # Event Loop
@@ -61,24 +53,17 @@ def main():
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')
+ threading.Thread(target=the_thread, args=(window,), daemon=True).start()
+ elif event == DL_START_KEY:
+ max_value = values[event]
+ downloading = True
+ 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 == 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['-PROGRESS-'].update(values[event]+1, max_value)
+ elif event == DL_END_KEY:
+ downloading = False
window.close()
diff --git a/DemoPrograms/Demo_Nice_Buttons.py b/DemoPrograms/Demo_Nice_Buttons.py
index 9e782d11..a1cefe13 100644
--- a/DemoPrograms/Demo_Nice_Buttons.py
+++ b/DemoPrograms/Demo_Nice_Buttons.py
@@ -15,7 +15,7 @@ button64 = 'iVBORw0KGgoAAAANSUhEUgAAAoAAAAFACAMAAAAbEz04AAAABGdBTUEAALGPC/xhBQAA
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()
diff --git a/DemoPrograms/Demo_OpenCV.py b/DemoPrograms/Demo_OpenCV.py
index 3abb443c..ea5cf72d 100644
--- a/DemoPrograms/Demo_OpenCV.py
+++ b/DemoPrograms/Demo_OpenCV.py
@@ -1,18 +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 2022 PySimpleGUI
+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.
"""
@@ -30,39 +28,37 @@ def main():
# ---===--- 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))
# 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()
-
#############
# | | #
# | | #
@@ -78,4 +74,6 @@ 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_Webcam_ASCII.py b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
index 37c500b5..4798c5d7 100644
--- a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
+++ b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py
@@ -2,6 +2,8 @@ import cv2
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,34 +22,40 @@ import PySimpleGUI as sg
pip install opencv-python
On Linux / Mac use pip3 instead of pip
-
- Copyright 2022, PySimpleGUI
"""
# 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.theme('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)
@@ -58,7 +66,7 @@ while True:
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)
@@ -66,8 +74,7 @@ while True:
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_PIL_Color_Picker.py b/DemoPrograms/Demo_PIL_Color_Picker.py
index 4d60e040..6727c9a3 100644
--- a/DemoPrograms/Demo_PIL_Color_Picker.py
+++ b/DemoPrograms/Demo_PIL_Color_Picker.py
@@ -29,7 +29,7 @@ layout = [ [sg.Graph((100,100), (0,100), (100,0), key='-GRAPH-')],
[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 = sg.Window('Color Picker', layout, no_titlebar=True, 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')
@@ -45,7 +45,7 @@ while True:
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)
+ sg.popup_scrolled(__file__, sg.get_versions(), keep_on_top=True, location=window.current_location())
window['-GRAPH-'].erase()
x, y = window.mouse_location()
diff --git a/DemoPrograms/Demo_PIL_Use.py b/DemoPrograms/Demo_PIL_Use.py
index 0854e242..bffd9857 100644
--- a/DemoPrograms/Demo_PIL_Use.py
+++ b/DemoPrograms/Demo_PIL_Use.py
@@ -13,65 +13,51 @@ import random
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 2020, 2022 PySimpleGUI.org
+ Copyright 2020 PySimpleGUI.org
"""
-def make_square(im, fill_color=(0, 0, 0, 0)):
+def make_square(im, min_size=256, fill_color=(0, 0, 0, 0)):
x, y = im.size
- size = max(x, y)
+ 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(source, size=(None, None), subsample=None, zoom=None, fill=False):
+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 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
+ :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(source, str):
- image = Image.open(source)
- elif isinstance(source, bytes):
- image = Image.open(io.BytesIO(base64.b64decode(source)))
+ if isinstance(file_or_bytes, str):
+ img = PIL.Image.open(file_or_bytes)
else:
- image = PIL.Image.open(io.BytesIO(source))
+ 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)
- 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
+ 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.ANTIALIAS)
+ if fill:
+ if resize is not None:
+ img = make_square(img, resize[0])
with io.BytesIO() as bio:
- resized_image.save(bio, format="PNG")
- contents = bio.getvalue()
- encoded = base64.b64encode(contents)
- return encoded
-
-
-
+ img.save(bio, format="PNG")
+ del img
+ return bio.getvalue()
def random_image():
return random.choice(sg.EMOJI_BASE64_LIST)
diff --git a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
index 9b400da0..36e1d8c6 100644
--- a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
+++ b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py
@@ -59,7 +59,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
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)
+ img = img.resize((int(cur_width * scale), int(cur_height * scale)), PIL.Image.ANTIALIAS)
with io.BytesIO() as bio:
img.save(bio, format="PNG")
del img
@@ -69,7 +69,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
# def image_file_to_bytes(filename, size):
# try:
# image = Image.open(filename)
-# image.thumbnail(size, Image.LANCZOS)
+# 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()
@@ -80,7 +80,7 @@ def convert_to_bytes(file_or_bytes, resize=None):
def set_image_to_blank(key):
img = PIL.Image.new('RGB', (100, 100), (255, 255, 255))
- img.thumbnail((1, 1), PIL.Image.LANCZOS)
+ img.thumbnail((1, 1), PIL.Image.ANTIALIAS)
bio = io.BytesIO()
img.save(bio, format='PNG')
imgbytes = bio.getvalue()
diff --git a/DemoPrograms/Demo_PNG_Viewer.py b/DemoPrograms/Demo_PNG_Viewer.py
index 6fc35b3f..5edb8ba1 100644
--- a/DemoPrograms/Demo_PNG_Viewer.py
+++ b/DemoPrograms/Demo_PNG_Viewer.py
@@ -32,14 +32,14 @@ def main():
# 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)],
+ [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-', 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)]]
+ layout = [[sg.Menu(menu)], [sg.Col(col_files), sg.Col(col)]]
window = sg.Window('Image Browser', layout, return_keyboard_events=True, use_default_focus=False)
diff --git a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py b/DemoPrograms/Demo_PyCharm_Diff_2_Files.py
index cc61600a..7bcd66a9 100644
--- a/DemoPrograms/Demo_PyCharm_Diff_2_Files.py
+++ b/DemoPrograms/Demo_PyCharm_Diff_2_Files.py
@@ -13,16 +13,16 @@ 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-')],
+ size=(90,1), 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-')],
+ size=(90,1), 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)
+ window = sg.Window('Compare 2 files using PyCharm', layout)
while True:
event, values = window.read()
print(event, values)
@@ -45,10 +45,6 @@ def main():
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__':
diff --git a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py
index 0d037947..352fddbf 100644
--- a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py
+++ b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py
@@ -1,14 +1,12 @@
+import subprocess
+import sys
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 2022 PySimpleGUI
+ be displayed in realtime in the window. The output is assumed to have color codes embedded in it
"""
@@ -80,38 +78,50 @@ def cut_ansi_string_into_parts(string_with_ansi_codes):
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]]]
+ 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.Multiline(size=(110, 30), font='courier 10', 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'), sg.Sizegrip()]]
+ [sg.Button('Run', bind_return_key=True), sg.Button('Exit')]]
- window = sg.Window('Realtime Shell Command Output', layout, resizable=True)
+ window = sg.Window('Realtime Shell Command Output', layout)
while True: # Event Loop
event, values = window.read()
+ # print(event, values)
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()
-
+ 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)
+ for line in p.stdout:
+ line = line.decode(errors='replace' if (sys.version_info) < (3, 5) else 'backslashreplace').rstrip()
+ 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] + '\n', text_color_for_value=ansi_item[1], background_color_for_value=ansi_item[2], append=True,
+ autoscroll=True)
+ window.refresh()
+
+ retval = p.wait(timeout)
+ return retval
+
+
+sg.theme('Dark Blue 3')
main()
diff --git a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
index 8d2ea58b..971901a1 100644
--- a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
+++ b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py
@@ -21,8 +21,7 @@ def main():
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)
+ sp = sg.execute_command_subprocess(values['-IN-'], pipe_output=True, wait=False)
results = sg.execute_get_results(sp, timeout=1)
print(results[0])
diff --git a/DemoPrograms/Demo_Sudoku.py b/DemoPrograms/Demo_Sudoku.py
index 041faf96..7e6ba67b 100644
--- a/DemoPrograms/Demo_Sudoku.py
+++ b/DemoPrograms/Demo_Sudoku.py
@@ -2,17 +2,18 @@ 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 2020 PySimpleGUI.com
-
+
"""
@@ -26,7 +27,7 @@ def generate_sudoku(mask_rate):
"""
while True:
n = 9
- solution = np.zeros((n, n), np.int_)
+ solution = np.zeros((n, n), np.int)
rg = np.arange(1, n + 1)
solution[0, :] = np.random.choice(rg, n, replace=False)
try:
@@ -35,11 +36,10 @@ def generate_sudoku(mask_rate):
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())
+ 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)
- solution[r, c] = np.random.choice(avb, size=1)[0]
+ solution[r, c] = np.random.choice(avb, size=1)
break
except ValueError:
pass
@@ -48,6 +48,7 @@ def generate_sudoku(mask_rate):
return puzzle, solution
+
def check_progress(window, solution):
"""
Gives you a visual hint on your progress.
@@ -64,23 +65,38 @@ def check_progress(window, solution):
solved = True
for r, row in enumerate(solution):
for c, col in enumerate(row):
- value = window[r, c].get()
+ 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')
+ window[r,c].update(background_color='red')
solved = False
else:
- window[r, c].update(background_color=sg.theme_input_background_color())
+ 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.
@@ -89,19 +105,8 @@ def main(mask_rate=0.7):
addressing of the individual squares is via a key that's a tuple (0,0) to (8,8)
"""
- def create_and_show_puzzle():
- # create and display a puzzle by updating the Input elements
- rate = 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
+
+
# 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.
@@ -109,18 +114,16 @@ def main(mask_rate=0.7):
# 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), 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)
+ [[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()
-
- while True: # The Event Loop
+ puzzle, solution = create_and_show_puzzle(window)
+ check_showing = False
+ while True: # The Event Loop
event, values = window.read()
- if event is None:
+ if event == sg.WIN_CLOSED:
break
if event == 'Solve':
@@ -128,6 +131,7 @@ def main(mask_rate=0.7):
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.')
@@ -136,14 +140,17 @@ def main(mask_rate=0.7):
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
+ pass # Likely because an input element didn't have focus
elif event == 'New Game':
- puzzle, solution = create_and_show_puzzle()
-
+ 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__":
- mask_rate = 0.7 # % Of cells to hide
- main(mask_rate)
+ DEFAULT_MASK_RATE = 0.7 # % Of cells to hide
+ main(DEFAULT_MASK_RATE)
diff --git a/DemoPrograms/Demo_System_Tray_Reminder.py b/DemoPrograms/Demo_System_Tray_Reminder.py
index 94bba7cb..b93d883e 100644
--- a/DemoPrograms/Demo_System_Tray_Reminder.py
+++ b/DemoPrograms/Demo_System_Tray_Reminder.py
@@ -29,7 +29,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()
diff --git a/DemoPrograms/Demo_Table_CSV_Display.pyw b/DemoPrograms/Demo_Table_CSV_Display.pyw
deleted file mode 100644
index e3beb08d..00000000
--- a/DemoPrograms/Demo_Table_CSV_Display.pyw
+++ /dev/null
@@ -1,161 +0,0 @@
-#!/usr/bin/env python
-import PySimpleGUI as sg
-import csv
-import os
-import operator
-
-"""
- Demo - Simple CSV Table Display
-
- Enables you to easily filter and sort tables that are in a CSV file format
-
- Choose your CSV file and then a table will be displayed.
- Clicking on a heading will sort on that column if no value is entered for the filter.
- If a filter value is entered and then a heading is clicked, then only rows matchines the filter in that column as are displayed
- The filtering is not case sensative so no need to worry about exact matches
- Use the checkbox to specify ascending or descending sorting
-
- The first row in your table needs to be the Column Names
-
- Copyright 2022 PySimpleGUI
-"""
-
-sg.theme('Dark gray 13')
-
-CSV_FILE = sg.popup_get_file('CSV File to Display', file_types=(("CSV Files", "*.csv"),), initial_folder=os.path.dirname(__file__), history=True)
-if CSV_FILE is None:
- sg.popup_error('Canceling')
- exit()
-
-csv.field_size_limit(2147483647) # enables huge tables
-
-def sort_table(table, cols, descending=False):
- """ 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), reverse=descending)
- except Exception as e:
- sg.popup_error('Error in sort_table', 'Exception in sort_table', e)
- return table
-
-
-def read_csv_file(filename):
- data = []
- header_list = []
- if filename is not None:
- try:
- with open(filename, encoding='UTF-16') as infile:
- reader = csv.reader(infile,delimiter='\t')
- # reader = fix_nulls(filename)
- header_list = next(reader)
- try:
- data = list(reader) # read everything else into a list of rows
- except Exception as e:
- print(e)
- sg.popup_error('Error reading file', e)
- return None, None
- except:
- with open(filename, encoding='utf-8') as infile:
- reader = csv.reader(infile, delimiter=',')
- # reader = fix_nulls(filename)
- header_list = next(reader)
- try:
- data = list(reader) # read everything else into a list of rows
- except Exception as e:
- with open(filename) as infile:
- reader = csv.reader(infile, delimiter=',')
- # reader = fix_nulls(filename)
- header_list = next(reader)
- try:
- data = list(reader) # read everything else into a list of rows
- except Exception as e:
- print(e)
- sg.popup_error('Error reading file', e)
- return None, None
- return data, header_list
-
-
-def main():
- data, header_list = read_csv_file(CSV_FILE)
-
- sg.popup_quick_message('Building your main window.... one moment....', background_color='#1c1e23', text_color='white', keep_on_top=True, font='_ 30')
-
- # ------ Window Layout ------
- layout = [ [sg.Text('Click a heading to sort on that column or enter a filter and click a heading to search for matches in that column')],
- [sg.Text(f'{len(data)} Records in table', font='_ 18')],
- [sg.Text(k='-RECORDS SHOWN-', font='_ 18')],
- [sg.Text(k='-SELECTED-')],
- [sg.T('Filter:'), sg.Input(k='-FILTER-', focus=True, tooltip='Not case sensative\nEnter value and click on a col header'),
- sg.B('Reset Table', tooltip='Resets entire table to your original data'),
- sg.Checkbox('Sort Descending', k='-DESCENDING-'), sg.Checkbox('Filter Out (exclude)', k='-FILTER OUT-', tooltip='Check to remove matching entries when filtering a column'), sg.Push()],
- [sg.Table(values=data, headings=header_list, max_col_width=25,
- auto_size_columns=True, display_row_numbers=True, vertical_scroll_only=True,
- justification='right', num_rows=50,
- key='-TABLE-', selected_row_colors='red on yellow', enable_events=True,
- expand_x=True, expand_y=True,
- enable_click_events=True)],
- [sg.Sizegrip()]]
-
- # ------ Create Window ------
- window = sg.Window('CSV Table Display', layout, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, resizable=True, finalize=True)
- window.bind("", '-CONTROL END-')
- window.bind("", '-CONTROL END-')
- window.bind("", '-CONTROL HOME-')
- window.bind("", '-CONTROL HOME-')
- original_data = data # save a copy of the data
- # ------ Event Loop ------
- while True:
- event, values = window.read()
- # print(event, values)
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
- if values['-TABLE-']: # Show how many rows are slected
- window['-SELECTED-'].update(f'{len(values["-TABLE-"])} rows selected')
- else:
- window['-SELECTED-'].update('')
- if event[0] == '-TABLE-':
- # if isinstance(event, tuple):
- filter_value = values['-FILTER-']
- # TABLE CLICKED Event has value in format ('-TABLE=', '+CLICKED+', (row,col))
- if event[0] == '-TABLE-':
- 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]
- # if there's a filter, first filter based on the column clicked
- if filter_value not in (None, ''):
- filter_out = values['-FILTER OUT-'] # get bool filter out setting
- new_data = []
- for line in data:
- if not filter_out and (filter_value.lower() in line[col_num_clicked].lower()):
- new_data.append(line)
- elif filter_out and (filter_value.lower() not in line[col_num_clicked].lower()):
- new_data.append(line)
- data = new_data
- new_table = sort_table(data, (col_num_clicked, 0), values['-DESCENDING-'])
- window['-TABLE-'].update(new_table)
- data = new_table
- window['-RECORDS SHOWN-'].update(f'{len(new_table)} Records shown')
- window['-FILTER-'].update('') # once used, clear the filter
- window['-FILTER OUT-'].update(False) # Also clear the filter out flag
- elif event == 'Reset Table':
- data = original_data
- window['-TABLE-'].update(data)
- window['-RECORDS SHOWN-'].update(f'{len(data)} Records shown')
- elif event == '-CONTROL END-':
- window['-TABLE-'].set_vscroll_position(100)
- elif event == '-CONTROL HOME-':
- window['-TABLE-'].set_vscroll_position(0)
- 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)
- window.close()
-
-
-if __name__ == '__main__':
- main()
diff --git a/DemoPrograms/Demo_Table_Checkmark.py b/DemoPrograms/Demo_Table_Checkmark.py
deleted file mode 100644
index 83e7fd77..00000000
--- a/DemoPrograms/Demo_Table_Checkmark.py
+++ /dev/null
@@ -1,85 +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 2023 PySimpleGUI
-"""
-
-# 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, 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 8ec56c9e..54b8add2 100644
--- a/DemoPrograms/Demo_Table_Element.py
+++ b/DemoPrograms/Demo_Table_Element.py
@@ -5,10 +5,9 @@ import string
"""
Basic use of the Table Element
-
- Copyright 2022 PySimpleGUI
"""
+sg.theme('Dark Red')
# ------ Some functions to help generate data for the table ------
def word():
@@ -25,34 +24,27 @@ def make_table(num_rows, num_cols):
# ------ 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 = [str(data[0][x])+' ..' for x in range(len(data[0]))]
# ------ Window Layout ------
layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25,
+ # background_color='light blue',
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',
+ alternating_row_color='lightyellow',
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
+ row_height=35,
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.Text('Change Colors = Changes the colors of rows 8 and 9')]]
# ------ Create Window ------
window = sg.Window('The Table Element', layout,
- # ttk_theme='clam',
# font='Helvetica 25',
- resizable=True
)
# ------ Event Loop ------
@@ -62,11 +54,10 @@ while True:
if event == sg.WIN_CLOSED:
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:][:])
+ window['-TABLE-'].update(values=data)
elif event == 'Change Colors':
window['-TABLE-'].update(row_colors=((8, 'white', 'red'), (9, 'green')))
window.close()
-
diff --git a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py
index 63ff1593..aeb43ac6 100644
--- a/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py
+++ b/DemoPrograms/Demo_Table_Element_Header_or_Cell_Clicks.py
@@ -15,7 +15,6 @@ import operator
This demo shows how you can use these click events to sort your table by columns
- Copyright 2022 PySimpleGUI
"""
sg.theme('Light green 6')
@@ -56,7 +55,6 @@ layout = [[sg.Table(values=data[1:][:], headings=headings + ['Extra'], max_col_w
auto_size_columns=True,
display_row_numbers=False,
justification='right',
- right_click_selects=True,
num_rows=20,
alternating_row_color='lightyellow',
key='-TABLE-',
@@ -74,33 +72,23 @@ layout = [[sg.Table(values=data[1:][:], headings=headings + ['Extra'], max_col_w
# ------ Create Window ------
window = sg.Window('The Table Element', layout,
- # ttk_theme='clam',
- resizable=True, right_click_menu=sg.MENU_RIGHT_CLICK_EDITME_VER_EXIT, finalize=True)
-
-# Add the ability to double-click a cell
-window["-TABLE-"].bind('' , "+-double click-")
+ ttk_theme='clam',
+ resizable=True)
# ------ Event Loop ------
while True:
event, values = window.read()
print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
+ if event == sg.WIN_CLOSED:
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 == 'Double':
for i in range(1, 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')))
- elif event == '-TABLE-+-double click-':
- print('Last cell clicked was', window['-TABLE-'].get_last_clicked_position())
if isinstance(event, tuple):
# TABLE CLICKED Event has value in format ('-TABLE=', '+CLICKED+', (row,col))
- # You can also call Table.get_last_clicked_position to get the cell clicked
if event[0] == '-TABLE-':
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]
diff --git a/DemoPrograms/Demo_Table_Simulation.py b/DemoPrograms/Demo_Table_Simulation.py
index 4beb9a21..19930e9b 100644
--- a/DemoPrograms/Demo_Table_Simulation.py
+++ b/DemoPrograms/Demo_Table_Simulation.py
@@ -28,9 +28,9 @@ def TableSimulation():
sg.Input(key='inputrow', justification='right', size=(8, 1), pad=(1, 1)),
sg.Input(key='inputcol', size=(8, 1), pad=(1, 1), justification='right'),
sg.Input(key='value', size=(8, 1), pad=(1, 1), justification='right')],
- [sg.Col(columm_layout, size=(800, 600), scrollable=True)]]
+ [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()
diff --git a/DemoPrograms/Demo_Tabs_Simple.py b/DemoPrograms/Demo_Tabs_Simple.py
index 924a7810..ac7a843a 100644
--- a/DemoPrograms/Demo_Tabs_Simple.py
+++ b/DemoPrograms/Demo_Tabs_Simple.py
@@ -1,16 +1,9 @@
#!/usr/bin/env python
-
-"""
- Demo - Simple Tabs
-
- How to use the Tab Element and the TabGroup Element
-
- Copyright 2021 PySimpleGUI
-"""
-
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')],
@@ -21,16 +14,17 @@ 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-'),
+tab_group_layout = [[sg.Tab('Tab 1', tab1_layout, font='Courier 15', 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-')]]
+ sg.Tab('Tab 4', tab4_layout, visible=False, key='-TAB4-'),
+ ]]
# 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')]]
+ [sg.Text('Make tab number'), sg.Input(key='-IN-', size=(3,1)), sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Select')]]
window = sg.Window('My window with tabs', layout, no_titlebar=False)
@@ -47,6 +41,5 @@ while True:
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_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py b/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py
deleted file mode 100644
index 9292e17e..00000000
--- a/DemoPrograms/Demo_Theme_Dark_Custom_Elements_Check_Toggle_Buttons.py
+++ /dev/null
@@ -1,96 +0,0 @@
-
-import PySimpleGUI as sg
-
-
-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_Time_Chooser.py b/DemoPrograms/Demo_Time_Chooser.py
deleted file mode 100644
index 89e20a97..00000000
--- a/DemoPrograms/Demo_Time_Chooser.py
+++ /dev/null
@@ -1,79 +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 2023 PySimpleGUI
-"""
-
-
-
-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_Periodic.py b/DemoPrograms/Demo_Timer_Periodic.py
deleted file mode 100644
index ff051fd2..00000000
--- a/DemoPrograms/Demo_Timer_Periodic.py
+++ /dev/null
@@ -1,111 +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 2022 PySimpleGUI
-"""
-
-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_User_Setting_Save_Window_Inputs.py b/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py
deleted file mode 100644
index 1c9de98a..00000000
--- a/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py
+++ /dev/null
@@ -1,57 +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 2022 PySimpleGUI
-"""
-
-# 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_As_Simple_Database.py b/DemoPrograms/Demo_User_Settings_As_Simple_Database.py
deleted file mode 100644
index 6d76bcd6..00000000
--- a/DemoPrograms/Demo_User_Settings_As_Simple_Database.py
+++ /dev/null
@@ -1,66 +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 2022 PySimpleGUI
-"""
-
-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 4a16fbd6..00000000
--- a/DemoPrograms/Demo_User_Settings_Auto_Load_and_Save.py
+++ /dev/null
@@ -1,55 +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 2023 PySimpleGUI
-"""
-
-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_Watermark_Window.py b/DemoPrograms/Demo_Watermark_Window.py
deleted file mode 100644
index 49b61713..00000000
--- a/DemoPrograms/Demo_Watermark_Window.py
+++ /dev/null
@@ -1,109 +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 2023 PySimpleGUI
-"""
-
-"""
-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_Config_Events.py b/DemoPrograms/Demo_Window_Config_Events.py
deleted file mode 100644
index 4df13a32..00000000
--- a/DemoPrograms/Demo_Window_Config_Events.py
+++ /dev/null
@@ -1,34 +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 2022 PySimpleGUI
-"""
-
-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_Open_Multiple_Times.py b/DemoPrograms/Demo_Window_Open_Multiple_Times.py
index ac4bbca7..ffcc6a49 100644
--- a/DemoPrograms/Demo_Window_Open_Multiple_Times.py
+++ b/DemoPrograms/Demo_Window_Open_Multiple_Times.py
@@ -10,10 +10,10 @@ import PySimpleGUI as sg
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 application is getting a little larger than the typical small data
+ way to encapsulate windows if your applcation is gettinga little larger than the typical small data
entry window.
- Copyright 2020, 2023 PySimpleGUI.org
+ Copyright 2020 PySimpleGUI.org
"""
@@ -25,12 +25,11 @@ def make_window():
:return: Window that is created using the layout defined in the function
:rtype: Window
"""
- layout = [[sg.Text('The program will only exit using the "Quit Program" button.')],
- [sg.Text('Closing the window or using Exit button will cause a new window to be created.')],
- [sg.Input(key='-IN-')],
- [sg.Button('Does Nothing'), sg.Button('Exit'), sg.Button('Quit Program')]]
+ 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 that restarts on exit', layout)
+ return sg.Window('Window Title', layout)
def main():
@@ -42,10 +41,8 @@ def main():
if event == sg.WIN_CLOSED or event == 'Exit':
window.close()
window = make_window()
- elif event == 'Quit Program': # The Quit Program button break out of event loop and exits program
- break
-
- window.close()
+ elif event == 'Go':
+ window['-OUT-'].update(values['-IN-'])
if __name__ == '__main__':
diff --git a/DemoPrograms/Demo_Window_Timer.py b/DemoPrograms/Demo_Window_Timer.py
deleted file mode 100644
index e21bff6d..00000000
--- a/DemoPrograms/Demo_Window_Timer.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import PySimpleGUI as sg
-
-"""
- Demo Program - Window Timers
-
- Uses the PySimpleGUI Window Timers to generate single or periodic timer events.
- Requires version 4.60.4.133 or greater of PySimpleGUI.
-
- Copyright 2022 PySimpleGUI
-"""
-
-
-def main():
- layout = [ [sg.Text('Demonatrataion of Window Timers', font='_ 15')],
- [sg.T('Timer duration in ms:'), sg.Input(1000, key='-DURATION-', s=4), sg.Checkbox('Repeats', True, key='-REPEATS-'), sg.Button('Start')],
- [sg.T('Timer ID to stop:'), sg.Input(key='-STOP-', s=4), sg.Button('Stop'), sg.B('Stop All'), sg.B('List Active')],
- [sg.Output(size=(90, 10))],
- [sg.Button('Does nothing'), sg.Button('Exit')] ]
-
- window = sg.Window('Window Title', layout)
-
- while True:
- event, values = window.read()
- print(event, values)
- if event == sg.WIN_CLOSED or event == 'Exit':
- break
- if event == 'Start':
- try:
- duration = int(values['-DURATION-'])
- except:
- continue
- window.timer_start(duration, repeating=values['-REPEATS-'])
- elif event == 'Stop':
- try:
- id = int(values['-STOP-'])
- except:
- continue
- window.timer_stop(id)
- elif event == 'Stop All':
- window.timer_stop_all()
- elif event == 'List Active':
- sg.cprint('Active Timers:', end='', c='white on red')
- sg.cprint(window.timer_get_active_timers(), c='white on green')
- window.close()
-
-if __name__ == '__main__':
- main()
-
diff --git a/DemoPrograms/readme.md b/DemoPrograms/readme.md
index a9619de2..54dd32a0 100644
--- a/DemoPrograms/readme.md
+++ b/DemoPrograms/readme.md
@@ -2,7 +2,7 @@
## One Stop Shopping For Templates and Techniques
-This folder of over 320 programs is your jump-start to getting you to a solution as quickly as possible. You can think of them as Recipes from a large PySimpleGUI Cookbook.
+This folder of over 170 programs is your jump-start, spring board, boost, shove in the back, cheat sheet to get you to a solution as quickly as possible. You can think of them as Recipes from a large PySimpleGUI Cookbook.
Programs in this folder have a range of uses and reasons for existing
@@ -10,37 +10,13 @@ Programs in this folder have a range of uses and reasons for existing
* Design patterns are "official" ways to get something done (Multiple windows)
* Integrate PySimpleGUI with another package / technology (OpenCV, Matplotlib)
* Assemble PySimpleGUI elements in a useful way (Bar graphs, games)
+* Additional user code that enable new functionality (ANSI color strings)
* How to deal with common GUI problems (work requiring lots of time)
## Demo Program Browser
-The best way to work with these demos is to use the Demo Program Browser. This browser will enable you to search by filename and also enable you to search inside the demos, a particularly powerful capability.
-
-It will enable you to run the programs or launch your editor / IDE to edit them.
-
-### Installing from GitHub
-
-You'll find installation instructions in the Cookbook. It is the first Recipe in the Cookbook. The instructions are detailed with many screenshots.
-
-### Installation Using Pip
-
-There are a few ways to get these programs on your system. One of the simplest is to use `pip`:
-
-`pip install psgdemos`
-
-Or if on Linux / Mac (that uses `pip3`
-
-
-`pip3 install psgdemos`
-
-This will install `psgdemos` from PyPI which includes the Demo Browser and all of these Demo Program source files.
-
-To invoke the demo browser after installing using pip, type:
-`psgdemos`
-
-from the command line and you'll be shown the Demo Browser
-
+The best way to work with these demos is to use the Demo Program Browser. You'll find installation instructions in the Cookbook. This browser will enable you to search by filename and also enable you to search inside the demos, a particularly powerful capability.
## Coding Conventions
@@ -81,7 +57,7 @@ There are Demo Programs folders under each of the ports folders in the GitHub.
## Running Demos Online
-Some of the Demo Programs are included in the online eCookbook (http://eCookbook.PySimpleGUI.org). The eCookbook has a mix of a few of these Demos along with some unique examples not in the Demo Program.
+Recently two online Python services have been used to demonstrate using PySimpleGUI- Trinket & repl.it. You will find not only some of the Demo Programs from this folder on these sites, but other demo programs as well. They make good "scratch pads" for posting PySimpleGUI code. They are superior to GithubGists because not only can you share your code, but people can run the code without having to install or do anything locally.
### Trinket
@@ -93,11 +69,26 @@ The benefits of using Trinket include
* No need to install PySimpleGUI or even Python on your local machine
* Additional explanation can be included with the code, including images
-This link will get you to the eCookbook:
+You'll find the demos that have been added to Trinket here:
-http://eCookbook.PySimpleGUI.org
+http://Trinket.PySimpleGUI.org
+
+### Repl.it
+
+Prior to discovering Trinket PySimpleGUI demo programs were being hosted online on repl.it. Repl.it has several advantages over Trinket including:
+
+* Able to run both PySimpleGUI and PySimpleGUIWeb programs
+* Can use other packages with PySimpleGUI
+* Can pip install specific PySimpleGUI versions to use
+
+You'll find a list of repl.it demos here:
+
+https://repl.it/@PySimpleGUI
+
+These programs may not be the most up to date and in fact are likely to contain old coding constructs and examples. As a result, use them more of a demonstration of "what's possible" rather than "exactly how to do it".
+
## Other Sample Code in this GitHub Account
The PySimpleGUI GitHub account has a number of repos that contain larger applications that use PySimpleGUI. A few linger in the PySimpleGUI project folder like the HowDoI, chess, exemaker, and some user created programs. They'll get moved out at some point. Until then, browse around the repo. Explore a little. Some are older, some newer, but none are as important as the Demo Programs folder which is kept up to date.
@@ -115,16 +106,14 @@ If you encounter more subtle problems, you should take into account that these p
# Author
-The PySimpleGUI Organization and a few rare examples were provided by PySimpleGUI users.
+The PySimpleGUI Organization and PySimpleGUI users
If the code has been provide by a PySimpleGUI user, then the comments at the top of the program will indicate the author.
-Because the PySimpleGUI project does not accept pull requests, it's unusual for Demo Progams to originate outside the project. The eCookbook is a better place to find user created examples.
-Of cource, GitHub is where you'll find many 1,000's of user created PySimpleGUI programs, so go take a look! Issue #10 here on the PySimpleGUI GitHub has screenshots submitted by users and is another location you can go for examples and inspiration.
# License
-Copyright 2019, 2020, 2021, 2022 PySimpleGUI
+Copyright 2019 PySimpleGUI.org
-GNU Lesser General Public License (LGPL 3) +
+GNU Lesser General Public License (LGPL 3) +
diff --git a/Demo_Toolbar/Demo_Floating_Toolbar.py b/Demo_Toolbar/Demo_Floating_Toolbar.py
new file mode 100644
index 00000000..de69a7cc
--- /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 00000000..05019d69
--- /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='iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsSAAALEgHS3X78AAAHPklEQVRYhbVXbUxb1xl+zjn30/a9/gBsbBwCBhPAUD4W2pClSZM0TemkdZPaSf0RTfszTZv2o1qzqmqiaL82salSqzZptVVqqmRV1dEssERKxJKxLAWajEYkAcxXyoBg4xgcY8AY23c/+EgwNiTRdqTz557zPOd5n/Oe95wLPGFzOp24fPp0yeTJk4cbjxzJelIe9qTA5uPHt7mHho6HOzsP1RQUWODxnO/o6Pj/C3A6naT5/ffLC9raWqZbW2v8t29GEz7/d3dXVuY56us7W69cmX1EHqaqKn1sAWffe6+ipK/vROjChaq+WNj/r2wWN44FEvAHamtcLhtfW3uuo7NT24xHVVUKPIYDzrw80vzuu1WuixdbQufPV3SJC747VcxUWC1ZvtFoRPX6tMX+wR27PJ6CLbt3d3zV1WWy2+0HZVn2APAkEgmPKIqeeDzeAwDhcFgLh8MaeVQB//j445qSrq4TU2fO1HlF+L07BGN5hVmXnWXG4PA4+q/OTVb1RwSjwSRZGxqaLm3deq7z+vU/B4NBjIyMwOfzQVEU+Hw+AgD19fUCAGwqwJmXR08dO1brampqjly7Zuu26/3j35GNNdutOqvVAV4QEA6H0D8wgr7u6OS29oCgSxCj7eWXvyB7snLjCDwLAiSTSe3YB20/avv3aNPD/NxmAk4dPbq9pLX1w3BHh23IrPMH6lW1vMyks+XmQxBEAIDRlI2iIoATJqw9kaS/sDt4P3b27A90d2yJql83EMIzxGILcYGniVT+jAKcDgc99dZbT7tOnGgO9/dn9RZb/f5nzeo2t1lPIGM6GAUlUbBlDxl4WA1GcAcEW2+27LddGiXz7cPqrd9fROXPDkC2GMAYv8q/sgUZBZw6fLi+5PPPj0d6e7NHnNm+qX1Wtdht0muLAj7rVhB0fR81VgLc/AKXTK/ioIuHe/5LFG6NgeMmbTdn4r6szrvM195vIAkN24+8AkYfLNfe3h5bEp4aud3Omo8e3eVubPzrgtdb4PU4fYHvbVFLn3LobblOxKJJdMyWwPXiL/F8XQV6brQjWv8r1D9VBvdsJ7Jy9JBlCXorMYyJmsBGZjA74ENo0IeEq7T5Srf3FrBBHWh5++09ZZ9+eiI2MpL/baHdH/yhS813Z+lzrHmQJD1mQrNIjvXBEf4G/NAFZEXvYCfrRtn9v0MI3oZozYUo6cDxFIZsEWOLiLDAQnR+2Cd7bPkm8759Z77u6oqtqwNOu51refPNvaWNjWcWx8edAzUu3/QrJWphuV2fk+OEJCsglGFuZhYtoTJ0lh2BuXwvvvrPLD6SfwHOtReFiUEYFApKOciyAlEUoOZJwj2zMq0N309GbvWU1VosTxcfOPB1y+XLgXA4rK0K+Nsbbzxfefr0B/GJCceoy+EPveZRHEUWgyXLAUlWQAkDIQxzMzO4Iz+Dssrt2FkkYnzgNsxFz+ClIh7ucBsgLM2jlFtyggKKhTP4CD+FiYg26x1wlypKhfm555qv3bgRZc7cXP7c668frHznnb/EJybsQ3Vuf/hQteIssRnMFgcknRGEstWemI0gSXR4oWARXHQEJVNXUesQ4Ex8C8PkNSQU0+pcSjmIsgJe4GByykooxzgd9wYQ6ekrrTEa64v377/OXqiutv387t0/LHq928bcW3wzP9mu5BRY9EazDZLOuBr5SudFEYViAPpIP5RwP7IMGrIXvJAjXkDgoEnGNfMp5SCIOhCahDFHNAQ5YSoxGsLcwFDRnoaGEDcej09M7NrVNDo+VBR8tcJcVmzT6/QWyDpT2uPJ61RAp0IDoAFIpowTkHX1lTEeJrMTjPlRup/Y2+ZjI4XDscG7VmszAYAd5eXGaHCi7seH6n7TsK9ip6LawPO6tAI+OfklAvem0o4BwEsv7oHH404zoiESnsS9YAD+hfzjv/vtJ38cDoZ6OQDo6Om5D6D1NY3+lOMFUMaDPlS1Hm6Dff2IT42D0vVjszEgUFedEct4AYwTUOyqvnm1b+AGkFIJCWVLi9Olnq7xjEAQCWiaayyhLXOkxWqgjANlHAh5AF4jgFIGxjhQxoNkiIJjFJLIAWStAgJgUUsuJV8GLGU82EYCVqhWsjddY5RCFrjU9UEIEI1vhNWWEjQ1oHSLEMqBMCG9AEZhkLl1W0AAROPxzFhNA8j6xMkgYGMHjBIPgaWQEWBuESCEpsdq2hrrNxGQ2QGOMQgcA5ey/j99KtR44H/hwOY5oOpEiPxash1kAdMzfEYHNE0D8KhbwLiNTwFPwLO1L+98I0FykS47sB5LNDziFhAsO5DpKFHIAoOQ8pIgBJB4BkJpWqz2OElIM0QBLOWAQeIgpiAJAFlkICSTA4+RhNjAAUYpZJGDlLIFhBBIPIOWoRI+hgNk+T7P8F4lFJIkQxHXk0nCIuYJTYsl0ECWk5DQB8/zTf8LUluScAguUG0mvv73bz6exuOHJKwUwg8/+lNk5et/AVSZbsni/k4yAAAAAElFTkSuQmCC'
+
+
+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 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 00000000..67af4517
--- /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 00000000..9f7cbc09
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 00000000..e5f4d178
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 00000000..39166560
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 00000000..726234af
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 00000000..6337c8a3
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 00000000..53de7e07
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 00000000..3245ab50
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 00000000..e4fbd085
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 00000000..4fe82d1b
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 00000000..93d2892e
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 00000000..fe9f038a
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 00000000..f2df8f43
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 00000000..7df8a04e
--- /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 00000000..dee9a36e
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 00000000..a90ac874
--- /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/PySimpleGUI.py b/PySimpleGUI.py
index fbbfd08d..697b1ef2 100644
--- a/PySimpleGUI.py
+++ b/PySimpleGUI.py
@@ -1,491 +1,21 @@
#!/usr/bin/python3
-version = __version__ = "4.61.0.206 Unreleased"
+version = __version__ = "4.60.5"
_change_log = """
- Changelog since 4.60.0 released to PyPI on 8-May-2022
-
- 4.61.0.1
- main_open_github_issue - prefill the "Details" using the platform module (thank you macdeport!)
- Fills Mac, Windows and Linux with details
- 4.61.0.2
- Fix for the "jumping window problem on Linux". Major credit to Chr0nic for his amazing "stick with it" work on this problem!
- 4.61.0.3
- Removed the previous fix attempt for jumping window on linux
- Added ability for Mac users to specify file_type in Browse and popup_get_file
- This feature must be ENABLED by the user in the Mac control panel that can be found in the PySimpleGUI Global Settings
- The default is this feature is OFF
- 4.61.0.4
- New location parameter option for Windows. Setting location=None tells PySimpleGUI to not set any location when window is created. It's up to the OS to decide.
- The docstring for Window has been changed, but not all the other places (like popup). Want to make sure this works before making all those changes.
- 4.61.0.5
- Added check for None invalid values parm when creating a Listbox element
- 4.61.0.6
- Column docstring changed to add reminder to call contents_changed if changing the contents of a scrollable column
- 4.61.0.7
- Fixed crash when horizontal_scroll=True for Listbox element
- 4.61.0.8
- Added readonly to Input.update
- 4.61.0.9
- Added Window.set_resizable - can change the X and Y axis resizing after window is created
- 4.61.0.10
- Added wrap parameter to Spin element - if True, wraps back to the first value when at the end
- Temp test code added for a new verification feature
- 4.61.0.11
- Fixed Spin Element docstring - readonly was not correct
- 4.61.0.12
- Output element - addition of wrap_lines and horizontal_scroll parameters
- Multiline element - addition of wrap_lines parameter
- 4.61.0.13
- Added Window.unbind
- 4.61.0.14
- Added (None, None) to the Window docstring
- 4.61.0.15
- Fix for continuous Graph element mouse up events when reading with a timeout=0. Big thank you to @davesmivers (THANKS DAVE!!) for finding and fixing
- 4.61.0.16
- Added platform (Windows, Mac, Linux) and platform version information to the get_versions function
- 4.61.0.17
- Added a fix for the file_types Mac problem that doesn't require the system settings to be used... let's give it a go!
- 4.61.0.18
- Added ubiquitious Edit Me to the right click menu
- 4.61.0.19
- PySimpleGUI Anniversary sale on Udemy course coupon
- 4.61.0.20
- Fix for bind_return_key - if a button has been disabled, then the event shouldn't be generated for the return key being pressed
- 4.61.0.21
- Added cols_justification for Table element - list or tuple of strings that indicates how each column should be justified
- 4.61.0.22
- Better error handling for table element's new justification list. If a bad value is found, will use the default value
- 4.61.0.23
- Additional mac filetype testing.... added more combinations that specify
- 4.61.0.24
- Added * *.* to the Mac filetypes to check for
- 4.61.0.25
- New logic for checking for the * case for Mac filetypes
- 4.61.0.26
- Docstring update - TabGroup visible parameter marked as deprecated . Use a Column element to make a TabGroup invisible
- 4.61.0.27
- Docstring update for the pin helper function that describes the shrinking of the container that it helps provide.
- Also added explanation that it's the elements you want to make visible/invisible that are what you want to pin
- 4.61.0.28
- Applied same Mac file_types fix to popup_get_file
- Removed filetypes setting from Mac Feature Control Panel
- 4.61.0.29
- Addition of enable_window_config_events to the Window object. This will cause a EVENT_WIMDOW_CONFIG event to be returned
- if the window is moved or resized.
- 4.61.0.30
- Made upgrade from GitHub window resizable so can screencapture the entire session
- 4.61.0.31
- Added new constant TKINTER_CURSORS which contains a list of the standard tkinter cursor names
- 4.61.0.32
- Added erase_all parameter to cprint (like the Debug Print already has)
- 4.61.0.33
- Fix popup_scrolled - was only adding the Sizegrip when there was no titlebar. It should be added to all windows
- unless the no_sizegrip parameter is set.
- popup_scrolled - added no_buttons option. If True then there will not be a row at the bottom where the buttons normally are.
- User will have to close the window with the "X"
- 4.61.0.34
- popup_scrolled - added button_justification parameter. Wanted to make scrolled popups consistent with other popups which have left justified
- buttons. But since they've been right justified in the past, want to give users the ability to retain that look.
- Since the Sizegrip works correctly now, it increases the changes of accidently clicking a button if it's right justified.
- 4.61.0.35
- Added default_color to ColorChooser button
- 4.61.0.36
- Added to Button element error message that images must be in PNG or GIF format
- 4.61.0.37
- Added exapnd_x and expand_y to all of the "lazy buttons" and Chooser buttons
- 4.61.0.38
- Column element - added horizontal_scroll_only parameter (fingers crossed on this one....)
- 4.61.0.39
- New signature testing
- 4.61.0.40
- Exposed the Table Element's ttk style using member variable TABLE.table_ttk_style_name
- 4.61.0.41
- New signature format
- 4.61.0.42
- Backed out the changes from 4.61.0.38 (horizontal_scroll_only parameter). Those changes broke code in the scrollable columns. Need to make time to work on this feature more.
- 4.61.0.43
- Added a print if get an exception trying to set the alpha channel after a window is created (troubleshooting a Mac problem)
- 4.61.0.44
- Updated Menubar docstring to clarify the Menubar iself cannot have colors changed, only the submenus. Use MenubarCustom if you want full control
- Format of file-signature changed
- 4.61.0.45
- Further refinement of Menubar docstring
- 4.61.0.46
- Added suggestion of using the Demo Browser to the checklist item of "Look for Demo Programs similar to your problem"
- 4.61.0.47
- Testing some importing methods
- Delay rerouting stdout and stderr in Output and Multiline elements until window is being built instead of when element is initialized
- 4.61.0.48
- Additional window movement capability. If Control+Mouse movement feature is enabled, then Control+Arrow key will move the window 1 pixel
- in the indicated direction
- 4.61.0.49
- Added Window.set_size to match the other settings that are performed through method calls. There is also the Window.size property, but
- since PySimpleGUI rarely uses properties, it makes sense to include a method as well as a property
- 4.61.0.50
- Fix for ColorChooser button filling in a None value when cancel from color choise dialog box. Nothing will be filled in target if dialog cancelled
- 4.61.0.51
- vtop, vcenter, vbottom helper functions gets background_color parameter
- vcenter and vbottom - added USING the expand_x and expand_y parms that were already defined. (HOPE NOTHING BREAKS!)
- 4.61.0.52
- justification parameter added to Listbox (default is left.. can be right and center now too)
- 4.61.0.53
- Made settings dictionary multiline in test harness write-only. New coupon code
- 4.61.0.54
- alpha_channel added to set_options. This sets the default value for the alpha_channel for all windows both user generated and PySimpleGUI generated (such as popups).
- 4.61.0.55
- Allow Browse/Chooser buttons (that have a target) to indicate a target key that is a tuple.
- 4.61.0.55
- While not actually correct.... 4.60.1 was released in the middle of the development above... I'm changing the version to look as
- if this release is based on 4.60.1. This code DOES have the same code that's in 4.60.1 so it's more a matter of symantics.
- Hoping this clears up confusion. Sorry for the dot-release causing so much confusion.
- 4.61.0.56
- Fix for Window.extend_layout. Was not picking up the background color of the container that the rows were being added to.
- 4.61.0.57
- Fixed Text element's update method docstring to indicate that value can be "Any" type not just strings
- 4.61.0.58
- Addition of without_titlebar paramter to Window.current_location. Defaults to False. If True, then the location of the main portion of the window
- will be returned (i.e. will not have the titlebar)
- 4.61.0.59
- Fix for crash if COLOR_SYSTEM_DEFAULT specified in parameter disabled_readonly_background_color or disabled_readonly_text_color for Input Element.
- Also applied similar fix for Tab element's focus color
- 4.61.0.60
- Addition of set_option parameter hide_window_when_creating. If set to False then window will not be hidden while creating and moving
- 4.61.0.61
- Changed the documentation location to PySimpleGUI.org (updated some comments as well as the SDK Reference Window's links)
- New coupon code. Make the Udemy button in the test harness now include the coupon code automatically
- 4.61.0.62
- Removed the "NOT avoilable on the MAC" from file_types parameter in the docstrings
- Use Withdraw to hide window during creation
- 4.61.0.63
- Addition of checklist item when logging new issue to GitHub - upgraded to latest version of PySimpleGUI on PyPI
- Listbox justification parameter found to not be implemented on some early verions of tkinter so had to protect this situation. This new feature crashed on the Pi for example
- 4.61.0.64
- Allow set_options(window_location=None) to indicate the OS should provide the window location.
- This will stop the Alpha channel being set to 0 when the window is created
- 4.61.0.65
- Addition of new Mac Control Panel option and emergency patch for MacOS version 12.3+
- If MacOS version 12.3 or greater than option is ON by default
- When ON, the default Alpha channel for all windows is set to 0.99.
- This can either be turned off, or can be overridden by calling set_options in your application
- 4.61.0.65
- Bumping version number to avoid confusion. An emergency 4.60.2 release was posted to PyPI. This change was added to this current GitHub version of PySimpleGUI.
- 4.61.0.66
- Fixed bug in checking Mac OS version number that is being released as 4.60.3
- 4.61.0.67
- Correctly check for Mac 12.3+ AND 13+ this time.
- 4.61.0.68
- Roll in the changes being released to PyPI as 4.60.3
- 4.61.0.69
- Test to see if the additional pack of Notebook in Tab code was causing expansion problems
- 4.61.0.70
- Debug Print - fix for bug caused by no_button being set with non_blocking... a lesson in thorough testing... assumption was either blocking OR no_button (or else app would
- close without seeing the output... unless something else blocked. (DOH)
- 4.61.0.71
- "Window closed" check added to update methods for elements. This will prevent a crash and instead show an error popup
- Will be helpful for users that forget to check for closed window event in their event loop and try to call update after window closed.
- 4.61.0.72
- Output element now automatically sets auto_refresh to True. Should this not be desired, switch to using the Multiline element. There will likely be
- no impact to this change as it seems like the windows are alredy refreshing OK, but adding it just to be sure.
- 4.61.0.73
- Addition of Window.key_is_good(key) method. Returns True if key is used in the window. Saves from having to understand the window's key dictionary.
- Makes for easier code completion versus writing "if key in window.key_dict"
- 4.61.0.74
- Combo - if readonly, then set the select colors to be "transparent" (text=text color, background=background color)
- 4.61.0.75
- Better description of bar_color parm for the ProgressMeter element and the one_line_progress_meter function
- Combo element - addition of select parameter to enable easier selection of the contents of clearing of the selection of the contents.
- 4.61.0.76
- Changed the _this_elements_window_closed to use a flag "quick_check" for cheking is the window is closed. Found that calling tkinter.update takes over 500ms sometimes!
- For appllications that call update frequently, this caused a catestrophic slowdown for complex windows.
- 4.61.0.77
- New Window method - get_scaling - gets the scaling value from tkinter. Returns DEFAULT_SCALING if error.
- 4.61.0.78
- Custom Titlebar - Support added to Window.minimize, Window.maximize, and Window.normal
- 4.61.0.79
- Fix for Mulitline showing constant error messages after a Window is closed.
- Fix for correctly restoring stdout, stderr after they've been rerouted. THIS CODE IS NOT YET COMPLETE! Shooting for this weekend to get it done!
- Image element - more speicific with tkinter when chaning to a new image so that pypy would stop crashing due to garbage collect not running.
- This change didn't fix the pypy problem but it also didn't hurt the code to have it
- 4.61.0.80
- Quick and dirty addition of Alt-shortcuts for Buttons (like exists for Menus)
- For backward compatablity, must be enabled using set_options with use_button_shortcuts=True
- Fixed docstring errors in set_options docstring
- 4.61.0.81
- Completed restoration of stdout & stderr
- If an Output Element is used or a Multline element to reroute stdout and/or stderr, then this hasn't worked quite right in the past
- Hopefuly now, it does. A LIFO list (stack) is used to keep track of the current output device and is scrubbed for closed windows and restored if one is closed
- 4.61.0.82
- Addition of Style Names for horizontaland vertical ttk scrollbars - hsb_style_name and vsb_style_name so that scrollbar colors can be changed in user code
- 4.61.0.83
- Output element - now automatically reroutes cprint to here as well. Assumption is that you want stuff to go here without
- needing to specify each thing. If want more control, then use the Multiline directly
- 4.61.0.84
- Output element - updated docstring
- 4.61.0.85
- Combo Element - new parameter enable_per_char_events. When True will get an event when individual characters are entered.
- 4.61.0.86
- Added path to the interpreter to the get_versions information for better debugging
- 4.61.0.87
- Dark Gray 16 theme added
- 4.61.0.88
- New batch of Emojis!
- 4.61.0.89
- Addition of TITLEBAR_TEXT_KEY to provide access to custom titlebar titles
- 4.61.0.90
- Implemented the visible parameter for TabGroup. Was not being honored when creating element. Added TabGroup.update so it can be made visible.
- 4.61.0.91
- Added support for Custom Titlebar to the Window.set_title method
- 4.61.0.92
- Addition of starting_row_number parameter to the Table element. Sets the value for the first row in the table.
- 4.61.0.93
- Added 2 parameters to popup - drop_whitespace is passed to the wraptext.fill method. right_justify_buttons will "push" buttons to
- the right side if set to True
- 4.61.0.94
- Added Element.save_element_screenshot_to_disk - uses the same PIL integration that the save window screenshot to disk uses but applied to a single element
- 4.61.0.95
- Changed popup again - replaced right_justify_buttons with button_justification. Also removed the extra padding that was being added to the buttons. This
- matches a changed made to popup_scrolled earlier
- 4.61.0.96
- More emojis? Yes... more emojis...
- 4.61.0.97
- The main test harness now shows the python interpreter used to launch the test harness to make clearer what's running
- 4.61.0.98
- Better alignment of text in test harness
- Fixed mispelling in SystemTray.show_message - crashed if an int was passed in as the time value
- 4.61.0.99
- popup_get_text - Addition of history feature to bring up to same level as other popup_get_ functions.
- 4.61.0.100
- Set the "Active" foreground and background colors for Menu and ButtonMenu items. Automatically uses the swapped foreground and background colors.
- This impacts both inside the menus themseleves as well as the ButtonMenus so that when they are used in a MenubarCustom they mouseover nicely now.
- 4.61.0.101
- Added Window.is_hidden method. Returns True if the window is currently hidden
- 4.61.0.102
- Fixed error in the main test harness "not modal" popup test. Was setting the "Force Modal" setting to true after the popup test.
- 4.61.0.103
- Trinket is detected using a new mechansim now. The previous one was waayyy too simnple and as a result has broken in the past week.
- 4.61.0.104
- Version bump to keep up with the PyPI emergency 4.60.4 release
- 4.61.0.105
- Added SYMBOL_BULLET character
- 4.61.0.106
- Neon Green, Blue, Yellow themes... was writing some tests using them and thought why not start a new theme color category... "neon"
- 4.61.0.107
- Fixed an unreported problem perhaps... Added saving new menu into the Menu.Widget memeber variable in the Menu.update method.
- 4.61.0.108
- Added drop_whitespace to the docstring for popup. Parm has been in the code for quite some time but forgot the docstring so it's not in the SDK reference.
- 4.61.0.109
- Changed error message in error window when an element reuse has been detected in a layout. Previous message wasn't clear why there was an error.
- 4.61.0.110
- Added very detailed information to popup_error_with_traceback if the Exception information is passed in as one of the arguments
- 4.61.0.111
- Menu Element - delete all items in existing Menu widget rather than making a new one when the Menu definition changes
- 4.61.0.112
- Input.update - added font parameter
- 4.61.0.113
- Dark Blue 18 theme, a materially kinda theme, added - tip - experiment like PySimpleGUI does when "computing" colors. Grab a color of a part of a theme and use it as a background or a secondary button color. In other words, mix and match since the colors should all work together by design.
- 4.61.0.114
- Added execute_py_get_running_interpreter to differentiate between the one in the settings file versus currently running interpreter
- 4.61.0.115
- Image Element... added Zooooooooommmmm parameter
- 4.61.0.116
- Proliferiation/infection of the zoom parameter to more elements with images - Button, ButtonMenu
- Note that zoom and subsample can BOTH be used. This enables fractional scaling. Want 2/3 the size of the image? subsample=3, zoom=2
- Tab is the remaining element this is being added to
- The Buttons implemented as functions need this addition as well
- Addition of the image_source parameter to Button and Button.update. This way of specifying images is commonly used in other elements
- Fixed ButtonMenu bug - subsample was not being applied to initial image in the layout
- 4.61.0.117
- Fix for set_vscroll_position not working correctly for a scrollable Column
- 4.61.0.118
- Completed addition of zoom options for images by adding image_zoom parameter to Tab element
- 4.61.0.119
- Fixed Neon Yellow theme. Had an extra "#" in a color.
- 4.61.0.120
- New coupon code
- 4.61.0.121
- New Jedi emoji
- 4.61.0.122
- Swapped Push and Stretch, VPush and VStretch. Made Push and VPush the function and Stratch and VStresth the aliases. Did this because
- Push is used almost universally, not Stretch.
- 4.61.0.123
- Fix for incorrect values for Element.ttk_style and Element.ttk_style_name. Some elements had values overwritten if a scrollbar, etc, was used
- Changed a number of the ttk elements (Button for example) to use the base name as the parm to creating the custom style to achieve
- a more predictable naming style (relies on the formula used in the create style function rather than ad hoc adding "custom" onto name)
- 4.61.0.124
- Multiline Element docstring fixes
- 4.61.0.125
- Addition of 2 overrides to Window.find_element so that more control is available to applications wishing to perform special key lookups
- 4.61.0.126
- Made button_color parameter's docstring value consistent across all calls. Now set to - (str, str) | str
- 4.61.0.127
- User settings delete calls - aded silent_on_error option so deletes of non-existant entries can uappen silently if desired.
- popup_quick_message - now defaults to keep-on-top to True
- 4.61.0.128
- Cleaned up User Settings API code for porting
- 4.61.0.129
- button_color parm added to ButtonMenu.update
- 4.61.0.130
- New coupon
- 4.61.0.131
- Window timers feature added. Get a single or repeating timer events for your Window by calling window.timer_start
- 4.61.0.132
- Added the Window.stop_all method to stop all timers for a window
- 4.61.0.133
- Added Window.timer_get_active_timers to get a list of the active timers for the window
- 4.61.0.134
- popup_get_date - exposed the fonts as parameters so that the user code and modify them (specifically to get around a Mac font bug)
- 4.61.0.135
- Renamed QuickMeter to _QuickMeter so that it's clear that it's not an object meant to be used by users
- 4.61.0.136
- Tree element - if headings is set to None, no headings area is shown
- 4.61.0.137
- "Take me to error" button is disabled in error traceback popup if not editor is configured. Also adds instructions if no editor.
- 4.61.0.138
- Added begin_at_sunday_plus to the CalendarButton docstring
- 4.61.0.139
- Moved debugger constants to inside of the debugger class. Simplified the locals and globals popups.
- 4.61.0.140
- Experimental change.... Table.get now returns the values from the widget's selection method
- 4.61.0.141
- Made the Debugger's use of popups change the theme to the same dark gray theme used in the rest of the debugger windows.
- 4.61.0.142
- Added selected_text_color & selected_background_color to Input element. Will override the default values
- 4.61.0.143
- Fixed bug in Combo.update - the width of the element wasn't getting updated to match new values
- 4.61.0.144
- Added selected_text_color & selected_background_color to Multiline element. Will override the default values
- 4.61.0.145
- Fixed bind_return_key docstrings in the pre-defined buttons. Made the Button bind_return_key docstring more descriptive
- 4.61.0.146
- Changed version numbers to 4.61.0 to try and fix the confusion about what's been released to PyPI.
- 4.61.0.147
- New Udemy coupon code
- 4.61.0.148
- Removed the print when the Mac Alpha Channel 0.99 patch is applied
- 4.61.0.149
- Removed second print when Mac patch applied
- 4.61.0.150
- Tree Element new parameter - click_toggles_select - if True then clicking a selected item will unselect it
- 4.61.0.151
- Fixed problem with TabGroups when the text was blank for a Tab. Was not correctly identifying the active tab in the Values dictionary
- 4.61.0.152
- Updated TabGroup.get to use the same method to find the currently active tab that was just added above.
- 4.61.0.153
- Updated layout error messages to include "sometimes" in the description of what may be causing error
- 4.61.0.154
- Updated Window.start_timer docstring to include the constants EVENT_TIMER and TIMER_KEY since the call reference doesn't show the variable names but rather the string value.
- 4.61.0.155
- Multiline new parameter autoscroll_only_at_bottom. When True, the element will autoscroll (keep scrollbar at the bottom) only if the scrollbar is already at the bottom.
- 4.61.0.156
- Added the new Multiline parameter autoscroll_only_at_bottom so that the Output element can also use this option
- 4.61.0.157
- Added the _optional_window_data function that is used to help with local PySimpleGUI testing of release candidates. Not meant to be used by end-users.
- 4.61.0.158
- Changed Checkbox activeforeground to be the same as the text so mouseover doesn't change color
- 4.61.0.159
- New Global Settings feature - Window watermarking. Can be forced on temporarily by settings watermark=True in your Window creation
- 4.61.0.160
- Fix "Bold" crash from watermarking feature
- 4.61.0.161
- New set_options to control user-defined watermarks
- 4.61.0.162
- Addition of new parms to Combo.update - text color, background color. Also font now applied correctly to dropdown list
- 4.61.0.163
- Checkbox - added highlight thickness parm to control how thick the focus ring is. Defaults to 1 still but now changable
- 4.61.0.164
- Input element - fixed problem where the input 'cursor' (the I-beam) was being set to the THEME'S color, not the color indicated by the individual element
- 4.61.0.165
- Multiline & Spin - Applied same fix for input "cursor" (I-Beam) color that was added to the Input element.
- Added new method - set_ibeam_color to Input, Multiline and Spin elements. Combo is a ttk element so it's not available using this call yet
- 4.61.0.166
- New Udemy coupon
- 4.61.0.167
- New Udemy coupon
- Fix for bad user settings key for user watermark. Added Python version to watermark
- 4.61.0.168
- Changed Radio activeforeground to be the same as the text so mouseover doesn't change color
- 4.61.0.169
- Allow no end-key to be specified for perform_long_operation/start_thread. Careful with backward compatibility! If you skip adding parm on old versions of PySimpleGUI then it'll not work.
- 4.61.0.170
- Possible fix for Mac Input Element issue that's been happening with no-titlebar windows on MacOS 13.2.1 Ventura
- 4.61.0.171
- Added formatted_datetime_now function for easy timestamps for logging
- 4.61.0.172
- Added upgrade service - No notification popups should be shown yet. Don't want to SPAM users while testing
- 4.61.0.173
- Made changing the "Show only critical" setting in global settings take effect immediately rather than waiting until closed settings window
- Added timer_stop_usec to return timer value in microseconds
- 4.61.0.174
- Overwrite upgrade data if any portion has changed
- 4.61.0.175
- Notification window - added countdown counter. Added hand cursor if message is a link and enable clicking of link to open the browser to that link
- 4.61.0.176
- Improved linux distro detection
- 4.61.0.177
- Custom Titlebar - Support for disabling resizing (maximizing too), support for disable minimize and disable close
- 4.61.0.178
- Input element - fix for bug with text color & logic wasn't quite right with the "read for disabled" stuff in the update as well as when making window
- 4.61.0.179
- New Udemy coupon
- 4.61.0.180
- Removed Security tab from system settings
- 4.61.0.181
- Added check for None and COLOR_SYSTEM_DEFAULT before any colors being set in Input.update
- 4.61.0.182
- Only enable the Mac alpha channel 0.99 patch when tkinter version is 8.6.12. Have learned this is not needed for any other tkinter version
- 4.61.0.183
- Show Critical upgrade service messages. Removed the extra upgrade from github button from tab.
- 4.61.0.184
- Fix for Combo.update background color changing incorrect widget setting.
- 4.61.0.185
- Fix for crash when no headings specified for a table by casting values into strings
- 4.61.0.186
- Fix for popup_get_file when using no_window=True. Now returns None if cancelled or window closed
- 4.61.0.187
- Corrected the Table.get docstring to reflect that it returns a list of ints
- 4.61.0.188
- Finished correcting the Table.get docstring.... think I got it right this time....
- 4.61.0.189
- Changed Table click events to be generated on Button Release instead of Button (down). Was not getting the
- correct selected rows in the values dictionary when the click event was generated using down. Now the selected rows is correct
- 4.61.0.190
- Addition of black2 theme
- Fix typo of text in _widget_was_created
- 4.61.0.191
- Fixed bug in Button.update. Was setting the activeforeground and activebackground which broke the mouseover or mouse press colors
- 4.61.0.192
- Fixed bug in Button.update. Corrected when activeforeground and activebackground are set. Removing them in version above was a mistake
- 4.61.0.193
- Fixed spelling errors... resuse should have been reuse
- 4.61.0.194
- Added Listbox.select_index and Listbox.set_index_color
- 4.61.0.195
- New Udemy Coupon
- 4.61.0.196
- Added highlight colors to the set_index_color method. Parms highlight_text_color & highlight_background_color control changing the highlight colors
- 4.61.0.197
- Made Table Element Header mouse-over and clicked be the inverse of the normal header colors. Makes for a much nicer experience
- 4.61.0.198
- Added no_buffering option to popup_animated
- 4.61.0.199
- Updated Udemy coupon code
- 4.61.0.200
- Fix for grab anywhere window movement and control+left_mouse_drag. Window move smoother, including the Move-All-Windows feature. Thank you JASON for the help!
- 4.61.0.201
- Added init for _mouse_offset_x and y in case tkinter doesn't call the mouse down callback
- 4.61.0.202
- Added doctring and destroy previous right click menu to set_right_click_menu
- 4.61.0.203
- Changed Sizer element to use Canvas instead of Column element
- 4.61.0.204
- One more change to sizer so that it uses pad instead of size.
- 4.61.0.205
- Fixed docstring for execute_command_subprocess. The command description was incorrect
- 4.61.0.206
- New Udemy Coupon code
-
+ Changelog since 4.60.0 released to PyPI on 8-May-2022. These are "Dot" releases....
+ 4.60.1
+ A "dot-release" / patch for crash that occurs if the horizontal_scroll parm is set in Listbox element
+ Was created when the ttk scrollbars were added
+ 4.60.2
+ A "dot-release" for Mac 12.3+ "Invisible window" problem. Adds option in Mac control panel to set Alpha to 0.99 as default
+ 4.60.3
+ Another shot at the 12.3+ Mac OS problem. Had bug in the version check code
+ 4.60.4
+ Dot release to quickly fix the Trinket detection which stopped working recently
+ 4.60.5
+ Fix for the Mac. If running MacOS Ventura 13.2.1 then windows with no titlebar had problems with Input elements. Added support for the Upgrade Service.
"""
__version__ = version.split()[0] # For PEP 396 and PEP 345
@@ -509,7 +39,7 @@ port = 'PySimpleGUI'
"""
- Copyright 2018, 2019, 2020, 2021, 2022, 2023 PySimpleGUI(tm)
+ Copyright 2018, 2019, 2020, 2021, 2022 PySimpleGUI(tm)
Before getting into the details, let's talk about the high level goals of the PySimpleGUI project.
@@ -558,26 +88,13 @@ port = 'PySimpleGUI'
In addition to the normal publishing requirements of LGPL3+, these also apply:
1. These and all comments are to remain in the source code
2. 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:
- https://www.PySimpleGUI.org - Main documentation
- There are also a lot of subdomains... many of which you can guess..
- https://SDK.PySimpleGUI.org - The SDK Reference tab
- https://Calls.PySimpleGUI.org - The SDK Reference tab
- https://Cookbook.PySimpleGUI.org - The Cookbook tab
- https://eCookbook.PySimpleGUI.org - The eCookbook located on Trinket
- https://Anncouncements.PySimpleGUI.org - The Announcements Issue on GitHub
- https://Install.PySimpleGUI.org - The "How to install" section of the docs
- https://Upgrading.PySimpleGUI.org - The "How to upgrade" section of the docs
- https://Udemy.PySimpleGUI.org - The Udemy course
- https://GitHub.PySimpleGUI.org - The PySimpleGUI GitHub (also the located at PySimpleGUI.com)
- https://Issues.PySimpleGUI.org - Open a new issue on GitHub
- https://Bugs.PySimpleGUI.org - Open a new issue on GitHub
- etc.....
-
+ 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.
3. If you use PySimpleGUI in your project/product, a notice of its use needs to be displayed in your readme file as per the license agreement
@@ -592,7 +109,7 @@ port = '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 use it in conjunction with the materials provided by the project.
+ The FASTEST WAY to learn PySimpleGUI is to begin to play with it, and to read the documentation.
http://www.PySimpleGUI.org
http://Calls.PySimpleGUI.org
http://Cookbook.PySimpleGUI.org
@@ -616,6 +133,7 @@ port = 'PySimpleGUI'
"Thank you" has fueled this project. I'm incredibly grateful to have users that are in turn grateful. It's a feedback loop of gratitude. What a fantastic thing!
"""
+
# all of the tkinter involved imports
import tkinter as tk
from tkinter import filedialog
@@ -629,15 +147,12 @@ from uuid import uuid4
# get the tkinter detailed version
tclversion_detailed = tkinter.Tcl().eval('info patchlevel')
framework_version = tclversion_detailed
-
import time
import pickle
import calendar
import datetime
import textwrap
-import socket
-from hashlib import sha256 as hh
import inspect
import traceback
import difflib
@@ -683,6 +198,7 @@ import re
import tempfile
import ctypes
import platform
+import socket
pil_import_attempted = pil_imported = False
@@ -709,9 +225,9 @@ def timer_start():
def timer_stop():
"""
- Time your code easily.... stop the timer and print the number of MILLISECONDS since the timer start
+ 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
+ :return: delta in milliseconds from timer_start was called
:rtype: int
"""
global g_time_delta, g_time_end
@@ -720,19 +236,6 @@ def timer_stop():
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):
"""
@@ -789,19 +292,6 @@ def _timeit_summary(func):
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
@@ -838,14 +328,14 @@ def running_windows():
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.
+ A special case for Trinket. Uses the hostname an platform together to determine if running on Trinket
Returns True if "Trinket" (in theory)
- :return: True if sys.platform indicates Linux and the number of environment variables is 1
+ :return: True if sys.platform indicates Linux and hostname starts with 'pygame-'
:rtype: (bool)
"""
if sys.platform.startswith('linux') and socket.gethostname().startswith('pygame-'):
@@ -853,6 +343,7 @@ def running_trinket():
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
@@ -940,10 +431,8 @@ 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
#################### COLOR STUFF ####################
BLUES = ("#082567", "#0A37A3", "#00345B")
PURPLES = ("#480656", "#4F2398", "#380474")
@@ -1091,15 +580,13 @@ 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_DO_NOT_USE_AN_ICON = '__TITLEBAR_NO_ICON__'
# Key indicating should not create any return values for element
@@ -1146,7 +633,6 @@ ALTERNATE_TABLE_AND_TREE_SELECTED_ROW_COLORS = ('SystemHighlightText', 'SystemHi
SYMBOL_SQUARE = '█'
SYMBOL_CIRCLE = '⚫'
SYMBOL_CIRCLE_OUTLINE = '◯'
-SYMBOL_BULLET = '•'
SYMBOL_UP = '▲'
SYMBOL_RIGHT = '►'
SYMBOL_LEFT = '◄'
@@ -1326,25 +812,6 @@ class TTKPartOverrides():
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_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', 'ibeam', 'icon', 'iron_cross', 'left_ptr', 'left_side', 'left_tee', 'leftbutton', 'll_angle', 'lr_angle', 'man', 'middlebutton', 'mouse', 'no', 'none', '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', 'size', 'size_ne_sw', 'size_ns', 'size_nw_se', 'size_we', 'sizing', 'spider', 'spraycan', 'star', 'starting', 'target', 'tcross', 'top_left_arrow', 'top_left_corner', 'top_right_corner', 'top_side', 'top_tee', 'trek', 'ul_angle', 'umbrella', 'uparrow', 'ur_angle', 'wait', 'watch', 'xterm']
# ------------------------- tkinter key codes for bindings ------------------------- #
# The keycode that when pressed will take a snapshot of the current window
@@ -1539,8 +1006,8 @@ class Element():
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.ttk_style_name = '' # set in the packer function
+
self._metadata = None # type: Any
self.ParentForm = None # type: Window
@@ -1563,12 +1030,6 @@ class Element():
# 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
- self.vsb = None # The vertical scrollbar if one is attached to element
## 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)
@@ -1798,11 +1259,48 @@ class Element():
"""
# 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)
+ if self.Key == TITLEBAR_MINIMIZE_KEY:
+ if running_linux():
+ self.ParentForm.TKroot.wm_attributes("-type", "normal")
+ # self.ParentForm.TKroot.state('icon')
+ # return
+ # self.ParentForm.maximize()
+ self.ParentForm.TKroot.wm_overrideredirect(False)
+ # self.ParentForm.minimize()
+ # self.ParentForm.TKroot.wm_overrideredirect(False)
+ self.ParentForm.TKroot.iconify()
+ # self._skip_first_restore_callback = True
+ self.ParentForm.TKroot.bind('', self._titlebar_restore)
+ else:
+ self.ParentForm.TKroot.wm_overrideredirect(False)
+ self.ParentForm.Minimize()
+ self.ParentForm.TKroot.bind('', self._titlebar_restore)
+ elif self.Key == TITLEBAR_MAXIMIZE_KEY:
+ if self.ParentForm.maximized:
+ self.ParentForm.normal()
+ else:
+ self.ParentForm.maximize()
+ elif self.Key == TITLEBAR_CLOSE_KEY:
+ self.ParentForm._OnClosingCallback()
+ else:
+ self._generic_callback_handler(self.DisplayText)
return
+ def _titlebar_restore(self, event):
+ if running_linux():
+ # if self._skip_first_restore_callback:
+ # self._skip_first_restore_callback = False
+ # return
+ self.ParentForm.TKroot.unbind('')
+ self.ParentForm.TKroot.deiconify()
+
+ # self.ParentForm.TKroot.wm_overrideredirect(True)
+ self.ParentForm.TKroot.wm_attributes("-type", 'dock')
+
+ else:
+ self.ParentForm.TKroot.unbind('')
+ self.ParentForm.TKroot.wm_overrideredirect(True)
+ self.ParentForm.normal()
def _ReturnKeyHandler(self, event):
"""
@@ -1819,9 +1317,6 @@ class Element():
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):
@@ -1920,12 +1415,6 @@ class Element():
"""
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
@@ -2198,13 +1687,8 @@ class Element():
: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)
+ self.Widget.yview_moveto(percent_from_top)
except Exception as e:
print('Warning setting the vertical scroll (yview_moveto failed)')
print(e)
@@ -2222,7 +1706,7 @@ class Element():
if SUPPRESS_WIDGET_NOT_FINALIZED_WARNINGS:
return False
- warnings.warn('You cannot Update element with key = {} until the window.read() is called or set finalize=True when creating window'.format(self.Key), UserWarning)
+ warnings.warn('You cannot Update element with key = {} until the window.read() is called or finalized=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:',
@@ -2278,12 +1762,6 @@ class Element():
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:
@@ -2291,12 +1769,6 @@ class Element():
if menu is None:
return
if menu:
- # If previously had a menu destroy it
- if self.TKRightClickMenu:
- try:
- self.TKRightClickMenu.destroy()
- 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):
@@ -2327,57 +1799,6 @@ class Element():
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):
"""
@@ -2461,7 +1882,7 @@ class Input(Element):
def __init__(self, default_text='', size=(None, None), s=(None, None), disabled=False, password_char='',
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,
+ use_readonly_for_disable=True, readonly=False, disabled_readonly_background_color=None, disabled_readonly_text_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
@@ -2510,10 +1931,6 @@ class Input(Element):
: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
@@ -2531,8 +1948,6 @@ class Input(Element):
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
@@ -2554,7 +1969,7 @@ class Input(Element):
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):
+ def update(self, value=None, disabled=None, select=None, visible=None, text_color=None, background_color=None, move_cursor_to='end', password_char=None, paste=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.
@@ -2575,55 +1990,25 @@ class Input(Element):
: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 disabled is True:
+ self.TKEntry['state'] = 'readonly' if self.UseReadonlyForDisable else 'disabled'
+ elif disabled is False:
+ self.TKEntry['state'] = 'readonly' if self.ReadOnly else 'normal'
+ self.Disabled = disabled if disabled is not None else self.Disabled
if background_color not in (None, COLOR_SYSTEM_DEFAULT):
self.TKEntry.configure(background=background_color)
- self.BackgroundColor = background_color
if text_color not in (None, COLOR_SYSTEM_DEFAULT):
self.TKEntry.configure(fg=text_color)
- self.TextColor = text_color
-
- if disabled is True:
- if self.UseReadonlyForDisable:
- if self.disabled_readonly_text_color not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKEntry.configure(fg=self.disabled_readonly_text_color)
- self.TKEntry['state'] = 'readonly'
- else:
- if self.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKEntry.configure(fg=self.TextColor)
- self.TKEntry['state'] = 'disabled'
- self.Disabled = True
- elif disabled is False:
- self.TKEntry['state'] = 'normal'
- if self.TextColor not in (None, COLOR_SYSTEM_DEFAULT):
- 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:
@@ -2655,32 +2040,6 @@ class Input(Element):
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):
"""
@@ -2713,7 +2072,7 @@ 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, change_submits=False, enable_events=False, enable_per_char_events=None, disabled=False, key=None, k=None, pad=None, p=None, expand_x=False, expand_y=False, tooltip=None, readonly=False, font=None, visible=True, metadata=None):
+ 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, change_submits=False, enable_events=False, disabled=False, 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]
@@ -2733,14 +2092,12 @@ class Combo(Element):
: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
+ :param bind_return_key: If True, then the return key will cause a the Combo to generate an event
:type bind_return_key: (bool)
: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 key: Used with window.find_element and with return values to uniquely identify this element
@@ -2790,12 +2147,12 @@ class Combo(Element):
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
+
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):
+ def update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None, visible=None, size=(None, 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
@@ -2808,30 +2165,23 @@ class Combo(Element):
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)
+ :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)
"""
-
if size != (None, None):
if isinstance(size, int):
size = (size, 1)
@@ -2840,12 +2190,6 @@ class Combo(Element):
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
@@ -2861,7 +2205,7 @@ class Combo(Element):
width = self.Size[0]
else:
width = max_line_len + 1
- self.TKCombo.configure(width=width)
+ # self.TKCombo.configure(width=width)
else:
self.TKCombo.configure(height=size[1])
self.TKCombo.configure(width=size[0])
@@ -2896,44 +2240,8 @@ class Combo(Element):
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()
@@ -2942,11 +2250,6 @@ class Combo(Element):
# 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):
"""
@@ -3066,11 +2369,6 @@ class OptionMenu(Element):
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')
@@ -3127,7 +2425,7 @@ class Listbox(Element):
"""
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,
+ bind_return_key=False, size=(None, None), s=(None, None), disabled=False, auto_size_text=None, font=None, no_scrollbar=False, horizontal_scroll=False,
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):
@@ -3142,7 +2440,7 @@ class Listbox(Element):
: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
+ :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event
: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
@@ -3150,8 +2448,6 @@ class Listbox(Element):
: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
@@ -3204,9 +2500,6 @@ class Listbox(Element):
: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
@@ -3239,7 +2532,6 @@ class Listbox(Element):
pad = pad if pad is not None else p
self.expand_x = expand_x
self.expand_y = expand_y
- self.justification = justification
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,
@@ -3271,10 +2563,6 @@ class Listbox(Element):
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:
@@ -3366,77 +2654,6 @@ class Listbox(Element):
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
@@ -3574,11 +2791,6 @@ class Radio(Element):
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:
@@ -3663,59 +2875,56 @@ class Checkbox(Element):
"""
def __init__(self, text, default=False, size=(None, None), s=(None, None), auto_size_text=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,
+ text_color=None, checkbox_color=None, 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 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)
+ :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 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 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
@@ -3723,7 +2932,6 @@ class Checkbox(Element):
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:
@@ -3789,11 +2997,6 @@ class Checkbox(Element):
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:
@@ -3862,7 +3065,7 @@ class Spin(Element):
"""
def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, readonly=False,
- 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,
+ 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,
tooltip=None, right_click_menu=None, expand_x=False, expand_y=False, visible=True, metadata=None):
"""
:param values: List of valid values
@@ -3875,7 +3078,7 @@ class Spin(Element):
: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.
+ :param readonly: Turns on the element specific events. Spin events happen when an item changes
:type readonly: (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
@@ -3883,7 +3086,7 @@ class Spin(Element):
: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
+ :param bind_return_key: If True, then the return key will cause a the element to generate an event
: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)
@@ -3899,8 +3102,6 @@ class Spin(Element):
: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.
@@ -3924,7 +3125,6 @@ class Spin(Element):
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
@@ -3967,10 +3167,6 @@ class Spin(Element):
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
@@ -4024,30 +3220,6 @@ class Spin(Element):
# 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.
@@ -4081,22 +3253,20 @@ class Multiline(Element):
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), 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,
+ def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None,
+ size=(None, None), s=(None, None), auto_size_text=None, background_color=None, text_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,
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
+ :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
@@ -4109,17 +3279,13 @@ class Multiline(Element):
: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.
+ :param enable_events: Turns on the element specific events. Spin events happen when an item changes
:type enable_events: (bool)
- :param do_not_clear: if False the element will be cleared any time the Window.read call returns
+ :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
@@ -4151,8 +3317,6 @@ class Multiline(Element):
: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
@@ -4188,9 +3352,6 @@ class Multiline(Element):
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
@@ -4204,6 +3365,8 @@ class Multiline(Element):
self.WriteOnly = write_only
self.AutoRefresh = auto_refresh
key = key if key is not None else k
+ self.previous_stdout = None
+ self.previous_stderr = None
self.reroute_cprint = reroute_cprint
self.echo_stdout_stderr = echo_stdout_stderr
self.Justification = 'left' if justification is None else justification
@@ -4212,12 +3375,12 @@ class Multiline(Element):
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
+ if reroute_stdout:
+ self.reroute_stdout_to_here()
+ if reroute_stderr:
+ self.reroute_stderr_to_here()
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
super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=sz, auto_size_text=auto_size_text, background_color=bg,
@@ -4228,7 +3391,7 @@ class Multiline(Element):
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):
"""
- Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
+ Changes some of the settings for the Multiline 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.
@@ -4265,14 +3428,8 @@ class Multiline(Element):
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'):
@@ -4319,11 +3476,8 @@ class Multiline(Element):
self.TKText.configure(state='disabled')
self.DefaultText = value
- # 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)
+ self.TKText.see(tk.END)
if disabled is True:
self.TKText.configure(state='disabled')
elif disabled is False:
@@ -4434,32 +3588,31 @@ class Multiline(Element):
"""
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))
+ self.previous_stdout = sys.stdout
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))
+ self.previous_stderr = sys.stderr
sys.stderr = self
def restore_stdout(self):
"""
Restore a previously re-reouted stdout back to the original destination
"""
- Window._restore_stdout()
+ if self.previous_stdout:
+ sys.stdout = self.previous_stdout
+ self.previous_stdout = None # indicate no longer routed here
def restore_stderr(self):
"""
Restore a previously re-reouted stderr back to the original destination
"""
- Window._restore_stderr()
+ if self.previous_stderr:
+ sys.stderr = self.previous_stderr
+ self.previous_stderr = None # indicate no longer routed here
def write(self, txt):
"""
@@ -4470,12 +3623,8 @@ class Multiline(Element):
"""
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)
+ self.previous_stdout.write(txt)
except:
pass
@@ -4484,47 +3633,25 @@ class Multiline(Element):
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)
-
-
+ try:
+ self.previous_stdout.flush()
+ except:
+ pass
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.
-
+ If this Widget is deleted, be sure and restore the old stdout, stderr
"""
-
- return
-
+ # These trys are here because found that if the init fails, then
+ # the variables holding the old stdout won't exist and will get an error
+ try:
+ self.restore_stdout()
+ except Exception as e:
+ pass
+ try:
+ self.restore_stderr()
+ except:
+ pass
Get = get
Update = update
@@ -4558,8 +3685,8 @@ class Text(Element):
: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 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/enum)
: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
@@ -4627,7 +3754,7 @@ class Text(Element):
when made visible.
:param value: new text to show
- :type value: (Any)
+ :type value: (str)
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -4640,11 +3767,6 @@ class Text(Element):
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))
@@ -4986,10 +4108,6 @@ class StatusBar(Element):
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
@@ -5107,6 +4225,110 @@ class TKProgressBar():
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, echo_stdout_stderr=False, font=None, pad=None):
+# """
+# :param parent: The "Root" that the Widget will be in
+# :type parent: tk.Tk | tk.Toplevel
+# :param width: Width in characters
+# :type width: (int)
+# :param height: height in rows
+# :type height: (int)
+# :param bd: Border Depth. How many pixels of border to show
+# :type bd: (int)
+# :param background_color: color of background
+# :type background_color: (str)
+# :param text_color: color of the text
+# :type text_color: (str)
+# :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 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
+# """
+# 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.output.configure(insertbackground=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
+# self.parent = parent
+# self.echo_stdout_stderr = echo_stdout_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
+# Refreshes the window after the write so that the change is immediately displayed
+#
+# :param txt: text of output
+# :type txt: (str)
+# """
+# try:
+# self.output.insert(tk.END, str(txt))
+# self.output.see(tk.END)
+# self.parent.update()
+# except:
+# pass
+#
+# try:
+# if self.echo_stdout_stderr:
+# self.previous_stdout.write(txt)
+# 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):
+# """
+# 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:
+# if self.echo_stdout_stderr:
+# self.previous_stdout.flush()
+# except:
+# pass
+#
+# 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 #
@@ -5114,23 +4336,23 @@ class TKProgressBar():
# ---------------------------------------------------------------------- #
class Output(Multiline):
"""
- Output Element - a multi-lined text area to where stdout, stderr, cprint are rerouted.
+ ** NOTE - It's recommended to use Multiline Element instead **
- 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
+ Output Element - a multi-lined text area where stdout and stderr are re-routed to.
- 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
+ The Multiline Element is the superior and recommended method for showing the output of stdout.
+ The Multiline Element has been added to significantly while the Output element has not.
+ If you choose to use a Multiline element to replace an Output element, be sure an turn on the write_only paramter in the Multline
+
+ Of course, Output Element continues to operate and be backwards compatible, but you're missing out on
+ features such as routing the cprint output to the element.
+
+ In Apr 2022, the Output Element was switched to be a subclass of the Multiline so that more code will be in common. Nowever
+ you will not get all of the parms unless you switch to the Multline Specifically
"""
- 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,
+ def __init__(self, size=(None, None), s=(None, None), background_color=None, text_color=None, pad=None, p=None, 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,
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
@@ -5145,8 +4367,6 @@ class Output(Multiline):
: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
@@ -5167,10 +4387,6 @@ class Output(Multiline):
: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
@@ -5188,8 +4404,104 @@ class Output(Multiline):
"""
- 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)
+ # 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
+ # key = key if key is not None else k
+ # self.echo_stdout_stderr = echo_stdout_stderr
+ # 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__(size=size, s=s, background_color=background_color, text_color=text_color, pad=pad, p=p, echo_stdout_stderr=echo_stdout_stderr, font=font, tooltip=tooltip,
+ key=key, k=k, right_click_menu=right_click_menu, write_only=True, reroute_stdout=True, reroute_stderr=True, autoscroll=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)
+ #
+ # @property
+ # def tk_out(self):
+ # """
+ # Returns the TKOutput object used to create the element
+ #
+ # :return: The TKOutput object
+ # :rtype: (TKOutput)
+ # """
+ # 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
+ #
+ # 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: string that will replace current contents of the output area
+ # :type value: (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 value is not None:
+ # self._TKOut.output.delete('1.0', tk.END)
+ # self._TKOut.output.insert(tk.END, value)
+ # if visible is False:
+ # self._pack_forget_save_settings(self._TKOut.frame)
+ # elif visible is True:
+ # self._pack_restore_settings(self._TKOut.frame)
+ #
+ # if visible is not None:
+ # self._visible = visible
+ #
+ # def get(self):
+ # """
+ # Returns the current contents of the output. Similar to Get method other Elements
+ # :return: the current value of the output
+ # :rtype: (str)
+ # """
+ # return self._TKOut.output.get(1.0, tk.END)
+ #
+ # 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)
+ # """
+ #
+ # 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=expand_row, fill=fill)
+ #
+ # def __del__(self):
+ # """
+ # Delete this element. Normally Elements do not have their delete method specified, but for this one
+ # it's important that the underlying TKOut object get deleted so that the stdout will get restored properly
+ # """
+ # self._TKOut.__del__()
+
+ # TKOut = tk_out
+ # Update = update
+ # Get = get
# ---------------------------------------------------------------------- #
@@ -5203,7 +4515,7 @@ class Button(Element):
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,
+ image_subsample=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):
@@ -5216,7 +4528,7 @@ class Button(Element):
: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", "*.* *"),).
+ :param file_types: the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.* *"),). NOT avoilable on the MAC
:type file_types: Tuple[(str, str), ...]
:param initial_folder: starting path for folders and files
:type initial_folder: (str)
@@ -5238,8 +4550,6 @@ class Button(Element):
: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
@@ -5249,7 +4559,7 @@ class Button(Element):
: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
+ :type button_color: (str, str) | str | (int, int) | None
: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
@@ -5260,7 +4570,7 @@ class Button(Element):
: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
+ :param bind_return_key: If True the return key will cause this button to be pressed
:type bind_return_key: (bool)
:param focus: if True, initial focus will be put on this button
:type focus: (bool)
@@ -5327,7 +4637,6 @@ class Button(Element):
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
@@ -5344,12 +4653,12 @@ class Button(Element):
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.ttk_style_name = '' # set in the packer function
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
@@ -5357,13 +4666,6 @@ class Button(Element):
# 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:
@@ -5436,7 +4738,6 @@ class Button(Element):
def _find_target(self):
target = self.Target
target_element = None
-
if target[0] == ThisRow:
target = [self.Position[0], target[1]]
if target[1] < 0:
@@ -5446,20 +4747,12 @@ class Button(Element):
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)
+ 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:
@@ -5498,16 +4791,7 @@ class Button(Element):
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
+ 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
@@ -5517,23 +4801,13 @@ class Button(Element):
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 = tk.colorchooser.askcolor(parent=self.ParentForm.TKroot) # 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)
+ 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)
- # elif _mac_allow_filetypes():
- # file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder)
- # else:
- # file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder)
+ file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder)
else:
file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot)
@@ -5546,16 +4820,7 @@ class Button(Element):
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)
- # elif _mac_allow_filetypes():
- # file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, defaultextension=self.DefaultExtension, initialdir=self.InitialFolder)
- # else:
- # file_name = tk.filedialog.asksaveasfilename(defaultextension=self.DefaultExtension, initialdir=self.InitialFolder)
+ 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, parent=self.ParentForm.TKroot)
@@ -5610,8 +4875,8 @@ class Button(Element):
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):
+ def update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None,
+ visible=None, image_subsample=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
@@ -5624,11 +4889,9 @@ class Button(Element):
: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
+ :type button_color: (str, str) | str | (int, int) | None
: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.
@@ -5639,8 +4902,6 @@ class Button(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)
"""
@@ -5648,33 +4909,12 @@ class Button(Element):
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.TKButton.configure(text=text)
self.ButtonText = text
if button_color != (None, None) and button_color != COLOR_SYSTEM_DEFAULT:
bc = button_color_to_tuple(button_color, self.ButtonColor)
@@ -5690,9 +4930,9 @@ class Button(Element):
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])
+ self.TKButton.config(foreground=bc[0], activeforeground=bc[0])
if bc[1] not in (None, COLOR_SYSTEM_DEFAULT):
- self.TKButton.config(background=bc[1], activeforeground=bc[1])
+ self.TKButton.config(background=bc[1], activebackground=bc[1])
self.ButtonColor = bc
if disabled is True:
self.TKButton['state'] = 'disabled'
@@ -5706,8 +4946,6 @@ class Button(Element):
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:
@@ -5721,8 +4959,6 @@ class Button(Element):
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:
@@ -5788,72 +5024,68 @@ class ButtonMenu(Element):
"""
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,
+ image_filename=None, image_data=None, image_size=(None, None), image_subsample=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):
+ 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)
+ :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 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) or 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
@@ -5878,7 +5110,6 @@ class ButtonMenu(Element):
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
@@ -5914,7 +5145,7 @@ class ButtonMenu(Element):
_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):
+ def update(self, menu_definition=None, visible=None, image_source=None, image_size=(None, None), image_subsample=None, button_text=None):
"""
Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior
@@ -5934,22 +5165,13 @@ class ButtonMenu(Element):
: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)
@@ -5978,16 +5200,12 @@ class ButtonMenu(Element):
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
@@ -6008,13 +5226,6 @@ class ButtonMenu(Element):
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):
"""
@@ -6056,7 +5267,7 @@ class ProgressBar(Element):
: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.
+ :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 style: Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'
:type style: (str)
@@ -6091,6 +5302,7 @@ class ProgressBar(Element):
self.NotRunning = True
self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION
self.RightClickMenu = right_click_menu
+ self.ttk_style_name = None # set in the pack function so can use in the update
# 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
@@ -6160,11 +5372,6 @@ class ProgressBar(Element):
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
@@ -6208,7 +5415,7 @@ 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):
+ 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, 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
@@ -6234,8 +5441,6 @@ class Image(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
@@ -6271,7 +5476,6 @@ class Image(Element):
self.TotalAnimatedFrames = 0
self.LastFrameTime = 0
self.ImageSubsample = subsample
- self.zoom = int(zoom) if zoom is not None else None
self.Source = filename if filename is not None else data
key = key if key is not None else k
@@ -6280,12 +5484,11 @@ class Image(Element):
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):
+ def update(self, source=None, filename=None, data=None, size=(None, None), subsample=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
@@ -6305,10 +5508,8 @@ class Image(Element):
: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 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 visible: control visibility of element
:type visible: (bool)
"""
@@ -6316,11 +5517,6 @@ class Image(Element):
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
@@ -6335,8 +5531,6 @@ class Image(Element):
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)
@@ -6346,16 +5540,11 @@ class Image(Element):
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:
@@ -6374,7 +5563,7 @@ class Image(Element):
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.configure(width=1, height=1, bd=0)
self.tktext_label.image = None
except:
pass
@@ -6555,10 +5744,6 @@ class Canvas(Element):
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:
@@ -7079,10 +6264,6 @@ class Graph(Element):
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)
@@ -7233,22 +6414,25 @@ class Graph(Element):
: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
+ 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.ParentForm.LastButtonClickedWasRealtime = False
+ 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()
_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')
+ if self.DragSubmits:
+ if isinstance(self.ParentForm.LastButtonClicked, str):
+ self.ParentForm.LastButtonClicked = self.ParentForm.LastButtonClicked + '+UP'
+ else:
+ self.ParentForm.LastButtonClicked = (self.ParentForm.LastButtonClicked, '+UP')
+ # self.ParentForm.LastButtonClicked += '+UP' # this is the old method that required string key
self.MouseButtonDown = False
-
# button callback
def button_press_call_back(self, event):
"""
@@ -7452,7 +6636,7 @@ class Frame(Element):
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 ]',
+ 'This means you have a badly placed ]',
'The offensive list is:',
element,
'This list will be stripped from your layout',
@@ -7470,7 +6654,7 @@ class Frame(Element):
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. ***',
+ '*** YOU ARE ATTEMPTING TO RESUSE 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',
@@ -7547,10 +6731,6 @@ class Frame(Element):
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()
@@ -7688,7 +6868,7 @@ class Tab(Element):
"""
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):
+ 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, metadata=None):
"""
:param title: text to show on the tab
:type title: (str)
@@ -7728,8 +6908,6 @@ class Tab(Element):
: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)
"""
@@ -7746,7 +6924,6 @@ class Tab(Element):
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 = []
@@ -7791,7 +6968,7 @@ class Tab(Element):
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 ]',
+ 'This means you have a badly placed ]',
'The offensive list is:',
element,
'This list will be stripped from your layout')
@@ -7806,7 +6983,7 @@ class Tab(Element):
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. ***',
+ '*** YOU ARE ATTEMPTING TO RESUSE 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',
@@ -7869,11 +7046,6 @@ class Tab(Element):
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
@@ -7989,7 +7161,7 @@ class TabGroup(Element):
: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
+ :param visible: set visibility state of the element
:type visible: (bool)
:param metadata: User metadata that can be set to ANYTHING
:type metadata: (Any)
@@ -8010,7 +7182,6 @@ class TabGroup(Element):
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
@@ -8049,7 +7220,7 @@ class TabGroup(Element):
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 ]',
+ 'This 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()
@@ -8065,7 +7236,7 @@ class TabGroup(Element):
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. ***',
+ '*** YOU ARE ATTEMPTING TO RESUSE 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',
@@ -8137,39 +7308,25 @@ class TabGroup(Element):
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
+ 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
+ :return: The key of the currently selected tab or the tab's text if it has no key
:rtype: Any | None
"""
try:
- current_index = self.TKNotebook.index('current')
- key = self.tab_index_to_key.get(current_index, None)
+ value = self.TKNotebook.tab(self.TKNotebook.index('current'))['text']
+ tab_key = self.FindKeyFromTabName(value)
+ if tab_key is not None:
+ value = tab_key
except:
- key = None
-
- return key
+ value = None
+ return value
def add_tab(self, tab_element):
"""
@@ -8241,32 +7398,6 @@ class TabGroup(Element):
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
@@ -8387,11 +7518,6 @@ class Slider(Element):
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:
@@ -8618,9 +7744,9 @@ class Column(Element):
: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
+ :param scrollable: if True then scrollbars will be added to the column
:type scrollable: (bool)
- :param vertical_scroll_only: if True then no horizontal scrollbar will be shown if a scrollable column
+ :param vertical_scroll_only: if Truen then no horizontal scrollbar will be shown
: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 ]]
@@ -8710,7 +7836,7 @@ class Column(Element):
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 ]',
+ 'This 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()
@@ -8726,7 +7852,7 @@ class Column(Element):
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. ***',
+ '*** YOU ARE ATTEMPTING TO RESUSE 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',
@@ -8800,10 +7926,6 @@ class Column(Element):
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:
@@ -8934,11 +8056,6 @@ class Pane(Element):
"""
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:
@@ -9189,8 +8306,6 @@ class Menu(Element):
['&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.
@@ -9199,36 +8314,35 @@ class Menu(Element):
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)
+ :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
+ :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 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. 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()
@@ -9281,18 +8395,11 @@ class Menu(Element):
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
+
+ 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)
@@ -9340,8 +8447,8 @@ Menubar = Menu # another name for Menu to make it clear it's the Menu Bar
# ---------------------------------------------------------------------- #
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,
+ 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, selected_row_colors=(None, None), header_text_color=None, header_background_color=None, header_font=None, header_border_width=None, header_relief=None,
row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, border_width=None,
@@ -9357,8 +8464,6 @@ class Table(Element):
: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
@@ -9369,8 +8474,6 @@ class Table(Element):
:type select_mode: (enum)
: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
@@ -9458,7 +8561,6 @@ class Table(Element):
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
@@ -9480,7 +8582,7 @@ class Table(Element):
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.StartingRowNumber = 0 # When displaying row numbers, where to start
self.RowHeaderText = 'Row'
self.enable_click_events = enable_click_events
self.right_click_selects = right_click_selects
@@ -9488,7 +8590,6 @@ class Table(Element):
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
if selected_row_colors == (None, None):
# selected_row_colors = DEFAULT_TABLE_AND_TREE_SELECTED_ROW_COLORS
selected_row_colors = theme_button_color()
@@ -9540,10 +8641,6 @@ class Table(Element):
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=())
@@ -9688,7 +8785,7 @@ class Table(Element):
self.TKTreeview.selection_set(selections)
# print(selections)
self.SelectedRows = [int(x) - 1 for x in selections]
- # print('The new selected rows = ', self.SelectedRows, 'selections =', 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))
@@ -9701,15 +8798,15 @@ class Table(Element):
def get(self):
"""
- Get the selected rows using tktiner's selection method. Returns a list of the selected rows.
+ 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: a list of the index of the selected rows (a list of ints)
- :rtype: List[int]
+ :return: the current table values (for now what was originally provided up updated)
+ :rtype: List[List[Any]]
"""
+ return self.Values
- selections = self.TKTreeview.selection()
- selected_rows = [int(x) - 1 for x in selections]
- return selected_rows
def get_last_clicked_position(self):
"""
@@ -9738,7 +8835,7 @@ class Tree(Element):
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,
+ change_submits=False, enable_events=False, 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,
@@ -9770,8 +8867,6 @@ class Tree(Element):
: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
@@ -9854,7 +8949,7 @@ class Tree(Element):
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()
@@ -9905,14 +9000,8 @@ class Tree(Element):
"""
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 = [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:
@@ -9924,7 +9013,6 @@ class Tree(Element):
# 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.
@@ -9986,10 +9074,6 @@ class Tree(Element):
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:
@@ -10194,7 +9278,7 @@ class ErrorElement(Element):
# 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):
+def Stretch(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.
@@ -10205,10 +9289,10 @@ def Push(background_color=None):
"""
return Text(font='_ 1', background_color=background_color, pad=(0,0), expand_x=True)
-P = Push
-Stretch = Push
+Push = Stretch
+P = Stretch
-def VPush(background_color=None):
+def VStretch(background_color=None):
"""
Acts like a Stretch element found in the Qt port.
Used in a Vertical fashion.
@@ -10219,119 +9303,8 @@ def VPush(background_color=None):
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
-
-
-
+VPush = VStretch
+VP = VStretch
# ------------------------------------------------------------------------- #
@@ -10358,14 +9331,6 @@ class Window:
_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
- _watermark = None
- _watermark_temp_forced = False
- _watermark_user_text = ''
def __init__(self, title, layout=None, default_element_size=None,
default_button_element_size=(None, None),
@@ -10376,12 +9341,13 @@ class Window:
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=True,
- 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_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,
+ finalize=False, element_justification='left', ttk_theme=None, use_ttk_buttons=None, modal=False, enable_close_attempted_event=False,
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,
+ 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,
metadata=None):
"""
:param title: The title that will be displayed in the Titlebar and on the Taskbar
@@ -10398,8 +9364,8 @@ class Window:
:type auto_size_buttons: (bool)
: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 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 location: (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen.
+ :type location: (int, int)
: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)
@@ -10407,7 +9373,7 @@ class Window:
: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
+ :type button_color: (str, str) or 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
@@ -10476,8 +9442,6 @@ class Window:
: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 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
@@ -10504,8 +9468,6 @@ class Window:
: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 metadata: User metadata that can be set to ANYTHING
:type metadata: (Any)
"""
@@ -10519,10 +9481,7 @@ class Window:
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.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
@@ -10624,7 +9583,6 @@ class Window:
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
@@ -10643,15 +9601,6 @@ class Window:
if self.use_custom_titlebar:
self.Margins = (0, 0)
self.NoTitleBar = True
- self._mouse_offset_x = self._mouse_offset_y = 0
-
- if watermark is True:
- Window._watermark_temp_forced = True
- _global_settings_get_watermark_info()
- elif watermark is False:
- Window._watermark = None
- Window._watermark_temp_forced = 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)
@@ -10752,7 +9701,7 @@ class Window:
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 ]',
+ 'This means you have a badly placed ]',
'The offensive list is:',
element,
'This list will be stripped from your layout'
@@ -10768,12 +9717,12 @@ class Window:
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. ***',
+ '*** YOU ARE ATTEMPTING TO RESUSE 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',
+ _error_popup_with_traceback('Error creating Window layout',
+ 'You have broken the layout reuse rule! Thou shall not reuse layouts.',
+ '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,
@@ -10812,12 +9761,6 @@ class Window:
'This item will be stripped from your layout')
continue
self.add_row(*row)
- # if _optional_window_data(self) is not None:
- # self.add_row(_optional_window_data(self))
- if Window._watermark is not None:
- self.add_row(Window._watermark(self))
-
-
def layout(self, rows):
"""
@@ -10868,7 +9811,7 @@ class Window:
:return: (Window) self so could be chained
:rtype: (Window)
"""
- column = Column(rows, pad=(0, 0), background_color=container.BackgroundColor)
+ column = Column(rows, pad=(0, 0))
if self == container:
frame = self.TKroot
elif isinstance(container.Widget, TkScrollableFrame):
@@ -11259,11 +10202,8 @@ class Window:
# 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)
+ Window._root_running_mainloop.mainloop()
+
# print('Out main')
self.CurrentlyRunningMainloop = False
# if self.LastButtonClicked != TIMEOUT_KEY:
@@ -11308,7 +10248,7 @@ class Window:
def _ReadNonBlocking(self):
"""
- Should be NEVER called directly by the user. The user can call Window.read(timeout=0) to get same effect
+ 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]
@@ -11444,7 +10384,7 @@ class Window:
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):
+ def find_element(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
@@ -11457,7 +10397,7 @@ class Window:
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!):
+ find_element is yypically 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"
@@ -11470,40 +10410,34 @@ class Window:
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
+ :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
"""
-
- 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]
+ key_error = False
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)
+ _error_popup_with_traceback('Key Error', 'Problem finding your key ' + str(key), 'Closest match = ' + str(closest_key))
+ if not SUPPRESS_RAISE_KEY_ERRORS:
+ raise KeyError(key)
element = ErrorElement(key=key)
+ key_error = True
else:
- element = None
- if not supress_raise:
- raise KeyError(key)
-
+ element = ErrorElement(key=key)
+ return element
if key_error:
- if not supress_guessing and closest_key is not None:
+ if closest_key is not None and not SUPPRESS_KEY_GUESSING:
element = self.AllKeysDict[closest_key]
-
+ return element
+ if not SUPPRESS_RAISE_KEY_ERRORS:
+ raise KeyError(key)
return element
Element = find_element # Shortcut function
@@ -11724,13 +10658,9 @@ class Window:
"""
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.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
@@ -11754,17 +10684,14 @@ class Window:
"""
if not self._is_window_created('tried Window.normal'):
return
- if self.use_custom_titlebar:
- self._custom_titlebar_restore()
+ if self.TKroot.state() == 'iconic':
+ self.TKroot.deiconify()
else:
- if self.TKroot.state() == 'iconic':
- self.TKroot.deiconify()
+ if not running_linux():
+ self.TKroot.state('normal')
else:
- if not running_linux():
- self.TKroot.state('normal')
- else:
- self.TKroot.attributes('-fullscreen', False)
- self.maximized = False
+ self.TKroot.attributes('-fullscreen', False)
+ self.maximized = False
def _StartMoveUsingControlKey(self, event):
@@ -11773,8 +10700,8 @@ class Window:
:param event: event information passed in by tkinter. Contains x,y position of mouse
:type event: (event)
"""
- self._start_move_save_offset(event)
- return
+
+ self._StartMove(event)
def _StartMoveGrabAnywhere(self, event):
@@ -11788,11 +10715,31 @@ class Window:
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)
+
+ self._StartMove(event)
+
def _StartMove(self, event):
- self._start_move_save_offset(event)
- return
+ try:
+ geometry = self.TKroot.geometry()
+ location = geometry[geometry.find('+')+1:].split('+')
+ self._startx = int(location[0])
+ self._starty = int(location[1])
+ self._mousex = event.x + event.widget.winfo_rootx()
+ self._mousey = event.y + event.widget.winfo_rooty()
+ # print(self._startx, self._starty)
+ # print(self._mousex, self._mousey)
+ # print(self.TKroot.geometry())
+ except:
+ pass
+ # print('Start move {},{} widget {}'.format(event.x,event.y, event.widget))
+
+ if Window._move_all_windows:
+ for window in Window._active_windows:
+ window._offsetx = event.x + event.widget.winfo_rootx() - window.TKroot.winfo_rootx()
+ window._offsety = event.y + event.widget.winfo_rooty() - window.TKroot.winfo_rooty()
+
+
def _StopMove(self, event):
"""
@@ -11803,28 +10750,6 @@ class Window:
"""
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)
@@ -11845,16 +10770,22 @@ class Window:
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:
+
+ _mousex = event.x + event.widget.winfo_rootx()
+ _mousey = event.y + event.widget.winfo_rooty()
+ deltax = _mousex - self._mousex
+ deltay = _mousey - self._mousey
+ x = self._startx + deltax
+ y = self._starty + deltay
+ self.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window
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}")
+ for window in Window._active_windows:
+ deltax = window._offsetx
+ deltay = window._offsety
+ x = window.TKroot.winfo_pointerx() - deltax
+ y = window.TKroot.winfo_pointery() - deltay
+ window.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window
except Exception as e:
print('on motion error', e)
@@ -11862,37 +10793,23 @@ class Window:
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
- """
- 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)
+ print('Config event = {} window = {}'.format(event, self.Title))
+ #
+ # 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))
+ #
+ # if Window._move_all_windows:
+ # for window in Window._active_windows:
+ # 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
+ # except Exception as e:
+ # print('on motion error {}'.format(e), 'title = {}'.format(window.Title))
"""
def _config_callback(self, event):
@@ -11981,7 +10898,6 @@ class Window:
: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:
@@ -12000,7 +10916,6 @@ class Window:
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.
"""
-
try:
del Window._active_windows[self] # will only be in the list if window was explicitly finalized
except:
@@ -12010,12 +10925,6 @@ class Window:
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:
@@ -12037,26 +10946,16 @@ class Window:
self.Rows = None
self.TKroot = None
-
-
-
- def is_closed(self, quick_check=None):
+ def is_closed(self):
"""
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)
+
+ :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()
@@ -12092,8 +10991,6 @@ class Window:
self.LastButtonClicked = WINDOW_CLOSE_ATTEMPTED_EVENT
if self.close_destroys_window:
self.RootNeedsDestroying = True
- self._restore_stdout()
- self._restore_stderr()
def disable(self):
"""
@@ -12132,14 +11029,6 @@ class Window:
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
@@ -12256,31 +11145,24 @@ class Window:
- def current_location(self, more_accurate=False, without_titlebar=False):
+ def current_location(self, more_accurate=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)]
+ :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)
+ :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:
+ if more_accurate:
geometry = self.TKroot.geometry()
location = geometry[geometry.find('+') + 1:].split('+')
x, y = int(location[0]), int(location[1])
@@ -12291,7 +11173,6 @@ class Window:
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
@@ -12340,25 +11221,6 @@ class Window:
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.
@@ -12371,25 +11233,6 @@ class Window:
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
@@ -12493,22 +11336,6 @@ class Window:
# _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
@@ -12564,12 +11391,6 @@ class Window:
"""
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):
@@ -12822,7 +11643,7 @@ class Window:
return grab
- def perform_long_operation(self, func, end_key=None):
+ def perform_long_operation(self, func, end_key):
"""
Call your function that will take a long time to execute. When it's complete, send an event
specified by the end_key.
@@ -12839,8 +11660,8 @@ class Window:
: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)
+ :param end_key: The key that will be generated when the function returns
+ :type end_key: (Any)
:return: The id of the thread
:rtype: threading.Thread
"""
@@ -12859,182 +11680,6 @@ class Window:
"""
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 __enter__(self):
# """
# WAS used with context managers which are no longer needed nor advised. It is here for legacy support and
@@ -13048,11 +11693,10 @@ class Window:
"""
Returns Element that matches the passed in key.
This is "called" by writing code as thus:
- window['element key'].update
+ 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
"""
@@ -13064,7 +11708,7 @@ class Window:
window() == window.read()
window(timeout=50) == window.read(timeout=50)
- :return: The famous event, values that read returns.
+ :return: The famous event, values that Read returns.
:rtype: Tuple[Any, Dict[Any, Any]]
"""
return self.read(*args, **kwargs)
@@ -13160,15 +11804,14 @@ def _long_func_thread(window, end_key, original_func):
: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 end_key: The event that will be sent when function returns
+ :type end_key: (Any)
: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)
+ window.write_event_value(end_key, return_value)
def _exit_mainloop(exiting_window):
@@ -13458,14 +12101,14 @@ class SystemTray:
"""
if isinstance(time, tuple):
- fade_duration, display_duration = time
+ fade_duraction, 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)
+ event = self.notify(title, message, icon=user_icon, fade_in_duration=fade_duraction, display_duration_in_ms=display_duration)
self.last_message_event = event
return event
@@ -13614,22 +12257,18 @@ def Sizer(h_pixels=0, v_pixels=0):
: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: (Column) A column element that has a pad setting set according to parameters
+ :rtype: (Column)
"""
- return Canvas(size=(0, 0), pad=((h_pixels, 0), (v_pixels, 0)))
+ return Column([[]], 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'
@@ -13650,72 +12289,64 @@ def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None
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):
+def vtop(elem_or_row, expand_x=None, expand_y=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]
+ :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)
+ :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([[e]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y) 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)
+ return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y)
-def vcenter(elem_or_row, expand_x=None, expand_y=None, background_color=None):
+def vcenter(elem_or_row, expand_x=None, expand_y=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]
+ :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)
+ :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([[e]], pad=(0, 0), vertical_alignment='center') 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)
+ return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='center')
-def vbottom(elem_or_row, expand_x=None, expand_y=None, background_color=None):
+def vbottom(elem_or_row, expand_x=None, expand_y=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]
+ :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)
+ :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([[e]], pad=(0, 0), vertical_alignment='bottom') 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)
+ return Column([[elem_or_row]], pad=(0, 0), vertical_alignment='bottom')
def Titlebar(title='', icon=None, text_color=None, background_color=None, font=None, key=None, k=None):
@@ -13772,7 +12403,7 @@ def Titlebar(title='', icon=None, text_color=None, background_color=None, font=N
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)]
+ icon_and_text_portion += [T(title, text_color=tc, background_color=bc, font=font, grab=True)]
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),
@@ -13848,7 +12479,7 @@ def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font
# ------------------------- 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):
+ font=None, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Browse')
:type button_text: (str)
@@ -13865,7 +12496,7 @@ def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None
: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
+ :type button_color:
:param disabled: set disable state for element (Default = False)
:type disabled: (bool)
:param change_submits: If True, pressing Enter key submits window (Default = False)
@@ -13886,10 +12517,6 @@ def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None
: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)
"""
@@ -13897,21 +12524,21 @@ def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None
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)
+ enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
: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", "*.* *"),).
+ :param file_types: filter file types Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC
:type file_types: Tuple[(str, str), ...]
:param initial_folder: starting path for folders and files
:type initial_folder:
@@ -13924,7 +12551,7 @@ def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES
: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
+ :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)
@@ -13945,24 +12572,20 @@ def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPES
: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)
+ button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ font=None, pad=None, p=None, key=None, k=None, visible=True, files_delimiter=BROWSE_FILES_DELIMITER, metadata=None):
"""
Allows browsing of multiple files. File list is returned as a single list with the delimiter defined using the files_delimiter parameter.
@@ -13970,7 +12593,7 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPE
: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", "*.* *"),).
+ :param file_types: Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC
:type file_types: Tuple[(str, str), ...]
:param disabled: set disable state for element (Default = False)
:type disabled: (bool)
@@ -13985,7 +12608,7 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPE
: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
+ :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)
@@ -14006,17 +12629,13 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPE
: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)
+ disabled=disabled, button_color=button_color, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
button._files_delimiter = files_delimiter
return button
@@ -14025,14 +12644,14 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=FILE_TYPE
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):
+ pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
: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", "*.* *"),).
+ :param file_types: Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC
: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)
@@ -14049,7 +12668,7 @@ def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_T
: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
+ :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)
@@ -14068,30 +12687,27 @@ def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_T
: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
+ :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)
+ enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
: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", "*.* *"),).
+ :param file_types: Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC
: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)
@@ -14126,22 +12742,18 @@ def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=FILE_TYPES
: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)
+ enable_events=enable_events, font=font, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ disabled=False, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Save')
@@ -14153,8 +12765,8 @@ def Save(button_text='Save', size=(None, None), s=(None, None), auto_size_button
: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 button_color: (str, str) or str
+ :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param disabled: set disable state for element (Default = False)
:type disabled: (bool)
@@ -14176,21 +12788,17 @@ def Save(button_text='Save', size=(None, None), s=(None, None), auto_size_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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Submit')
@@ -14202,10 +12810,10 @@ def Submit(button_text='Submit', size=(None, None), s=(None, None), auto_size_bu
: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
+ :type button_color: (str, str) or 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
+ :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param tooltip: text, that will appear when mouse hovers over the element
:type tooltip: (str)
@@ -14225,22 +12833,18 @@ def Submit(button_text='Submit', size=(None, None), s=(None, None), auto_size_bu
: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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Open')
@@ -14252,10 +12856,10 @@ def Open(button_text='Open', size=(None, None), s=(None, None), auto_size_button
: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
+ :type button_color: (str, str) or 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
+ :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param tooltip: text, that will appear when mouse hovers over the element
:type tooltip: (str)
@@ -14275,21 +12879,17 @@ def Open(button_text='Open', size=(None, None), s=(None, None), auto_size_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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'OK')
@@ -14301,10 +12901,10 @@ def OK(button_text='OK', size=(None, None), s=(None, None), auto_size_button=Non
: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
+ :type button_color: (str, str) or 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
+ :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param tooltip: text, that will appear when mouse hovers over the element
:type tooltip: (str)
@@ -14324,21 +12924,17 @@ def OK(button_text='OK', size=(None, None), s=(None, None), auto_size_button=Non
: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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Ok')
@@ -14350,10 +12946,10 @@ def Ok(button_text='Ok', size=(None, None), s=(None, None), auto_size_button=Non
: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
+ :type button_color: (str, str) or 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
+ :param bind_return_key: (Default = True) If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param tooltip: text, that will appear when mouse hovers over the element
:type tooltip: (str)
@@ -14373,21 +12969,17 @@ def Ok(button_text='Ok', size=(None, None), s=(None, None), auto_size_button=Non
: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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- 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):
+ tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button (Default value = 'Cancel')
@@ -14399,203 +12991,7 @@ def Cancel(button_text='Cancel', size=(None, None), s=(None, None), auto_size_bu
: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
+ :type button_color: (str, str) or 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
@@ -14618,24 +13014,20 @@ def No(button_text='No', size=(None, None), s=(None, None), auto_size_button=Non
: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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
-# ------------------------- 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):
+# ------------------------- 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):
"""
- :param button_text: text in the button (Default value = 'Help')
+ :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)
@@ -14644,14 +13036,59 @@ def Help(button_text='Help', size=(None, None), s=(None, None), auto_size_button
: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
+ :type button_color: (str, str) or 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
+ :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: (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)
+ :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)
+
+
+# ------------------------- 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):
+ """
+
+ :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) or 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:
@@ -14667,21 +13104,152 @@ def Help(button_text='Help', size=(None, None), s=(None, None), auto_size_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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
+
+
+# ------------------------- 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):
+ """
+
+ :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) or 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, 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)
+ :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)
+
+
+# ------------------------- 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):
+ """
+
+ :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) or 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)
+ :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)
+
+
+# ------------------------- 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):
+ """
+
+ :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) or 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, 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)
+ :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)
# ------------------------- 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):
+ tooltip=None, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
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.
@@ -14696,14 +13264,14 @@ def Debug(button_text='', size=(None, None), s=(None, None), auto_size_button=No
: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
+ :type button_color: (str, str) or 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
+ :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:
@@ -14719,10 +13287,6 @@ def Debug(button_text='', size=(None, None), s=(None, None), auto_size_button=No
: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)
"""
@@ -14733,13 +13297,13 @@ def Debug(button_text='', size=(None, None), s=(None, None), auto_size_button=No
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)
+ image_subsample=2, 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), 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):
+ font=None, bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None):
"""
DEPIRCATED
@@ -14764,10 +13328,10 @@ def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(
: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
+ :type button_color: (str, str) or 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
+ :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 disabled: set disable state for element (Default = False)
:type disabled: (bool)
@@ -14783,10 +13347,6 @@ def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(
: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)
"""
@@ -14794,13 +13354,13 @@ def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(
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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, 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), 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):
+ bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None):
"""
DEPRICATED
@@ -14826,10 +13386,10 @@ def CloseButton(button_text, image_filename=None, image_data=None, image_size=(N
: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
+ :type button_color: (str, str) or 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
+ :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 disabled: set disable state for element (Default = False)
:type disabled: (bool)
@@ -14845,10 +13405,6 @@ def CloseButton(button_text, image_filename=None, image_data=None, image_size=(N
: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)
"""
@@ -14856,7 +13412,7 @@ def CloseButton(button_text, image_filename=None, image_data=None, image_size=(N
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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata)
CButton = CloseButton
@@ -14865,7 +13421,7 @@ 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):
+ bind_return_key=False, disabled=False, focus=False, pad=None, p=None, key=None, k=None, metadata=None):
"""
:param button_text: text in the button
:type button_text: (str)
@@ -14886,10 +13442,10 @@ def ReadButton(button_text, image_filename=None, image_data=None, image_size=(No
: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
+ :type button_color: (str, str) or 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
+ :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 disabled: set disable state for element (Default = False)
:type disabled: (bool)
@@ -14907,10 +13463,6 @@ def ReadButton(button_text, image_filename=None, image_data=None, image_size=(No
: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)
"""
@@ -14919,7 +13471,7 @@ def ReadButton(button_text, image_filename=None, image_data=None, image_size=(No
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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, metadata=metadata)
ReadFormButton = ReadButton
@@ -14929,7 +13481,7 @@ 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):
+ font=None, disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button
@@ -14953,12 +13505,12 @@ def RealtimeButton(button_text, image_filename=None, image_data=None, image_size
: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
+ :type button_color: (str, str) or 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
+ :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: (bool)
@@ -14974,10 +13526,6 @@ def RealtimeButton(button_text, image_filename=None, image_data=None, image_size
: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)
"""
@@ -14985,13 +13533,13 @@ def RealtimeButton(button_text, image_filename=None, image_data=None, image_size
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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, 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), 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):
+ disabled=False, bind_return_key=False, focus=False, pad=None, p=None, key=None, k=None, visible=True, metadata=None):
"""
This is a special type of Button.
@@ -15021,12 +13569,12 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N
: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
+ :type button_color: (str, str) or 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
+ :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: (bool)
@@ -15042,10 +13590,6 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N
: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)
"""
@@ -15053,7 +13597,7 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N
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)
+ pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
# ------------------------- Calendar Chooser Button lazy function ------------------------- #
@@ -15063,7 +13607,7 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
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):
+ no_titlebar=True, location=(None, None), metadata=None):
"""
Button that will show a calendar chooser window. Fills in the target element with result
@@ -15094,12 +13638,12 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
: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
+ :type button_color: (str, str) or 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
+ :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: bool
@@ -15115,8 +13659,6 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
: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
@@ -15131,10 +13673,6 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
: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)
"""
@@ -15142,7 +13680,7 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
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)
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
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
@@ -15161,7 +13699,7 @@ def CalendarButton(button_text, target=(ThisRow, -1), close_when_date_chosen=Tru
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):
+ key=None, k=None, visible=True, metadata=None):
"""
:param button_text: text in the button
@@ -15188,12 +13726,12 @@ def ColorChooserButton(button_text, target=(ThisRow, -1), image_filename=None, i
: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
+ :type button_color: (str, str) or 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
+ :param bind_return_key: If True, then the return key will cause a the Listbox to generate an event
:type bind_return_key: (bool)
:param focus: Determines if initial focus should go to this element.
:type focus: (bool)
@@ -15205,26 +13743,19 @@ def ColorChooserButton(button_text, target=(ThisRow, -1), image_filename=None, i
: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,
+ 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, 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
+ bind_return_key=bind_return_key, focus=focus, pad=pad, p=p, key=key, k=k, visible=visible, metadata=metadata)
+
##################################### ----- BUTTON Functions ------ ##################################################
@@ -15513,8 +14044,7 @@ def _BuildResultsForSubform(form, initialize_only, top_level_form):
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)
+ tab_key = element.FindKeyFromTabName(value)
if tab_key is not None:
value = tab_key
except:
@@ -15720,10 +14250,8 @@ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False,
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:
@@ -15733,10 +14261,8 @@ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False,
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:
@@ -15901,11 +14427,10 @@ def _change_ttk_theme(style, theme_name):
# style.configure(ttkstyle, **kwargs)
# return ttkstyle
-def _make_ttk_style_name(base_style, element, primary_style=False):
+def _make_ttk_style_name(base_style, element):
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
+ element.ttk_style_name = style_name
return style_name
@@ -15929,13 +14454,11 @@ def _make_ttk_scrollbar(element, orientation, window):
# 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 ------------------
@@ -16499,18 +15022,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
@@ -16548,15 +15061,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
@@ -16567,8 +15077,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -16632,15 +15140,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
@@ -16659,16 +15158,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ style_name = _make_ttk_style_name('.custombutton.TButton', element)
button_style = ttk.Style()
- element.ttk_style = button_style
_change_ttk_theme(button_style, toplevel_form.TtkTheme)
button_style.configure(style_name, font=font)
@@ -16709,8 +15205,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -16724,8 +15218,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -16783,11 +15275,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -16797,24 +15286,20 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
+ 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
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
+ 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)
@@ -16830,10 +15315,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -16873,20 +15356,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TKEntry.bind('', element._KeyboardHandler)
element.TKEntry.bind('', element._ReturnKeyHandler)
-
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
+ if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
element.TKEntry.configure(background=element.BackgroundColor, selectforeground=element.BackgroundColor)
-
- if text_color not in (None, COLOR_SYSTEM_DEFAULT):
+ if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
element.TKEntry.configure(fg=text_color, 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):
+
+ if element.disabled_readonly_background_color is not None:
element.TKEntry.config(readonlybackground=element.disabled_readonly_background_color)
- if element.disabled_readonly_text_color not in (None, COLOR_SYSTEM_DEFAULT) and element.Disabled:
+ if element.disabled_readonly_text_color is not None:
element.TKEntry.config(fg=element.disabled_readonly_text_color)
element.Widget.config(highlightthickness=0)
@@ -16908,6 +15385,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None):
+ element.Widget.config(insertbackground=theme_input_text_color())
# row_should_expand = True
@@ -16920,13 +15399,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
else:
width = max_line_len + 1
element.TKStringVar = tk.StringVar()
- style_name = _make_ttk_style_name('.TCombobox', element, primary_style=True)
+ style_name = _make_ttk_style_name('.TCombobox', element)
+
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)
+ unique_field = _make_ttk_style_name('.TCombobox.field', element)
# Set individual widget options
@@ -16935,7 +15415,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)])
@@ -16945,12 +15424,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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),
@@ -16959,8 +15432,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
"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._newfont = tkinter.font.Font(font=font)
+ tk_row_frame.option_add("*TCombobox*Listbox*Font", element._newfont)
element.TKCombo = element.Widget = ttk.Combobox(tk_row_frame, width=width, textvariable=element.TKStringVar, font=font, style=style_name)
@@ -16969,7 +15442,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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))
+ '[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
@@ -17001,8 +15478,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
@@ -17052,24 +15527,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
@@ -17086,6 +15546,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
@@ -17169,11 +15632,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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))
@@ -17182,15 +15640,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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')
@@ -17225,6 +15677,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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, selectbackground=text_color)
if element.Disabled is True:
@@ -17236,11 +15690,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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()
+ if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None):
+ element.Widget.config(insertbackground=theme_input_text_color())
# row_should_expand = True
# ------------------------- CHECKBOX pleacement element ------------------------- #
@@ -17265,9 +15716,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ element.Widget.configure(highlightthickness=1)
if element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
element.TKCheckbutton.config(highlightbackground=element.BackgroundColor)
if element.TextColor != COLOR_SYSTEM_DEFAULT:
@@ -17302,7 +15752,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
base_style_name = ".Horizontal.TProgressbar"
else:
base_style_name = ".Vertical.TProgressbar"
- style_name = _make_ttk_style_name(base_style_name, element, primary_style=True)
+ style_name = _make_ttk_style_name(base_style_name, element)
element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width,
orientation=direction, BarColor=bar_color,
border_width=element.BorderWidth, relief=element.Relief,
@@ -17344,7 +15794,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -17376,17 +15825,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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 text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
+ element.TKSpinBox.configure(fg=text_color)
if element.ChangeSubmits:
element.TKSpinBox.configure(command=element._SpinboxSelectHandler)
# element.TKSpinBox.bind('', element._SpinChangedHandler)
@@ -17400,6 +15846,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
if element.BindReturnKey:
element.TKSpinBox.bind('', element._SpinboxSelectHandler)
+ if theme_input_text_color() not in (COLOR_SYSTEM_DEFAULT, None):
+ element.Widget.config(insertbackground=theme_input_text_color())
_add_right_click_menu_and_grab(element)
# ------------------------- IMAGE placement element ------------------------- #
elif element_type == ELEM_TYPE_IMAGE:
@@ -17412,11 +15860,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
else:
photo = None
- if photo is not None:
- if element.ImageSubsample:
- photo = photo.subsample(element.ImageSubsample)
- if element.zoom:
- photo = photo.zoom(element.zoom)
+ if element.ImageSubsample and photo is not None:
+ photo = photo.subsample(element.ImageSubsample)
# print('*ERROR laying out form.... Image Element has no image specified*')
except Exception as e:
photo = None
@@ -17519,10 +15964,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -17586,7 +16029,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
# ------------------------- 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'
@@ -17605,8 +16047,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
@@ -17629,19 +16069,17 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
# 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)
+ 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.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not 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)
@@ -17653,7 +16091,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ custom_style = _make_ttk_style_name('.customtab.TNotebook', element)
style = ttk.Style()
_change_ttk_theme(style, toplevel_form.TtkTheme)
@@ -17683,7 +16121,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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):
+ if element.FocusColor is not None:
style.configure(custom_style + '.Tab', focuscolor=element.FocusColor)
style.configure(custom_style + '.Tab', font=font)
@@ -17703,8 +16141,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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:
@@ -17730,13 +16167,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
tkscale.config(highlightthickness=0)
if element.ChangeSubmits:
tkscale.config(command=element._SliderChangedHandler)
- if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
+ 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 not in (None, COLOR_SYSTEM_DEFAULT):
+ if text_color is not None and text_color != 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)
@@ -17805,7 +16242,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
@@ -17815,29 +16251,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ treeview.column(heading, width=width, minwidth=10, anchor=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
+ 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
@@ -17848,8 +16269,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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
+ style_name = _make_ttk_style_name( '.customtable.Treeview', element)
+
table_style = ttk.Style()
element.ttk_style = table_style
@@ -17882,17 +16303,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+ treeview.bind('', element._table_clicked)
if element.right_click_selects:
if running_mac():
treeview.bind('', element._table_clicked)
@@ -17982,8 +16396,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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',
+ displaycolumns=displaycolumns, show='tree headings',
height=height,
selectmode=element.SelectMode)
treeview = element.TKTreeview
@@ -17994,19 +16407,19 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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)
+
+ 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):
"""
@@ -18047,7 +16460,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
# ----- configure colors -----
# style_name = str(element.Key) + '.Treeview'
- style_name = _make_ttk_style_name('.Treeview', element, primary_style=True)
+ style_name = _make_ttk_style_name('.Treeview', element)
tree_style = ttk.Style()
_change_ttk_theme(tree_style, toplevel_form.TtkTheme)
@@ -18146,12 +16559,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
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_name = _make_ttk_style_name(".Line.TSeparator", element)
style = ttk.Style()
_change_ttk_theme(style, toplevel_form.TtkTheme)
- if element.color not in (None, COLOR_SYSTEM_DEFAULT):
+ if element.color is not None:
style.configure(style_name, background=element.color)
separator = element.Widget = ttk.Separator(tk_row_frame, orient=element.Orientation, )
@@ -18339,53 +16752,44 @@ def _convert_window_to_tk(window):
master.title(window.Title)
InitializeResults(window)
-
PackFormIntoFrame(window, master, window)
window.TKroot.configure(padx=window.Margins[0], pady=window.Margins[1])
-
# ....................................... DONE creating and laying out window ..........................#
if window._Size != (None, None):
master.geometry("%sx%s" % (window._Size[0], window._Size[1]))
screen_width = master.winfo_screenwidth() # get window info to move to middle of screen
screen_height = master.winfo_screenheight()
- if window.Location is not None:
- if window.Location != (None, None):
- x, y = window.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
-
- if window.RelativeLoction != (None, None):
- x += window.RelativeLoction[0]
- y += window.RelativeLoction[1]
-
- move_string = '+%i+%i' % (int(x), int(y))
- master.geometry(move_string)
- window.config_last_location = (int(x), (int(y)))
- window.TKroot.x = int(x)
- window.TKroot.y = int(y)
- window.starting_window_position = (int(x), (int(y)))
- master.update_idletasks() # don't forget
- master.geometry(move_string)
- master.update_idletasks() # don't forget
+ if window.Location != (None, None):
+ x, y = window.Location
+ elif DEFAULT_WINDOW_LOCATION != (None, None):
+ x, y = DEFAULT_WINDOW_LOCATION
else:
- master.update_idletasks()
- x, y = int(master.winfo_x()), int(master.winfo_y())
- window.config_last_location = x,y
- window.TKroot.x = x
- window.TKroot.y = y
- window.starting_window_position = x,y
+ 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
+
+ if window.RelativeLoction != (None, None):
+ x += window.RelativeLoction[0]
+ y += window.RelativeLoction[1]
+
+ move_string = '+%i+%i' % (int(x), int(y))
+ master.geometry(move_string)
+ window.config_last_location = (int(x), (int(y)))
+ window.TKroot.x = int(x)
+ window.TKroot.y = int(y)
+ window.starting_window_position = (int(x), (int(y)))
+ master.update_idletasks() # don't forget
+ master.geometry(move_string)
+ master.update_idletasks() # don't forget
+
_no_titlebar_setup(window)
return
@@ -18420,17 +16824,15 @@ def StartupTK(window):
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)
+ # root.bind('', Debugger._build_main_debugger_window)
+ # root.bind('', Debugger._build_floating_window)
+ 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:
@@ -18480,19 +16882,12 @@ def StartupTK(window):
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
+ root.attributes('-alpha', 1 if window.AlphaChannel is None else window.AlphaChannel) # Make window visible again
+ except:
+ pass
if window.ReturnKeyboardEvents and not window.NonBlocking:
root.bind("", window._KeyboardCallback)
@@ -18537,8 +16932,7 @@ def StartupTK(window):
if window.modal or DEFAULT_MODAL_WINDOWS_FORCED:
window.make_modal()
- if window.enable_window_config_events:
- window.TKroot.bind("", window._config_callback)
+ # window.TKroot.bind("", window._config_callback)
# ----------------------------------- tkinter mainloop call -----------------------------------
Window._window_running_mainloop = window
@@ -18658,7 +17052,7 @@ METER_OK = True
METER_STOPPED = False
-class _QuickMeter(object):
+class QuickMeter(object):
active_meters = {}
exit_reasons = {}
@@ -18670,7 +17064,7 @@ class _QuickMeter(object):
:type title: (str)
:param current_value: current value
:type current_value: (int)
- :param max_value: max value of progress meter
+ :param max_value: max value of QuickMeter
:type max_value: (int)
:param key: Used with window.find_element and with return values to uniquely identify this element
:type key: str | int | tuple | object
@@ -18678,10 +17072,10 @@ class _QuickMeter(object):
:type *args: (Any)
:param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v')
:type orientation: (str)
- :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 bar_color: color of a bar line
+ :type bar_color: (str, str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param size: (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)
:type size: (int, int)
:param border_width: width of border around element
@@ -18752,9 +17146,9 @@ class _QuickMeter(object):
if event in ('Cancel', None) or current_value >= max_value:
exit_reason = METER_REASON_CANCELLED if event in ('Cancel', None) else METER_REASON_REACHED_MAX if current_value >= max_value else METER_STOPPED
self.window.close()
- del (_QuickMeter.active_meters[self.key])
- _QuickMeter.exit_reasons[self.key] = exit_reason
- return _QuickMeter.exit_reasons[self.key]
+ del (QuickMeter.active_meters[self.key])
+ QuickMeter.exit_reasons[self.key] = exit_reason
+ return QuickMeter.exit_reasons[self.key]
return METER_OK
def ComputeProgressStats(self):
@@ -18788,22 +17182,22 @@ class _QuickMeter(object):
def one_line_progress_meter(title, current_value, max_value, *args, key='OK for 1 meter', orientation='v', bar_color=(None, None), button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False, no_titlebar=False, keep_on_top=None, no_button=False):
"""
- :param title: text to display in titlebar of window
+ :param title: text to display in eleemnt
:type title: (str)
:param current_value: current value
:type current_value: (int)
- :param max_value: max value of progress meter
+ :param max_value: max value of QuickMeter
:type max_value: (int)
- :param *args: stuff to output as text in the window along with the meter
+ :param *args: stuff to output
:type *args: (Any)
- :param key: Used to differentiate between multiple meters. Used to cancel meter early. Now optional as there is a default value for single meters
+ :param key: Used to differentiate between mutliple meters. Used to cancel meter early. Now optional as there is a default value for single meters
:type key: str | int | tuple | object
:param orientation: 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v')
:type orientation: (str)
- :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 bar_color: color of a bar line
+ :type bar_color: Tuple(str, str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param size: (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)
:type size: (int, int)
:param border_width: width of border around element
@@ -18819,16 +17213,16 @@ def one_line_progress_meter(title, current_value, max_value, *args, key='OK for
:return: True if updated successfully. False if user closed the meter with the X or Cancel button
:rtype: (bool)
"""
- 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, no_titlebar=no_titlebar, keep_on_top=keep_on_top, no_button=no_button)
- _QuickMeter.active_meters[key] = meter
- _QuickMeter.exit_reasons[key] = None
+ 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, no_titlebar=no_titlebar, keep_on_top=keep_on_top, no_button=no_button)
+ QuickMeter.active_meters[key] = meter
+ QuickMeter.exit_reasons[key] = None
else:
- meter = _QuickMeter.active_meters[key]
+ 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)
+ OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter, 'exit_reasons', QuickMeter.exit_reasons)
exit_reason = OneLineProgressMeter.exit_reasons.get(key)
return METER_OK if exit_reason in (None, METER_REASON_REACHED_MAX) else METER_STOPPED
@@ -18843,10 +17237,10 @@ def one_line_progress_meter_cancel(key='OK for 1 meter'):
:rtype: None
"""
try:
- meter = _QuickMeter.active_meters[key]
+ meter = QuickMeter.active_meters[key]
meter.window.Close()
- del (_QuickMeter.active_meters[key])
- _QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED
+ del (QuickMeter.active_meters[key])
+ QuickMeter.exit_reasons[key] = METER_REASON_CANCELLED
except: # meter is already deleted
return
@@ -18978,13 +17372,13 @@ class _DebugWin():
else:
print(*args, sep=sepchar, end=endchar)
# This is tricky....changing the button type depending on the blocking parm. If blocking, then the "Quit" button should become a normal button
- if blocking and not self.no_button:
+ if blocking:
self.quit_button.BType = BUTTON_TYPE_READ_FORM
try: # The window may be closed by user at any time, so have to protect
self.quit_button.update(text='Click to continue...')
except:
self.window = None
- elif not self.no_button:
+ else:
self.quit_button.BType = BUTTON_TYPE_CLOSES_WIN_ONLY
try: # The window may be closed by user at any time, so have to protect
self.quit_button.update(text='Quit')
@@ -18992,9 +17386,9 @@ class _DebugWin():
self.window = None
try: # The window may be closed by user at any time, so have to protect
- if blocking and not self.no_button:
+ if blocking:
self.window['-PAUSE-'].update(visible=False)
- elif not self.no_button:
+ else:
self.window['-PAUSE-'].update(visible=True)
except:
self.window = None
@@ -19013,7 +17407,7 @@ class _DebugWin():
elif not paused and event == TIMEOUT_EVENT and not blocking:
break
elif event == '-PAUSE-':
- if blocking or self.no_button: # if blocking or shouldn't have been a button event, ignore the pause button entirely
+ if blocking: # if blocking, ignore the pause button entirely
continue
if paused:
self.window['-PAUSE-'].update(text='Pause')
@@ -19150,7 +17544,7 @@ def cprint_set_output_destination(window, multiline_key):
def cprint(*args, end=None, sep=' ', text_color=None, font=None, t=None, background_color=None, b=None, colors=None, c=None, window=None, key=None,
- justification=None, autoscroll=True, erase_all=False):
+ justification=None, autoscroll=True):
"""
Color print to a multiline element in a window of your choice.
Must have EITHER called cprint_set_output_destination prior to making this call so that the
@@ -19207,8 +17601,6 @@ def cprint(*args, end=None, sep=' ', text_color=None, font=None, t=None, backgro
:type justification: (str)
:param autoscroll: If True the contents of the element will automatically scroll as more data added to the end
:type autoscroll: (bool)
- :param erase_all If True the contents of the element will be cleared before printing happens
- :type erase_all (bool)
"""
destination_key = CPRINT_DESTINATION_MULTILINE_ELMENT_KEY if key is None else key
@@ -19240,8 +17632,6 @@ def cprint(*args, end=None, sep=' ', text_color=None, font=None, t=None, backgro
mline = destination_window.find_element(destination_key, silent_on_error=True) # type: Multiline
try:
# mline = destination_window[destination_key] # type: Multiline
- if erase_all is True:
- mline.update('')
if end is None:
mline.print(*args, text_color=kw_text_color, background_color=kw_background_color, end='', sep=sep, justification=justification, font=font,
autoscroll=autoscroll)
@@ -19363,13 +17753,12 @@ def set_options(icon=None, button_color=None, element_size=(None, None), button_
suppress_error_popups=None, suppress_raise_key_errors=None, suppress_key_guessing=None,warn_button_key_duplicates=False, enable_treeview_869_patch=None,
enable_mac_notitlebar_patch=None, use_custom_titlebar=None, titlebar_background_color=None, titlebar_text_color=None, titlebar_font=None,
titlebar_icon=None, user_settings_path=None, pysimplegui_settings_path=None, pysimplegui_settings_filename=None, keep_on_top=None, dpi_awareness=None, scaling=None, disable_modal_windows=None, force_modal_windows=None, tooltip_offset=(None, 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, alpha_channel=None,
- hide_window_when_creating=None, use_button_shortcuts=None, watermark_text=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, alpha_channel=None):
"""
: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: bytes | str
:param button_color: Color of the button (text, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param element_size: element size (width, height) in characters
:type element_size: (int, int)
:param button_element_size: Size of button
@@ -19491,15 +17880,9 @@ def set_options(icon=None, button_color=None, element_size=(None, None), button_
: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
+ :param alpha_channel Default alpha channel to be used on all windows
+ :type alpha_channel (float)
:type sbar_relief: (str)
- :param alpha_channel: Default alpha channel to be used on all windows
- :type alpha_channel: (float)
- :param hide_window_when_creating: If True then alpha will be set to 0 while a window is made and moved to location indicated
- :type hide_window_when_creating: (bool)
- :param use_button_shortcuts: If True then Shortcut Char will be used with Buttons
- :type use_button_shortcuts: (bool)
- :param watermark_text: Set the text that will be used if a window is watermarked
- :type watermark_text: (str)
:return: None
:rtype: None
"""
@@ -19559,10 +17942,9 @@ def set_options(icon=None, button_color=None, element_size=(None, None), button_
global DEFAULT_MODAL_WINDOWS_FORCED
global DEFAULT_TOOLTIP_OFFSET
global DEFAULT_ALPHA_CHANNEL
+
global _pysimplegui_user_settings
global ttk_part_overrides_from_options
- global DEFAULT_HIDE_WINDOW_WHEN_CREATING
- global DEFAULT_USE_BUTTON_SHORTCUTS
# global _my_windows
if icon:
@@ -19746,7 +18128,6 @@ def set_options(icon=None, button_color=None, element_size=(None, None), button_
if tooltip_offset != (None, None):
DEFAULT_TOOLTIP_OFFSET = tooltip_offset
-
if alpha_channel is not None:
DEFAULT_ALPHA_CHANNEL = alpha_channel
@@ -19772,15 +18153,6 @@ def set_options(icon=None, button_color=None, element_size=(None, None), button_
if sbar_width is not None:
ttk_part_overrides_from_options.sbar_width = sbar_width
- if hide_window_when_creating is not None:
- DEFAULT_HIDE_WINDOW_WHEN_CREATING = hide_window_when_creating
-
- if use_button_shortcuts is not None:
- DEFAULT_USE_BUTTON_SHORTCUTS = use_button_shortcuts
-
- if watermark_text is not None:
- Window._watermark_user_text = watermark_text
-
return True
@@ -19835,8 +18207,6 @@ LOOK_AND_FEEL_TABLE = {
"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
"Black": {"BACKGROUND": "#000000", "TEXT": "#FFFFFF", "INPUT": "#4D4D4D", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#707070", "BUTTON": ("#000000", "#FFFFFF"),
"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
- "Black2": {"BACKGROUND": "#000000", "TEXT": "#FFFFFF", "INPUT": "#000000", "TEXT_INPUT": "#FFFFFF", "SCROLL": "#FFFFFF", "BUTTON": ("#000000", "#FFFFFF"),
- "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
"Tan": {"BACKGROUND": "#fdf6e3", "TEXT": "#268bd1", "INPUT": "#eee8d5", "TEXT_INPUT": "#6c71c3", "SCROLL": "#eee8d5", "BUTTON": ("#FFFFFF", "#063542"),
"PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
"TanBlue": {"BACKGROUND": "#e5dece", "TEXT": "#063289", "INPUT": "#f9f8f4", "TEXT_INPUT": "#242834", "SCROLL": "#eee8d5", "BUTTON": ("#FFFFFF", "#063289"),
@@ -20170,9 +18540,6 @@ LOOK_AND_FEEL_TABLE = {
"DarkBlue17": {"BACKGROUND": "#21294c", "TEXT": "#f9f2d7", "INPUT": "#f2dea8", "TEXT_INPUT": "#000000", "SCROLL": "#f2dea8",
"BUTTON": ("#f9f2d7", "#141829"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0,
"COLOR_LIST": ["#141829", "#21294c", "#f2dea8", "#f9f2d7"], "DESCRIPTION": ["#000000", "Blue", "Yellow"], },
- "DarkBlue18": {"BACKGROUND": "#0c1825", "TEXT": "#d1d7dd", "INPUT": "#001c35", "TEXT_INPUT": "#d1d7dd", "SCROLL": "#00438e",
- "BUTTON": ("#75b7ff", "#001c35"), "PROGRESS": ('#0074ff', '#75b7ff'), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0,
- "COLOR_LIST": ["#141829", "#21294c", "#f2dea8", "#f9f2d7"], "DESCRIPTION": ["#000000", "Blue", "Yellow"], },
"DarkBrown6": {"BACKGROUND": "#785e4d", "TEXT": "#f2eee3", "INPUT": "#baaf92", "TEXT_INPUT": "#000000", "SCROLL": "#baaf92",
"BUTTON": ("#FFFFFF", "#785e4d"), "PROGRESS": DEFAULT_PROGRESS_BAR_COMPUTE, "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0,
"COLOR_LIST": ["#785e4d", "#ff8426", "#baaf92", "#f2eee3"], "DESCRIPTION": ["Grey", "Brown", "Orange", "Autumn"], },
@@ -20208,20 +18575,12 @@ LOOK_AND_FEEL_TABLE = {
"BUTTON": ("#fafbfc", "#155398"), "PROGRESS": ("#155398", "#1d2125"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
"DarkGrey15": {'BACKGROUND': '#121212', 'TEXT': '#dddddd', 'INPUT': '#1e1e1e', 'TEXT_INPUT': '#69b1ef', 'SCROLL': '#272727',
'BUTTON': ('#69b1ef', '#2e2e2e'), 'PROGRESS': ('#69b1ef', '#2e2e2e'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,},
- "DarkGrey16": {'BACKGROUND': '#353535', 'TEXT': '#ffffff', 'INPUT': '#191919', 'TEXT_INPUT': '#ffffff', 'SCROLL': '#454545',
- 'BUTTON': ('#ffffff', '#454545'), 'PROGRESS': ('#757575', '#454545'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,},
"DarkBrown7": {"BACKGROUND": "#2c2417", "TEXT": "#baa379", "INPUT": "#baa379", "TEXT_INPUT": "#000000", "SCROLL": "#392e1c",
"BUTTON": ("#000000", "#baa379"), "PROGRESS": ("#baa379", "#453923"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, },
"Python": {"BACKGROUND": "#3d7aab", "TEXT": "#ffde56", "INPUT": "#295273", "TEXT_INPUT": "#ffde56", "SCROLL": "#295273",
"BUTTON": ("#ffde56", "#295273"), "PROGRESS": ("#ffde56", "#295273"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, },
"PythonPlus": {"BACKGROUND": "#001d3c", "TEXT": "#ffffff", "INPUT": "#015bbb", "TEXT_INPUT": "#fed500", "SCROLL": "#015bbb",
- "BUTTON": ("#fed500", "#015bbb"), "PROGRESS": ("#015bbb", "#fed500"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, },
- "NeonBlue1": {"BACKGROUND": "#000000", "TEXT": "#ffffff", "INPUT": "#000000", "TEXT_INPUT": "#33ccff", "SCROLL": "#33ccff",
- "BUTTON": ("#33ccff", "#000000"), "PROGRESS": ("#33ccff", "#ffffff"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
- "NeonGreen1": {"BACKGROUND": "#000000", "TEXT": "#ffffff", "INPUT": "#000000", "TEXT_INPUT": "#96ff7b", "SCROLL": "#96ff7b",
- "BUTTON": ("#96ff7b", "#000000"), "PROGRESS": ("#96ff7b", "#ffffff"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
- "NeonYellow1": {"BACKGROUND": "#000000", "TEXT": "#ffffff", "INPUT": "#000000", "TEXT_INPUT": "#ffcf40", "SCROLL": "#ffcf40",
- "BUTTON": ("#ffcf40", "#000000"), "PROGRESS": ("#ffcf40", "#ffffff"), "BORDER": 1, "SLIDER_DEPTH": 0, "PROGRESS_DEPTH": 0, },
+ "BUTTON": ("#fed500", "#015bbb"), "PROGRESS": ("#015bbb", "#fed500"), "BORDER": 1, "SLIDER_DEPTH": 1, "PROGRESS_DEPTH": 0, },
}
@@ -20898,7 +19257,7 @@ def clipboard_get():
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=None, location=(None, None), relative_location=(None, None), any_key_closes=False, image=None, modal=True, button_justification=None, drop_whitespace=True):
+ keep_on_top=None, location=(None, None), relative_location=(None, None), any_key_closes=False, image=None, modal=True):
"""
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.
@@ -20907,60 +19266,52 @@ def popup(*args, title=None, button_color=None, background_color=None, text_colo
choice, _ = sg.Window('Continue?', [[sg.T('Do you want to continue?')], [sg.Yes(s=10), sg.No(s=10)]], disable_close=True).read(close=True)
- :param *args: Variable number of your arguments. Load up the call with stuff to see!
- :type *args: (Any)
- :param title: Optional title for the window. If none provided, the first arg will be used instead.
- :type title: (str)
- :param button_color: Color of the buttons shown (text color, button color)
- :type button_color: (str, str) | str
- :param background_color: Window's background color
- :type background_color: (str)
- :param text_color: text color
- :type text_color: (str)
- :param button_type: 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.
- :type button_type: (int)
- :param auto_close: If True the window will automatically close
- :type auto_close: (bool)
- :param auto_close_duration: time in seconds to keep window open before closing it automatically
- :type auto_close_duration: (int)
- :param custom_text: A string or pair of strings that contain the text to display on the buttons
- :type custom_text: (str, str) | str
- :param non_blocking: If True then will immediately return from the function without waiting for the user's input.
- :type non_blocking: (bool)
- :param icon: icon to display on the window. Same format as a Window call
- :type icon: str | bytes
- :param line_width: Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH
- :type line_width: (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 | Tuple[font_name, size, modifiers]
- :param no_titlebar: If True will not show the frame around the window and the titlebar across the top
- :type no_titlebar: (bool)
- :param grab_anywhere: If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too
- :type grab_anywhere: (bool)
- :param location: Location on screen to display the top left corner of window. Defaults to window centered on screen
- :type location: (int, int)
- :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 keep_on_top: If True the window will remain above all current windows
- :type keep_on_top: (bool)
- :param any_key_closes: If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false.
- :type any_key_closes: (bool)
- :param image: Image to include at the top of the popup window
- :type image: (str) or (bytes)
- :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
- :type modal: bool
- :param right_justify_buttons: If True then the buttons will be "pushed" to the right side of the Window
- :type right_justify_buttons: bool
- :param button_justification: Speficies if buttons should be left, right or centered. Default is left justified
- :type button_justification: str
- :param drop_whitespace: Controls is whitespace should be removed when wrapping text. Parameter is passed to textwrap.fill. Default is to drop whitespace (so popup remains backward compatible)
- :type drop_whitespace: bool
- :return: Returns text of the button that was pressed. None will be returned if user closed window with X
- :rtype: str | None
+ :param *args: Variable number of your arguments. Load up the call with stuff to see!
+ :type *args: (Any)
+ :param title: Optional title for the window. If none provided, the first arg will be used instead.
+ :type title: (str)
+ :param button_color: Color of the buttons shown (text color, button color)
+ :type button_color: (str, str) | None
+ :param background_color: Window's background color
+ :type background_color: (str)
+ :param text_color: text color
+ :type text_color: (str)
+ :param button_type: 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.
+ :type button_type: (int)
+ :param auto_close: If True the window will automatically close
+ :type auto_close: (bool)
+ :param auto_close_duration: time in seconds to keep window open before closing it automatically
+ :type auto_close_duration: (int)
+ :param custom_text: A string or pair of strings that contain the text to display on the buttons
+ :type custom_text: (str, str) | str
+ :param non_blocking: If True then will immediately return from the function without waiting for the user's input.
+ :type non_blocking: (bool)
+ :param icon: icon to display on the window. Same format as a Window call
+ :type icon: str | bytes
+ :param line_width: Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH
+ :type line_width: (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 | Tuple[font_name, size, modifiers]
+ :param no_titlebar: If True will not show the frame around the window and the titlebar across the top
+ :type no_titlebar: (bool)
+ :param grab_anywhere: If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too
+ :type grab_anywhere: (bool)
+ :param location: Location on screen to display the top left corner of window. Defaults to window centered on screen
+ :type location: (int, int)
+ :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 keep_on_top: If True the window will remain above all current windows
+ :type keep_on_top: (bool)
+ :param any_key_closes: If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false.
+ :type any_key_closes: (bool)
+ :param image: Image to include at the top of the popup window
+ :type image: (str) or (bytes)
+ :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
+ :type modal: bool
+ :return: Returns text of the button that was pressed. None will be returned if user closed window with X
+ :rtype: str | None
"""
-
-
if not args:
args_to_print = ['']
else:
@@ -20989,7 +19340,7 @@ def popup(*args, title=None, button_color=None, background_color=None, text_colo
msg_list = message.split('\n') # break into segments that will each be wrapped
message_wrapped = '\n'.join([textwrap.fill(msg, local_line_width) for msg in msg_list])
else:
- message_wrapped = textwrap.fill(message, local_line_width, drop_whitespace=drop_whitespace)
+ 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)
@@ -21017,28 +19368,23 @@ def popup(*args, title=None, button_color=None, background_color=None, text_colo
layout += [[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[1]), 1))]]
- elif button_type == POPUP_BUTTONS_YES_NO:
- layout += [[PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True,
+ elif button_type is POPUP_BUTTONS_YES_NO:
+ layout += [[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 == POPUP_BUTTONS_CANCELLED:
+ elif button_type is POPUP_BUTTONS_CANCELLED:
layout += [[
- PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True )]]
- elif button_type == POPUP_BUTTONS_ERROR:
- layout += [[PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True)]]
- elif button_type == POPUP_BUTTONS_OK_CANCEL:
+ PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3))]]
+ elif button_type is POPUP_BUTTONS_ERROR:
+ layout += [[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:
layout += [[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 == POPUP_BUTTONS_NO_BUTTONS:
+ elif button_type is POPUP_BUTTONS_NO_BUTTONS:
pass
else:
- layout += [[PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True,)]]
- if button_justification is not None:
- justification = button_justification.lower()[0]
- if justification == 'r':
- layout[-1] = [Push()] + layout[-1]
- elif justification == 'c':
- layout[-1] = [Push()] + layout[-1] + [Push()]
-
+ layout += [[PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True,
+ pad=((20, 0), 3))]]
window = Window(_title, layout, 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,
@@ -21073,59 +19419,56 @@ def MsgBox(*args):
# ======================== Scrolled Text Box =====#
# ===================================================#
-def popup_scrolled(*args, title=None, button_color=None, background_color=None, text_color=None, yes_no=False, no_buttons=False, button_justification='l', auto_close=False, auto_close_duration=None, size=(None, None), location=(None, None), relative_location=(None, None), non_blocking=False, no_titlebar=False, grab_anywhere=False, keep_on_top=None, font=None, image=None, icon=None, modal=True, no_sizegrip=False):
+def popup_scrolled(*args, title=None, button_color=None, background_color=None, text_color=None, yes_no=False, auto_close=False, auto_close_duration=None,
+ size=(None, None), location=(None, None), relative_location=(None, None), non_blocking=False, no_titlebar=False, grab_anywhere=False, keep_on_top=None, font=None,
+ image=None, icon=None, modal=True, no_sizegrip=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: Variable number of items to display
- :type *args: (Any)
- :param title: Title to display in the window.
- :type title: (str)
- :param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
- :param yes_no: If True, displays Yes and No buttons instead of Ok
- :type yes_no: (bool)
- :param no_buttons: If True, no buttons will be shown. User will have to close using the "X"
- :type no_buttons: (bool)
- :param button_justification: How buttons should be arranged. l, c, r for Left, Center or Right justified
- :type button_justification: (str)
- :param auto_close: if True window will close itself
- :type auto_close: (bool)
- :param auto_close_duration: Older versions only accept int. Time in seconds until window will close
- :type auto_close_duration: int | float
- :param size: (w,h) w=characters-wide, h=rows-high
- :type size: (int, int)
- :param location: Location on the screen to place the upper left corner of the window
- :type location: (int, int)
- :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 non_blocking: if True the call will immediately return rather than waiting on user input
- :type non_blocking: (bool)
- :param background_color: color of background
- :type background_color: (str)
- :param text_color: color of the text
- :type text_color: (str)
- :param no_titlebar: If True no titlebar will be shown
- :type no_titlebar: (bool)
- :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False)
- :type grab_anywhere: (bool)
- :param keep_on_top: If True the window will remain above all current windows
- :type keep_on_top: (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 image: Image to include at the top of the popup window
- :type image: (str) or (bytes)
- :param icon: filename or base64 string to be used for the window's icon
- :type icon: bytes | str
- :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
- :type modal: bool
- :param no_sizegrip: If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar
- :type no_sizegrip: (bool)
- :return: Returns text of the button that was pressed. None will be returned if user closed window with X
- :rtype: str | None | TIMEOUT_KEY
+ :param *args: Variable number of items to display
+ :type *args: (Any)
+ :param title: Title to display in the window.
+ :type title: (str)
+ :param button_color: button color (foreground, background)
+ :type button_color: (str, str) or str
+ :param yes_no: If True, displays Yes and No buttons instead of Ok
+ :type yes_no: (bool)
+ :param auto_close: if True window will close itself
+ :type auto_close: (bool)
+ :param auto_close_duration: Older versions only accept int. Time in seconds until window will close
+ :type auto_close_duration: int | float
+ :param size: (w,h) w=characters-wide, h=rows-high
+ :type size: (int, int)
+ :param location: Location on the screen to place the upper left corner of the window
+ :type location: (int, int)
+ :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 non_blocking: if True the call will immediately return rather than waiting on user input
+ :type non_blocking: (bool)
+ :param background_color: color of background
+ :type background_color: (str)
+ :param text_color: color of the text
+ :type text_color: (str)
+ :param no_titlebar: If True no titlebar will be shown
+ :type no_titlebar: (bool)
+ :param grab_anywhere: If True, than can grab anywhere to move the window (Default = False)
+ :type grab_anywhere: (bool)
+ :param keep_on_top: If True the window will remain above all current windows
+ :type keep_on_top: (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 image: Image to include at the top of the popup window
+ :type image: (str) or (bytes)
+ :param icon: filename or base64 string to be used for the window's icon
+ :type icon: bytes | str
+ :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
+ :type modal: bool
+ :param no_sizegrip: If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar
+ :type no_sizegrip: (bool)
+ :return: Returns text of the button that was pressed. None will be returned if user closed window with X
+ :rtype: str | None | TIMEOUT_KEY
"""
-
if not args: return
width, height = size
width = width if width else MESSAGE_BOX_LINE_WIDTH
@@ -21156,26 +19499,16 @@ def popup_scrolled(*args, title=None, button_color=None, background_color=None,
height_computed = height
layout += [[Multiline(complete_output, size=(max_line_width, height_computed), background_color=background_color, text_color=text_color, expand_x=True,
expand_y=True, k='-MLINE-')]]
+ 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 Button
-
if yes_no:
- buttons = [button('Yes'), button('No')]
- elif no_buttons is not True:
- buttons = [button('OK', size=(5, 1), button_color=button_color)]
+ layout += [[Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), button('Yes'), button('No')]]
else:
- buttons = None
-
- if buttons is not None:
- if button_justification.startswith('l'):
- layout += [buttons]
- elif button_justification.startswith('c'):
- layout += [[Push()] + buttons + [Push()]]
- else:
- layout += [[Push()] + buttons]
-
- if no_sizegrip is not True:
- layout[-1] += [Sizegrip()]
+ layout += [[Text('', size=(pad, 1), auto_size_text=False, background_color=background_color),
+ button('OK', size=(5, 1), button_color=button_color)]]
+ if no_titlebar and no_sizegrip is not True:
+ layout += [[Sizegrip()]]
window = Window(title or args[0], layout, auto_size_text=True, button_color=button_color, auto_close=auto_close,
auto_close_duration=auto_close_duration, location=location, relative_location=relative_location, resizable=True, font=font, background_color=background_color,
@@ -21260,7 +19593,7 @@ def popup_non_blocking(*args, title=None, button_type=POPUP_BUTTONS_OK, button_c
:param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK).
:type button_type: (int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21314,7 +19647,7 @@ def popup_quick(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=No
:param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK).
:type button_type: (int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21359,7 +19692,7 @@ def popup_quick(*args, title=None, button_type=POPUP_BUTTONS_OK, button_color=No
# --------------------------- popup_quick_message - a NonBlocking, Self-closing Popup with no titlebar and no buttons ---------------------------
def popup_quick_message(*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=True, location=(None, None), relative_location=(None, None), image=None, modal=False):
+ font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=False):
"""
Show Popup window with no titlebar, doesn't block, and auto closes itself.
@@ -21370,7 +19703,7 @@ def popup_quick_message(*args, title=None, button_type=POPUP_BUTTONS_NO_BUTTONS,
:param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK).
:type button_type: (int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param keep_on_top: If True the window will remain above all current windows
:type keep_on_top: (bool)
:param background_color: color of background
@@ -21425,7 +19758,7 @@ def popup_no_titlebar(*args, title=None, button_type=POPUP_BUTTONS_OK, button_co
:param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK).
:type button_type: (int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21478,7 +19811,7 @@ def popup_auto_close(*args, title=None, button_type=POPUP_BUTTONS_OK, button_col
:param button_type: Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK).
:type button_type: (int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21532,7 +19865,7 @@ def popup_error(*args, title=None, button_color=(None, None), background_color=N
:param title: Title to display in the window.
:type title: (str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21586,7 +19919,7 @@ def popup_cancel(*args, title=None, button_color=None, background_color=None, te
:param title: Title to display in the window.
:type title: (str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21639,7 +19972,7 @@ def popup_ok(*args, title=None, button_color=None, background_color=None, text_c
:param title: Title to display in the window.
:type title: (str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21691,7 +20024,7 @@ def popup_ok_cancel(*args, title=None, button_color=None, background_color=None,
:param title: Title to display in the window.
:type title: (str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21744,7 +20077,7 @@ def popup_yes_no(*args, title=None, button_color=None, background_color=None, te
:param title: Title to display in the window.
:type title: (str)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21810,7 +20143,7 @@ def popup_get_folder(message, title=None, default_path='', no_window=False, size
:param size: (width, height) of the InputText Element
:type size: (int, int)
:param button_color: button color (foreground, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: color of background
:type background_color: (str)
:param text_color: color of the text
@@ -21955,14 +20288,14 @@ def popup_get_file(message, title=None, default_path='', default_extension='', s
:type save_as: (bool)
:param multiple_files: if True, then allows multiple files to be selected that are returned with ';' between each filename
:type multiple_files: (bool)
- :param file_types: List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),).
+ :param file_types: List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). NOT avoilable on the MAC
:type file_types: Tuple[Tuple[str,str]]
:param no_window: if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown
:type no_window: (bool)
:param size: (width, height) of the InputText Element or Combo element if using history feature
:type size: (int, int)
:param button_color: Color of the button (text, background)
- :type button_color: (str, str) | str
+ :type button_color: (str, str) or str
:param background_color: background color of the entire window
:type background_color: (str)
:param text_color: color of the text
@@ -22051,16 +20384,9 @@ def popup_get_file(message, title=None, default_path='', default_extension='', s
# for Macs, setting parent=None fixes a warning problem.
if save_as:
if running_mac():
- is_all = [(x, y) for (x, y) in file_types if all(ch in '* .' for ch in y)]
- if not len(set(file_types)) > 1 and (len(is_all) != 0 or file_types == FILE_TYPES_ALL_FILES):
- filename = tk.filedialog.asksaveasfilename(initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get file' dialog box
- else:
- filename = tk.filedialog.asksaveasfilename(filetypes=file_types,
- initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get file' dialog box
+ filename = tk.filedialog.asksaveasfilename(initialdir=initial_folder,
+ initialfile=default_path,
+ defaultextension=default_extension) # show the 'get file' dialog box
else:
filename = tk.filedialog.asksaveasfilename(filetypes=file_types,
initialdir=initial_folder,
@@ -22069,34 +20395,20 @@ def popup_get_file(message, title=None, default_path='', default_extension='', s
defaultextension=default_extension) # show the 'get file' dialog box
elif multiple_files:
if running_mac():
- is_all = [(x, y) for (x, y) in file_types if all(ch in '* .' for ch in y)]
- if not len(set(file_types)) > 1 and (len(is_all) != 0 or file_types == FILE_TYPES_ALL_FILES):
- filename = tk.filedialog.askopenfilenames(initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get file' dialog box
- else:
- filename = tk.filedialog.askopenfilenames(filetypes=file_types,
- initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get file' dialog box
+ filename = tk.filedialog.askopenfilenames(initialdir=initial_folder,
+ initialfile=default_path,
+ defaultextension=default_extension) # show the 'get file' dialog box
else:
filename = tk.filedialog.askopenfilenames(filetypes=file_types,
- initialdir=initial_folder,
- initialfile=default_path,
- parent=root,
- defaultextension=default_extension) # show the 'get file' dialog box
+ initialdir=initial_folder,
+ initialfile=default_path,
+ parent=root,
+ defaultextension=default_extension) # show the 'get file' dialog box
else:
if running_mac():
- is_all = [(x, y) for (x, y) in file_types if all(ch in '* .' for ch in y)]
- if not len(set(file_types)) > 1 and (len(is_all) != 0 or file_types == FILE_TYPES_ALL_FILES):
- filename = tk.filedialog.askopenfilename(initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get files' dialog box
- else:
- filename = tk.filedialog.askopenfilename(filetypes=file_types,
- initialdir=initial_folder,
- initialfile=default_path,
- defaultextension=default_extension) # show the 'get files' dialog box
+ filename = tk.filedialog.askopenfilename(initialdir=initial_folder,
+ initialfile=default_path,
+ defaultextension=default_extension) # show the 'get files' dialog box
else:
filename = tk.filedialog.askopenfilename(filetypes=file_types,
initialdir=initial_folder,
@@ -22108,8 +20420,6 @@ def popup_get_file(message, title=None, default_path='', default_extension='', s
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]
- if not filename:
- return None
return filename
if save_as:
@@ -22177,68 +20487,48 @@ def popup_get_file(message, title=None, default_path='', default_extension='', s
def popup_get_text(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=None, location=(None, None), relative_location=(None, None), image=None, history=False, history_setting_filename=None, modal=True):
+ grab_anywhere=False, keep_on_top=None, location=(None, None), relative_location=(None, None), image=None, modal=True):
"""
Display Popup with text entry field. Returns the text entered or None if closed / cancelled
- :param message: message displayed to user
- :type message: (str)
- :param title: Window title
- :type title: (str)
- :param default_text: default value to put into input area
- :type default_text: (str)
- :param password_char: character to be shown instead of actually typed characters. WARNING - if history=True then can't hide passwords
- :type password_char: (str)
- :param size: (width, height) of the InputText Element
- :type size: (int, int)
- :param button_color: Color of the button (text, background)
- :type button_color: (str, str) | str
- :param background_color: background color of the entire window
- :type background_color: (str)
- :param text_color: color of the message text
- :type text_color: (str)
- :param icon: filename or base64 string to be used for the window's icon
- :type icon: bytes | 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 no_titlebar: If True no titlebar will be shown
- :type no_titlebar: (bool)
- :param grab_anywhere: If True can click and drag anywhere in the window to move the window
- :type grab_anywhere: (bool)
- :param keep_on_top: If True the window will remain above all current windows
- :type keep_on_top: (bool)
- :param location: (x,y) Location on screen to display the upper left corner of window
- :type location: (int, int)
- :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 image: Image to include at the top of the popup window
- :type image: (str) or (bytes)
- :param history: If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided
- :type history: bool
- :param history_setting_filename: Filename to use for the User Settings. Will store list of previous entries in this settings file
- :type history_setting_filename: (str)
- :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
- :type modal: bool
- :return: Text entered or None if window was closed or cancel button clicked
- :rtype: str | None
+ :param message: message displayed to user
+ :type message: (str)
+ :param title: Window title
+ :type title: (str)
+ :param default_text: default value to put into input area
+ :type default_text: (str)
+ :param password_char: character to be shown instead of actually typed characters
+ :type password_char: (str)
+ :param size: (width, height) of the InputText Element
+ :type size: (int, int)
+ :param button_color: Color of the button (text, background)
+ :type button_color: (str, str) or str
+ :param background_color: background color of the entire window
+ :type background_color: (str)
+ :param text_color: color of the message text
+ :type text_color: (str)
+ :param icon: filename or base64 string to be used for the window's icon
+ :type icon: bytes | 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 no_titlebar: If True no titlebar will be shown
+ :type no_titlebar: (bool)
+ :param grab_anywhere: If True can click and drag anywhere in the window to move the window
+ :type grab_anywhere: (bool)
+ :param keep_on_top: If True the window will remain above all current windows
+ :type keep_on_top: (bool)
+ :param location: (x,y) Location on screen to display the upper left corner of window
+ :type location: (int, int)
+ :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 image: Image to include at the top of the popup window
+ :type image: (str) or (bytes)
+ :param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
+ :type modal: bool
+ :return: Text entered or None if window was closed or cancel button clicked
+ :rtype: str | None
"""
-
- # First setup the history settings file if history feature is enabled
- if history and history_setting_filename is not None:
- try:
- history_settings = UserSettings(history_setting_filename)
- except Exception as e:
- _error_popup_with_traceback('popup_get_file - Something is wrong with your supplied history settings filename',
- 'Exception: {}'.format(e))
- return None
- elif history:
- history_settings_filename = os.path.basename(inspect.stack()[1].filename)
- history_settings_filename = os.path.splitext(history_settings_filename)[0] + '.json'
- history_settings = UserSettings(history_settings_filename)
- else:
- history_settings = None
-
if image is not None:
if isinstance(image, str):
layout = [[Image(filename=image)]]
@@ -22247,50 +20537,25 @@ def popup_get_text(message, title=None, default_text='', password_char='', size=
else:
layout = [[]]
- layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)]]
- if not history:
- layout += [[InputText(default_text=default_text, size=size, key='-INPUT-', password_char=password_char)]]
- else:
- text_list = history_settings.get("-PSG text list-", [])
- last_entry = text_list[0] if text_list else default_text
- layout += [[Combo(text_list, default_value=last_entry, key='-INPUT-', size=size if size != (None, None) else (80, 1), bind_return_key=True),
- Button('Clear History', tooltip='Clears the list of files shown in the combobox')]]
-
- layout += [[Button('Ok', size=(6, 1), bind_return_key=True), Button('Cancel', size=(6, 1))]]
+ layout += [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)],
+ [InputText(default_text=default_text, size=size, key='-INPUT-', password_char=password_char)],
+ [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, no_titlebar=no_titlebar,
background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location, relative_location=relative_location, finalize=True, modal=modal, font=font)
-
- while True:
- event, values = window.read()
- if event in ('Cancel', WIN_CLOSED):
- break
- elif event == 'Clear History':
- history_settings.set('-PSG text list-', [])
- window['-INPUT-'].update('', [])
- popup_quick_message('History of Previous Choices Cleared', background_color='red', text_color='white', font='_ 20', keep_on_top=True)
- elif event in ('Ok', '-INPUT-'):
- if values['-INPUT-'] != '':
- if history_settings is not None:
- list_of_entries = history_settings.get('-PSG text list-', [])
- if values['-INPUT-'] in list_of_entries:
- list_of_entries.remove(values['-INPUT-'])
- list_of_entries.insert(0, values['-INPUT-'])
- history_settings.set('-PSG text list-', list_of_entries)
- break
-
+ button, values = window.read()
window.close()
del window
- if event in ('Cancel', WIN_CLOSED):
+ if button != 'Ok':
return None
else:
- text = values['-INPUT-']
- return text
+ path = values['-INPUT-']
+ return path
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), relative_location=(None, None), close_when_chosen=False, icon=None, locale=None, month_names=None, day_abbreviations=None, day_font = 'TkFixedFont 9', mon_year_font = 'TkFixedFont 10', arrow_font = 'TkFixedFont 7', modal=True):
+ location=(None, None), relative_location=(None, None), close_when_chosen=False, icon=None, locale=None, month_names=None, day_abbreviations=None, modal=True):
"""
Display a calendar window, get the user's choice, return as a tuple (mon, day, year)
@@ -22322,12 +20587,6 @@ def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sun
: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 day_font: Font and size to use for the calendar
- :type day_font: str | tuple
- :param mon_year_font: Font and size to use for the month and year at the top
- :type mon_year_font: str | tuple
- :param arrow_font: Font and size to use for the arrow buttons
- :type arrow_font: str | tuple
:param modal: If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True
:type modal: bool
:return: Tuple containing (month, day, year) of chosen date or None if was cancelled
@@ -22342,6 +20601,10 @@ def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sun
if not SUPPRESS_ERROR_POPUPS:
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
@@ -22461,7 +20724,7 @@ def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sun
# --------------------------- PopupAnimated ---------------------------
def popup_animated(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), relative_location=(None, None), alpha_channel=None, time_between_frames=0, transparent_color=None, title='', icon=None, no_buffering=False):
+ location=(None, None), relative_location=(None, None), alpha_channel=None, time_between_frames=0, transparent_color=None, title='', icon=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
@@ -22498,8 +20761,6 @@ def popup_animated(image_source, message=None, background_color=None, text_color
:type title: (str)
:param icon: Same as Window icon parameter. Can be either a filename or Base64 byte string. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO
:type icon: str | bytes
- :param no_buffering: If True then no buffering will be used for the GIF. May work better if you have a large animation
- :type no_buffering: (bool)
:return: True if the window updated OK. False if the window was closed
:rtype: bool
"""
@@ -22525,10 +20786,7 @@ def popup_animated(image_source, message=None, background_color=None, text_color
Window._animated_popup_dict[image_source] = window
else:
window = Window._animated_popup_dict[image_source]
- if no_buffering:
- window['-IMAGE-'].update_animation_no_buffering(image_source, time_between_frames=time_between_frames)
- else:
- window['-IMAGE-'].update_animation(image_source, time_between_frames=time_between_frames)
+ window['-IMAGE-'].update_animation(image_source, time_between_frames=time_between_frames)
event, values = window.read(1)
if event == WIN_CLOSED:
return False
@@ -22633,27 +20891,23 @@ def popup_menu(window, element, menu_def, title=None, location=(None, None)):
top_menu.invoke(0)
-def popup_error_with_traceback(title, *messages, emoji=None):
+def popup_error_with_traceback(title, *messages):
"""
Show an error message and as many additoinal lines of messages as you want.
Will show the same error window as PySimpleGUI uses internally. Has a button to
- take the user to the line of code you called this popup from.
- If you include the Exception information in your messages, then it will be parsed and additional information
- will be in the window about such as the specific line the error itself occurred on.
+ take the user to the line of code you called this popup from
- :param title: The title that will be shown in the popup's titlebar and in the first line of the window
- :type title: str
- :param *messages: A variable number of lines of messages you wish to show your user
- :type *messages: Any
- :param emoji: An optional BASE64 Encoded image to shows in the error window
- :type emoji: bytes
+ :param title: The title that will be shown in the popup's titlebar and in the first line of the window
+ :type title: str
+ :param messages: A variable number of lines of messages you wish to show your user
+ :type messages: *Any
"""
# For now, call the function that PySimpleGUI uses internally
- _error_popup_with_traceback(str(title), *messages, emoji=emoji)
+ _error_popup_with_traceback(str(title), *messages)
-def _error_popup_with_traceback(title, *args, emoji=None):
+def _error_popup_with_traceback(title, *args):
if SUPPRESS_ERROR_POPUPS:
return
trace_details = traceback.format_stack()
@@ -22665,7 +20919,7 @@ def _error_popup_with_traceback(title, *args, emoji=None):
error_message = line
break
if file_info_pysimplegui is None:
- _error_popup_with_code(title, None, None, 'Did not find your traceback info', *args,emoji=emoji)
+ _error_popup_with_code(title, None, None, 'Did not find your traceback info', *args)
return
error_parts = None
@@ -22679,44 +20933,22 @@ def _error_popup_with_traceback(title, *args, emoji=None):
return
filename = error_parts[0][error_parts[0].index('File ') + 5:]
line_num = error_parts[1][error_parts[1].index('line ') + 5:]
- _error_popup_with_code(title, filename, line_num, error_message, *args, emoji=emoji)
+ _error_popup_with_code(title, filename, line_num, error_message, *args)
-def _error_popup_with_code(title, filename, line_num, *args, emoji=None):
- """
- Makes the error popup window
-
- :param title: The title that will be shown in the popup's titlebar and in the first line of the window
- :type title: str
- :param filename: The filename to show.. may not be the filename that actually encountered the exception!
- :type filename: str
- :param line_num: Line number within file with the error
- :type line_num: int | str
- :param args: A variable number of lines of messages
- :type args: *Any
- :param emoji: An optional BASE64 Encoded image to shows in the error window
- :type emoji: bytes
- """
- editor_filename = execute_get_editor()
- emoji_data = emoji if emoji is not None else _random_error_emoji()
+def _error_popup_with_code(title, filename=None, line_num=None, *args):
layout = [[Text('ERROR'), Text(title)],
- [Image(data=emoji_data)]]
- lines = []
- for msg in args:
- if isinstance(msg, Exception):
- lines += [[f'Additional Exception info pased in by PySimpleGUI or user: Error type is: {type(msg).__name__}']]
- lines += [[f'In file {__file__} Line number {msg.__traceback__.tb_lineno}']]
- lines += [[f'{msg}']]
- else:
- lines += [str(msg).split('\n')]
+ [Image(data=_random_error_emoji())]]
+ # make max length of line be 90 chars and allow the height to vary based on number of needed lines
+ lines = [str(msg).split('\n') for msg in args]
max_line_len = 0
for line in lines:
max_line_len = max(max_line_len, max([len(s) for s in line]))
- layout += [[Text(''.join(line), size=(min(max_line_len, 90), None))] for line in lines]
- layout += [[Button('Close'), Button('Take me to error', disabled=True if not editor_filename else False), Button('Kill Application', button_color='white on red')]]
- if not editor_filename:
- layout += [[Text('Configure editor in the Global settings to enable "Take me to error" feature')]]
+ layout += [[Text(str(msg), size=(min(max_line_len, 90), None))] for msg in args]
+
+ layout += [[Button('Close'), Button('Take me to error'), Button('Kill Application', button_color='white on red')]]
+
window = Window(title, layout, keep_on_top=True)
while True:
@@ -23078,6 +21310,7 @@ class UserSettings:
# rvalue += '\n-------------------- Settings End----------------------\n'
rvalue += '\n'
return rvalue
+ # return str(self.dict) # previouisly returned just a string version of the dictionary
def set_default_value(self, default):
@@ -23174,6 +21407,34 @@ class UserSettings:
self.read()
return self.full_filename
+ #
+ # def merge_comments_from_file(self, full_filename):
+ # print('--- merging comments -----')
+ # merged_lines = []
+ # with open(full_filename, 'r') as f:
+ # new_file_contents = f.readlines()
+ # current_section = ''
+ # for line in new_file_contents:
+ # if len(line) == 0: # skip blank lines
+ # merged_lines.append(line)
+ # continue
+ # if line[0] == '[': # if a new section
+ # current_section = line[:line.index(']')]
+ # merged_lines.append(line)
+ # continue
+ # if len(line.lstrip()):
+ # if line.lstrip()[0] == '#': # if a comment line, save it
+ # merged_lines.append(line)
+ # # Process a line with an = in it
+ # try:
+ # key = line[:line.index('=')]
+ # merged_lines.append(line)
+ # except:
+ # merged_lines.append(line)
+ # print('--- merging complete ----')
+ # print(*merged_lines)
+ #
+
def save(self, filename=None, path=None):
"""
@@ -23201,6 +21462,9 @@ class UserSettings:
if not self.silent_on_error:
_error_popup_with_traceback('UserSettings.save error', '*** UserSettings.save() Error saving settings to file:***\n', self.full_filename, e)
+ # if self.use_config_file and self.retain_config_comments:
+ # self.merge_comments_from_file(self.full_filename)
+
return self.full_filename
@@ -23260,6 +21524,19 @@ class UserSettings:
self.dict = settings_dict
self.save()
+ # def as_dict(config):
+ # """
+ # Converts a ConfigParser object into a dictionary.
+ #
+ # The resulting dictionary has sections as keys which point to a dict of the
+ # sections options as key => value pairs.
+ # """
+ # the_dict = {}
+ # for section in config.sections():
+ # the_dict[section] = {}
+ # for key, val in config.items(section):
+ # the_dict[section][key] = val
+ # return the_dict
def read(self):
"""
@@ -23310,7 +21587,7 @@ class UserSettings:
return True
return False
- def delete_entry(self, key, section=None, silent_on_error=None):
+ def delete_entry(self, key, section=None):
"""
Deletes an individual entry. If no filename has been specified up to this point,
then a default filename will be used.
@@ -23318,8 +21595,6 @@ class UserSettings:
:param key: Setting to be deleted. Can be any valid dictionary key type (i.e. must be hashable)
:type key: (Any)
- :param silent_on_error: Determines if error should be shown. This parameter overrides the silent on error setting for the object.
- :type silent_on_error: (bool)
"""
if self.full_filename is None:
self.set_location()
@@ -23330,7 +21605,7 @@ class UserSettings:
if self.autosave:
self.save()
else:
- if silent_on_error is False or (silent_on_error is not True and not self.silent_on_error):
+ if not self.silent_on_error:
_error_popup_with_traceback('User Settings delete_entry Warning - key', key, ' not found in settings')
else:
@@ -23342,7 +21617,6 @@ class UserSettings:
# del section_dict[key]
# del section_dict[key]
-
def delete_section(self, section):
"""
Deletes a section with the name provided in the section parameter. Your INI file will be saved afterwards if auto-save enabled (default is ON)
@@ -23536,8 +21810,7 @@ def user_settings_set_entry(key, value):
settings.set(key, value)
-
-def user_settings_delete_entry(key, silent_on_error=None):
+def user_settings_delete_entry(key):
"""
Deletes an individual entry. If no filename has been specified up to this point,
then a default filename will be used.
@@ -23545,12 +21818,9 @@ def user_settings_delete_entry(key, silent_on_error=None):
:param key: Setting to be saved. Can be any valid dictionary key type (hashable)
:type key: (Any)
- :param silent_on_error: Determines if an error popup should be shown if an error occurs. Overrides the silent onf effort setting from initialization
- :type silent_on_error: (bool)
"""
settings = UserSettings._default_for_function_interface
- settings.delete_entry(key, silent_on_error=silent_on_error)
-
+ settings.delete_entry(key)
def user_settings_get_entry(key, default=None):
@@ -23698,7 +21968,7 @@ def execute_command_subprocess(command, *args, wait=False, cwd=None, pipe_output
The function will immediately return without waiting for the process to complete running. You can use the returned Popen object to communicate with the subprocess and get the results.
Returns a subprocess Popen object.
- :param command: The command/file to execute. What you would type at a console to run a program or shell command.
+ :param command: Filename to load settings from (and save to in the future)
:type command: (str)
:param *args: Variable number of arguments that are passed to the program being started as command line parms
:type *args: (Any)
@@ -23783,7 +22053,6 @@ def execute_py_file(pyfile, parms=None, cwd=None, interpreter_command=None, wait
python_program = interpreter_command
else:
# use the version CURRENTLY RUNNING if nothing is specified. Previously used the one from the settings file
- # ^ hmmm... that's not the code is doing now... it's getting the one from the settings file first
pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program
python_program = pysimplegui_user_settings.get('-python command-', '')
if python_program == '': # if no interpreter set in the settings, then use the current one
@@ -23801,10 +22070,10 @@ def execute_py_file(pyfile, parms=None, cwd=None, interpreter_command=None, wait
def execute_py_get_interpreter():
"""
- Returns Python Interpreter from the system settings. If none found in the settings file
- then the currently running interpreter is returned.
+ Returns the command that is currently running. Previously returned the one from the system settings, but
+ have determined that the one currently running is the better choice.
- :return: Full path to python interpreter (uses settings file or sys.executable)
+ :return: Full path to python interpreter (uses sys.executable)
:rtype: (str)
"""
pysimplegui_user_settings.load() # Refresh the settings just in case they've changed via another program
@@ -23814,16 +22083,6 @@ def execute_py_get_interpreter():
return interpreter
-def execute_py_get_running_interpreter():
- """
- Returns the command that is currently running.
-
- :return: Full path to python interpreter (uses sys.executable)
- :rtype: (str)
- """
- return sys.executable
-
-
def execute_editor(file_to_edit, line_number=None):
"""
Runs the editor that was configured in the global settings and opens the file to a specific line number.
@@ -23927,10 +22186,10 @@ def execute_file_explorer(folder_to_open=''):
def execute_find_callers_filename():
"""
- Returns the first filename found in a traceback that is not the name of this file (__file__)
+ Returns the first filename found in a traceback that is not the nsame of this file (__file__)
Used internally with the debugger for example.
- :return: filename of the caller, assumed to be the first non PySimpleGUI file
+ :return: filename of the caller, asseumed to be the first non PySimpleGUI file
:rtype: str
"""
try: # lots can go wrong so wrapping the entire thing
@@ -23979,7 +22238,7 @@ def _create_full_editor_command(file_to_edit, line_number, edit_format_string):
return command
-def execute_get_editor():
+def _get_editor():
"""
Get the path to the editor based on user settings or on PySimpleGUI's global settings
@@ -24068,17 +22327,13 @@ def _mac_should_set_alpha_to_99():
if not ENABLE_MAC_ALPHA_99_PATCH:
return False
- # ONLY enable this patch for tkinter version 8.6.12
- if framework_version != '8.6.12':
- return False
-
# At this point, we're running a Mac and the alpha patch is enabled
# Final check is to see if Mac OS version is 12.3 or later
try:
platform_mac_ver = platform.mac_ver()[0]
mac_ver = platform_mac_ver.split('.') if '.' in platform_mac_ver else (platform_mac_ver, 0)
if (int(mac_ver[0]) >= 12 and int(mac_ver[1]) >= 3) or int(mac_ver[0]) >= 13 :
- # print("Mac OS Version is {} and patch enabled so applying the patch".format(platform_mac_ver))
+ print("Mac OS Version is {} and patch enabled so applying the patch".format(platform_mac_ver))
return True
except Exception as e:
warnings.warn('_mac_should_seet_alpha_to_99 Exception while trying check mac_ver. Error = {}'.format(e), UserWarning)
@@ -24145,28 +22400,26 @@ def main_mac_feature_control():
red_x = b"R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
+COLOR_SCHEME = 'dark grey 13'
+DEBUGGER_POPOUT_THEME = 'dark grey 13'
+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'
+DEBUGGER_VARIABLE_DETAILS_FONT = 'Courier 10'
class _Debugger:
debugger = None
- DEBUGGER_MAIN_WINDOW_THEME = 'dark grey 13'
- DEBUGGER_POPOUT_THEME = 'dark grey 13'
- 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
-
- DEBUGGER_POPOUT_WINDOW_FONT = 'Sans 8'
- DEBUGGER_VARIABLE_DETAILS_FONT = 'Courier 10'
-
'''
# # ######
## ## ## # # # # # ###### ##### # # #### #### ###### #####
@@ -24189,12 +22442,12 @@ class _Debugger:
# Includes the DUAL PANE (now 2 tabs)! Don't forget REPL is there too!
def _build_main_debugger_window(self, location=(None, None)):
old_theme = theme()
- theme(_Debugger.DEBUGGER_MAIN_WINDOW_THEME)
+ theme(COLOR_SCHEME)
def InVar(key1):
row1 = [T(' '),
- I(key=key1, size=(_Debugger.WIDTH_VARIABLES, 1)),
- T('', key=key1 + 'CHANGED_', size=(_Debugger.WIDTH_RESULTS, 1)), B('Detail', key=key1 + 'DETAIL_'),
+ 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
@@ -24215,9 +22468,10 @@ class _Debugger:
Button('Popout', key='-POPOUT-')]]
var_layout = []
- for i in range(_Debugger.NUM_AUTO_WATCH):
- var_layout.append([T('', size=(_Debugger.WIDTH_WATCHER_VARIABLES, 1), key='_WATCH%s_' % i),
- T('', size=(_Debugger.WIDTH_WATCHER_RESULTS, _Debugger.MAX_LINES_PER_RESULT_MAIN), key='_WATCH%s_RESULT_' % i,)])
+ 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')]
@@ -24234,7 +22488,8 @@ class _Debugger:
[TabGroup([[Tab('Variables', col1), Tab('REPL & Watches', col2)]])]]
# ------------------------------- Create main window -------------------------------
- window = Window("PySimpleGUI Debugger", layout, icon=PSG_DEBUGGER_LOGO, margins=(0, 0), location=location, keep_on_top=True, right_click_menu=[[''], ['Exit', ]])
+ window = Window("PySimpleGUI Debugger", layout, icon=PSG_DEBUGGER_LOGO, margins=(0, 0), location=location, keep_on_top=True,
+ right_click_menu=[[''], ['Exit', ]])
Window._read_call_from_debugger = True
window.finalize()
@@ -24292,10 +22547,7 @@ class _Debugger:
result = str(eval(str(var), myglobals, mylocals))
except:
result = ''
- old_theme = theme()
- theme(_Debugger.DEBUGGER_MAIN_WINDOW_THEME)
- popup_scrolled(str(values['_VAR{}_'.format(event[4])]) + '\n' + result, title=var, non_blocking=True, font=_Debugger.DEBUGGER_VARIABLE_DETAILS_FONT)
- theme(old_theme)
+ popup_scrolled(str(values['_VAR{}_'.format(event[4])]) + '\n' + result, title=var, non_blocking=True, font=DEBUGGER_VARIABLE_DETAILS_FONT)
# BUTTON - OBJ
elif event.endswith('_OBJ_'): # OBJECT BUTTON
var = values['_VAR{}_'.format(event[4])]
@@ -24307,20 +22559,17 @@ class _Debugger:
result = ObjToStringSingleObj(result)
except Exception as e:
result = '{}\nError showing object {}'.format(e, var)
- old_theme = theme()
- theme(_Debugger.DEBUGGER_MAIN_WINDOW_THEME)
- popup_scrolled(str(var) + '\n' + str(result), title=var, non_blocking=True, font=_Debugger.DEBUGGER_VARIABLE_DETAILS_FONT)
- theme(old_theme)
+ popup_scrolled(str(var) + '\n' + str(result), title=var, non_blocking=True, font=DEBUGGER_VARIABLE_DETAILS_FONT)
# ------------------------------- 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('All Locals', mylocals)
+ self._display_all_vars(mylocals)
# BUTTON - Globals (quick popup)
elif event == '-GLOBALS-':
- self._display_all_vars('All Globals', myglobals)
+ self._display_all_vars(myglobals)
# BUTTON - clear all
elif event == 'Clear All Auto Watches':
if popup_yes_no('Do you really want to clear all Auto-Watches?', 'Really Clear??') == 'Yes':
@@ -24363,7 +22612,7 @@ class _Debugger:
self.watcher_window.Element('_WATCH{}_RESULT_'.format(slot)).Update('')
slot += 1
- if slot + int(not self.custom_watch in (None, '')) >= _Debugger.NUM_AUTO_WATCH:
+ 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:
@@ -24375,7 +22624,7 @@ class _Debugger:
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, _Debugger.NUM_AUTO_WATCH):
+ 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('')
@@ -24424,12 +22673,12 @@ class _Debugger:
'''
# displays them into a single text box
- def _display_all_vars(self, title, dict):
+ def _display_all_vars(self, dict):
num_cols = 3
output_text = ''
num_lines = 2
cur_col = 0
- out_text = title + '\n'
+ out_text = 'All of your Vars'
longest_line = max([len(key) for key in dict])
line = []
sorted_dict = {}
@@ -24437,19 +22686,15 @@ class _Debugger:
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)
- wrapped_text = str(value)
+ 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
- old_theme = theme()
- theme(_Debugger.DEBUGGER_MAIN_WINDOW_THEME)
- popup_scrolled(out_text, title=title, non_blocking=True, font=_Debugger.DEBUGGER_VARIABLE_DETAILS_FONT, keep_on_top=True, icon=PSG_DEBUGGER_LOGO)
- theme(old_theme)
+ if cur_col + 1 == num_cols:
+ cur_col = 0
+ num_lines += len(wrapped_list)
+ else:
+ cur_col += 1
+ popup_scrolled(out_text, non_blocking=True)
'''
##### # #
@@ -24471,7 +22716,7 @@ class _Debugger:
def _choose_auto_watches(self, my_locals):
old_theme = theme()
- theme(_Debugger.DEBUGGER_MAIN_WINDOW_THEME)
+ theme(COLOR_SCHEME)
num_cols = 3
output_text = ''
num_lines = 2
@@ -24499,7 +22744,7 @@ class _Debugger:
layout += [
[Ok(), Cancel(), Button('Clear All'), Button('Select [almost] All', key='-AUTO_SELECT-')]]
- window = Window('Choose Watches', layout, icon=PSG_DEBUGGER_LOGO, finalize=True, keep_on_top=True)
+ window = Window('All Locals', layout, icon=PSG_DEBUGGER_LOGO, finalize=True)
while True: # event loop
event, values = window.read()
@@ -24554,7 +22799,7 @@ class _Debugger:
if self.popout_window: # if floating window already exists, close it first
self.popout_window.Close()
old_theme = theme()
- theme(_Debugger.DEBUGGER_POPOUT_THEME)
+ theme(DEBUGGER_POPOUT_THEME)
num_cols = 2
width_var = 15
width_value = 30
@@ -24571,10 +22816,10 @@ class _Debugger:
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, _Debugger.MAX_LINES_PER_RESULT_FLOATING)
- line += [Text('{}'.format(key), size=(width_var, 1), font=_Debugger.DEBUGGER_POPOUT_WINDOW_FONT),
- Text(' = ', font=_Debugger.DEBUGGER_POPOUT_WINDOW_FONT),
- Text(value, key=key, size=(width_value, h), font=_Debugger.DEBUGGER_POPOUT_WINDOW_FONT)]
+ 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
@@ -24760,9 +23005,7 @@ def get_versions():
Returns a human-readable string of version numbers for:
Python version
- Platform (Win, Mac, Linux)
- Platform version (tuple with information from the platform module)
- PySimpleGUI Port (PySimpleGUI in this case)
+ PySimpleGUI Port (tkinter in this case)
tkinter version
PySimpleGUI version
The location of the PySimpleGUI.py file
@@ -24772,40 +23015,14 @@ def get_versions():
:return:
:rtype: str
"""
- if running_mac():
- platform_name, platform_ver = 'Mac', platform.mac_ver()
- elif running_windows():
- platform_name, platform_ver = 'Windows', platform.win32_ver()
- elif running_linux():
- platform_name, platform_ver = 'Linux', platform.libc_ver()
- else:
- platform_name, platform_ver = 'Unknown platorm', 'Unknown platform version'
-
- versions = "Python Interpeter: {}\nPython version: {}.{}.{}\nPlatform: {}\nPlatform version: {}\nPort: {}\ntkinter version: {}\nPySimpleGUI version: {}\nPySimpleGUI filename: {}".format(sys.executable, sys.version_info.major,
+ versions = "Python version: {}.{}.{}\nPort: {}\ntkinter version: {}\nPySimpleGUI version: {}\nPySimpleGUI filename: {}".format(sys.version_info.major,
sys.version_info.minor,
- sys.version_info.micro,
- platform_name, platform_ver,
- port,
- tclversion_detailed,
- ver,
+ sys.version_info.micro, port,
+ tclversion_detailed, ver,
__file__)
return versions
-def scheck_hh():
- with open(__file__, "r",encoding="utf8") as file:
- lines_in_file = file.readlines()
- combined_lines = ''.join(lines_in_file[:-1])
- entire_file_bytes = bytearray(combined_lines, encoding='utf8')
- cfileh = hh(entire_file_bytes)
- return cfileh.hexdigest()
-
-
-def read_last_line():
- with open(__file__, "r",encoding="utf8") as file:
- last_line = file.readlines()[-1]
- return last_line
-
# ==================================================#
#
# MM""""""""`M oo oo
@@ -24890,84 +23107,18 @@ EMOJI_BASE64_MIKE = b'iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAkzklEQVR4nM
EMOJI_BASE64_SUPERHERO = b'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'
-EMOJI_BASE64_BLANK_STARE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NDMxMTQxQTEyOUM0MTFFREE2QUNBOEEzMUIzMDUzQjMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDMxMTQxQTAyOUM0MTFFREE2QUNBOEEzMUIzMDUzQjMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqFWMWkAAA0HSURBVHjazFoJdFTVGf7e7EsyCVnIBiSQAKIVRUCM4sI5QjRqWy0Ug8W20oCHKmp7DgqiUHsOLmDrwaVo8dRIlWrdlaUI9SCxoBCBVAQEA1knG2GyTCazvHn9732TmXnMkplJgr1z/nPf3Pvevfe7/3//7T1BkiQEF0EQMJgyOx3TqbqOaBrRRTRcPk0xIty91NdEfbV0+Q3RfqLdn57l/4esCIMBSGD0VK0nuo/9LyZIt5UAE4uAJLMAQa0FvB7q8UYdR6TujnPAYYK5+W2guZWD76alrSTAL1xwgATsAaqeu/5qYDlB01rGA+m3AOZJ8g3dh2iVFYTLMajdb20Hli6n4XrgpGXOILBHhhUgASulaus9dwF3LrgIGEXoBK3c6ekC6p4C3Gcx1IUt8aHHgWMn4KXrFALaM+QA52TgNIlewYYNU4C8ewMd9qNAwwYMd2HLPHgCWLWarr1YTSCfGDKABM5d/miBpnjuejjUI+CAEd2igM01R9CMLHQKKXBDi24kw4ZUdAkWOnUq/mwfDHDyoxpaUtDpvzZLdhrBTU/bOJlhR4rUiZFo5f8zpTagvREWewN2v1aLpuq2jwnkjwcNkMC11b/5dcaDl07xt+20Ae+24wctc16+BdL2bcsJ5Lpo96kGUCbLtOWLM5YFgTvT98OD45u8ZCsktfYZWqMuYQ7Sw1L9v0hX5zmQROeaidHbJ3cjF01Il84iDR0klN1IlWx+0WLX8s55YUFXTItlT7LCRL9HSCLhNMujCfKoHTSTVchBGzJx0pGNFk0erNp8mkGN635m7tjZjvRIY2uicO+hhT8HFua8EjBjPdWYI74Ycm+PnXRNL1fnqKXaTv8dfbJ9Y30RxYfkx2QEjAYb1HRtNtvIfgI5RBOS5L7zSwMd25Zzgf+rVEijtapIVL1xAaTyp4XzzmtpfBEnTgH3r7jwImkgPfXB64DFrAS4pBx4aSPI6GJhXAD1ekiwzAjIKxntfQeB1U+Tmtbo4MyfDElnuCDg1D0dQP23uGk+sOMtZd/o0bz6RSSAqgjiuejXZRCQdlOgsW4dB+c1JKFv/JXDC84rwt1YJ5O1AaKZTNOkmbxrfnmYDVDHqUVJzyy/nfks+lx/26GDjbx2jr18+FmmUkOd4vPPvV64m+p57coZj84wemv2jZwpJTEDJMU6QWEOu77E2ucu7JlTJSUr/rubGyGmZvHrw+d5pJMn8+qeuO2gv1j/xnfOkz7qAoO0KH01X9m+Q3nfiFQudT+JWcnomelUBdwrp0se3J05Jow8q3Dg4X/CmTJS0Txm16sYs/u12KKGK27Gd/NWKtpSv6/CjzY9CG9PQCa99m540nLR1dEUTur0MXGQZFkoHMug+85A+4fY+mkATHBxpmajcu2eEHBcJ924CPvW7BgQ3FcrPwwBx41/4VRUPrkXXl3AGIqdtrilKJyIFuazMbRp8r+z27BrT/iHGeeiBrJ6M/5bHjnSOPqrdXAlp0Ud48Cm4wo2MRPFSm1t4gBzM9ic6mR/JH7qNF3pTYqbam5dFtMEneOmROw7N/Gq2FRA6eKQthPfJQ4wzWxmPSQaLVsC8m+yKG5qumZezGJiK7wiDLjiWANW1M1fEaJszgyCgz7rSQBtnwfGJXFjlkOIWfUGSm/WuFD/NXd8RECMVGT3GPFrSZ6TWy5RlBVTa2xzh9OiNuY4s7DZPykjtVaeTPBNFEdJajwe0mZqqQkLTAAD5PVf93NNTdfUCoFAg9bSa3cnzEFbD8t42D7zDe7jmsB2Q4KGJtcSFe18JWaAltpvQtrSv61UgGOg1JIIreiGTnRB73HC4O6D0e3AuHfXU7QvcWJA1f2bLCUG8KSVsd/rkgfwiYfG44ba6aDokhkcLy7596sxgcuq2hYZ+JlqPzhGGtHDAerdTg7M5OolIoDbN0IvEEAiDZHa64G533pIcQKkuMpe1xD0INVsxzQ0kaa3BwYCZ6LFmInmPzYz6uDGtjpMeOfJiP2XvfxbaJw9AXBeNwyePpgJWDK1W5zduOaJW2CmQ2iiNRgJnJ5ESU2bkpnBOD8wyLD6oqk56EEfB3WOTgqhdNARJw0QYSKgKbSQ3zw8FaOO7Q0ZY3LFckx/dsGAHC5eczMKdmz0i6fe4+Lcy2g6gWufLUPyuRYwA2UQZFdFRwA1BLZgtO/4SPErmZDCBrM22iEZjBDamqAbmcXPo4p2UiQnsOS1B+GkU+EQ1Lx20Za4yesRY7IDwKi9/8C4vVtI/L3QEzeNVDNJYXOwn0dgekagFonvOTt/F00MiYBOJexsz5kVlGPgOd5O2RyxkEPyMzqY6YPItQu+cUiHulzKcalPoPPJSn5+UKLByhXth/EA3Ot0Bf6UUrwlSiwO9cBFnHH29aHPbidu0TX9d9NiPHQtv4UQ4Ffwsbzn8G0UM0oiPce4zrjP/Ptemw1O4hwjZhS8ySkQ2htkyfAZZerCETl8eiMeEf3r1l249o5SeRCSPHjYWbTWQBpZALGjDU4ylgKRlxYn6fXwaPRwazTwqLREpMwZ+UJtjyEpCBAJGrNzHg80jh5IZLgl2jgvnT3R7YKHzriLaUzmazC753MYOShTEtQN3yI7TwbWX/bt58rxUMwA6ebNKe/idQ7Qx+MZ04EvD9jg0hn4eZD5xESDDLDDSQsgkoQgLsrM6c0tQvXq7WF3ccbd+UHekcSBsGdZ7eHtvjkY6XQcqY7+zJ8f4B7fQE8CSqaz2zezJINc8RBwaxmLyTrhzcqD2NLoczLkWbx+CoBjZGw6xYFEk1AoniOgNKYqWMJZCiM9G/qaw1ySSFL94Fh6kgUdiWS2K9nrKwayijz3ZhvA0iSq+mMQWsnTzc0ncSWgWh0/H25+fuTdj1fR9N/ffw49kM+caEzi84A2VPP9IXjIFv/09iDxpPqjT+TsYdyZbQp800fnof3V52SA/St57wPg4MGAxnNnFvAom10zrSc6yJz0OSBFk5twCyERVBlNnAS1hmtLbXsd1LYW/z2LFlGwOhYKZ3jFo/xICXGLKD10dnZ/+iCJOajywHfQDpaUCli/WY2+WlIUrac5+blBZ1Q0pXKNx1KMks4YhXXkopH7p3J0QWW3Qd1xmqcMFcCNAoyFWqwqc4U8flze+HcGY+gvvXMxqt/YCOFwkBnt6BGgTVcjc7QKS0tcPIKprpazXd+d7CO3jlwhW3PcJlBLqnMyxcdTLidO+SKste9HfrdSUcEZMS9hgPTwN8TFPS9swg0zbwgKfwyyWFtMkj/xOmWKTOGKk2xzby9LXhEIDc+aw2Ty+w0JldV/4Md2wKh5QFeNQM4SduFoczsunjvXl6Yzy8BabLGtkAHS64cunfjYGjribtxDa/sy8Yg+qOxsxyVVh/AYO9AdvhcfehInpwfDWmx2WXeUXCZPVPW1rFQIXBGBiyknGe9HCKz7OMt8M2O77Xs9JuR4Mfcq97AAXPu+novxZXonPpcDlucJ2LK4tHOi38kQ2Pup+jM7gmNJdU+bJiuGFMvgQDU3M0VF7tcBQbKdldhy6mmJCwhYZUK++1B86URgmdPJPgi4jR6fSUOOT2AtbCFfEbFM10eJAhoWgAOVG7N0Envlpoj2j1VGNdBDVYYFIHu/CPml5FjfoPn9GWn/PHJc15/dZCm2CgJc8X8LkECtouqPzGVLn1wMS+ElA8aD7e3t6OmRP1rSed1wHtnD3wMyD4zAPvWDALx5JOqoGpWbDTE1BZouO2AlxSCpDMgrvTvuBYjkBtXX1ytzzkf3kIF2IieLIgczcK4TnqZmnvuq2d6KonjG18TJpXs3bJw1umjWavb5lgZt7+EYCVkvSdvja5wJ7bCa3KCCggJYrVbyeOQxjFoXVj5C3g45B5PyA+v8zwEUep5BGXF3y2DeLkUrfym6agFwiPw2AseKbwFwuweViUFOTg4nVrq7JcXY/eXq6bx6c1g4SNyb+vvf0YzHy8NzQhP6JYBGLWHD0v3yuwiHFss3TYNVn46PMwP51LLmT5Hs6fW5dHpkZGSgLco6fsmi+bcwkbh4Ykg5SEezsqQ48isdY67yBYtRJ/rBcQfd6MYL9+2HS6VV3LclezacQW1msxlCambEee6ay530r4ZcRMeOCf+KmH3N1NBEAMYoz/6zS0LXoBIkfLLofVx/TpkfqsgtVSq5tBzSsKRQI0j9yAwkDSlAEs8nn348vFFupIV8XUUcyxrtbxuX0+2/7urVYunzxYq056qpn0efcEQ2d6ytEb6tXbcGKlrTiqHk4CORfMw2G/mN5wUtycaA820xufHS/fsU/dU1IwaccO8X5Jd2RHihI0vw2iEDOG2Ab3/CKZiIoVdVHlZ6yxRtc1s+U/w3GAzwitHt8aQJQySiJAqfPLA4fF9dK/j3M6kXXxnTZHuqs3HHmSUKpXJr2xcwiX2K+0ws3M8p5FmAxgjfpj5Qztf294Hm/J8AAwB+bzEl4qNO1QAAAABJRU5ErkJggg=='
-EMOJI_BASE64_COOL = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NjU2QUIxRjUyOUM1MTFFRDk2Nzg4MjA4RThGMEY0RDUiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NjU2QUIxRjQyOUM1MTFFRDk2Nzg4MjA4RThGMEY0RDUiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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'
+EMOJI_BASE64_HAPPY_LIST = [EMOJI_BASE64_HAPPY_STARE, EMOJI_BASE64_HAPPY_LAUGH, EMOJI_BASE64_HAPPY_JOY, EMOJI_BASE64_HAPPY_IDEA, EMOJI_BASE64_HAPPY_GASP,
+ EMOJI_BASE64_HAPPY_RELIEF, EMOJI_BASE64_HAPPY_WINK, EMOJI_BASE64_HAPPY_THUMBS_UP, EMOJI_BASE64_HAPPY_HEARTS,
+ EMOJI_BASE64_HAPPY_CONTENT, EMOJI_BASE64_HAPPY_BIG_SMILE, EMOJI_BASE64_PRAY, EMOJI_BASE64_GUESS, EMOJI_BASE64_FINGERS_CROSSED,
+ EMOJI_BASE64_CLAP]
-EMOJI_BASE64_EYE_ROLL = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzlDNDJCNTQyOUM1MTFFREE0NkZBRDk2MDIyOEZEQTIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzlDNDJCNTMyOUM1MTFFREE0NkZBRDk2MDIyOEZEQTIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PpNdYAgAAAwySURBVHjazFoJdFNVGv7ey9I2SZN0o7SFrpQKVLDIJurAgBVnVBaHmeN+jgIDis44HlwKuA3D5jgiwgyK24g7oMAwbiAoUGSxFQqyjIVWSjeS0iZtkzTrm/+9lzZJs7RN0+o95+a93Pvuffe7/3////vvfQwinAoTMJQuUyiPozyCYZDJcRgQ6Fmqq6O6n+j2B8qHKe/ZfRkXIjkeJgKAHqWBLqeBRmdlAHfMAkYOB7QagJXIBBRw2UL24XQBjU3AsZPAps2ATi80M1CfjxHg1/sdIIEaQwP4NiEO0nUrwSQkJwCJMwD1ePGBtiqgdiNg1/dq8mrqgIVPAJY2GAlsAYGt7FOABExBwFoKrgS76lklMHgREJUqVnIkhpr1gOlUpLUeTiew4DGgqhpmAhpLQF0RB0jgnmBZrPr0IyUkQ5+nllKxwmEEKp8iNbSiL5ODQB49Azz7nPD3NgK5LWIACdx7GfnaO59+dRFc6jEwQwELYrClsgQ1DiWaoYaB0cIArVBng1z43574MjtkPn1Gow1R8EyKljNQjxahTOiJM4hXykmcHsm4BGtdHeKt1di6upxr0ZmLCOTqXgMkcPfLJ096Y8rab6CSiGVNDuDJn/CzpsI/ZXKoujCRQB4OGyCBYziGdSUWO/Frjad8/jn8IlLhTAYEkAkb4I2JOF+yVZ/9fF4cYtFCimbGnqoScG2VSOHqBLXhVUjFtUIFT+bVq0P1YAg5SF4JO+5JrY3QeHpiVPTWWNQiFTpmAOoxEOWWgdDL0lAry0SG4Rhy7hu3g0DODNa/NNTLyWJlX9beQwZkVkfZLab5fs/Z7UBzK2BspkxXPf23k+trNXueaTX5tlEpPRBVClqT0YBMSnBjgXQ1eRwVIJH4j+lHHdDi1W8RMCMUBmkI9Vy2+BG6SfKAQ/0muMhAz7yXXJ21f9UxngT94WsEXOEL8MZC+tmN35EUP+6RihJAbtcWusl71SPRs/Mx7Q/ivW3wcDhV8f0CTmLUQV77o3C//V3gTCcyt3gpzLsaoAzUlg3ZszzFc2+pwO3z3LfDrutTcBx5dntNlZjra+DUDBDeyadnVgZcSopgfbFBpDdk6q94C3G9p7B6DZrIp9tSh/a5xBhafKxa00FjeKCCs49PQ1kAopQ2SLT4PZHg/Tfx8UDs6I6C4kMiYeZns1/UMlbja8hIkvbkLOG+4bLvs+PHCpffdxsg8c3po0bwJihOLLj8OTZu6n8/xyqUvoTUnb74wve5IbnC5dZuW1HS6RE+BQ3bUU/m2RGXEkSnGJQt2ICWdE+zzM83YND+97sFpJHW1+l7VoihFaUoox4FL90DqZaDy+zxL5y1DS6FGqdON/u0j9MITW/quZHpTHgTB/uVtZA1Pfz0Zz7g+NScORLFK/Z12eeRJTvQNHRsBzg+WTVJ+GHuWlRPvts3qjAa4EgYFMxnJ4YHULcF5928k5PKO0mOxan7XsCE534DTWWZT1Xux6tw7VM34NBzu4J2fXLeWozc+DBydqzxHZS9DVetnwtjdgHaUrI9IIg9tFtvL40NreZdPtH0FY5+H7iq7IFXMGHZzcL9lRsfQvZ/10Fb/h3Grp4NmckAxmnHwKM7YVdqAra3ksrH6EULOfHpGxB/5iDSijfTfaFQNuKtRShbtTdg23Pd5MPS0A5JjCtP/S9wdcvgYYJutKfUg5uF7J2yPl2H8zMeJSm96MtBc65G7taVXlKzYvimJ/3eEdVYG/DdF2he8vJ6K0HdB6ILrOmdNbQkpQcoGwxlXddiUNaW+y02Pun1kVBRw37hYmyhfllpeNsN8hioK4/7lat/OoHGK67psr0hb0JAgCZzpNZgiDTwyHbY1Ekhnzk5fz3S977tL5n6CpTPXtK1w28z9c6XduehGAplGJeTlqSv6Rqy/R84WvRJ8NnPGQ2pyeizTr1Tzn9eROXNDwVt/+1fd2PM0kI/nyusTXkEAQ4SNs44Inv+dO/aJZNQvPIAdAU3+gzihzlrUHXDHOS/+WgIDdhBxsWGkse3kCpHe3xoRr7Q55gX7qTg2hwQYKK/13N124pSHzzx7Jij4WStjvN7zywLZ1MDJHGe3hkKEK8rul6wimUPbICNuKqm4jiGvVMEia2ty8nL2LURGbtfQwVJ8vKIX0FKgNIOfCj0KXBQqyVwuwy/ou96QtX2UZReKHNvhI0nzv2+O5x0mc0E0L+N9nwptBtKw4yPOMGH8tm/LnCToblecXi9cNnfExXdefSY588wd4TEkK/itdReV90vZNtl8VVPRiqFpLVRDFW91mC56El29gTge7u+9i+U6S9AotaC37dw6Or6Fh1J1dnY4GtRtfGQ6vzPZg4fBb+7dqDbKkoPN6LEt+wKUomz5TqwFPDypJcjHRYCUZIoG60AQ1PKyOTCOuV3ixhWEkI0Lho/6R5vmXlSSZnnmWK2B7W6TFQ0WKsJ48d1ikYaw6VqXmkpGcO7HxDpG68qnMPRsUYEVbKY+1SgbEwMGJtocKbf6mcUXeG4iZ2XvOjQALfhjCIGIk1OFSXVT4mRSiCJT0KUO2LxfjW//kjgy3u88VuYgEGj8nHx788Ap0ntleSmSkltX/k3SSxaBWvWVeJapHXCB6JB471Noc8zx9+bEVJq7S4p+nyJYOTmzQWyszzPLF8FtLZAEuzEqaute2HrsIbWer1bz8tOAB9+5B0Ep8OeOEiIDTmbVVBXjs/dDdi8LCQToyBQCmEtM04HpA1VkHpFEwv+6O//ipYg5PZ9V2vwjb3FmHP9BA/AUSPFvOxtGSwV7kE0VHmMH5FrpyoOLrUGrphY/yC5MzCHDay5mbIBEl0tSclXG9goBjE5Miy9y/+U+CsxVHw47HiQZmYu1mLOlOsCkGA1C9VVciyeZRV2u8toeRyjoKH8nIVmnYxBkDiuqzSMQszRpP35+eL/FdvkwbwI9uwRxrg+/IBXTBNm3ItDL60G09gSZK3Qoi8oEHOgZCS+bTYLR9GCLvHnECoVEBsbvuFZ/JQYY/eabNMMHbFYsPCRx4ORpq6TRgOkpIjGIStLvO8NuKKlgnuaSmOr6zVAN8gNNPsF/II+696+mJgnGhGbo+/cg65ZtB2zxtmFa+n3olEhcGk0pr3dMl49fSlZVv5IZvYttwD76qMgJyVfdGvfHDWt2BYFcoEYrbRijwjnZQL25x5Z53BfTkBvJwbxlvB9TC6DcQUccoeQv1T2DhR/xsg778OlDGoucO3fy9xBwL4IiyREYqYJLE88+bOBGTSgyTSggWENhkEVteVp/nYCtD0iLKg/qBZPGNqPvzq2Qc4Ud3m+/osFyH8J5XbA7bxjkkvhu/nLmo38pX1vnw9ZNxHgz36xAAnUVLq8y2+1qNJzoR12NWQqdcg2er0eJpOJVJOBjMIg68mDvInkLdY8AvvOzwKQgPCSeTlKDlesCi5yjmxjE1iGZZA+fQ5R0p5FGU7irBcvXvRlSacPwEHONz4eHHXL75LAbIGEut76pT7wOWCv40GvHbaX3jxYSk7qIxZVz7MV5GqbiOEc2MfhTBghlISC48zMTNTW1sJmE/mmOqYNj5Ezj5KByc9CR+T85vuY7dqGHJLu+Yjui7anaUnY9cb+YhYlV4PACWXZxEriiZWcON0zZXB1Up7U1FQkJye7I3TBPSA/y7fN/XcKlvZ0n0mQBDSVOTXbr9xKRKO6mkPWeP82ax88ApnERYScwUP/nACDLBabk6d01N926Rsk2o2iZaX4LyEhAQ0IumuBMaMg545DSlJ0RFSCtPbmrFlGz9vq/epMQeLdfz18SAAnTg4n/Oc6Se6T5MkwSTybvkpiCqwm+Bccf1ssTPTOvlDR1/OGBK9UpAz2AxcofbDgS0zX+W6AvZcyzUtLKHDWpqC5JSgZ4KV7U0QB8p9oXDMmcJ2dFOWSjsKfjCuCtn9w3TVwOD2SW/7b4tAvTEhBGcWWuiCfuS1aKIxpbCQl+OLivwSuqCJwpWRUlWlZQRvz0pRKPIvq+LmELpwXi68PEBcNcgZYOImMhxQ7IgnwkWCnOYZWchHF3dfzExXxWNhwl0/ZTJ3vrrtcLofFxAlONsS+cEpEAJIqsMODHBU73PtKckVMt8CdvajB5NKFaJZ6Qo5pl49A4fS1UgqFAhiQLnyN32AM3Ne8u4WxTezqnf8XYABghGAV33jD3QAAAABJRU5ErkJggg=='
+EMOJI_BASE64_SAD_LIST = [EMOJI_BASE64_YIKES, EMOJI_BASE64_WEARY, EMOJI_BASE64_DREAMING, EMOJI_BASE64_THINK, EMOJI_BASE64_SKEPTICAL, EMOJI_BASE64_FACEPALM,
+ EMOJI_BASE64_FRUSTRATED, EMOJI_BASE64_PONDER, EMOJI_BASE64_NOTUNDERSTANDING, EMOJI_BASE64_CRY, EMOJI_BASE64_DEAD, EMOJI_BASE64_ZIPPED_SHUT,
+ EMOJI_BASE64_NO_HEAR, EMOJI_BASE64_NO_SEE, EMOJI_BASE64_NO_SPEAK]
-EMOJI_BASE64_OK = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREOTYwNDQzMkMzNjExRUQ4MTVBQjZCNjk3OTUzN0IxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREOTYwNDQ0MkMzNjExRUQ4MTVBQjZCNjk3OTUzN0IxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQ5NjA0NDEyQzM2MTFFRDgxNUFCNkI2OTc5NTM3QjEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQ5NjA0NDIyQzM2MTFFRDgxNUFCNkI2OTc5NTM3QjEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz67w/ebAAAYJUlEQVR42txa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'
-
-EMOJI_BASE64_QUESTION = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QTM5RTlGQzYyOUM0MTFFREIxNTdEMDBGMzhGNjVBNEIiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QTM5RTlGQzUyOUM0MTFFREIxNTdEMDBGMzhGNjVBNEIiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnJxYvsAAA4ZSURBVHja1FoHdBVVGv5mXkvvPSEhCS3AQhKaIihVwAainkNZlgUpIiKsrsdVlC4oqyyIegDBguBh0QSQIiR0UVoIgUVKICQhBZKQkPZekldm9p+Zl1fySl5I4jnec+6bN3fu3Pt/9+/3DoM/WRkZCAVdnqAaRZWlWkT1aHo5dPb6M38SUNF0yaQa2EzXcwR0wJ8KIIGrpot3TWwiMpccgtY3xG4/z8JreOSNZLDaeuG2MwG91eYAiRhvuoyg+gjVgQyD3jwvtjks1EdLfdLo7w6q3xNhvMV4e6jDc+mpBrGjKyVhwxxEHdwg/GWFsZhWgPGlyyKadx4RqPD2Aia/CPTpBYSHAkply8a7Vwps2QacOC3enqT6lCByld0Gdj//4a8tGmvoJF/INdXZBLAr00JQwQToEAFKmvQCMHE8oAroDfgPBXQVROXWNpGE67nAeyvA19SgnuZyT9/Nt+h995JcDJodBwLoGt8JmKC4Z8aOAeZOp1fCpgC+j0kPizcBNRfaXPcu3waqa4Fly4HDKVrwMgV6rpuK8GPWi1jVZQDOrT5jS/M4RgQobwaYjJagNrEn3D5aTsoduximV+58AtRlPzSAO0w0WYFOyGHicZuJw23EoZiJQAE6iFddV4XY7/HAKIx4wSTvAisnEOE7jfQF+mafve+Efk+5k4eD6PJLyjcyeCWuI2DShCglW/DgmN13rjA9kcH0FesFpg8uMklogKpVnDy5pRABlw6j39EV4E6ceFMAR7QJgz5rNEwOC/VVMw7AjXV3x649ex5jEPY3sU3DyZCacxxHmWE4xQzCTabzH+4yhr/kBlbXYLovGzAWWe/stumnqijG49Mj7esggYvkvXwKOqXfZ5K8Ja4V0ZjLCtqOUE+o0ZO/gng+B7HIRSxvrMb/luWChRacINt68BBxphmjM3SyP+TqynwC2NGeiBbW7KlCktF7cXANnBvq0Ye/gP78OfTlM5DMZ6Ibf91l0NU1xJFy4DRpVEQYEBMltbPEAs6Ih6xqsyV56WgBnPA3VviRN+HeEu2aLZgeam5bmi9du/NXMYw/isH8L3icO4kw3HM4SRURcous4A5iRi69n3cHyC8kQrmWcfofrwC9E4G75c33DcxKQ/KSUY23wY0BQ1MOLh7eDXiG24cIFIsNszSzrTqQX8LvNyi6/R24eIUMyzXAYGieAF7pBk7pAV7lYfzvDl7hRtW+EVIWXMV/NlTg/TcBjwCjlLjZH/uRBYnwzrsEYyQ02fKZ3IJ7XtGRwPtBOXSnN8pEhnj5ajtxY7cDwolAztMHnAdVd29wbl4t1kmeVkh/r8h0z3r7QNuhO1S5WVj+SS1WfeDSMCeagmvKwaWvzxKWKcYifvoWk4iB9ylIMfgEQRfcUVz9ti6MTAZ5aDj0JXclva+pBq/TkhYlwv3aKVwjKUlIcByOMrxj2ZdbBL2v9+reJJq4ohXB1cf3IWDu7eoCGLkCDAWwvFYrcbW+3shOGb7bbsDKFUAvinMPHwGi930KPUmM+FivhVf+/4S/O50CJN2y1sf6QixZLSFvb3AmYoLDoCu6Y7rXl5eiIboHVHmXJcsRBDwq5Cmb5zd9dT+J5xf2xmQd3pbtRK2aJgmI+GO9OWumQeAi5y5x6shRqe00hZ11oXE4srOOqgYNgZFC89MOhzNZLcGnsxYWTXNDWsWAyHbFw5MIqsM7i1eRiwFB1s9JF3kSXwGgoItCObUxh6ywZImFUM5oJEc5FdHQEFHbzd6+2DiBXNlOSsfg1xXHTMDEJs6AxxYOsepmqKwQjZvy7k2UlDodkTQUhxxy0F9IXxnjbU0mzma2rySe+uCEFbhGbp5aedK6jYyOwU+KPJKTYDIsJgDausa/XzrloDSa0dyWH8D1m+0HrsEvzInNZ6ALiYKitNDmUW6eJGnDX1ShOj6ZOM7Bm3wllfNkZCqd6qCmzpKCAhTdbT+AlfFJzuPS3kNhEz5RuXkLWEAGdPZM4C+6zEZwAwhc/2b9oBDsgtebHtTUOieynhJRTUgMNKGxUFOtC+lI97HonPIhgrPSnL7rXeg8CPemMM1asKRYsNhoFzp2BF6hAOSdhWLOd86p62n8UyrkxRzJtvqq08kruj2Kq1NXO3xuUDXvMz1Kcp0/Ly+C3rKBRJFn5XjwQN9yr2N9SzpYIRkibwebfQHXTzsdMPT8PpcmHrhopON2e+pJ4VxjcNOi4MGmRSOJT0SolPLYK8GXDqOs9wibdr+cTNHUu7SyunoMemcw+cBOqIpLhm9OBjzv3TaKJGdjeISUxc2tdQA5S44mdAFOOmBW1x1L4Z99FtkvLTS1xe1di4jfUlqe3d+9JVYrOWposMZH0Q3D6eHn2zqAeyg0e97L0ygq/YCN3xonrK8D62atWyGZB8XaHoVTN0ndjf4yqkPrAG5PO47nxxujunBjVs/Wq6ErLwcbGf1QxJb0fQY3x79lDiKMjnrg+8OdILSf/iR0tZHcBy4DJHObEkX2ZXyTsFV+/w50PpSrlZVQtB/q+u70xCW432s4lNX3kbR+BomhOXLIfXoeflt+xBYkAdNZJL4SCjNgISdsLHX1ons81SIjU9jEufdNBDKyyiGLShDTGK62GqyXj9MBazok4NKrm0RfJhgReyV2/3q43S8AV6cBX6ema53D8WS+AVCUF5hsjWmRJE+zv0UAaQAh3PFrvH97HvDSy8IKSqc7hqpKkSghb3PspK9JAbOWUh2djrIBoTaAFwwHb97uC0r9FK7YW9bTC/I7WfDzs24/J+2mbGsRQJp/fup+fNsopr5GZqnyLoGP6QX9vWIx+LVMStstwyejJg8MhqJEch2TJ1o/v3Fd2rlukaOnF7Y2Ws7G8up06tSgoUxKbpWMtleR+flDQQZNRfmpsB8jryjGMApNo6JsU8mHc/QQJceUx4wbA3zxFXHx9kVydkkwPCgHp1G3HaeUSsh8/MCo3MDWVUNZdAOMTgpZWBWD5e/xNut6/IR4me3SgjVtiHPHmdJyTBH8YN49aVe5h+D0T+okZfcLBBMUTkT5ghVOOSmEEnWLd7KgjHB2owDr7iFuCQpZu/C+QsFAVVMGVcktKMhayytLRIc+koKksgAVlKEyPN7dVlM3filK23MuLaC9Rkr/+bQfyCJqgGxjWlZVBaxZS7ZD28SyqzzBeXgbN3HdRDFuTGQZYUeYCBY4Iog5q6kCo7f9GCIyEniSQHXpYm7bfFSJ0ioGr43WwsfdvHgfr6F0tRzDCOCxhxVRofzz8y34eO7L5gZfCpOWLgZW7lKRVeTRw1OHgjyeUhg1Ee+ayMppNiFeSCL3k0hV5eRkzd+TFwF6u5nBffOdCG6bq+AcAqQBPsFBrJ46gaSKiKizCA0F5W8gxo8ZxUMlbyaxJaezdj0LwUN4BYXAPyqWRJ5H+q+3sXuvdG45YxqP+Hhb8S4oZ6x837IV5DLrsJ5om9+6bMLieGD836HfS57mSr65sVuEAZfyZSivYRHh73hHedVHLLScFxZ8/SPuFBbizBnzMXNIfC9ER0ejf79+2LpoAdiDN/D6XOuxNA0MukZwOJRORuW42BRD4Fp8iOf0jJ50UdhSa5gxDYjvZNyMJbVa/ZMKkQEcpj5hq0/3yDCt+4zFpGXroJOrkJGR0SwRuambsWqFGeD2kwpU5BpQnC22TSFg2x7WSjsVMhpYKy7C1xDShlEzZ5CVjaV80IdHUQUrWljWYomyLjH47w9kGDanYv+BAy0iRDjcPHJUDHxoRN0uappK89e02g21pDNxdBNdZpLFR3x/OWooQ5hLVk6IhT9ew6KymkGXZ/8qcs7VUpi2E7qaKoLHv02AzrR5RPSwLxo/UhgvpI6UCg1I28mJQLenMPiOuOjfoy/8uiY6HaP07BGoi3KL0+9z7bZ93upPuUaFsDU/buG8GhPlxnLgCIN1m1h0HDddNIWFZGiqqylSIfa76+qgvS5uhtWJW3k8L+x0fdYaXWsXgCOD2OdlCxelHkxeiPn8eqzl3rCO+cggjZlIbqJzP6hungdDjpCVK+EeGgVZTAKqa83+U0k49XlXYagQj8Z54VCLPIopSKP4ofZQmfPv3toDIJ+eYr1/8jL/NTZzs8T/whcSnhTczH+LRczYaSTJNpEh7t69S37SPAZ/Ic10otvHIrLRksEeNwU3fi5Ft1ZsG7qsf8+MDGT2DZljq2NbGAIi02FXvvQdjZri5gDK5Tid1u5Y4eHhiImJISmW1lrm6WkDTuQwGba+SehKc/u1G0AafMysJHAb/o29Mjnz9LtDM8EbFBjBH7HpOz7uKlaGfYHLFylRDk2CrMmGMG8hPAI4AWRYWBi4kHiUldmff9nbojqXticHD2w8mcXExSqgsjhVS+dGQ23whY/47aq5pPrPxI8/yfDCJPMh6jcRT2FT1Fh8GfUcUkKHWPV3EzY+A8JwlCKX0kr7BFD6pqCFjmsXgEMGExcyknEuU49Xp1nHjx7QoMoQiPQ7nSDnpQjnyXkdsevnbnhxcB4+f+006sk/almF6Z1yhS8Btt7l8iQRzcoi/+iAi3OmiVzMbnOAtGqr3lw0Vjxi27GbwZND7Od//up8nLnugeMXPDGoi5rSRXPQ/NWc41jW8L1Vfy0rR6aPWeH8/PzA+gY4TS9HD4OM6Alqaw7+S1Upfdx35Zr9DjnF5v8frNTj3cUdcOZaMLYe7mRqf3fCZUy4d9g6FnU3i7CC/CQf3RMZF4AiBx9KCl9Akce53KYAo8LR7IdYlcYjNyE9fOpZf0mvlAYoZNav1rPWx+J9q5ocpyndkJJKgXuF47kC/RHuCt3/F2AAAcUfZBL6KZgAAAAASUVORK5CYII='
-
-EMOJI_BASE64_SKEPTIC = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RTIzRDJEN0QyOUM0MTFFREE3NTdFMjk3NzIzN0VDMjYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RTIzRDJEN0MyOUM0MTFFREE3NTdFMjk3NzIzN0VDMjYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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'
-
-EMOJI_BASE64_SLEEPING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEMzN0M3NDAyOUM0MTFFREEyOUNENzdBMTRBNTI1NTkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEMzN0M3M0YyOUM0MTFFREEyOUNENzdBMTRBNTI1NTkiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrS+R4AAAA5YSURBVHjazFoJdFNVGv5e1oa26Qbdi4VSqGVk3wV0QBBQFJRFzwzCGRBmEHEURdxGxmERFcVlUFARQQXZZa2CIFCkndKyU1ooLRRoE9omXWiTZnnz3/fSJmnSNuki3HPuuS/vLu9+///ff7vhcBeUESHoTs2pRoZ9sL8Yr3i7NneXAORTl6ejLK6X2351Tjr6z+vDE0CJt2tLcJcUq1RWb1+/+QNY85emrMu1Mme6sP1RTaQaR7Wd7ZvlVIupZlNNpjqa6gLHuUfW3IAxOBL+uacw4MWeIO41aa+yFgIyippnOA6TeB5S9u7B+8Ua3wEIDADkctd5lZVA7jXgvc+AAg0h53CL5m8ytwl4joFjhYGjMsTNNwOpiaIaTjXa1kY4PKcQUV7mmgjocdrMCtpMbKcO4F+YCa5znLDBZpXsfGDOS8DBjeWw+Pih3Ynd6LForNPZY+fVcY4hJBrVQeEwhkTBGBRJlT1Ho+PGhfApyv9U5gWo3gTgoEQC9fJ3SOa6hgKhE4gNmRx0h7wCUloGFJUAJTqgN+lPiW37B/bThtvdI4BjhcCxpnPd+ft38I1+I+RkEgMYKPMAGKHA5hdn0UF5WA20JxIrSBK0PwI3VnoMauTEOkpFpiDKR8Dn1lWk7dBBTxI3Yh+H5O1XhP6YfbVrX6I9HKR2OnEyz9PvhR3bzJqpsgaAMRkvmTwO3PQZRMT288SO8gw6OAs9+shJrid2cWOxW/IoLdbPLeVHjOMEcD2WjkNpfD/wnMjOkIwk3Bj5rKBozCr1sM7fzMutUYp9F9wPeYUOypKbkFWWCuMPf6tBdUCo8Nxr4cPCKyIIz9UDbr5Mind3b1Rxki4fitaEtxAt51JrdhmfxI3CJskkbJM8gVIEuCfYOPunqkJjkbw6F/1eHYRqdVucemOn0N+Q6An9pElpb4wCz1DVUy1gzyb/kNm/rS9yGetWi9IC2xLiMf6TL0kyg0eIL/VHAc13OMvdh/XSKVgvmYJCQVF5Xtjm2xRcxv3/iMexVTngeCsCso5jwZZhGGqSYwyNUWnzIC8vhrLoOpS6Aij1hcKzT/H1mr1JaONWelzrsN+UI1/n135n0PNdWbPOrZmgwf9O7ILxK757GxplT1zgEjG3oCPOVc4kPb/ea604gE/BI9Y9GMvvQnf+NBauAfZ17i+I4eBZHfEYGZd+FQeRlklGMpYmzOwApRJoGwz4kZ7xUQH+/mRmyGLcO4x8tQ+RRaPiHfa7qio8DlaFSvRazNXwzb/AuDfVBSA7c1Z14L98f9BhtVJ891UhCFzjQMbwezHRuhkTrFvghwqX/nMEYC15mr+nAf/bkQKpoQIqTS52JkGojsVoJN1FgpdEOuzkZec+EuBOdZaemfz5pdofQ6bHsGaRW0NPJqA4Z5MOk2zgLLRaWp29JvIXMNX6rVDDoHHqqzKQS5IKHE0BUtNpM26Ok2bQBHFtMgM1542dF2OHnrD6+NpQ8FBdPIZRk4Gli53nz5jOqI7VxKGZxJC9usQhtcZXXlYERamWce8tF1eNBofKhg7VPLbycK1FTSk4h8FlHwlgpLC4cCSJFPehY4DJ5AqEl/vAog6BxS8Y1jai0lFlJuPcP9cJG1LoCoVzpSwpIHW+CeX+USS2UpHiEVHgyDCqMo9h3GNA//7Oa7/2BmqUDe+olIZPUkFSbSiwKR/mBjFWJdZwcHvfmQPwN+takHUSea+fJbQ60sIrvgCOn3ADRCaHJTgUloB2xAG/BsXYEN8fXVfOAi+R0jyFUEHVGNsNfIm+dpy54AbkkTGwqtTYsbPMBWAoWQJSfacLhzxtjxiqDbj6+DwYA8MjjG2jI6iFrKqczMXIKzUc5H/ZRka80/v2lbJmYdY80VcUDLPSF5bAMJipQiJtWa+cxNJ0M98hxpFAHhEtcP0pEtXu3exd12g/n6/yzJth4m/Xor5d7D0V57BilQjOGNudqOnfurESiS1HKpM3VNmoaRUq4/LGH6udAF4ixVPU5xGPiCaIPHFP3o0FM4poe6fuF+w9QOJCrlSrg6vRdiHtYLpxrfa3SVsAjojrczkNZvItZDZW9KaY+MD7e/DQk3JwFnNjy77BpvXowpSvzAFIZZb4kfC4PzbqlZLoW2wKjVpeLqr0rduAyZPE14HkQLZvz0TV3JtJLCmcosYi+g5RLIqS+NS+zDhzZ6J6WXA7Z4e8opy0sBqnTjuP69NHaGIbA1cDMChA7Si71Thz4c4A5BQKp9+WMh1MoR1cxiWIAdQTnuZkjOxMw2qwBWvHkZ1zlyRqSE/U6IDCQvtr5r6RXhrhKcDq28wds9jclrJU3Cz847GY/IKQvPSooE3dlfQMFyUZ6inAHJYPgckmzlU5QsTd7PxDnaLv1Afp835w22emc5ZKIZOwIZUzQN7mKmVfauK5pnohj2lnU4mTMqtxnbwp5TH3wj8/031u8+pZVLWNEbgUlr4XYWm7BWBXHnkehpAoYUzXb16mc6h0BkimgKdoQautahJAFl+VX2TUMV63yzh5XZzV1caYfAPrXUjbaxROz15d/4dMRiRsEDMBmt5jcObvK3HhmXdrwUX/th5B2ankh9YhrNVC4ZBP0zVzjb8JM/mDxhvixyLEkKVuSX1zF3wLc9Dz42lO7zOnLEVx4uBGP9b2zK8YTPXSk69C23MUeKkM7U7tR+fNi4mgllqvxlW9SpoH0C5j4kmmoBepGa6DA3MyoI/rJYiZ2wz0knEefTR+6zKhulWcdb0TAlcLvikiaiOa6OlWnBQ36v6KAH/66gXEJn3hughF0gPfHgFFeXHzU/iVzhE2Rz4aV21oHgdJ5X6RdhKL+/YURVRIH7DF6dxYrTw4pf0MRB/+XqitdkdRXloHIPmcJgMiIprBQSorNu5wg74onyha8QcZdR5mbYHbSEPQsInNAEiatPJsHfesI3FRpi+ENCAYZs3NJi1eERmPlLd249TzX7tVFCw8MmsLhSiCxYN83fSAg77p07t5HGSEcmLV/OfswSdP8YpF5935MvkFE7A1ZOsCCGhnJC85DEupTgAiAKJqLr5FoKrrXUMeEQNZiUjcAId0q8UqNGleASQJmb1llzMHWVHcuAhpUAiJ6m2B2o2JGW80CEByh/7V9XxRdOA2G1VXKpVKyKPaQ67NhVxzBQkJzv3nzwvNGq/MBInpeqzDuglj7Z2PjgR2/1IESVSCwEFGbcegtKESmLEf2iETvRMnXz9IA4MhLbsFRWay8G7oEGD0KOdxP4le3SqvOGgTUycdPfdZGxcLLkEW5p0aC0r/Gf7Zdinqsnxa/dwKj4I8Mhqq21ohD6O4kQWJkoN/H6ULOCEerxQYwnvFQZuEPfSf5fj9rXn2dyz7vDNJAy4iHhJ1AKxlpR6DTFw0wRUQ2TWJn1rgFkf2U154BVIHT5opkycp0luyXeF2zU8+EzMXTfJkiCrHkeI8YM50MfvMKGuI6w2ezgajhLWqUhBZ3myypxnY+WKXfeRPcuSxc3KyYXJFrQMtMVRAqtdAdu2Ks2cTDyF71sYhkJCQBrXW4dH5TCEuzKZ9ZjTNVRPLi2s34KNpTwNnaB8m8pw+JK/q5dcAn5x0O7fJj+SVvkLehD2LZsBKRtkscIY5CVy1+wggKAj48wNA374NnGFfHiUVdjtxMRv4/nsYSCV08SpL4DafyPKkm8mO0f6y8p373vlaDpPOArnBiqpGIpiwMCAqkjyjODqDtC3fNp5vbMl2keuvjzfi2/W0jyzkELhOzXO27WXItDk4uvYzN7YpRAJZsAQvPWqEj7x1nZu+USYhVU/laRLLjU1K1Ll7eaUK10KteOBWMToMpyhIV27vK73NQVMqQUwIj2A/vlWAbfhZivzjJuRm8asIWF/az7kmJ7Ia6hzZFsfjOmDArJkULlrsXsSyn5RQq3jMGVXdIoCMtMyRI8DBQ4KpMpCuGk/AklokU9fYgJo/IYynUK+fTSmsOaRAoZ7D3NHV8PPxjotM4dJ5QgZFZuft/u8BqgsIVHqLpyI9HUhAmXX8gF0ODRoI7iqngL6KwwsE0rcOSD2ZyuJi8aIkhzRxjkMakl2nsdsoUGAr1+ZNJFBbWjXX2pRJ7D8ztsTrIBIpMoyoSUnrSLxYju4sM1tUfycAKTR+raHzgKnMnLD7BM5shOR2KfMz99AYEk7hPu8q1S9pfMUdB+gBAd6l5tVao03GXqpUQapqA6lPG+FZpvIld0yFMk7JrCckvBU8eTWm68K9tY7NJ7Bf0lqMgMG2pbLoXdUdAUgbGUbNHtISPqH9hsM3uqPHczUaDdnUKqdMmuz8rxg5HGgfTZGNmHjDiVPA1l04vU+LHs21gw2W0aHIJG2a0DkOfHSk6Inp9KQ4zqsQNXqK1+uFkUdgtVrpzNoiFRLfWTPEkO3ee8iW2UKC7l2By7noZj4NX+Lk7VYBSJya+snKQQmdhi8B8hZx0B1AHoWJxWVASlpVkyVAQj5sbGws9Hq9cMmeTvp0YE87uJqy9E1woyaDJXGDvA6XPCxrOz0wHzj5IBg4VmLDvV+kQqpCujpBOH9OPmhgIBQKBRGLtHE96qZXNwQSoRUtzkG26EMPkvNz1n3+08ff1+Wdv8qEZTPEfzDkafzw3qb7sCF8BMplomOaru6Cx7VHEVZtvzpQq9W4RZanrJ7/6Cwh923MU2C3mAktykEyCetfmV1/ElYWHOX0288BnMDpsAp8PDsV/UvPO0fooUNqAQvz2N+c2sY0mN0gGsS3uIjSByfVd+lURmdQ1S7S6d17M1z/eyKXWpE0YyseLkp19j/Dna/7uMg4nKDpWr377/13GSQkUYtbDCD7s8LYke77SsgZzybz1SYy1p6iiLZH/nmFfpj96UCnOVPiTzdyeBTYSW5AvtZ9d4ioYl5vbN//F2AAf/wxX7nIyEIAAAAASUVORK5CYII='
-
-EMOJI_BASE64_TEAR = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTAwRDAzM0EyOUM1MTFFRDlBNTNFODhEQ0E0RkNFQ0MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTAwRDAzMzkyOUM1MTFFRDlBNTNFODhEQ0E0RkNFQ0MiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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'
-
-EMOJI_BASE64_UPSIDE_DOWN = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjVBRkMyMkUyOUM1MTFFRDgzMzZDOUJBMEFDQjg1REMiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjVBRkMyMkQyOUM1MTFFRDgzMzZDOUJBMEFDQjg1REMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjoblMQAAAwGSURBVHjazFoLdBTVGf5mZ9+b1yYbQsgmEAOCgSioaCiVgiCoFUs59aCYarVYi6dWj9rWF60t+KSKD2gFtOLxVYvKQRGFHJGoPARNQAgEEwKYt1mSTXY3yWYf0//ObHZ3MrvJbh7APefunb0z9/Hd//3PcIIgoHfhOA4DLVelgQ2eTXUG1clUz6fprLSMSbkOOqm/li4rqR6k+gXV4uLT8GGICjdYgARoFDUvUV3I/s+/GphzBTAmBzAYVDSZBvC7+52nix75gaCW7AY2fhjs/oTq3QT4+BkHSMBeoOaPty8GFi2gMUlTgbRrAF2W9MDprYBt86Ap8NE2Or1XxMsNBPS2YQdIwP5EzTOP3kc8eA2RKqModLODOK32eUDwYqjLt8TAD60QL58joPcPC8C5FrjmzoLx/keJUpYFoRstdMzNH2C4y5FTwNbtTEjh324DP6QAiXLCY6tzkTvjBbg4EzphQH2nCx/UVqMJGXByCeiGFu1Igh0paOeS4IcqOL4NyYo5k6k3vKQIbKQdCXDSTN1IEtqRjmaavQkWwQYLbOioqUWi/Qe89lg1G6IiagqDBkiU8x7ZZOOXjU0L9r1YD5R34KwVnb8TMxYaQQD7VBiqGJTJes/KtTJwW1vOLjhW3CoDGtZuZ/vbMSgKzrGoBH6nD4vTupAIB4xCB96t3EG2oV5kmxRIbNXDXqwmCg4SEMmUGdEhslu04oWaGDJBvBaIGG1cMoIzcVLL2N7GWdCATGLYdFS5M9GgGY0WdQauvCkRfKeTJ0r6I82v7od6L//tAT+mm9chOLzpHczz7VQ863QBrg6prWXXVH00prMroGDpnr/XWSaYJIh6nR1qUhkm+m8ytiKT8I419tyPoFGrQ9dNdwDPv4htbLtxA6Ry5/TLNfIe+04UlwArV595trzj18AN18v7MjIkRos2Rt0H9YxW5qNYwmZ0VWDt68D7W4gaBtKa1nwIau2wA+N8HmjrjmH9G3YcOQZc9wv5/YIL6ec7jCU2rYpHyTy8lPkN5itDPXUvieC8qVlwj5k8rOC8zY3w1P0gVi/xuztnEjwj87BrH6DvxVTz5orNiri0KOmZB6YyV5kLEXnDO5KH4snIHXaqqdNHBq/9jnZ4m+rhNWeK/999T/5smllsFsUFkJSrTtZByuXt96lfoz9jMqe2jAjtx+uF4PPBZzJj77445uj7tkqmXFjpzhwb1yZrZxbh1JzfQuAjL2U59DnO3/g4VB5lxMHp5Ifpa2mGJzMPfNU3ime12jgBnjeafvTZgZm7UF4RYBdTSkzAqhb+GY1T54c8D3sjEuqroG1vhk9nRKclG47sfNgKZolV3elA4T+uVYLUaCF4JDsqdHcHOai0DLh4Sui5iRPp8LthJkXT2i9A0qBZeUzMtJIORsM6bNoaO9W+fnQLEmvKUbj851B3tMdM6a+e/BLTH5kJzh+Kd/nkFHhtP8pkh5Xde+QAsylKKysD06clsVBwwmgr/WrSA+ahHF/uZfKn63ejreOn4fIV18Utb9adb4qVUTWx5khUNvV3uOA3JqOuTu6oW6StTugNMJqSyUxhzr8mldjTETw4X0Jqvxs1H9szKMUSDi5S8Xc44UtU7sNklPYdqxa1JLABHJ1e3drQ5MZknO3C5DDSPgJKJiW+aII3kDNZGQKoM+JcKPHsIxpAu4fZdJ+zF2DNOQEQnCqS3Rb3HTNAB8PW9LbCvTlXSyBqscdqB6samhgvdMl7yekFC6B5ZTqkZcJPcOTWp4PHWUiaNFYT0VMO3/4s7OMuE69H7vsQYzetjOpmKbR3i9icjJWCladqI/BzdxfZpCYlufMuCYELUHrvso8jslK0suexbUFwrDRedj3K7nk9Mod6uhR9PzaLzbGYAJI34K6oVCZzVB1tEal3eMnzETdy9OblsSkN8k58ERSHa+R5SnC0Pu9qU/SfOCnu+2jMWrTdoUzm8O02qIwJomcfS3FaL4jtuazxfdg9lxwgrc87bIrnqk8MMOnUU64olFhDZTRJnr07xCa82xVxDJOjWErSyYNR7/laT8sPOTEJKpcdo0b1omy8WTUSo+bw/0U39ApIyT8UuqUIoHD5/IhzZO/YELMMphwvVfRlfbo+4sZYmT1LqXriiiZIUa0/cBgPT54k/c/NCQxobSCXLRF+p4Oi7qaAx6/BtLsm4fitT8CRNwUj9m1BdsmbdHx9MIjfD4EqfMQN5Fznr7qN/NhCVC/+Kzg6uHGrl8JYUyHHpjeAd0rBQn5+mJKTRPJ/8caDz7zzQQhgTxbM2Xgc3gt+KgIMHobHI9bcNXcH+zwDsGVJ+z/FZKpRg9e0dGjJ1+1tjnftEpun4mJR0khtZYfkfat6sh6CH+r0jDNqyPlUS4DyPtxSJL/31S5xvwfiVjJ0UvYem1pKLmlSwMc1VOymALUNmqwcaeHh8nCYT2FOFdfRUNBtOPqVFBNNiE3++gVI4BY8+6+Q81DdADz5OJBOmLT134sLGuuPQp+UIG1iVDZtKE2UFXDxg2GxnwiI5mHz6ShmMzRViutoKYxKTJTWl7HnbrFZEnXa/lL37K3S9o3AweOkOcNeLJee4LH5I6C7Sfm2mSWG/KZkMb3h15n6pjCtr3J3kBNhJ/XfRkqkRfGIJp3Hz+ZwmD1J+d7xoUfQ5wsYdQxn+7tlT2HdA6Q/qupCnacdHHTZPGbO5jBrohc2m5QnKSNJsNtbydtoHVjAS1SaMpnqFLKjJOYHTvLYWqZGq1P56mHbdrF5ehBZNfF01nOleOLIUVi0SWEaVS9RPi1Rai3EtnOvkqqCokTkNlLlbrfk9et1gI5qMsm0up8dmBOk+Y06Oac1NgIlX8BN+3twUABZ2W5DOp5B5+JF0E8qkPouzPHj83Jyctv6FzbmvqamDkzPNAfmv2h0iILfk8J7bQP8BK7fJG3MrhqBNLz1X+x4/EnJPpsCFNxXxQ+refi8XKJBVqpfVHT/fA7ChtdxiMAN7SvsMKWTTrfrDEaoFy7iuM3faVF0hQc5Fv+Qg2txcni5WIt5BR58ttkvBGK+PAJ3ImblPIjPSFj+4j/MTVXRVeGlwOSLAKt18GaxhmLRw4eB3fs5wdslsNnYFw5FBKwzblM6VF86EeBx1DCX/FoaXkjTDoR3GRvsh/QB0HsEqHzQvsJQf8oVBfy93db8VeH5TGb7dNWlawjEH4Y1PzVcAAnUUkZNZtqY3Pj1CVaoeLmB72xnkSujEvMWWFC4ggC3nLMACRTz6P/C0gppF02HyXoeVBptH06MgFOnTkn2SkVr1lXCUy++gN8RkLmGswLw6hFoIeNtTk6CV6shQrihcjqJVGMmwHLJjLg3YSM3yOl0htkuAb5vi0Fzg9bw0xb9p8k5EgTRJcsm4LWxzq2OdzNzLXhrU/HvzXrrAuDEMjXa94uRBjunhx6pGBBAC7lBZrMZNTU1kqb5sQbL/y55OeOzoUowhOz13BtQgzhceVW8m+FVuFGvcZHEXA0GjpWLxwXCqJSU+FRmWFqRJ7YeM2YMNBoiGykjliWblEsuoUE+5u4loihcNiwUpInveu3dm1VofCPife2IHEXfeGsb7vml9MaouHQUNu0ajS3p01GvkwJYteDD7XVbQnmYrCyc9HhQSVzhnkk+a6+3BfPnAatfBYvhNcNBwTUZwlsRE83sxE1Z8jzmjIKmIDjxgC6ux9LrKtClCikeL8fjlaz5vXxXHt+UcTjdFnkTUwrAB74sHjqANGHCtVE+t7HRRg6R56FLDX00YEnuwo0zqxXPFuS24rOp/4Yh7CtgxqoHEscF/5tMJnS6BLQ4Iq+3/EFRD749pADpUDfde2fke3VkzfZ+Le+7eVYI3CufnI+7XpomA1lUv032/P7kUJLYaCRH1xT9FRkTU+KaG4dUBsksRP1cin2TJvTytU2GUPS95JrvFWMadGmy/3kdoWhar9fDlzYaTtdRdHXT/wimtOhXzJlDCpkM+6ApyNjzpoWR75ENFGUwKW9izIJ8z7ppoqIJL1e2fCt/KN0qZsuqo5j6WxaJadeNQ8WiB38ThSFYGmPPXoq88y+NaaL7Xr0ca9LlH5vdVvdxxCxUSYl0gH3kjuf0t97/BRgAmT5e+n0KfyMAAAAASUVORK5CYII='
-
-EMOJI_BASE64_WIZARD = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpkNTJlMTYxMC0xNThlLTlhNDItYTY0Ni0yNjViYjMyYzFkMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEIwRDE1RUEyOUM1MTFFREFCMjU4NjU5N0VFM0Q1OUEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEIwRDE1RTkyOUM1MTFFREFCMjU4NjU5N0VFM0Q1OUEiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ZDUyZTE2MTAtMTU4ZS05YTQyLWE2NDYtMjY1YmIzMmMxZDA4IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOmQ1MmUxNjEwLTE1OGUtOWE0Mi1hNjQ2LTI2NWJiMzJjMWQwOCIv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'
-
-EMOJI_BASE64_CRAZY = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZFNUE0RkQ2MzQwQjExRURCOURBOTRFOUM4NDIwRTUwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZFNUE0RkQ3MzQwQjExRURCOURBOTRFOUM4NDIwRTUwIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkU1QTRGRDQzNDBCMTFFREI5REE5NEU5Qzg0MjBFNTAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkU1QTRGRDUzNDBCMTFFREI5REE5NEU5Qzg0MjBFNTAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz64kfh5AAAWqElEQVR42rxa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'
-
-EMOJI_BASE64_GLASSES = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkFDODJFQTk4MzQwQjExRURCMjlGODk3NDQ5NTQ5RUZCIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkFDODJFQTk5MzQwQjExRURCMjlGODk3NDQ5NTQ5RUZCIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QUM4MkVBOTYzNDBCMTFFREIyOUY4OTc0NDk1NDlFRkIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QUM4MkVBOTczNDBCMTFFREIyOUY4OTc0NDk1NDlFRkIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz63QkX8AAAWkklEQVR42rxa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'
-
-EMOJI_BASE64_HEAD_EXPLODE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjlCMDEyRDc5MzQwQzExRUQ4QjhGREE4RURBODNBOEY0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjlCMDEyRDdBMzQwQzExRUQ4QjhGREE4RURBODNBOEY0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OUIwMTJENzczNDBDMTFFRDhCOEZEQThFREE4M0E4RjQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OUIwMTJENzgzNDBDMTFFRDhCOEZEQThFREE4M0E4RjQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7feGyYAAAQ70lEQVR42sxa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'
-
-
-EMOJI_BASE64_LAPTOP = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjI3RUM1QzE3MzQwQzExRUQ4M0I0Q0I4NzYwOERFNjZDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjI3RUM1QzE4MzQwQzExRUQ4M0I0Q0I4NzYwOERFNjZDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjdFQzVDMTUzNDBDMTFFRDgzQjRDQjg3NjA4REU2NkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjdFQzVDMTYzNDBDMTFFRDgzQjRDQjg3NjA4REU2NkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7XxuepAAASgUlEQVR42uxa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'
-
-
-
-EMOJI_BASE64_PARTY = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjIxMUE2MDI2MzQwQjExRURCNEM2QjE1MzA1QTRFQ0FFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjIxMUE2MDI3MzQwQjExRURCNEM2QjE1MzA1QTRFQ0FFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MjExQTYwMjQzNDBCMTFFREI0QzZCMTUzMDVBNEVDQUUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MjExQTYwMjUzNDBCMTFFREI0QzZCMTUzMDVBNEVDQUUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5A1idCAAAUNElEQVR42tRaCZgU5Zl+q6qrqu+enu65Z5gDxoERZDiMQpD7jIrGjWPAmATM5bHBmOSJbgxJ9NFEl02yu8Yzqz7RJfFAsxgF5QqCAnKNzODAHMw9zNU93dN3nftV9UwEQcLKZIPFU1PNTPXf//t/7/d+7/dXQ9d1LF26FH/r4AD2erCPPlNYpT/qLU8uZ9ibBVzch4HLcr43XwZ8/tapS1YtK5yOYFe3yDbhvl3hxrcloP9iBsme741ZwISqRYvtXJ4fDt6K8fa8ch3IuciD+MkAq3Jcjm9NG5Mlculb9gPbd217Ixbp6UVndx8OJVqCNkC52AF+IkWn5Xiqnryh6oU7qwqfDSXlY04bj8defffG/Y0frFuyMr+yen5BlriW3fBsfdsth4FD+mctgndMKyqCrhVOKvX9/Koy//1NwXjqD1F5UyRP27vkgVwUlRSg2janco278q2ZYJZ9/P0zAMFxMUdw9Zt1r2XYeNIWCIGYVF/bH5WM39utnAMRFvL6PDjtDiytqPJXTBQ33PvCkdU7ZPWPI++/F5hvp9uXA6/GL0aANb2RFF3qP/57ndWh/ykfaq0LrJWBu9KNK1bk2H6bP+X5Nb+ucW+JK08Z990P9FHevrECqPsvoOGiV9GRI9rKIPGmB6yxNJoOfkmIJFbGhFlZlse/N/XJhYzwQ+O+SiBMl9zVwBcvSop+0qFIuiRrKnjZAnZGH7grArRMtE5JCbnBPKzNtD+SDOzD7UhowwbB+5mogyOHpmmSlmDATg2B/3objUD6KajQOnwI7nCiyOrHU6s/90jXGPc1+4BbdwMvfqYAshyTEm44CW5NIxiPTOA0aPsyIT9bCo8nF8JEFRNusGHGvVNnry/1XrIWOPyZAsj7tJhjOdHSQ6KqMVA350B6vAx6lIWQbUHut4iZsoy8YpH98Tcn/2g153nabzL1M5KDKUkeUkIsuF4XlNdzoB6iFDOqPEeCs6Id7Kwo8AGtW0KF/aQbt/iu/IYl9n5FvFhNynHt6KbW6AM9QPCiBRgeTMX61uUiJ1YINUHIdAZwKOC/0gFuXh+pEIEr1aG8x6JvO4t8qwdLtEuvGrsyiXHj3Ituuv3doY3B1CN0FwOTA4Y8QftUnk+kd5cJVtSnkqMGMJ6QI/EmCxgvT1OUwE4YgqW6k64RmipNmyfQPIfARjuUAcoBUUfUHYcvz4HDdUGUV1ju/K5guZFNy5NK0U8lZD3WH9eHBgaV5r5+ua4jgToqwvVkEAZP+/CxBOZu3014ZagFk2jlZtsX44XwOgLYNmoANegxLT9GKjoAYVof2Cqqg6KWBmela4SD8kwZ1KMpiOIQ6mLdyFspI7PAjS1bWvDztXmZFg+fCW3EOZgwoac0BEMq+gZk9PQp2HswfGJ3bWzPsU48f1LFloTx0R5OIlAPYLqtyIzeW9E7sCnSNqoUpWHj/KpWYOEg2CTNTGXSZCOQWr0L8h+KwDV74XAFsLv3GITlIUyfnYft/1OPcZcosNgMGkhnDMrwDHy5dBYKmGBhMG/e2LIjR4rK6o7tuXnDpqGdtW3KT5tC6k59W+wJiroXJ5WX8OvAfsj66OYgZVm/ylHGWGhghs4EB63VAXW3H+yBLIgpAd3xAN4JHsSYlUOYuciLnX9uhZTHomJZMQbjGvVYHP3TSMJ1U5+MHxaDrUkOsiogHvViy7Y1mDX5daxctR+zqrxz1r8cfPvVndLPPryr56HY30tk3HR/AVA9uN1JOlgKtFmgd9qhdVqhRHV0J/vxYaQZQ+WdmPc1B443WvGVtydhz/jvg/tcFXQKnM7hFIBEeDP8NLBFhSdowfxXKMS9mWjK5vF0eQ5siWo4K5JQv58QrFcceGjKYw869wSVH6t/D4BVdm7V2vsuWdOyO4DuNxth1xzQLBokRxRSdgT2KRLGL7ShoCIPe1+M4mbubvTcsiJNYekjOp71MELpI19nbPSUANuup4VwTKKaOvweF51fugYTFPu/TPjNPTV1Sf3lUQdYmi3OnbowC1O/yCISSiESIAUVOWobgZbaBLLG2DHQlkDNpl70Vc7AD2YE4FB/CUbTTUoLNFsWp+eMBJ7IyRIGHTLPg/uqgEEnj+kWAYosIMbbEJCtGIjRGXGCWTAPOTvGPdiyr/EtourQqAKsa0/88ts37ndUlNmuu3p1AdqOqnB4OcR7hhDti+CDbRI4qh4FxSLGdGwj0XmdJkk5N8wnWdHToqnq5M8ZMBQZp7FdN/yaJ6HhSB3HksiI9FoUGGRnCyirJKYkNRxtkcA4ndg9OVHeVIPrGlN4/vwAKue34XBQ02t72hJPLJjvu05NzkXVovGId+3AjgNvYutBBSHJSnFgIb2vmlewlKsMk84zZpibzCkc1fW/8pMxXpunZl4ZuhpbmhY1hs9PSuL2b+RCs/JgaLUqx1kwMY9f0dUmPx/Xz635aYC5llOLKRloJpOKZ/Ase6O4JAs3LV5+CfKWLDN6Jxxs6MJLWxOQCirB5meaAJhzpNr5HGosCk0mE8ELlOMWbK1tBPdcL1auzEYiySDDa0FpkTCNaZXz6fbukffl5k+C0+UrMgIXDvW2SKnIMMDbfBMwMWMO2Q4VM+xLsSX6IO7vPwOglVhUWcROySqkMaJGPTuO1146hIS7AHxmFs1MBi5094kWiOUtUEJBojK1YQ4XhOISHDpah9mdKeTkCiYJSkvF7Pz3Y+OJpibAqmkrvKtvW3+vaMXN5PUz+ntj72d5W7+T7iY8bAVmi49jsfMpvBN7Dw8PHDq7i0FBfq5QYPFmE/0Y9B87iPrmFDgvyZ+mYlQOg56CSOx2pekdj5oUH9Kp7DTEzd7aOHKyeNg5XDrytsFga+rRf1v4xLbNz62IRVP7MzIdcwb6G9l0BOtTtWhL3YmtsZ3YFqv7JHdgbPQWF4p+8NQA6SE0HjmC3hhNptBxSj4NB4IAM6pCdY+Hzp5/V8YaLDCsm9UKLRoxF05LJsE4PGhq7sWcOemJeDwcHA6uAvH0wra17DH2tk401G87UV/35+srLr1mdjy0oT79yY8Hm/GD0G+xOVp3LuuTz8Pn94nEcBKPeAvqj3ZAE6n8cxacyk1OSkK2exApmgCVpwVQpL/NTBIVVk4hkZmPWN44aqw5U12NYXXKR91qR19ARTSqmgnusBsA2eKzjVVbsyH0yn+v2qjQeOkICucnCQ4Wfo+HRIihdRk6iubWJClb9mldMycl0DttGVqWr4GUkQVHZwMq/nA/HF3HoPHWs4PTNDMBWr5wB07OqaZFscFXuxNlT94NNtBDQSR542wIhzmEQgrcLnJCVEb8NsZtN8zxJ8SEZbn/W0dP03DabBRBdQhKXyMCIUN5Ppq0EYGey69B0z/9CMLQADJrd5mr3filHyGVkWtS9mw5Z4TpxPK70DPrBjjaj8P74XuIFY5Da/U9JjsYVTXzMSZxiEQUeknyzzGw86zI6aPb8Iq8QBFMtiIWHkA8xZEg8Ok6RlGQ3H4odjcue/x2OLobiZop6ORIwqVV5t+ESOAs0VNNStr6OzBl3S2wBrvMsRSbC4NjJtLC5EAMdg/vyVoQjah/tXzDdn9UAUoKuRBEP4QkaUgpVPNsXDpPSEi4VBz5u182J60RMFVMi4/nxGFzcjp75taMThGyDXTA2XUcDL02xEUx8pFsnb9uF6RwKP1e8zM4pFL6qV2WzowmQBK4UCpBYiX10weOuEr9tGgYE9Y5y2l1zQB7ToExqCvaEImF0XsiAiZO97PUOzrJ3/K0cAx7Rv+o0UInFV022tFz1d6/CZDcgUjuoJJW0OpLBZzhUBcN6DR9o2AxFI5KgVESzEmcX5U3AKUXgzOjw1D0E8koWo8m4JXmYtYUckpeFjv3vYMW7MEYv51AMqaN4wmw8VIjezmQ1GPxC8lBcgd2cgd3kTtYRXk+LhCQYnH1u0DqLZJpKrSiDi1BBjiVIqrazgMfmW2GQyKnBLLDC1ugk8QoQM6FR5TsGZ8qx9jCChxnNpMC5+Kma6rxzIYIgvEjyCUzYSyM02kzASbIfKeSWvcF7YuSO0iSO/jVwz+fN2//3jfvs9oEYaC3TzYSQqA2wOvmTD+qEW11RTndSJ8rgsMi0nL1bdTz2Wk4CVY7NVNcJ0LhIbDJDLy1Ywf4IhlFjlKkSD2Ngm/jVbjcFtPnRqIawhG15YLaJXIHRoEytuQ6O1r3Pbhw9ncPTVbf/i2WF5YSZzC2RMTuEwloNurqw4PgfFnp5xQjrkbHx2jLmAXdUNhEQTkS/QmcrO2BTvTgDLoKfQiK72Gs9TLMn5GJSLuOBNVVowBD1ZBhU5CRYTGe+dBCKFAVvQGjJTKynMDb2x7elHWp0BkPaaX2LBaXVVJubA5TqciDPBiEHugHa6emlDObPLNendEmEUDZ6UbXjJux9Lka8JZb4fTaMBhnoeUdQYPaDC7uRbguB8+370cfsw95BTRmIoa8HA5uYo1GCHt7ZfVkCk2j2vAaFehYl3KAWHpVqd+Cygo7Cjz9aCP7bhhkPRaDmkiYRtxwO8yIB2WGGyjDSIsCBKJlRuNOHJiYCdueF+FRCjBE8m/l42jsr8dJIo0MqplCN3K8VGY8pUB7Ayrn2k2CGA10W7vUHtPQPOrPJvqj2o6jDeYuJTzk6GdOtUHr7wWXkUGuxpYGY1gvw2gTcPOUyEtKqfRJ/zfMgP/D3eidPhZyRRJhfStU2zuIsAdQnBODL6eG2pZuXFLkQFZBMdQ4/U6MY/x4u8n+8KCChpNSbYqYOuoAexTs23sg1muY8o5OCZdf6cEYRwhsezOsIgeL2w3G6SGwduJHupPQmY9aYJ1yKWzzI+AvQ9a+zcigeuYhY+61ueFzZ8Dn9cOXVYDM7AJYicocOSaxpxnz5rjN/DOGamtLoXdA2TjSoGXb8kdvX5T6gr5dRxKb21tTX9PIpIvkZO78Ti7e3BLEwSPHwerkRCwkOiKd1ElAIFkfpqxBXSMCrvajcLfVmq2RYeV0l9uMuiE2kJNgY0ky7THwegJ+6sxuWOVHRYUNhlAb6X2oJjZwUsImYz6LCq/1PD33iVULXp//m+bw8QsHaKxaV1j91YuvBb68elW2OBBSke3jMfFKF2olGVfTRHTq0VraBhAYJJ9JGhwjz5qUGHM/FKfuzxg5SSOKnEY1VYOT6qrHx5CYCCguFrGtmToHL49JE+2IJzTYbCw+qIlh/9HE09Q5dXtFH9bNfPyn+fb87z039+WCxz781W/+1PJSV0KJf3qAxtEi48jvtwytzc0VHr58pst8NKQbO2UWBuXlNhT7qaYZVoqEIxpTEaczldKQpOIs0dXYVTOiarghq5WFKLI0ebOBNXo8U6M4+rF3gHKWFFOhdDDAGdTcsHFwf31U/8XIo413T27f4ROrr5qRO+muWfnPztzeecdjX99x4/qOaKv+qQEagzcl8chjfww4r+uXf7JgfgYKqBEWCODAkIp8j05GXDcVL8NjQaaRO+w5dynM05B/mcAYAGOKhmhCxdQyu7kQhylyr2wc3LO9Vb4ppCNiGpFUALfv+urr/1n3r5v8Vl8ZDSHF5HjHCLhPDdA4kjTEviF9beCN8OG6hsRPqq92TSn1CjjcEcekYqsZFWPC5sQNAMbWpH6mm0uzNb0vakTNQjMyFqq2OU61XYeTqP3c7/sHdx2OPVkf0X9B4M7Y7K0frDUazYZREZmP77Y3Snhtjl9qzxQCv9u73dKQ62eueCMRKi7JE+FyseRZWQgCSxNnTM02ehBmuIvTqCMxwZOyyhKFJWZsSWgIEQv21UXDoV7l2FO7ghtPhLU/Bqgn/jQbdhcE0DiunQ7+0Xtw3/4ahN7rU27yBpC163ioPE9AOS+w4yinCiiaLqog9kwrO123O7NHtsaYZEJJJVN7ghKCZLsiVGb6QoNyfcuA2hqmakBS0fj//gj71OP718G37tt4ETwWELseMvNCNb8/2k828z3jqzKOsGbkbJHBvEoX+zu20JetGv0hcdLa35bq6JUe7NXQRNEJfGGxW16zrvTaBx5p/ktjU1y5cpJLPHQwrBNo6R8C8LntGFo4FVsXTQf3Hy/h17b0U3MjnRzFdlyWIbJfzPb75vEZ/lKGF0QST+7UjoNxlDgyS9k3ZFnR4v2DgYnZbN/i5TmXLV6e+0DPiVinwDMHr136/k8PEsDUPwJgIAL5Sw/il1+uRMTLeV67e6HmlmRNHxpS3INKZqljwgxYPD5wvPBR1uqnK4yqqVxoMMQlPEO5/U419y9vJFDkio7raIqMe/fPPSUzffqc8kqxZ/eJ1JrmJE6cNoEpn7PjtjWXY/0zVLhqahAMxEc9B1kJZZOvWPDQP/+wyo3gu1DCATS1J/Hv6znIGfmEQaY6KZ/WPY0EkdWNksCQPcuAjUx4c3sI994TwMrJTbj+C17MvTO7BA6uhJiMNfd1JDobperTIulyleCbK/+CG6sbMffKaQTwwr3oxx/GXJ5vv7X6hhI3ejaTCw7CInBmXdAYMV0xh3tDRSXFVNNPmlS6Gk94E5yQfopkNLPUUxYV5CIjy4O4wiEvi0/b16iKrDEils11X0MpMOFjUwia/erb29/HBwcjo2K2T/vWE+CdW2W/Ocd5IP1tFzZdCgYCCqKa+6/PEWTV2DFO4s7r6/HDG48gPzuBzc7L8WruIuz2Tk4/XtNV6g1JajMy0d7HQJLUjx5RyRrmft5lq8rivnbavtwHB3twpOUFjB1TCGPLZLQBljmYBcvmiX5oqSBZlYCi6NF4jFG7B3RVEbxDHEvyrzHBTFdq6JvLGpRLSwblkpyo9J1l9cql2QOJmC5IR51jlRpXeZLTtaCu60HRbg9HJavW3kfdfBIKEWCQOpdgUak4uORKxzLrqd9eDFO3dPcdd2Fs4VasWJV3tjn+rwADAJLTB06jQFIqAAAAAElFTkSuQmCC'
-
-EMOJI_BASE64_RAINEDON = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjcyRjZCQzYyMzQwQzExRUQ5MjA3RUZFMzQ4MkFCQjI2IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjcyRjZCQzYzMzQwQzExRUQ5MjA3RUZFMzQ4MkFCQjI2Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NzJGNkJDNjAzNDBDMTFFRDkyMDdFRkUzNDgyQUJCMjYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzJGNkJDNjEzNDBDMTFFRDkyMDdFRkUzNDgyQUJCMjYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5YPJNEAAAa/0lEQVR42rR6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'
-
-EMOJI_BASE64_READING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjA3RjUzNDBDMzQwQzExRURCRUQ1RUI5NjYxNTQwNzBFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjA3RjUzNDBEMzQwQzExRURCRUQ1RUI5NjYxNTQwNzBFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDdGNTM0MEEzNDBDMTFFREJFRDVFQjk2NjE1NDA3MEUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDdGNTM0MEIzNDBDMTFFREJFRDVFQjk2NjE1NDA3MEUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7w5cDgAAARpElEQVR42uxaaYwc5Zl+qrq6q+9req6e2xe+sAGDGTs2MU5kMElI2AUJ1ighy8KfPaIgbVgiRSttFFBWWmmDFGllZdFK2WxQWAmhZQOGgO3E2BjbYMz4YmzjGc/Y03P0fXdX1T5fVc14bI/ncPD+QGnpm+ruqfrqe97jeZ/3q5YMw8AX+SXjC/76wgNU9uzZ80dNoHNMj3KfBDgMuHUdEX70c3g5POJetkF5BjR7lDkKYsgS0pqEQl6cIM6w5+T35gU3+pI+jyhwAaviwFquvnd5E1a0NKBJVRFRnPBHwvCGgnC6nIAY4lWrA9UqkMujnkyjyPeFWg3pRApjJ4dxmv8+OAx8VAOO8/QK/r8BiosaJCyNO/Hord345qplWN3bG1RbOuNoau9AtLkRkpPrqgwARa6xXpr9TsJbBJzJAIlRYGyMCD+CcboffR+dwa5zBfyqLONoQb/JAEW4EFh3l4ofbFyFHfc/EA3ec99q+LruBNQuLpQryBBQ+hCBnWMQ5ha2Eoc9JGtUGa8HDgK/fQvVQ8fw6sUSXuiv4mPduAkARfIsV/DkhsV4fscTsaYvf+MrkFvXExRTLXeWoHYDWQJjrE3NLH0OFKha3n37beCVV5E/dhY/OVvHP4/XoX9uAGOkhyUKnt+8NfLc95/biqZVX4OuNWC0WMDoxH7Usx+hrpWgSSrqHFW4yCAOVCUXo+/yLSpcrfis8p3M9Yn3Ev+6jKr52cUrFdR5pWYenaiZ56pyFVK9ik/7y9jzRglHd+d+daSAJ8e1ufNzToAiYja48SPXE0//0/bnnsWiQAfqVQPvMfpeGathtGYQmP/zoatr7q2ZoAVIcXQZZbgcJQT/9xXEf/6jl/bk8FdFHcZc65/1tUrGNvX+7b9Y/sKvpUX+KEp1B97NO7BzxIG8Tg8JDpVuTg0z6FfhxzLcrCU+ZOUQUo4YRtbcg1Bp9PbGY4cvJgwcMW7Ug/SL5/bOyIHgS7vXPnrHSjjJ51Wthn8fHEamWoFXZvhINTilumlltySWIo4VO4UYfvw8eRPhBRGSFTOxJsPWxeC09EbVcKHEGcpiNoOhboggVVDSzUBFmd8VNBUlpxeOSgXr/n7LyPFjZ+4Y1nDpuoV+NoDNDnxt+8ba2m8vfwfhyhmyKOMh9QYerb0MpygDgrdJAAZLdp3Fq24fNR5Z6M0hRIBuD2laVRCQZLvsO2TrvYPxpIihWO9lsTqnrR6Y2xMFFX1DKrKaB5o/jL7bki2pU/h2ooyf1o0FAvTxhj0h/OWfb/OgzcUb1FNcOYVH6bfoP1HCf78ODFywivZ0YDX7KICZR1jV42pqF2Blh32cAaA4Onh08tjaZODBB8q4464y2nhBiEZVswMIL6caiGHH6WH8LGuYqmj+ALmo7pWLsHHxmmVcXQNXIlZ8lCyWwAv/yoqg+yCHwuZqJMleoVOGJI7iM/WWxGEI3SXez1DbhRUkDqujMUyXG9NdX+FnWumT4Qz2vJ/F3z4N3NVLIxa5FJ7S0EgnLMKq5gRuz1ZxYEEAWxSsX7MKIUdsmXUzxcDo0ffw4r8xMj0xOHtugSFMbMwuUGZ6j1m+F0bRCzmOvOk+2cN8a++GPvwZdv7HEMK0dazZihhhteXLIL/1Pu7lpwML6ia8MjavWS280sqJCEQbwr7fnUQiw5t29JA9FTvZPueh1SFTyIqjkc9AGx+BlkoC8S4UDA/27bdC2Y4yxCmCgz5sUqQFtEsip7uiWNPaEeQZYTPEjORR7N9PYgmGYbi81mJuWhPngCMUsZOUEiCXhVahGIg04NRpCqeclRHCvuK0nkYs8lqdy/wAMt2CrTHEow0BfghxFJD49AjOnhd4oze/iRO5qbohuVxWetDgImSlcATj48ClEYuIRKr6fOZoJYu2zhsgDdMYDCDmjfBqoVJq53DmxCDGczJkv//KBvBmvRg1stt7GXO1DF1hVWW5GPhsmlKhk6NRBDwyYvMGSMOEwkEE4bL71PxRnDypQ3e6oZvfGbNa/4/VL1MYRS5KdgdMVtENHlUvBgevvII9p9TuQsO8WZQ10E+AMhy0oEY2K32C8xeEsic4h3PG/JOocGQSg87/i6MoD7pTnb/DGG9yrWIxs5DhZBCN7yUOw6RM4UUWQLLqRDJl5p/AL+zp85tOic0bYJsCr8ctqJT55xzEmcMX8QnbPM1pmDQuieQ39ClvybUqSo2dGNr6OPLxxVAzE4j//jcIn/nA9Prc4DTTGINbv4PUig3m56YPd6Hl4GtWLZ30rQDqC4DTY8+7FsFs3Eh28U8qy3kCFP4JEttbL/fhw6OHcOa4gTu2P4axi2dw/PRRlNx0b6QZCnNEeK4SaUHfk/+CUmcnQ4ksx8BP3tKL1b94BuH+Q7N70jZS/589i9FN95vXi7DMLL8N1WAMbf/5YzMaRMHXUwl6tgZPsAV53zYc3PsmTvaNIpOzSGde3USTioa4jGddMtZ83FfE2q+/gOYld+C+7z6FzQ89ijVr1iKgFVEcOIvMpUEY5SKGtj2F5Jat7OLFhgvMRRpeBTVPlJ540w6761QE9nm57ltx9qFnrGs1Ow1pk1zLrYi880vIQ+cQdetYf/saPPzdp/HQ9/4BG7/5MGTm5IpNT2BoIInBEwOZJheWhVU4JmoYuK4H4xK+tP2RB3f0rNuCi+dOYevD30JTaxsT3ECxWIQ/dB+WbdiCB4YHcfrgPhza9Rocu19CqVRAqvfr0LuXXO4UQk2m90Q+GdLMmkKiUq8GG63OXbNXNJGDb9/v0PHey7gtpGL93/w11m7dhtaly5mCfnjcbg4V33n2H8050slhrOzd/FjAozz24k9/8jqK9b3XAPQ74HMY8NXZvyxeeyce+973rXClNbP5POo1Ni70RNDvYxEOkrlCaF28DOu/8Qge6vsQx955A/t3vobD3hZc2PAICr3b4E5eND0k6P26ESo7mbMJuovd/GfH0PKHV7B64BB6W7y4+8Ft6Fz/Q0Sa43CTUdyqi52HjArJplgqoVguw+v14fFnfmjONT40gBdf+LERlBBk+XDnNIxKNjhpU1T+dcjv3ZAv1vSm7u7udffeh44ltyC+aAnCjU0IRhuhMsElBnuNN3CIGWhJIZQ1MqDwbpI3+OzQH3Do3V3YP17F2MgInFoFjkgTWx/lsogWSSaLbpHX5jIwskkozW1Y2+DBl6imV2zeiuZbVsND9nCz2Ms8typ6URpZZj4qnKtazKOQTpFwxpC4MIAL/afQ//FhfLz3nbTPo45ptary7mh1mwkwTHm5Ne4+tmXLPavExdlMBpl0hpIoj3yxAIlM6AmEmNwRBKIxNHV2I9raAX+sEd5AGA0tLWiMt5Pggqa8qlbKSJzuQ9/+vXifYE+eOIk0G1spFIOD5+ss2lp6DO5CEj3tnVi3aTPu3PJVdN+2Hl6qFQGiSu+Mj1zE2KVh5FMpFNNJpBLDGBs8j/ToRZSyaRQzadRKeRrBiWAggEDAzwIeIav68MEHh/FfR4d6lcnSSsNWRQj6qXv8Xi9FbPwyq7KuleihQqGIcvICBoc/xYl80QwTiTnmYPHVxbUE39KzBG2LliLesxTdd23C0k1fQX5iFB/vfhuHf78bn/UfQSwSwZp1t6N3O/ObYS62JioU1gfe/B8Mn/uUud+PiUtDbKapfVkbtXIBLqeTa/NSlnkRYeS0tUTgXdQOl5BzkjSNlA0zjCc1i3IlYxuMIt0cV788jHUvK6osX7kfWK/XCL6EMsGWuJD0sf0Y3LfLzA/Z5abcCiAc78S3/u4HuPfxp3Dp0xMINbfQ+81465c78erPf8ZJmOP0hJNhH6QXhCeWRr1wk4W9LOwuU9FcCWJyrXVtBtEx7Vxl/vp3ctJrt3W8wuvMF+kq8EIMnD8/iAN7d2H0bB8aupehmSybTY1jtP8ExgbOobW5EXevv5M5rcwIwjBmBjHvhy82U+pCsCuKw0zg6R68nkevBq+Zmy9XTc75XCKcOtpw97rbkCDpZI69B6dTwVqG12jQg0w2B8XpQm1yw3hBelwyCWi6x6z7KuZ3xFVXwqRU9n9tZKnA4MCAuf2g0WJOxraPei0YDFLr+VHX9RsS0pOh5OZcnd1dUx4WCxsZG5/y1IL3TBnOOqVbigSUYxkrlyvmfYTxvOSQItursIxG5d7l8bdl1bNC8gUDp+tuOFwqksUciuMluKQifNVBrGgNY8WypTfeH4i9FoKo17UrrHzD/TCNk0omcfhEPxKaE2WH25RzsWgELo2eGyvCCLbi7pX+nUrTlx/songOmC639/Fy9KROCq7Sm2Kr6oORAUSDI2hrb+ci6wvpW628FFrSmHmhc4X/9XbEjpw6izNqK2SPz+6oJPg7uxBixGn2th6N2qzQumXTwiwFGmk5cekSSWACTrEiTuQQnQOMG1vInM8NpBvKO7EuobCUOpk6WzRnMmisoVM5aG3t8ItOQbRaslyTr7WqdDlpxdZBtQS5nEelpgHGQgFYRVaE5/Wg6PrC86+uESBbNLmYZTdTn1rrJOEYM7VLkkJNyIa2iS7Pis1ckS+T+5q+KC4lJ7Bk0cK9WOU82izeL9fqC86/JJXWhOxDvbHLFPKWoTTEmpoQaW01dbOhW3utUwANFuwaWx+hH7XMuN1HGdYOVyGDls7wgh/4iVukC+VZmFBGgexXqtSgKrLZscz5mwAaSwiBBqmKcnbMlHXmYxpemr5Ygl+RoFKUyHSYua9zRWG1tz8kO5ElgpZLOYZC2lTzkOYPUNw4z8XnKxV7ETN7Q6Olk4XigsqOqJtOow45n4TMFJLsCLmi+7c9O+VBmS2NrLrR2NGDdEUzJZh1AYWvP4qBxAQ62uML8t44CWAupwjswsthj2qK5rlqoqh/E+PsIOBFnYJfFvtDktDLOhop+oOUgGLtU9sp05ekk17TzDWNal/SrF1m0/asi16XMm8PCrGbLpSQK5VN7822aGFEQRqjmfy8EkDM5WKtdpJBYQLRrd1wNs7ZTMos8NIVJCMWwBO1SgkTiREkRxNw6AQmhtgdq1SxJOrGymW3zqtUCEAVEkcinbNDXrou+ZrPIcRumviRTLEMf76EWMBjhu2sORgMYOPSduw/fgpFFnnxnM1gzlVyMgazKcQ7O+H2Bc1HAIpZClgzVPZpPirSsULFrCmmtfi9c/wClvfE4fF45tSLlv4zMDSRQYXsqTgccxpj+rUjqSzc1K9+j2tWkCIce7o60D80gn61xawA0qQkFMI/1jLlDFmAkzmEYs+JZCdrCoDmHgp7tGZHDaFQyFIHcyxWJPbQRBq58vWJZfqrNm1OcbbQu4M0TqFcm97TzQySgDqbonClE9ZjN7Fe4qgSfJ44xNam2EVQUscORGuBBuQYIqJDdooHSmJjplpA0CWjo60VRfEMQBMekaeKvTG9aPCNoPqLySyZs2r3jJf/V6M3BRjx9fR0LFXr1xipRil4fiyFlnAAEZ/bknrGtfcTXmxlU76Sjffw+FmUJHYkbjYFhoTz2QkEwg2MyLJfOXv0o79wuBzbYj51x+LW5qgmscUJuKG6Q1DIqqI2nSeDuqnSfaoLXg5VPLez64ko5NlihaNEDxhXgDPsUiDOKROMT3XCsC1k7tJVqhZJzEA6FxgJqYKKMEF6nNZDVnGtMFaJqZIvVU2R4IvEsDQUQYUNt9jmKJeKcEgKMgMXMHBp4nnlSAGv+4va6/f79Y2LFi+OjvNC2Or/chxbxCEmnKDFxCIcNnlo02rQTGFp/hKGc2XJqCK3hIgU5wmPlyn/zKfDxrWlQ1xn1lE73CfZWJsWApcZmsXd54fbH4Cfn2NBH3XpCbzRP/GyYtG62EOVZJFn+uQD9hkIRLoqB6SriGI28kmRIUNeN/yMAJFro9m86UVpniQ01/3MhsGODBG+wuwOCZ4bbsqkBZ4rSGxgLI2wVzVzr8hokBegjG70pzg33nUuYGWG/UYQyGjWIhbF3s6/2T+pVm4+vsnQNq4Kc2PaXsrNA/mn32z/CeCcmzKXf/Qzk1g3cHNz8P8EGADoEz7iM5u4dwAAAABJRU5ErkJggg=='
-
-EMOJI_BASE64_SANTA = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjQ0ODdCM0Y5MzQwQjExRUQ5M0NERjlEMzk2Q0RBNDlFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjQ0ODdCM0ZBMzQwQjExRUQ5M0NERjlEMzk2Q0RBNDlFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NDQ4N0IzRjczNDBCMTFFRDkzQ0RGOUQzOTZDREE0OUUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NDQ4N0IzRjgzNDBCMTFFRDkzQ0RGOUQzOTZDREE0OUUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6dQR9sAAATTklEQVR42sxa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'
-
-EMOJI_BASE64_SEARCH = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkJDNDI1OTlGMzQwQzExRUQ5QjBFQjEzMjUwNkNBQ0QwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkJDNDI1OUEwMzQwQzExRUQ5QjBFQjEzMjUwNkNBQ0QwIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QkM0MjU5OUQzNDBDMTFFRDlCMEVCMTMyNTA2Q0FDRDAiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QkM0MjU5OUUzNDBDMTFFRDlCMEVCMTMyNTA2Q0FDRDAiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6a40hqAAAatklEQVR42sR6CZhU5Znue04tXUtXVe/VK73QdNNNNyAgAaEFRFRERHEkQY3BucmIM1EnamImyXXmJo/x3quJmXG8M9cluMWYGMWJC+AGxqsBlK2haXqH3peq3mpfzjnz/qeqm25okdzM3FvPc56q7jp1/v/9v/d7v/f7z5Hwn/xKMwIGFXlRFRWlJpQ7jKhRNZTzqzwe6TwkHkEe/bKEUwEFB7viOKTIaBiN//njS//RgOwyL6qiJNuIKquMlekpWJSXiaKsTBRkZyEtzw1kZQDOVMBi4bmcQTQG+PzAgAdoaoXa3YvuAS+OjUbw2pCKfxuMYZSL8v8HIFcdDhnOLBkLrRKuyrbhitICVJYWI6O2GigrAXKyATcPWHloF56NEgIONwLNrUD9EeDkSbR0jOHhM3E871f+HwEUoJwy7JkSVjgNuKkkG6tnl6Bi0QJgYS1QVAikZkz5gZhY/EvATV48EdH2vuT7aWDPO0BjE15oiOBvPDH4/9MACmCM1Jx8A24tcmHLvHmGqpUrHZhfPYaiAs7ezJPUJBjlz6CFARgdA9p6GXQTLxkBdr0F7P0D3v0sjJs88YsHKV0ssEwZCwoNuKe2GH+xak2qc836RSidQ85FjlEiBghKu7gIXfRqMie7mZN+O/rsFWhMXYI/fKDC/MKzrx0K4auMpPJnAxTAsg0ozDPgB5eUYtv1m5zWNTesgauUXBw5zBl8yEgF/0OlagwuNEmV+Ey+FO8pa3BMrUanuQKqyQCJ0Vz+s60wvfbKDz6O4ZGLEZ4vnFoqaVIk41vV2fjJ5s1m98ZbVsNReR2jNQp0Pc/3Nn2V/9yXDw40SlXYLy3DXmkNGqR5aJHmzDw7ApSDIdR9d1nEU19/WUMUh7/s+saZ/plpgqPKhH9asRjb7rq3AsUrv8YzqxixPTx+zahF/q/BhWHRAX0mXYr3pStRL83XIzbja0qE8mMdKPE1YbG6H+5VwZR9TfifpxVczbqp/EkAM4xw11jwm1s3S6vuuH89jAU3Mc+IpvNfgeGPEqv6J4ITAI5Il2CPdDU+l5boABWhJBd4VWjNmIcGrFL3wd13ENm+FuTGvTBy/EgFXUEV1p45ik0tCl6/aICZRtYuK9746780L7v5O7ezaq8BQj6gh+DGj+JL5jT56qNJOSYtwAfyWnws1eGkVK1T8UKvOVoL5mv1uFL6EJfJB1EhNcMSH9e/G+GCdrBkhJPjm0nVulUsHS34Xm8cvw+oiH8pQJsBhuoUPHvHVtOym+//K9qMy7hUHKDnSYI7fkFwUdaHBqkG/0dagd3yNTiKheiV8i8IqEQ7jRqcwDoCutzwKaqlUzBrYyIpMUJHM8xyk5HFadDM2YWhY+prWoJAMYKtYBSrK/CVziNY1xLFrgsCNPBXs2RsX70MN3z9/lt41a9Q9plng698IbguqUin227pGvxRWq6Lg3oB7mbBg3laAyO0F+sM+1AjNcCuevSJ97Cof9QOHGpgYe8AhrxMc2ZWJs3ClSTRzZtpWkkAD8+V5ARQI2e+eCndTiPu7FWwK6BcAGCWAbnVWfjRt+5dCSmbV4zw7ACBjeybzLc4Tz3BKH0krcIueb2eU4PI+UJAKYjogFZIf8S1hvdwiXQMbpW2ZISL08Oi3UxAJ4DTnUBvP0WZ66mZLZCsNsipNKqyjFHvMJqeHkcbwf8NSTUyflZ3RBQrGcVZ+Vh7qgVzAkDLFwLkQt2y9kpbbtGy9SR6XHfLGNuDYS0Nhw1L8JZ8nQ7suFR7QXEQtFtE5d5o2I2V8n62DAyJT9ULdj0B7acnaDudiFg4mgRks8HgdkG22qHKJqgGHiSixBBJ7mKkDHRgz4eduv2rW82AjycMusopinWorkbq0Q5sGlDw2IwAWe9S8lOxecM1vIIxF/64Fb1KFh6LPYL3TdXokGefXzmNCTuVhQCF4ThWax9info+anEc9pgHfgI6xTL5C2GWCayLf/tEQ5RigWy3Q84jIJsDqplOyJSi67wa8EEZGSY3k3phMDCS5GVOCUzBAH73hhcFs4Dc/ET0xEuAnMvqlb0PN9pjeJxicx5RjZnAooxiV/WpeXehOb4BQ7ILp+IWPK1OKbRSssgSWPF4EzJb92PxwFuo8B5AaahLNwWKHdhJqn1GZncxQh5SUTWYIVmskDPTYChxMmJ2aElAOtlEMqmJv2RGUuLf8VFvgof8rI6N6oPL+WXwN47hjd/H8c1vJiIofiryNL+Ac8rHwhNjOk1PnQew1oRFzbXXpz+f9bdYqyXs2fiEWeZnq1nR5Tvv+Fsw7X0Tzt4+FKW6YHHOQlb1NkRK8xGIxeHp6cbpgSPwKH0YHjsOhc2eXMi+Ni0bCmcjaeo0QDMVdYkREwmgDHsSKJiH6vgo4tY8mAuK0HiyA0dZrZZSXCKRRARtJEFpKWzuVtQNKjMA5HC1WnE50qUJMeER86EOn2FryjvIObEL9b89iVicmnzDdixdfwPyykr1cyPRCCKBAJXNALvLNamhHaca8M4rL+HN556Ff3gQEiMAcwpBqBcuoJyxbE+FxuuqvnEdoP5vUjeemQvDUD8+2hdCDVsyWlOoSRLMZhaZP8A6moCn49r5IlPod+TBJUUwmyU6X+3BZmUHMpVnsfNpql1DPq6+6yVsuO1WRLlsn+99Fy88+hA6O84gFAkhyslIXG0L1c+eYkbN0stQeulKzNqwFZsX1uHYy0/h1MfvIppVRDXLT0bwwi7Z4EyDFg5Di8f0SArASiQMY14ROtubceL49Cjm5FLgsrCwpRuOcU1U0ikA+VfqtwOP4XbFg0yJldVsRIwU+/HDTObCbXh49/+C1WrEi48+jD2vvgKvbwTW3FlIcWbAmJ4Po8nEVdQINozxoB+nd7+L0I6nYGUkajZuwfJ7H0Jx3ZX49Ikfw9vDNq5gzhfTFInc0wXG6SRVvWeDOz6GeFY2ZFL/wIEwLrkkwWKRh+np+lFs7oagVv20jkgUhZpIMyPGYmO0ITwWwA8faqeh/W/4yY4daD36R3zr8oV4+fkdXKZKFK7aiMzKBUh1FyAl1QkjldFEIbGmZcBZUILs+Usxa91fwF42D0defR7vPPB1OHKLcO3PXkS+y0ZP28hRDecloET1lJT4pPiIsiEJT6bbFyKJRaFEo5Cz3ejgVM90Joq9+JrEQW4u09SMqplavoBPyK4WZf3R8D8efApldd/GnT96CG+/+Ax+eNtmBNMKUFR3FUFk6rTRDxGFCeHgoZErGic48Z0tfxbyr7gRUaMV73zvGxjvOo2rHn4auQ6qQh/tisGYXOGYfkRd2fox8bceRWvqlPJEqgb8UB0Z9CEGnabJFNWnUJCv6+LCGfpm9IsdLZiDeOXJ1xC3zMX2//r3eOulHXjivu3IWbQCrpI5ULmCmnrx+xBaPK6Dzqj9ClKrlmDvI/djrKsda370OJzRUWg+L2QuSDC7GI3feARH734aR+95Rv8s/idHw7oJmIy2AMikUySjXuGbWV+DwURwdbPC7EqRUWU8p4c0FBtRU1mOKwrTxvHLX0Xwk1+9gcZDB/HYXV9Ffmk5TFRAVTJ8gTAkqCUmKhE8pwBNmEXp7Cgak8SS6aYzMaPt7V+j6vpb4SDNuj54A+GS+Wj41uMYq74EiimVpcWOYHEpRkuXIuv4XhhjYaikJZJio8+BvDRSQiMDo6iuIbD0ZJ9JwWmuR6A/hGfC2tnJynRSTYNeKC+/0I3r73xQV8Nn//4uXLveDbNwG9rMiifHqJ6MUDijAL7iWozzCFIppeR3UxdEpQo6yqoBRyb2P/kTlK/bjOLS2fDklCFYUpzY9lWSBz8HZxVjcNF6LhzparFOX1JGUbM6KGq0fN1nbZudwbbZkaGoSJumot0KOo4cw9DshfNz779tK5579FHUFLVh6bL5+Pykct6ugXAbEgceL1uIgUXXIOguRUxQSVyM0m4bPIPsI+8ireUzPc/0iAqQjELmguXo+eA19B07gNot30T9zp1UAKISDNGmbzP688sT44n6OcEIQVNeR5Vp91JS0NUVmcxBsYnMf7n42cV/DU8GglWhxetB94ob/woROuCDbz+Dm79WypqnzGw3SMe+ZTei5cb7MDp7HnPWpkuxOBSa5/HiSrRtuhs9l99yVoT0n7KIU3FTS+fi5BsvInvRSsyJeGE7eTCx3XiOMqSMDuq/1U23wXj2OiK3RR7S8g0NJqKnt08UXFYsOz/ap5eJOHyubJu/bsMmHNy3F0U5QWTMdkGncdITTqWlZ8Fa9NTdqPs4QzTReExGVxXn8J1r07fsGgws2cgBImdP4GCpRXPg6WhBYHgIpTULkXF413SADJjBF0IOWaAJgRFSaZDP36phuAKkM42UXgoouuJI0RL752fnHFYwt3DOnFJ3QSE+efN1LF+9QC/ENpukr7oQD8FTISYRVw4nfgNpOh3YeVt1wtPyZ/2XbkAoa5aeSwkqqTDa2SGYzBg8eQRuRjFv/+uwdPYkQDIK1r5uVL78D7D3NkGlMCU86Tl1UzCD16C30N2MmJ9YA4NhsjKczUG7hEp3QVGB+GO4tw0lG/kx3o9UBtoo/F6yfRFAx8sWsVY5KeEXsR9JgDG7BaMVS2H99LVpuwIp9JWepnq4N29DzlgvFvz8GwgVVelssfW3IWXco9P9bAmUp6WocE6CtrEQx4if7S5m0kNjuQGls6rnG4PhGA2sD+lpmu642bbpx3jkLMX8+XP+pN1rEclAXvn5g9qd8PX3wEwnZHakwzg6gPTQuB4ZEbWp4CYif76My4kUV5OWTdVtmyJuVk07TeztONIzEAqEIMVHYDP06yqW5gScDiHL4bPiNtVZTMkHMbyiJdz9tENsSLGpVafURd2GURHivK5MATHQjjEeBGXVD20mOsanb5pJ+saMqgObuLQolYxmMHmvcVo3oYkVkmRJH0gN9ZJOVqRQj8R9vE4PHYWSUFRDODAJaoIORo5l4SAmOcFCkfAT38f4D5sWQwrlLSIAi3ZInuDSxIlfkMy6YeBvfGMsDdFp5kEMosUVoZr6Ib4Kkq6hIDwGCYNTWSbm1z8y0A+HMxXjITuGhoIociXGLyuRcPgEC7oo3KSEta8VSvVSCAI5eeF0Y+KGp5mHUZoOXLwpPCcj7kVaYZEOMMw6GaTlCFB0zOS/sH8x4VTM9mTHK01Wbi0chOqn9wwHz9/DF2WDv2PV0eufEFrPEIF4cUaRMTJ148LYqqCts/FEyGSQrPG4Faeah1E016lzrrxMYmQUDuKHYnMh88wJgg0hnYbZNqW70amoTt9tV0UAwnHYOk9SEKjfnJSFs0nje6DpCFLzSxAeH0HY74Ms9h2E0SNgWn/61JGEYzEk6t3UhlhiGybzehpbM1smGZKcyCk2Kd4w3j73Jqkc0tA41NfdIyxZFZvVfX/wT9omsZPlzk7sjThdaahkuBacOQATx40JCqqJdyUJUsHZ9zjpmXZqP8yeHma+TAFQmEoJA+7v70LO3Pnw9bJpJrc0gtS626B1tiISUzBcuwbt2x+Dd/n1Z21fEpwxPRPGvnadj/MXJFqlQUbv6FGMDCn47XmCxpzubGtsbuhqaSpfe9PN+P6LT6KrXUNRGcOfqmJ+rRnxVjfSc3MoDFHYGz5BmskOz9xLk/UxSUuRWoJdSdeVfuoI0mmYFaF2Sd5K/Owb7CMtw8ihwT7x8r9AIUC/MRX+5asxungdQgVU3bgKZ+sBWFm29F9ykjKF0MhEN3UxVMPDWHE5ULeSp3L8D99nfziIfx6Ko/M8gKM8YWAs/m8f7Xxl0+0P/gOyS6rx5jse/PU9jL+aihWrS9A5koK4fwyq2QaNnXXmoV0weboxzBoXzsiDwkwW4GSGM8UziLTmA3C1H9Fpp+qtU0zfdiCx0Pv5x8ieuxBmekyxd3PyB79DpLwGhrExpNV/iLy3n4K94zgMAY5HG4j0HJhsVhh9HkgdXexOYpi9SMaWm1VeA9i3D/hkPw50xPHfFe0LNn69wNvv/XrHwFf/9u/cW+99AE/efzu2bJmNrNJCuC1GFObF0NI5AuSl6t2F2BBKbTkEW3ej7m5idPcCoJF5YR7pI+/9iIt/EJQWIQWp34ozEyOyGZ7ONly9/UF0fvIu+gIxpDVxMd74Baw9LSxTXAgRcbZNam4RjLRjxvA4NLbwUjCAwhJglOqWyXJss6jY9zHw+htoO+bHbcPK9PIw5W447Q5TWxoac2XnOC+//o478el7H2GwdxiXri6mg4nCRod3soGD0w+prIUqDaAiJhOLwTDuhWmoB6aBTsjefqiciCIEgt13xO7SWynvsg0YWXolzvz+JVTMLkXpqg34+PGH4PcOw9FRz+hQVGi9NBoAKT0LJiqsORqA1MvOf7Afhe4YbqT9XbRCwpE+E2ryVbQcVQW4E4fHsJngmr/0Dm+OjKyVRa6D/7TvcKnYBvzOtSvxvQcqsfjKYk42Ii6GhhYJUkEx4uw6NLbTmjQhm1qyPGgJ18EvBtbehlBhGWQuhoO+0vvqv0DqPoUNj7+CeubeH3/9S8QyuYBULLE5bCBlDVxMecwLddgDAxW1mK3i8hXAgvlANjPm/eMG7DlggN0Ti3a2ay8dC+LbTLHQlzzPMHHnFUHNF2kbbDq89abt90ql8xbhFw89gcqSFOSUM8E1LlNTXG9eNdJNEVsYzHAhIFrSH07UbT0fSVNn4wFkfr4b3p3PINzTiqt++ksMnTqGT575OaJ5FTA4XTCzOzeGfZDEDYy+LthVH2qqFFy3EVi/PnGDRew9dZwBdr8roe+EEvX0aa8x3X/HAlImEoFzH9W+DKCW6BKbw+2d6khP85qv3v0ACqqW4uH7fs4mK4jaRVRRTUZXKy0d7YLmyNCjpaln9wcSBiXh/i3BMSjePrR/+iFLhoSrHn4GoZEh7P3pAwgZGTEumDzILqK/G5bQKIpzo6ijMm68Dli9hiWqKLFYba0E9h6wazdLIseqroB6RR0WrFqOrXWLsdUSwC2sYntJ076Legghi6tVKeNn1339a/fd+cRzeHnn29j384dQktqNK66rou0pQE+vEWoao2gRoiMl3L3otvUblBoigXEMtjTC23QcRV9ZjWUUld7jh/HBT79PkGOi0wGbErjdQEUlD4rGrFmJoi08ZR+n2tzE2lYPnPa4MEYfftumMaxeRZ0jVTNykgWX12k7Ctz9A3zy4RBW0y3FL+opC/0JCw3fX7Fs3o+rb7/HlDVvCU7u+j1Ov/8bWKIcXUqD3ZkGs80OmbkjPGyclA1TWMaGhhBmvcwor0Ltlr+k4tXg0Ms7cIbyP6sghiLmVSENRF5u4hEvAZYODr0MptjvPHmKn72pCJsLoKXlIMoxYgO92Fxbj6/dxN9knPOQEdvbZ/4VePRXuKNNwXPnlgrpQs/IzDHgmkKH9Gjl2g01VTdtgyN3FiPTgIH6g/A0H0d0bCRphHm+yQJbdh5yay9F3sKlsGfl4fSBT3Hit/8bBeZGXH8DF21W0tpx9b0eoJtp196WuGfoDaYjZnbDThGz57iR4nDozAhQlXtb2jFX+wR/9x0VhRPRm/JoiZdO5t7vovXd01hCNzP2Jz3plGWEq8yAb6a7TLfl1i5ZQMpJ2ZU1sGXlwpBimbyKTDsWo33yM696jxxE32d7kKa06G6jkr3s6GhiF6yXBOggII/fBn88HaaMAtjc+bBlZMJktSQ7JEW3dInbhEb09fZDbtmDB7cHcGltctJTI0Vq//ZXwCNP4b7jUTw+NYoX9YySg3ZgqRU7zA7LNwpYjILegUS+sS5KsonGXjTJAUTHBxEYHEEO86SYRZnuCl76g0EvLVrEgUDcAVO6G9ZMNyz80uJ0Jto0fWdcmbEll1n4/bRz3Z9+gDs3dmPztQlVnRZFppTI03sewJndrbhkUBE3yi/wINC5r1wDtlC5tp0ZsaP8+tuRUVJKD8nmq+0UDvzjgyhxR9Apng40uWCn/AXZlTf5mRxRB7t3F0xlqXCkpiLTbkuI0cStMoV1T1EntpARlwwz3Iuh/aMnk5xuNLV0Y8RHcco45ySujYv5fN3VKD7UjtsI8ImLBmhlbZ/twh3/5XbglZ1e7HrobmSWFDFXShDyhbGoJoZt24B/fpLNcerlyJw9O3Hb65xJCsqFwwlXLkkaLIY4hk0OHHVWIkIWzPe1ojA8wM7DoIOd+lujkWUnMxutnWb0D0WR5UxuMGnTnmXRn8j4zZvY3tqBpyN6ab+IZ5YYh8oVi7HKXZ14AGDRvEosL3PD2N4AW/8HuPUWVd9l1lNG5I7YmD3vYE/JxNiwtBv33HgSyysHMQo7Xs+4HE2Ocpy2FeKt7DocclZBnmHTR8BNzUhHfyAdrVRaX2iG5GKBSKcyX12H6nwDNp1X6Gd86JXlqdiAH9bMxqUjg8DHn4jbVMWsWUUY9QVpr/r0fRuxLyVuhoyby2FNT58UiMnFZXO4aXknNq9pR152AIvLh5GfEcDpASfa41mchaa7nx5LHpxxP3Kiw1Clc9ae1PYM+2GP9GMOa2eabfouxgQalx04+CmKe0N4gTxSZgRI4yHVWPDdusr85+YtX7pyxDQPR8/MQihuYpHvQQftxUBfLzp74zjMXvFYQwqGukKwFs5GirjFNuUuVDQuo7ZkFLeva2F0ZASDZn3xinPHcUP+SbozE47FSxNbcIKekoqKYNc0gCJv9X0XdiW+M72oqogjzZHYrpgWcK5rWjrw+WHkN/ZgJwPdPyPAbAOWXHFJ5avrv/uwPWDLRMyS6KStzLuU/BIojiz9ERD9Rgtna3LP4VJZEfH2wFZQpk9USpJLVSV8/cpW5Lr9CATMePz1ech2seFNDyPFSfrSRb46OB+akEb+rjTYjaLw4HkRNFJNw4oCz0AA2eYR5BUlojW5CTdx+4KRPXkCUnszOj0aPp4R4BwzNq25actVPtkSa6r/XDYirGpi60BVJBPdvyXVCQuLuohYlNzyn2lEenmVFvONSrIaVp3uTEUYAEXVIqwDY8urhiSXLS7F47LitEfV3PSQajJomn/MFP3HY8tiJ1DKiqOqruhY5LLREz6TGg9pkiQybfKQZDmkxOPxkCobxjsHpLmlQnMlzZEixSWFYY/zSL4XuCW15zTWsJVs/XcBBgBgfpzLi+mf8QAAAABJRU5ErkJggg=='
-
-EMOJI_BASE64_WAVE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkRGNTgwMkZBMzQwQTExRURBNkNDQkZERTBEOEZGMDRFIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkRGNTgwMkZCMzQwQTExRURBNkNDQkZERTBEOEZGMDRFIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6REY1ODAyRjgzNDBBMTFFREE2Q0NCRkRFMEQ4RkYwNEUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6REY1ODAyRjkzNDBBMTFFREE2Q0NCRkRFMEQ4RkYwNEUiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5C42NVAAAXfklEQVR42txa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'
-
-EMOJI_BASE64_DEPRESSED = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo0NiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Njo0NiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6RDBCRDY1RDgzQTE5MTFFREEzQUVCMkM5Q0FGMjBGQkQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6RDBCRDY1RDkzQTE5MTFFREEzQUVCMkM5Q0FGMjBGQkQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-
-EMOJI_BASE64_GOLD_STAR = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjAwNzJEQTBGM0VENzExRUQ4MTVGRDVBOTkzQTU1RkNBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjAwNzJEQTEwM0VENzExRUQ4MTVGRDVBOTkzQTU1RkNBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MDA3MkRBMEQzRUQ3MTFFRDgxNUZENUE5OTNBNTVGQ0EiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MDA3MkRBMEUzRUQ3MTFFRDgxNUZENUE5OTNBNTVGQ0EiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6kluKgAAAWMElEQVR42txa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'
-
-EMOJI_BASE64_HONEST = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMCswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NToxMCswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OTcxODg4QkEzQTE5MTFFREI5NzBDNjdEOTlGMzkxMzYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OTcxODg4QkIzQTE5MTFFREI5NzBDNjdEOTlGMzkxMzYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-EMOJI_BASE64_ILL = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo0NSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NTo0NSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM0Q0M3NzQzQTE5MTFFRDk4OTc5NDZCQjZGRkVFNkYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM0Q0M3NzUzQTE5MTFFRDk4OTc5NDZCQjZGRkVFNkYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-EMOJI_BASE64_ILL2 = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg3Rjc1MzhFMzk1RjExRURCNDE5OUIwMTlERDQxNDQ0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjg3Rjc1MzhGMzk1RjExRURCNDE5OUIwMTlERDQxNDQ0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODdGNzUzOEMzOTVGMTFFREI0MTk5QjAxOURENDE0NDQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODdGNzUzOEQzOTVGMTFFREI0MTk5QjAxOURENDE0NDQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5KgkPlAAATKUlEQVR42rxa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'
-
-EMOJI_BASE64_KEY = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxMSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowNToxMSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Nzc2Rjg5REQzQkM2MTFFREI1NERBRUFBN0E2RjE4QTMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Nzc2Rjg5REUzQkM2MTFFREI1NERBRUFBN0E2RjE4QTMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-EMOJI_BASE64_MASK = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkEwREMzM0YzMzk1RjExRUQ4QTI1Q0I5Mjg1NTQzM0JDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkEwREMzM0Y0Mzk1RjExRUQ4QTI1Q0I5Mjg1NTQzM0JDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTBEQzMzRjEzOTVGMTFFRDhBMjVDQjkyODU1NDMzQkMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTBEQzMzRjIzOTVGMTFFRDhBMjVDQjkyODU1NDMzQkMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz72uRrEAAAUlUlEQVR42sRa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'
-
-EMOJI_BASE64_SALUTE = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTI0VDA4OjE1OjA5KzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowMSswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yNFQxMjowOTowMSswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDBFQjc1QTUzQkM3MTFFREJBMzhGMzA3RkNBN0M3QUIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDBFQjc1QTYzQkM3MTFFREJBMzhGMzA3RkNBN0M3QUIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMEVCNzVBMzNCQzcxMUVEQkEzOEYzMDdGQ0E3QzdBQiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMEVCNzVBNDNCQzcxMUVEQkEzOEYzMDdGQ0E3QzdBQiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnF7VKUAABYsSURBVHjavFoJdFxndf7eMrtGoxmtlmTLkmVZ3u1gO9jESeo2C+AspdAmnJwSlpJzOFAoBzgF2oalPYWWtuRAKWubBppAOEBoEpIAie3EjhOvkjfZsqzF1q4ZzYxmX957/f73RqORLFlyGpij/zzNzJv3/u+/9373u/f90pNPPon/70szAKPkvfjfLwGqgTJNR8Aw4ONHbn5ugzXkwmk58XOemoKEmCwhrCoIhflNzph9D4UnSdcxp1tvvRXV1dXX9ZsFXy5xcwNNtQpaXTI2SRLWN1djRa0ffqcLXtUGNyfvFPNUVaiKAknXYeTy0PiZbujIaBpSmSxisTgiF0cxFk/jAkF1DmXRzZPOJyTkdWPpc9q3b58JUn2joIQJqhSsrpawl2DuWd2E9W2tqNq82Q9fVTX8tRyVHjjVKG00DOSHBJb5LyYmnudfFpiKAcEgEI8Dvf1AxxlkB4fRdaYf+6Mafjai4WBCx5KhSm8E2DoPdpTZ8PEtzdj79jvLynfe3ITqlWsBH4caICDOcqqL4ySQvMz3yaXNRCrcQJk9sygBnzoNvPAi8HoHDvfH8A0CfZJAtTfVgtU2+Nrc+EJd0/KPyOVVdq/rPAYmq1Af34Pqyq1ApIPjaSBxjqCyMyuylJdRGLplzdKXjxG8ew/HzcDpU9j5o59i57EOfGg4jU91Z3DyWq67JAuKAK+1oX29F4+VL1+x3b6sBZnxK5C9NTDKapEZOosffGYUNQ20XLbEGiUvfQGkBk9UFjbE1bN10H1HgOdeokV/hakTg/hoZx4/nAvyuixIcGtvqLI9qwSqmnW7C5nQKCrWbofdV4XxiSCypNH3RT4LveVG0iLZgJfVOG1xlAhBgNMWuJVheqRmDgFW5tkqfyne27laYjiMDNxIWiOfhDOQgP72Kdi2xsprHzv031sOn3J15PHd+SypLsEt/ev96hO6x9Ms8QruQB089S30wDTGRkeRGe7DVONqvLb2s5ZrvSm8vIifiUTjFysPeL8wIe38uzv+feuRkwMdObygGVdzxsKuybGmTPp7Uvtm1elB5cZdsHsrMNXTgWhPJxLDA4hmDBy5/xFmuYVJ8k1/TccqwyFWXo3Dn/yJWtVQ9S2mqarrsmB7GW7wueQP2xtWwdvUjtTEEGQmOXfLRkz0XoR96DRu+cgO3LPhJ3CmonCoGSY7MdJwSNnCClquNm0GO91NNmcnISvZ+a1surFw4SxNI/P/HI9pwyGuggyPKfOqdqQMFyJaGeKGBzGO0bgXCakM6doKGHftbWn+zqMfG9fwcN5YAsBqp+Rq9Kn/6mpqU23eANJjV+iazZC8lRgdGoI+3oM/f2cCdzYz2s++hLzIYxxM2NaRGPK5wpHvuS5gckeuhCG99B8bZ0ClA5n/UwDAZrP+p6IBPccaivWdkwTjEDayczDzXBrkQdzDLmNouQv/WYMPuIfwyJSByWsCrHagalut84cVrZtv0TgrxeaAr3m9KTXGhwaRv3wOvuwEXiS2nz1lAckXgOVLAAqbGdIS+dow1ZDpfVQ9lDwlIBVr2AmsfhnwJ3cDb7uJ9+H7NO+t5nWsrExg7Vo0do7ijikdT8wLUFx4mRPtm+rKHq/efNNWV10z9FwGKvXWVDSKiWAIGO2BMtaPsKFiLF/JZWXwuelmYtlLhizLBVySZb65pGHMg1CAFFxKk4qF1egOaTM/agXz53ClK4TjnUl87MPAzl3UEgkrHMXYsAGoPIR39+bwhDEXoAC3xS/f3FRT8bhv0y0Nzqp66Brp2mZHOBRCcDICe7gPGOth7DiQW7kOhttn+dd8852XGa5PVBl0BS06aS0TzSf7PVDqmyANnMf3Hg0iQHetrCuEAtegvgFoqcW2o73wk/DDRRYV4Db7pXc1N9Q94992hwWOv9K4YkETXBjKRC8ajYumzM/VrIDuruBV6Yu6tsShLzKu/o2k0BO4wEYiDp1A86NDVH0p6I2tSGo2HHiFrlzIAwKgj1OqrsVyhmp70XAqT9jowwdbm1f+2L/tdq/N6zfBSXSryNQUInRNOdgPOZvAZdsm5CqqoHtoOT3/e0gHBtVSOSSXy3Jz4brhIMsPAq/w4/wF6tSoFRXThmpsgERDbigC3FGp/qCtfe13K7busSkOF909X1gR+j9JRZ0chJRLQ1u+mVbzw7A7odtcRdcsnYySTc0aknH9iVESYZEpXINHmYste7yFLy0q1lMJSP5Ks+oYHraIqKi6mPxpzI3FGKxxqx9wNq6DAKfnsoXrSIznHMsX5qx0DHptq7WaIxeYo+gAkmwF/vSkhEvxNyM33ovQ+pvNJfV3vYq6Y8+YEzZkZWmVCgktHajH2I69iC9rgys8iNqjz8Fz5Rx0FpWGCDaxlqkkdF85dFlFb28e7e0lwpxu6mZdai+EtPrph9L41s8OIVt+F1S7Yq6QAJhMZ+j7ERg2J8POASeTujYxDK1pC78vKeENi/V67v0Uhv/gXcXPQzfchGjzFqz5yZf4mW4tyrXAcfLJ2mac/eC/INXQaJpBSKnR7Xdj3WOfhffVZ6wig3MzaAhdUiGTwfv7pswQNgU9j26SeoMX1eWKxdXyrtuBP711FBOnjnMOatE9E8kklPQUMpIbm9wd2BQYRJZAdQIudU8ln0G4dRuGdxNcBjMjDUy89XZMrtsNJZdZ3DXpEQN3fNgCl7JkmDjmy8vQ946PQqdEhDGDRCfDSu4yhMNWkSyEgJiWKQYc8JJFPRaLsnLeexewNdCBUN8ArehAnKyVp5/nM0LFx/Dp+0dNhSHSA0+YHX/8P75inSVcjauzwtTKTYuDo4tnPX7EGtZYXZrSF98nq5uQqVsJWZshNkMsGs0lwJELTaIR0yLpCkHg4v9uC6AuqBR46H06bMOHEQtPIRpL0D2jSEaTePetaTQw14yM8Tyn6+qkLayYis+vVETjKRVbArOwTNJy5rjqOkIn6PxOxHlpLAvNR8JL0cqJRJFkp1WPgwtsNwF+Qvk6MlkH6lcD998WxJXjh5HNsT6LDODB+9bhgfvcphvExUXs9quZnJoqcOEwbKGwWYwWXzxViaVQeebAoiRjMD7V1BSqTu+b6blN535GRODC63BNDjM8SrxHuCuvK6RgbKpkPWRzyIblU5AfkT+Of1M+CZH312wE2ip6kbjYjQffHsKHPtoA1RhDgvGUETGh2q6anK7Y4AxewZoffwmukUFLCIs4CI6h7cdfhme4mwxoX7z1qDqx/KXHUPvyryzh5bR0lv/kYbQ8/Yjpg1IJURmiLcf3YvGEFRd6mazyReVhrJjYh+2Z1/DO2/K4+I2L2NDKpYl00hViRQFdzKhzQZJ4KrsOomzwAuKNbeYSeoYvwhkepdJ3LrGbxWXPZ9H25Jex7PVfIMPCWo2F4es7ZbqurtjncV/JvFcupxUtXhBGeanQ2TEBirrrb2q/j0f7dmP96jDecgNjbtzAetE8WmKRrhGkLRlG5bmDRcsuGdy0VWSLCsv7OiFdOmkCEG4pcqCpxYyFOlUzHi1O48iKcnOmouc5fe71+FrLf+BMtxM93VSZeVPtmt9N12VCHxr5/DUmqBKUyxwiNt9Ye0KAckBzuMwFMgpuaRC4MUs9SQV8hsnw0wYVWiWbRVKkcsuC06ULF/tETx0yP1L3T47gdDqNj02Dd1i5xfRTg+pGsttmM9rv4yVY1NCKdClReAopKFKMyz0DkPoEnGJCLgCU/2LiS7DxhMajz2LDw3e/dKw/fk9CwcuTk8V+H5hr4WXaFOAM2l+nVJovXfxOdbcggtK2GS0rZKCwb3l5MYyRJuEMxRCMapbvqh+PPIxUxwUMff/pX54cij1AXHG/gZDIe9MA7QQY8PMmY7Qek4weYYVBFbEQSLGqpj41jDfupozh0usb2fSczhpDIJOEh8bxllnkIgDGmHYTFEXTD2/Up35BRK8+/sTpSbw/aIksDOXIMRNIinakVGintzQDhzrTZlPIrLajrBH9VYVKfLayyVTUUttWF+LHMFfarCwWAiz0pchpitWgEazpDA6ymkhasxaxPycXyFRcRmQc5azcWDkVAQrPY/BcmF4a9Tf78ZlzKTwS1JEt5mgJQ6xxh8MhtAZqrM82tFtqX9ayyIvKg9lVIvOIeq2ok0o4V1QFkdbtSNS3IFNeg1wZSy2bPJsJC/GvMHDs8RAcTCvl/WdQ0XOkkAFkk1i0qahVSUxblMJTFguSjGPZSphWzBZmL8onLsu5Yh48msA/J+d0znUZscEJ9I0FCXAZTGXftorVciXo3GHI/jpoiRi0SNiMR4kSTiKVS0LxchJ2rn71+GXUHHkaeVcZMv5a5Kg1c24f8u5yWspmKhFR86mUhLZ4BLZYEI7IGCQR5wSl0/p5xrsZ97kScIJguMCynjEDrnX1DMHwVIyPIzYC9BYBJud5LBDnZxMJvNZzCbet3WxVB9X1wDpq4X0nJiHXNJr5SayqQUEuxqzOlfBpybqrFJ6EfbAPjqti0ihOWJys01o5SVnQhWdV+Z4ySJERkp+B1lbLPcXajoXoomH08t+BRTvb9PhXOs6UdKsZHn94C3+QZhlFAS0q6qLCLaqK6dykFxukJusa4jGuAk3kyeKwWYMKRaOUEzm0eI25Y3ohRK3q9UEhwejBCbQQXE2NpbJElIzQPQcncZR3z8rSIgDH8zhx4SKGohNWbzPM41ZWPi1NvOBAHyVnDkptvXlDU6Maxuyx0GQXAjCn/TEzrGJZYrJTqutgY86SR3oh0x9v3DH7590XOM8cnjdK1NeCAEnKoa4hHDh9lidz/pdHya4U5HffS3ctS8Lo6oRzlHpTYZlVUQGlqhayz8+JMGGS4SziwdXAFxtixnR/M665eHJlLWyVAdhddjijo5DPn4Q6OYY77oTZqhDhKdwzGgEuXcIYDfPKkp5NiP5+NIf/+c0+vPcmuqaLc44wx6xmUH/iL4GXXjbw2pEQdFKtzhWQnG5IojkkADqd/Eyx1L5o5Rootg4NzLQ7pGkLTjeLzaavbjV/RW2YjsMIkzKSSaj5FIkMaG0B3nEbzNgTrmkWuTTA+fMEOIrnGFrjS374MqLjNweP4/XO47ixaZUFUNBxNdPfrltkdCRYKuV1tJfnMDYcRWgyiqkhq50ui7uSLU3GFPmNcSOJoywX+jNWTBlmrOYK/f68BYzvGWXweq2nuyvWk0A0BVdSKtbv0LCuPY9EqpgxzOf5hw4ym+j4Zt64jqdLSR25ywn89Xf+C799+PNQ3C5L6wnVZB651oF6CX/8R5bPR+gmURafISqGUCiH8GQOFD2mfBILI4pw0U4VrGcaTrE6IEIpOXgUKdXPpB0gf1VxESt8VpfMx++fPSHh8kkJgrBzuRnCFkXAs88AZ/rxzUsZHL/uB6B9OezfdxafD3wLX7nvvVZ4Cc1rtxmwq4b5v1DwolUgVltMsHnlHHcnKDGx6adPswAqlpCffqpUmkn0AhmL34r7CL7xOI2i5YRDvPgiw+UADnCen9PeyBNe8aPuHL7680OwhyL44t57IQkANRUGqrwGIgkJiayECrcxXYvNm8YECNHxmltcTnNLLnfteYRikglqRZVhXmuS3vLrF4ADB/HbzjjuC+Ux71YOVXhHgot0LVksUuGFHL4sd+H8yCi+suOtaNn9NmBHm4ZfHLGhZ1TGTv6vZRfswL9h3S0sHCS4nnEZ65p01Hp1HHoVdCskzg3gm/15fJHgFmxaqA9swTGmg65QFM8MZ0Hlhq75upgiWfOLnzK+9g0+j4dOHMODq9q0Vr8u4fVuGavrdVSXG+ZzwXnTmXHN4sHqnmF2ajQ79fzdq90KsjEyK8nne99G+HQ/fjmQxtepnzsX2/0kpZ9nFURiPdPFgrcDybOXcOb8IPZPZfDrMQ2nCHjiqvYJb+yV4KtVcWuNG/dW+qRtLFlaW1YYTqEs/CQGqinzgaXQALbCKO71kYvCxPxAkJZw0ZxFoEgmCmRF6TVwBRgNSf2puNE1HsfTQ5xXUMOlxZ56TG8jkYz95Gt1Znuc2FXU3w8cPwUwyQ+cvIQTBeseppN3pefZ+eRT4OAkV9fZsNKtop2r2sJ4WV5XhgqPHR6CtJMQ6nRFrTQrEMmw9hEwwKVcNkPy6CewjOjejyURi6dB0YUBXvv8UBY95KY+jmD8Op7lzAB8aU4rRy0MyZIzVwaBs7Tu0ZNInOpGZ/cQfjWYxgtc5I7MVXuSZr8cQpQU5Gq7E//gWbHqc1l/vZX0hfxiNeEe6Dx9diq/PaYhIzwj9ibt1FgY4NyHrrbCfhLemAoJ3ReB147BOHoKnWcv4+krKTzFCD+RKnHfCgWeOhXbHTJ20ZorxJL5VOxQve6Nut09E5AEqsYjkUgWv8xbj1sSqoTTwxkcmtJwLq7/rgHOl1QK1mV9inOUR68cgvbKMRw4P4F/okslK1T8mb/MvscRqF7rql0O1VNukUWhWTuLbQp9zXQ6jUQiaTaSZFbxxuRoKhOLHo2m8/87kMKLyTwGCw1CXbRdNAnJlPG7ADh3l5DNAttLoH/7j6ySUYfyla2ws3i0e/3WxoQlPcg1MBWbovIJm0+2ZNExSycgD/WgPD+cJ2ENCqVjV1n/ZpEeHMNgdwgPX8zgsGYstttQnreHuoROb2Hw903LSTQ1LqhNt8Pj95qbF4TGNHRtdnlrzC5vpndUiA99ZWVwkmpDpM4kxbXODB1wpPH+B6Aua8DKlXVWZ0/IvYHLWPv3X0XzZA+2jWuIXrNhLsqgME/J5kr2a8rz7xhcKE7DpPSsplquSK435siZXF5mSrAuls1bK6oaVl8vprrNzXpCZNuZV+rq6hAIBMyHrDlDNtNL23ILnPiBaKa1si7dewdaq2S8Z9GoCpMOw3FrtwJdAG4nUOa0xK94ryiLAx0aFxt/bOaWE2OOG6SzCtqXR3HPrsssufJ4/mgjjnRVYdBbjY7yNQjbvAjkprA7fJLHGPKsiQRAhaJ3uNeDyXDQBFX0MMNqN+xhCff4U3jo0mU8ei02V6lIeEGr9UYvQSondJ8FWOzAEEebMgNY3EwwpRii0hdlyygBZnQPykTH25gRlemcgh1rgvjAnd0sE3Pm5B6q7YLP3YK/urwT465GfpbBkOrBc4oL7wwegi8Xp3pR4WJNKbu8GKfMyOSserS4dnwfYLbZswtv6RjGbibJfQtSRe9pjB08hv7uc8h2nYExeAUVMbpsJm1dWCsIbiZfc1eRAB+iSwbFiFgL0t8LnBpuRXlDo8WUBVfc3BLGR+7qojgWJYS1IsKNN64KoXZqEi9PrEDK5jGfgWQYc5ME2pocshyG7Bpj7PiNK3jLFgJ0zeEILrrXCenF/VApQn4+lz4efPBBBu5KqKcz+Lbomp2LmRmgytGBFfUOrGIps3V5JdaTM2oCflQ1NqJ6WR3stLbMm2lc4DzjQ+wH8Fzqt0mumoYY2VAv3SW8Z8uIh7iUdEbBgVPLUqOTbu09N/d5GF/S/Td2oTu8L/O1xF5Vt0mKpCWNMXulFLRVJOuylM8sFNUyr2s07HCOTmoQzmGX8ymGacpsE1DYt7UDt9yAt106iGUTGkbms+D/CTAAhJlzsfEd80MAAAAASUVORK5CYII='
-
-EMOJI_BASE64_SCREAM = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozMiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDozMiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODBFNDg4M0IzQTE5MTFFREI5MDlCRjk1RjI3MDhCODIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODBFNDg4M0MzQTE5MTFFREI5MDlCRjk1RjI3MDhCODIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-EMOJI_BASE64_SMIRKING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTkgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIyMEM4ODY3Mzk1RjExRURCQ0VERkNGNDZDRTc2QURBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIyMEM4ODY4Mzk1RjExRURCQ0VERkNGNDZDRTc2QURBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QjIwQzg4NjUzOTVGMTFFREJDRURGQ0Y0NkNFNzZBREEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QjIwQzg4NjYzOTVGMTFFREJDRURGQ0Y0NkNFNzZBREEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz64K2SuAAATvElEQVR42sRa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'
-
-EMOJI_BASE64_WARNING2 = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxMiswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1NDoxMiswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzRFNzk4NjMzQTE5MTFFREFCNTRBMDE4Q0NEQTM2OTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzRFNzk4NjQzQTE5MTFFREFCNTRBMDE4Q0NEQTM2OTciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3NEU3OTg2MTNBMTkxMUVEQUI1NEEwMThDQ0RBMzY5NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3NEU3OTg2MjNBMTkxMUVEQUI1NEEwMThDQ0RBMzY5NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PlQ3kxoAABbQSURBVHja3FppkFzVdf7e1nv39PTMqDWLRtJoNKNt0AKyNowAicUxUBbGjqHKwQYK21V22XHixK7EqTiJHaccYopKyimnjHHs2A4GYwNlDEgYEGJfJDRa0EizaPbp6X3vfku++17PMKMNicU/8qgrpl/3e+9+55z7ne+c+4D/54f0Xi52c8hA1AO0tLgQNS208VSEo15WUKcqUDUNLvEcXUeFwzBMZPk5yZHgtWNjFYwXgQkVGM7zpPUOzwwAS5YGlUUtoUCjW3WHZVl264auF0vFYq6Uz5woIlG20J/VMX7BAGXJfkCoUcbmoIqrVrVja2sj2qML0da9sgFN0RC8XgmKMQnFykPlrAnQPggOVQ7TAAgS5TIRpoC+fuDkCGLpDIYO9OONWAGPxwzsyxH0XLC8rXbz8rZ/uOOya+5sLFYiXl6g5WmSQgHVcgkFjly1jJIi41ghOX5vOvHdfVnzHul8gTVIWLJIwx0rW/GJnTvQtfFDrWjrWo66RSsBTz1nT6cUT3AcByqTRJR3LrbmxMrZnsbfFNMEOgz0HgWefAojr/bhUXrhh8creIP2QFDG2hdvu2P/iryJYi4NS1FhMUTg8UCqVGARqJXLwUhMQyH4X1ViE1+JpXvUdwIXUeFbouBrGzrxxRt21Tduu/oSRDo38cYddEMBSL0OxB6iJQnOqJwbyDkOrx/oXsOxFviTa9D26uv4/P/+Bp8J9eK+wTK+CZcqSxUD00/vQdkyIEmMlFAISvsimPEEzMkpmLSUZVnwSDKikitM+E1nBahwkgskdF0cxL23fNK1bdcdO4lpO79pAvKjNPd9QPp5J+5mPCS/hwVt1IYAy0X94SuBS1bC88Aj+PzvHsNliQruV8X8JUiy8J5pohDww7WiC+WBQVSnJuFj7KsyJ8HhMWVPWYf3rABXaFjd0hZ55Pq/vHzplTfdiHGlCzk66OVkAoNcPMXq1ahKH0NF86JMuqmQS3Q4txN/m2dBK9HKLv5C/F/mr9y82mVf4QwvivBZBfhLBfgiBZR3ZdC+KrlK/X38790uzZJ8XlSLRYzwUXJrM6JrepAjo8WGh+HOZ9Hm8cPvD8KTnsKdd37EdUaATRIamxaGfql+/5GlhSu24mHSXK4E3Mul1Ss4ULoGUP9IHC84md68vH43Qsd2S9iyBRPZJIx8EYG2dgQWtcPMZFDqWAYtugAlv498PAb5UALPPvucdNo0Gbfo8Lu+U/rqv6+5avtWBAhOBOFPpgkuU/vBH+uwaoMTKOUNKJkcik0NqLt2J8JVA7LXC/+ypVCDfhLFYsiaC8lDvYi/+DKkTBqZibHTPdit4uLopo7bNtywDVsqw5AtHdn8MHYmX8FNag51Sp6LuASPHZjlWoiV4bFKdshZNLvKxaShitNpVMxV4Tea/Un8tizN3mH2jiWOjOFHSvcjawUwlKxDa/IIzPEYUuMnYTQ2IHrlDvg7lkKrq4O3rQ2FoSFMPvEkkgTnmhhjqjIQ8Z6yBlU+lWe+8NWrxpXtgV9yNg0Oc6TuwXVKr83+kzGHV0ReE7mMDI0yR5V4eE/7fIHDOkfGFrlRYSQIlg9wBg1UDC5XbfA7kT/rw0wNbY5dTg4BB2PNfO7lKHOtZV56GcHO5QitWQ2ZF1m8mc6cmOvrQ3kqBkUXBpb5n+RRT1EmTWuX4qMbty3jp1YOZiB9COXEW/jJz4DdTwPxlANQWJ9c7QzhJVKzGJZUyxPnyHn2P7SAJKxgGW/nFXEOggmpJqgoNl0MfP42GoN/l3Uvo8mCm6kh0NUJb0sLzFIJJq1hkHTUQBANm7egwlzoSSVgMekrOMWDUQVb1/Vgoa91tUPZMi9OvYS77q7i4d0ytNYWSB0R4pBtXHK1YlNy1ReyJ6sWc3YCNrkWbKDWmXlDMnXIFTE5Fwy3DwrzqVzMwhT0r2jQaag4GfG3e05iZLyKr3xZiA0Vcl0I9Zs2w7d6DQrj46jEYgisXMnwHES+fwBaOIz6dRchlEojfvQQ1NzkfIA+GVdu3EDzududqSgpvLLnVfz+KZ5a3gmzoZVG5jqj3pINHVMbrsXY1ptQamyzPREcPoy2p3+B4NCbsFzeM9OiXoHuDWHsqjsQW7sTOo0jAEbeeALND/8AajIGi+fkhoXwBIPYf/ggfveEgRULvAzhJpjFOOSn/oCToyPQurrR4nYh/eZBTO7ew5CX0FYfgdvt4bUheGLa2wB9TKBLGnDJog4Gv1zvhFz+MJ56choGZYZcH6VXRWya9jyP3/AVTGzbBRcnpKWnbU9mlqzFm1+4FB0P3YXmlx+2PTQPnlFFObwAh//suyg2L4Fnehzu5AQMGmPiipsxveZKdN19B3wnj8AoFSEtbIHS0IjXXpuEZ30Ja/P9cJ04Aplh2MTvS4yQavdymMf74DnRh/pSBR63lyvPg0wlB90yw7MAZQuNbU1Y1LigjjPhkA1kTryMQ0cEXpKNxIgmo0r0XnHBYsb5BNbdfTt8k/3QCtSGDOdyqAn51m7kWrtQ9ddDLWUZqvK8BZhvXYHml36L+mMvwZMg25XytiHKkRakll+C4pLV8I0eo6erMEj1SqQR8dFJPLY/gWO+Q9g5NYYV5Ok6zieSTEM72oc65j29bIDiBlOFDA5UM9jXGkW+5OueBUjfNEciWOCOhIU/yS8nceLwUYyRNeWusJ0A7ClynXjio2h/8l6bYArRpQS0wgbjmxxEw+FnEe57pbYO56sZsb4ih5+DUinYhioRVHbRKnpWh29qEC37HkCJXjBk1TaGRS9Z9fX0lAoXAUysX4+fL1mGhpP9qM9k0UzFs2DgKMrJFMYDMqb5zOnGRcgt7mTaYt4cODE4C7BFQ0O0iUSqhR1v5Q6h90ABFcUNhURgh+aMGKgUkWtbiaFrbke682JUvGGo5Zy9Bhc//iPUDbxxjuRtouIPY3jHZxBbvxPlYJQEZcAbO4m25+5H0977yYoU8ZRfIIlRVkPxBBF2JRCOP4FxdTOmV29BXFMwaJahsdTR2w3+Tobq8ULlNe7JYUwdeOnRvmThe7MA/RKiDfVwOFlQd/Y1HD0ucocXluZ2CjkRyqTfXFs3em//N5SjUSE8nWziDyHZsxmZpWux6r6vI3Jkn7225q1B3sPkvY58+p+RXLcZthbgbS0yZH7xcry15G9QDDai9affgmk53reYbA13gDVkEjfuGMfxEw/hyMkmJIshpMvhssfnZQFhSUapkE2nU4PxVPpkKp64b6CIR/MMglmAnGO9yD1QRG03yoQ5gMk4J+Xzz7O+6XKjb9dfOeCKp1cDBsVw38e/jvX33Aa1kLLX5uw6p3GGyJ42uOIpubHiyMCT130O/v1PI/zGHj7Lw3xWseeQoMgoUlgw1WHrlhh634zh2/fgkUEd36rdI1exMJg/tZad2w0g+VBGEFDpENLxEqhhyUi+t0OTE0x3XIzMchZtpbOEICdaam7GdM/lkPXqHO/pZNAoJi/5KFA9R8lEJTOx81a72rDnTWlkqRoKfJ6Yj62gqk79KHtYZpvotccZwJ0KUJGVWq7Kv4Ecl0FOXOF2z7sgs3iNc9W5micMh/TSdfPDkzMrNrWTLaOzdd8ZDyH1Fq1EpW6BHdI2NZKsBPFkc3MmzjloquigvEM34jSZIQRneQAl4Ymq4Jv55UPVV/fOnSExTybzU+tAg7Wj8NA5r+d3JhO1wbrOJjYhLGzZpKCYP5Mpzx+gbooHF47Swlk7FMSQZGnejFzZ+Hm1JOzfzZ03JymYFhXr3NcLAcXcqDK32kw6o9rpRX2O52vCvnQhAPMl8fPCW879ztBbEXmtbmC/s4beYZLh46+clgNFrvNODZ+7WKaHg/37oWXiJCjlDELdmZuoXij6c+cNkH8k7Bi37FJBxLc9LJrNMpxIEIojNHAADQf3cpWf5Y4kKv/AMSb8vfOkmpislk2g5fkHnKL5TAYSbQjWWs17fvo2uBnRzrWozVF+pbJ9KnXeAAsWpql8Zi3FnAmfW6REnQK3MPswiWui87f/isDxtxyQWq3KF17hZ/fEBLrv/ycoorIgMQiiEJWDUCsiLwqAC595GHY72DXnWrdQh1Us+/VdCJ543c6XdngyakQJBbKwfw6lFJwpTb4TwNlgGakiEZu2uxOquJ/IiUGu86ToOZqS3YOUuPiFV9yJCaz5r69gdPstSKzahqq3juomx7B8HW1/+Bl8VCWGEL1ME7o3QDnXAS/lnSszTdAylj/4XVv1TGy63hbfojLxU9O2PvMLhI++gIrdSanlEkFywnuSgVBwDptnbO+MnDdA3iaWSCJulhAV0RFmvqcMxNAUdWPEDzOTgtK00AlVxorGJN7x8N1YtOfHLHnCJIYcXLkETFFDMkGLyqEabMDhW/8ZmWU98I0PYtWP/5rrcMiu+1peeADRVx9FJdRoe9ediTnkQZkoosYJTRbAoryvlBEUBg86gkrMb5oFzEgFw+cdoqqEKWrWyVTSWR8yw22JKAsZaqItIMoXM5t2EhAfLkjDLlb5cHdyjGI7Z4egSMozomD00k8is7LHyW3tSzB85a12whfXz8g4d2rSMQxDUqgkM5+b1+8QUYNcxm5hsJ6FYHrBoIy2dNF09h/Obw3STn2T6I/Ha+uCN2J1D6nEalt0kjkBg+iNBNlNNGIMo8aOtLjqsquMmRaGyHmVQATx1Zc5EqwmxRLdm1FsaHMSuCTNMrPJELTKJRhJAi3kZ78TxlRE44bVfXu7oznEVywkkMtiVJMwet4hqnMSuSJe6h/Ex5avcWTTmpVAY9BAgg+QqQfNVBlmLk0rZykA1Jo3SQKK/HZ/hkNm1V5iGVVmiM6mYt6vymo7r/qgjo/YOtNO5KZldwlmDDYLToQnZaK4l1Itonul41ixJFMJoH8KR/O4sDwo9O8LBw7PKRBptZ5VfPb0lA1wdquIT7JIIBbD0yoXbauL0DJpVjObgZ4vQBs6ikD/AeYMJ3WIElOLx+AaPQGTAlp4TESCuI8jx6R54GxDhcKwEjFEF1hYvLgmPPiTkRGRtPGsfh6Kal7KnaziIAvk4UISi4TwFj2lj1wFPPMCPUgGBEnG4Dq0RNoQRDCTzKRTkhrNLIij8z++iNjBm1BsXk4GnUTkhUfhJsPa5de8BG69/X9xLXOUHKqDVi2gGoth7bWwGVS0KYWjjx2DPlHF3vPpHc8DWJaQ6B3E3r4+3NLD9UewiDQDH95mYe++Pmj1caiNURikV5H7bQ/ONESN+c1QO7GTQFof/P4cNaM64Kw5kkRQIplSImlJbhfxcd0ZLJEmh6AT3IpOE9u2Od4ThCrY88QQenMWei8YoHB5vIyf734Gt6y92Ok7cV3i4x8HOjqAx59KIDGU4Hk3J8PYCwQdRaB6alspkr19JXZ+bD4X62tuZ1sQEAFIBCW2v2Q4fVDbOCJkY1wKVNSqUYSPt95+A7Btq7PbJHqxXj7q6BGmrmk8WLRs+rowgOIYN7B79z68fuP12NBAWh6dcox8Ka04oGt49aCEi8KssjNlTE4lkCZRFyqcNHOj8ALsjUnRntacSmSmL2O3G81aC7xqh7AQAqK55FZ01BFQ4wKgrgk4lNLQugjYsZO/E90Cw/FeilnqhReQmDLw3+e7vXEaQFqm3JfEN/7zXjz2F39up0DbwCIzCCtKfhlX7KAaWWhimmyW5kMTCRMJFsiJRMmeRLFo52Z7YsKRll1schC3K2hvyqKuzhESERJtQ4PzOcLPqYKEoSdkVBkJTL1waw5ZC1s98TjX3zC+M23g5LsGKI5BHU88/DK+GfoRvn39Lj7A5VReAY9lLx+j6jjCzygNsewTOWo2MUsOKLFfMQNwpkAVkxQGE96Yu3ch/rajuuZgcY3YFnI7AWEfjz0G8gB+MaDjbsPCeR/K2bYP4gb2jg+hEh/G9oXNkBc0OR7cP6CgvclEe6PlAKilsLlDnKtV3HZm0WobKuLc2X4vQIqcPpGS8fwxFRs7DVy01LQ3e37zEJn8Wdz3ZhF3xqtnbXicP8CZg5H3XGoaLx/vxWqqpea2KEuOkozxtIx1Swxoyrl3kSxr/jhr+SjVdptohD29KvIVCduW6HiDJeWvH8Tw3kP42pEy/i6tQ/9A3pPxSfC1qPjEikbc1hCVNpV8invjKgubVhnw+pywe9ebuLXiVazbo4MSdr/G9JI3kYmZB/on8T+TJJSYgUnTepf3v5AfEyhCCnraPNjKcLpicQO6AgE0B0NoIkEoYvdYaGOP0IxCmtbCbqbFYNbinxnBLlhFTZdK2UQ1zb8nBqbRz2T+3FgZz6YMvE7Cq+I9HtJ7uTAks5Qz0WIJjaOhzqsgREvXUQQHw27lG9VISxtqbXhxhZocK2QK5X+pWBiQJeQKBlJUJFkuzWl+nsha9n7K+3q861cJxETSpu0UUXSOjHF1aDqaCTBML7sXBMyCySLOzok1bemiZI2l8SqBDPIGZZ4aLqCWsN9vZO/Hu2oBBQq9uL5Zw0cjAe06f7h+uez2iu2pWuvTmjdxoV4ExVd1O8lXZb08nEqnX0yVrF+P69iXrM5/feuPBtDPdd8C/GmdBxtY4/rJeB4mfq9bx7L6hQvW+xd3S+6mFqjBMGRFxRlbYbXH6QSXSCSQZeXh7ApTyGfjqI6cGElX9DcpVePCDsyjOSb68Qkd9zOxHzc+KJIRQmtTEH/7pc9d9I8bt7jgKR9GJlPAGAvjXsrd58e3ofGijSyByrXumzUL69Sbiz128eKbUKDZbNYGalgETcbpKD2PXVeXUE//t0edF/aEUvrhvTj+0CFsiVE4fSBrsF5C9NIty79085dZsyR3w+5EMv4Wc/FMx8U7CrpTG85U+MRQ0WVbmokErqgWXJJhe6ugeKCZVahiu5sSyEPNNh1PIJXJw+2y0MNCuy0KzOzXLGZFc3MGna8dx63JEu7SrQ8AYIuGT92wq3sBYj+jvBlzpIFQKRysZqAFw2/30U3J9siO9ePYumYSJyeCeOi5dkzoIRyMdGHc04SAXsClyf1orKZsibNwYVR0BJEa11AslG21M1sn0GabPgSs78TtR3vxA93urFzYIb/DC6/amqW4dV3Hi0BmbJ7uEVtZ0ylSv9fvlEiWZHvvU9v78emr+7CsLY0rNo7gi9cdQq4+jKO+bqTVAEa9C/G7pq1IaHWQxdsWRBQM16FQdSOZOmW3gQC9FOBXfhgrG2XseDchek6AVC+X7tyKtYHQ9GnbHNk8PZjyQ/E6myRVQ8b1m4dx9eYRhquMckGDUVLR1ZnGPTsew9bq6849GKJZLYTnwhfBlJyep4vKOlMNYipW20iW5u82XcaasCeKz3ql9xGgcFZrELds32pXsqcdYjKFqh8un9+utuv8ZWxjWAp2yRc1fO9XPTjQH6EXZHQuTeI7qx9DQGyo2KB0jDJc4wQqOnaKePOHrhqdYGRUTgFILdO6BLh4DS6nklr8vgFkeNZvXIGrly6bsyZmXnUhoLFJ0e6PQHEpdmj6XAZcimUDcmkGLuuZQHOkYHfFbRUjmbObmuKzQmAagVq1jUk1EMLwONm1cIYsQ5vQ0PXNKq593wBGVWzatAHtogF8SipDllpymPrF9C20X3ee+2Kg+EeVLVy2TgAsUpMaGB5inum9BllfuPaeDauRbB/q9az98oAittZ8QYxOkVWTDvueGqY9q4HlzfiY5/0AKF7KY3h+ZsO607cYxfzEy+QDIxo8kSabYM4k44yqeG/NQt9QGJ995kY8rWzg05zXZLtz/ejKD895adaCJxRAvFiHoZMOgZ0apo3NBNmFywIy1lwIwP8TYACByE157HTupAAAAABJRU5ErkJggg=='
-
-EMOJI_BASE64_WARNING = b'iVBORw0KGgoAAAANSUhEUgAAADgAAAA4CAYAAACohjseAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+tpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTQ1IDc5LjE2MzQ5OSwgMjAxOC8wOC8xMy0xNjo0MDoyMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDIyLTA5LTIyVDA4OjEwOjQzKzA3OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1MyswNzowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMi0wOS0yMlQwODo1Mzo1MyswNzowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Njk5N0ZDN0QzQTE5MTFFREEyRTJFOTM2QUFEMzdENzMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Njk5N0ZDN0UzQTE5MTFFREEyRTJFOTM2QUFEMzdENzMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RS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'
-
-EMOJI_BASE64_JEDI = b'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'
-
-
-EMOJI_BASE64_HAPPY_LIST = [EMOJI_BASE64_HAPPY_STARE, EMOJI_BASE64_BLANK_STARE, EMOJI_BASE64_HAPPY_LAUGH, EMOJI_BASE64_HAPPY_JOY, EMOJI_BASE64_HAPPY_IDEA, EMOJI_BASE64_HAPPY_GASP, EMOJI_BASE64_HAPPY_RELIEF, EMOJI_BASE64_HAPPY_WINK, EMOJI_BASE64_HAPPY_THUMBS_UP, EMOJI_BASE64_HAPPY_HEARTS, EMOJI_BASE64_HAPPY_CONTENT, EMOJI_BASE64_HAPPY_BIG_SMILE, EMOJI_BASE64_PRAY, EMOJI_BASE64_GUESS, EMOJI_BASE64_FINGERS_CROSSED, EMOJI_BASE64_CLAP, EMOJI_BASE64_COOL, EMOJI_BASE64_UPSIDE_DOWN, EMOJI_BASE64_OK, EMOJI_BASE64_COOL, EMOJI_BASE64_GLASSES, EMOJI_BASE64_HEAD_EXPLODE, EMOJI_BASE64_GLASSES, EMOJI_BASE64_LAPTOP, EMOJI_BASE64_PARTY, EMOJI_BASE64_READING, EMOJI_BASE64_SANTA, EMOJI_BASE64_SEARCH, EMOJI_BASE64_WAVE, EMOJI_BASE64_KEY, EMOJI_BASE64_SALUTE, EMOJI_BASE64_HONEST,EMOJI_BASE64_WIZARD, EMOJI_BASE64_JEDI, EMOJI_BASE64_GOLD_STAR, EMOJI_BASE64_SMIRKING]
-
-EMOJI_BASE64_SAD_LIST = [EMOJI_BASE64_YIKES, EMOJI_BASE64_WEARY, EMOJI_BASE64_DREAMING, EMOJI_BASE64_SLEEPING, EMOJI_BASE64_THINK, EMOJI_BASE64_SKEPTIC, EMOJI_BASE64_SKEPTICAL, EMOJI_BASE64_FACEPALM, EMOJI_BASE64_FRUSTRATED, EMOJI_BASE64_PONDER, EMOJI_BASE64_NOTUNDERSTANDING, EMOJI_BASE64_QUESTION, EMOJI_BASE64_CRY, EMOJI_BASE64_TEAR, EMOJI_BASE64_DEAD, EMOJI_BASE64_ZIPPED_SHUT, EMOJI_BASE64_NO_HEAR, EMOJI_BASE64_NO_SEE, EMOJI_BASE64_NO_SPEAK, EMOJI_BASE64_EYE_ROLL, EMOJI_BASE64_CRAZY, EMOJI_BASE64_RAINEDON, EMOJI_BASE64_DEPRESSED, EMOJI_BASE64_ILL, EMOJI_BASE64_ILL2, EMOJI_BASE64_MASK, EMOJI_BASE64_WARNING, EMOJI_BASE64_WARNING2, EMOJI_BASE64_SCREAM]
EMOJI_BASE64_LIST = EMOJI_BASE64_HAPPY_LIST + EMOJI_BASE64_SAD_LIST
-EMOJI_BASE64_JASON = EMOJI_BASE64_WIZARD
-EMOJI_BASE64_TANAY = EMOJI_BASE64_JEDI
def _random_error_emoji():
c = random.choice(EMOJI_BASE64_SAD_LIST)
@@ -25112,8 +23263,7 @@ def __show_previous_upgrade_information():
recommended_version = pysimplegui_user_settings.get('-upgrade recommendation-', '')
severity_level = pysimplegui_user_settings.get('-severity level-', '')
- if severity_level != 'Critical':
- return
+ message2 = r'https://www.PySimpleGUI.org'
layout = [[Image(EMOJI_BASE64_HAPPY_THUMBS_UP), T('An upgrade is available & recommended', font='_ 14')],
[T('It is recommended you upgrade to version {}'.format(recommended_version))],
@@ -25134,9 +23284,8 @@ def __show_previous_upgrade_information():
if event in ('Close', WIN_CLOSED) or seconds_left < 1:
break
if values['-SKIP IN FUTURE-']:
- if not running_trinket():
- pysimplegui_user_settings['-upgrade info available-'] = False
- pysimplegui_user_settings['-upgrade info seen-'] = True
+ pysimplegui_user_settings['-upgrade info available-'] = False
+ pysimplegui_user_settings['-upgrade info seen-'] = True
if event == '-MESSAGE 1-' and 'http' in message1 and webbrowser_available:
webbrowser.open_new_tab(message1)
elif event == '-MESSAGE 2-' and 'http' in message2 and webbrowser_available:
@@ -25148,20 +23297,15 @@ def __show_previous_upgrade_information():
def __get_linux_distribution():
- line_tuple = ('Linux Distro', 'Unknown', 'No lines Found in //etc//os-release')
- try:
- with open('/etc/os-release') as f:
- data = f.read()
- lines = data.split('\n')
- for line in lines:
- if line.startswith('PRETTY_NAME'):
- line_split = line.split('=')[1].strip('"')
- line_tuple = tuple(line_split.split(' '))
- return line_tuple
- except:
- line_tuple = ('Linux Distro', 'Exception','Error reading//processing //etc//os-release')
-
- return line_tuple
+ with open('/etc/os-release') as f:
+ data = f.read()
+ lines = data.split('\n')
+ for line in lines:
+ if line.startswith('PRETTY_NAME'):
+ line_split = line.split('=')[1].strip('"')
+ line_tuple = tuple(line_split.split(' '))
+ return line_tuple
+ return ('Linux Distro', 'Unknown','No lines Found in //etc//os-release')
def __perform_upgrade_check_thread():
@@ -25224,7 +23368,7 @@ def __perform_upgrade_check_thread():
def __perform_upgrade_check():
# For now, do not show data returned. Still testing and do not want to "SPAM" users with any popups
- __show_previous_upgrade_information()
+ # __show_previous_upgrade_information()
threading.Thread(target=lambda: __perform_upgrade_check_thread(), daemon=True).start()
@@ -25650,8 +23794,6 @@ def main_open_github_issue():
window = Window('Open A GitHub Issue', layout, finalize=True, resizable=True, enable_close_attempted_event=True, margins=(0, 0))
-
-
# for i in range(len(checklist)):
[window['-T{}-'.format(i)].set_cursor('hand1') for i in range(len(checklist))]
# window['-TABGROUP-'].expand(True, True, True)
@@ -25881,10 +24023,10 @@ def _copy_files_from_github():
python_command = python_command.replace('pythonw', 'python')
layout = [[Text('Pip Upgrade Progress')],
- [Multiline(s=(90,15), k='-MLINE-', reroute_cprint=True, write_only=True, expand_x=True, expand_y=True)],
- [Button('Downloading...', k='-EXIT-'), Sizegrip()]]
+ [Multiline(s=(90,15), k='-MLINE-', reroute_cprint=True, write_only=True)],
+ [Button('Downloading...', k='-EXIT-')]]
- window = Window('Pip Upgrade', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True, resizable=True)
+ window = Window('Pip Upgrade', layout, finalize=True, keep_on_top=True, modal=True, disable_close=True)
window.disable_debugger()
@@ -26012,7 +24154,13 @@ def main_get_debug_data(suppress_popup=False):
:returns: String containing the information to place into the GitHub Issue
:rtype: (str)
"""
- message = get_versions()
+ message = \
+ """Python version: {}
+ port: tkinter
+ tkinter version: {}
+ PySimpleGUI version: {}
+ PySimpleGUI filename: {}""".format(sys.version, tclversion_detailed, ver, __file__)
+
clipboard_set(message)
if not suppress_popup:
@@ -26057,27 +24205,6 @@ def _global_settings_get_ttk_scrollbar_info():
DEFAULT_TTK_THEME = pysimplegui_user_settings.get('-ttk theme-', DEFAULT_TTK_THEME)
-def _global_settings_get_watermark_info():
- if not pysimplegui_user_settings.get('-watermark-', False) and not Window._watermark_temp_forced:
- Window._watermark = None
- return
- forced = Window._watermark_temp_forced
- prefix_text = pysimplegui_user_settings.get('-watermark text-', '')
-
- ver_text = ' ' + version.split(" ", 1)[0] if pysimplegui_user_settings.get('-watermark ver-', False if not forced else True) or forced else ''
- framework_ver_text = ' Tk ' + framework_version if pysimplegui_user_settings.get('-watermark framework ver-', False if not forced else True) or forced else ''
- watermark_font = pysimplegui_user_settings.get('-watermark font-', '_ 9 bold')
- # background_color = pysimplegui_user_settings.get('-watermark bg color-', 'window.BackgroundColor')
- user_text = pysimplegui_user_settings.get('-watermark text-', '')
- python_text = ' Py {}.{}.{}'.format(sys.version_info.major, sys.version_info.minor, sys.version_info.micro)
- if user_text:
- text = str(user_text)
- else:
- text = prefix_text + ver_text + python_text + framework_ver_text
- Window._watermark = lambda window: Text(text, font=watermark_font, background_color= window.BackgroundColor)
-
-
-
def main_global_get_screen_snapshot_symcode():
pysimplegui_user_settings = UserSettings(filename=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME, path=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH)
@@ -26214,20 +24341,10 @@ def main_global_pysimplegui_settings():
theme_tab = Tab('Theme',
[[T('Leave blank for "official" PySimpleGUI default theme: {}'.format(OFFICIAL_PYSIMPLEGUI_THEME))],
[T('Default Theme For All Programs:'),
- Combo([''] + theme_list(), settings.get('-theme-', None), readonly=True, k='-THEME-', tooltip=tooltip_theme), Checkbox('Always use custom Titlebar', default=pysimplegui_user_settings.get('-custom titlebar-',False), k='-CUSTOM TITLEBAR-')],
- [Frame('Window Watermarking',
- [[Checkbox('Enable Window Watermarking', pysimplegui_user_settings.get('-watermark-', False), k='-WATERMARK-')],
- [T('Prefix Text String:'), Input(pysimplegui_user_settings.get('-watermark text-', ''), k='-WATERMARK TEXT-')],
- [Checkbox('PySimpleGUI Version', pysimplegui_user_settings.get('-watermark ver-', False), k='-WATERMARK VER-')],
- [Checkbox('Framework Version',pysimplegui_user_settings.get('-watermark framework ver-', False), k='-WATERMARK FRAMEWORK VER-')],
- [T('Font:'), Input(pysimplegui_user_settings.get('-watermark font-', '_ 9 bold'), k='-WATERMARK FONT-')],
- # [T('Background Color:'), Input(pysimplegui_user_settings.get('-watermark bg color-', 'window.BackgroundColor'), k='-WATERMARK BG COLOR-')],
- ],
- font='_ 16', expand_x=True)]])
+ Combo([''] + theme_list(), settings.get('-theme-', None), readonly=True, k='-THEME-', tooltip=tooltip_theme), Checkbox('Always use custom Titlebar', default=pysimplegui_user_settings.get('-custom titlebar-',False), k='-CUSTOM TITLEBAR-')]],
+ font='_ 16', expand_x=True)
-
-
- settings_tab_group = TabGroup([[theme_tab, ttk_tab, interpreter_tab, explorer_tab, editor_tab, snapshots_tab, ]])
+ settings_tab_group = TabGroup([[theme_tab, ttk_tab, interpreter_tab, explorer_tab, editor_tab, snapshots_tab ]])
layout += [[settings_tab_group]]
# [T('Buttons (Leave Unchecked To Use Default) NOT YET IMPLEMENTED!', font='_ 16')],
# [Checkbox('Always use TTK buttons'), CBox('Always use TK Buttons')],
@@ -26239,7 +24356,7 @@ def main_global_pysimplegui_settings():
ttk_theme_list = ttk.Style().theme_names()
window['-TTK THEME-'].update(value=DEFAULT_TTK_THEME, values=ttk_theme_list)
-
+
while True:
event, values = window.read()
if event in ('Cancel', WIN_CLOSED):
@@ -26252,12 +24369,6 @@ def main_global_pysimplegui_settings():
pysimplegui_user_settings.set('-python command-', values['-PYTHON COMMAND-'])
pysimplegui_user_settings.set('-custom titlebar-', values['-CUSTOM TITLEBAR-'])
pysimplegui_user_settings.set('-theme-', new_theme)
- pysimplegui_user_settings.set('-watermark-', values['-WATERMARK-'])
- pysimplegui_user_settings.set('-watermark text-', values['-WATERMARK TEXT-'])
- pysimplegui_user_settings.set('-watermark ver-', values['-WATERMARK VER-'])
- pysimplegui_user_settings.set('-watermark framework ver-', values['-WATERMARK FRAMEWORK VER-'])
- pysimplegui_user_settings.set('-watermark font-', values['-WATERMARK FONT-'])
- # pysimplegui_user_settings.set('-watermark bg color-', values['-WATERMARK BG COLOR-'])
# TTK SETTINGS
pysimplegui_user_settings.set('-ttk theme-', values['-TTK THEME-'])
@@ -26285,15 +24396,9 @@ def main_global_pysimplegui_settings():
if key[0] == '-TTK SCROLL-':
pysimplegui_user_settings.set(json.dumps(('-ttk scroll-', key[1])), value)
- # Upgrade Service Settings
- pysimplegui_user_settings.set('-upgrade show only critical-', values['-UPGRADE SHOW ONLY CRITICAL-'])
-
-
-
theme(new_theme)
_global_settings_get_ttk_scrollbar_info()
- _global_settings_get_watermark_info()
window.close()
return True
@@ -26317,7 +24422,6 @@ def main_global_pysimplegui_settings():
for i in range(100):
Print(i, keep_on_top=True)
Print('Close this window to continue...', keep_on_top=True)
-
window.close()
# In case some of the settings were modified and tried out, reset the ttk info to be what's in the config file
style = ttk.Style(Window.hidden_master_root)
@@ -26431,8 +24535,7 @@ def main_sdk_help():
[T(size=(80, 1), font='Courier 10 underline', k='-DOC LINK-', enable_events=True)]], pad=(0, 0), expand_x=True, expand_y=True, vertical_alignment='t')
layout = [[button_col, mline_col]]
layout += [[CBox('Summary Only', enable_events=True, k='-SUMMARY-'), CBox('Display Only PEP8 Functions', default=True, k='-PEP8-')]]
- # layout = [[Column(layout, scrollable=True, p=0, expand_x=True, expand_y=True, vertical_alignment='t'), Sizegrip()]]
- layout += [[Button('Exit', size=(15, 1)), Sizegrip()]]
+ # layout += [[Button('Exit', size=(15, 1))]]
window = Window('SDK API Call Reference', layout, resizable=True, use_default_focus=False, keep_on_top=True, icon=EMOJI_BASE64_THINK, finalize=True, right_click_menu=MENU_RIGHT_CLICK_EDITME_EXIT)
window['-DOC LINK-'].set_cursor('hand1')
@@ -26516,6 +24619,7 @@ def main_sdk_help():
_error_popup_with_traceback('Exception in SDK reference', e)
window.close()
+
# oo
#
# 88d8b.d8b. .d8888b. dP 88d888b.
@@ -26614,11 +24718,11 @@ def _create_main_window():
# [ProgressBar(100, bar_color=('red', 'green'), orientation='h')],
[Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], select_mode=SELECT_MODE_EXTENDED, size=(20, 5), no_scrollbar=True),
- Spin([1, 2, 3, 'a', 'b', 'c'], initial_value='a', size=(4, 3), wrap=True)],
+ Spin([1, 2, 3, 'a', 'b', 'c'], initial_value='a', size=(4, 3))],
[Combo(['Combo item %s' % i for i in range(5)], size=(20, 3), default_value='Combo item 2', key='-COMBO1-', )],
[Combo(['Combo item %s' % i for i in range(5)], size=(20, 3), font='Courier 14', default_value='Combo item 2', key='-COMBO2-', )],
# [Combo(['Combo item 1', 2,3,4], size=(20, 3), readonly=False, text_color='blue', background_color='red', key='-COMBO2-')],
-
+
]
frame3 = [
@@ -26670,7 +24774,7 @@ def _create_main_window():
[T(pysimplegui_user_settings.get('-upgrade message 1-',''))],
[T(pysimplegui_user_settings.get('-upgrade message 2-',''))],
[Checkbox('Show Only Critical Messages', default=pysimplegui_user_settings.get('-upgrade show only critical-', False), key='-UPGRADE SHOW ONLY CRITICAL-', enable_events=True)],
- [Button('Show Notification Again'),
+ [Button('Show Notification Again'), B('Upgrade from GitHub', button_color='white on red', key='-UPGRADE FROM GITHUB-'),
],
]
tab_upgrade = Tab('Upgrade\n',upgrade_recommendation_tab_layout, expand_x=True)
@@ -26715,7 +24819,7 @@ def _create_main_window():
# [B(image_data=ICON_BUY_ME_A_COFFEE,pad=(1, 0), key='-COFFEE-'),
[B(image_data=UDEMY_ICON,pad=(1, 0), key='-UDEMY-'),
B('SDK Reference', pad=(1, 0)), B('Open GitHub Issue',pad=(1, 0)), B('Versions for GitHub',pad=(1, 0)),
- ButtonMenu('ButtonMenu', button_menu_def, pad=(1, 0),key='-BMENU-', tearoff=True, disabled_text_color='yellow')
+ ButtonMenu('ButtonMenu', button_menu_def, pad=(1, 0),key='-BMENU-', tearoff=True)
]]
layout = [[]]
@@ -26732,7 +24836,7 @@ def _create_main_window():
window = Window('PySimpleGUI Main Test Harness', layout,
# font=('Helvetica', 18),
# background_color='black',
- right_click_menu=['&Right', ['Right', 'Edit Me', '!&Click', '&Menu', 'E&xit', 'Properties']],
+ right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']],
# transparent_color= '#9FB8AD',
resizable=True,
keep_on_top=False,
@@ -26808,7 +24912,7 @@ def main():
elif event.startswith('See'):
window._see_through = not window._see_through
window.set_transparent_color(theme_background_color() if window._see_through else '')
- elif event in ('-INSTALL-', '-UPGRADE FROM GITHUB-'):
+ elif event == '-INSTALL-' or event == '-UPGRADE FROM GITHUB-':
_upgrade_gui()
elif event == 'Popup':
popup('This is your basic popup', keep_on_top=True)
@@ -26821,16 +24925,18 @@ def main():
elif event == 'Get Text':
popup_scrolled('Returned:', popup_get_text('Enter some text', keep_on_top=True))
elif event.startswith('-UDEMY-'):
- webbrowser.open_new_tab(r'https://www.udemy.com/course/pysimplegui/?couponCode=522B20BF5EF123C4AB30')
+ webbrowser.open_new_tab(r'https://udemy.com/PySimpleGUI')
elif event.startswith('-SPONSOR-'):
if webbrowser_available:
webbrowser.open_new_tab(r'https://www.paypal.me/pythongui')
elif event == '-COFFEE-':
if webbrowser_available:
+ # webbrowser.open_new_tab(r'https://udemy.com/PySimpleGUI')
webbrowser.open_new_tab(r'https://www.buymeacoffee.com/PySimpleGUI')
elif event in ('-EMOJI-HEARTS-', '-HEART-', '-PYTHON HEARTS-'):
- popup_scrolled("Oh look! It's a Udemy discount coupon!", '522B20BF5EF123C4AB30',
+ popup_scrolled("Oh look! It's a Udemy discount coupon!", '4FD91A459D56B1029FF8',
'A personal message from Mike -- thank you so very much for supporting PySimpleGUI!', title='Udemy Coupon', image=EMOJI_BASE64_MIKE, keep_on_top=True)
+
elif event == 'Themes':
search_string = popup_get_text('Enter a search term or leave blank for all themes', 'Show Available Themes', keep_on_top=True)
if search_string is not None:
@@ -26865,26 +24971,22 @@ def main():
set_options(force_modal_windows=False)
popup('Normal Popup - Not Modal', 'You can interact with main window menubar ',
'but will have no effect immediately', 'button clicks will happen after you close this popup', modal=False, keep_on_top=True)
- set_options(force_modal_windows=forced_modal)
+ set_options(force_modal_windows=True)
elif event == 'P NoBlock':
popup_non_blocking('Non-blocking', 'The background window should still be running', keep_on_top=True)
elif event == 'P AutoClose':
popup_auto_close('Will autoclose in 3 seconds', auto_close_duration=3, keep_on_top=True)
elif event == 'Versions for GitHub':
main_get_debug_data()
- elif event == 'Edit Me':
- execute_editor(__file__)
elif event == 'Open GitHub Issue':
window.minimize()
main_open_github_issue()
window.normal()
elif event == 'Show Notification Again':
- if not running_trinket():
- pysimplegui_user_settings.set('-upgrade info seen-', False)
+ pysimplegui_user_settings.set('-upgrade info seen-', False)
__show_previous_upgrade_information()
elif event == '-UPGRADE SHOW ONLY CRITICAL-':
- if not running_trinket():
- pysimplegui_user_settings.set('-upgrade show only critical-', values['-UPGRADE SHOW ONLY CRITICAL-'])
+ pysimplegui_user_settings.set('-upgrade show only critical-', values['-UPGRADE SHOW ONLY CRITICAL-'])
i += 1
@@ -26949,18 +25051,6 @@ TimerStop = timer_stop
test = main
sdk_help = main_sdk_help
-def _optional_window_data(window):
- """
- A function to help with testing PySimpleGUI releases. Makes it easier to add a watermarked line to the bottom
- of a window while testing release candidates.
-
- :param window:
- :type window: Window
- :return: An element that will be added to the bottom of the layout
- :rtype: None | Element
- """
- return None
-
pysimplegui_user_settings = UserSettings(filename=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_FILENAME, path=DEFAULT_USER_SETTINGS_PYSIMPLEGUI_PATH)
# ------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------
@@ -26969,9 +25059,6 @@ theme(theme_global())
# ------------------------ Read the ttk scrollbar info ------------------------
_global_settings_get_ttk_scrollbar_info()
-# ------------------------ Read the window watermark info ------------------------
-_global_settings_get_watermark_info()
-
# See if running on Trinket. If Trinket, then use custom titlebars since Trinket doesn't supply any
if running_trinket():
USE_CUSTOM_TITLEBAR = True
@@ -26993,6 +25080,12 @@ _read_mac_global_settings()
if _mac_should_set_alpha_to_99():
# Applyting Mac OS 12.3+ Alpha Channel fix. Sets the default Alpha Channel to 0.99
set_options(alpha_channel=0.99)
+# if running_mac():
+# print('Your Mac patches are:')
+# print('Modal windows disabled:', ENABLE_MAC_MODAL_DISABLE_PATCH)
+# print('No titlebar patch:', ENABLE_MAC_NOTITLEBAR_PATCH)
+# print('No grab anywhere allowed with titlebar:', ENABLE_MAC_DISABLE_GRAB_ANYWHERE_WITH_TITLEBAR)
+# print('Currently the no titlebar patch ' + ('WILL' if _mac_should_apply_notitlebar_patch() else 'WILL NOT') + ' be applied')
__perform_upgrade_check()
@@ -27009,5 +25102,4 @@ if __name__ == '__main__':
main_sdk_help()
exit(0)
main()
- exit(0)
-#25424909a31c4fa789f5aa4e210e7e07d412560195dc21abe678b68a3b4bdb2a8a78651d8613daaded730bc2a31adc02ba8b99717fff701cda8ae13c31f1dcee9da8837908626f1c5cc81e7a34d3b9cd032dba190647564bba72d248ad6b83e30c8abc057f3f1b1fb3a2ca853069de936f3f53522fd4732b743268e0fcde54577a05880f2057efe6bbd6349f77d6c002544f38e24db40ab84f3dde4a4b8b31e84480db31656fb74ae0c01a7af0b35ac66cf8a0fbb8ca85685fea075608c7862da6635511d0e5403c4a637138324ce1fb1308b765cba53863ddf7b01ca4fc988932b03c4a8403a72b8105f821913f02925218dbecf1e089bd32e78667939503f2abfd89b37fa293927e30550d441f21dc68273d2d07ed910f6a69bc8c792015eb623ada7e65347cf0389cf2a1696a7ccf88098a4fb4bfa44e88fac2a94a44e25b010355e48d483d896c58eb771ef47e01066156f9344750b487e176ca0642601951f096d4c03045aa8f912d475dbe04b82c6ddf1ac3adbf815aef4ca2c6add058c2789b66a9abd875f334752ec1bde11b9b56e334823304b6cc3fadf7daae277c982ebc7eadb726a33e2740d075ad082b9c20304c4a53228d6f05357c40903a78113aea4e6169e1a5351866f7a9ffc6666eb08a31bfb84d90cb3002f7ebf87871988b88a7b8a52d36a1a7dd826360b5c6ad922829d9f73d204f09d1b9ad9ffd8d
\ No newline at end of file
+ exit(0)
\ No newline at end of file
diff --git a/PySimpleGUIdebugger/readme.md b/PySimpleGUIdebugger/readme.md
new file mode 100644
index 00000000..f1b09c70
--- /dev/null
+++ b/PySimpleGUIdebugger/readme.md
@@ -0,0 +1,28 @@
+
+
+
+## is no more.... but `imwatching` you now the same thing
+
+
+# Project renamed to:
+# `imwatchingyou`
+
+So head over to that project page.
+https://github.com/PySimpleGUI/imwatchingyou
+
+----------------------
+
+To install it:
+
+`pip install imwatchingyou`
+
+To use it, check out the Demo Program on the project's page.
+
+----------------------
+
+About the creepy title
+
+Don't worry, I'm not watching YOU...
+
+#### I'm not watching you, YOU are watching YOUR CODE
+
diff --git a/ThemeMaker/Theme_Maker.py b/ThemeMaker/Theme_Maker.py
new file mode 100644
index 00000000..ff8c3130
--- /dev/null
+++ b/ThemeMaker/Theme_Maker.py
@@ -0,0 +1,262 @@
+import PySimpleGUI as sg
+import color_themes
+
+"""
+ Program that is used to create new themes for use with PySimpleGUI's "Look and Feel" settings.
+ You are presented with a grid of mini-windows that is created for color palettes downloaded from https://colorhunt.co/palettes
+ The file color_themes.py contains a large dictionary of approx 1780 palettes.
+
+ For each palette you are shown 4 candidate themes, 2 "light" and 2 "dark". The window shows 5 palettes so you'll have a
+ total of 20 candidate themes displayed in total.
+ Each candidate theme has a 3 options - The button color (text and background), the text color for Input/Multiline elements,
+ and the name of the theme when you save it. These you choose using the radio buttons and one input field.
+ To "save" one of these candidate themes, check the checkbox to the left of the layout, choose the radio buttons for button
+ & text settings and optionally change the theme name that is shown above the grid of OK buttons. By default the name starts
+ with either "Dark" or "Light" and is followed by the first 2 "tags" that were posted with the palette on the colorhunt site.
+
+ After you've selected the themes you want to save from the window of 20 click any "OK" button in the window or close the
+ window with the "X". You will see the dictionary text in the Debug Window and the values will also be written to a file.
+ You'll then be shown the next group of 20 candidate themes.
+
+ If you want to exit the program entirely, click any "Cancel" button the page. Note - cliicking "Cancel" will not save any
+ theme you have checked with the checkbox. You should only exit from a window you have not selected any themes for saving
+
+ If a Theme is selected for saving, then the values for the LOOK_AND_FEEL dictionary are displayed in a debug window and are
+ also appended to the file new_theme_dict.py. You will need to edit the new_theme_dict.py file to get the syntax correct.
+ A "," or "}" may need to be added in order to make the table be correct.
+
+ If you're using this program it's assumed you know what you're doing and understand the LOOK_AND_FEEL dictionary and can
+ figure out how to get the syntax correct for adding it to the main dictionary of themes.
+"""
+
+#----------------- Window to get layout for window ---------#
+
+CANDIDATES_PER_ROW = 4
+PALETTES_PER_WINDOW = 5
+STARTING_PALETTE = 0
+sg.change_look_and_feel('Dark Blue 3')
+layout = [
+ [sg.T('Choose your window layout (default is a huge window)')],
+ [sg.In(default_text=CANDIDATES_PER_ROW),sg.T('Candidates Per Row')],
+ [sg.In(default_text=PALETTES_PER_WINDOW),sg.T('Palettes Per Window (4 candidates for each)')],
+ [sg.In(default_text=0),sg.T(f'Starting palette number of {len(color_themes.themes)} palettes')],
+ [sg.OK()]]
+window = sg.Window('Choose Theme Layout', layout,default_element_size=(4,1))
+event, values = window.read()
+window.close()
+
+if event is None:
+ sg.popup_no_buttons('Aborting....', no_titlebar=True, auto_close=True, keep_on_top=True)
+ exit()
+try:
+ CANDIDATES_PER_ROW = int(values[0])
+ PALETTES_PER_WINDOW = int(values[1])
+ STARTING_PALETTE = int(values[2])
+except:
+ sg.popup_no_buttons('Bad input... Aborting....', no_titlebar=True, auto_close=True, keep_on_top=True)
+ exit()
+
+TOTAL_CANDIDATES_PER_PAGE = PALETTES_PER_WINDOW * 4
+#-----------------------------------------------------------#
+
+def rgb_to_hsl(r, g, b):
+ r = float(r)
+ g = float(g)
+ b = float(b)
+ high = max(r, g, b)
+ low = min(r, g, b)
+ h, s, v = ((high + low) / 2,)*3
+ if high == low:
+ h = s = 0.0
+ else:
+ d = high - low
+ l = (high + low) / 2
+ s = d / (2 - high - low) if l > 0.5 else d / (high + low)
+ h = {
+ r: (g - b) / d + (6 if g < b else 0),
+ g: (b - r) / d + 2,
+ b: (r - g) / d + 4,
+ }[high]
+ h /= 6
+ return h, s, v
+
+def hex_to_rgb(hex):
+ hex = hex.lstrip('#')
+ hlen = len(hex)
+ return tuple(int(hex[i:i + hlen // 3], 16) for i in range(0, hlen, hlen // 3))
+
+
+def sorted_tuple(tup, position):
+ tup.sort(key=lambda x: x[position])
+ return tup
+
+sg.popup_quick_message('Hang on this could me a few moments....', background_color='red', text_color='white', keep_on_top=True)
+
+sg.LOOK_AND_FEEL_TABLE = {} # Entirely replace the look and feel table in PySimpleGUI
+palette_counter = 0
+for key, colors in color_themes.themes.items():
+ if palette_counter < STARTING_PALETTE:
+ palette_counter += 1
+ continue
+ # Sort the colors from darkest to lightest
+ color_lightness_pairs = []
+ for color in colors:
+ if type(color) in (tuple, list):
+ continue
+ r,g,b = hex_to_rgb(color)
+ lightness = (rgb_to_hsl(r=r, g=g, b=b))[2]
+ color_lightness_pairs.append((lightness, color))
+ sorted_colors_tuples = sorted_tuple(color_lightness_pairs, 0) # sort the pairs by the first item (lightness)
+ scolors = [c for l, c in sorted_colors_tuples] # Colors sorted from darkest to lightest
+ # Create a "Dark" and a "Light" theme based on the sorted colors
+ sg.LOOK_AND_FEEL_TABLE['Dark'+key] = {'BACKGROUND': scolors[0],
+ 'TEXT': scolors[3],
+ 'INPUT': scolors[2],
+ 'TEXT_INPUT': '#000000',
+ 'SCROLL': scolors[2],
+ 'BUTTON': ('#FFFFFF', scolors[1]),
+ 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST':scolors,
+ 'DESCRIPTION':colors[4]}
+
+ sg.LOOK_AND_FEEL_TABLE['Light'+key] = {'BACKGROUND': scolors[3],
+ 'TEXT': scolors[0],
+ 'INPUT': scolors[1],
+ 'TEXT_INPUT': '#FFFFFF',
+ 'SCROLL': scolors[0],
+ 'BUTTON': ('#FFFFFF', scolors[2]),
+ 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': scolors,
+ 'DESCRIPTION':colors[4]}
+
+ sg.LOOK_AND_FEEL_TABLE['Dark2'+key] = {'BACKGROUND': scolors[1],
+ 'TEXT': scolors[3],
+ 'INPUT': scolors[2],
+ 'TEXT_INPUT': '#000000',
+ 'SCROLL': scolors[2],
+ 'BUTTON': ('#FFFFFF', scolors[1]),
+ 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST':scolors,
+ 'DESCRIPTION':colors[4]}
+
+
+ sg.LOOK_AND_FEEL_TABLE['Light2'+key] = {'BACKGROUND': scolors[2],
+ 'TEXT': scolors[0],
+ 'INPUT': scolors[1],
+ 'TEXT_INPUT': '#FFFFFF',
+ 'SCROLL': scolors[0],
+ 'BUTTON': ('#FFFFFF', scolors[2]),
+ 'PROGRESS': sg.DEFAULT_PROGRESS_BAR_COLOR,
+ 'BORDER': 1,
+ 'SLIDER_DEPTH': 0,
+ 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': scolors,
+ 'DESCRIPTION':colors[4]}
+
+
+WINDOW_BACKGROUND = 'lightblue'
+
+def sample_layout(theme_name, colors, description):
+ name = 'Dark' if theme_name.startswith('D') else 'Light'
+ name += "".join(description[:2])
+ layout = [[sg.Text('Text element', size=(12,1)), sg.InputText(' '.join(colors),text_color='#000000' ),sg.Radio('',theme+'1', key='-INPUT_RAD0-'+theme, default=True, metadata='#000000'),
+ sg.Slider((0,10),size=(10,20), orientation='h')],
+ [sg.T(size=(12,1)), sg.InputText(colors[0], text_color='#FFFFFF'),sg.Radio('',theme+'1', key='-INPUT_RAD1-'+theme, metadata='#FFFFFF')],
+ [sg.T(size=(12,1)), sg.InputText(colors[0], text_color=colors[0]),sg.Radio('',theme+'1', key='-INPUT_RAD2-'+theme, metadata=colors[0])],
+ [sg.T(size=(12,1)),sg.InputText(colors[3], text_color=colors[3]),sg.Radio('',theme+'1', key='-INPUT_RAD3-'+theme, metadata=colors[3])],
+ [sg.T(', '.join(description)), sg.In(name, key='-NEW_THEME_NAME-'+theme)],
+ [sg.Button('OK'), sg.Radio('',theme+'2',key='-BTN_RAD1-'+theme, default=True, metadata=sg.DEFAULT_BUTTON_COLOR),
+ sg.Button('OK', button_color=('white', colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD2-'+theme, metadata=('white', colors[0])),
+ sg.Button('OK', button_color=('black', colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD9-'+theme, metadata=('black', colors[0])),
+ sg.Button('OK', button_color=('white', colors[3])),sg.Radio('', theme+'2', key='-BTN_RAD10-' + theme, metadata=('white', colors[3])),
+ sg.Button('OK', button_color=('black', colors[3])),sg.Radio('', theme+'2', key='-BTN_RAD11-' + theme, metadata=('black', colors[3]))],
+ [sg.Button('OK', button_color=(colors[0],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD3-'+theme, metadata=(colors[0], colors[1])),
+ sg.Button('OK', button_color=(colors[2],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD4-'+theme, metadata=(colors[2], colors[1])),
+ sg.Button('OK', button_color=(colors[3],colors[1])),sg.Radio('',theme+'2',key='-BTN_RAD5-'+theme, metadata=(colors[3], colors[1])),
+ sg.Button('OK', button_color=(colors[3],colors[0])),sg.Radio('',theme+'2',key='-BTN_RAD7-'+theme, metadata=(colors[3], colors[0])),
+ sg.Button('OK', button_color=(colors[0],colors[3])),sg.Radio('',theme+'2',key='-BTN_RAD8-'+theme, metadata=(colors[0], colors[3])),
+ sg.Button('Cancel', button_color=(colors[3], colors[2])),sg.Radio('',theme+'2',key='-BTN_RAD6-'+theme, metadata=(colors[3], colors[2])),
+ ] ]
+ return layout
+# layout = [[sg.Text('Here is list of some themes', font='Default 18', background_color=WINDOW_BACKGROUND)]]
+layout = []
+row = []
+layouts = []
+for count, theme in enumerate(sg.LOOK_AND_FEEL_TABLE.keys()):
+ sg.change_look_and_feel(theme)
+ if count and not(count % CANDIDATES_PER_ROW):
+ layout += [row]
+ row = []
+ row += [sg.CB('',text_color='black', background_color=WINDOW_BACKGROUND, key='-CB-'+theme)]
+ row += [sg.Frame(theme, sample_layout(theme, sg.LOOK_AND_FEEL_TABLE[theme]['COLOR_LIST'], sg.LOOK_AND_FEEL_TABLE[theme]['DESCRIPTION']))]
+ if count and not (count % TOTAL_CANDIDATES_PER_PAGE):
+ if layout:
+ layouts.append(layout)
+ layout = []
+if row:
+ layout += [row]
+if layout:
+ layouts.append(layout)
+
+for layout in layouts:
+ window = sg.Window('PySimpleGUI Theme Maker', layout, background_color=WINDOW_BACKGROUND, default_element_size=(30,1))
+ event, values = window.read()
+ if event is not None and event.startswith('Cancel'):
+ break
+ for key, value in values.items():
+ if type(key) is str and key.startswith('-CB-') and value:
+ theme = key[4:]
+ theme_entry = sg.LOOK_AND_FEEL_TABLE[theme]
+ if values['-INPUT_RAD1-'+theme]:
+ input_text_color = window['-INPUT_RAD1-'+theme].metadata
+ elif values['-INPUT_RAD2-'+theme]:
+ input_text_color = window['-INPUT_RAD2-'+theme].metadata
+ elif values['-INPUT_RAD3-'+theme]:
+ input_text_color = window['-INPUT_RAD3-'+theme].metadata
+ elif values['-INPUT_RAD0-'+theme]:
+ input_text_color = window['-INPUT_RAD0-'+theme].metadata
+ else:
+ print('** ERROR none of the radio buttons are true for input text **')
+ continue
+
+ if values['-BTN_RAD1-'+theme]:
+ b_color = window['-BTN_RAD1-'+theme].metadata
+ elif values['-BTN_RAD2-'+theme]:
+ b_color = window['-BTN_RAD2-'+theme].metadata
+ elif values['-BTN_RAD3-'+theme]:
+ b_color = window['-BTN_RAD3-'+theme].metadata
+ elif values['-BTN_RAD4-'+theme]:
+ b_color = window['-BTN_RAD4-'+theme].metadata
+ elif values['-BTN_RAD5-'+theme]:
+ b_color = window['-BTN_RAD5-'+theme].metadata
+ elif values['-BTN_RAD6-'+theme]:
+ b_color = window['-BTN_RAD6-'+theme].metadata
+ elif values['-BTN_RAD7-'+theme]:
+ b_color = window['-BTN_RAD7-'+theme].metadata
+ elif values['-BTN_RAD8-'+theme]:
+ b_color = window['-BTN_RAD8-'+theme].metadata
+ elif values['-BTN_RAD9-'+theme]:
+ b_color = window['-BTN_RAD9-'+theme].metadata
+ elif values['-BTN_RAD10-'+theme]:
+ b_color = window['-BTN_RAD10-'+theme].metadata
+ elif values['-BTN_RAD11-'+theme]:
+ b_color = window['-BTN_RAD11-'+theme].metadata
+ else:
+ print('** ERROR none of the radio buttons are true for button color **')
+ continue
+ sg.LOOK_AND_FEEL_TABLE[theme]['TEXT_INPUT'] = input_text_color
+ sg.LOOK_AND_FEEL_TABLE[theme]['BUTTON'] = b_color
+ with open('new_theme_dict.py', 'a') as outfile:
+ outfile.write(f"'{values['-NEW_THEME_NAME-'+theme]}' : {sg.LOOK_AND_FEEL_TABLE[theme]},\n")
+ sg.Print(f"'{values['-NEW_THEME_NAME-'+theme]}' : {sg.LOOK_AND_FEEL_TABLE[theme]}\n")
+ window.close()
+ del window
diff --git a/ThemeMaker/color_themes.py b/ThemeMaker/color_themes.py
new file mode 100644
index 00000000..8aa98567
--- /dev/null
+++ b/ThemeMaker/color_themes.py
@@ -0,0 +1,1782 @@
+themes = {
+ '163372': ('#f4efd3', '#cccccc', '#c2b0c9', '#9656a1', ['Yellow', 'Grey', 'Purple', 'Pastel']),
+ '163318': ('#594a4e', '#e78fb3', '#ffc0ad', '#6fc1a5', ['Brown', 'Pink', 'Green', 'Vintage']),
+ '163537': ('#ff8ba7', '#ffc6c7', '#faeee7', '#c3f0ca', ['Pink', 'Green', 'Bright', 'Summer']),
+ '163154': ('#10316b', '#000000', '#e25822', '#ececeb', ['Blue', 'Orange', 'Retro']),
+ '163151': ('#a35638', '#e08f62', '#d7c79e', '#9dab86', ['Brown', 'Autumn', 'Summer', 'Warm']),
+ '163063': ('#ffac8e', '#fd7792', '#3f4d71', '#55ae95', ['Pink', 'Green', 'Retro']),
+ '162867': ('#1b2a49', '#465881', '#00909e', '#c9d1d3', ['Blue', 'Cold', 'Winter']),
+ '162930': ('#3fc5f0', '#42dee1', '#6decb9', '#eef5b2', ['Blue', 'Green', 'Yellow', 'Bright', 'Neon', 'Summer']),
+ '162807': ('#003f5c', '#472b62', '#bc4873', '#fb5b5a', ['Purple', 'Orange', 'Neon']),
+ '162836': ('#9be3de', '#beebe9', '#fffdf9', '#ffe3ed', ['Turquoise', 'Bright']),
+ '162790': ('#110133', '#00918e', '#4dd599', '#ffdc34', ['Turquoise', 'Green', 'Yellow']),
+ '162677': ('#bd574e', '#fa877f', '#ffad87', '#dedef0', ['Red', 'Pink', 'Skin', 'Pastel']),
+ '162174': ('#f45905', '#c70d3a', '#512c62', '#45969b', ['Orange', 'Turquoise']),
+ '162777': ('#eafbea', '#6f9a8d', '#1f6650', '#ea5e5e', ['Green']),
+ '162734': ('#010038', '#293a80', '#537ec5', '#f39422', ['Blue', 'Orange']),
+ '162116': ('#fff4e4', '#f88020', '#d1274b', '#3d0e1e', ['Orange']),
+ '162076': ('#f35588', '#ffbbb4', '#71a95a', '#007944', ['Pink', 'Green']),
+ '161920': ('#39375b', '#745c97', '#d597ce', '#f5b0cb', ['Purple', 'Pastel']),
+ '161696': ('#f8f8f8', '#f1d6ab', '#e3b04b', '#2b2b28', ['Grey', 'Yellow']),
+ '161649': ('#380e7f', '#6915cf', '#d62196', '#e497cd', ['Purple']),
+ '161263': ('#dcffcc', '#9fdfcd', '#baabda', '#d79abc', ['Green', 'Purple', 'Bright', 'Summer', 'Pastel']),
+ '160952': ('#8f4426', '#de6b35', '#f9b282', '#64ccda', ['Brown', 'Orange', 'Warm']),
+ '160620': ('#851de0', '#aa26da', '#c355f5', '#f1fa3c', ['Purple', 'Yellow', 'Neon']),
+ '160646': ('#ffe7d1', '#f6c89f', '#4b8e8d', '#396362', ['Skin', 'Turquoise']),
+ '160243': ('#0c093c', '#df42d1', '#eea5f6', '#fad6d6', ['Purple']),
+ '160589': ('#e5d8bf', '#94aa2a', '#e47312', '#d55252', ['Green', 'Orange', 'Summer', 'Vintage']),
+ '160292': ('#c2e8ce', '#f2eee5', '#f6ad7b', '#be7575', ['Green', 'Orange', 'Brown', 'Pastel', 'Summer']),
+ '160127': ('#090057', '#57007e', '#c400c6', '#ffa069', ['Purple']),
+ '160163': ('#5eb7b7', '#96d1c7', '#fc7978', '#ffafb0', ['Turquoise', 'Red']),
+ '161876': ('#dfddc7', '#f58b54', '#a34a28', '#211717', ['Grey', 'Orange', 'Autumn', 'Halloween']),
+ '162500': ('#6807f9', '#9852f9', '#c299fc', '#ffd739', ['Purple', 'Yellow']),
+ '160018': ('#293462', '#00818a', '#ec9b3b', '#f7be16', ['Blue', 'Turquoise', 'Orange', 'Yellow']),
+ '159891': ('#efe9cc', '#eadea6', '#f6cd90', '#deb881', ['Yellow', 'Bright', 'Pastel', 'Summer', 'Skin']),
+ '159652': ('#003f5c', '#58508d', '#bc5090', '#ff6361', ['Purple', 'Orange']),
+ '159621': ('#494ca2', '#8186d5', '#c6cbef', '#e3e7f1', ['Blue']),
+ '159988': ('#ffd369', '#e26241', '#940a37', '#5b0909', ['Yellow', 'Orange', 'Warm']),
+ '159620': ('#f54291', '#ff78ae', '#ffa0d2', '#fff8cd', ['Pink', 'Bright']),
+ '159618': ('#f1d4d4', '#ddb6c6', '#ac8daf', '#484c7f', ['Skin', 'Pink', 'Purple', 'Pastel']),
+ '159679': ('#f0134d', '#ff6f5e', '#f5f0e3', '#40bfc1', ['Red', 'Orange', 'Turquoise']),
+ '159617': ('#ecfcff', '#b2fcff', '#5edfff', '#3e64ff', ['Blue', 'Neon']),
+ '159378': ('#fff1e9', '#ffd5d5', '#fc7fb2', '#45454d', ['Pink', 'Wedding', 'Skin']),
+ '159233': ('#3c4245', '#5f6769', '#719192', '#dfcdc3', ['Grey', 'Turquoise', 'Cold']),
+ '159131': ('#7c0a02', '#b22222', '#e25822', '#f1bc31', ['Red', 'Orange', 'Warm']),
+ '159619': ('#e6f8f9', '#b1e8ed', '#edb5f5', '#e86ed0', ['Blue', 'Pink', 'Bright']),
+ '158462': ('#443737', '#272121', '#ff0000', '#ff4d00', ['Brown', 'Red', 'Dark', 'Warm', 'Halloween']),
+ '158806': ('#5d1451', '#2f416d', '#14868c', '#94ceca', ['Blue', 'Cold']),
+ '158845': ('#ffe7ad', '#db75c5', '#a05f96', '#6a1051', ['Yellow', 'Purple']),
+ '158955': ('#2a1a5e', '#f45905', '#fb9224', '#fbe555', ['Blue', 'Orange', 'Yellow', 'Sunset']),
+ '159070': ('#f9d5bb', '#f66767', '#d35656', '#3c3d47', ['Orange', 'Red', 'Warm']),
+ '158356': ('#470938', '#1a3e59', '#5c94bd', '#f2d6eb', ['Blue', 'Cold']),
+ '158058': ('#5026a7', '#8d448b', '#cc6a87', '#eccd8f', ['Purple', 'Sunset']),
+ '158271': ('#233714', '#6b591d', '#efcfb6', '#fdeced', ['Brown', 'Skin']),
+ '158349': ('#6d0c74', '#7f78d2', '#d2d0fe', '#fdecff', ['Purple', 'Pink']),
+ '158293': ('#42b883', '#347474', '#35495e', '#ff7e67', ['Green', 'Orange']),
+ '158245': ('#ffdfdf', '#fbc1bc', '#315b96', '#233567', ['Pink', 'Blue', 'Skin']),
+ '157808': ('#512c96', '#3c6f9c', '#dd6892', '#f9c6ba', ['Purple', 'Turquoise', 'Pink', 'Vintage']),
+ '158095': ('#445c3c', '#fda77f', '#c9d99e', '#fae8c8', ['Green', 'Orange', 'Summer', 'Pastel']),
+ '157642': ('#ffbbcc', '#ffcccc', '#ffddcc', '#ffeecc', ['Pink', 'Bright', 'Skin', 'Pastel']),
+ '157748': ('#1a2849', '#505bda', '#b063c5', '#ffaac3', ['Blue', 'Purple', 'Pink', 'Cold']),
+ '157673': ('#43ab92', '#f75f00', '#c93838', '#512c62', ['Turquoise', 'Orange', 'Retro']),
+ '157400': ('#f9f9f9', '#f6ecbf', '#caadde', '#c886e5', ['Yellow', 'Purple', 'Bright', 'Pastel']),
+ '157216': ('#504658', '#f0decb', '#ffb5b5', '#ce2e6c', ['Grey', 'Pink', 'Skin']),
+ '157179': ('#394a6d', '#3c9d9b', '#52de97', '#c0ffb3', ['Turquoise', 'Green', 'Cold']),
+ '157118': ('#23374d', '#1089ff', '#e5e5e5', '#eeeeee', ['Blue', 'Grey', 'Cold']),
+ '156896': ('#3b064d', '#8105d8', '#ed0cef', '#fe59d7', ['Purple', 'Neon']),
+ '157018': ('#bbeaa6', '#e3c878', '#ed9a73', '#e688a1', ['Green', 'Orange', 'Pastel', 'Summer', 'Warm']),
+ '156898': ('#f7e8f6', '#f1c6e7', '#e5b0ea', '#bd83ce', ['Pink', 'Purple', 'Pastel', 'Wedding']),
+ '156759': ('#d9eeec', '#64b2cd', '#3c70a4', '#da9833', ['Blue', 'Summer']),
+ '156692': ('#b2e4d5', '#f2a6a6', '#b18ea6', '#e7f3ee', ['Turquoise', 'Pink', 'Pastel', 'Bright']),
+ '156569': ('#f6f078', '#01d28e', '#434982', '#730068', ['Yellow', 'Green', 'Blue', 'Summer']),
+ '156488': ('#fcf9ea', '#badfdb', '#f8a978', '#ffc5a1', ['Orange', 'Bright', 'Pastel', 'Summer']),
+ '156620': ('#202040', '#202060', '#602080', '#b030b0', ['Black', 'Purple', 'Dark']),
+ '156447': ('#4baea0', '#b6e6bd', '#f1f0cf', '#f0c9c9', ['Green', 'Pastel', 'Bright']),
+ '156357': ('#c70d3a', '#ed5107', '#230338', '#02383c', ['Red', 'Orange', 'Warm']),
+ '156338': ('#ddf796', '#f3fe7e', '#979797', '#757575', ['Yellow', 'Grey']),
+ '156289': ('#47e4bb', '#ec9b3b', '#e8647c', '#000000', ['Turquoise', 'Orange', 'Retro']),
+ '156039': ('#ecf4f3', '#d1eecc', '#76dbd1', '#57a99a', ['Green', 'Turquoise']),
+ '155973': ('#e4f2f0', '#99d8d0', '#70416d', '#170a19', ['Turquoise', 'Purple', 'Pastel', 'Cold']),
+ '156179': ('#fb0091', '#fb8691', '#fb9e91', '#fbda91', ['Pink', 'Orange', 'Skin']),
+ '156086': ('#f7f7f7', '#5d5d5d', '#a0c334', '#e5d429', ['Grey', 'Green']),
+ '155497': ('#d2fafb', '#51dacf', '#41aaa8', '#2c003e', ['Blue', 'Turquoise', 'Cold']),
+ '156010': ('#91b029', '#e6a400', '#eaebd8', '#ffffea', ['Green', 'Orange', 'Summer']),
+ '155912': ('#fa5477', '#ef4b4b', '#f2e3c9', '#7ecfc0', ['Red']),
+ '155496': ('#d2fafb', '#6bc5d2', '#105e62', '#b5525c', ['Blue', 'Winter', 'Cold']),
+ '155144': ('#000272', '#341677', '#a32f80', '#ff6363', ['Blue', 'Dark', 'Neon']),
+ '154853': ('#f77754', '#584b42', '#537d91', '#a4d1c8', ['Orange', 'Brown', 'Turquoise', 'Vintage']),
+ '155460': ('#1fab89', '#ff8080', '#ffba92', '#c6f1d6', ['Green', 'Red']),
+ '155435': ('#010a43', '#f3d3d3', '#eda593', '#ff3f98', ['Pink', 'Skin']),
+ '154559': ('#b7e778', '#40dab2', '#be6283', '#ed7575', ['Green', 'Red', 'Vintage', 'Spring']),
+ '155182': ('#45454d', '#ff4893', '#ffd5d5', '#fff1e9', ['Pink']),
+ '155146': ('#ebefd0', '#32dbc6', '#49beb7', '#ff502f', ['Turquoise', 'Orange', 'Vintage']),
+ '156756': ('#f6f6f6', '#eae9e9', '#d4d7dd', '#420000', ['Grey']),
+ '155139': ('#01024e', '#543864', '#8b4367', '#ff6464', ['Dark']),
+ '155241': ('#f0dd92', '#ffffc5', '#d6e4aa', '#83b582', ['Yellow', 'Summer', 'Pastel']),
+ '153787': ('#eb7070', '#fec771', '#e6e56c', '#64e291', ['Red', 'Orange', 'Green', 'Summer']),
+ '155006': ('#f0d78c', '#fcfafa', '#64c4ed', '#4f81c7', ['Yellow', 'Blue', 'Summer']),
+ '154852': ('#160f30', '#241663', '#a72693', '#eae7af', ['Black', 'Blue', 'Purple', 'Dark']),
+ '154258': ('#c5f0a4', '#35b0ab', '#226b80', '#f34573', ['Green']),
+ '155005': ('#b6ffea', '#fce2ae', '#ffb3b3', '#ffdcf7', ['Turquoise', 'Bright', 'Pastel', 'Skin']),
+ '154644': ('#3a1f5d', '#c83660', '#e15249', '#f6d365', ['Blue', 'Red', 'Yellow', 'Sunset']),
+ '154242': ('#207561', '#589167', '#a0cc78', '#da4302', ['Green']),
+ '154922': ('#61f2f5', '#ffffff', '#e0e0e0', '#723881', ['Blue', 'Grey', 'Purple', 'Neon', 'Bright']),
+ '154209': ('#6e2142', '#943855', '#e16363', '#ffd692', ['Warm', 'Skin']),
+ '153879': ('#ffcbcb', '#ffb5b5', '#407088', '#132743', ['Pink', 'Blue', 'Vintage']),
+ '154142': ('#fcf9ea', '#badfdb', '#49beb7', '#ff8a5c', ['Blue', 'Orange', 'Summer']),
+ '154222': ('#200f21', '#382039', '#5a3d5c', '#f638dc', ['Black', 'Purple', 'Dark']),
+ '153705': ('#9cf196', '#eceba7', '#ebce95', '#edaaaa', ['Green', 'Yellow', 'Pastel']),
+ '153606': ('#042f4b', '#fff6da', '#fbc99d', '#ed1250', ['Orange', 'Skin']),
+ '154210': ('#ecfcff', '#b2fcff', '#5edfff', '#3e64ff', ['Blue', 'Cold', 'Neon']),
+ '153362': ('#ebfffb', '#ff5858', '#61234e', '#032535', ['Red', 'Retro']),
+ '153353': ('#7ecfc0', '#f2e3c9', '#ec8f6a', '#ef4b4b', ['Turquoise', 'Orange']),
+ '152950': ('#f9e090', '#ff935c', '#dc5353', '#a72461', ['Yellow', 'Orange', 'Warm', 'Gold']),
+ '154144': ('#c7f0db', '#8bbabb', '#6c7b95', '#464159', ['Turquoise', 'Cold']),
+ '152872': ('#faf5ef', '#d7d1c9', '#99b19c', '#672f2f', ['Grey', 'Winter']),
+ '152856': ('#ffb997', '#f67e7d', '#843b62', '#0b032d', ['Warm', 'Orange']),
+ '153796': ('#293462', '#216583', '#00818a', '#f7be16', ['Blue', 'Turquoise', 'Cold']),
+ '152973': ('#696464', '#e9e5dd', '#d04925', '#992e24', ['Grey', 'Orange', 'Skin']),
+ '152863': ('#007065', '#00a79d', '#f5c181', '#ffeecf', ['Turquoise', 'Yellow', 'Summer']),
+ '152733': ('#cf455c', '#ffdd67', '#ff8a5c', '#444444', ['Red', 'Yellow', 'Orange', 'Warm']),
+ '152777': ('#f6edcf', '#f0dab1', '#daf1f9', '#a4d7e1', ['Blue', 'Skin', 'Pastel', 'Bright', 'Summer']),
+ '152664': ('#ff8080', '#ffba92', '#e0f5b9', '#c6f1d6', ['Red', 'Pastel', 'Bright', 'Summer']),
+ '152420': ('#f9f6f2', '#f1d6ab', '#a0855b', '#38470b', ['Brown', 'Skin']),
+ '152310': ('#eaeaea', '#a1dd70', '#00bdaa', '#8559a5', ['Grey', 'Green']),
+ '153118': ('#44000d', '#83142c', '#ad1d45', '#f9d276', ['Brown', 'Dark', 'Warm']),
+ '152232': ('#08ffc8', '#fff7f7', '#dadada', '#204969', ['Turquoise', 'Neon', 'Grey', 'Cold']),
+ '152139': ('#ffb6b9', '#fae3d9', '#bbded6', '#8ac6d1', ['Pink', 'Pastel']),
+ '152965': ('#252525', '#ff0000', '#af0404', '#414141', ['Black', 'Red', 'Neon', 'Dark']),
+ '151744': ('#fffcc1', '#fdeaab', '#cba1d2', '#ab72c0', ['Yellow', 'Purple', 'Summer']),
+ '152688': ('#2d3561', '#c05c7e', '#f3826f', '#ffb961', ['Orange', 'Warm', 'Sunset']),
+ '153137': ('#f4f6f6', '#ff9c91', '#cd3f3e', '#1c2938', ['Grey', 'Orange', 'Skin', 'Wedding']),
+ '151774': ('#f5b5fc', '#96f7d2', '#f0f696', '#fcb1b1', ['Purple', 'Neon', 'Pastel', 'Retro', 'Summer']),
+ '152714': ('#f8f8f8', '#50b6bb', '#45969b', '#f96d15', ['Turquoise', 'Orange', 'Retro']),
+ '152509': ('#bb1542', '#eb5f5d', '#fabc74', '#239f95', ['Red']),
+ '151338': ('#fff1ac', '#f9bcdd', '#d5a4cf', '#b689b0', ['Yellow', 'Pink', 'Purple', 'Pastel', 'Spring']),
+ '152246': ('#540e33', '#de356a', '#fdc8b7', '#6e9086', ['Red', 'Vintage']),
+ '151359': ('#f38eff', '#ff00c8', '#ffcece', '#fff0f0', ['Pink', 'Neon', 'Bright']),
+ '152282': ('#f9f3ec', '#63aabc', '#ed3833', '#60204b', ['Turquoise', 'Red', 'Vintage']),
+ '152027': ('#d3f6f3', '#f9fce1', '#fee9b2', '#fbd1b7', ['Blue', 'Yellow', 'Bright', 'Pastel', 'Summer']),
+ '151976': ('#293462', '#216583', '#f76262', '#fff1c1', ['Blue', 'Retro']),
+ '151885': ('#f4ff61', '#a8ff3e', '#32ff6a', '#27aa80', ['Yellow', 'Green', 'Neon', 'Bright', 'Summer']),
+ '151784': ('#60a9a6', '#caf2d7', '#f5fec0', '#fddede', ['Turquoise', 'Bright', 'Summer', 'Pastel']),
+ '151197': ('#f7e8e8', '#f2a2e4', '#f090d9', '#ea7dc7', ['Pink', 'Skin']),
+ '152058': ('#e42c64', '#614ad3', '#2d248a', '#121b74', ['Red', 'Blue']),
+ '151637': ('#aeeff0', '#f1f0d1', '#f0e3c4', '#daa592', ['Blue', 'Beach', 'Pastel']),
+ '151883': ('#ca5fa6', '#f36886', '#fa8282', '#ffaf65', ['Purple', 'Red', 'Warm', 'Wedding']),
+ '151737': ('#fdef96', '#f7b71d', '#afa939', '#2b580c', ['Yellow', 'Orange', 'Green', 'Summer', 'Warm']),
+ '151393': ('#f2f6f5', '#c8dad3', '#93b5b3', '#63707e', ['Grey', 'Vintage']),
+ '151198': ('#fac0e1', '#caa5f1', '#59d4e8', '#39bdc8', ['Pink', 'Turquoise', 'Paste']),
+ '150983': ('#dff0ea', '#95adbe', '#574f7d', '#4f3a65', ['Blue', 'Cold', 'Winter', 'Grey']),
+ '150928': ('#010059', '#52437b', '#ff7a8a', '#fcf594', ['Purple']),
+ '150643': ('#fafdcb', '#aee7e8', '#28c3d4', '#248ea9', ['Yellow', 'Blue', 'Summer']),
+ '150168': ('#17223b', '#263859', '#6b778d', '#ff6768', ['Dark']),
+ '149737': ('#f1d4d4', '#ddb6c6', '#ac8daf', '#484c7f', ['Pink', 'Purple', 'Skin', 'Pastel']),
+ '149522': ('#f6ef98', '#23eae6', '#1b7fbd', '#112f91', ['Blue', 'Summer']),
+ '149558': ('#e6f8f9', '#b1e8ed', '#edb5f5', '#e86ed0', ['Blue', 'Purple', 'Cold']),
+ '149559': ('#525252', '#414141', '#313131', '#ca3e47', ['Grey', 'Dark']),
+ '149560': ('#f4f4f4', '#eadca6', '#e2c275', '#c36a2d', ['Grey', 'Brown', 'Skin', 'Pastel']),
+ '149616': ('#090088', '#930077', '#e4007c', '#ffbd39', ['Blue', 'Red']),
+ '148495': ('#f2f4d1', '#b2d3be', '#89a3b2', '#5e6073', ['Grey']),
+ '148705': ('#f5f687', '#fcfdd8', '#e2bebe', '#b96b9f', ['Green', 'Purple']),
+ '148116': ('#f2f4f6', '#1ee3cf', '#6b48ff', '#0d3f67', ['Grey', 'Turquoise', 'Purple', 'Neon']),
+ '148970': ('#ff487e', '#ff9776', '#ffd5be', '#ffedff', ['Pink', 'Orange', 'Skin', 'Spring']),
+ '148452': ('#c1f6e7', '#ffcbcb', '#bb7171', '#4e3440', ['Turquoise', 'Pink', 'Skin', 'Vintage']),
+ '148361': ('#fff78f', '#22b9ca', '#0c99c1', '#f30cd4', ['Yellow', 'Turquoise', 'Purple', 'Retro']),
+ '148314': ('#ffc6be', '#ffa1c5', '#a773c3', '#854777', ['Pink', 'Purple', 'Warm']),
+ '147884': ('#f1f4df', '#10eaf0', '#0028ff', '#24009c', ['Blue', 'Cold', 'Neon']),
+ '148160': ('#e6f0b6', '#b8e9c0', '#6384b3', '#684949', ['Green']),
+ '147708': ('#064acb', '#366ed8', '#f3a953', '#f2f3f3', ['Blue']),
+ '147876': ('#293462', '#a64942', '#fe5f55', '#fff1c1', ['Red', 'Warm']),
+ '148315': ('#8a00d4', '#d527b7', '#ff82c3', '#ffc46b', ['Purple']),
+ '147615': ('#553c8b', '#9ea9f0', '#ccc1ff', '#ffeafe', ['Purple']),
+ '147574': ('#f6f6f6', '#bdf2d5', '#7ad9f5', '#5d13e7', ['Grey', 'Green', 'Turquoise']),
+ '147387': ('#454d66', '#009975', '#58b368', '#d9d872', ['Green']),
+ '147578': ('#fcf9ec', '#b0f4e6', '#67eaca', '#12d3cf', ['Turquoise', 'Bright', 'Summer']),
+ '147532': ('#2d132c', '#801336', '#c72c41', '#ee4540', ['Dark', 'Black', 'Red']),
+ '147323': ('#5bd1d7', '#348498', '#004d61', '#ff502f', ['Blue']),
+ '147389': ('#b0deff', '#ffc5a1', '#ffd19a', '#fff8a6', ['Blue', 'Orange', 'Skin', 'Bright', 'Pastel']),
+ '147169': ('#fab95b', '#71a0a5', '#665c84', '#212121', ['Orange', 'Turquoise']),
+ '147205': ('#f7ff56', '#94fc13', '#4be3ac', '#032d3c', ['Yellow', 'Green', 'Bright', 'Neon', 'Summer']),
+ '147179': ('#004a2f', '#002f35', '#ff6337', '#ffa323', ['Green', 'Orange']),
+ '147250': ('#eeeeee', '#dedede', '#ff4949', '#c10000', ['Grey', 'Red']),
+ '145544': ('#8adfdc', '#313848', '#735372', '#8f758e', ['Turquoise', 'Vintage']),
+ '145468': ('#22eaca', '#b31e6f', '#ee5a5a', '#ff9e74', ['Turquoise', 'Orange', 'Retro', 'Neon']),
+ '147299': ('#d2f3e0', '#feb9c8', '#f6a7ba', '#f5fbf1', ['Green', 'Pink', 'Bright', 'Pastel']),
+ '145393': ('#e41749', '#f5587b', '#ff8a5c', '#fff591', ['Red', 'Pink', 'Orange', 'Yellow', 'Neon']),
+ '145446': ('#beeef7', '#6fc2d0', '#373a6d', '#ff8246', ['Blue', 'Orange']),
+ '145389': ('#b206b0', '#e41749', '#f5587b', '#ff8a5c', ['Purple', 'Red', 'Warm']),
+ '145355': ('#33313b', '#4592af', '#e3c4a8', '#f6f5f5', ['Black', 'Turquoise', 'Grey', 'Vintage']),
+ '145454': ('#f3c1c6', '#f0f69f', '#b0e0a8', '#d8eff0', ['Pink', 'Bright', 'Pastel', 'Spring']),
+ '145313': ('#bfcd7e', '#ee7777', '#8e2e6a', '#311054', ['Orange', 'Vintage', 'Wedding']),
+ '145229': ('#211717', '#a34a28', '#f58b54', '#dfddc7', ['Black', 'Brown', 'Orange', 'Skin', 'Warm']),
+ '144444': ('#ffeaa5', '#226b80', '#40a798', '#ffebd3', ['Yellow', 'Turquoise', 'Retro']),
+ '145322': ('#fff3a3', '#ff7bb0', '#ff3e6d', '#7572f4', ['Yellow', 'Red', 'Spring', 'Bright', 'Neon']),
+ '145088': ('#6c5ce7', '#7b88ff', '#fdcb6e', '#fff3b1', ['Blue', 'Yellow', 'Summer']),
+ '144698': ('#103c42', '#02576c', '#05a19c', '#ffe837', ['Turquoise']),
+ '144599': ('#e6d385', '#5c7658', '#681313', '#d25959', ['Yellow', 'Green', 'Red']),
+ '144615': ('#866ec7', '#8f71ff', '#82acff', '#b7fbff', ['Purple', 'Blue', 'Cold']),
+ '144758': ('#7fa99b', '#f6e79c', '#f79c1d', '#9c2c2c', ['Yellow', 'Orange', 'Vintage']),
+ '144942': ('#010059', '#107595', '#fdbfb3', '#fcf594', ['Blue']),
+ '144598': ('#ab93c9', '#d698b9', '#eda1ab', '#ffbea3', ['Pastel', 'Skin']),
+ '144332': ('#560d0d', '#76a21e', '#c6cf65', '#f3ff93', ['Brown', 'Green', 'Vintage']),
+ '144426': ('#7189bf', '#df7599', '#ffc785', '#72d6c9', ['Blue', 'Pastel', 'Vintage']),
+ '144330': ('#ebefd0', '#32dbc6', '#49beb7', '#085f63', ['Turquoise', 'Cold']),
+ '145074': ('#ff0b55', '#d61d4e', '#323232', '#ffdee6', ['Red']),
+ '144399': ('#222831', '#393e46', '#d65a31', '#eeeeee', ['Black', 'Grey', 'Orange', 'Dark', 'Halloween']),
+ '144327': ('#f5e1da', '#f1f1f1', '#49beb7', '#085f63', ['Pink', 'Skin', 'Turquoise']),
+ '144191': ('#e8e8e8', '#5588a3', '#145374', '#00334e', ['Grey', 'Blue', 'Cold', 'Winter']),
+ '143744': ('#a9eec2', '#fad284', '#f38181', '#705772', ['Green', 'Orange', 'Vintage', 'Summer']),
+ '144541': ('#7f4782', '#aa5c9f', '#e2598b', '#fdd043', ['Purple']),
+ '143675': ('#616f39', '#ffd98e', '#ffb677', '#ff8364', ['Green', 'Orange', 'Summer', 'Skin', 'Pastel']),
+ '143590': ('#0c084c', '#096386', '#00b7a8', '#f0eec8', ['Blue', 'Turquoise', 'Cold', 'Winter']),
+ '143563': ('#f9f8eb', '#76b39d', '#05004e', '#fd5f00', ['Green', 'Orange', 'Retro']),
+ '143360': ('#eaf5ff', '#a9c6de', '#247e6c', '#e4c666', ['Blue']),
+ '143564': ('#240041', '#900048', '#ff4057', '#ff8260', ['Red', 'Warm']),
+ '143359': ('#fffde8', '#f7e0a3', '#f09c67', '#4c8492', ['Yellow', 'Orange', 'Skin']),
+ '143259': ('#f2eee0', '#c8e6f5', '#5ca0d3', '#5e0a0a', ['Blue']),
+ '144179': ('#f1e4e4', '#15cda8', '#099a97', '#9764c7', ['Grey', 'Green', 'Purple', 'Vintage']),
+ '144326': ('#085f63', '#49beb7', '#facf5a', '#ff5959', ['Turquoise', 'Yellow', 'Red', 'Retro']),
+ '143269': ('#305f72', '#f1d1b5', '#f0b7a4', '#f18c8e', ['Skin', 'Pastel']),
+ '143225': ('#fff5eb', '#f6e0b3', '#dbcc8f', '#4e4e4e', ['Yellow', 'Skin']),
+ '142991': ('#d7f7f5', '#75cac3', '#2a6171', '#f34573', ['Turquoise', 'Cold']),
+ '142837': ('#f0e9e9', '#c19191', '#aa7070', '#8b5d5d', ['Brown', 'Skin']),
+ '142663': ('#ececec', '#9fd3c7', '#385170', '#142d4c', ['Grey', 'Turquoise', 'Blue', 'Cold', 'Winter', 'Pastel']),
+ '142721': ('#f2eee0', '#c8e6f5', '#5ca0d3', '#6d3939', ['Blue', 'Summer']),
+ '142797': ('#fffbbe', '#eec1ea', '#be97dc', '#a374d5', ['Yellow', 'Pink', 'Purple', 'Pastel', 'Bright']),
+ '142073': ('#eaeaea', '#00bdaa', '#257aa6', '#621e81', ['Grey', 'Turquoise']),
+ '142677': ('#444444', '#f30067', '#00d1cd', '#eaeaea', ['Grey', 'Red', 'Turquoise', 'Neon']),
+ '142173': ('#c5fad9', '#aceacf', '#f77fee', '#db66e4', ['Green', 'Purple']),
+ '141859': ('#fffeec', '#aeddcd', '#e4508f', '#556fb5', ['Yellow', 'Green', 'Red', 'Blue', 'Pastel', 'Spring']),
+ '141761': ('#00028c', '#21aa93', '#01676b', '#ffc3e7', ['Blue', 'Green', 'Pink', 'Vintage']),
+ '141715': ('#5a3921', '#6b8c42', '#7bc67b', '#ffffb5', ['Brown', 'Green']),
+ '142059': ('#ffc15e', '#8158fc', '#692db7', '#34314f', ['Purple']),
+ '141682': ('#480032', '#df0054', '#ff8b6a', '#ffd6c2', ['Brown', 'Red', 'Orange', 'Warm', 'Halloween']),
+ '141714': ('#302387', '#ff3796', '#00faac', '#fffdaf', ['Blue', 'Pink', 'Green', 'Neon', 'Retro']),
+ '141668': ('#ff62a5', '#ffe5ae', '#6b76ff', '#dee0d9', ['Pink', 'Yellow', 'Grey', 'Retro']),
+ '141642': ('#f5c7f7', '#c54fa7', '#8d309b', '#3426a4', ['Pink', 'Purple']),
+ '141641': ('#f9fd50', '#85ef47', '#00bd56', '#207dff', ['Yellow', 'Green', 'Blue', 'Neon', 'Bright', 'Summer']),
+ '141534': ('#183661', '#1c4b82', '#dd6b4d', '#dae1e7', ['Blue', 'Orange']),
+ '141624': ('#7fe7cc', '#dfe38e', '#efca8c', '#f17e7e', ['Turquoise', 'Yellow', 'Red', 'Pastel']),
+ '141287': ('#e7eaf6', '#a2a8d3', '#38598b', '#113f67', ['Blue', 'Grey', 'Cold', 'Winter']),
+ '141416': ('#11144c', '#3a9679', '#fabc60', '#e16262', ['Green', 'Yellow', 'Red', 'Retro']),
+ '141096': ('#e3c4a8', '#4592af', '#226089', '#000000', ['Brown', 'Blue']),
+ '141219': ('#f6f5f5', '#e9e4e6', '#3bb4c1', '#048998', ['Grey', 'Turquoise']),
+ '140793': ('#dadddf', '#f69314', '#c40b13', '#621295', ['Grey', 'Orange', 'Purple']),
+ '140815': ('#ffd7e8', '#f2c0ff', '#bf9fee', '#866ec7', ['Pink', 'Purple']),
+ '140770': ('#f8b739', '#f3dcad', '#e44985', '#bd245f', ['Yellow', 'Pink']),
+ '141031': ('#f54291', '#ff78ae', '#ffa0d2', '#fff8cd', ['Pink', 'Yellow']),
+ '141288': ('#f3f9fb', '#87c0cd', '#226597', '#113f67', ['Blue', 'Cold', 'Winter']),
+ '141044': ('#1d1919', '#ffce76', '#0075f6', '#0900c3', ['Black', 'Yellow', 'Blue']),
+ '140056': ('#eeeeee', '#d8cbbb', '#bb8fa9', '#560764', ['Grey', 'Purple', 'Pastel']),
+ '139817': ('#cdffeb', '#ffaaaa', '#c7004c', '#8f1537', ['Red', 'Bright']),
+ '139648': ('#494ca2', '#8186d5', '#c6cbef', '#e3e7f1', ['Purple', 'Cold', 'Winter']),
+ '139838': ('#ff5d9e', '#8f71ff', '#82acff', '#8bffff', ['Pink', 'Purple', 'Blue', 'Bright', 'Neon']),
+ '140436': ('#33313b', '#62374e', '#007880', '#fdc57b', ['Vintage']),
+ '140707': ('#fcd307', '#1c1259', '#ee4266', '#d5daeb', ['Yellow', 'Red', 'Grey', 'Retro']),
+ '140769': ('#dbe9b7', '#fdfdf6', '#f4dada', '#b8b2a6', ['Green', 'Pink', 'Bright', 'Pastel', 'Spring', 'Wedding']),
+ '141021': ('#b7fbff', '#fff6be', '#ffe0a3', '#ffa1ac', ['Blue', 'Yellow', 'Summer', 'Bright', 'Spring']),
+ '139632': ('#421b9b', '#a06ee1', '#cbbcf6', '#cef9e2', ['Purple', 'Green', 'Retro']),
+ '141100': ('#022c43', '#053f5e', '#115173', '#ffd700', ['Blue', 'Dark', 'Yellow', 'Night']),
+ '140495': ('#faf562', '#f36a7b', '#b824a4', '#aaaaaa', ['Yellow', 'Purple', 'Grey']),
+ '140172': ('#352961', '#774181', '#e6b2c6', '#f6e5e5', ['Purple', 'Pink']),
+ '140155': ('#f8f1f1', '#d2c8c8', '#a3816a', '#0a065d', ['Grey', 'Winter', 'Skin']),
+ '140154': ('#1b1919', '#616f39', '#a7d129', '#f8eeb4', ['Black', 'Green']),
+ '140700': ('#ffe6eb', '#defcfc', '#cbf1f5', '#a6e3e9', ['Pink', 'Blue', 'Bright', 'Pastel']),
+ '139667': ('#070d59', '#1f3c88', '#5893d4', '#f7b633', ['Blue', 'Cold']),
+ '139670': ('#f857b5', '#f781bc', '#fdffdc', '#c5ecbe', ['Pink', 'Green', 'Spring']),
+ '139970': ('#6f0765', '#4c0045', '#bd512f', '#ffb228', ['Purple', 'Orange']),
+ '140057': ('#eeeeee', '#acc6aa', '#71a0a5', '#77628c', ['Grey', 'Green', 'Purple', 'Pastel', 'Vintage']),
+ '139633': ('#5d3a3a', '#905858', '#b5e0ba', '#f7ffbd', ['Brown']),
+ '139458': ('#99235c', '#df4d19', '#a43737', '#572121', ['Purple', 'Orange', 'Brown', 'Warm']),
+ '139521': ('#b4e9e2', '#32dbc6', '#309286', '#ebefd0', ['Turquoise']),
+ '139409': ('#35477d', '#6c5b7b', '#c06c84', '#f67280', ['Blue', 'Red']),
+ '139362': ('#a1dd70', '#fdfff0', '#e8ecd6', '#a23131', ['Green', 'Red', 'Spring']),
+ '139296': ('#00a8b5', '#774898', '#de4383', '#f3ae4b', ['Turquoise', 'Purple', 'Orange', 'Retro']),
+ '139297': ('#6d3580', '#cc4165', '#e4734f', '#ffe26f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset', 'Warm']),
+ '139181': ('#010101', '#69779b', '#acdbdf', '#f0ece2', ['Black', 'Blue', 'Winter', 'Dark', 'Cold']),
+ '139410': ('#51eaea', '#fffde1', '#ff9d76', '#fb3569', ['Blue', 'Orange', 'Red', 'Summer', 'Bright', 'Spring']),
+ '139257': ('#f68787', '#f8a978', '#f1eb9a', '#a4f6a5', ['Red', 'Orange', 'Yellow', 'Green', 'Bright', 'Neon', 'Spring']),
+ '139088': ('#d9d9d9', '#e88a1a', '#cf3030', '#141414', ['Grey', 'Orange', 'Autumn', 'Halloween']),
+ '139087': ('#10316b', '#0b8457', '#eac100', '#dee1ec', ['Blue', 'Green', 'Yellow', 'Grey', 'Vintage']),
+ '138719': ('#5e0606', '#831212', '#970690', '#ffa400', ['Brown', 'Purple', 'Orange', 'Warm']),
+ '139015': ('#ffcece', '#ffc1c8', '#ffe3b0', '#8ed6ff', ['Pink', 'Yellow', 'Blue', 'Pastel', 'Bright', 'Skin']),
+ '138663': ('#233142', '#4f9da6', '#facf5a', '#ff5959', ['Blue', 'Yellow', 'Red']),
+ '138966': ('#f3f8ff', '#deecff', '#c6cfff', '#e8d3ff', ['Blue', 'Ping', 'Pastel', 'Wedding', 'Bright']),
+ '138572': ('#ffa900', '#9d8221', '#014441', '#01252a', ['Orange', 'Turquoise']),
+ '138947': ('#df0e62', '#fac70b', '#127681', '#21174a', ['Red', 'Yellow', 'Turquoise', 'Retro']),
+ '138573': ('#e8e2db', '#fab95b', '#f16821', '#1a3263', ['Grey', 'Orange', 'Autumn', 'Gold', 'Skin']),
+ '138358': ('#1c819e', '#005542', '#ffbe00', '#dfdfdf', ['Turquoise', 'Yellow']),
+ '138363': ('#ffd3de', '#f6b8d1', '#5dc0a6', '#3f8f8d', ['Pink', 'Turquoise', 'Spring']),
+ '138365': ('#6927ff', '#837dff', '#bf81ff', '#ffd581', ['Purple', 'Neon']),
+ '138308': ('#f77754', '#018790', '#0a516d', '#2b2726', ['Orange', 'Turquoise']),
+ '138147': ('#3c415e', '#738598', '#dfe2e2', '#1cb3c8', ['Grey', 'Blue', 'Winter', 'Cold']),
+ '138409': ('#f9989f', '#fccb8f', '#faf096', '#c5f8c8', ['Red', 'Orange', 'Yellow', 'Green', 'Bright', 'Spring', 'Summer']),
+ '137864': ('#113f67', '#34699a', '#408ab4', '#65c6c4', ['Blue', 'Turquoise', 'Cold']),
+ '138325': ('#fcf9ed', '#ffba5a', '#ff7657', '#665c84', ['Orange', 'Skin']),
+ '138016': ('#f5f5f5', '#30e3ca', '#2f89fc', '#40514e', ['Grey', 'Turquoise', 'Blue', 'Cold', 'Retro', 'Neon']),
+ '137905': ('#283148', '#913535', '#bbbbbb', '#e9eec9', ['Brown', 'Grey', 'Autumn', 'Vintage']),
+ '138039': ('#fff4e3', '#ffcdab', '#ffa45c', '#5d5d5a', ['Orange', 'Warm', 'Autumn', 'Skin']),
+ '137655': ('#074684', '#0ea5c6', '#a0edf7', '#f2efb6', ['Blue']),
+ '138132': ('#eef2f5', '#ea168e', '#612570', '#1eafed', ['Grey', 'Pink', 'Purple', 'Blue', 'Retro', 'Neon']),
+ '137927': ('#feffdb', '#ffc60b', '#ff8b00', '#444444', ['Yellow', 'Orange', 'Summer', 'Autumn', 'Warm', 'Gold']),
+ '137721': ('#00204a', '#005792', '#448ef6', '#fdb44b', ['Blue', 'Orange', 'Winter', 'Cold']),
+ '137525': ('#900c3f', '#c70039', '#ff5733', '#ffc300', ['Blue', 'Orange', 'Yellow', 'Warm']),
+ '137229': ('#f4f9f4', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'White']),
+ '137415': ('#33313b', '#3c4f65', '#834c69', '#e6f5ff', ['Black', 'Dark']),
+ '137086': ('#fffafa', '#ffe0e0', '#ffc0d0', '#efdfbf', ['Pink', 'Pastel', 'Bright', 'Spring', 'White', 'Skin']),
+ '137660': ('#a2eae2', '#41aaa8', '#105e62', '#b5525c', ['Turquoise', 'Cold', 'Winter']),
+ '137720': ('#d34848', '#ff8162', '#ffcd60', '#fffa67', ['Red', 'Yellow', 'Warm']),
+ '137739': ('#ffcccc', '#caabd8', '#9873b9', '#714288', ['Pink', 'Purple', 'Pastel', 'Wedding']),
+ '137537': ('#0c005a', '#bc2525', '#ff0000', '#eaeaea', ['Blue', 'Red', 'Neon']),
+ '137357': ('#cdffeb', '#009f9d', '#07456f', '#0f0a3c', ['Turquoise', 'Blue', 'Cold', 'Winter']),
+ '137439': ('#ffefe0', '#fed9ca', '#c5c5c5', '#7d7d7d', ['Grey', 'Skin']),
+ '137194': ('#c82121', '#dee1ec', '#becbff', '#0d0cb5', ['Red', 'Blue', 'Retro']),
+ '137170': ('#ff8484', '#d84c73', '#5c3b6f', '#35234b', ['Pink', 'Purple']),
+ '137109': ('#f4f3f3', '#dfdfdf', '#bfd8d5', '#b1bed5', ['Grey', 'Pastel', 'Bright', 'White']),
+ '137195': ('#3a0088', '#930077', '#e61c5d', '#ffe98a', ['Purple', 'Red', 'Yellow', 'Sunset']),
+ '137244': ('#ef6c57', '#7ed3b2', '#b9e6d3', '#f2f2f2', ['Red', 'Green', 'Pastel']),
+ '137001': ('#4e2161', '#9bbfab', '#ebf0c2', '#774e26', ['Purple', 'Brown', 'Vintage']),
+ '136945': ('#cd4545', '#f16821', '#f3a333', '#fffe9a', ['Red', 'Orange', 'Yellow', 'Warm', 'Halloween', 'Summer']),
+ '137211': ('#eeeeee', '#cde8f6', '#d195f9', '#0033c7', ['Grey', 'Blue', 'Purple']),
+ '136806': ('#f59aa3', '#f5e4c3', '#34a7b2', '#5b2e35', ['Pink', 'Yellow', 'Turquoise', 'Brown']),
+ '136567': ('#222831', '#393e46', '#b55400', '#eeeeee', ['Black', 'Grey', 'Brown', 'Dark', 'Winter']),
+ '136570': ('#fafafa', '#e3e3e3', '#ee6f57', '#cb3737', ['Grey', 'Orange', 'Vintage', 'Retro', 'White', 'Skin']),
+ '136572': ('#d1d1d1', '#c8e8ed', '#f7fdb1', '#ded473', ['Grey', 'Blue', 'Yellow', 'Bright']),
+ '136769': ('#fe9191', '#e4406f', '#ca2374', '#9c297f', ['Orange', 'Red', 'Warm', 'Wedding']),
+ '136716': ('#6e3b3b', '#ac3f21', '#be6a15', '#f3cf7a', ['Brown', 'Warm', 'Gold', 'Skin']),
+ '135813': ('#6effbf', '#dcaee8', '#ffc5e6', '#fcf2db', ['Green', 'Purple', 'Pink', 'Bright', 'Neon']),
+ '136053': ('#d6f8b8', '#acdeaa', '#8fbbaf', '#6b7b8e', ['Green', 'Pastel', 'Cold']),
+ '136873': ('#e6dedd', '#8f1d14', '#1b120f', '#f89d13', ['Grey', 'Red', 'Black', 'Orange', 'Warm', 'Halloween', 'Autumn']),
+ '136330': ('#ebfffb', '#7efaff', '#13abc4', '#3161a3', ['Blue', 'Cold', 'Winter', 'Neon']),
+ '136145': ('#5c4d4d', '#915b4a', '#a96851', '#f2f1e7', ['Grey', 'Brown', 'Warm', 'Vintage', 'Skin']),
+ '135566': ('#fa86be', '#a275e3', '#9aebed', '#fffcab', ['Pink', 'Purple', 'Yellow', 'Bright', 'Neon']),
+ '135842': ('#c9f658', '#dbff3d', '#55968f', '#8acbbb', ['Green', 'Turquoise', 'Bright', 'Neon']),
+ '136148': ('#ffaaaa', '#e37070', '#c7004c', '#8f1537', ['Pink', 'Red', 'Warm', 'Skin']),
+ '135960': ('#69779b', '#9692af', '#acdbdf', '#d7eaea', ['Grey', 'Blue', 'Pastel', 'Cold', 'Winter']),
+ '136290': ('#ffedc6', '#cdeeaa', '#96dae4', '#6d70c6', ['Yellow', 'Green', 'Blue', 'Summer']),
+ '136149': ('#f185b3', '#d52484', '#90007f', '#3d0043', ['Pink', 'Purple']),
+ '135873': ('#ffe6eb', '#defcfc', '#cbf1f5', '#a6e3e9', ['Pink', 'Blue', 'Pastel', 'Bright']),
+ '135814': ('#1b335f', '#ff6bd6', '#ffb0fe', '#ffecd3', ['Pink', 'Yellow']),
+ '135904': ('#fbfad3', '#c6e377', '#729d39', '#36622b', ['Green']),
+ '135910': ('#e8e2db', '#fab95b', '#f5564e', '#1a3263', ['Grey', 'Orange', 'Warm', 'Autumn', 'Gold']),
+ '135151': ('#f9f8eb', '#76b39d', '#05004e', '#fd5f00', ['Green', 'Orange', 'Retro', 'Vintage']),
+ '135383': ('#5d50c6', '#f85e9f', '#f18fac', '#facd49', ['Purple', 'Pink', 'Yellow']),
+ '135565': ('#f05a28', '#f7931e', '#fff0bc', '#fefcdb', ['Orange', 'Yellow', 'Warm', 'Summer', 'Autumn', 'Gold', 'Skin']),
+ '134291': ('#f3f9fb', '#474f85', '#51e3d4', '#f3ecd3', ['Blue', 'Turquoise', 'Cold', 'White']),
+ '135431': ('#3e3838', '#ae7c7c', '#6cbbb3', '#efe784', ['Brown', 'Turquoise', 'Yellow', 'Retro']),
+ '134056': ('#ffb4ac', '#679186', '#264e70', '#ffebd3', ['Pink', 'Green', 'Blue', 'Vintage', 'Wedding', 'Pastel']),
+ '134309': ('#a8026f', '#db2d43', '#e76838', '#fbd5af', ['Purple', 'Orange', 'Sunset', 'Warm']),
+ '135437': ('#fcf8f3', '#aedadd', '#db996c', '#6e7da2', ['Blue', 'Brown', 'Vintage']),
+ '135573': ('#b5edba', '#f06f32', '#a44444', '#594129', ['Orange', 'Brown']),
+ '135057': ('#ffeed0', '#f79f24', '#f12d2d', '#7c064d', ['Orange', 'Red', 'Sunset', 'Warm', 'Summer']),
+ '134245': ('#182952', '#2b3595', '#7045af', '#e14594', ['Blue', 'Purple', 'Dark']),
+ '133895': ('#d7f7f5', '#75cac3', '#2a6171', '#f3d516', ['Turquoise', 'Yellow']),
+ '134927': ('#070d59', '#1f3c88', '#5893d4', '#ceddef', ['Blue', 'Cold', 'Winter']),
+ '133828': ('#fafafa', '#e0bb20', '#841818', '#000000', ['Orange', 'Red', 'Black', 'Autumn', 'Halloween', 'White']),
+ '133859': ('#20716a', '#23a393', '#ffc0c2', '#f7e9e3', ['Turquoise', 'Pink']),
+ '133655': ('#db2d43', '#87e5da', '#c7f2e3', '#f7aa00', ['Red', 'Turquoise', 'Orange', 'Retro']),
+ '133330': ('#587850', '#709078', '#78b0a0', '#f8d0b0', ['Green', 'Pastel']),
+ '133349': ('#ff8f56', '#ff5959', '#984a59', '#60424c', ['Orange', 'Warm', 'Brown']),
+ '133164': ('#f2f4fb', '#d22780', '#f8b500', '#5e227f', ['Grey', 'Purple', 'White']),
+ '133103': ('#ebebe3', '#2b2b28', '#4a4a48', '#c19898', ['Grey', 'Black', 'Skin']),
+ '134419': ('#feffdf', '#ffe79a', '#ffa952', '#ef5a5a', ['Yellow', 'Orange', 'Red', 'Warm', 'Bright', 'Spring']),
+ '134510': ('#ebf0f6', '#98ccd3', '#364e68', '#132238', ['Grey', 'Blue', 'Cold', 'Winter']),
+ '132460': ('#fdf1db', '#a6cb12', '#e00543', '#84253e', ['Green', 'Red', 'Summer', 'Neon']),
+ '133340': ('#1d5464', '#207e82', '#298f9b', '#d8d860', ['Turquoise']),
+ '133192': ('#c1224f', '#f16f6f', '#94d2e6', '#fff78f', ['Red', 'Blue', 'Yellow']),
+ '133430': ('#f3f6c8', '#ea9c1b', '#5f685a', '#362207', ['Yellow', 'Orange', 'Grey', 'Autumn']),
+ '133121': ('#0b032d', '#843b62', '#f67e7d', '#ffb997', ['Black', 'Purple', 'Orange', 'Halloween']),
+ '133026': ('#ece493', '#84a1be', '#5c7893', '#535962', ['Yellow', 'Blue']),
+ '132892': ('#f3f0d1', '#e29c68', '#c85108', '#a20e0e', ['Orange', 'Red', 'Autumn', 'Skin']),
+ '132843': ('#260c1a', '#f05d23', '#c5d86d', '#f7f7f2', ['Black', 'Orange', 'Green', 'Autumn', 'Halloween']),
+ '132595': ('#faf9f9', '#add2c9', '#5ea3a3', '#488b8f', ['Grey', 'Turquoise', 'White']),
+ '132296': ('#eaec96', '#43c0ac', '#a93199', '#fa0559', ['Yellow', 'Turquoise', 'Purple', 'Neon']),
+ '131930': ('#f9ecec', '#f0d9da', '#c8d9eb', '#ecf2f9', ['Pink', 'Blue', 'Pastel', 'Skin']),
+ '132247': ('#071e3d', '#1f4287', '#278ea5', '#21e6c1', ['Blue', 'Turquoise', 'Dark', 'Winter']),
+ '132003': ('#edfffa', '#8bd5cb', '#c56868', '#974949', ['Turquoise', 'Brown', 'Winter']),
+ '132031': ('#6b76ff', '#a5aeff', '#c8e4fe', '#feffe0', ['Blue', 'Yellow', 'Summer']),
+ '132222': ('#fbeed7', '#ffba5a', '#ff7657', '#665c84', ['Orange']),
+ '131913': ('#1d2323', '#5c848e', '#decdc3', '#e0e0ec', ['Black', 'Turquoise', 'Grey', 'Winter']),
+ '131456': ('#f9f8eb', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'Pastel']),
+ '132032': ('#05004e', '#ff0000', '#fb7777', '#ffcccc', ['Blue', 'Red', 'Halloween']),
+ '131949': ('#612147', '#509aaf', '#7dd8c7', '#f5ffc3', ['Turquoise']),
+ '132045': ('#fcf5ee', '#fbe8e7', '#f7ddde', '#ffc4d0', ['Skin', 'Pastel', 'White', 'Skin']),
+ '131527': ('#45b7b8', '#706381', '#2c3848', '#f7de1c', ['Turquoise', 'Grey', 'Yellow']),
+ '131278': ('#ffffd2', '#e4e4e4', '#8293ff', '#503bff', ['Yellow', 'Blue', 'Summer', 'Bright']),
+ '131852': ('#fdf0f6', '#951555', '#771144', '#1e0411', ['Pink', 'Purple', 'Black', 'Wedding']),
+ '131743': ('#d1f6c1', '#45b7b7', '#8b4c8c', '#f57665', ['Green', 'Turquoise', 'Purple', 'Orange', 'Retro']),
+ '131504': ('#ff9234', '#ffcd3c', '#fefed5', '#35d0ba', ['Orange', 'Turquoise', 'Bright']),
+ '131839': ('#adccc7', '#144c52', '#053220', '#d34c26', ['Turquoise', 'Orange', 'Brown', 'Winter', 'Cold']),
+ '130905': ('#64638f', '#9795cf', '#aba9e9', '#cbc9ff', ['Purple', 'Cold', 'Winter']),
+ '131842': ('#fbf9fa', '#fd0054', '#a80038', '#2b2024', ['Grey', 'Red', 'Black', 'White']),
+ '131404': ('#373640', '#63686e', '#7e97a6', '#b6f7c1', ['Black', 'Grey', 'Green']),
+ '131306': ('#f2f4b2', '#cce490', '#0c907d', '#0d627a', ['Green']),
+ '131234': ('#f9f9f9', '#bcbab8', '#9d8f8f', '#625757', ['Grey']),
+ '131292': ('#a26ea1', '#f18a9b', '#ffb480', '#ffff9d', ['Sunset', 'Purple', 'Orange', 'Yellow']),
+ '131235': ('#fff0f8', '#ffc2e9', '#cca2e1', '#543e5c', ['Pink', 'Wedding']),
+ '131403': ('#373331', '#605a56', '#80ac7b', '#e8eaa1', ['Black', 'Grey', 'Green']),
+ '130857': ('#7acfdf', '#f47645', '#f9ad8d', '#fde3d9', ['Blue', 'Orange']),
+ '130847': ('#deecfc', '#b9ceeb', '#87a8d0', '#c3b4d2', ['Blue', 'Grey', 'Winter', 'Pastel']),
+ '131265': ('#f2f7ff', '#0b409c', '#10316b', '#ffe867', ['Blue', 'Yellow', 'Winter', 'Cold']),
+ '131233': ('#c7f2e3', '#9ed9c5', '#eeddd2', '#b73535', ['Turquoise', 'Red']),
+ '130541': ('#9fe8fa', '#26baee', '#73d2f3', '#fff4e0', ['Blue', 'Summer', 'Bright']),
+ '130807': ('#f7f7f7', '#eeeeee', '#393e46', '#929aab', ['Grey', 'White']),
+ '132357': ('#a8026f', '#db2d43', '#e76838', '#fbf9af', ['Purple', 'Orange', 'Yellow', 'Sunset']),
+ '130836': ('#b8ffd0', '#ecffc1', '#ffe6cc', '#dfbaf7', ['Green', 'Yellow', 'Purple', 'Bright', 'Spring', 'Neon']),
+ '130904': ('#f8b500', '#ece8d9', '#00adb5', '#393e46', ['Orange', 'Turquoise']),
+ '130476': ('#005792', '#53cde2', '#d1f4fa', '#edf9fc', ['Blue', 'Cold', 'Winter']),
+ '130941': ('#1fe5bd', '#41a7b3', '#5e227f', '#d22780', ['Turquoise', 'Purple']),
+ '131266': ('#f2f4fb', '#ff9280', '#ff2400', '#45315d', ['Grey', 'Orange']),
+ '130199': ('#033fff', '#4a9ff5', '#5ff4ee', '#c2fcf6', ['Blue', 'Cold', 'Winter']),
+ '130498': ('#ccf0c3', '#bca3ca', '#7c4789', '#4a0e5c', ['Green', 'Purple', 'Retro']),
+ '130443': ('#000000', '#3e432e', '#616f39', '#a7d129', ['Black', 'Green', 'Dark', 'Winter']),
+ '130852': ('#73dbc4', '#faf7e6', '#ff008b', '#fff8a1', ['Turquoise', 'Pink', 'Yellow', 'Spring', 'Neon']),
+ '130428': ('#2d3999', '#9a1ba0', '#f08181', '#ebbb91', ['Purple']),
+ '130136': ('#f5efe3', '#e6e7e5', '#f7d3ba', '#a6aa9c', ['Grey', 'Pastel', 'Skin']),
+ '129370': ('#dfe2fe', '#b1cbfa', '#8e98f5', '#7874f2', ['Purple', 'Cold', 'Winter']),
+ '130871': ('#ff1f5a', '#ffd615', '#f9ff21', '#1e2a78', ['Red', 'Yellow', 'Bright', 'Neon']),
+ '130221': ('#d1f4fa', '#005792', '#ffe6eb', '#ffcdcd', ['Blue', 'Pink']),
+ '130422': ('#ddf516', '#12e2a3', '#389168', '#0f117a', ['Yellow', 'Turquoise', 'Blue']),
+ '130172': ('#343434', '#e6b31e', '#fcfaf1', '#cacaca', ['Grey', 'Orange', 'Gold']),
+ '130345': ('#0000ff', '#6a5acd', '#add8e6', '#e6e6fa', ['Blue', 'Purple', 'Cold']),
+ '130295': ('#cb9b42', '#b1d1c5', '#f2f3ee', '#dbd7cb', ['Brown', 'Grey', 'Pastel']),
+ '130374': ('#ff8000', '#d3560e', '#851e52', '#521168', ['Orange', 'Purple', 'Warm']),
+ '129119': ('#dcb5ff', '#d9f2ff', '#a5bdfd', '#77529e', ['Pink', 'Blue', 'Purple']),
+ '129199': ('#f7f4e3', '#d2e1c8', '#fee4a6', '#f9c4aa', ['Green', 'Yellow', 'Pastel', 'Summer']),
+ '130118': ('#12e6c8', '#a287f4', '#414141', '#000000', ['Turquoise', 'Purple', 'Grey', 'Black']),
+ '129031': ('#bae5d5', '#d7acd4', '#eec2c2', '#f2f2b0', ['Turquoise', 'Purple', 'Yellow', 'Pastel', 'Retro']),
+ '130108': ('#573697', '#933f99', '#e88c5d', '#fadbac', ['Purple', 'Orange', 'Wedding']),
+ '129160': ('#f1fff1', '#c4f0c5', '#be3737', '#6a0000', ['Green', 'Red']),
+ '128881': ('#ffdfd3', '#fec8d8', '#d291bc', '#957dad', ['Pink', 'Purple', 'Pastel', 'Vintage', 'Warm', 'Skin']),
+ '129865': ('#a3f3eb', '#f1ffab', '#fbd341', '#fb9a40', ['Blue', 'Yellow', 'Orange', 'Gold', 'Summer', 'Bright']),
+ '130038': ('#2c2828', '#3b2c85', '#219897', '#85cfcb', ['Black', 'Purple', 'Turquoise', 'Dark', 'Winter']),
+ '129857': ('#faf6e9', '#ece8d9', '#fffdf6', '#494949', ['Grey', 'Pastel', 'Wedding', 'White', 'Skin']),
+ '129890': ('#5f1854', '#8b104e', '#1abb9c', '#f7f7f7', ['Purple', 'Turquoise']),
+ '129673': ('#20716a', '#23a393', '#f4a9c7', '#fff78c', ['Green', 'Pink', 'Yellow', 'Wedding']),
+ '129495': ('#6bd5e1', '#ffd98e', '#ffb677', '#ff8364', ['Blue', 'Yellow', 'Orange', 'Summer']),
+ '130290': ('#612c83', '#509aaf', '#7dd8c7', '#f5ffc3', ['Purple', 'Turquoise', 'Yellow']),
+ '129982': ('#c3f1ff', '#f87d42', '#db3951', '#00136c', ['Blue', 'Orange']),
+ '128882': ('#f0ece2', '#dfd3c3', '#c7b198', '#596e79', ['Grey', 'Brown', 'Pastel', 'Vintage', 'Skin']),
+ '127205': ('#fb929e', '#ffdfdf', '#fff6f6', '#aedefc', ['Pink', 'Blue']),
+ '129224': ('#f5e965', '#ff9668', '#db456f', '#a74faf', ['Yellow', 'Orange', 'Purple', 'Sunset', 'Neon']),
+ '128764': ('#dbf1f2', '#cd5555', '#882042', '#efedbb', ['Blue', 'Red', 'Yellow', 'Vintage', 'Wedding']),
+ '126476': ('#d3d5fd', '#929aab', '#474a56', '#0b0b0d', ['Purple', 'Grey', 'Black', 'Winter', 'Cold']),
+ '126653': ('#35013f', '#b643cd', '#ff5da2', '#99ddcc', ['Black', 'Purple', 'Pink', 'Turquoise', 'Wedding', 'Retro', 'Neon']),
+ '126189': ('#eeeeee', '#7971ea', '#393e46', '#222831', ['Grey', 'Purple', 'Black', 'Wedding']),
+ '128556': ('#a1c45a', '#fff9e0', '#f1c550', '#ea4c4c', ['Green', 'Yellow', 'Red', 'Summer']),
+ '126603': ('#481380', '#742dd2', '#efb1ff', '#ffe2ff', ['Purple', 'Pink', 'Cold']),
+ '126547': ('#00a8b5', '#774898', '#e62a76', '#fbb901', ['Turquoise', 'Purple', 'Pink', 'Yellow', 'Retro']),
+ '125778': ('#fdfdc4', '#ffe8cf', '#ffdede', '#ccffec', ['Yellow', 'Pink', 'Turquoise', 'Bright', 'Pastel', 'Summer']),
+ '125409': ('#ecf4f3', '#76dbd1', '#57a99a', '#555151', ['Grey', 'Turquoise']),
+ '125435': ('#f0f2eb', '#b5592a', '#f09027', '#8cbeaa', ['Grey', 'Brown', 'Turquoise', 'Autumn', 'Skin']),
+ '126369': ('#f30e5c', '#f6f3a7', '#f6c523', '#228c7b', ['Red', 'Yellow', 'Green', 'Spring']),
+ '125519': ('#b6e1e0', '#9cd3d3', '#e8630a', '#2b4353', ['Blue', 'Orange']),
+ '125408': ('#363434', '#5c5757', '#62929a', '#efecec', ['Black', 'Grey', 'Turquoise', 'Winter']),
+ '125661': ('#e9e2d0', '#ea9085', '#6e5773', '#4f323b', ['Orange', 'Purple', 'Vintage', 'Wedding']),
+ '125679': ('#a3a7e4', '#bae2be', '#f0f1b3', '#c5e5e3', ['Purple', 'Green', 'Yellow', 'Blue', 'Summer']),
+ '126188': ('#ff5959', '#ffad5a', '#4f9da6', '#1a0841', ['Red', 'Orange', 'Turquoise', 'Retro']),
+ '125424': ('#89f8ce', '#f5fac7', '#dec8ed', '#cc99f9', ['Green', 'Yellow', 'Purple', 'Bright', 'Neon']),
+ '125434': ('#7b3c3c', '#db5f29', '#f0f0e4', '#68bde1', ['Brown', 'Orange', 'Blue', 'Retro']),
+ '125272': ('#e0ffcd', '#fdffcd', '#ffebbb', '#ffcab0', ['Green', 'Yellow', 'Orange', 'Pastel', 'Bright', 'Summer']),
+ '125503': ('#182952', '#2b3595', '#7045af', '#e14594', ['Blue', 'Purple', 'Dark']),
+ '124846': ('#f7f7f7', '#393e46', '#5c636e', '#f8b500', ['Grey', 'Yellow', 'White']),
+ '125267': ('#ffd96a', '#f34949', '#ff9090', '#ffb6b9', ['Yellow', 'Red', 'Pink', 'Warm', 'Summer']),
+ '125004': ('#155e63', '#76b39d', '#f9f8eb', '#eae7e7', ['Turquoise', 'Green', 'Grey']),
+ '125241': ('#ff9900', '#ca431d', '#8b104e', '#520556', ['Orange', 'Purple', 'Warm', 'Sunset']),
+ '125016': ('#f9499e', '#fff0db', '#bbbbbb', '#5e5e5e', ['Pink', 'Yellow', 'Grey', 'Wedding']),
+ '125270': ('#f7aa00', '#235784', '#40a8c4', '#bcdbdf', ['Orange', 'Blue', 'Vintage']),
+ '124844': ('#f7f7f7', '#3b0944', '#5f1854', '#1abb9c', ['Grey', 'Purple', 'Turquoise', 'Wedding', 'Retro', 'White']),
+ '124795': ('#f5f4e8', '#c50d66', '#f07810', '#eec60a', ['Grey', 'Red', 'Orange', 'Yellow']),
+ '124945': ('#fef9d9', '#ce7d00', '#935900', '#00541a', ['Yellow', 'Brown', 'Green', 'Vintage', 'Skin']),
+ '125279': ('#fad3cf', '#a696c8', '#2470a0', '#060608', ['Pink', 'Purple', 'Blue', 'Black', 'Wedding']),
+ '124759': ('#f2f2f2', '#ebd5d5', '#ea8a8a', '#685454', ['Grey', 'Pink', 'Brown', 'Pastel', 'White', 'Skin']),
+ '125017': ('#ff6473', '#757882', '#5cc1b3', '#6ef7c8', ['Red', 'Grey', 'Turquoise']),
+ '124691': ('#fff6da', '#84f2d6', '#fc6b3f', '#262525', ['Yellow', 'Turquoise', 'Orange', 'Black', 'Retro', 'Neon']),
+ '124981': ('#87e5da', '#92a4c0', '#f4adad', '#e58cdb', ['Turquoise', 'Pink', 'Purple', 'Vintage']),
+ '124653': ('#ffffe3', '#87e0ff', '#53c7f0', '#1d97c1', ['Yellow', 'Blue', 'Summer']),
+ '124611': ('#13334c', '#005792', '#f6f6e9', '#fd5f00', ['Blue', 'Orange']),
+ '124591': ('#e01171', '#ab0e86', '#59057b', '#0f0766', ['Red', 'Purple']),
+ '124558': ('#d5eeff', '#f7ca44', '#a2792f', '#5c3c10', ['Blue', 'Yellow', 'Brown']),
+ '124494': ('#de5b7b', '#eccfd1', '#f0e3c4', '#98ded3', ['Red', 'Pink', 'Yellow', 'Turquoise']),
+ '124492': ('#1b3764', '#4ab8b8', '#fafccb', '#efa35c', ['Blue', 'Turquoise', 'Yellow', 'Orange']),
+ '124440': ('#0e0220', '#e40475', '#48e0e4', '#d7fbf6', ['Black', 'Pink', 'Blue', 'Retro', 'Wedding']),
+ '124219': ('#2e99b0', '#fcd77f', '#ff2e4c', '#1e1548', ['Blue', 'Yellow', 'Red']),
+ '124355': ('#7a4579', '#d56073', '#ec9e69', '#ffff8f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset']),
+ '124155': ('#dd0a35', '#e4d1d3', '#1687a7', '#014955', ['Red', 'Blue']),
+ '124065': ('#d0efb5', '#eb7878', '#2f3e75', '#f3e595', ['Green', 'Red', 'Blue', 'Yellow', 'Vintage']),
+ '124180': ('#0e3150', '#6dc9c8', '#ffc0c2', '#f7e9e3', ['Blue', 'Turquoise', 'Pink']),
+ '123915': ('#fff6f6', '#ffe5ab', '#a1c45a', '#ffcdb5', ['Pink', 'Yellow', 'Green', 'White']),
+ '123973': ('#233142', '#455d7a', '#f95959', '#facf5a', ['Black', 'Blue', 'Red', 'Yellow', 'Halloween']),
+ '123883': ('#d1478c', '#ff7a5c', '#f7f9ff', '#53d397', ['Purple', 'Orange', 'Grey', 'Green']),
+ '123619': ('#ff9393', '#ff6767', '#ff3434', '#0c317a', ['Pink', 'Red', 'Blue']),
+ '123723': ('#edf0c7', '#4e9525', '#2e5a1c', '#ff5c00', ['Green', 'Orange', 'Christmas']),
+ '123522': ('#ffd3ad', '#ffa96a', '#005585', '#15005d', ['Orange', 'Blue']),
+ '123266': ('#35d0ba', '#f8c43a', '#c93d1b', '#04322e', ['Turquoise', 'Yellow', 'Orange', 'Retro']),
+ '123079': ('#feb062', '#575151', '#3f3b3b', '#e7b3b3', ['Orange', 'Grey', 'Pink', 'Vintage']),
+ '123388': ('#efff9d', '#2aa9d2', '#1874c3', '#2931b3', ['Yellow', 'Blue']),
+ '122811': ('#232931', '#f73859', '#f1d18a', '#ededed', ['Black', 'Red', 'Yellow', 'Grey']),
+ '123063': ('#005874', '#1c819e', '#e6e6d4', '#ffbe00', ['Blue', 'Yellow', 'Retro']),
+ '122132': ('#fbd685', '#63aebb', '#7a5d7e', '#312b30', ['Yellow', 'Turquoise', 'Purple', 'Wedding']),
+ '122076': ('#7c203a', '#f85959', '#ff9f68', '#feff89', ['Red', 'Orange', 'Yellow', 'Warm', 'Sunset', 'Neon']),
+ '122308': ('#f5f5c6', '#7da87b', '#326765', '#27253d', ['Yellow', 'Green', 'Black']),
+ '124272': ('#99e1e5', '#f3e8cb', '#f2c6b4', '#fbafaf', ['Blue', 'Yellow', 'Orange', 'Pink', 'Pastel', 'Summer']),
+ '122131': ('#f5b17b', '#4e709d', '#89a4c7', '#cdd5e0', ['Orange', 'Blue', 'Grey']),
+ '121992': ('#db3b61', '#ef3f61', '#3a3a59', '#555574', ['Red', 'Grey']),
+ '121977': ('#f5eee6', '#f3d7ca', '#e6a4b4', '#c86b85', ['Orange', 'Pink', 'Pastel', 'Skin']),
+ '121928': ('#2d095c', '#20366b', '#dd7777', '#eae3e3', ['Purple', 'Blue', 'Red', 'Grey']),
+ '121927': ('#aa530e', '#df8931', '#f5c16c', '#f3eded', ['Brown', 'Orange', 'Grey', 'Autumn', 'Gold', 'Skin']),
+ '121899': ('#860f44', '#bb3939', '#ea5f2d', '#eec89f', ['Red', 'Orange', 'Warm', 'Halloween']),
+ '121900': ('#17bebb', '#2e282a', '#cd5334', '#edb88b', ['Turquoise', 'Black', 'Orange']),
+ '121795': ('#ffeaa5', '#fe5f55', '#c7efcf', '#eef5db', ['Yellow', 'Red', 'Green', 'Summer', 'Spring']),
+ '121870': ('#35477d', '#6c5b7b', '#c06c84', '#f67280', ['Blue', 'Red']),
+ '123653': ('#eda1c1', '#fab2ac', '#bee4d2', '#d7f8f7', ['Pink', 'Orange', 'Green', 'Blue', 'Pastel', 'Spring']),
+ '122050': ('#1a2c5b', '#3e4e88', '#7971ea', '#b8dff0', ['Blue', 'Purple', 'Winter', 'Cold']),
+ '123528': ('#fffdb7', '#aef4a4', '#79b8d1', '#e36488', ['Yellow', 'Green', 'Blue', 'Pink']),
+ '121829': ('#2b007b', '#2f89fc', '#e7e6fc', '#dd7c1b', ['Blue', 'Purple', 'Orange', 'Wedding']),
+ '124879': ('#eaa81b', '#c95501', '#7d0000', '#012c0b', ['Orange', 'Warm', 'Autumn', 'Gold', 'Skin']),
+ '121517': ('#2d4059', '#ffb400', '#f6f6f6', '#ea5455', ['Orange', 'Grey', 'Red', 'Retro']),
+ '121859': ('#f9fa9b', '#ff7777', '#ceecf0', '#f0f3f3', ['Yellow', 'Red', 'Blue', 'Grey', 'Spring', 'Bright']),
+ '122310': ('#5e8b6f', '#436e4f', '#fa8f4d', '#f87829', ['Green', 'Orange']),
+ '121496': ('#fee9d7', '#f9bf8f', '#e2434b', '#34222e', ['Orange', 'Red', 'Warm', 'Autumn', 'Halloween', 'Skin']),
+ '122094': ('#535238', '#4bbb8b', '#6ddabe', '#c9ffc7', ['Brown', 'Green', 'Turquoise']),
+ '121460': ('#424153', '#fdadc7', '#ea4c88', '#993399', ['Pink', 'Purple']),
+ '121096': ('#1b3c59', '#456173', '#a6ed8e', '#f2f2f0', ['Blue', 'Green', 'Grey']),
+ '121558': ('#ffffc1', '#ffd2a5', '#d38cad', '#8a79af', ['Yellow', 'Orange', 'Purple', 'Pastel', 'Sunset']),
+ '120781': ('#0d7e83', '#13293d', '#ffaf87', '#eef0f2', ['Turquoise', 'Orange', 'Grey', 'Retro']),
+ '120467': ('#fd5f00', '#00204a', '#005792', '#d9faff', ['Orange', 'Blue']),
+ '120199': ('#f76262', '#216583', '#65c0ba', '#cffdf8', ['Red', 'Blue', 'Turquoise']),
+ '120122': ('#ff7517', '#3e3939', '#2c2727', '#f6f4f4', ['Orange', 'Grey', 'Black']),
+ '120121': ('#f9f8ed', '#c4e3cb', '#6a9c78', '#fff1bc', ['Yellow', 'Green']),
+ '120066': ('#480032', '#df0054', '#ff8b6a', '#ffd2bb', ['Red', 'Orange', 'Halloween']),
+ '120172': ('#ffa258', '#fff7c2', '#a02a63', '#4b125c', ['Orange', 'Yellow', 'Purple', 'Autumn', 'Halloween']),
+ '119977': ('#003545', '#00454a', '#3c6562', '#ed6363', ['Navy', 'Dark', 'Turquoise', 'Red', 'Dark']),
+ '119891': ('#90aeff', '#cefc86', '#60efb8', '#f9f7f7', ['Blue', 'Green', 'Grey', 'Bright']),
+ '119477': ('#6900ff', '#9951ff', '#ffd700', '#faf7ff', ['Purple', 'Yellow', 'Wedding', 'Bright']),
+ '119402': ('#203541', '#374955', '#f62a66', '#ffd933', ['Black', 'Red', 'Yellow']),
+ '118963': ('#f4f9f4', '#c4e3cb', '#8aae92', '#616161', ['Grey', 'Green']),
+ '119315': ('#333366', '#ff5f5f', '#f9e75e', '#f0f0f0', ['Red', 'Yellow', 'Grey']),
+ '119560': ('#fbffa8', '#74dac6', '#20c1bd', '#33354a', ['Yellow', 'Turquoise', 'Black']),
+ '118964': ('#092a35', '#658525', '#cfee91', '#f8eeb4', ['Black', 'Green', 'Yellow']),
+ '119215': ('#92e6e6', '#fff9af', '#d65d7a', '#524c84', ['Blue', 'Yellow', 'Red']),
+ '119059': ('#bad7df', '#ffe2e2', '#f6f6f6', '#99ddcc', ['Blue', 'Pink', 'Grey', 'Green', 'Pastel', 'Wedding', 'Spring']),
+ '118962': ('#283149', '#404b69', '#00818a', '#dbedf3', ['Black', 'Turquoise', 'Dark', 'Winter']),
+ '120110': ('#fff9e0', '#f1c550', '#ff6600', '#ce2525', ['Yellow', 'Orange', 'Red', 'Warm', 'Autumn', 'Gold']),
+ '118872': ('#323643', '#606470', '#93deff', '#f7f7f7', ['Black', 'Grey', 'Blue', 'Cold', 'Winter']),
+ '118869': ('#5ba19b', '#fceaea', '#f5d9d9', '#fbead1', ['Turquoise', 'Pink', 'Yellow', 'Wedding', 'Pastel']),
+ '118850': ('#404b69', '#283149', '#f73859', '#f3ecc8', ['Blue', 'Red', 'Yellow']),
+ '118847': ('#eeeeee', '#ff7100', '#be3030', '#222222', ['Grey', 'Orange', 'Black', 'Autumn']),
+ '118762': ('#eaafaf', '#a2738c', '#645c84', '#427996', ['Pink', 'Purple', 'Pastel', 'Wedding', 'Pastel']),
+ '118629': ('#e9fadd', '#b8e4c9', '#3f5468', '#42291c', ['Green', 'Blue', 'Black']),
+ '118795': ('#a8e6cf', '#fdffab', '#ffd3b6', '#ffaaa5', ['Green', 'Yellow', 'Orange', 'Red', 'Pastel', 'Spring', 'Bright']),
+ '118927': ('#e7759a', '#ffa35f', '#ba78cd', '#755da3', ['Pink', 'Orange', 'Purple']),
+ '118594': ('#062743', '#113a5d', '#c4ffdd', '#f9f9f9', ['Blue', 'Green', 'Grey', 'Cold']),
+ '118766': ('#ef7b7b', '#fcf3ca', '#c4eada', '#919190', ['Red', 'Yellow', 'Grey']),
+ '118677': ('#feffdf', '#dde0ab', '#97cba9', '#668ba4', ['Yellow', 'Green', 'Turquoise', 'Blue', 'Wedding']),
+ '118591': ('#062743', '#113a5d', '#ff7a8a', '#f9f9f9', ['Blue', 'Pink', 'Grey']),
+ '118622': ('#fce8aa', '#97de95', '#08c299', '#571179', ['Yellow', 'Green', 'Purple', 'Spring']),
+ '118585': ('#083358', '#0f4471', '#fc3c3c', '#f6f6f6', ['Blue', 'Red', 'Grey', 'Winter']),
+ '118479': ('#ffd3ad', '#ffa96a', '#005585', '#15005d', ['Orange', 'Blue']),
+ '118376': ('#f2f2f0', '#ff5e3a', '#2c365d', '#272e4f', ['Grey', 'Orange', 'Blue', 'Halloween', 'White']),
+ '118368': ('#feeb97', '#4fb783', '#409d9b', '#034561', ['Yellow', 'Green', 'Turquoise', 'Blue']),
+ '118331': ('#f8b195', '#f67280', '#c06c84', '#355c7d', ['Orange', 'Red', 'Blue', 'Wedding', 'Autumn', 'Warm']),
+ '118279': ('#090089', '#0060ca', '#91ceff', '#fcdc74', ['Blue', 'Yellow', 'Cold']),
+ '118126': ('#294a66', '#0b3846', '#ffbbbb', '#fcd2c2', ['Blue', 'Pink', 'Wedding']),
+ '118028': ('#240041', '#900048', '#ff4057', '#ff8260', ['Purple', 'Red', 'Orange', 'Halloween']),
+ '117924': ('#eff0f4', '#74dbef', '#0074e4', '#264e86', ['Grey', 'Blue', 'Cold']),
+ '117701': ('#f8d5f0', '#58d5d3', '#41a4c3', '#3f4b83', ['Pink', 'Turquoise', 'Blue']),
+ '117699': ('#fff1bc', '#7dc383', '#6a9c78', '#446e5c', ['Yellow', 'Green']),
+ '117613': ('#002bdc', '#2f4bff', '#00a6e7', '#ffe37f', ['Blue', 'Yellow']),
+ '117601': ('#232931', '#393e46', '#4ecca3', '#eeeeee', ['Black', 'Grey', 'Turquoise', 'Dark']),
+ '117579': ('#f6ec66', '#fadc6d', '#f97272', '#f65454', ['Yellow', 'Red']),
+ '117514': ('#702283', '#962071', '#76b39d', '#fdb44b', ['Purple', 'Green', 'Yellow', 'Retro']),
+ '117565': ('#faffb8', '#c5f0a4', '#35b0ab', '#226b80', ['Yellow', 'Green', 'Turquoise', 'Bright']),
+ '117448': ('#f8b595', '#f67280', '#c06c84', '#6c5b7c', ['Orange', 'Red', 'Purple', 'Pastel', 'Halloween', 'Skin']),
+ '117192': ('#448ef6', '#75c2f6', '#65daf7', '#ffe981', ['Blue', 'Yellow', 'Bright']),
+ '116909': ('#e4eddb', '#307672', '#144d53', '#1a3c40', ['Green', 'Turquoise', 'Winter']),
+ '116708': ('#ff4d4d', '#ff8364', '#fdb87d', '#ffe8d5', ['Red', 'Orange', 'Warm']),
+ '117534': ('#fafaf6', '#00fff0', '#00d1ff', '#3d6cb9', ['Grey', 'Turquoise', 'Blue', 'Bright', 'Cold', 'White', 'Neon']),
+ '116691': ('#1c1124', '#684656', '#de774e', '#b7e1b5', ['Black', 'Orange', 'Green', 'Vintage', 'Halloween', 'Autumn']),
+ '116690': ('#1c1124', '#693e52', '#74b49b', '#a7d7c5', ['Black', 'Green', 'Vintage', 'Wedding']),
+ '116678': ('#8ea6b4', '#e7eff3', '#ff8f56', '#984a59', ['Grey', 'Orange', 'Autumn', 'Winter']),
+ '116554': ('#45eba5', '#21aba5', '#1d566e', '#163a5f', ['Green', 'Turquoise', 'Blue']),
+ '116599': ('#011f3f', '#0960bd', '#429ffd', '#fef2bf', ['Blue', 'Yellow', 'Cold']),
+ '116542': ('#ff6107', '#e9290f', '#c40018', '#292725', ['Orange', 'Red', 'Black', 'Warm']),
+ '118369': ('#f7f7f7', '#ff570c', '#606470', '#323643', ['Grey', 'Orange', 'White']),
+ '116523': ('#84b9ef', '#fbe4c9', '#ff5d5d', '#952e4b', ['Blue', 'Red', 'Spring']),
+ '116408': ('#78fee0', '#4bc2c5', '#3b9a9c', '#fef4a9', ['Turquoise', 'Yellow', 'Neon']),
+ '116289': ('#ecf0f1', '#33cccc', '#2980b9', '#2c3e50', ['Grey', 'Turquoise', 'Blue', 'Cold']),
+ '114376': ('#edfead', '#d9f489', '#bdcf88', '#d95858', ['Yellow', 'Green', 'Red', 'Christmas']),
+ '114273': ('#ff6138', '#ffff9d', '#beeb9f', '#79bd8f', ['Red', 'Yellow', 'Green', 'Summer', 'Spring', 'Bright']),
+ '114244': ('#394a51', '#7fa99b', '#fbf2d5', '#fdc57b', ['Turquoise', 'Orange']),
+ '114174': ('#283149', '#404b69', '#f73859', '#dbedf3', ['Red', 'Blue']),
+ '114093': ('#fbfae1', '#cef0b9', '#64a36f', '#ffe121', ['Yellow', 'Green', 'Bright']),
+ '112989': ('#f56a47', '#b32c50', '#681a1e', '#0a0944', ['Orange', 'Red', 'Brown', 'Warm', 'Halloween']),
+ '112572': ('#f8f9fc', '#c00000', '#de3c3c', '#f7b32d', ['Grey', 'Red', 'Orange', 'Warm', 'White']),
+ '112238': ('#ffe6eb', '#ffcdcd', '#6a65d8', '#1d2786', ['Pink', 'Purple', 'Wedding', 'Skin']),
+ '112038': ('#28544b', '#acbd86', '#ffd6a0', '#ffa06f', ['Green', 'Orange', 'Autumn']),
+ '112036': ('#6c567b', '#c06c84', '#f67280', '#f8b195', ['Purple', 'Red', 'Warm']),
+ '111625': ('#fffb97', '#97ffcf', '#2fe1d6', '#38c6bd', ['Yellow', 'Turquoise', 'Summer', 'Spring', 'Bright', 'Neon']),
+ '111393': ('#e7f5f2', '#f9c7cf', '#12776f', '#0f4137', ['Pink', 'Turquoise', 'Wedding']),
+ '111218': ('#375a7f', '#4d7cae', '#6a99cb', '#fcfa70', ['Blue', 'Yellow', 'Winter', 'Cold']),
+ '111185': ('#360982', '#b72a67', '#ff9797', '#fde8cb', ['Blue', 'Purple', 'Pink', 'Sunset', 'Wedding']),
+ '111086': ('#323232', '#8559a5', '#6db193', '#f4e5c2', ['Black', 'Purple', 'Green', 'Retro']),
+ '111027': ('#e95280', '#23b1a5', '#ffdd7e', '#f3f3f3', ['Pink', 'Turquoise', 'Yellow', 'Grey', 'Summer']),
+ '110992': ('#22559c', '#f27370', '#fa9856', '#ede862', ['Blue', 'Red', 'Orange', 'Yellow', 'Sunset']),
+ '110977': ('#abedd8', '#46cdcf', '#0081c6', '#48466d', ['Blue', 'Turquoise']),
+ '110878': ('#fae3e3', '#b7b7b7', '#137083', '#3d0240', ['Pink', 'Grey', 'Turquoise', 'Purple', 'Wedding', 'Vintage', 'Skin']),
+ '110868': ('#11cbd7', '#c6f1e7', '#f0fff3', '#fa4659', ['Turquoise', 'Red', 'Bright', 'Cold']),
+ '115428': ('#fda403', '#e8751a', '#c51350', '#8a1253', ['Orange', 'Purple', 'Halloween', 'Autumn', 'Warm', 'Gold']),
+ '110859': ('#a7efe9', '#7fdfd4', '#fbe1b6', '#fbac91', ['Turquoise', 'Orange', 'Summer']),
+ '110982': ('#032a33', '#255965', '#4c6f7b', '#f1d18a', ['Black', 'Turquoise', 'Yellow']),
+ '110660': ('#faa9e0', '#f8b3eb', '#eaa3fc', '#fce4b0', ['Pink', 'Purple', 'Yellow', 'Pastel', 'Spring']),
+ '110659': ('#fbf0f0', '#dfd3d3', '#b8b0b0', '#7c7575', ['Pink', 'Grey', 'Skin']),
+ '110922': ('#ff6d24', '#4e413b', '#857671', '#e2ded3', ['Orange', 'Brown', 'Grey', 'Autumn', 'Skin']),
+ '110354': ('#f4eec0', '#aed09e', '#61b292', '#7e6752', ['Yellow', 'Green', 'Turquoise', 'Brown']),
+ '110223': ('#c7f3ff', '#fdc7ff', '#ffdcf5', '#f2f4c3', ['Blue', 'Pink', 'Yellow', 'Bright', 'Spring']),
+ '109426': ('#f6efb4', '#35c2bd', '#2796cb', '#3379e4', ['Yellow', 'Turquoise', 'Blue']),
+ '109414': ('#00204a', '#005792', '#00bbf0', '#fdb44b', ['Blue', 'Orange', 'Cold']),
+ '109517': ('#f12b6b', '#ff467e', '#fd94b4', '#f6c7c7', ['Red', 'Pink', 'Spring']),
+ '109389': ('#f6ffcd', '#bcffa8', '#6ba083', '#4f323b', ['Yellow', 'Green']),
+ '108974': ('#00204a', '#005792', '#00bbf0', '#d9faff', ['Blue', 'Winter', 'Cold']),
+ '108807': ('#fcfcfc', '#83ffe6', '#ff5f5f', '#2c2c2c', ['Grey', 'Turquoise', 'Red', 'Black', 'Neon']),
+ '108676': ('#ececeb', '#f9a828', '#07617d', '#2e383f', ['Grey', 'Orange', 'Blue']),
+ '108574': ('#ff6464', '#ff8264', '#ffaa64', '#fff5a5', ['Red', 'Orange', 'Yellow', 'Summer', 'Warm']),
+ '108559': ('#f9f8eb', '#76b39d', '#155263', '#f0b917', ['Yellow', 'Turquoise']),
+ '108539': ('#fffcef', '#d2ebcd', '#ff7f5b', '#393939', ['Yellow', 'Green', 'Orange', 'Vintage']),
+ '109078': ('#6b0848', '#a40a3c', '#ec610a', '#ffc300', ['Purple', 'Red', 'Orange', 'Yellow', 'Warm', 'Halloween']),
+ '108347': ('#0278ae', '#51adcf', '#a5ecd7', '#e8ffc1', ['Blue', 'Turquoise', 'Yellow', 'Winter', 'Cold']),
+ '108305': ('#70d4b4', '#ffebb7', '#bbbbbb', '#aaaaaa', ['Turquoise', 'Yellow', 'Grey']),
+ '108180': ('#ec7700', '#d65f00', '#c04d00', '#efefef', ['Orange', 'Grey', 'Gold', 'Skin']),
+ '108152': ('#3a0088', '#930077', '#e61c5d', '#ffbd39', ['Blue', 'Purple', 'Red', 'Yellow']),
+ '108141': ('#194769', '#f6f6e9', '#d7eef2', '#f2855e', ['Blue', 'Orange']),
+ '108068': ('#0e9577', '#04dead', '#f1efb9', '#fbfae1', ['Green', 'Yellow', 'Spring']),
+ '107892': ('#970747', '#fef4e8', '#1989ac', '#283e56', ['Red', 'Blue', 'Retro']),
+ '108560': ('#fdfdeb', '#f9ce00', '#00818a', '#09194f', ['Green', 'Blue']),
+ '107677': ('#0f3057', '#00587a', '#008891', '#e7e7de', ['Blue', 'Turquoise', 'Grey', 'Cold', 'Winter']),
+ '107673': ('#9f609c', '#ea8f79', '#e4d183', '#f8f1e5', ['Purple', 'Orange', 'Yellow', 'Pastel', 'Wedding']),
+ '107618': ('#283149', '#404b69', '#da0463', '#dbedf3', ['Grey', 'Red']),
+ '107483': ('#f4e8c1', '#a0c1b8', '#726a95', '#351f39', ['Yellow', 'Grey', 'Purple', 'Black', 'Retro']),
+ '107482': ('#ffb6b9', '#fae3d9', '#bbded6', '#61c0bf', ['Red', 'Turquoise', 'Pastel', 'Wedding']),
+ '107279': ('#ecfafb', '#81cbc8', '#4aa6b5', '#d6c481', ['Turquoise', 'Wedding']),
+ '107218': ('#5628b4', '#d80e70', '#e7455f', '#f7b236', ['Purple', 'Red', 'Yellow', 'Neon']),
+ '107208': ('#f4f4f4', '#65eeb7', '#ff5722', '#474744', ['Grey', 'Turquoise', 'Orange', 'Neon']),
+ '107172': ('#232855', '#215b63', '#5fcc9c', '#aaffc7', ['Blue', 'Turquoise', 'Green']),
+ '107141': ('#4a772f', '#ffdd00', '#fa9e05', '#a7095c', ['Green', 'Yellow', 'Orange', 'Purple']),
+ '107139': ('#ffa3ac', '#00043c', '#005d6c', '#00c9b1', ['Pink', 'Blue', 'Turquoise', 'Wedding']),
+ '107050': ('#265961', '#227066', '#76a665', '#ffdd5c', ['Green', 'Yellow']),
+ '106985': ('#17139c', '#dd3e3e', '#ffe5e1', '#f2f2f2', ['Blue', 'Red', 'Grey', 'Retro']),
+ '106972': ('#ff7777', '#fff195', '#fcffbf', '#f5e9ff', ['Red', 'Yellow', 'Pink', 'Bright', 'Summer', 'Spring']),
+ '106827': ('#ebebeb', '#fec100', '#528078', '#3e615b', ['Grey', 'Yellow', 'Turquoise']),
+ '106929': ('#333644', '#84577c', '#c65f63', '#f6e1b8', ['Black', 'Purple', 'Red', 'Yellow', 'Vintage']),
+ '106789': ('#fdfdfd', '#e1eb71', '#ecab69', '#e36161', ['Grey', 'Yellow', 'Orange', 'Red', 'Summer', 'White']),
+ '106748': ('#f2d1a8', '#ebebeb', '#669b7c', '#557669', ['Orange', 'Grey', 'Green']),
+ '106736': ('#8e1d41', '#dbbf0d', '#ffcd19', '#ffefb4', ['Purple', 'Yellow']),
+ '106735': ('#111f4d', '#f2f4f7', '#e43a19', '#020205', ['Black', 'Grey', 'Orange', 'Blue', 'Retro', 'White']),
+ '106734': ('#fcf9f4', '#ffc97c', '#ea7659', '#c1c1c1', ['Orange', 'Grey', 'Autumn', 'White', 'Skin']),
+ '106733': ('#5f4444', '#af3264', '#ff63b5', '#ffbbbb', ['Brown', 'Purple', 'Pink']),
+ '106719': ('#bc5148', '#fef8e6', '#7bcecc', '#3090a1', ['Red', 'Yellow', 'Blue']),
+ '106550': ('#e7e6e1', '#f7f6e7', '#c1c0b9', '#537791', ['Grey', 'Blue', 'Retro']),
+ '106475': ('#faf4d0', '#c14545', '#ea4c4c', '#703b3b', ['Yellow', 'Red', 'Brown', 'Warm']),
+ '106516': ('#ecfeff', '#00b7c2', '#128494', '#4ef037', ['Blue', 'Turquoise', 'Green', 'Bright', 'Neon']),
+ '106499': ('#d0ef84', '#f4d143', '#fda831', '#de561c', ['Green', 'Yellow', 'Orange', 'Autumn', 'Gold']),
+ '106460': ('#fffbcc', '#fd2e2e', '#cf1b1b', '#900d0d', ['Yellow', 'Red', 'Warm']),
+ '106353': ('#248888', '#e6e6e6', '#e7475e', '#f0d879', ['Turquoise', 'Grey', 'Red', 'Yellow']),
+ '106339': ('#e1ffcf', '#cfcbf1', '#bab5f6', '#4d3664', ['Green', 'Purple', 'Retro', 'Wedding', 'Bright']),
+ '106302': ('#08085e', '#a2ef44', '#fff07a', '#e8fcf6', ['Blue', 'Green', 'Yellow']),
+ '106083': ('#f6c667', '#b30753', '#280f34', '#bff4ed', ['Yellow', 'Purple', 'Turquoise', 'Retro']),
+ '105887': ('#ffdd93', '#58dada', '#1ca2bb', '#005e7c', ['Orange', 'Blue', 'Summer']),
+ '105848': ('#fffde1', '#fef778', '#fba746', '#7f7f7f', ['Yellow', 'Orange', 'Grey', 'Gold']),
+ '105677': ('#393232', '#4d4545', '#8d6262', '#ed8d8d', ['Grey', 'Pink', 'Dark', 'Skin']),
+ '105661': ('#a9eca2', '#f5ffcb', '#ffe3b0', '#f5c8bd', ['Green', 'Yellow', 'Orange', 'Pastel', 'Summer', 'Bright']),
+ '105495': ('#36626a', '#588d9c', '#73b1c1', '#f1d18a', ['Blue', 'Yellow', 'Winter', 'Wedding']),
+ '105407': ('#211572', '#24bddf', '#f4f4f4', '#fffdbb', ['Blue', 'Grey', 'Yellow', 'Wedding']),
+ '105558': ('#f7f2c1', '#f0ca6d', '#48ba95', '#403321', ['Yellow', 'Turquoise']),
+ '105358': ('#282d4f', '#23103a', '#a0204c', '#ff6c00', ['Blue', 'Dark', 'Purple', 'Orange', 'Halloween']),
+ '105443': ('#ffc7c7', '#ffe2e2', '#f6f6f6', '#8785a2', ['Pink', 'Purple', 'Retro', 'Wedding', 'Skin']),
+ '105240': ('#f2e8c6', '#f5841a', '#bb0029', '#03002c', ['Yellow', 'Orange', 'Red', 'Black', 'Halloween', 'Autumn']),
+ '105342': ('#096c47', '#0b8457', '#eac100', '#f8f1d0', ['Green', 'Yellow']),
+ '105206': ('#211572', '#48c0d3', '#dedede', '#ffe578', ['Blue', 'Grey', 'Yellow', 'Retro', 'Wedding']),
+ '105115': ('#3e333f', '#fc4442', '#f0e19e', '#f2f2f2', ['Black', 'Red', 'Yellow', 'Grey']),
+ '104108': ('#c6de41', '#2d6e7e', '#153b44', '#071c21', ['Green', 'Turquoise']),
+ '104487': ('#f6490d', '#000249', '#1dced8', '#faf9f0', ['Orange', 'Blue', 'Grey']),
+ '103966': ('#071a52', '#086972', '#17b978', '#a7ff83', ['Blue', 'Turquoise', 'Green', 'Neon']),
+ '103371': ('#363636', '#dc2f2f', '#ff894c', '#f8f8f8', ['Grey', 'Red', 'Orange']),
+ '103635': ('#fcf9f9', '#f1f864', '#bceb3c', '#7cbd1e', ['Grey', 'Yellow', 'Green', 'Summer', 'Bright', 'Spring', 'White', 'Neon']),
+ '102684': ('#000000', '#86003c', '#e41f7b', '#ff8ba0', ['Black', 'Pink', 'Dark']),
+ '103350': ('#e0fcff', '#bde4f4', '#404969', '#ff7f50', ['Blue', 'Orange', 'Winter']),
+ '102454': ('#a1d9ff', '#ca82f8', '#ed93cb', '#f2bbbb', ['Blue', 'Purple', 'Pink', 'Wedding']),
+ '101919': ('#734488', '#492645', '#9febeb', '#fafcdb', ['Purple', 'Blue', 'Yellow', 'Wedding', 'Retro', 'Wedding']),
+ '101494': ('#ff895d', '#d5eeff', '#78bbe6', '#1b435d', ['Orange', 'Blue']),
+ '100840': ('#302939', '#50595c', '#e99b9b', '#ffd8d8', ['Black', 'Grey', 'Pink']),
+ '101875': ('#1fffff', '#fffde1', '#ff9d76', '#ff4273', ['Turquoise', 'Yellow', 'Orange', 'Red', 'Summer', 'Spring', 'Bright', 'Neon']),
+ '101433': ('#212125', '#239d60', '#a3de83', '#f7f39a', ['Black', 'Green', 'Yellow']),
+ '101294': ('#fafafa', '#ffe9e3', '#c4c1e0', '#7c73e6', ['Grey', 'Pink', 'Purple', 'Vintage', 'Wedding', 'White']),
+ '100741': ('#624464', '#d02e77', '#fed6be', '#fffee6', ['Purple', 'Wedding']),
+ '101436': ('#fbfbfb', '#b9e1dc', '#f38181', '#756c83', ['Grey', 'Turquoise', 'Red', 'Vintage', 'Retro', 'White']),
+ '101251': ('#3f52e3', '#f6f6f6', '#efe891', '#f12d2d', ['Blue', 'Grey', 'Yellow', 'Red', 'Summer']),
+ '98686': ('#323232', '#295f4e', '#6db193', '#f4e5c2', ['Black', 'Green', 'Yellow']),
+ '101477': ('#fbfbfb', '#fff1c1', '#78b7bb', '#808b97', ['White', 'Yellow', 'Turquoise', 'Grey', 'Pastel']),
+ '100883': ('#dffcb5', '#b7f5de', '#add1fc', '#9870fc', ['Green', 'Turquoise', 'Purple']),
+ '99599': ('#161d6e', '#1160aa', '#9bb4da', '#e9d2b3', ['Blue']),
+ '98521': ('#33425b', '#87dfd6', '#38817a', '#f9f8eb', ['Turquoise', 'Wedding']),
+ '101730': ('#feff89', '#ff9f68', '#f85959', '#ac005d', ['Yellow', 'Orange', 'Red', 'Purple', 'Sunset']),
+ '100864': ('#0881a3', '#fffdfb', '#fde9df', '#ffd6a4', ['Blue', 'Pink', 'Yellow', 'White']),
+ '100885': ('#f67280', '#c06c84', '#6c5b7b', '#355c7d', ['Red', 'Purple', 'Sunset']),
+ '100984': ('#fff5db', '#e1addc', '#c238b5', '#810075', ['Yellow', 'Pink', 'Purple', 'Wedding']),
+ '98202': ('#1b3c68', '#0074e4', '#00b8c0', '#e9ffb2', ['Blue', 'Turquoise']),
+ '98138': ('#393e46', '#5c636e', '#f96d00', '#f2f2f2', ['Grey', 'Orange']),
+ '98780': ('#d1f386', '#eda045', '#df654a', '#cc376d', ['Green', 'Orange', 'Purple', 'Autumn']),
+ '98625': ('#34374c', '#2c2e3e', '#ee2b47', '#f6f6f6', ['Black', 'Red', 'Grey']),
+ '98666': ('#f5e1da', '#f1f1f1', '#40a798', '#476269', ['Grey', 'Turquoise', 'Wedding', 'Skin']),
+ '97923': ('#37474f', '#607d8b', '#90a4ae', '#f7b633', ['Blue', 'Grey', 'Orange']),
+ '100564': ('#ffbdd4', '#ffe5b9', '#ffc77f', '#ff5c5c', ['Pink', 'Orange', 'Red']),
+ '97912': ('#f75940', '#334252', '#364857', '#3dc7be', ['Orange', 'Turquoise', 'Retro']),
+ '97771': ('#dddddd', '#113c4a', '#265a5c', '#3f7b70', ['Grey', 'Turquoise', 'Green', 'Cold']),
+ '97718': ('#ececec', '#3e3e3e', '#ee046c', '#fcac0c', ['Grey', 'Black', 'Pink', 'Orange']),
+ '97657': ('#f54d42', '#ff8356', '#ffcd00', '#f5f5f5', ['Orange', 'Yellow', 'Grey']),
+ '97656': ('#b0dedb', '#e3f3f7', '#fc6e5e', '#583131', ['Turquoise', 'Red', 'Brown']),
+ '97590': ('#fbf7f7', '#f1e9e3', '#ee712b', '#dc4712', ['Pink', 'Grey', 'Orange', 'Autumn', 'Gold', 'White']),
+ '97426': ('#f3ecc8', '#78c2c3', '#3f6699', '#0d1b4c', ['Yellow', 'Turquoise', 'Blue', 'Winter']),
+ '97212': ('#cbf078', '#f8f398', '#f1b963', '#e46161', ['Green', 'Yellow', 'Orange', 'Red', 'Spring']),
+ '97209': ('#f9f9f9', '#ded5c4', '#ef7e56', '#305973', ['Grey', 'Orange', 'Blue', 'White']),
+ '97068': ('#8e3343', '#ec9454', '#f1f08a', '#c6cd78', ['Red', 'Orange', 'Yellow', 'Green', 'Autumn', 'Halloween']),
+ '96781': ('#fcfcfc', '#0fc9e7', '#3186b2', '#4756ca', ['Grey', 'Blue', 'White']),
+ '96726': ('#e9007f', '#7cdfff', '#d5fffb', '#fcffc8', ['Purple', 'Blue', 'Yellow', 'Bright', 'Neon']),
+ '96297': ('#fafcd6', '#259f6c', '#1e6b7f', '#140303', ['Yellow', 'Green', 'Blue', 'Black']),
+ '97007': ('#3e4377', '#fd367e', '#f1f2f3', '#ff9900', ['Pink', 'Grey', 'Orange', 'Wedding']),
+ '96253': ('#f9fbfc', '#a0dbdb', '#56a7a7', '#fcea90', ['Grey', 'Turquoise', 'Yellow', 'Spring', 'White']),
+ '95689': ('#003459', '#028090', '#02c39a', '#fce38a', ['Turquoise', 'Green', 'Yellow']),
+ '95996': ('#d5f7ff', '#494b67', '#ff006c', '#ecebff', ['Blue', 'Red', 'Grey']),
+ '95353': ('#00649f', '#01aac1', '#00dbe7', '#97ecc5', ['Blue', 'Turquoise', 'Cold']),
+ '95351': ('#453246', '#f86254', '#b04d5d', '#ffd05b', ['Red', 'Yellow']),
+ '95568': ('#f0f0f0', '#43dde6', '#364f6b', '#fc5185', ['Grey', 'Blue', 'Pink']),
+ '95181': ('#085f63', '#49beb7', '#fccf4d', '#ef255f', ['Turquoise', 'Yellow', 'Red', 'Spring']),
+ '95097': ('#4a2c2c', '#d3504a', '#ffdc76', '#fefea4', ['Brown', 'Red', 'Yellow']),
+ '94589': ('#a13939', '#e75151', '#fcc88a', '#c2c57f', ['Red', 'Orange', 'Green', 'Christmas', 'Autumn']),
+ '94531': ('#f1f4f6', '#5ac8d8', '#597fca', '#2552ac', ['Blue', 'Turquoise']),
+ '94235': ('#f5fac8', '#aee8e6', '#8bcfcc', '#539092', ['Yellow', 'Turquoise', 'Blue', 'Turquoise']),
+ '94200': ('#9b5d73', '#b0757c', '#c38b8b', '#fff1c5', ['Brown', 'Yellow', 'Skin']),
+ '94114': ('#66bfbf', '#eaf6f6', '#fcfefe', '#f76b8a', ['Turquoise', 'Grey', 'Pink', 'White']),
+ '93578': ('#f8eeb4', '#cfee91', '#658525', '#092a35', ['Yellow', 'Green', 'Green', 'Black']),
+ '93536': ('#f5f5f5', '#01ecd5', '#4586ff', '#32424a', ['Grey', 'Turquoise', 'Blue', 'Black', 'Cold']),
+ '93497': ('#283e56', '#1989ac', '#e8f1f5', '#ffde25', ['Blue', 'Yellow']),
+ '93465': ('#f7f7f8', '#4eeaf6', '#c82586', '#291f71', ['Grey', 'Blue', 'Purple', 'Neon']),
+ '93362': ('#155263', '#ff6f3c', '#ff9a3c', '#ffc93c', ['Turquoise', 'Orange', 'Yellow']),
+ '93463': ('#f5eeee', '#ea21a2', '#af05aa', '#171313', ['Grey', 'Pink', 'Purple', 'Black']),
+ '93272': ('#f60c86', '#f9f6d8', '#a5bfdd', '#2e89ba', ['Pink', 'Yellow', 'Blue', 'Wedding', 'Spring']),
+ '93126': ('#657dc4', '#838ed9', '#ece8e5', '#f59292', ['Blue', 'Blue', 'Pink']),
+ '92811': ('#682666', '#cf0a2c', '#e73e51', '#ffce00', ['Purple', 'Red', 'Red', 'Yellow']),
+ '92806': ('#393939', '#849561', '#eed690', '#ecefd8', ['Grey', 'Brown', 'Yellow', 'Grey']),
+ '93125': ('#d4a5a5', '#ffecda', '#f9ffea', '#a6d0e4', ['Red', 'Orange', 'Yellow', 'Blue', 'Pastel', 'Vintage', 'Summer', 'Skin']),
+ '92530': ('#97124b', '#dc4444', '#f5a855', '#f4e557', ['Red', 'Orange', 'Yellow', 'Halloween']),
+ '92752': ('#143a52', '#6e828a', '#cde3eb', '#e3eff3', ['Grey', 'Wedding', 'Winter', 'Cold']),
+ '92339': ('#432160', '#ff7a5a', '#50e3c2', '#fcf4d9', ['Purple', 'Orange', 'Turquoise', 'Yellow']),
+ '92337': ('#faf8d7', '#acc6aa', '#71a0a5', '#77628c', ['Yellow', 'Green', 'Purple']),
+ '92306': ('#a1eafb', '#fdfdfd', '#ffcef3', '#cabbe9', ['Blue', 'Grey', 'Pink', 'Purple', 'Bright', 'Wedding', 'Spring']),
+ '92208': ('#fff4c9', '#c7e78b', '#81ae64', '#709053', ['Yellow', 'Green', 'Green', 'Green']),
+ '91572': ('#ffe037', '#1dcd9f', '#088c6f', '#23033c', ['Yellow', 'Turquoise']),
+ '90182': ('#ff395e', '#8fecc8', '#6f6f6f', '#4a4a4a', ['Red', 'Turquoise', 'Grey', 'Grey']),
+ '89959': ('#000249', '#0f4392', '#ff5151', '#ff8b8b', ['Blue', 'Red', 'Wedding', 'Halloween']),
+ '89958': ('#f6f6f6', '#d6e4f0', '#1e56a0', '#163172', ['Grey', 'Blue', 'Cold', 'White']),
+ '91891': ('#ff007b', '#ff5757', '#ff8585', '#ffebeb', ['Pink', 'Red', 'Orange', 'Spring']),
+ '92753': ('#f5f5f5', '#ececec', '#facc2e', '#27b1be', ['Grey', 'Yellow', 'Turquoise']),
+ '89012': ('#d5def5', '#8594e4', '#6643b5', '#430f58', ['Blue', 'Purple', 'Cold', 'Winter']),
+ '88466': ('#bff4ed', '#280f34', '#b30753', '#f6c667', ['Blue', 'Black', 'Red', 'Yellow']),
+ '88465': ('#1fad9f', '#cd3131', '#ab1212', '#f6c667', ['Turquoise', 'Red', 'Orange']),
+ '88422': ('#fc00a3', '#b30c7b', '#780662', '#e3f6f5', ['Pink', 'Purple', 'Purple']),
+ '88310': ('#461b93', '#6a3cbc', '#8253d7', '#f78f1e', ['Purple', 'Orange', 'Halloween']),
+ '88241': ('#ff008e', '#124e96', '#0d8abc', '#daeaf6', ['Pink', 'Blue', 'Blue']),
+ '87834': ('#ffdaa9', '#6fa3a9', '#5f72b2', '#60366f', ['Orange', 'Blue', 'Blue', 'Purple', 'Retro']),
+ '87607': ('#71397c', '#91519d', '#c582d5', '#ffdf5a', ['Purple', 'Yellow']),
+ '89856': ('#ffffc1', '#ffd2a5', '#ffa8b8', '#d988bc', ['Yellow', 'Orange', 'Pink', 'Purple', 'Bright', 'Warm']),
+ '88510': ('#626eef', '#09a8fa', '#41c5d3', '#fffa9d', ['Blue', 'Turquoise', 'Yellow', 'Bright']),
+ '87245': ('#581845', '#900c3f', '#c70039', '#ff5733', ['Red', 'Orange', 'Warm', 'Dark', 'Halloween']),
+ '100322': ('#4a3333', '#98d083', '#bcfcc9', '#f2feca', ['Brown', 'Green', 'Yellow']),
+ '87037': ('#e3d9ca', '#95a792', '#596c68', '#403f48', ['Grey', 'Green']),
+ '88143': ('#c84361', '#e78775', '#abcdcb', '#ebe59b', ['Red', 'Blue', 'Yellow', 'Summer']),
+ '88187': ('#6a0000', '#935656', '#c4f0c5', '#f1fff1', ['Brown', 'Green', 'Skin']),
+ '87687': ('#7d156d', '#b94e8a', '#d87ca1', '#ffd7f1', ['Purple', 'Pink', 'Wedding']),
+ '87026': ('#363333', '#272121', '#e16428', '#f6e9e9', ['Black', 'Orange', 'Pink', 'Dark', 'Halloween']),
+ '88300': ('#feffea', '#a3de83', '#2eb872', '#ff5d6e', ['Yellow', 'Green', 'Green', 'Red', 'Spring']),
+ '88012': ('#f5feff', '#bde4f4', '#404969', '#dc552c', ['Blue', 'Orange', 'Winter', 'White']),
+ '87640': ('#f03861', '#fef2f2', '#f5d97e', '#e8b844', ['Red', 'Pink', 'Yellow', 'Spring']),
+ '86615': ('#39065a', '#6a0572', '#9a0f98', '#ea0599', ['Purple', 'Pink', 'Dark']),
+ '86614': ('#626060', '#928b8b', '#dadbc0', '#e7e9de', ['Grey']),
+ '87244': ('#27296d', '#5e63b6', '#a393eb', '#f5c7f7', ['Blue', 'Blue', 'Purple', 'Purple', 'Cold']),
+ '86611': ('#ffbc2c', '#86b86b', '#4d4d4d', '#ececec', ['Yellow', 'Green', 'Grey', 'Grey']),
+ '86606': ('#f7f7f7', '#f5b553', '#854836', '#000000', ['Grey', 'Orange', 'Brown', 'Black', 'Autumn', 'White', 'Skin']),
+ '85473': ('#dff4f3', '#dde7f2', '#b9bbdf', '#878ecd', ['Blue', 'Purple', 'Winter', 'Cold']),
+ '85472': ('#dce8ba', '#f3d179', '#f09872', '#f46060', ['Yellow', 'Orange', 'Red', 'Pastel', 'Autumn']),
+ '85014': ('#f1e290', '#f677c1', '#9b3284', '#690074', ['Yellow', 'Pink', 'Purple']),
+ '84735': ('#f2f9f1', '#388e3c', '#8bc34a', '#ddeedf', ['Grey', 'Green']),
+ '84551': ('#6c5070', '#df6a6a', '#f6f6e3', '#c2dbc1', ['Purple', 'Red', 'Green', 'Vintage', 'Pastel']),
+ '86342': ('#0e2431', '#fc3a52', '#f9b248', '#e8d5b7', ['Black', 'Red', 'Orange', 'Brown', 'Warm', 'Halloween']),
+ '84458': ('#f8ed86', '#a5e9db', '#2ca4bf', '#415b90', ['Yellow', 'Turquoise', 'Blue']),
+ '84126': ('#a6e4e7', '#f9f9f9', '#ebcbae', '#8f8787', ['Turquoise', 'Grey', 'Orange', 'Brown']),
+ '83572': ('#e9e2d0', '#ea9085', '#d45d79', '#6e5773', ['Brown', 'Pink', 'Red', 'Purple', 'Autumn', 'Skin']),
+ '86343': ('#ffed8f', '#a7d46f', '#359768', '#3c3352', ['Yellow', 'Green']),
+ '82296': ('#c4aff0', '#fffeec', '#64d7d6', '#5782bb', ['Purple', 'Yellow', 'Turquoise', 'Blue', 'Wedding']),
+ '81897': ('#ffe495', '#ffc97b', '#44558f', '#e6f7f7', ['Yellow', 'Orange', 'Blue', 'Gold']),
+ '82054': ('#dd105e', '#46466e', '#8787a3', '#bdbdd7', ['Red', 'Grey']),
+ '81699': ('#feff9a', '#6fe8c8', '#85fede', '#b7abfb', ['Yellow', 'Turquoise', 'Purple', 'Bright']),
+ '81608': ('#ca498c', '#8b2f8a', '#b08fbb', '#f6d5d5', ['Purple', 'Purple', 'Purple', 'Pink']),
+ '81561': ('#ffe3b7', '#840404', '#cb0101', '#ffaf00', ['Orange', 'Red', 'Yellow', 'Warm']),
+ '80765': ('#ffdd83', '#e3f8ff', '#28cc9e', '#a6ed8e', ['Yellow', 'Green', 'Summer', 'Spring']),
+ '81674': ('#fcefee', '#fccde2', '#fc5c9c', '#c5e3f6', ['Pink', 'Pink', 'Pink', 'Blue', 'Retro', 'Wedding']),
+ '83571': ('#588c73', '#f2e394', '#f2ae72', '#d96459', ['Green', 'Yellow', 'Orange', 'Red', 'Christmas']),
+ '95352': ('#3b0944', '#5f1854', '#a12559', '#f1bbd5', ['Purple', 'Pink', 'Dark']),
+ '80660': ('#ffed78', '#feffea', '#addce4', '#586b8f', ['Yellow', 'Blue', 'Summer']),
+ '80619': ('#f2fcfc', '#bdf1f6', '#8fbaf3', '#0245a3', ['Turquoise', 'Blue', 'Cold', 'Winter']),
+ '80367': ('#f7f09b', '#ff5200', '#971549', '#470031', ['Yellow', 'Orange', 'Purple', 'Sunset', 'Warm']),
+ '80280': ('#e2eff1', '#65799b', '#555273', '#e23e57', ['Blue', 'Grey', 'Red', 'Retro', 'Cold']),
+ '82938': ('#222831', '#393e46', '#f96d00', '#f2f2f2', ['Black', 'Grey', 'Orange', 'Grey', 'Autumn']),
+ '82114': ('#22eaaa', '#b31e6f', '#ee5a5a', '#ffb174', ['Green', 'Purple', 'Orange', 'Vintage', 'Spring']),
+ '80168': ('#f1f6f5', '#9ef4e6', '#12cc94', '#6088bb', ['Grey', 'Turquoise', 'Green', 'Blue']),
+ '80113': ('#c02727', '#f4806d', '#ffffd3', '#f3f2b4', ['Red', 'Orange', 'Yellow']),
+ '80102': ('#e9e9e5', '#d4d6c8', '#9a9b94', '#52524e', ['Grey', 'Pastel', 'Winter']),
+ '79894': ('#324e7b', '#86a6df', '#5068a9', '#f8f8f8', ['Blue', 'Grey', 'Cold', 'Winter']),
+ '79877': ('#434343', '#a64452', '#f7c873', '#f8f8f8', ['Grey', 'Red', 'Orange', 'Autumn']),
+ '79851': ('#ef6c35', '#161c2e', '#2bb3c0', '#faf7f2', ['Orange', 'Black', 'Turquoise', 'Grey']),
+ '79812': ('#9ffbfb', '#a100ff', '#db97ff', '#ffb6ff', ['Blue', 'Purple', 'Pink', 'Bright', 'Cold']),
+ '79725': ('#000000', '#1a8b9d', '#b2d430', '#fff5f5', ['Black', 'Turquoise', 'Green', 'Grey']),
+ '79143': ('#4e1e1e', '#e63870', '#fbe6a2', '#58e481', ['Brown', 'Pink', 'Yellow', 'Green']),
+ '79336': ('#ffeed0', '#f79f24', '#e20049', '#7c064d', ['Orange', 'Red', 'Purple']),
+ '79270': ('#f0bebe', '#5ea3a6', '#3a718c', '#ffffdf', ['Pink', 'Turquoise', 'Yellow']),
+ '78936': ('#19215e', '#f7e6b5', '#fa67ab', '#80185f', ['Blue', 'Yellow', 'Pink', 'Purple', 'Retro', 'Wedding']),
+ '78974': ('#303481', '#d6e6f2', '#f5f5f5', '#fff200', ['Blue', 'Blue', 'Grey', 'Yellow', 'Bright']),
+ '79457': ('#e5f9bd', '#a0e418', '#7fb414', '#525050', ['Green', 'Bright']),
+ '78984': ('#f9c4ac', '#626f92', '#474168', '#272637', ['Orange', 'Blue', 'Black']),
+ '78945': ('#070739', '#521477', '#c327ab', '#e1e099', ['Black', 'Purple', 'Yellow', 'Dark']),
+ '79451': ('#a9eee6', '#fefaec', '#f38181', '#625772', ['Blue', 'Red', 'Vintage']),
+ '79325': ('#e3e8f8', '#c0c5cd', '#3e588f', '#203562', ['Blue', 'Grey', 'Wedding', 'Cold']),
+ '78942': ('#464545', '#fb5660', '#f98e90', '#f0f3b0', ['Grey', 'Red', 'Pink', 'Yellow']),
+ '78705': ('#0b5269', '#03051e', '#978d58', '#eae1e1', ['Blue', 'Black', 'Brown', 'Grey', 'Dark']),
+ '79837': ('#8e9fe6', '#6acafc', '#6ce6dd', '#dbf094', ['Blue', 'Purple', 'Turquoise', 'Green']),
+ '78747': ('#2d5c7f', '#fff1a8', '#ff8f56', '#984a59', ['Blue', 'Yellow', 'Orange', 'Sunset']),
+ '78711': ('#feceab', '#ff847c', '#eb4a5f', '#2a363b', ['Orange', 'Red', 'Black', 'Autumn', 'Warm']),
+ '87062': ('#fffbe0', '#fce38a', '#2994b2', '#444f5a', ['Yellow', 'Blue']),
+ '78761': ('#fdfce0', '#f0eeb1', '#dad773', '#b1ad25', ['Yellow', 'Green']),
+ '78675': ('#3c1b1f', '#b21e4b', '#e2bf81', '#f6e1b5', ['Brown', 'Red', 'Yellow', 'Warm']),
+ '78631': ('#314a52', '#52686a', '#acbdc5', '#ffded5', ['Grey', 'Pink', 'Winter']),
+ '78674': ('#f8f8f8', '#c246c6', '#91157e', '#65195e', ['Grey', 'Purple', 'Purple', 'Purple']),
+ '78630': ('#062121', '#181810', '#e4dcad', '#eeeeee', ['Black', 'Black', 'Brown', 'Grey']),
+ '78589': ('#e1f5f2', '#6bc5d2', '#5a5d9d', '#390050', ['Turquoise', 'Blue', 'Purple', 'Blue', 'Winter', 'Cold']),
+ '78489': ('#18587a', '#fc624d', '#fca7a7', '#ffd6d6', ['Blue', 'Pink', 'Orange']),
+ '78408': ('#343434', '#8e8b82', '#e9dcbe', '#f3f3f3', ['Grey', 'Brown']),
+ '78378': ('#f7f39a', '#a3de83', '#38817a', '#346473', ['Yellow', 'Green', 'Turquoise']),
+ '77930': ('#970747', '#fef4e8', '#13445a', '#446878', ['Red', 'Grey', 'Blue', 'Wedding', 'Retro']),
+ '77071': ('#331621', '#cc085e', '#de7d48', '#eeca98', ['Purple', 'Pink', 'Orange', 'Halloween', 'Warm']),
+ '93416': ('#f8fcfb', '#c9fdd7', '#79d1c3', '#6892d5', ['Grey', 'Blue', 'Green', 'Vintage', 'Bright', 'Cold']),
+ '77996': ('#f2f7ff', '#0b409c', '#10316b', '#fdbe34', ['Blue', 'Blue', 'Blue', 'Yellow']),
+ '77134': ('#ac0c0c', '#a7d82e', '#f5f883', '#fbfadf', ['Red', 'Green', 'Yellow', 'Christmas', 'Spring']),
+ '77067': ('#f8f5e4', '#f97300', '#0e3047', '#10828c', ['Orange', 'Black', 'Turquoise']),
+ '76029': ('#dbdbeb', '#7577cd', '#080957', '#ff6d02', ['Purple', 'Blue', 'Orange', 'Cold']),
+ '76768': ('#1684a7', '#09a599', '#f6ec72', '#f6f6f6', ['Blue', 'Green', 'Yellow', 'Grey']),
+ '75979': ('#6a759b', '#21273d', '#b9d4f1', '#f1f6f8', ['Blue', 'Black', 'Grey', 'Cold', 'Winter']),
+ '74943': ('#2e3b3e', '#50666b', '#f9b8be', '#fd6378', ['Grey', 'Pink', 'Vintage']),
+ '78712': ('#dcedc2', '#ffd3b5', '#ffaaa6', '#ff8c94', ['Green', 'Orange', 'Pink', 'Vintage', 'Pastel']),
+ '76728': ('#f1e58a', '#4c5374', '#71647c', '#d0f0f7', ['Yellow', 'Blue', 'Grey']),
+ '74172': ('#222222', '#045757', '#044343', '#e4e4e4', ['Black', 'Turquoise', 'Grey', 'Dark']),
+ '78331': ('#3f3038', '#fdf6fa', '#fdaed8', '#f361af', ['Grey', 'Pink', 'Wedding']),
+ '73365': ('#466551', '#368c72', '#7ecba1', '#e7eed2', ['Green']),
+ '75751': ('#f1684e', '#85c8dd', '#d3e0e2', '#e9f6f5', ['Orange', 'Blue', 'Grey', 'Turquoise']),
+ '76698': ('#e8f79a', '#49d292', '#3b445b', '#383746', ['Yellow', 'Green', 'Black']),
+ '76530': ('#f9f9f9', '#efe94b', '#9f1861', '#631357', ['Grey', 'Yellow', 'Purple']),
+ '76335': ('#f48fb1', '#f06292', '#ad1457', '#880e4f', ['Pink', 'Pink', 'Purple', 'Red']),
+ '76161': ('#fcf4d9', '#8ed2c9', '#00aaa0', '#d55b3e', ['Yellow', 'Turquoise', 'Orange']),
+ '77723': ('#560764', '#bb8fa9', '#d8cbbb', '#eeeeee', ['Purple', 'Grey', 'Wedding']),
+ '75278': ('#fc345c', '#49beb7', '#afffdf', '#eafff7', ['Red', 'Turquoise', 'Green', 'Spring', 'Bright']),
+ '73354': ('#1b4b36', '#538f6a', '#aebd77', '#e0e7f1', ['Green', 'Grey']),
+ '73684': ('#2a363b', '#cf4647', '#f5d061', '#f8f6f6', ['Black', 'Red', 'Yellow', 'Grey']),
+ '74985': ('#33425b', '#3498db', '#fcc29a', '#ecf0f1', ['Blue', 'Orange', 'Grey']),
+ '73271': ('#1d3e53', '#254b62', '#476d7c', '#77abb7', ['Blue', 'Dark', 'Winter', 'Cold']),
+ '76308': ('#fbfbfb', '#b1d056', '#e0ff59', '#ffa33e', ['Green', 'Grey', 'Orange', 'Bright']),
+ '74079': ('#22213d', '#4e3188', '#24babc', '#eaef9b', ['Black', 'Purple', 'Turquoise', 'Yellow']),
+ '76066': ('#f4e1e1', '#f98903', '#c62727', '#4c3232', ['Pink', 'Orange', 'Red', 'Brown', 'Autumn']),
+ '74864': ('#1c1124', '#693e52', '#badf96', '#f7ffcd', ['Black', 'Brown', 'Green', 'Yellow']),
+ '74744': ('#7eb19f', '#0c8282', '#ef9037', '#edddbd', ['Turquoise', 'Turquoise', 'Orange']),
+ '73149': ('#303841', '#2e4750', '#f6c90e', '#f7f7f7', ['Black', 'Yellow']),
+ '76222': ('#fffdef', '#f1f1f1', '#e70000', '#c50000', ['Grey', 'Red']),
+ '73228': ('#8aacff', '#626fe6', '#6d42c7', '#e85b48', ['Blue', 'Blue', 'Purple', 'Orange']),
+ '73246': ('#eeeeee', '#ea9215', '#3a4750', '#303841', ['Grey', 'Orange']),
+ '74392': ('#45171d', '#f03861', '#ff847c', '#fecea8', ['Brown', 'Red', 'Orange', 'Yellow', 'Warm']),
+ '74886': ('#fffcea', '#a5f2e7', '#8983f3', '#3a0077', ['Yellow', 'Blue', 'Purple', 'Retro']),
+ '75752': ('#d8dfe2', '#71adb5', '#176d81', '#0d3446', ['Grey', 'Turquoise', 'Winter', 'Cold']),
+ '73012': ('#432c51', '#535474', '#54a4af', '#ecbc55', ['Purple', 'Turquoise', 'Orange']),
+ '73808': ('#f9f3e6', '#e2dcd5', '#e8aa8c', '#5e616a', ['Orange', 'Grey']),
+ '77461': ('#ffecba', '#ff8d68', '#a10054', '#001f52', ['Yellow', 'Orange', 'Sunset', 'Autumn']),
+ '72699': ('#073059', '#2866ab', '#5fbdc5', '#d8d95c', ['Blue']),
+ '74424': ('#ffdede', '#f7f3ce', '#c5ecbe', '#4797b1', ['Pink', 'Yellow', 'Green', 'Blue', 'Bright', 'Spring']),
+ '72427': ('#3e3e3e', '#405559', '#68868c', '#ededed', ['Grey', 'Turquoise', 'Winter']),
+ '72814': ('#fc8a15', '#f6f6f6', '#1ee494', '#009378', ['Orange', 'Grey', 'Green', 'Bright']),
+ '73938': ('#febfb3', '#e1396c', '#96d38c', '#d0f9b1', ['Pink', 'Red', 'Green']),
+ '72112': ('#d3d6db', '#3a4750', '#303841', '#be3144', ['Grey', 'Black', 'Red', 'Wedding', 'Winter']),
+ '72512': ('#c2faf1', '#f6f6f6', '#dfeff0', '#295e6a', ['Turquoise', 'Grey', 'Blue', 'Cold', 'Bright']),
+ '72277': ('#eae7ed', '#b793e6', '#646ecb', '#3532a7', ['Grey', 'Purple', 'Blue', 'Blue', 'Cold']),
+ '71918': ('#ff6a38', '#9ed0e0', '#5c868e', '#19483f', ['Orange', 'Blue', 'Turquoise']),
+ '73328': ('#fffb85', '#ffd464', '#fa5b75', '#5a3662', ['Yellow', 'Yellow', 'Pink', 'Purple']),
+ '72484': ('#205d67', '#639a67', '#d8ebb5', '#d9bf77', ['Blue', 'Green', 'Brown', 'Vintage']),
+ '73289': ('#f5f7fa', '#5be7c4', '#4fc1e9', '#7a57d1', ['Blue', 'Turquoise', 'Blue', 'Purple', 'Retro']),
+ '71715': ('#ff5200', '#003355', '#04536c', '#adaca7', ['Orange', 'Blue', 'Grey']),
+ '72652': ('#defcf9', '#cadefc', '#c3bef0', '#cca8e9', ['Blue', 'Purple', 'Pastel']),
+ '71572': ('#31588a', '#638ccc', '#90b2e4', '#eacf79', ['Blue', 'Yellow']),
+ '72200': ('#2f1b41', '#9f1e49', '#fecd51', '#f2f2f2', ['Purple', 'Red', 'Yellow', 'Grey', 'Retro']),
+ '72875': ('#11cbd7', '#9feed1', '#fff6a2', '#f60c86', ['Blue', 'Turquoise', 'Yellow', 'Pink', 'Spring', 'Bright']),
+ '75964': ('#99f0ca', '#c9fdd7', '#fdffe7', '#8c7676', ['Green', 'Green', 'Yellow', 'Brown']),
+ '71827': ('#151680', '#1c44ac', '#375fc0', '#f1fea4', ['Blue', 'Yellow', 'Cold']),
+ '71453': ('#d2d4d6', '#7d8df6', '#5a4db2', '#ff771b', ['Grey', 'Blue', 'Orange']),
+ '71826': ('#b9f9ff', '#dafdff', '#f7e590', '#f5cd6d', ['Blue', 'Yellow', 'Summer', 'Bright']),
+ '71378': ('#222831', '#393e46', '#0092ca', '#eeeeee', ['Black', 'Grey', 'Blue', 'Winter']),
+ '73138': ('#f6fea1', '#ffb270', '#f08e6b', '#ff7575', ['Yellow', 'Orange', 'Red', 'Gold']),
+ '71387': ('#dafaf8', '#d6e1a5', '#027b7e', '#2a014b', ['Turquoise']),
+ '71609': ('#f49393', '#f21368', '#aa236d', '#261d1d', ['Pink', 'Red', 'Purple', 'Black']),
+ '72664': ('#22c7a9', '#2db6a3', '#fccf4d', '#fef3cc', ['Turquoise', 'Turquoise', 'Yellow', 'Yellow']),
+ '71318': ('#691a40', '#9e3668', '#f6a9ce', '#fde3f0', ['Purple', 'Pink', 'Pink']),
+ '71250': ('#4b4a5a', '#a55540', '#e79a58', '#e1d5d2', ['Grey', 'Brown', 'Orange', 'Autumn']),
+ '69667': ('#fafafa', '#e8f1f5', '#005691', '#004a7c', ['Grey', 'Blue', 'Cold', 'Winter']),
+ '70782': ('#f4f4ec', '#76e2f4', '#615dec', '#301781', ['Grey', 'Turquoise', 'Blue', 'Cold']),
+ '71302': ('#a8e6cf', '#dcedc1', '#ffd3b6', '#ffaaa5', ['Turquoise', 'Green', 'Orange', 'Pink', 'Pastel']),
+ '71050': ('#f3f6f6', '#30e3ca', '#11999e', '#40514e', ['Grey', 'Turquoise']),
+ '71246': ('#3d262a', '#127c56', '#eab64d', '#ecf3f6', ['Brown', 'Green', 'Orange', 'Grey']),
+ '70717': ('#2a2b5f', '#393c83', '#3dc4d0', '#44d9e6', ['Blue', 'Cold']),
+ '71366': ('#ff4545', '#ff9867', '#ffbf87', '#ffedb2', ['Red', 'Orange', 'Yellow', 'Warm']),
+ '70596': ('#e7f0d2', '#d2ea9b', '#abcb89', '#83b271', ['Green']),
+ '70716': ('#921224', '#bce0da', '#ebf5ee', '#bdc6b8', ['Red', 'Blue', 'Grey', 'Vintage', 'Wedding']),
+ '70746': ('#f8fdc3', '#facbf8', '#efa7f3', '#f677f7', ['Yellow', 'Pink', 'Bright']),
+ '68865': ('#ddf5f7', '#c0d9e5', '#44679f', '#3b577d', ['Blue', 'Cold']),
+ '69534': ('#eceff4', '#00ad7c', '#fbd490', '#475762', ['Grey', 'Green', 'Orange']),
+ '70050': ('#141829', '#21294c', '#f2dea8', '#f9f2d7', ['Black', 'Blue', 'Yellow']),
+ '71012': ('#fff6fb', '#ffbee3', '#fc5bb6', '#ff0592', ['Pink', 'Bright', 'Wedding']),
+ '69740': ('#f2eee3', '#baaf92', '#785e4d', '#ff8426', ['Grey', 'Brown', 'Orange', 'Autumn']),
+ '69056': ('#428b46', '#b7b56e', '#d6d88b', '#e9eab4', ['Green', 'Brown', 'Yellow']),
+ '70734': ('#7386d5', '#a0b6f5', '#ffefef', '#ff2c2c', ['Blue', 'Blue', 'Grey', 'Red']),
+ '70588': ('#0962ea', '#0e7cf4', '#0aa0f6', '#faf15d', ['Blue', 'Yellow']),
+ '68768': ('#f9f8eb', '#ffe1b6', '#7a9eb1', '#415865', ['Yellow', 'Blue']),
+ '70274': ('#f70776', '#c3195d', '#680747', '#141010', ['Red', 'Pink', 'Purple', 'Black']),
+ '69955': ('#2e2b2b', '#388186', '#a5e9e1', '#fdf6f6', ['Black', 'Turquoise', 'Grey']),
+ '68755': ('#fffe9f', '#ffd480', '#fca180', '#f56262', ['Yellow', 'Yellow', 'Orange', 'Red']),
+ '68238': ('#f2f9f1', '#ddeedf', '#b6cdbd', '#5c715e', ['Grey', 'Green', 'Vintage']),
+ '68089': ('#c7f5fe', '#fcc8f8', '#eab4f8', '#f3f798', ['Blue', 'Pink', 'Purple', 'Yellow', 'Bright']),
+ '69360': ('#525252', '#414141', '#313131', '#ec625f', ['Grey', 'Black', 'Red', 'Dark']),
+ '67181': ('#f0eec9', '#9ee6cf', '#50c9ba', '#4ba2ac', ['Yellow', 'Turquoise']),
+ '70476': ('#fafafa', '#ff6699', '#c54c82', '#512e67', ['Grey', 'Pink', 'Purple']),
+ '67166': ('#7effdb', '#b693fe', '#8c82fc', '#ff9de2', ['Turquoise', 'Purple', 'Pink']),
+ '68212': ('#1d7d81', '#213458', '#887575', '#f6e8e8', ['Turquoise', 'Blue', 'Brown', 'Pink']),
+ '68660': ('#57d1c9', '#ed5485', '#fffbcb', '#ffe869', ['Turquoise', 'Pink', 'Yellow', 'Yellow']),
+ '66766': ('#dff5f2', '#87dfd6', '#46b7b9', '#2f9296', ['Turquoise']),
+ '67816': ('#f3f3f3', '#ffdd67', '#ffcd38', '#4a4a4a', ['Grey', 'Yellow', 'Gold']),
+ '68797': ('#280b45', '#61105e', '#c84771', '#ffe98a', ['Purple', 'Yellow']),
+ '67815': ('#8ef6e4', '#9896f1', '#d59bf6', '#edb1f1', ['Turquoise', 'Purple', 'Pink']),
+ '68019': ('#a44a4a', '#dd8968', '#e4c478', '#e8e46d', ['Red', 'Orange', 'Yellow', 'Warm', 'Gold']),
+ '67703': ('#eeeeee', '#59569d', '#f25292', '#fea096', ['Grey', 'Purple', 'Pink', 'Pink']),
+ '67082': ('#d3f6d1', '#a7d7c5', '#74b49b', '#5c8d89', ['Green', 'Turquoise']),
+ '67020': ('#ff6f6f', '#fff46e', '#f6f6f6', '#a58bff', ['Red', 'Yellow', 'Grey', 'Purple', 'Bright']),
+ '68678': ('#2f1b41', '#872341', '#be3144', '#f05941', ['Red', 'Orange']),
+ '68013': ('#dddddd', '#574e6d', '#43405d', '#4b586e', ['Grey', 'Winter', 'Cold']),
+ '67450': ('#1fad9f', '#cd3131', '#ab1212', '#f6e4b5', ['Turquoise', 'Red', 'Yellow']),
+ '67080': ('#fc993c', '#ffe775', '#bd4682', '#8c2057', ['Orange', 'Yellow', 'Purple', 'Purple']),
+ '67593': ('#fafbd4', '#b2ebf9', '#aea1ea', '#8c54a1', ['Yellow', 'Blue', 'Purple', 'Wedding', 'Retro']),
+ '66373': ('#dde8b9', '#e8d2ae', '#cb8589', '#796465', ['Brown', 'Pastel', 'Vintage']),
+ '66528': ('#070f4e', '#2772db', '#3ab1c8', '#f5ebeb', ['Blue', 'Grey', 'Cold']),
+ '66334': ('#c8f4de', '#a4e5d9', '#66c6ba', '#649dad', ['Turquoise']),
+ '67660': ('#bc4f4f', '#e98b50', '#f3cd97', '#fef2a0', ['Orange', 'Yellow', 'Gold']),
+ '66246': ('#f9f8ed', '#f4e7d3', '#0881a3', '#1f4e5f', ['Blue', 'Wedding']),
+ '65976': ('#d7aef3', '#94f6f2', '#f7f680', '#fbd0f5', ['Purple', 'Turquoise', 'Yellow', 'Pink', 'Spring', 'Bright']),
+ '66663': ('#ebe9f6', '#453c38', '#6a5c55', '#f66e00', ['Brown', 'Grey', 'Orange']),
+ '65978': ('#ddfee4', '#28cc9e', '#196b69', '#132f2b', ['Green', 'Turquoise']),
+ '66989': ('#ca3e6b', '#fa8383', '#9dd3cc', '#ffe4b3', ['Red', 'Pink', 'Turquoise', 'Yellow']),
+ '65929': ('#f6f5f5', '#e3e3e3', '#3bb4c1', '#048998', ['Grey', 'Turquoise', 'Cold']),
+ '67169': ('#ff006c', '#d62b70', '#973961', '#623448', ['Red', 'Purple', 'Purple', 'Brown']),
+ '66816': ('#233142', '#455d7a', '#f95959', '#e3e3e3', ['Black', 'Blue', 'Red', 'Grey']),
+ '66979': ('#f5fac8', '#a5f0e4', '#82c7eb', '#8ea1f0', ['Yellow', 'Blue']),
+ '66822': ('#4b2c34', '#447878', '#779977', '#ddddbb', ['Brown', 'Turquoise', 'Green']),
+ '66724': ('#f7f09b', '#ff5200', '#c31207', '#77024d', ['Yellow', 'Orange', 'Red', 'Purple']),
+ '66380': ('#146c78', '#0e91a1', '#7dce94', '#efede7', ['Blue', 'Green', 'Grey']),
+ '66554': ('#faee1c', '#f3558e', '#9c1de7', '#581b98', ['Yellow', 'Pink', 'Purple', 'Purple']),
+ '66116': ('#a9eee6', '#fefaec', '#f9a1bc', '#625772', ['Turquoise', 'Yellow', 'Pink', 'Purple']),
+ '65520': ('#1b8057', '#55a44e', '#d7c37a', '#ede9a3', ['Green', 'Yellow', 'Brown']),
+ '67108': ('#3d1860', '#643579', '#bb99cd', '#f5edf7', ['Purple', 'Cold']),
+ '65211': ('#e67676', '#f2f062', '#a9e6e6', '#7692e4', ['Red', 'Yellow', 'Blue']),
+ '66214': ('#1b3c59', '#456173', '#11bfae', '#f2f2f0', ['Blue', 'Turquoise', 'Grey', 'Cold']),
+ '66130': ('#bff4ed', '#280f34', '#e41655', '#b30753', ['Blue', 'Black', 'Red']),
+ '65423': ('#f3f169', '#46c3db', '#2d6cdf', '#482ff7', ['Yellow', 'Blue']),
+ '65168': ('#f5e1da', '#f1f1f1', '#40a798', '#476268', ['Grey', 'Turquoise', 'Vintage']),
+ '65474': ('#511e78', '#8b2f97', '#cf56a1', '#fcb2bf', ['Purple', 'Pink']),
+ '65846': ('#90f6d7', '#35bcbf', '#41506b', '#263849', ['Turquoise', 'Turquoise', 'Black']),
+ '63974': ('#ecfffb', '#b4f1f1', '#2d767f', '#1e6262', ['Blue', 'Turquoise', 'Cold']),
+ '76788': ('#eeeeee', '#fcc314', '#94ac3c', '#295ba7', ['Grey', 'Yellow', 'Green', 'Blue', 'Spring']),
+ '65180': ('#f2e9d0', '#eaceb4', '#e79e85', '#bb5a5a', ['Brown', 'Orange', 'Red', 'Pastel', 'Vintage', 'Warm']),
+ '65473': ('#402785', '#5f4e9e', '#fafb97', '#fcc97b', ['Purple', 'Yellow']),
+ '64711': ('#ebfffa', '#c6fce5', '#6ef3d6', '#0dceda', ['Blue', 'Green', 'Turquoise', 'Bright', 'Cold']),
+ '64753': ('#f4f4f4', '#fb9935', '#b90b0b', '#8c0909', ['Grey', 'Orange', 'Red', 'Autumn']),
+ '63788': ('#ffabe5', '#c7f5ff', '#d89fff', '#f6fcae', ['Pink', 'Blue', 'Purple', 'Yellow', 'Spring', 'Bright']),
+ '63283': ('#1c226b', '#3e31ae', '#4aa9af', '#d1fffa', ['Purple', 'Turquoise', 'Blue', 'Cold']),
+ '63326': ('#dc3737', '#f7af1d', '#f5e180', '#aeaf7a', ['Red', 'Orange', 'Yellow', 'Autumn']),
+ '65068': ('#36d1c4', '#a0eecc', '#fff2be', '#f6318c', ['Turquoise', 'Green', 'Yellow', 'Pink', 'Spring', 'Bright']),
+ '65119': ('#4c6983', '#38556a', '#273952', '#b6fff9', ['Black', 'Winter', 'Cold']),
+ '65360': ('#be0eaa', '#ea2ba2', '#fb9696', '#f6ca97', ['Purple', 'Pink', 'Yellow', 'Spring']),
+ '62610': ('#e0fcff', '#90f2ff', '#6eb6ff', '#7098da', ['Blue', 'Bright', 'Cold']),
+ '65139': ('#fbf7f7', '#f9d00f', '#f0ae2c', '#f92727', ['Grey', 'Yellow', 'Red', 'Bright', 'Gold']),
+ '64640': ('#1b5a7a', '#1aa59a', '#a6ed8e', '#f3ffb9', ['Blue', 'Turquoise', 'Green', 'Yellow']),
+ '64641': ('#ff9898', '#cf455c', '#971549', '#470031', ['Pink', 'Red', 'Red', 'Purple', 'Warm']),
+ '63093': ('#586e72', '#fbf27c', '#5c835a', '#305c5c', ['Grey', 'Yellow', 'Green']),
+ '64291': ('#eb89b5', '#ffd7e9', '#fffbf3', '#fff8d2', ['Pink', 'Yellow', 'Bright']),
+ '63246': ('#f4f7f7', '#aacfd0', '#5da0a2', '#34495e', ['Grey', 'Turquoise', 'Cold']),
+ '62822': ('#7b77ff', '#92cce1', '#f68686', '#ffe3b9', ['Purple', 'Orange', 'Red', 'Yellow']),
+ '64412': ('#fff6f6', '#eea1eb', '#cb22d7', '#891180', ['Pink', 'Purple']),
+ '65088': ('#f6eb9a', '#5853bc', '#362391', '#1c0c59', ['Yellow', 'Blue']),
+ '63973': ('#f03861', '#fef2f2', '#f5d97e', '#7d5e3f', ['Red', 'Yellow', 'Brown']),
+ '62766': ('#d9f9f4', '#9cd9de', '#86c1d4', '#5a92af', ['Turquoise', 'Blue', 'Cold']),
+ '63915': ('#2aaf74', '#4ed99c', '#d1ebfe', '#f7be7f', ['Green', 'Blue', 'Orange']),
+ '62940': ('#f69d9d', '#ffeab6', '#fdffba', '#c0ffc2', ['Pink', 'Orange', 'Yellow', 'Green', 'Bright']),
+ '62803': ('#253b6e', '#1f5f8b', '#1891ac', '#d2ecf9', ['Blue', 'Cold']),
+ '63955': ('#f6faf7', '#e7eaa8', '#b4bb72', '#303e27', ['Grey', 'Green', 'Yellow']),
+ '63931': ('#b80257', '#dd356e', '#fc7fb6', '#ffbbe1', ['Red', 'Red', 'Pink', 'Pink']),
+ '62923': ('#76d3ff', '#d78bff', '#fffa9d', '#ffbd74', ['Blue', 'Purple', 'Yellow', 'Orange']),
+ '64857': ('#f2f7ff', '#0b409c', '#10316b', '#ffce63', ['Blue', 'Orange', 'Cold']),
+ '66129': ('#1fab89', '#62d2a2', '#9df3c4', '#d7fbe8', ['Green']),
+ '65249': ('#fee856', '#ffce3e', '#e65c7b', '#834496', ['Yellow', 'Yellow', 'Purple']),
+ '66990': ('#07689f', '#a2d5f2', '#fafafa', '#ff7e67', ['Blue', 'Orange']),
+ '63366': ('#560764', '#913175', '#dd5b82', '#fe9797', ['Purple', 'Pink']),
+ '62678': ('#266f89', '#3d93a3', '#3ec483', '#d2e48e', ['Blue', 'Green']),
+ '64671': ('#29c6cd', '#f6e4c4', '#fea386', '#f19584', ['Blue', 'Orange']),
+ '62767': ('#ffd9e8', '#de95ba', '#7f4a88', '#4a266a', ['Pink', 'Purple']),
+ '62193': ('#212121', '#323232', '#0d7377', '#14ffec', ['Black', 'Turquoise', 'Cold', 'Dark']),
+ '62655': ('#fd9191', '#fddd8a', '#f5fc9e', '#9efcb4', ['Pink', 'Orange', 'Yellow', 'Green']),
+ '62928': ('#eff7d3', '#cedcc3', '#a7b99e', '#535a3b', ['Yellow', 'Brown', 'Grey', 'Green']),
+ '62935': ('#3c3b5c', '#d53939', '#ffb563', '#7b3c59', ['Blue', 'Red', 'Orange', 'Purple', 'Halloween']),
+ '62535': ('#616eef', '#09a8fa', '#41c5d3', '#d0f1cf', ['Blue', 'Turquoise', 'Cold']),
+ '63012': ('#658361', '#d0dd97', '#f8fae4', '#f9de79', ['Green', 'Green', 'Grey', 'Yellow']),
+ '62386': ('#2c3e50', '#34495e', '#ecf0f1', '#bdc3c7', ['Grey']),
+ '62180': ('#f3f6f6', '#90eee1', '#55b3f3', '#6356e5', ['Grey', 'Turquoise', 'Blue']),
+ '62955': ('#f6378f', '#ffdd00', '#f5efe8', '#8ea5eb', ['Pink', 'Yellow', 'Grey', 'Blue', 'Spring']),
+ '62456': ('#388e3c', '#8bc34a', '#dce775', '#fff59d', ['Green', 'Green', 'Yellow', 'Yellow']),
+ '62241': ('#eff0f4', '#d3d6db', '#415f9d', '#233b6e', ['Grey', 'Blue', 'Winter', 'Cold']),
+ '45072': ('#f4f56e', '#72e8e1', '#58b3d3', '#418c9f', ['Yellow', 'Turquoise', 'Blue', 'Turquoise']),
+ '70512': ('#14103b', '#f02a71', '#7ec0e4', '#6789ba', ['Black', 'Pink', 'Blue', 'Blue']),
+ '45047': ('#eeeeee', '#234c63', '#379956', '#ffc85b', ['Grey', 'Blue', 'Green', 'Orange', 'Retro']),
+ '62199': ('#e38ed2', '#c75696', '#9d3978', '#512e67', ['Pink', 'Purple', 'Purple', 'Purple']),
+ '44798': ('#006c9a', '#00bebe', '#00f3e4', '#9ff9c1', ['Blue', 'Turquoise']),
+ '44662': ('#333c4a', '#495664', '#f6f7d3', '#f8fceb', ['Black', 'Yellow']),
+ '62624': ('#ff8fe5', '#fbff64', '#76e3ff', '#7bc7fa', ['Pink', 'Yellow', 'Blue', 'Bright']),
+ '45023': ('#2a528a', '#5d6ec7', '#9f71db', '#e9d498', ['Blue', 'Purple', 'Yellow']),
+ '44995': ('#ffdd83', '#e3f8ff', '#31bccc', '#405983', ['Yellow', 'Blue', 'Turquoise', 'Blue', 'Summer']),
+ '44992': ('#3a3a62', '#604fdd', '#26c6d0', '#e6e993', ['Purple', 'Turquoise', 'Yellow']),
+ '44707': ('#499491', '#a3dec9', '#f7fed8', '#fbd400', ['Turquoise', 'Yellow']),
+ '44958': ('#f70c9b', '#cb007b', '#d6e3ed', '#99b0c2', ['Pink', 'Purple', 'Grey']),
+ '44675': ('#f0fff3', '#c6f1e7', '#70acb1', '#59606d', ['Turquoise', 'Grey']),
+ '44906': ('#b31313', '#ff9000', '#fdda16', '#ffee82', ['Red', 'Orange', 'Yellow', 'Warm', 'Gold']),
+ '44586': ('#4d12ee', '#2f24c1', '#3fd1cb', '#f8f6f6', ['Blue', 'Turquoise', 'Grey']),
+ '44559': ('#34495d', '#2c3d4f', '#ee7738', '#f59d2a', ['Black', 'Orange']),
+ '44658': ('#8c7676', '#99f0ca', '#c9fdd7', '#fdffe7', ['Brown', 'Green', 'Yellow', 'Bright']),
+ '44430': ('#f9f5f0', '#f2ead3', '#f4991a', '#321313', ['Grey', 'Orange', 'Brown', 'Retro', 'Warm', 'Wedding']),
+ '44400': ('#4e4e6a', '#1f6cb0', '#70a3c4', '#e7e8f5', ['Grey', 'Blue', 'Cold']),
+ '62847': ('#f73f52', '#ffea85', '#f6f6f6', '#7986c7', ['Red', 'Yellow', 'Grey', 'Blue']),
+ '44259': ('#defbc2', '#90d26d', '#459d72', '#342b2b', ['Green']),
+ '44258': ('#f4f4f4', '#6decb9', '#11999e', '#3c3c3c', ['Grey', 'Green', 'Turquoise', 'Black']),
+ '43937': ('#282f44', '#e6af2e', '#f5d061', '#ececec', ['Black', 'Yellow', 'Grey', 'Gold']),
+ '44626': ('#104455', '#0a3442', '#3ad3cd', '#7fffd6', ['Turquoise', 'Cold']),
+ '44243': ('#d2f6fc', '#a9d2ff', '#7984ee', '#6730ec', ['Blue', 'Purple', 'Cold']),
+ '43846': ('#f1ed63', '#d97d97', '#9862ae', '#815a8f', ['Yellow', 'Pink', 'Purple']),
+ '43879': ('#ffd6b6', '#ea7362', '#b74242', '#5c2626', ['Orange', 'Brown', 'Warm']),
+ '43813': ('#364f6b', '#3fc1c9', '#fce38a', '#fc5185', ['Blue', 'Yellow', 'Pink']),
+ '43750': ('#1b435d', '#78bbe6', '#d5eeff', '#ff895d', ['Blue', 'Orange', 'Cold']),
+ '43765': ('#ffa0c2', '#f9f5ce', '#e3ce8b', '#9e7e44', ['Pink', 'Yellow', 'Brown']),
+ '44109': ('#fff2b2', '#9ed763', '#2c9e4b', '#0a4650', ['Yellow', 'Green']),
+ '44226': ('#f54ea2', '#a94caf', '#7b3b8c', '#41228e', ['Pink', 'Purple']),
+ '43974': ('#20decb', '#41eecb', '#f9f296', '#fcd78e', ['Turquoise', 'Yellow', 'Spring']),
+ '44449': ('#2e94b9', '#fffdc1', '#f0b775', '#fd5959', ['Blue', 'Yellow', 'Orange', 'Red']),
+ '43379': ('#e1eacd', '#bad8b6', '#61b390', '#01352c', ['Green', 'Black']),
+ '43753': ('#005689', '#007cb9', '#d5eeff', '#ff895d', ['Blue', 'Orange']),
+ '43636': ('#1b1f3a', '#53354a', '#a64942', '#ff7844', ['Black', 'Brown', 'Orange', 'Dark', 'Warm']),
+ '43601': ('#113f67', '#34699a', '#408ab4', '#65c6c4', ['Blue', 'Turquoise', 'Cold']),
+ '44038': ('#f2ffdf', '#b1f1b2', '#1e757b', '#424d69', ['Green', 'Turquoise']),
+ '43120': ('#ffbc65', '#ac4c5e', '#5c476f', '#eeeeee', ['Orange', 'Red', 'Purple', 'Grey']),
+ '43560': ('#272932', '#1c7293', '#b9e3c6', '#f1f2eb', ['Black', 'Blue', 'Green', 'Grey', 'Cold']),
+ '43744': ('#c54c82', '#ec729c', '#f4aeba', '#fdfdcb', ['Purple', 'Pink', 'Yellow', 'Warm']),
+ '43327': ('#ff5656', '#edf2f6', '#6a7efc', '#494953', ['Red', 'Blue', 'Blue', 'Grey']),
+ '42678': ('#f7f0e9', '#ffaf9b', '#df5333', '#424242', ['Grey', 'Orange', 'Black']),
+ '43162': ('#58828b', '#5e9387', '#c8e29d', '#f2f299', ['Turquoise', 'Green', 'Yellow']),
+ '42664': ('#233142', '#36506c', '#a5def1', '#ebf7fd', ['Black', 'Blue', 'Winter']),
+ '65175': ('#f23557', '#f0d43a', '#22b2da', '#3b4a6b', ['Red', 'Yellow', 'Blue', 'Blue']),
+ '43278': ('#f7f7f7', '#fcd59b', '#1fa8cf', '#2657c1', ['Grey', 'Yellow', 'Blue']),
+ '42568': ('#354649', '#6c7a89', '#a3c6c4', '#e0e7e9', ['Black', 'Grey', 'Winter', 'Cold']),
+ '42970': ('#faf4e1', '#fabc41', '#ec9454', '#c72767', ['Yellow', 'Orange', 'Purple', 'Warm', 'Vintage', 'Gold']),
+ '42656': ('#f2f2f2', '#cdcdcd', '#005691', '#004a7c', ['Grey', 'Blue', 'Cold']),
+ '42755': ('#fdf196', '#f08edb', '#bb47be', '#a31c88', ['Yellow', 'Pink', 'Purple', 'Spring']),
+ '42452': ('#303841', '#3a4750', '#ea9215', '#eeeeee', ['Black', 'Grey', 'Orange']),
+ '42726': ('#cbf9da', '#3dd2cc', '#3e6b89', '#122d42', ['Turquoise', 'Blue', 'Cold']),
+ '42617': ('#f47c7c', '#f7f48b', '#a1de93', '#70a1d7', ['Red', 'Yellow', 'Green', 'Blue']),
+ '42214': ('#283739', '#2c5d63', '#a9c52f', '#f5f5f5', ['Black', 'Turquoise', 'Green', 'Grey']),
+ '42563': ('#ed9153', '#fbd157', '#fbede1', '#53435b', ['Orange', 'Yellow', 'Autumn', 'Gold']),
+ '42191': ('#e3fdfd', '#cbf1f5', '#a6e3e9', '#71c9ce', ['Turquoise', 'Cold']),
+ '42676': ('#303a52', '#574b90', '#9e579d', '#fc85ae', ['Purple', 'Pink']),
+ '42560': ('#798a65', '#faf3df', '#d15385', '#8e415b', ['Green', 'Yellow', 'Purple', 'Purple']),
+ '42254': ('#f4f7ed', '#86ee60', '#2e6e65', '#2b3752', ['Grey', 'Green', 'Turquoise', 'Blue']),
+ '42012': ('#2e94b9', '#475053', '#acdcee', '#f0fbff', ['Blue', 'Grey', 'Cold']),
+ '42272': ('#f38181', '#fce38a', '#d6f7ad', '#95e1d3', ['Red', 'Yellow', 'Green', 'Blue']),
+ '62260': ('#2a363b', '#e84a5f', '#ff847b', '#fecea8', ['Black', 'Red', 'Orange', 'Warm']),
+ '41858': ('#1333a6', '#317ae1', '#1fdedb', '#fffcbf', ['Blue', 'Turquoise', 'Yellow']),
+ '41890': ('#ffca61', '#ffec85', '#f2ffdf', '#c9f0d6', ['Orange', 'Yellow', 'Turquoise', 'Spring', 'Summer', 'Gold']),
+ '42237': ('#283739', '#228896', '#a9c52f', '#f5f5f5', ['Turquoise', 'Blue', 'Green', 'Grey']),
+ '42657': ('#7a08fa', '#a82ffc', '#c264fe', '#f8ecfd', ['Purple', 'Cold']),
+ '41810': ('#adf7d1', '#95e8d7', '#7dace4', '#8971d0', ['Turquoise', 'Turquoise', 'Blue', 'Purple']),
+ '42533': ('#384259', '#f73859', '#7ac7c4', '#c4edde', ['Red', 'Turquoise']),
+ '41825': ('#f9a828', '#ececeb', '#07617d', '#2e383f', ['Orange', 'Grey', 'Blue', 'Black']),
+ '42088': ('#c2fcd9', '#a0e4b0', '#f8fba2', '#fa7f7f', ['Green', 'Yellow', 'Red', 'Summer', 'Bright', 'Spring']),
+ '41796': ('#425e92', '#0c81f6', '#5fe1d9', '#f7fad1', ['Blue', 'Blue', 'Turquoise', 'Yellow']),
+ '41771': ('#247291', '#f8da5b', '#eef2e2', '#f5f9ee', ['Blue', 'Yellow', 'Grey']),
+ '41748': ('#fff200', '#f5f5f5', '#d6e6f2', '#303841', ['Yellow', 'Grey', 'Black', 'Bright']),
+ '41747': ('#015668', '#06648c', '#0f81c7', '#0de2ea', ['Blue', 'Blue', 'Blue', 'Turquoise', 'Cold']),
+ '41721': ('#70198a', '#bb8fa9', '#c1ea9f', '#f6f1f8', ['Purple', 'Green', 'Grey', 'Wedding', 'Retro']),
+ '41625': ('#2f2b2b', '#f3368d', '#ffc468', '#fff7ca', ['Black', 'Pink', 'Orange', 'Yellow']),
+ '41622': ('#afffff', '#74dbef', '#5e88fc', '#264e86', ['Blue', 'Cold']),
+ '41314': ('#2a3356', '#f35b25', '#fdfcfc', '#e8e2e2', ['Blue', 'Orange', 'Grey', 'Retro']),
+ '41115': ('#45171d', '#e84a5f', '#ff847c', '#fecea8', ['Brown', 'Red', 'Orange']),
+ '41029': ('#c190f0', '#9876de', '#fdfe9a', '#9adeb9', ['Purple', 'Purple', 'Yellow', 'Green']),
+ '41025': ('#f4f7f7', '#79a8a9', '#4d727e', '#1f4e5f', ['Grey', 'Turquoise', 'Cold']),
+ '41482': ('#00ad7c', '#52d681', '#b5ff7d', '#fff8b5', ['Green', 'Yellow']),
+ '41089': ('#f85f73', '#fbe8d3', '#928a97', '#283c63', ['Red', 'Grey', 'Blue']),
+ '39932': ('#295e62', '#1c4648', '#d5d46f', '#dff09d', ['Turquoise', 'Yellow']),
+ '40871': ('#baf5f0', '#d17ae5', '#e889e5', '#f9fcc9', ['Blue', 'Purple', 'Pink', 'Yellow', 'Spring', 'Bright']),
+ '40803': ('#fcf0c8', '#f7d098', '#911f27', '#630a10', ['Yellow', 'Red', 'Warm']),
+ '40848': ('#95efce', '#2ea1d9', '#395ea6', '#3e467f', ['Turquoise', 'Blue']),
+ '40787': ('#f9fcfd', '#c9eff9', '#07a4b5', '#fed8a7', ['Blue', 'Orange']),
+ '39481': ('#392f2f', '#3a7563', '#59a985', '#e6d3a7', ['Brown', 'Green']),
+ '40181': ('#fafafa', '#ff347f', '#c9356c', '#f48db4', ['Grey', 'Pink']),
+ '39112': ('#ffffe7', '#c6e5f3', '#539ddb', '#084a83', ['Yellow', 'Blue', 'Cold']),
+ '40128': ('#fa4659', '#feffe4', '#a3de83', '#2eb872', ['Red', 'Yellow', 'Green', 'Spring']),
+ '40377': ('#f5f5f5', '#c5d200', '#51710a', '#424242', ['Grey', 'Green', 'Green', 'Grey']),
+ '40297': ('#c7ffff', '#fbeeff', '#ebc6ff', '#7e80ff', ['Blue', 'Pink', 'Bright']),
+ '42666': ('#900c27', '#c70039', '#f6c667', '#f1f8fd', ['Red', 'Yellow', 'Orange', 'Warm']),
+ '41743': ('#003744', '#1a554f', '#fda856', '#f6fe91', ['Green', 'Orange', 'Yellow']),
+ '39602': ('#ffcfdf', '#fefdca', '#e0f9b5', '#a5dee5', ['Pink', 'Yellow', 'Green', 'Blue', 'Pastel', 'Spring', 'Bright']),
+ '40156': ('#0f1021', '#d01257', '#fb90b7', '#ffcee4', ['Black', 'Pink', 'Pink']),
+ '39902': ('#d7ffdf', '#ace6c0', '#77b5a6', '#9d4545', ['Green', 'Green', 'Turquoise', 'Brown']),
+ '38962': ('#fafafa', '#c7eeff', '#0077c0', '#1d242b', ['Grey', 'Blue', 'Black', 'Cold']),
+ '41475': ('#241e92', '#5432d3', '#7b6cf6', '#e5a5ff', ['Purple', 'Blue', 'Pink', 'Cold']),
+ '39857': ('#ffeee7', '#fbb448', '#e3670c', '#cc3d0b', ['Pink', 'Orange', 'Orange', 'Autumn', 'Warm']),
+ '39609': ('#15b7b9', '#10ddc2', '#f5f5f5', '#f57170', ['Blue', 'Turquoise', 'Grey', 'Red']),
+ '39601': ('#2f3c4f', '#506e86', '#fcb040', '#de703b', ['Blue', 'Orange']),
+ '38861': ('#e4fffe', '#a4f6f9', '#ff99fe', '#ba52ed', ['Blue', 'Pink', 'Purple', 'Bright']),
+ '39305': ('#083836', '#66d37e', '#c6e872', '#fbffa3', ['Green', 'Yellow']),
+ '39666': ('#f95959', '#ffe1a1', '#fcffcc', '#d3e785', ['Red', 'Orange', 'Yellow', 'Green']),
+ '39614': ('#718ca1', '#59748c', '#354d62', '#d7f2f7', ['Blue', 'Turquoise', 'Cold', 'Winter']),
+ '39495': ('#f7e74a', '#09c6ab', '#068888', '#02556d', ['Yellow', 'Turquoise', 'Blue']),
+ '39065': ('#6251da', '#828bff', '#7ab7ff', '#f0fc93', ['Blue', 'Purple', 'Yellow']),
+ '38961': ('#eaefc4', '#9bdf46', '#25a55f', '#346473', ['Green']),
+ '38863': ('#f1ffd9', '#8bdbf5', '#b292ea', '#eb55bf', ['Yellow', 'Blue', 'Purple', 'Pink', 'Spring']),
+ '39317': ('#2b4450', '#497285', '#dfebed', '#f78536', ['Turquoise', 'Blue', 'Orange']),
+ '38824': ('#f1fafb', '#a0e4f1', '#9dc6ff', '#4993fa', ['Turquoise', 'Blue', 'Cold']),
+ '39056': ('#513c3c', '#2a769a', '#41c3be', '#f7f36b', ['Brown', 'Blue', 'Turquoise', 'Yellow']),
+ '38857': ('#ecffc9', '#64fed6', '#82a6ee', '#7871bf', ['Yellow', 'Turquoise', 'Blue', 'Purple']),
+ '39176': ('#fffc3a', '#ea648d', '#884ea2', '#3d3551', ['Yellow', 'Pink', 'Purple']),
+ '38817': ('#e6f8f6', '#a0f6d2', '#72dfd0', '#03414d', ['Turquoise']),
+ '39631': ('#683531', '#bf382a', '#ef7079', '#f7e8c3', ['Brown', 'Red', 'Yellow', 'Warm']),
+ '38641': ('#d1ffa2', '#00cf95', '#0098ef', '#6d0ad3', ['Green', 'Blue', 'Purple']),
+ '38340': ('#2f3032', '#383a56', '#b0a565', '#ede68a', ['Black', 'Blue', 'Yellow', 'Dark']),
+ '38642': ('#d5fdff', '#9de5ff', '#aca8ff', '#ac73ff', ['Blue', 'Purple', 'Cold']),
+ '38618': ('#01005e', '#22267b', '#28518a', '#17b794', ['Blue', 'Green', 'Cold', 'Dark', 'Winter']),
+ '38654': ('#b062ea', '#f392f2', '#fed08f', '#f6f39f', ['Purple', 'Pink', 'Orange', 'Yellow', 'Bright']),
+ '38301': ('#d2fafb', '#5acfd6', '#189bfa', '#0c4b8e', ['Turquoise', 'Blue', 'Cold']),
+ '38724': ('#feffa0', '#acdb86', '#547c66', '#3b5b5d', ['Yellow', 'Green']),
+ '38497': ('#c9182b', '#f23a3a', '#e3f3ac', '#44c662', ['Red', 'Green', 'Christmas']),
+ '38290': ('#3f1263', '#986ead', '#d8cbbb', '#f2f2f2', ['Purple', 'Purple', 'Brown', 'Grey']),
+ '38288': ('#f1fdf3', '#e5f4e7', '#d1e9d2', '#99cda9', ['Green', 'Green', 'Green', 'Green']),
+ '37482': ('#5f2f14', '#1297bd', '#1ad7db', '#f3f1f1', ['Brown', 'Blue', 'Grey', 'Vintage', 'Wedding']),
+ '37362': ('#00334e', '#145374', '#5588a3', '#e8e8e8', ['Blue', 'Grey', 'Cold', 'Winter']),
+ '37243': ('#f5ff8d', '#50cb86', '#4c74c9', '#312f44', ['Yellow', 'Green', 'Blue', 'Black']),
+ '37155': ('#283739', '#2c5d63', '#a2c11c', '#e0e0e0', ['Black', 'Turquoise', 'Green', 'Grey']),
+ '38859': ('#fbffe0', '#ffd6a6', '#ff8ab4', '#d86eff', ['Yellow', 'Orange', 'Pink', 'Purple', 'Spring']),
+ '37340': ('#0c4762', '#51dacf', '#9ef5cf', '#f4eeee', ['Turquoise', 'Grey']),
+ '42937': ('#700961', '#b80d57', '#e03e36', '#ff7c38', ['Purple', 'Orange', 'Warm']),
+ '37026': ('#0eb29a', '#f5fdff', '#ddf0c2', '#8c999a', ['Turquoise', 'Green', 'Grey']),
+ '37211': ('#39627f', '#4b788f', '#e4de66', '#beb000', ['Blue', 'Green']),
+ '38164': ('#d65f5f', '#faf99f', '#a1f6b6', '#78d8d0', ['Red', 'Yellow', 'Turquoise', 'Green']),
+ '36953': ('#3c2f3d', '#2eac6d', '#9dda52', '#f0f0f0', ['Black', 'Green', 'Green', 'Grey']),
+ '36842': ('#f2f299', '#c8e29d', '#5e9387', '#58828b', ['Yellow', 'Green']),
+ '36777': ('#fff9c1', '#ffa1d0', '#c244fb', '#84e9ff', ['Yellow', 'Pink', 'Purple', 'Blue']),
+ '36668': ('#005689', '#007cb9', '#f6c667', '#f1f8fd', ['Blue', 'Orange']),
+ '36477': ('#00e0ff', '#74f9ff', '#a6fff2', '#e8ffe8', ['Blue', 'Bright', 'Summer']),
+ '36237': ('#b23256', '#fcd47d', '#31aa75', '#a2ef44', ['Red', 'Yellow', 'Green', 'Christmas']),
+ '36487': ('#fffaa2', '#d600b1', '#a500a3', '#680097', ['Yellow', 'Purple']),
+ '36394': ('#64868e', '#98b4a6', '#d1e4d1', '#f3fbf1', ['Turquoise', 'Green', 'Grey', 'Green']),
+ '38862': ('#f4f1ae', '#ff8d52', '#f85a16', '#ca005e', ['Yellow', 'Orange', 'Purple', 'Warm']),
+ '36181': ('#007ab5', '#005a85', '#004262', '#d8e6ec', ['Blue', 'Cold']),
+ '38613': ('#fffbaf', '#ff5656', '#cd0a0a', '#42cfc4', ['Yellow', 'Red', 'Red', 'Turquoise']),
+ '36185': ('#442a9d', '#f14e95', '#b13cd5', '#faf3fc', ['Purple', 'Pink']),
+ '36113': ('#191ba9', '#5cc2f2', '#c1eaf2', '#f7f3f3', ['Blue', 'Grey', 'Cold']),
+ '36041': ('#fd5959', '#ff9c6d', '#fcff82', '#afc5ff', ['Red', 'Orange', 'Yellow', 'Blue']),
+ '36105': ('#43496e', '#544d7e', '#65589c', '#ffc12d', ['Purple', 'Orange']),
+ '35990': ('#fcf798', '#e0fff9', '#74d2ff', '#5ca4ca', ['Yellow', 'Blue', 'Bright']),
+ '35881': ('#fcfaef', '#e2e0a5', '#d3504a', '#a63636', ['Brown', 'Red', 'Vintage']),
+ '35742': ('#fe7187', '#ca4b7c', '#7a2e7a', '#a8d7f7', ['Pink', 'Purple', 'Blue']),
+ '35642': ('#daebee', '#b6d7de', '#fcedda', '#ff5126', ['Blue', 'Orange', 'Wedding']),
+ '35780': ('#07588a', '#6ac1b8', '#bfe9db', '#e1f6f4', ['Blue', 'Turquoise', 'Green', 'Cold']),
+ '35644': ('#f8ecd9', '#eebee3', '#c576ac', '#662753', ['Yellow', 'Pink', 'Purple']),
+ '35619': ('#f8ffae', '#f36363', '#ef4a4a', '#d32d2d', ['Yellow', 'Orange', 'Red', 'Warm']),
+ '35489': ('#e8ecf1', '#b5cfd8', '#7393a7', '#6c737e', ['Grey', 'Blue', 'Winter', 'Pastel', 'Cold']),
+ '36435': ('#f2ff9b', '#6af79a', '#57acc5', '#444b6c', ['Yellow', 'Green', 'Blue']),
+ '35271': ('#65ead1', '#f469a9', '#ff917b', '#fcffc1', ['Turquoise', 'Pink', 'Orange', 'Yellow', 'Retro', 'Spring']),
+ '35497': ('#303841', '#3a4750', '#d72323', '#eeeeee', ['Red', 'Grey']),
+ '35469': ('#e4fcf9', '#ace6f6', '#4b89ac', '#446491', ['Blue', 'Cold']),
+ '35159': ('#ee9494', '#ebffaf', '#b4e8c0', '#c3b9ea', ['Red', 'Yellow', 'Green', 'Purple', 'Bright']),
+ '34110': ('#6f4f8b', '#6d739d', '#7dbcc8', '#b9eaf5', ['Purple', 'Blue']),
+ '34098': ('#2794eb', '#bff8d4', '#47d6b6', '#17b3c1', ['Blue', 'Turquoise', 'Green']),
+ '41371': ('#f5f5f5', '#b9e937', '#57d131', '#406661', ['Grey', 'Green']),
+ '37188': ('#2e94b9', '#fffdc1', '#f0b775', '#d25565', ['Blue', 'Yellow', 'Orange', 'Red']),
+ '34781': ('#3c9099', '#5fbdb0', '#e3e2c3', '#f0efe2', ['Turquoise', 'Grey', 'Pastel']),
+ '34104': ('#c4317b', '#ac7c7c', '#d0baa8', '#efe4e4', ['Purple', 'Brown']),
+ '34002': ('#48f3db', '#51c4e9', '#6150c1', '#4a3764', ['Turquoise', 'Blue', 'Purple', 'Cold']),
+ '34608': ('#7a4579', '#d56073', '#ec9e69', '#ffff8f', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset', 'Wedding', 'Warm']),
+ '33990': ('#f7fbfc', '#d6e6f2', '#b9d7ea', '#769fcd', ['Grey', 'Blue', 'Bright', 'Cold']),
+ '33743': ('#343434', '#2d4059', '#ea5455', '#fde9c9', ['Black', 'Blue', 'Red', 'Yellow']),
+ '33592': ('#ebe8be', '#b3c87a', '#347a2a', '#202e24', ['Green']),
+ '33357': ('#415f77', '#d1e9ea', '#fc5050', '#ffd00c', ['Blue', 'Red', 'Yellow']),
+ '35508': ('#f7b679', '#e77c7c', '#b55c6c', '#61305d', ['Orange', 'Purple']),
+ '33208': ('#062d92', '#046fdb', '#03d6d2', '#fffcbf', ['Blue', 'Blue', 'Turquoise', 'Yellow']),
+ '33261': ('#4b2b30', '#5e3b4d', '#aa96b7', '#d9e2a8', ['Brown', 'Purple', 'Purple', 'Green']),
+ '33148': ('#f4fab3', '#a4eae8', '#53aca8', '#498eb9', ['Yellow', 'Blue', 'Turquoise', 'Summer']),
+ '32736': ('#dddddd', '#516c8d', '#28385e', '#304163', ['Grey', 'Blue', 'Cold']),
+ '32822': ('#b8eef1', '#bf68f6', '#fd89dd', '#f0e48e', ['Blue', 'Purple', 'Pink', 'Yellow', 'Bright', 'Retro']),
+ '32734': ('#cabfab', '#dfd8c8', '#41444b', '#52575d', ['Brown', 'Brown', 'Grey', 'Grey']),
+ '32512': ('#041122', '#259073', '#7fda89', '#e6f99d', ['Black', 'Turquoise', 'Green', 'Yellow']),
+ '32089': ('#ff9090', '#ffcf7f', '#fffa62', '#89c4ff', ['Pink', 'Orange', 'Yellow', 'Blue']),
+ '32030': ('#2daf94', '#3ec8ac', '#4be4c5', '#c8f6ed', ['Turquoise']),
+ '32519': ('#ffdbc5', '#ef4339', '#b01c33', '#2e112d', ['Orange', 'Red', 'Black', 'Warm']),
+ '31443': ('#9ddcdc', '#fff4e1', '#ffebb7', '#e67a7a', ['Blue', 'Yellow', 'Red']),
+ '32487': ('#414a50', '#85a6b1', '#8bd7d1', '#caedde', ['Grey', 'Turquoise', 'Blue', 'Cold']),
+ '33469': ('#f72464', '#ff858a', '#fff3a7', '#568564', ['Red', 'Pink', 'Yellow', 'Green', 'Spring']),
+ '31016': ('#54777d', '#eadb9d', '#feffe4', '#e7e3c5', ['Turquoise', 'Brown', 'Yellow']),
+ '30601': ('#384137', '#406661', '#3bb873', '#94ed88', ['Green']),
+ '32018': ('#83580b', '#d9b650', '#f5dd7b', '#fde994', ['Brown', 'Yellow', 'Gold']),
+ '32571': ('#4f1c4c', '#a91d1d', '#da4949', '#fde9c9', ['Purple', 'Red']),
+ '31046': ('#ffa5a5', '#ffffc2', '#c8e7ed', '#bfcfff', ['Pink', 'Yellow', 'Blue', 'Pastel', 'Summer', 'Bright']),
+ '31006': ('#f0f2ac', '#a7cbd9', '#7e94bf', '#5357a6', ['Yellow', 'Blue']),
+ '29213': ('#93e4c1', '#3baea0', '#118a7e', '#1f6f78', ['Green', 'Turquoise']),
+ '30356': ('#121435', '#faf9f0', '#edebca', '#ff5722', ['Black', 'Yellow', 'Orange']),
+ '30546': ('#1d2b53', '#7e2553', '#ff004d', '#fff024', ['Blue', 'Red', 'Yellow']),
+ '29954': ('#f5f5f5', '#b9e937', '#00b906', '#424242', ['Grey', 'Green', 'Green', 'Grey']),
+ '30296': ('#353e55', '#b36458', '#bcd3c2', '#e0e7b8', ['Vintage']),
+ '29746': ('#591fce', '#0c9cee', '#3dbdc2', '#a1f480', ['Purple', 'Blue', 'Turquoise', 'Green']),
+ '30670': ('#da1212', '#f08c00', '#c6da20', '#f3f5d5', ['Red', 'Orange', 'Green', 'Yellow', 'Autumn', 'Christmas']),
+ '30163': ('#fafafa', '#e1eeff', '#c2cfd8', '#543a3a', ['Grey', 'Blue', 'Brown', 'Vintage', 'Wedding', 'Cold']),
+ '29652': ('#b8f7d4', '#6fe7db', '#7fa6ee', '#835af1', ['Green', 'Turquoise', 'Blue', 'Purple']),
+ '32264': ('#fdffa3', '#f59af0', '#a980e4', '#a2e4a2', ['Yellow', 'Pink', 'Purple', 'Green']),
+ '29637': ('#61b292', '#aed09e', '#f1e8a7', '#a8896c', ['Green', 'Yellow', 'Brown']),
+ '30252': ('#1f024c', '#45056e', '#8f1383', '#e47676', ['Purple', 'Orange', 'Dark']),
+ '29275': ('#f87d09', '#f6f6f6', '#a7cdcc', '#004a55', ['Orange', 'Grey', 'Turquoise']),
+ '28905': ('#1a1a1b', '#333f44', '#37aa9c', '#94f3e4', ['Black', 'Turquoise']),
+ '29979': ('#e0c97e', '#fcf8b3', '#fb9378', '#ab6088', ['Brown', 'Yellow', 'Orange', 'Purple']),
+ '30285': ('#efecea', '#334854', '#e04462', '#f9c535', ['Grey', 'Black', 'Red', 'Yellow']),
+ '29318': ('#504d4d', '#646363', '#f5b316', '#e7e5e5', ['Grey', 'Grey', 'Yellow', 'Grey']),
+ '28937': ('#17e7a4', '#f6f1f1', '#e0d909', '#7d7474', ['Green', 'Grey', 'Yellow']),
+ '29636': ('#89aa97', '#f4e3b7', '#fff798', '#fd7e89', ['Green', 'Yellow', 'Red', 'Spring']),
+ '28684': ('#0e1555', '#4e1184', '#932b77', '#fd367e', ['Purple', 'Pink']),
+ '28636': ('#015051', '#04837b', '#01a7a3', '#04f2d5', ['Turquoise']),
+ '28621': ('#303841', '#3a4750', '#f6c90e', '#f64e8b', ['Black', 'Yellow', 'Pink']),
+ '28624': ('#c8b273', '#834655', '#9f5069', '#f6cac9', ['Brown', 'Pink']),
+ '28505': ('#fff5b5', '#ff9071', '#e85395', '#a73ccb', ['Yellow', 'Orange', 'Pink', 'Purple', 'Spring']),
+ '28465': ('#9bf4d5', '#29cdb5', '#fff3e1', '#373331', ['Turquoise', 'Turquoise', 'Yellow', 'Black']),
+ '28797': ('#083c5a', '#4cb648', '#fcc72c', '#e4f4fd', ['Blue', 'Green', 'Yellow']),
+ '28270': ('#fdea2e', '#f40968', '#512e5e', '#20194a', ['Yellow', 'Pink', 'Purple', 'Black']),
+ '27893': ('#9a47cb', '#ff80f3', '#ffd48b', '#fff079', ['Purple', 'Pink', 'Orange', 'Yellow']),
+ '26451': ('#15eda3', '#0ea47a', '#068b80', '#127780', ['Green']),
+ '28174': ('#f5d7a1', '#f0a28e', '#ba6476', '#812d58', ['Yellow', 'Orange', 'Purple', 'Autumn', 'Warm']),
+ '27119': ('#bbe9db', '#aeccc6', '#9ba6a5', '#757a79', ['Grey', 'Turquoise']),
+ '27158': ('#020438', '#284184', '#1f8ea3', '#00eaff', ['Blue', 'Turquoise', 'Cold']),
+ '26949': ('#4ae3b5', '#eeeeee', '#2a5d67', '#171332', ['Turquoise', 'Grey', 'Black']),
+ '27422': ('#f2ef99', '#de8ae8', '#972ea9', '#6a0e97', ['Yellow', 'Purple']),
+ '26375': ('#f36b6b', '#ece58a', '#1fb57b', '#84d270', ['Red', 'Yellow', 'Green']),
+ '25912': ('#003e21', '#067242', '#098b54', '#f8d098', ['Green', 'Green', 'Green', 'Orange']),
+ '25843': ('#ffe700', '#fe4e6e', '#613864', '#d8d7d7', ['Yellow', 'Pink', 'Purple', 'Grey']),
+ '25796': ('#f1fcfd', '#c7eeff', '#4d6de3', '#393737', ['Blue', 'Black', 'Cold']),
+ '24652': ('#000000', '#3e3636', '#d72323', '#f5eded', ['Black', 'Grey', 'Red', 'Dark']),
+ '25644': ('#feff9f', '#78dec9', '#2a6f7f', '#0e2033', ['Yellow', 'Turquoise', 'Turquoise', 'Black']),
+ '25451': ('#fff29c', '#ffb26b', '#ff639f', '#ff2865', ['Yellow', 'Orange', 'Pink', 'Red']),
+ '25729': ('#222831', '#393e46', '#00adb5', '#00fff5', ['Black', 'Blue', 'Cold', 'Dark']),
+ '24114': ('#cff800', '#feff92', '#0fefbd', '#7899dc', ['Green', 'Yellow', 'Turquoise', 'Blue']),
+ '24625': ('#240747', '#eb2632', '#f0ab8d', '#f6e4ad', ['Black', 'Red', 'Pink', 'Yellow']),
+ '24484': ('#76508e', '#482d57', '#03c1eb', '#86f3b8', ['Purple', 'Blue', 'Green']),
+ '24360': ('#fefea4', '#ffdc76', '#773838', '#4a2c2c', ['Yellow', 'Brown', 'Warm']),
+ '23782': ('#f79486', '#faf885', '#fcffc9', '#8ff5d2', ['Red', 'Yellow', 'Turquoise']),
+ '21781': ('#222831', '#2d4059', '#ff5722', '#eeeeee', ['Black', 'Orange', 'Grey', 'Dark']),
+ '23588': ('#a20a0a', '#bb9518', '#ccd51a', '#f7ffa8', ['Red', 'Brown', 'Yellow']),
+ '23083': ('#28615b', '#e4f6f6', '#ccccea', '#c089f8', ['Turquoise', 'Turquoise', 'Purple', 'Purple']),
+ '22672': ('#0c056d', '#590d82', '#b61aae', '#f25d9c', ['Blue', 'Purple', 'Purple', 'Pink']),
+ '22660': ('#fdf196', '#c5fcda', '#98e5ec', '#67bac6', ['Yellow', 'Blue', 'Bright']),
+ '22272': ('#f9f7f7', '#dbe2ef', '#3f72af', '#112d4e', ['Grey', 'Blue', 'Black', 'Cold']),
+ '20916': ('#222831', '#393e46', '#fd7014', '#eeeeee', ['Black', 'Grey', 'Orange', 'Dark']),
+ '21046': ('#83e4b5', '#3ec8ac', '#4e90a4', '#6e60a0', ['Green', 'Turquoise', 'Blue', 'Purple']),
+ '20752': ('#27e1ce', '#efffb7', '#d6ec78', '#ff98da', ['Turquoise', 'Yellow', 'Green', 'Pink', 'Spring', 'Bright']),
+ '20933': ('#f7f6de', '#fa7e0a', '#8f0e0e', '#530c0c', ['Orange', 'Red', 'Brown', 'Autumn', 'Halloween', 'Warm']),
+ '20614': ('#f8ff95', '#7be77e', '#7a8cf0', '#a45fe6', ['Yellow', 'Green', 'Blue', 'Purple']),
+ '20605': ('#300532', '#aa3763', '#f6dec4', '#fef8dd', ['Purple', 'Purple', 'Yellow', 'Yellow']),
+ '20660': ('#faf8f8', '#17ead9', '#6078ea', '#4b4848', ['Grey', 'Turquoise', 'Blue', 'Grey']),
+ '20333': ('#3e3e3e', '#f4722b', '#f6e7c1', '#b3a78c', ['Grey', 'Orange', 'Autumn']),
+ '19659': ('#fa5555', '#f7fb76', '#8ded8e', '#2d7d8f', ['Red', 'Yellow', 'Green', 'Turquoise']),
+ '20198': ('#055049', '#069a8e', '#a1e3d8', '#f5f093', ['Turquoise', 'Yellow']),
+ '20288': ('#fffbe0', '#fcda05', '#393e46', '#222831', ['Yellow', 'Black']),
+ '19949': ('#ffdd00', '#f64e8b', '#a01ba7', '#452b45', ['Yellow', 'Pink', 'Purple']),
+ '19832': ('#001f3f', '#083358', '#0da574', '#ffd717', ['Blue', 'Green', 'Yellow']),
+ '26363': ('#ea5959', '#f98b60', '#ffc057', '#ffe084', ['Red', 'Orange', 'Yellow', 'Warm']),
+ '19897': ('#fbffa3', '#c6e872', '#66d37e', '#0d625e', ['Yellow', 'Green']),
+ '19148': ('#468966', '#fff0a5', '#ffb03b', '#b64926', ['Green', 'Yellow', 'Orange', 'Gold']),
+ '19775': ('#7bc74d', '#222831', '#393e46', '#eeeeee', ['Green', 'Black', 'Grey']),
+ '19337': ('#faa9df', '#fae98f', '#f04f4f', '#810749', ['Pink', 'Yellow', 'Red', 'Purple']),
+ '19020': ('#743c08', '#df760b', '#f6b61e', '#ffebaf', ['Brown', 'Orange', 'Yellow', 'Warm', 'Gold']),
+ '19113': ('#303841', '#00adb5', '#eeeeee', '#ff5722', ['Black', 'Turquoise', 'Grey', 'Orange', 'Retro']),
+ '18933': ('#f9ebc4', '#a7cf5d', '#a97555', '#483d3c', ['Green', 'Brown']),
+ '18919': ('#e6ee75', '#da4949', '#4f1c4c', '#0d132a', ['Yellow', 'Orange', 'Purple', 'Black']),
+ '18915': ('#6163d3', '#6db7ca', '#fcf769', '#ffd23e', ['Blue', 'Yellow']),
+ '18612': ('#6fe7dd', '#3490de', '#6639a6', '#521262', ['Turquoise', 'Blue', 'Purple']),
+ '18378': ('#303841', '#3a4750', '#f6c90e', '#eeeeee', ['Black', 'Yellow', 'Grey', 'Dark']),
+ '18562': ('#fcffc1', '#9bf4d5', '#1dad9b', '#346357', ['Yellow', 'Turquoise']),
+ '18221': ('#2b1f31', '#413d65', '#5fb9b0', '#bef992', ['Black', 'Purple', 'Turquoise', 'Green', 'Dark']),
+ '18914': ('#fbff7c', '#ffe35e', '#e4663a', '#92253f', ['Yellow', 'Orange', 'Red', 'Warm']),
+ '18473': ('#eb76ff', '#ffa8ec', '#ffccfc', '#fbffb1', ['Purple', 'Pink', 'Pink', 'Yellow', 'Bright']),
+ '18160': ('#283739', '#2c5d63', '#a9c52f', '#f7eebb', ['Black', 'Turquoise', 'Green', 'Yellow']),
+ '18085': ('#29d2e4', '#13829b', '#fcc29a', '#fde9c9', ['Blue', 'Turquoise', 'Orange']),
+ '16545': ('#26252c', '#e54861', '#f2a379', '#efd5b7', ['Black', 'Red', 'Orange', 'Orange']),
+ '18916': ('#e9f679', '#9bdf46', '#25a55f', '#346473', ['Yellow', 'Green', 'Blue']),
+ '17722': ('#a42127', '#c83b3b', '#ef9b59', '#fee785', ['Red', 'Orange', 'Yellow', 'Warm']),
+ '17117': ('#08d9d6', '#252a34', '#ff2e63', '#eaeaea', ['Turquoise', 'Black', 'Red', 'Grey']),
+ '17726': ('#e3dfc8', '#f5f1da', '#808c6c', '#fdac61', ['Brown', 'Green', 'Orange', 'Wedding', 'Autumn']),
+ '16615': ('#432f44', '#ea5455', '#a7425c', '#ffd460', ['Black', 'Red', 'Yellow']),
+ '19373': ('#fefea4', '#fed96b', '#fc92e3', '#ee7cff', ['Yellow', 'Pink']),
+ '16256': ('#27323a', '#435055', '#29a19c', '#a3f7bf', ['Black', 'Grey', 'Turquoise', 'Green', 'Dark']),
+ '17143': ('#e4f1fe', '#8dc6ff', '#22313f', '#34495e', ['Blue', 'Black', 'Cold']),
+ '17190': ('#902424', '#d9af5d', '#cede48', '#e9efba', ['Red', 'Orange', 'Yellow', 'Green', 'Christmas']),
+ '17001': ('#e4f68f', '#50c19a', '#686354', '#444036', ['Green', 'Brown']),
+ '16467': ('#2c2d34', '#e94822', '#f2910a', '#efd510', ['Black', 'Orange', 'Yellow', 'Warm']),
+ '15881': ('#3e1e68', '#583c87', '#e45a84', '#ffacac', ['Purple', 'Purple', 'Pink']),
+ '17826': ('#b2e672', '#fffd88', '#ffd478', '#f96b85', ['Green', 'Yellow', 'Red', 'Summer', 'Bright']),
+ '16765': ('#ff7676', '#f6f49d', '#5dae8b', '#466c95', ['Red', 'Yellow', 'Green', 'Blue']),
+ '15662': ('#260980', '#283996', '#3aa3c1', '#f6ffd2', ['Blue', 'Yellow', 'Cold']),
+ '17140': ('#fffcca', '#55e9bc', '#11d3bc', '#537780', ['Yellow', 'Green', 'Turquoise', 'Summer']),
+ '14886': ('#403121', '#a65e09', '#ed9728', '#faf494', ['Brown', 'Orange', 'Yellow', 'Warm', 'Gold']),
+ '16579': ('#88bef5', '#ba53de', '#f469a9', '#f4fa9c', ['Blue', 'Purple', 'Pink', 'Yellow']),
+ '15830': ('#364f6b', '#3fc1c9', '#f5f5f5', '#fc5185', ['Blue', 'Turquoise', 'Grey', 'Pink']),
+ '16617': ('#e6e6e6', '#fad662', '#e57b5c', '#be4747', ['Grey', 'Yellow', 'Orange', 'Red', 'Gold']),
+ '16255': ('#423737', '#5d5d5d', '#00adb5', '#a3f7bf', ['Grey', 'Blue', 'Green']),
+ '15697': ('#e23e57', '#88304e', '#522546', '#311d3f', ['Red', 'Purple']),
+ '15541': ('#f8f8f8', '#faebcd', '#f7c873', '#434343', ['Grey', 'Yellow', 'Black', 'Gold']),
+ '14881': ('#303841', '#47555e', '#7aa5d2', '#eeeeee', ['Black', 'Grey', 'Blue', 'Cold']),
+ '14832': ('#e4f9f5', '#30e3ca', '#11999e', '#40514e', ['Turquoise', 'Grey', 'Cold']),
+ '15473': ('#57385c', '#a75265', '#ec7263', '#febe7e', ['Purple', 'Orange', 'Vintage', 'Warm']),
+ '15211': ('#ffee7d', '#534c98', '#b767ff', '#44fadd', ['Yellow', 'Purple', 'Purple', 'Turquoise']),
+ '15458': ('#222831', '#393e46', '#ff5722', '#eeeeee', ['Black', 'Grey', 'Orange']),
+ '14587': ('#bb2253', '#ec185d', '#ff9171', '#ffb383', ['Red', 'Orange']),
+ '13930': ('#2bcdc1', '#38817a', '#393e46', '#f66095', ['Turquoise', 'Grey', 'Pink']),
+ '13136': ('#f7fdb6', '#a4d792', '#21825c', '#424141', ['Yellow', 'Green']),
+ '12715': ('#fef0ff', '#d6c8ff', '#c79ecf', '#7e6bc4', ['Pink', 'Pink', 'Purple', 'Purple']),
+ '12370': ('#f78536', '#dfebed', '#497285', '#2b4450', ['Orange', 'Blue', 'Turquoise']),
+ '14114': ('#3ec1d3', '#f6f7d7', '#ff9a00', '#ff165d', ['Blue', 'Yellow', 'Orange', 'Red']),
+ '13933': ('#4a304d', '#b17179', '#ffb37b', '#fff199', ['Purple', 'Orange', 'Yellow', 'Sunset', 'Warm']),
+ '14339': ('#fce38a', '#0e5f76', '#083d56', '#0c2233', ['Yellow', 'Blue', 'Black']),
+ '13712': ('#4d606e', '#3fbac2', '#d3d4d8', '#f5f5f5', ['Blue', 'Grey', 'Grey', 'Cold']),
+ '14963': ('#ffef6f', '#ff9757', '#d84545', '#7b3030', ['Yellow', 'Orange', 'Red', 'Brown', 'Warm']),
+ '10150': ('#e5fcc2', '#9de0ad', '#45ada8', '#547980', ['Green', 'Turquoise']),
+ '14818': ('#ff5a5a', '#ffb072', '#f9ffa5', '#aabbff', ['Red', 'Orange', 'Yellow', 'Blue']),
+ '13607': ('#9bb899', '#fcceaa', '#f5827d', '#ea4961', ['Green', 'Orange', 'Red']),
+ '14684': ('#23425f', '#a64942', '#ff7844', '#ffab5e', ['Blue', 'Brown', 'Orange', 'Warm']),
+ '12509': ('#106ee8', '#0fc1a1', '#90e0ab', '#cbffce', ['Blue', 'Turquoise', 'Green']),
+ '14490': ('#eff2dd', '#fcda05', '#ee4848', '#5c3551', ['Grey', 'Yellow', 'Red', 'Purple']),
+ '12508': ('#5d414d', '#7e858b', '#abd4c1', '#e5f6c6', ['Brown', 'Grey', 'Green', 'Yellow']),
+ '13096': ('#222832', '#2f3847', '#e7a117', '#c57f1e', ['Black', 'Grey', 'Orange', 'Brown']),
+ '11346': ('#2be5a6', '#b5ffc7', '#f37ef9', '#904ca7', ['Green', 'Pink', 'Purple']),
+ '13941': ('#fbef7c', '#f1ac59', '#c93737', '#ff6898', ['Yellow', 'Orange', 'Red', 'Pink']),
+ '13837': ('#331940', '#5e366a', '#0cca98', '#00ffcc', ['Black', 'Purple', 'Turquoise', 'Retro']),
+ '14207': ('#fffd75', '#60e550', '#3b6ac0', '#6e3274', ['Yellow', 'Green', 'Blue', 'Purple']),
+ '12457': ('#cefff1', '#ace7ef', '#a6acec', '#a56cc1', ['Turquoise', 'Blue', 'Purple', 'Cold']),
+ '13313': ('#2a363b', '#e84a5f', '#ff847c', '#fecea8', ['Black', 'Red', 'Red', 'Orange']),
+ '13305': ('#e3e7b3', '#f6ffe2', '#e4ce8e', '#d77948', ['Yellow', 'Brown', 'Orange']),
+ '12461': ('#38486f', '#584f84', '#876a96', '#d7c1e0', ['Purple']),
+ '11752': ('#0278ae', '#51dacf', '#9ef5cf', '#e8ffc1', ['Blue', 'Turquoise', 'Yellow']),
+ '13139': ('#e14242', '#8d3434', '#eacd65', '#ebebcd', ['Red', 'Red', 'Orange', 'Yellow']),
+ '11685': ('#fff395', '#7459dc', '#41b3ff', '#63f5ef', ['Yellow', 'Purple', 'Blue', 'Turquoise']),
+ '12081': ('#ffc8c8', '#ff9999', '#444f5a', '#3e4149', ['Pink', 'Black']),
+ '9409': ('#ffde74', '#ffa974', '#ff715a', '#ff3757', ['Yellow', 'Orange', 'Orange', 'Red']),
+ '10701': ('#1a2f4b', '#28475c', '#2f8886', '#84c69b', ['Turquoise', 'Green']),
+ '11196': ('#faee5a', '#e4fcf9', '#ace6f6', '#4b89ac', ['Yellow', 'Blue']),
+ '12280': ('#f8e796', '#c98b70', '#635270', '#363863', ['Yellow', 'Orange', 'Purple']),
+ '9385': ('#d8fff1', '#78e4d4', '#b485d8', '#5b73a7', ['Turquoise', 'Purple', 'Blue']),
+ '11000': ('#f1f1f1', '#ff41ed', '#8109b7', '#0c1845', ['Grey', 'Pink', 'Purple', 'Black']),
+ '10468': ('#f1fafb', '#a0e4f1', '#7ea6f4', '#4a4de7', ['Blue', 'Cold', 'Wedding']),
+ '11994': ('#fe7847', '#ca2c3f', '#a21738', '#4c0b2f', ['Orange', 'Red']),
+ '9375': ('#d4ffa3', '#00d8b1', '#1f9ec7', '#3f7a9c', ['Green', 'Turquoise', 'Blue']),
+ '9353': ('#ff5ab0', '#f7fed4', '#4df4ff', '#1bb5ec', ['Pink', 'Yellow', 'Blue', 'Blue']),
+ '8656': ('#152a38', '#29435c', '#556e53', '#d1d4c9', ['Black', 'Blue', 'Green', 'Grey', 'Dark']),
+ '9544': ('#dd4747', '#ed6d54', '#ffbe5b', '#ffe559', ['Orange', 'Yellow']),
+ '11237': ('#a3f7bf', '#29a19c', '#4b6289', '#60316e', ['Turquoise', 'Green', 'Blue', 'Purple']),
+ '11343': ('#feffcb', '#ffb576', '#ff6b83', '#c6394d', ['Yellow', 'Orange', 'Red']),
+ '9416': ('#3b5f41', '#66a96b', '#98e19a', '#c5f5c2', ['Green', 'Green', 'Green', 'Green']),
+ '10697': ('#f8c957', '#ecf0f1', '#3498db', '#34495e', ['Yellow', 'Grey', 'Blue', 'Blue']),
+ '10953': ('#a561ff', '#fd72ad', '#fcce9e', '#cfe3ff', ['Purple', 'Pink', 'Orange', 'Blue']),
+ '10792': ('#303841', '#3a4750', '#00adb5', '#eeeeee', ['Black', 'Turquoise', 'Grey', 'Dark']),
+ '10119': ('#37b7b5', '#a0e4e0', '#c7f6f5', '#f6b132', ['Turquoise', 'Orange']),
+ '9970': ('#ffee7d', '#b767ff', '#534c98', '#44fadd', ['Yellow', 'Purple', 'Purple', 'Turquoise']),
+ '9501': ('#ee0e51', '#e4dcef', '#505458', '#363540', ['Red', 'Pink', 'Grey', 'Black']),
+ '8169': ('#004182', '#118df0', '#fbffa3', '#ff4b68', ['Blue', 'Blue', 'Yellow', 'Red']),
+ '8863': ('#faf6ed', '#f6bf4f', '#a2453d', '#aaaaaa', ['Yellow', 'Orange', 'Brown', 'Grey', 'Autumn', 'Gold']),
+ '10225': ('#3d6271', '#3d899c', '#45a298', '#d8f8b7', ['Blue', 'Turquoise', 'Green']),
+ '9214': ('#9bcb3c', '#eff669', '#f29f3d', '#cf3333', ['Green', 'Yellow', 'Orange', 'Red', 'Summer']),
+ '8025': ('#73f7dd', '#2cc4cb', '#1972a4', '#2e3a87', ['Turquoise', 'Blue']),
+ '8765': ('#fcf5b8', '#b4cd93', '#427a5b', '#403f3f', ['Yellow', 'Green', 'Grey']),
+ '9834': ('#fcff89', '#fe7187', '#ca4b7c', '#6e386e', ['Yellow', 'Pink', 'Purple', 'Purple']),
+ '9148': ('#f33535', '#d8e9f0', '#33425b', '#29252c', ['Red', 'Blue', 'Black']),
+ '9506': ('#00b8a9', '#f8f3d4', '#f6416c', '#ffde7d', ['Turquoise', 'Yellow', 'Red']),
+ '9522': ('#433751', '#2f576e', '#748b9c', '#f0e3e3', ['Purple', 'Turquoise', 'Grey', 'Pink']),
+ '9585': ('#990000', '#ff6600', '#c1d343', '#f7f7cf', ['Red', 'Orange', 'Green', 'Yellow', 'Autumn', 'Retro', 'Christmas']),
+ '8306': ('#feff94', '#ad64c5', '#83d9ef', '#bcfff2', ['Yellow', 'Purple', 'Blue']),
+ '9140': ('#ffb400', '#fffbe0', '#2994b2', '#474744', ['Orange', 'Yellow', 'Blue', 'Grey']),
+ '8168': ('#0278ae', '#51dacf', '#9ef5cf', '#e8ffb1', ['Blue', 'Turquoise', 'Yellow']),
+ '9474': ('#f64662', '#c61951', '#741938', '#56132a', ['Red']),
+ '9084': ('#2185d5', '#3a4750', '#303841', '#f3f3f3', ['Blue', 'Grey', 'Black', 'Grey']),
+ '8283': ('#f4f7f7', '#aacfd0', '#79a8a9', '#1f4e5f', ['Grey', 'Turquoise', 'Blue']),
+ '8529': ('#83ffe1', '#7045ff', '#c768ff', '#ffaded', ['Turquoise', 'Purple', 'Pink']),
+ '9264': ('#ffe165', '#de4242', '#84243b', '#412135', ['Yellow', 'Red', 'Black']),
+ '8016': ('#d4ed9d', '#64a97b', '#3a5465', '#3d3931', ['Green', 'Green', 'Blue', 'Black']),
+ '8941': ('#2fc5cc', '#6df1cc', '#e3ffc3', '#ff89c0', ['Turquoise', 'Pink', 'Bright']),
+ '8860': ('#fcefed', '#6173f4', '#3b2e40', '#f35e3e', ['Pink', 'Blue', 'Black', 'Orange', 'Retro']),
+ '8011': ('#bef2eb', '#6dc995', '#3a91aa', '#6b4897', ['Blue', 'Green', 'Turquoise', 'Purple']),
+ '8835': ('#913131', '#e5ab39', '#c2ff6b', '#a7da46', ['Red', 'Orange', 'Green', 'Green']),
+ '8182': ('#7b99fa', '#53cdd8', '#96eab7', '#f1f3b8', ['Blue', 'Turquoise', 'Green', 'Yellow']),
+ '8634': ('#152a38', '#2f5241', '#d6cfb9', '#e4e5db', ['Green', 'Grey', 'Wedding']),
+ '8328': ('#a8d8ea', '#aa96da', '#fcbad3', '#ffffd2', ['Blue', 'Purple', 'Pink', 'Yellow']),
+ '8321': ('#f06161', '#eb786b', '#f3a871', '#e9ec82', ['Red', 'Orange', 'Yellow', 'Warm']),
+ '8015': ('#081f37', '#5fc9f3', '#2e79ba', '#1e549f', ['Black', 'Blue']),
+ '8303': ('#b2085d', '#f9c11c', '#0d8549', '#3a3d44', ['Yellow', 'Green']),
+ '8350': ('#dbd8e3', '#5c5470', '#352f44', '#2a2438', ['Grey', 'Purple', 'Black', 'Dark']),
+ '7642': ('#f38181', '#fce38a', '#eaffd0', '#95e1d3', ['Red', 'Yellow', 'Blue']),
+ '8171': ('#35013f', '#561050', '#951556', '#e9b5d2', ['Purple', 'Pink', 'Wedding']),
+ '7635': ('#c8f0f0', '#86d8dc', '#7047a3', '#3a276a', ['Blue', 'Purple']),
+ '8043': ('#fbe0d8', '#4d727e', '#283644', '#7a6552', ['Pink', 'Turquoise', 'Brown', 'Vintage', 'Wedding']),
+ '8123': ('#f6ea8c', '#f26d5b', '#c03546', '#492540', ['Yellow', 'Orange', 'Red', 'Purple', 'Warm']),
+ '7956': ('#155674', '#60beb3', '#79f8bb', '#f5ffae', ['Blue', 'Turquoise', 'Green', 'Yellow']),
+ '8029': ('#eeeeee', '#ff9966', '#e52b50', '#9c2542', ['Grey', 'Orange', 'Red']),
+ '8012': ('#b9bc6d', '#ffe894', '#ef765f', '#95415a', ['Green', 'Yellow', 'Orange']),
+ '8013': ('#353b6e', '#252243', '#74deed', '#9365db', ['Blue', 'Blue', 'Turquoise', 'Purple']),
+ '7938': ('#eeccb4', '#d83c65', '#4f1567', '#604cc3', ['Orange', 'Red', 'Purple']),
+ '8001': ('#f0d394', '#98651e', '#6e4b1f', '#533710', ['Brown']),
+ '7817': ('#3498db', '#ecf0f1', '#34495e', '#f1c40f', ['Blue', 'Grey', 'Orange']),
+ '7968': ('#ff004d', '#9d0b28', '#5a082d', '#33030d', ['Red', 'Purple', 'Black', 'Dark']),
+ '7908': ('#a03232', '#c86f5e', '#e6c073', '#fffeb8', ['Red', 'Red', 'Brown', 'Yellow']),
+ '7919': ('#f7f373', '#65d269', '#2d8b7d', '#2f64a3', ['Yellow', 'Green', 'Turquoise', 'Blue']),
+ '7639': ('#db5ca6', '#942e88', '#f9cc6a', '#fcff88', ['Pink', 'Purple', 'Yellow', 'Yellow']),
+ '7638': ('#43bfc7', '#69e9f5', '#645fce', '#40356f', ['Turquoise', 'Blue', 'Purple']),
+ '7636': ('#ffe0a3', '#e18237', '#943939', '#6a2634', ['Yellow', 'Orange', 'Red', 'Autumn', 'Halloween']),
+ '7637': ('#59b791', '#83f084', '#f3ffa1', '#f1d665', ['Green', 'Green', 'Yellow', 'Yellow']),
+ '7640': ('#6ea7c1', '#6b55ae', '#e67fa2', '#ffefa1', ['Turquoise', 'Purple', 'Pink', 'Yellow']),
+ '7641': ('#e4f5e5', '#a6dfde', '#88a6e5', '#8d6ec8', ['Green', 'Turquoise', 'Blue', 'Purple']),
+ '7659': ('#feff94', '#ad64c5', '#88d8ec', '#bcfff2', ['Yellow', 'Purple', 'Blue']),
+ '7634': ('#f0f08e', '#91ca62', '#478077', '#3a4874', ['Yellow', 'Green', 'Turquoise', 'Blue']),
+ '7403': ('#0b88a8', '#a6dc8c', '#dfeb95', '#095062', ['Blue', 'Green', 'Yellow']),
+ '7223': ('#5c4b77', '#6990e4', '#b145ad', '#f6a2d4', ['Purple', 'Blue', 'Pink']),
+ '6843': ('#894949', '#b2704e', '#cd9d77', '#fcc0c0', ['Brown', 'Orange', 'Pink', 'Autumn']),
+ '7555': ('#f2676a', '#fbe087', '#ad2959', '#62013c', ['Red', 'Yellow', 'Purple', 'Purple']),
+ '7429': ('#bef2ff', '#4f7097', '#93a7d1', '#1bf5af', ['Blue', 'Green', 'Retro']),
+ '7422': ('#241023', '#883c82', '#b7569a', '#ffbf00', ['Black', 'Purple', 'Orange']),
+ '7187': ('#217756', '#63b75d', '#b0d553', '#fced25', ['Green', 'Yellow']),
+ '7469': ('#b074e9', '#e09ee8', '#f6e97f', '#f3f74d', ['Purple', 'Purple', 'Yellow', 'Yellow']),
+ '6941': ('#2e3837', '#166678', '#7db9b3', '#e1f6f4', ['Turquoise', 'Cold']),
+ '7431': ('#cc0500', '#ef2f2a', '#ef832a', '#efac2a', ['Red', 'Orange']),
+ '7355': ('#422b72', '#266d98', '#3cb29a', '#c4f080', ['Purple', 'Blue', 'Turquoise', 'Green']),
+ '7277': ('#2c5460', '#bbdc2f', '#61b136', '#cbe0e0', ['Green', 'Grey']),
+ '7247': ('#2d4059', '#ea5455', '#f07b3f', '#ffd460', ['Red', 'Orange', 'Yellow', 'Warm']),
+ '6577': ('#430d27', '#582233', '#713045', '#c94e4e', ['Purple', 'Brown']),
+ '6496': ('#5585b5', '#53a8b6', '#79c2d0', '#bbe4e9', ['Blue', 'Turquoise']),
+ '7195': ('#118df0', '#0e2f56', '#ff304f', '#ececda', ['Blue', 'Blue', 'Red', 'Grey']),
+ '6679': ('#b7b9f4', '#5254d8', '#192294', '#000278', ['Purple', 'Blue']),
+ '7129': ('#552e5a', '#cf7979', '#f6e198', '#ecffa3', ['Purple', 'Orange', 'Yellow', 'Yellow']),
+ '7128': ('#853e3e', '#c15757', '#ead27a', '#f7f79b', ['Brown', 'Red', 'Yellow']),
+ '6482': ('#b9dbe6', '#5f818a', '#36595f', '#304852', ['Blue', 'Grey']),
+ '6917': ('#00c3ff', '#b463a6', '#5c4978', '#3b475e', ['Blue', 'Purple']),
+ '6362': ('#4cb3cd', '#52d6d3', '#5968b1', '#302579', ['Blue', 'Turquoise', 'Purple']),
+ '6749': ('#41646e', '#4e7376', '#c2be53', '#e4e1b0', ['Turquoise', 'Green', 'Brown']),
+ '6998': ('#f06868', '#fab57a', '#edf798', '#80d6ff', ['Red', 'Orange', 'Yellow', 'Blue', 'Summer']),
+ '6850': ('#ebedc8', '#9ab5c1', '#74698c', '#c1867b', ['Pastel']),
+ '6837': ('#ef5353', '#b84040', '#dbee7b', '#e2c85b', ['Red', 'Yellow']),
+ '5986': ('#66e1b4', '#006159', '#00796f', '#009589', ['Turquoise', 'Green', 'Green', 'Green']),
+ '6158': ('#352f44', '#2a2438', '#411e8f', '#310a5d', ['Black', 'Purple', 'Dark']),
+ '5271': ('#2f3c4f', '#506f86', '#fbb040', '#de703c', ['Blue', 'Orange']),
+ '6770': ('#aa1111', '#b15858', '#f2c280', '#fcf8a6', ['Red', 'Red', 'Orange', 'Yellow']),
+ '6644': ('#068b78', '#9ed79a', '#f2ff97', '#ffcf5e', ['Green', 'Turquoise', 'Yellow', 'Orange']),
+ '6713': ('#002c6a', '#e45171', '#f8a79b', '#f8d99b', ['Blue', 'Red', 'Pink', 'Yellow']),
+ '6379': ('#793b89', '#be2490', '#e5a0dc', '#e9bbe5', ['Purple', 'Purple', 'Pink', 'Pink']),
+ '6186': ('#f3cba5', '#975a5e', '#453953', '#25161b', ['Brown', 'Black', 'Vintage']),
+ '6588': ('#00a388', '#79bd8f', '#beeb9f', '#ffff9d', ['Green', 'Yellow']),
+ '6494': ('#333644', '#84577c', '#c65f63', '#e1bf7f', ['Black', 'Purple', 'Red', 'Yellow']),
+ '5334': ('#397298', '#8ac4ff', '#9179ef', '#7b417d', ['Blue', 'Blue', 'Purple', 'Purple']),
+ '6156': ('#54447b', '#49b47e', '#94dd4d', '#ffd944', ['Purple', 'Green', 'Yellow', 'Retro']),
+ '5895': ('#f3ff92', '#f6ce59', '#2e8fc6', '#56cfd2', ['Yellow', 'Orange', 'Blue', 'Turquoise']),
+ '6324': ('#827055', '#a79e8b', '#d4ceb0', '#ede7cf', ['Brown', 'Grey']),
+ '6303': ('#dcdada', '#d869c0', '#fffd8c', '#ffbd59', ['Grey', 'Purple', 'Yellow', 'Orange']),
+ '6178': ('#f0f0ef', '#edd690', '#b1bd5d', '#955a47', ['Grey', 'Orange', 'Green', 'Brown']),
+ '4175': ('#6b62ce', '#372e96', '#2f99ad', '#84efe2', ['Blue', 'Turquoise']),
+ '6131': ('#001f3f', '#083358', '#0d63a5', '#ffd717', ['Blue', 'Yellow']),
+ '6116': ('#d15260', '#e95c63', '#ff9d7b', '#f2f089', ['Red', 'Orange', 'Yellow']),
+ '6053': ('#152744', '#367591', '#61d2b4', '#9dfdc7', ['Blue', 'Turquoise', 'Green']),
+ '6054': ('#61bbb6', '#a1dfff', '#ad56cd', '#4a3b85', ['Turquoise', 'Blue', 'Purple']),
+ '5582': ('#fffac0', '#ffd79a', '#73b9d7', '#9de6e8', ['Yellow', 'Orange', 'Blue', 'Blue']),
+ '5979': ('#761a1a', '#c13131', '#a7cd78', '#fff279', ['Red', 'Green', 'Yellow', 'Christmas']),
+ '5594': ('#1b0044', '#5727a3', '#9153f4', '#d6c5f0', ['Purple', 'Purple', 'Purple', 'Purple']),
+ '5896': ('#f4f787', '#85eb4e', '#32c38c', '#3f84ac', ['Yellow', 'Green', 'Blue']),
+ '5712': ('#da5c53', '#a8e4b1', '#4aa3ba', '#306d75', ['Red', 'Green', 'Blue']),
+ '5831': ('#3d065a', '#b51a62', '#70d4b4', '#ddddc7', ['Purple', 'Turquoise']),
+ '5656': ('#80a3a2', '#abcecf', '#c4dce0', '#daf4f5', ['Grey', 'Blue']),
+ '5512': ('#fff07a', '#d69830', '#ab3124', '#5f233f', ['Yellow', 'Orange', 'Red', 'Purple', 'Gold']),
+ '5563': ('#a21232', '#1a1831', '#20615b', '#dece9c', ['Red', 'Black', 'Turquoise', 'Retro']),
+ '5335': ('#449187', '#91e4a6', '#5f64c0', '#453064', ['Green', 'Blue']),
+ '5485': ('#f35f5f', '#cc435f', '#f1ea65', '#36a3eb', ['Red', 'Yellow', 'Blue']),
+ '5389': ('#442d7c', '#6341b4', '#f85aca', '#dafa8b', ['Purple', 'Pink', 'Green']),
+ '5429': ('#51af5b', '#b3e55e', '#feed30', '#ffcb3c', ['Green', 'Yellow', 'Orange']),
+ '5240': ('#7696db', '#562d7d', '#ae427b', '#ff8a98', ['Blue', 'Purple', 'Pink']),
+ '5242': ('#80c0ce', '#467292', '#9adea2', '#c2f69b', ['Blue', 'Blue', 'Green', 'Green']),
+ '5308': ('#83afa6', '#58727f', '#e5e5e5', '#d3a284', ['Turquoise', 'Grey', 'Brown']),
+ '2763': ('#222831', '#393e46', '#00adb5', '#eeeeee', ['Black', 'Grey', 'Turquoise', 'Dark']),
+ '5337': ('#f3f2c9', '#f0d587', '#93af56', '#336371', ['Yellow', 'Green', 'Turquoise']),
+ '5272': ('#363b4e', '#4f3b78', '#927fbf', '#c4bbf0', ['Black', 'Purple', 'Dark']),
+ '5336': ('#e25d4e', '#a93545', '#d9528b', '#ff92e8', ['Red', 'Pink']),
+ '5239': ('#523f79', '#807be4', '#73cff0', '#afffea', ['Purple', 'Turquoise', 'Blue', 'Green']),
+ '5241': ('#eaf887', '#79dc96', '#3bbbb3', '#377aaf', ['Yellow', 'Green', 'Turquoise', 'Blue']),
+ '5243': ('#ff8a69', '#f06161', '#bb4272', '#7a3476', ['Orange', 'Red', 'Purple']),
+ '5246': ('#f6f982', '#d9d46f', '#fa5862', '#c64272', ['Yellow', 'Yellow', 'Red']),
+ '4994': ('#f6f6d9', '#47e4e0', '#5f81e4', '#f67ff5', ['Yellow', 'Turquoise', 'Blue', 'Pink']),
+ '5044': ('#51af5b', '#b3e55e', '#f7ffa3', '#dddb6a', ['Green', 'Yellow']),
+ '5091': ('#f8aa27', '#fac55b', '#fff8b6', '#20655f', ['Orange', 'Yellow', 'Turquoise', 'Summer', 'Gold']),
+ '5163': ('#f9f3cf', '#ede7cf', '#ddbc89', '#aa512f', ['Yellow', 'Brown']),
+ '5125': ('#89fad0', '#4ec9e1', '#6796e5', '#228291', ['Turquoise', 'Blue']),
+ '5124': ('#288fb4', '#1d556f', '#efddb2', '#fa360a', ['Blue', 'Yellow', 'Red']),
+ '5132': ('#ff6464', '#ffbd67', '#f8fe85', '#5be7a9', ['Red', 'Orange', 'Yellow', 'Green']),
+ '4343': ('#d9dad7', '#c24d2c', '#3e4a61', '#1a2639', ['Grey', 'Orange', 'Blue', 'Winter']),
+ '4900': ('#c6f1a2', '#a8d966', '#43a367', '#385380', ['Green', 'Blue']),
+ '4973': ('#f7f5b2', '#bad4f9', '#5e89ef', '#352771', ['Yellow', 'Purple', 'Blue', 'Blue']),
+ '4899': ('#6a2e2e', '#cd5a5a', '#ffcf68', '#eff6a5', ['Brown', 'Red', 'Yellow', 'Warm']),
+ '4901': ('#f46188', '#491d7f', '#642ab6', '#7779ff', ['Pink', 'Purple', 'Purple', 'Blue']),
+ '4902': ('#489cc1', '#74f6a7', '#43a680', '#236969', ['Blue', 'Green']),
+ '4910': ('#062925', '#044a42', '#3a9188', '#b8e1dd', ['Green', 'Turquoise', 'Cold']),
+ '4733': ('#a099ff', '#5a67a6', '#fcb241', '#d68d08', ['Purple', 'Orange']),
+ '4802': ('#96cd39', '#f5ff65', '#ffba47', '#ff5b44', ['Green', 'Yellow', 'Orange', 'Red', 'Summer', 'Bright']),
+ '4803': ('#293462', '#211a4c', '#f33535', '#a51c2d', ['Blue', 'Red']),
+ '4804': ('#243d44', '#167a8b', '#2dea8f', '#24b273', ['Turquoise', 'Green']),
+ '4281': ('#9a60c1', '#ac92fa', '#96ebf0', '#48c3be', ['Purple', 'Turquoise']),
+ '4698': ('#563761', '#a7425c', '#f3825f', '#ffe26f', ['Purple', 'Orange', 'Yellow']),
+ '4464': ('#f2eb80', '#a2bf39', '#2685bf', '#144673', ['Yellow', 'Green', 'Blue']),
+ '4622': ('#1c0c2a', '#343b99', '#61bdf6', '#9affdc', ['Black', 'Blue', 'Turquoise']),
+ '4282': ('#8e334c', '#ec9454', '#f1f08a', '#c6cd78', ['Purple', 'Orange', 'Yellow']),
+ '4461': ('#0c2233', '#065471', '#0a91ab', '#ffc045', ['Black', 'Blue', 'Orange', 'Dark']),
+ '4581': ('#f7dead', '#cd4439', '#72b896', '#6f7777', ['Yellow', 'Red', 'Green', 'Grey', 'Retro']),
+ '4515': ('#f7f4ea', '#9ce3cf', '#6a7ff5', '#574b9b', ['Grey', 'Turquoise', 'Blue', 'Wedding', 'Retro']),
+ '4260': ('#b7569a', '#883c82', '#e4f091', '#f9cd76', ['Purple', 'Purple', 'Yellow', 'Orange']),
+ '3881': ('#f1efe9', '#beceb0', '#34857f', '#b0a48a', ['Grey', 'Green', 'Brown', 'Turquoise', 'Winter']),
+ '4535': ('#e0fffb', '#29cdb5', '#008698', '#f39c9c', ['Blue', 'Turquoise', 'Pink']),
+ '4390': ('#ffb19b', '#f66060', '#9a2c80', '#551863', ['Pink', 'Orange', 'Purple', 'Purple']),
+ '4337': ('#620808', '#a53f3f', '#f4ce74', '#ffe9c1', ['Brown', 'Brown', 'Yellow', 'Yellow']),
+ '4285': ('#80ef91', '#4ba54d', '#f3ef82', '#f0c15a', ['Green', 'Green', 'Yellow', 'Orange']),
+ '4371': ('#f0e9ff', '#cea9ff', '#b346ff', '#545454', ['Purple', 'Purple', 'Grey']),
+ '4125': ('#302a77', '#5457a6', '#eebb55', '#f1e6d1', ['Blue', 'Blue', 'Orange', 'Yellow']),
+ '4319': ('#3b939b', '#2f8189', '#91f3fc', '#c9fbff', ['Turquoise', 'Blue']),
+ '4259': ('#80e5e9', '#7d77f6', '#793e71', '#e471a7', ['Turquoise', 'Blue', 'Purple', 'Pink']),
+ '4174': ('#ffe180', '#eba059', '#8b3c76', '#41245c', ['Yellow', 'Orange', 'Purple', 'Purple']),
+ '4176': ('#f0f87f', '#4bc87f', '#29668b', '#6eaff7', ['Yellow', 'Green', 'Blue']),
+ '4177': ('#85203b', '#cb3b3b', '#e0c45c', '#fff98c', ['Red', 'Yellow']),
+ '4071': ('#ff5335', '#dfe0d4', '#3e92a3', '#353940', ['Orange', 'Grey', 'Turquoise', 'Black']),
+ '3287': ('#055049', '#faf35e', '#069a8e', '#a1e3d8', ['Green', 'Yellow', 'Turquoise']),
+ '4111': ('#000033', '#0066cc', '#0099ff', '#ededed', ['Black', 'Blue', 'Grey']),
+ '3807': ('#fffbe3', '#ffa9a9', '#6a425c', '#26271a', ['Yellow', 'Pink', 'Purple', 'Brown']),
+ '3661': ('#1b515e', '#338275', '#88b990', '#abcd9e', ['Green']),
+ '4038': ('#04879c', '#0c3c78', '#090030', '#f30a49', ['Turquoise', 'Blue', 'Black', 'Red', 'Dark']),
+ '3907': ('#d14848', '#ec952e', '#f0e449', '#d6f7f8', ['Red', 'Orange', 'Yellow']),
+ '4057': ('#272e6e', '#ffffc3', '#ffc55c', '#e95d35', ['Blue', 'Yellow', 'Orange', 'Orange']),
+ '3942': ('#f2f1a7', '#ef5959', '#b43144', '#88a9f7', ['Yellow', 'Red', 'Blue', 'Summer']),
+ '3890': ('#f1f5bc', '#fecb92', '#f99a9a', '#d1f6a4', ['Yellow', 'Orange', 'Pink', 'Green']),
+ '3454': ('#335c49', '#678c40', '#bdbe36', '#e5dd90', ['Green', 'Yellow']),
+ '3943': ('#8aacff', '#6151bb', '#d7f096', '#67ba6d', ['Blue', 'Green']),
+ '3792': ('#5d697a', '#383838', '#f66b34', '#f2d639', ['Grey', 'Black', 'Orange', 'Yellow']),
+ '3780': ('#06cdff', '#8200ff', '#470c85', '#18134c', ['Blue', 'Purple', 'Purple', 'Black']),
+ '3167': ('#824c96', '#433466', '#ffaf4f', '#ed733f', ['Purple', 'Orange']),
+ '3740': ('#2b3964', '#3482aa', '#6db3b5', '#f9cc7b', ['Blue', 'Turquoise', 'Orange']),
+ '3781': ('#f4e022', '#5a37c3', '#18224b', '#de1b4a', ['Yellow', 'Purple', 'Black', 'Red']),
+ '3574': ('#47d0bd', '#daec8b', '#fffdd6', '#ff5da2', ['Turquoise', 'Green', 'Yellow', 'Pink']),
+ '3459': ('#ccf62c', '#98c74e', '#60a261', '#357a5b', ['Green']),
+ '3642': ('#f0dca2', '#e0b58c', '#cd7856', '#b5421e', ['Orange', 'Yellow', 'Brown']),
+ '3604': ('#ff304f', '#002651', '#775ada', '#28c7fa', ['Red', 'Blue', 'Purple']),
+ '3656': ('#ff6d3f', '#b14b4b', '#594057', '#36162e', ['Orange', 'Red', 'Purple', 'Brown', 'Halloween']),
+ '3452': ('#4ac3be', '#a3dec9', '#e6efbf', '#faac64', ['Turquoise', 'Orange']),
+ '3460': ('#eb586f', '#d8e9f0', '#4aa0d5', '#454553', ['Red', 'Blue', 'Blue', 'Grey']),
+ '3666': ('#ffea66', '#f59159', '#c75080', '#6b206a', ['Yellow', 'Orange', 'Purple']),
+ '3667': ('#776ae3', '#88e570', '#fbff67', '#ffb44a', ['Purple', 'Green', 'Yellow', 'Orange']),
+ '3267': ('#d1dbbd', '#91aa9d', '#3e606f', '#193441', ['Turquoise', 'Grey']),
+ '3590': ('#3d5a59', '#9aebdd', '#367db5', '#313e86', ['Turquoise', 'Blue', 'Blue', 'Blue']),
+ '3589': ('#ffe390', '#ff926b', '#ff4a4a', '#a83c54', ['Yellow', 'Orange', 'Red']),
+ '3538': ('#d5441c', '#013c4d', '#9dd5cb', '#f3e5b1', ['Orange', 'Blue', 'Yellow']),
+ '3530': ('#f7fa86', '#76e7c7', '#9e7eff', '#9c4b9e', ['Yellow', 'Turquoise', 'Purple']),
+ '3528': ('#0d7685', '#084d68', '#69c181', '#ccf186', ['Turquoise', 'Green']),
+ '3527': ('#fdf3f3', '#f8e7e7', '#a070a1', '#724060', ['Pink', 'Purple']),
+ '3328': ('#957541', '#be9639', '#fccf5b', '#dde9eb', ['Brown', 'Yellow', 'Grey', 'Autumn', 'Gold']),
+ '3435': ('#7c6fff', '#5ca9ff', '#fcff90', '#ffde68', ['Purple', 'Blue', 'Yellow', 'Summer']),
+ '3449': ('#3b5441', '#83e85a', '#2cb978', '#107a8b', ['Green', 'Green', 'Green', 'Turquoise']),
+ '3063': ('#c2ffff', '#8bdeff', '#a888ff', '#26466f', ['Blue', 'Purple']),
+ '3269': ('#fadb3f', '#ecf7c5', '#ea5656', '#27332d', ['Yellow', 'Red', 'Black']),
+ '2978': ('#bdd8f1', '#82a6cb', '#3667a6', '#214177', ['Blue']),
+ '3373': ('#d8b5de', '#f9f1bf', '#f3b75b', '#cc7f2a', ['Purple', 'Yellow', 'Orange', 'Gold']),
+ '3382': ('#ffc7c7', '#dc7646', '#a45c5c', '#6c476e', ['Pink', 'Orange', 'Brown', 'Purple']),
+ '3383': ('#515661', '#2e9f82', '#68c170', '#d6ec8c', ['Grey', 'Turquoise', 'Green']),
+ '3177': ('#fdfbda', '#d3d0a8', '#819f7f', '#2d4659', ['Yellow', 'Green']),
+ '3173': ('#e9e6c9', '#ca6144', '#566683', '#393e51', ['Orange', 'Blue']),
+ '3324': ('#c24242', '#e08932', '#e5c955', '#f2f5b1', ['Red', 'Orange', 'Yellow', 'Yellow']),
+ '3059': ('#80ffdb', '#55e0a3', '#5b70f3', '#4850b9', ['Turquoise', 'Green', 'Blue', 'Blue']),
+ '3060': ('#442b72', '#993d9a', '#8a6bf0', '#fedf96', ['Purple', 'Purple', 'Purple', 'Yellow']),
+ '3186': ('#d0f66a', '#36c186', '#158a8c', '#1e5287', ['Green', 'Green', 'Turquoise', 'Blue']),
+ '3213': ('#f7ebc9', '#f2cc96', '#814906', '#d35823', ['Yellow', 'Orange', 'Brown', 'Orange']),
+ '3062': ('#fba834', '#fce850', '#387adf', '#50c4ed', ['Orange', 'Yellow', 'Blue']),
+ '3168': ('#a8e0e1', '#5a96bb', '#75448c', '#c46caa', ['Blue', 'Purple']),
+ '2870': ('#5dacbd', '#24527a', '#a7bcb9', '#e0ebeb', ['Blue', 'Grey']),
+ '3043': ('#feed30', '#ff6868', '#924992', '#504077', ['Yellow', 'Red', 'Purple', 'Blue']),
+ '3065': ('#f5eb82', '#dfb361', '#d3775d', '#a75377', ['Yellow', 'Orange', 'Purple']),
+ '2937': ('#e4e4e4', '#41b3d3', '#61d2dc', '#444444', ['Grey', 'Blue']),
+ '2982': ('#a62671', '#db466b', '#f96c48', '#f5d773', ['Purple', 'Red', 'Orange', 'Yellow', 'Sunset']),
+ '3061': ('#1f3a52', '#41a186', '#8cca6e', '#d3f689', ['Turquoise', 'Green']),
+ '2562': ('#343434', '#055e68', '#62a388', '#b9d2d2', ['Black', 'Turquoise', 'Green', 'Grey', 'Dark']),
+ '2881': ('#062c80', '#0e6ac7', '#4fb9fc', '#f6f5da', ['Blue', 'Yellow']),
+ '2655': ('#ff9234', '#ffcd3c', '#fafcb4', '#b0db72', ['Orange', 'Yellow', 'Green', 'Gold']),
+ '2829': ('#eb2a5d', '#ff6f41', '#ffb44b', '#ffeb7d', ['Red', 'Orange', 'Orange', 'Yellow']),
+ '2707': ('#fffbb7', '#ffa849', '#68848b', '#4a2b13', ['Yellow', 'Orange', 'Blue', 'Brown']),
+ '2613': ('#5639a6', '#20236d', '#fa4848', '#ffe087', ['Blue', 'Red', 'Yellow']),
+ '2715': ('#1a2634', '#203e5f', '#ffcc00', '#fee5b1', ['Black', 'Blue', 'Yellow']),
+ '2814': ('#740021', '#8d0033', '#bd3246', '#fdc8aa', ['Red', 'Orange']),
+ '2314': ('#1d0251', '#019081', '#74cc7e', '#d2eba7', ['Purple', 'Turquoise', 'Green']),
+ '2661': ('#2f2342', '#e42f45', '#b42b3f', '#7ca0e5', ['Black', 'Red', 'Red', 'Blue']),
+ '2779': ('#4a2377', '#61529f', '#ba69de', '#f3e96d', ['Purple', 'Yellow', 'Wedding']),
+ '2738': ('#4ac6b7', '#4f5e7f', '#965f8a', '#ff7070', ['Turquoise', 'Blue', 'Purple', 'Orange']),
+ '2705': ('#ffedc6', '#ffc478', '#fff87d', '#724330', ['Orange', 'Orange', 'Yellow', 'Brown']),
+ '2485': ('#492b7b', '#301551', '#ed8a0a', '#f7d914', ['Purple', 'Orange', 'Yellow']),
+ '2555': ('#eadada', '#d59dc5', '#bf5caa', '#4d3a4d', ['Pink', 'Purple', 'Grey', 'Wedding']),
+ '2759': ('#114b5f', '#1a936f', '#88d498', '#f3e9d2', ['Turquoise', 'Green', 'Yellow']),
+ '2499': ('#303242', '#394359', '#f2be8d', '#ba6c65', ['Black', 'Red', 'Vintage']),
+ '2193': ('#483243', '#684184', '#cb73bb', '#f3c2cb', ['Purple', 'Pink']),
+ '2640': ('#e35454', '#f6fa7b', '#d2d868', '#ac9742', ['Red', 'Yellow', 'Brown']),
+ '2358': ('#d93153', '#eb5033', '#ff9d00', '#ffd82c', ['Red', 'Orange', 'Orange', 'Yellow']),
+ '2641': ('#e0f6aa', '#69aeff', '#9d4dff', '#6b3278', ['Green', 'Blue', 'Purple']),
+ '2487': ('#0e2e3b', '#166678', '#7db9b3', '#d8d7c3', ['Black', 'Blue', 'Turquoise', 'Brown']),
+ '2512': ('#e8e3c7', '#d4ceb0', '#b85b3f', '#a65238', ['Brown', 'Orange']),
+ '2389': ('#d2e4f1', '#8facc0', '#818d97', '#484d51', ['Blue', 'Grey']),
+ '2520': ('#2f1b44', '#892c41', '#c89034', '#fbff5f', ['Purple', 'Red', 'Orange', 'Yellow']),
+ '2171': ('#f83e4b', '#f7e185', '#cb9bba', '#9d53c3', ['Red', 'Yellow', 'Purple']),
+ '2130': ('#d2f079', '#c8d35b', '#ad8c45', '#a2663e', ['Green', 'Brown']),
+ '1895': ('#fadb3f', '#ecf7c5', '#515748', '#27332d', ['Yellow', 'Grey', 'Black']),
+ '1910': ('#2c2955', '#4c5fb1', '#f9f194', '#cdd582', ['Black', 'Blue', 'Yellow', 'Green']),
+ '2128': ('#231a31', '#e42f45', '#b42b3f', '#8ab2ff', ['Black', 'Red', 'Red', 'Blue']),
+ '1907': ('#d6ecfa', '#6f3826', '#b84a39', '#f15c5c', ['Blue', 'Brown', 'Red', 'Wedding']),
+ '2053': ('#0e153a', '#3d5af1', '#22d1ee', '#e2f3f5', ['Blue', 'Blue', 'Blue']),
+ '2127': ('#e4ba6f', '#fae88e', '#eb5e60', '#a52f57', ['Orange', 'Yellow', 'Red']),
+ '1894': ('#83cbfb', '#377fd9', '#edf68d', '#f1d851', ['Blue', 'Yellow']),
+ '1464': ('#d7df71', '#0e5f76', '#083d56', '#081e3f', ['Yellow', 'Blue', 'Black']),
+ '1908': ('#4b4c7a', '#eb92fb', '#c855bc', '#a03271', ['Pink', 'Purple']),
+ '1909': ('#362999', '#4262c5', '#44aec2', '#93efed', ['Purple', 'Blue', 'Turquoise']),
+ '1914': ('#efbfc6', '#c22828', '#8a0f0f', '#3c0303', ['Pink', 'Red', 'Brown']),
+ '1805': ('#f7b449', '#dde9f8', '#8293e3', '#5847ad', ['Orange', 'Blue', 'Purple']),
+ '1652': ('#f5f0e8', '#d3bd9a', '#a28f70', '#674f04', ['Grey', 'Brown']),
+ '1806': ('#fff56c', '#f1b149', '#4366a9', '#679ceb', ['Yellow', 'Orange', 'Blue']),
+ '1770': ('#aee1fc', '#60abfb', '#5170fd', '#4636fc', ['Blue']),
+ '1813': ('#438a70', '#52ceba', '#8affb4', '#eaff81', ['Green', 'Turquoise', 'Turquoise', 'Yellow']),
+ '1418': ('#e5edc4', '#e1a6e1', '#934662', '#463832', ['Yellow', 'Pink', 'Purple', 'Brown']),
+ '1649': ('#f0f5f9', '#c9d6df', '#52616b', '#1e2022', ['Grey', 'Black']),
+ '1660': ('#f6538f', '#b83f87', '#f3e94c', '#e8d124', ['Pink', 'Purple', 'Yellow', 'Yellow']),
+ '1608': ('#1a2634', '#203e5f', '#eec550', '#f9e3a3', ['Black', 'Blue', 'Yellow']),
+ '1181': ('#eca106', '#d34f1e', '#91300a', '#5f1b00', ['Orange', 'Brown', 'Gold']),
+ '1298': ('#3f3f3f', '#95956e', '#d2d86e', '#efefef', ['Grey', 'Green', 'Wedding', 'Retro']),
+ '1504': ('#48466d', '#3d84a8', '#46cdcf', '#abedd8', ['Turquoise', 'Blue']),
+ '1319': ('#70560d', '#c3a655', '#efd99b', '#f8edcd', ['Brown', 'Yellow']),
+ '1303': ('#e7272d', '#ae2a2f', '#fec24a', '#f6e5e4', ['Red', 'Yellow', 'Pink']),
+ '1037': ('#ffea54', '#ffcb3c', '#feaa2b', '#ff5757', ['Yellow', 'Orange', 'Red', 'Gold']),
+ '1043': ('#4ec9df', '#63a1d0', '#3576a7', '#344986', ['Blue']),
+ '643': ('#353941', '#26282b', '#5f85db', '#90b8f8', ['Black', 'Blue', 'Dark']),
+ '1223': ('#49260a', '#623b1c', '#caad8c', '#f6eddd', ['Brown']),
+ '839': ('#fbf8ca', '#a13f80', '#5e1043', '#360827', ['Yellow', 'Purple', 'Black', 'Wedding']),
+ '717': ('#266352', '#128061', '#53c0a2', '#b5f7e6', ['Green']),
+ '658': ('#611919', '#8e2735', '#deae4f', '#faf189', ['Brown', 'Red', 'Orange', 'Yellow']),
+ '361': ('#f9ed69', '#f08a5d', '#b83b5e', '#6a2c70', ['Yellow', 'Orange', 'Red', 'Purple']),
+ '362': ('#225763', '#41d8bf', '#2f89b3', '#3b50b2', ['Blue', 'Turquoise']),
+ '471': ('#c1f880', '#55c59d', '#4f5aa8', '#7481cf', ['Green', 'Turquoise', 'Blue']),
+ '470': ('#f75b5b', '#c83b4c', '#46265c', '#794d9a', ['Red', 'Purple']),
+ '469': ('#1b4b4d', '#f3f66f', '#f1d15f', '#e8984a', ['Yellow', 'Orange']),
+ '823': ('#561f55', '#df3554', '#902424', '#541f1f', ['Purple', 'Red', 'Red', 'Brown']),
+ '820': ('#65e892', '#3994d6', '#354abf', '#3d289b', ['Green', 'Blue']),
+ '255': ('#ef8f6b', '#d36239', '#e2dd66', '#a8b94e', ['Orange', 'Orange', 'Yellow', 'Green']),
+ '277': ('#e6a157', '#c9753d', '#973a3a', '#5b252d', ['Orange', 'Red', 'Brown', 'Warm']),
+ '278': ('#33425b', '#5baaec', '#526ed0', '#484cb0', ['Blue', 'Cold', 'Winter']),
+ '276': ('#fda4cf', '#f46d6d', '#b3533d', '#f0d4a2', ['Pink', 'Orange']),
+ '274': ('#56bfb5', '#38817a', '#f5f093', '#fbd66f', ['Turquoise', 'Yellow']),
+ '273': ('#884939', '#967248', '#caa653', '#e9e995', ['Brown', 'Yellow', 'Autumn']),
+ '272': ('#ff94c7', '#e760bf', '#7e49ac', '#343a69', ['Pink', 'Purple']),
+ '271': ('#7a81eb', '#504aa7', '#253361', '#599597', ['Purple', 'Blue', 'Blue', 'Turquoise']),
+ '280': ('#96c99c', '#55829c', '#485791', '#3a316e', ['Green', 'Blue', 'Purple']),
+ '282': ('#eefca9', '#b7e576', '#83cc61', '#5a9e7c', ['Green', 'Summer']),
+ '307': ('#693f27', '#e4c144', '#df7943', '#c24b39', ['Brown', 'Yellow', 'Orange']),
+ '221': ('#b0e6ff', '#7687db', '#8f45a9', '#582e48', ['Blue', 'Blue', 'Purple', 'Purple']),
+ '222': ('#304d4e', '#4b7551', '#8a9e52', '#f0d699', ['Green', 'Yellow']),
+ '223': ('#dffcad', '#6ec189', '#595cae', '#424478', ['Green', 'Blue']),
+ '224': ('#ffd7be', '#95977a', '#3f4c48', '#373640', ['Green']),
+ '225': ('#b3f7f6', '#7dd076', '#f1f592', '#f4cb81', ['Blue', 'Green', 'Yellow', 'Orange']),
+ '226': ('#352d4d', '#6d6192', '#69b0c1', '#92e0a9', ['Blue', 'Purple', 'Turquoise', 'Green']),
+ '227': ('#7a9eaf', '#655989', '#de88a5', '#ffcebb', ['Blue', 'Purple', 'Pink', 'Orange']),
+ '231': ('#314357', '#456672', '#e3b587', '#c98c70', ['Turquoise', 'Orange', 'Brown', 'Vintage']),
+ '228': ('#764f51', '#7fc5ca', '#9fe6dc', '#cfffff', ['Brown', 'Turquoise']),
+ '229': ('#477d7f', '#1f5357', '#64bd97', '#c2ffbb', ['Turquoise', 'Green']),
+ '230': ('#d19feb', '#fffd9d', '#f7d08c', '#ed8282', ['Purple', 'Yellow', 'Red', 'Bright']),
+ '232': ('#f6aad0', '#e9767c', '#8f5b4a', '#ddd49f', ['Pink', 'Red', 'Brown']),
+ '233': ('#a6f2db', '#7bcace', '#678eb4', '#4f4e79', ['Turquoise', 'Blue', 'Blue']),
+ '234': ('#8cdadb', '#815e94', '#f4f49e', '#f1d089', ['Turquoise', 'Purple', 'Yellow', 'Yellow']),
+ '236': ('#3b503d', '#4a746e', '#f1edb3', '#c8cf94', ['Green', 'Turquoise', 'Yellow']),
+ '237': ('#ee8374', '#54567a', '#dab784', '#f8f3b6', ['Orange', 'Blue', 'Yellow', 'Yellow']),
+ '238': ('#2b2e4a', '#e84545', '#903749', '#53354a', ['Red']),
+ '240': ('#49493c', '#9fa180', '#f2f77f', '#6ebaa7', ['Brown', 'Brown', 'Yellow', 'Turquoise']),
+ '241': ('#efd8f4', '#d4abdc', '#ea5656', '#f1e38a', ['Purple', 'Red', 'Yellow']),
+ '242': ('#ee7c4b', '#c45d3e', '#c6c5b3', '#f5f0c4', ['Orange', 'Orange', 'Brown', 'Yellow', 'Gold']),
+ '243': ('#b2b7ff', '#d5e8ff', '#d9a2f1', '#d86f9b', ['Blue', 'Purple', 'Pink']),
+ '244': ('#edf3b7', '#e5c890', '#9268a5', '#644a7f', ['Yellow', 'Orange', 'Purple', 'Purple']),
+ '248': ('#3d322c', '#654534', '#9c563d', '#d9b26e', ['Brown']),
+ '246': ('#5f5dbd', '#5e87b8', '#83cee0', '#a4fbe3', ['Blue', 'Blue', 'Turquoise', 'Turquoise']),
+ '247': ('#804d3b', '#522e24', '#75beda', '#9aedf4', ['Brown', 'Brown', 'Blue']),
+ '249': ('#dbef98', '#605cb8', '#60c2a4', '#9df0ac', ['Green']),
+ '250': ('#9a69e1', '#47429d', '#f7b7f3', '#e27393', ['Purple', 'Blue', 'Pink', 'Pink']),
+ '253': ('#6c95ec', '#3d61ad', '#81e1af', '#41a06f', ['Blue', 'Green']),
+ '254': ('#d19178', '#a1583e', '#d4c07a', '#f8f7a5', ['Brown', 'Yellow']),
+ '208': ('#bdf9f7', '#93c4ff', '#b67ccf', '#765a60', ['Blue', 'Purple']),
+ '187': ('#1d1716', '#402a23', '#a55233', '#f3bc77', ['Black', 'Brown', 'Brown', 'Orange']),
+ '188': ('#fa8572', '#b24968', '#6c3779', '#6c5fa7', ['Orange', 'Purple', 'Purple']),
+ '189': ('#f7ec77', '#da5151', '#ed9f66', '#876464', ['Yellow', 'Red', 'Orange', 'Brown']),
+ '190': ('#48829e', '#51dacf', '#9ef5cf', '#e8ffb1', ['Blue', 'Turquoise', 'Yellow']),
+ '191': ('#d5ab9c', '#e6e696', '#7bc0a3', '#54878f', ['Brown', 'Yellow', 'Green', 'Turquoise', 'Pastel']),
+ '192': ('#e2eff1', '#b6d5e1', '#65799b', '#555273', ['Blue']),
+ '193': ('#ffe76a', '#e0ab5b', '#94784c', '#6e4c41', ['Yellow', 'Orange', 'Brown', 'Gold']),
+ '194': ('#333a7b', '#4b6982', '#70c6c7', '#b4ffd8', ['Blue', 'Blue', 'Turquoise', 'Green']),
+ '195': ('#e5f1e3', '#a3cd9e', '#529471', '#35635b', ['Green']),
+ '196': ('#3e3245', '#524a79', '#97d8ec', '#74bbca', ['Black', 'Turquoise', 'Blue']),
+ '198': ('#8fc9ae', '#548e87', '#385b66', '#bddaa5', ['Green']),
+ '202': ('#98d8ff', '#796dce', '#694b7c', '#402a30', ['Blue', 'Blue', 'Purple', 'Purple']),
+ '203': ('#9effa9', '#36485e', '#333146', '#29252c', ['Green', 'Blue', 'Black']),
+ '204': ('#f7ffba', '#f7e39c', '#ebaf81', '#da8067', ['Yellow', 'Orange']),
+ '205': ('#36413d', '#4c657e', '#f29696', '#ffe2ad', ['Black', 'Blue', 'Pink', 'Yellow']),
+ '206': ('#c1e8da', '#c96868', '#5e4949', '#866770', ['Turquoise', 'Red', 'Grey', 'Brown']),
+ '209': ('#d4a2be', '#75597d', '#b0b8b4', '#f8e4dd', ['Pink', 'Purple', 'Grey']),
+ '211': ('#364968', '#fddf97', '#e09664', '#6c4343', ['Blue', 'Yellow', 'Orange', 'Brown']),
+ '212': ('#ffebbc', '#5da7ae', '#543d46', '#292830', ['Yellow', 'Blue', 'Brown', 'Black']),
+ '213': ('#ebbf58', '#769353', '#3d655d', '#33484d', ['Orange', 'Green', 'Turquoise', 'Blue']),
+ '215': ('#4531b1', '#a836ad', '#f16896', '#fff0a4', ['Blue', 'Purple', 'Pink', 'Yellow']),
+ '216': ('#d15555', '#eda489', '#e8fd96', '#a1d76f', ['Red', 'Pink', 'Yellow', 'Green']),
+ '217': ('#a45fbe', '#382f60', '#485188', '#4b81ab', ['Purple', 'Blue']),
+ '218': ('#567582', '#464d5c', '#f7dda4', '#b89068', ['Turquoise', 'Yellow', 'Brown']),
+ '219': ('#3e6545', '#9973e2', '#82ceda', '#ecffb1', ['Green', 'Purple', 'Blue', 'Yellow']),
+ '220': ('#bbe06c', '#7cb855', '#469b4c', '#3c6e57', ['Green', 'Green', 'Green', 'Green']),
+ '185': ('#2a221e', '#46322b', '#c73f65', '#d580bc', ['Brown', 'Pink']),
+ '180': ('#686ee2', '#5c3e84', '#f35c6e', '#ffa87b', ['Blue', 'Purple', 'Red', 'Orange']),
+ '181': ('#abf2fb', '#b589ef', '#a964cd', '#f1a3c5', ['Blue', 'Purple', 'Pink']),
+ '182': ('#ffff8f', '#ec9e69', '#d56073', '#7a4579', ['Yellow', 'Orange', 'Red', 'Purple', 'Sunset', 'Wedding']),
+ '129': ('#f39de5', '#9b77da', '#4e6b9f', '#6fa5b1', ['Pink', 'Purple', 'Blue', 'Blue']),
+ '130': ('#516091', '#74bec1', '#adebbe', '#eef3ad', ['Blue', 'Turquoise', 'Green', 'Yellow', 'Pastel']),
+ '133': ('#ebd9dd', '#d8aed3', '#9182c4', '#486989', ['Pink', 'Purple', 'Blue']),
+ '134': ('#8be3e1', '#d3f7ad', '#95bb76', '#97935c', ['Blue', 'Green', 'Brown']),
+ '136': ('#734444', '#c37857', '#eeedbe', '#99b27f', ['Brown', 'Green']),
+ '137': ('#4c5f7a', '#393e6f', '#3d2e4f', '#321d2f', ['Blue', 'Black', 'Purple', 'Dark']),
+ '139': ('#e1dfba', '#7f7e90', '#4d424d', '#36292c', ['Grey']),
+ '140': ('#b1e9a3', '#7ac38f', '#88e0d0', '#c7eeff', ['Green', 'Green', 'Turquoise', 'Blue']),
+ '141': ('#e97a7a', '#8b4f80', '#8b76a5', '#b9c0d5', ['Red', 'Purple', 'Grey', 'Pastel']),
+ '146': ('#e04b5a', '#e49756', '#5b305a', '#9a4c68', ['Red', 'Orange', 'Purple', 'Purple']),
+ '152': ('#f2fc9f', '#edbb91', '#da6969', '#b05977', ['Yellow', 'Orange', 'Red']),
+ '155': ('#8ecccc', '#50717b', '#3a4042', '#212121', ['Blue', 'Grey', 'Black']),
+ '156': ('#e6f18c', '#72b37e', '#437975', '#555c78', ['Yellow', 'Green']),
+ '157': ('#7fcbd7', '#857ebb', '#ca9dd7', '#facbd3', ['Blue', 'Purple', 'Pink']),
+ '158': ('#d789d7', '#9d65c9', '#5d54a4', '#2a3d66', ['Pink', 'Purple']),
+ '159': ('#f7c469', '#c46352', '#714433', '#412525', ['Orange', 'Brown', 'Autumn']),
+ '160': ('#9ae17b', '#6bba62', '#307470', '#42476d', ['Green', 'Green', 'Purple']),
+ '161': ('#634258', '#6d6087', '#60a0b0', '#9ad1aa', ['Purple', 'Blue', 'Green']),
+ '162': ('#f1f4c6', '#d6d0b8', '#aaa6a4', '#837d7d', ['Yellow', 'Brown', 'Grey']),
+ '165': ('#f96d6d', '#b84d69', '#a9d7f6', '#8fb1e9', ['Red', 'Blue']),
+ '171': ('#d68438', '#f1b24b', '#36846b', '#4bb39a', ['Orange', 'Turquoise', 'Gold']),
+ '174': ('#639cd9', '#5454c5', '#342056', '#220e24', ['Blue', 'Purple', 'Black', 'Dark']),
+ '177': ('#7dd87d', '#4c9173', '#5b446a', '#906387', ['Green', 'Green', 'Purple']),
+}
\ No newline at end of file
diff --git a/ThemeMaker/readme.md b/ThemeMaker/readme.md
new file mode 100644
index 00000000..46a7e074
--- /dev/null
+++ b/ThemeMaker/readme.md
@@ -0,0 +1,172 @@
+# Theme Maker
+
+## A Tool To Make PySimpleGUI "Look and Feel" Entries
+
+The Look and Feel themes are defined using a dictionary. Each theme has a dictionary of colors and other settings such as the color for the text, background, input fields, buttons, etc. Generating these themes has been a tedious and long process in the past. This tool was created to make that process easier, more enjoyable, and perhaps something users could participate in.
+
+This program uses over 1,700 color palettes that were downloaded from https://colorhunt.co/palettes and put into a python file as a dictionary. You'll find the dictionary in `color_themes.py`.
+
+Here is how the dictionary looks when shortened to 3 entires:
+
+```python
+themes = {
+ '163372': ('#f4efd3', '#cccccc', '#c2b0c9', '#9656a1', ['Yellow', 'Grey', 'Purple', 'Pastel']),
+ '163318': ('#594a4e', '#e78fb3', '#ffc0ad', '#6fc1a5', ['Brown', 'Pink', 'Green', 'Vintage']),
+ '163537': ('#ff8ba7', '#ffc6c7', '#faeee7', '#c3f0ca', ['Pink', 'Green', 'Bright', 'Summer']) }
+```
+
+## What It Does
+
+Each palette, a group of 4 colors, is used to present a small "candidate theme layout". A single "candidate" looks like this:
+
+
+
+For each palette you will be presented with 4 of those layouts. Two are "Dark" and two are "Light". You can choose options in each of these layouts and choose to save it.
+
+The program generates text in a debug window and also appends the text to an output file. This text can be used directly in a look and feel table.
+
+
+## Installing
+
+There is no installation if you already have PySimpleGUI installed. Simply download the 2 .py files in this folder and run the one named Theme_Maker.py
+
+## Running - Initial Window
+
+The first window you're presented with collects information from you regarding how you would like the theme generation window to be laid out and where to start in the palette dictionary.
+
+
+
+
+
+
+
+
+
+
+
+Program that is used to create new themes for use with PySimpleGUI's "Look and Feel" settings.
+You are presented with a grid of mini-windows that is created for color palettes downloaded from https://colorhunt.co/palettes
+The file color_themes.py contains a large dictionary of approx 1780 palettes.
+
+For each palette you are shown 4 candidate themes, 2 "light" and 2 "dark". The window shows 5 palettes so you'll have a
+total of 20 candidate themes displayed in total.
+Each candidate theme has a 3 options - The button color (text and background), the text color for Input/Multiline elements,
+and the name of the theme when you save it. These you choose using the radio buttons and one input field.
+To "save" one of these candidate themes, check the checkbox to the left of the layout, choose the radio buttons for button
+& text settings and optionally change the theme name that is shown above the grid of OK buttons. By default the name starts
+with either "Dark" or "Light" and is followed by the first 2 "tags" that were posted with the palette on the colorhunt site.
+
+After you've selected the themes you want to save from the window of 20 click any "OK" button in the window or close the
+window with the "X". You will see the dictionary text in the Debug Window and the values will also be written to a file.
+You'll then be shown the next group of 20 candidate themes.
+
+If you want to exit the program entirely, click any "Cancel" button the page. Note - cliicking "Cancel" will not save any
+theme you have checked with the checkbox. You should only exit from a window you have not selected any themes for saving
+
+If a Theme is selected for saving, then the values for the LOOK_AND_FEEL dictionary are displayed in a debug window and are
+also appended to the file new_theme_dict.py. You will need to edit the new_theme_dict.py file to get the syntax correct.
+A "," or "}" may need to be added in order to make the table be correct.
+
+If you're using this program it's assumed you know what you're doing and understand the LOOK_AND_FEEL dictionary and can
+figure out how to get the syntax correct for adding it to the main dictionary of themes.
+
+## Choosing and Saving New Themes
+
+Let's say you were working with these candidate themes:
+
+
+
+
+You like the first 2 themes on the second row, so you
+
+* Mark the checkbox next to each of those 2 themes
+* Click the 2 radio buttons indicating choice for input text choice and button color
+* Enter a name to be used for the theme
+* Click OK anywhere on the screen
+
+Here is how my choices appear for those 2 entries:
+
+
+
+The result will be that a debug window will open and display the text for the 2 new theme entries for the look and feel theme dictionary.
+
+
+
+Similar text will be appended to the end of the file "new_theme_dict.py".
+
+
+## Integrating the New Themes
+
+Now that you've got the text for the themes it's time to integrate it into your PySimpleGUI environment. The way you do this is that you add your themes direcvtly to the look and feel dictionary.
+
+Begin by copying the text from either the .py file or the debug window:
+
+```python
+'DarkGreenArmy' : {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}
+
+'LightGreenArmy' : {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}
+```
+
+This code is written as if you were going to directly add the code inside the PySimpleGUI.py file itself. Instead you'll be adding them directly from your user code rather than modifying the PySimpleGUI.py file.
+
+Adding the entries to the table can be accomplished using simple assignment to a new dictionary entry. The look and feel dictionary in PySimpleGUI is named `sg.LOOK_AND_FEEL_TABLE`. Here is a sample user program that adds these 2 new themes to the table and then uses one of them to display a window and another to display a popup.
+
+
+```python
+import PySimpleGUI as sg
+
+sg.LOOK_AND_FEEL_TABLE['DarkGreenArmy'] = {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94',
+ 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}
+
+sg.LOOK_AND_FEEL_TABLE['LightGreenArmy'] = {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d',
+ 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0,
+ 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}
+
+sg.change_look_and_feel('Dark Green Army')
+
+
+layout = [ [sg.Text('My Window')],
+ [sg.Input(key='-IN-')],
+ [sg.Button('Popup'), 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 == 'Popup':
+ sg.ChangeLookAndFeel('Light Green Army')
+ sg.popup('This popup is using a new "Light Green Army" look and feel theme')
+window.close()
+```
+
+## Displaying the New Themes
+
+When the above program is executed, you are first prsented with a window that's created using the new "DarkGreenArmy" theme. Notice that you can use the "fuzzy theme matching" to make your code more readable by referencing to the theme as "Dark Green Army" when calling `change_look_and_feel`
+
+
+
+Clicking the popup causes the light look and feel theme to be loaded prior to calling `popup` to display a window. This will cause the popup to use the light theme and creates this window:
+
+
+
+## Go Make The World More Colorful!!
+
+Now that you've created some of your very own Look and Feel themes, go use them to create some nice looking windows! **Anything** is better than a default gray window.
+
+
+
+# Author
+
+The PySimpleGUI Organization
+
+
+
+# License
+
+Copyright 2019 PySimpleGUI.org
+
+ GNU Lesser General Public License (LGPL 3) +
diff --git a/YoloObjectDetection/Readme.md b/YoloObjectDetection/Readme.md
new file mode 100644
index 00000000..6c7e9c43
--- /dev/null
+++ b/YoloObjectDetection/Readme.md
@@ -0,0 +1,6 @@
+
+# PySimpleGUI openCV YOLO Deep Learning
+
+To save room in the PySimpleGUI Repo, this project has been moved to its own repo on GitHub
+
+You'll now find the project at: https://github.com/PySimpleGUI/PySimpleGUI-YOLO
diff --git a/docs/Demos.md b/docs/Demos.md
deleted file mode 100644
index 352cab2a..00000000
--- a/docs/Demos.md
+++ /dev/null
@@ -1,894 +0,0 @@
-## [Browser_START_HERE_Demo_Programs_Browser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Browser_START_HERE_Demo_Programs_Browser.py)
-
-
-## [Demo_All_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_All_Elements.py)
-
-
-## [Demo_All_Elements_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_All_Elements_Simple.py)
-
-
-## [Demo_Animated_GIFs.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Animated_GIFs.py)
-
-
-## [Demo_Animated_GIFs_Using_PIL.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Animated_GIFs_Using_PIL.py)
-
-
-## [Demo_Auto_Save_Window_Position.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Auto_Save_Window_Position.py)
-
-
-## [Demo_Bar_Chart.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Bar_Chart.py)
-
-
-## [Demo_Base64_Image_Encoder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Base64_Image_Encoder.py)
-
-
-## [Demo_Base64_Single_Image_Encoder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Base64_Single_Image_Encoder.py)
-
-
-## [Demo_Borderless_Window.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Borderless_Window.py)
-
-
-## [Demo_Buttons_Base64_Shaded.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Base64_Shaded.py)
-
-
-## [Demo_Buttons_Base64_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Base64_Simple.py)
-
-
-## [Demo_Buttons_Base64_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Base64_Simple.py)
-
-
-## [Demo_Buttons_Base64_User_Settings.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Base64_User_Settings.py)
-
-
-## [Demo_Buttons_Mac.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Mac.py)
-
-
-## [Demo_Buttons_Nice_Graphics.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Nice_Graphics.py)
-
-
-## [Demo_Buttons_Realtime.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Buttons_Realtime.py)
-
-
-## [Demo_Button_Click.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Click.py)
-
-
-## [Demo_Button_Events_From_Browse.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Events_From_Browse.py)
-
-
-## [Demo_Button_Func_Calls.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Func_Calls.py)
-
-
-## [Demo_Button_States.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_States.py)
-
-
-## [Demo_Button_Toggle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Toggle.py)
-
-
-## [Demo_Button_Toggle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Toggle.py)
-
-
-## [Demo_Button_Toggle2.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Toggle2.py)
-
-
-## [Demo_Button_Toggle_Simple_Graphic.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py)
-
-
-## [Demo_Button_Toggle_Simple_Graphic.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Button_Toggle_Simple_Graphic.py)
-
-
-## [Demo_Calendar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Calendar.py)
-
-
-## [Demo_Calendar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Calendar.py)
-
-
-## [Demo_Canvas.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Canvas.py)
-
-
-## [Demo_Canvas.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Canvas.py)
-
-
-## [Demo_Chat.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Chat.py)
-
-
-## [Demo_Chat_With_History.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Chat_With_History.py)
-
-
-## [Demo_Checkboxes_Custom.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Checkboxes_Custom.py)
-
-
-## [Demo_Class_Wrapper.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Class_Wrapper.py)
-
-
-## [Demo_Close_Attempted_Event.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Close_Attempted_Event.py)
-
-
-## [Demo_Close_Attempted_Event.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Close_Attempted_Event.py)
-
-
-## [Demo_Color_Chooser_Custom.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Color_Chooser_Custom.py)
-
-
-## [Demo_Color_Names.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Color_Names.py)
-
-
-## [Demo_Color_Names_Smaller_List.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Color_Names_Smaller_List.py)
-
-
-## [Demo_Color_Swatches.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Color_Swatches.py)
-
-
-## [Demo_Columns.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Columns.py)
-
-
-## [Demo_Column_And_Frames.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_And_Frames.py)
-
-
-## [Demo_Column_Collapsible_Sections.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_Collapsible_Sections.py)
-
-
-## [Demo_Column_Elem_Swap_Entire_Window.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py)
-
-
-## [Demo_Column_Fixed_Size_Justified_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py)
-
-
-## [Demo_Column_Fixed_Size_Justified_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_Fixed_Size_Justified_Elements.py)
-
-
-## [Demo_Combo_Filechooser_With_History_And_Clear.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Combo_Filechooser_With_History_And_Clear.py)
-
-
-## [Demo_Compact_Layouts_Element_Renaming.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Compact_Layouts_Element_Renaming.py)
-
-
-## [Demo_Compare_Files.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Compare_Files.py)
-
-
-## [Demo_Control_Panel_Button_Grid.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Control_Panel_Button_Grid.py)
-
-
-## [Demo_Control_Panel_Button_Grid.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Control_Panel_Button_Grid.py)
-
-
-## [Demo_Conways_Game_of_Life.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Conways_Game_of_Life.py)
-
-
-## [Demo_Crossword_Puzzle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Crossword_Puzzle.py)
-
-
-## [Demo_Dashboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Dashboard.py)
-
-
-## [Demo_Date_Chooser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Date_Chooser.py)
-
-
-## [Demo_Debugger_Built_Into_PSG.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Debugger_Built_Into_PSG.py)
-
-
-## [Demo_Demo_Programs_Browser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Demo_Programs_Browser.py)
-
-
-## [Demo_Design_Pattern_Multiple_Windows.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py)
-
-
-## [Demo_Design_Pattern_Multiple_Windows1.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows1.py)
-
-
-## [Demo_Design_Pattern_Multiple_Windows2.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows2.py)
-
-
-## [Demo_Design_Pattern_Multiple_Windows3.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py)
-
-
-## [Demo_Design_Pattern_Multiple_Windows_Both_Visible.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Multiple_Windows_Both_Visible.py)
-
-
-## [Demo_Design_Pattern_Persistent_Window.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py)
-
-
-## [Demo_Design_Pattern_Save_Theme.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Design_Pattern_Save_Theme.py)
-
-
-## [Demo_Desktop_Floating_Toolbar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Floating_Toolbar.py)
-
-
-## [Demo_Desktop_Widget_Count_To_A_Goal.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Count_To_A_Goal.py)
-
-
-## [Demo_Desktop_Widget_CPU_Dashboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py)
-
-
-## [Demo_Desktop_Widget_CPU_Gauge.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Gauge.py)
-
-
-## [Demo_Desktop_Widget_CPU_Graph.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py)
-
-
-## [Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Grid_Of_Gauges.py)
-
-
-## [Demo_Desktop_Widget_CPU_Square.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Square.py)
-
-
-## [Demo_Desktop_Widget_CPU_Top_Processes.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Top_Processes.py)
-
-
-## [Demo_Desktop_Widget_CPU_Utilization_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py)
-
-
-## [Demo_Desktop_Widget_Date.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Date.py)
-
-
-## [Demo_Desktop_Widget_Days_Counter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Days_Counter.py)
-
-
-## [Demo_Desktop_Widget_Days_Until_Date.pyw](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Days_Until_Date.pyw)
-
-
-## [Demo_Desktop_Widget_Digital_Picture_Frame.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Digital_Picture_Frame.py)
-
-
-## [Demo_Desktop_Widget_Drive_Usage.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Drive_Usage.py)
-
-
-## [Demo_Desktop_Widget_Drive_Usage_Gauges.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Drive_Usage_Gauges.py)
-
-
-## [Demo_Desktop_Widget_FedEx_Package_Tracking.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_FedEx_Package_Tracking.py)
-
-
-## [Demo_Desktop_Widget_Launcher_Bar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Launcher_Bar.py)
-
-
-## [Demo_Desktop_Widget_Manual_Counter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Manual_Counter.py)
-
-
-## [Demo_Desktop_Widget_Postit.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Postit.py)
-
-
-## [Demo_Desktop_Widget_Postit_3_Lines.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Postit_3_Lines.py)
-
-
-## [Demo_Desktop_Widget_psutil_Dashboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py)
-
-
-## [Demo_Desktop_Widget_RAM_Gauge.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_RAM_Gauge.py)
-
-
-## [Demo_Desktop_Widget_RAM_Square.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_RAM_Square.py)
-
-
-## [Demo_Desktop_Widget_Template.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Template.py)
-
-
-## [Demo_Desktop_Widget_Timer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Timer.py)
-
-
-## [Demo_Desktop_Widget_Time_Handwritten.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Time_Handwritten.py)
-
-
-## [Demo_Desktop_Widget_Weather.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Desktop_Widget_Weather.py)
-
-
-## [Demo_Disable_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Disable_Elements.py)
-
-
-## [Demo_Dispatchers.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Dispatchers.py)
-
-
-## [Demo_DuplicateFileFinder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_DuplicateFileFinder.py)
-
-
-## [Demo_Edit_Me_Option.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Edit_Me_Option.py)
-
-
-## [Demo_Emojis.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Emojis.py)
-
-
-## [Demo_Emojis.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Emojis.py)
-
-
-## [Demo_Event_Binding.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Event_Binding.py)
-
-
-## [Demo_Event_Callback_Simulation.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Event_Callback_Simulation.py)
-
-
-## [Demo_Execute_Py.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Execute_Py.py)
-
-
-## [Demo_EXE_Maker.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_EXE_Maker.py)
-
-
-## [Demo_Fill_Form.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Fill_Form.py)
-
-
-## [Demo_Floating_Toolbar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Floating_Toolbar.py)
-
-
-## [Demo_Focus_Navigation_Using_Arrow_Keys.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py)
-
-
-## [Demo_Focus_Navigation_Using_Arrow_Keys.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Focus_Navigation_Using_Arrow_Keys.py)
-
-
-## [Demo_Font_Previewer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Font_Previewer.py)
-
-
-## [Demo_Font_Sizer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Font_Sizer.py)
-
-
-## [Demo_Font_String.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Font_String.py)
-
-
-## [Demo_Frame_Based_Dashboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Frame_Based_Dashboard.py)
-
-
-## [Demo_Frame_For_Screen_Captures.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Frame_For_Screen_Captures.py)
-
-
-## [Demo_Game_Frontend_Battleship.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Game_Frontend_Battleship.py)
-
-
-## [Demo_Game_Frontend_Battleship_No_List_Comprehensions.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py)
-
-
-## [Demo_Game_Frontend_Battleship_Single_List_Comprehension.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py)
-
-
-## [Demo_Game_Wordle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Game_Wordle.py)
-
-
-## [Demo_Game_Wordle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Game_Wordle.py)
-
-
-## [Demo_GoodColors.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_GoodColors.py)
-
-
-## [Demo_Google_TTS.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Google_TTS.py)
-
-
-## [Demo_Google_TTS.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Google_TTS.py)
-
-
-## [Demo_Graph_Bar_Chart_Dual_Axis.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Bar_Chart_Dual_Axis.py)
-
-
-## [Demo_Graph_Custom_Progress_Meter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Custom_Progress_Meter.py)
-
-
-## [Demo_Graph_Drag_Rectangle_Super_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Drag_Rectangle_Super_Simple.py)
-
-
-## [Demo_Graph_Drawing.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Drawing.py)
-
-
-## [Demo_Graph_Drawing_And_Dragging_Figures.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py)
-
-
-## [Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py)
-
-
-## [Demo_Graph_Element_Sine_Wave.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Element_Sine_Wave.py)
-
-
-## [Demo_Graph_Element_Sine_Wave.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Element_Sine_Wave.py)
-
-
-## [Demo_Graph_Element_Sine_Wave.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Element_Sine_Wave.py)
-
-
-## [Demo_Graph_Noise.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Graph_Noise.py)
-
-
-## [Demo_Hello_World.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Hello_World.py)
-
-
-## [Demo_Hotkey.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Hotkey.py)
-
-
-## [Demo_Image_Elem_Image_Viewer_PIL_Based.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Image_Elem_Image_Viewer_PIL_Based.py)
-
-
-## [Demo_Image_Elem_Splash_Screen.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Image_Elem_Splash_Screen.py)
-
-
-## [Demo_Image_Elem_Splash_Screen.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Image_Elem_Splash_Screen.py)
-
-
-## [Demo_Img_Viewer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Img_Viewer.py)
-
-
-## [Demo_Input_Auto_Complete.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Input_Auto_Complete.py)
-
-
-## [Demo_Input_Save_Last_Used_Entry_In_User_Settings.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Input_Save_Last_Used_Entry_In_User_Settings.py)
-
-
-## [Demo_Input_Validation.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Input_Validation.py)
-
-
-## [Demo_Invisible_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Invisible_Elements.py)
-
-
-## [Demo_Invisible_Elements_Pinning.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Invisible_Elements_Pinning.py)
-
-
-## [Demo_Justification_Columns.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Justification_Columns.py)
-
-
-## [Demo_Justification_Using_Stretch_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Justification_Using_Stretch_Elements.py)
-
-
-## [Demo_Keyboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Keyboard.py)
-
-
-## [Demo_Keyboard_Realtime.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Keyboard_Realtime.py)
-
-
-## [Demo_Keypad.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Keypad.py)
-
-
-## [Demo_Layout_Add_and_Delete_Rows.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Add_and_Delete_Rows.py)
-
-
-## [Demo_Layout_Extend.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Extend.py)
-
-
-## [Demo_Layout_Reuse_Effect.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Reuse_Effect.py)
-
-
-## [Demo_Layout_Vertical.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Vertical.py)
-
-
-## [Demo_Layout_Vertical_Centered.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Vertical_Centered.py)
-
-
-## [Demo_Layout_Vertical_Centered_Using_Sizer_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Vertical_Centered_Using_Sizer_Element.py)
-
-
-## [Demo_Layout_Vertical_Centered_Using_VPush_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py)
-
-
-## [Demo_Layout_Vertical_Centered_Using_VPush_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Layout_Vertical_Centered_Using_VPush_Element.py)
-
-
-## [Demo_LED_Indicators.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_LED_Indicators.py)
-
-
-## [Demo_LED_Indicators_Text_Based.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_LED_Indicators_Text_Based.py)
-
-
-## [Demo_Listbox_Search_Filter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Listbox_Search_Filter.py)
-
-
-## [Demo_Listbox_Search_Filter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Listbox_Search_Filter.py)
-
-
-## [Demo_Long_Operations.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Long_Operations.py)
-
-
-## [Demo_Long_Operations.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Long_Operations.py)
-
-
-## [Demo_Look_And_Feel_Theme_Browser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Look_And_Feel_Theme_Browser.py)
-
-
-## [Demo_Look_And_Feel_Theme_Dump.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Look_And_Feel_Theme_Dump.py)
-
-
-## [Demo_Main_Control_Test_Panel.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Main_Control_Test_Panel.py)
-
-
-## [Demo_Make_Windows_Shortcut.pyw](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Make_Windows_Shortcut.pyw)
-
-
-## [Demo_Matplotlib.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib.py)
-
-
-## [Demo_Matplotlib_Animated.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Animated.py)
-
-
-## [Demo_Matplotlib_Animated_Scatter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Animated_Scatter.py)
-
-
-## [Demo_Matplotlib_Browser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Browser.py)
-
-
-## [Demo_Matplotlib_Browser_Paned.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Browser_Paned.py)
-
-
-## [Demo_Matplotlib_Embedded_TEMPLATE.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Embedded_TEMPLATE.py)
-
-
-## [Demo_Matplotlib_Embedded_Toolbar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py)
-
-
-## [Demo_Matplotlib_Image_Elem.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Image_Elem.py)
-
-
-## [Demo_Matplotlib_Image_Elem.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Image_Elem.py)
-
-
-## [Demo_Matplotlib_Image_Elem.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Image_Elem.py)
-
-
-## [Demo_Matplotlib_PyLab.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_PyLab.py)
-
-
-## [Demo_Matplotlib_Styles.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Styles.py)
-
-
-## [Demo_Matplotlib_Two_Windows.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Matplotlib_Two_Windows.py)
-
-
-## [Demo_Media_Player.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Media_Player.py)
-
-
-## [Demo_Media_Player_VLC_Based.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Media_Player_VLC_Based.py)
-
-
-## [Demo_Menubar_Custom.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Menubar_Custom.py)
-
-
-## [Demo_Menubar_Custom.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Menubar_Custom.py)
-
-
-## [Demo_Menus.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Menus.py)
-
-
-## [Demo_Menu_With_Toolbar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Menu_With_Toolbar.py)
-
-
-## [Demo_Multiline_cprint_Printing.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiline_cprint_Printing.py)
-
-
-## [Demo_Multiline_Multicolored_Text.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiline_Multicolored_Text.py)
-
-
-## [Demo_Multiline_Right_Click_Menu_Clipboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiline_Right_Click_Menu_Clipboard.py)
-
-
-## [Demo_Multiple_Windows_Experimental.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiple_Windows_Experimental.py)
-
-
-## [Demo_Multiple_Windows_read_all_windows_25_lines.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multiple_Windows_read_all_windows_25_lines.py)
-
-
-## [Demo_Multithreaded_Animated_Shell_Command.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py)
-
-
-## [Demo_Multithreaded_Calling_Popup.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Calling_Popup.py)
-
-
-## [Demo_Multithreaded_Different_Threads.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Different_Threads.py)
-
-
-## [Demo_Multithreaded_Logging.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Logging.py)
-
-
-## [Demo_Multithreaded_Long_Shell_Operation_Animated.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py)
-
-
-## [Demo_Multithreaded_Long_Tasks.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Long_Tasks.py)
-
-
-## [Demo_Multithreaded_Long_Task_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py)
-
-
-## [Demo_Multithreaded_Multiple_Threads.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py)
-
-
-## [Demo_Multithreaded_popup.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_popup.py)
-
-
-## [Demo_Multithreaded_ProgressBar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_ProgressBar.py)
-
-
-## [Demo_Multithreaded_Write_Event_Value.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Write_Event_Value.py)
-
-
-## [Demo_Multithreaded_Write_Event_Value_MultiWindow.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Multithreaded_Write_Event_Value_MultiWindow.py)
-
-
-## [Demo_Nice_Buttons.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Nice_Buttons.py)
-
-
-## [Demo_NonBlocking_Form.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_NonBlocking_Form.py)
-
-
-## [Demo_Notification_Window_Alpha_Channel.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Notification_Window_Alpha_Channel.py)
-
-
-## [Demo_Notification_Window_Fade_In_Out.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Notification_Window_Fade_In_Out.py)
-
-
-## [Demo_Notification_Window_Multiprocessing.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Notification_Window_Multiprocessing.py)
-
-
-## [Demo_one_line_progress_meter.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_one_line_progress_meter.py)
-
-
-## [Demo_OpenCV.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV.py)
-
-
-## [Demo_OpenCV_4_Line_Program.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_4_Line_Program.py)
-
-
-## [Demo_OpenCV_7_Line_Program.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_7_Line_Program.py)
-
-
-## [Demo_OpenCV_Draw_On_Webcam_Image.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_Draw_On_Webcam_Image.py)
-
-
-## [Demo_OpenCV_Simple_GUI.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_Simple_GUI.py)
-
-
-## [Demo_OpenCV_Webcam.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_Webcam.py)
-
-
-## [Demo_OpenCV_Webcam_ASCII.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py)
-
-
-## [Demo_OpenCV_Webcam_ASCII.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py)
-
-
-## [Demo_Paned_Window.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Paned_Window.py)
-
-
-## [Demo_Password_Login.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Password_Login.py)
-
-
-## [Demo_PIL_Color_Picker.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PIL_Color_Picker.py)
-
-
-## [Demo_PIL_Rounded_Rectangle_Buttons.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PIL_Rounded_Rectangle_Buttons.py)
-
-
-## [Demo_PIL_Toggle_Button.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PIL_Toggle_Button.py)
-
-
-## [Demo_PIL_Use.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PIL_Use.py)
-
-
-## [Demo_PNG_Thumbnail_Viewer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py)
-
-
-## [Demo_PNG_Viewer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PNG_Viewer.py)
-
-
-## [Demo_Pong.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Pong.py)
-
-
-## [Demo_Pong_Multiple_Platforms.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Pong_Multiple_Platforms.py)
-
-
-## [Demo_Popups.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Popups.py)
-
-
-## [Demo_Popup_Custom.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Popup_Custom.py)
-
-
-## [Demo_Post_An_Issue.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Post_An_Issue.py)
-
-
-## [Demo_Progress_Meters.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Progress_Meters.py)
-
-
-## [Demo_Progress_Meter_Simulated.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Progress_Meter_Simulated.py)
-
-
-## [Demo_psutil_Kill_Processes.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_psutil_Kill_Processes.py)
-
-
-## [Demo_psutil_Kill_Python_Processes.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_psutil_Kill_Python_Processes.py)
-
-
-## [Demo_PyCharm_Diff_2_Files.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PyCharm_Diff_2_Files.py)
-
-
-## [Demo_PyCharm_Self_Edit.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PyCharm_Self_Edit.py)
-
-
-## [Demo_pyfiglet.pyw](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_pyfiglet.pyw)
-
-
-## [Demo_PyGame_Integration.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PyGame_Integration.py)
-
-
-## [Demo_PyGame_Snake_Game.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_PyGame_Snake_Game.py)
-
-
-## [Demo_Pyplot_Bar_Chart.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Pyplot_Bar_Chart.py)
-
-
-## [Demo_Pyplot_Bar_Chart2.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Pyplot_Bar_Chart2.py)
-
-
-## [Demo_Radio_Buttons_Simulated.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Radio_Buttons_Simulated.py)
-
-
-## [Demo_Save_Any_Window_As_Image.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Save_Any_Window_As_Image.py)
-
-
-## [Demo_Save_Windows_As_Images.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Save_Windows_As_Images.py)
-
-
-## [Demo_Script_Launcher.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Script_Launcher.py)
-
-
-## [Demo_Script_Launcher_ANSI_Color_Output.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py)
-
-
-## [Demo_Script_Launcher_Realtime_Output.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py)
-
-
-## [Demo_SDK_Help_Func_Parms.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_SDK_Help_Func_Parms.py)
-
-
-## [Demo_SDK_Help_Init_Update_Parms.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_SDK_Help_Init_Update_Parms.py)
-
-
-## [Demo_Separator_Elements.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Separator_Elements.py)
-
-
-## [Demo_Settings_Save_Load.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Settings_Save_Load.py)
-
-
-## [Demo_Simple_Material_Feel.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Simple_Material_Feel.py)
-
-
-## [Demo_Sort_Visualizer.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Sort_Visualizer.py)
-
-
-## [Demo_Spinner_Compound_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Spinner_Compound_Element.py)
-
-
-## [Demo_Spin_Element_Wraps_Around.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Spin_Element_Wraps_Around.py)
-
-
-## [Demo_Status_Bar.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Status_Bar.py)
-
-
-## [Demo_Sudoku.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Sudoku.py)
-
-
-## [Demo_Sudoku_1_Line.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Sudoku_1_Line.py)
-
-
-## [Demo_Super_Simple_Form.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Super_Simple_Form.py)
-
-
-## [Demo_System_Tray_GUI_Window_Design_Pattern.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_System_Tray_GUI_Window_Design_Pattern.py)
-
-
-## [Demo_System_Tray_Icon.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_System_Tray_Icon.py)
-
-
-## [Demo_System_Tray_Icon_Using_psgtray.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py)
-
-
-## [Demo_System_Tray_Icon_Using_psgtray.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_System_Tray_Icon_Using_psgtray.py)
-
-
-## [Demo_System_Tray_Reminder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_System_Tray_Reminder.py)
-
-
-## [Demo_Table_CSV.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_CSV.py)
-
-
-## [Demo_Table_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_Element.py)
-
-
-## [Demo_Table_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_Element.py)
-
-
-## [Demo_Table_Pandas.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_Pandas.py)
-
-
-## [Demo_Table_Simulation.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_Simulation.py)
-
-
-## [Demo_Table_Simulation_Arrow_Keys.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py)
-
-
-## [Demo_Tabs.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Tabs.py)
-
-
-## [Demo_Tabs_Nested.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Tabs_Nested.py)
-
-
-## [Demo_Tabs_Simple.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Tabs_Simple.py)
-
-
-## [Demo_Text_Element_Autosize.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Text_Element_Autosize.py)
-
-
-## [Demo_Theme_Add_Your_Own.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Add_Your_Own.py)
-
-
-## [Demo_Theme_Browser.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Browser.py)
-
-
-## [Demo_Theme_Change_Your_Windows_Theme.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Change_Your_Windows_Theme.py)
-
-
-## [Demo_Theme_Color_Swatches.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Color_Swatches.py)
-
-
-## [Demo_Theme_Custom_Saved_In_UserSettings.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Custom_Saved_In_UserSettings.py)
-
-
-## [Demo_Theme_Previewer_Dark.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Theme_Previewer_Dark.py)
-
-
-## [Demo_Titlebar_Custom_Async.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Titlebar_Custom_Async.py)
-
-
-## [Demo_Titlebar_Custom_Dark_Theme.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Titlebar_Custom_Dark_Theme.py)
-
-
-## [Demo_Titlebar_Custom_Multiple_Combinations.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Titlebar_Custom_Multiple_Combinations.py)
-
-
-## [Demo_Titlebar_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Titlebar_Element.py)
-
-
-## [Demo_Touch_Keyboard.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Touch_Keyboard.py)
-
-
-## [Demo_Tree_Element.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Tree_Element.py)
-
-
-## [Demo_TTK_Scrollbars.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_TTK_Scrollbars.py)
-
-
-## [Demo_Turtle.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Turtle.py)
-
-
-## [Demo_Unicode_Characters.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Unicode_Characters.py)
-
-
-## [Demo_Uno_Card_Game.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Uno_Card_Game.py)
-
-
-## [Demo_User_Settings.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Settings.py)
-
-
-## [Demo_User_Settings_As_Simple_Database.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Settings_As_Simple_Database.py)
-
-
-## [Demo_User_Settings_Browse_File_Folder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Settings_Browse_File_Folder.py)
-
-
-## [Demo_User_Settings_Class.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Settings_Class.py)
-
-
-## [Demo_User_Settings_Class.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Settings_Class.py)
-
-
-## [Demo_User_Setting_Save_Window_Inputs.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_User_Setting_Save_Window_Inputs.py)
-
-
-## [Demo_Window_Background_Image.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Background_Image.py)
-
-
-## [Demo_Window_Disappear.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Disappear.py)
-
-
-## [Demo_Window_Location_Finder.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Location_Finder.py)
-
-
-## [Demo_Window_Open_Multiple_Times.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Open_Multiple_Times.py)
-
-
-## [Demo_Window_Pin_On_Top.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Pin_On_Top.py)
-
-
-## [Demo_Window_Relative_Location.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Relative_Location.py)
-
-
-## [Demo_Window_Relative_Location.py](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Window_Relative_Location.py)
-
-
diff --git a/docs/Screens.md b/docs/Screens.md
deleted file mode 100644
index 23a4da7f..00000000
--- a/docs/Screens.md
+++ /dev/null
@@ -1,1534 +0,0 @@
-[splatert](https://github.com/splatert) 2023-11-19T04:48:55Z
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-11-07T14:22:15Z
-
-
-
------------
-
-[SaSp73](https://github.com/SaSp73) 2023-11-07T09:35:57Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-10-26T09:38:54Z
-
-
-
------------
-
-[ikeman32](https://github.com/ikeman32) 2023-10-25T21:58:09Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-10-21T16:11:14Z
-
-
-
------------
-
-[onyx-and-iris](https://github.com/onyx-and-iris) 2023-09-06T00:00:13Z
-
-
-
------------
-
-[definite-d](https://github.com/definite-d) 2023-08-26T16:34:23Z
-
-
-
-
------------
-
-[luisegarduno](https://github.com/luisegarduno) 2023-06-25T05:18:40Z
-
-
-
------------
-
-[mrtnbm](https://github.com/mrtnbm) 2023-05-25T16:24:22Z
-
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2023-05-24T04:03:28Z
-
-
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2023-05-24T02:35:07Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-05-12T09:55:03Z
-
-
-
------------
-
-[zaricj](https://github.com/zaricj) 2023-04-19T09:55:26Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-03-16T18:56:49Z
-
-
-
------------
-
-[lucasmartins19](https://github.com/lucasmartins19) 2023-03-14T21:50:57Z
-
-
-
-
-
-
-
-
-
------------
-
-[J-Josu](https://github.com/J-Josu) 2023-02-14T12:29:42Z
-
-
-
------------
-
-[chanon-kr](https://github.com/chanon-kr) 2023-02-14T06:27:10Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-02-08T22:16:35Z
-
-
-
------------
-
-[J-Josu](https://github.com/J-Josu) 2023-01-30T13:20:08Z
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-01-29T15:31:26Z
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2023-01-28T02:30:37Z
-
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2023-01-04T23:30:35Z
-
-
-
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2022-12-18T21:41:57Z
-
-
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2022-12-18T19:36:12Z
-
-
-
-
------------
-
-[kevinsmia1939](https://github.com/kevinsmia1939) 2022-11-27T20:08:24Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-11-20T17:25:00Z
-
-
-
-
------------
-
-[grahamperrin](https://github.com/grahamperrin) 2022-11-19T02:38:40Z
-
-
-
------------
-
-[kevinsmia1939](https://github.com/kevinsmia1939) 2022-11-06T02:26:54Z
-
-
-
------------
-
-[dwelden](https://github.com/dwelden) 2022-10-21T19:16:53Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-20T17:00:32Z
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-06T17:12:16Z
-
-
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-10-06T13:16:36Z
-
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-10-03T19:01:04Z
-
-
-
------------
-
-[definite-d](https://github.com/definite-d) 2022-10-01T16:38:20Z
-
-
-
------------
-
-[physcofury](https://github.com/physcofury) 2022-09-25T10:00:25Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-24T15:34:14Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-24T15:11:30Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-20T16:21:44Z
-
-
-
------------
-
-[vasja34](https://github.com/vasja34) 2022-08-26T10:39:11Z
-
-
-
-
-
------------
-
-[dennisbyington](https://github.com/dennisbyington) 2022-08-24T17:45:32Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-08-12T17:48:51Z
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-08-11T18:55:00Z
-
-
-
------------
-
-[pithoner](https://github.com/pithoner) 2022-07-30T01:07:47Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-07-10T06:13:54Z
-
-
-
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-06-27T04:35:24Z
-
-
-
-
------------
-
-[jerrylususu](https://github.com/jerrylususu) 2022-06-23T13:05:19Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-20T16:42:25Z
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-20T16:22:36Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-20T11:28:20Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-18T12:50:10Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-15T10:41:07Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-13T11:49:29Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-11T21:59:48Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-11T21:43:40Z
-
-
-
-
-
------------
-
-[VatsalP](https://github.com/VatsalP) 2022-06-11T00:30:56Z
-
-
-
------------
-
-[lonewanderer27](https://github.com/lonewanderer27) 2022-06-09T09:12:22Z
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-08T11:33:09Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-07T12:48:16Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-07T12:31:48Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-06T02:12:11Z
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-06-05T20:27:42Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T19:42:55Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T12:13:02Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T12:11:44Z
-
-
-
------------
-
-[macdeport](https://github.com/macdeport) 2022-06-05T08:35:05Z
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-06-05T00:10:14Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T23:34:38Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T23:17:34Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T22:27:46Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T22:17:00Z
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-05-31T06:58:52Z
-
-
-
-
-
-
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-05-02T15:50:00Z
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2022-05-01T12:40:06Z
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2022-05-01T11:03:33Z
-
-
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-04-17T01:08:06Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-04-16T19:21:39Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-04-16T13:08:06Z
-
-
-
------------
-
-[wrwetzel](https://github.com/wrwetzel) 2022-04-16T12:27:46Z
-
-
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-04-06T21:17:33Z
-
-
-
------------
-
-[gfcwfzkm](https://github.com/gfcwfzkm) 2022-04-06T15:08:50Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-24T16:02:11Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-24T15:53:14Z
-
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-03-22T07:14:12Z
-
-
-
------------
-
-[NFadhlurrahman](https://github.com/NFadhlurrahman) 2022-03-20T13:47:20Z
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-03-14T22:37:40Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-08T22:12:47Z
-
-
-
------------
-
-[resnbl](https://github.com/resnbl) 2022-03-07T22:17:13Z
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-03-03T19:59:59Z
-
-
-
------------
-
-[Zilversmit](https://github.com/Zilversmit) 2022-02-28T00:22:25Z
-
-
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-26T05:17:23Z
-
-
-
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-20T06:53:03Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-16T17:06:49Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-08T14:07:12Z
-
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-02-08T08:58:44Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-07T01:20:01Z
-
-
-
-
------------
-
-[bouc79](https://github.com/bouc79) 2022-02-06T22:41:19Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-06T14:32:34Z
-
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-06T09:04:59Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-05T13:09:31Z
-
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-04T09:56:34Z
-
-
-
------------
-
-[cosme12](https://github.com/cosme12) 2022-02-02T01:50:45Z
-
-
-
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-02T01:01:39Z
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-02-02T01:01:13Z
-
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-02-02T00:35:46Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-27T23:21:27Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-27T21:31:02Z
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2022-01-27T20:10:58Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-24T15:28:45Z
-
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-01-24T12:06:52Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-01-23T13:53:09Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-17T18:34:55Z
-
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2022-01-16T21:53:25Z
-
-
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-01-16T15:01:47Z
-
-
-
------------
-
-[tostos5963](https://github.com/tostos5963) 2022-01-13T22:13:15Z
-
-
-
------------
-
-[tostos5963](https://github.com/tostos5963) 2022-01-13T15:26:56Z
-
-
-
------------
-
-[shullaw](https://github.com/shullaw) 2022-01-13T02:19:24Z
-
-
-
------------
-
-[Cornbrother](https://github.com/Cornbrother) 2022-01-07T18:47:55Z
-
-
-
------------
-
-[autostatic](https://github.com/autostatic) 2021-12-27T15:43:43Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-20T15:41:30Z
-
-
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-20T15:25:43Z
-
-
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-19T17:07:16Z
-
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-19T13:29:03Z
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2021-12-08T17:34:51Z
-
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-05T00:39:31Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-02T16:14:05Z
-
-
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-02T16:07:45Z
-
-
-
-
------------
-
-[Vresod](https://github.com/Vresod) 2021-11-23T23:47:10Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-23T15:28:51Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-23T14:57:40Z
-
-
-
------------
-
-[frici11](https://github.com/frici11) 2021-11-23T13:41:00Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-20T12:17:53Z
-
-
-
------------
-
-[luflopes](https://github.com/luflopes) 2021-11-19T21:30:33Z
-
-
-
-
-
-
-
------------
-
-[Pranav-P-16](https://github.com/Pranav-P-16) 2021-11-04T02:55:59Z
-
-
-
-
-
-
------------
-
-[Pranav-P-16](https://github.com/Pranav-P-16) 2021-10-31T04:14:25Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-10-22T14:51:31Z
-
-
-
-
------------
-
-[mechanicalnull](https://github.com/mechanicalnull) 2021-10-22T12:04:54Z
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2021-09-25T11:30:05Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-09-04T14:37:53Z
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2021-09-04T07:29:45Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-31T13:09:22Z
-
-
-
------------
-
-[readicculus](https://github.com/readicculus) 2021-08-30T22:16:48Z
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-11T20:28:32Z
-
-
-
------------
-
-[AyhamSaffar](https://github.com/AyhamSaffar) 2021-08-11T00:21:44Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-07T16:30:26Z
-
-
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2021-08-07T11:00:56Z
-
-
-
------------
-
-[vinniec](https://github.com/vinniec) 2021-08-07T07:57:36Z
-
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2021-06-24T05:44:57Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2021-05-27T07:20:01Z
-
-
-
------------
-
-[Fethbita](https://github.com/Fethbita) 2021-05-20T15:10:13Z
-
-
-
------------
-
-[elibroftw](https://github.com/elibroftw) 2021-05-02T00:27:51Z
-
-
-
-
------------
-
-[daemon2021](https://github.com/daemon2021) 2021-04-28T08:26:39Z
-
-
-
------------
-
-[pamoroso](https://github.com/pamoroso) 2021-04-21T14:05:25Z
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-05T13:31:15Z
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-05T05:28:37Z
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-04T22:05:55Z
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-04T08:23:29Z
-
-
-
------------
-
-[pgbowers](https://github.com/pgbowers) 2021-03-25T14:59:48Z
-
-
-
------------
-
-[ThomasFreedman](https://github.com/ThomasFreedman) 2021-03-17T14:40:26Z
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-03-10T16:42:53Z
-
-
-
------------
-
-[ill13](https://github.com/ill13) 2021-03-08T22:03:07Z
-
-
-
------------
-
-[vinniec](https://github.com/vinniec) 2021-03-04T20:44:34Z
-
-
-
-
------------
-
-[pgbowers](https://github.com/pgbowers) 2021-03-02T14:55:14Z
-
-
-
------------
-
-[techtanic](https://github.com/techtanic) 2021-02-03T16:11:53Z
-
-
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2021-02-02T10:18:38Z
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-12-31T20:08:31Z
-
-
-
------------
-
-[ingoogni](https://github.com/ingoogni) 2020-12-28T13:30:50Z
-
-
-
------------
-
-[d-flood](https://github.com/d-flood) 2020-12-23T13:20:24Z
-
-
-
-
------------
-
-[mo-han](https://github.com/mo-han) 2020-12-09T00:47:23Z
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-11-25T21:26:16Z
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-11-25T12:56:45Z
-
-
-
------------
-
-[Kodikuu](https://github.com/Kodikuu) 2020-11-06T18:01:53Z
-
-
-
------------
-
-[Kodikuu](https://github.com/Kodikuu) 2020-11-06T12:18:24Z
-
-
-
------------
-
-[PyICoder](https://github.com/PyICoder) 2020-11-02T07:27:14Z
-
-
-
------------
-
-[d-flood](https://github.com/d-flood) 2020-11-01T23:49:39Z
-
-
-
------------
-
-[mainer-hat](https://github.com/mainer-hat) 2020-10-27T15:56:03Z
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-16T03:26:07Z
-
-
-
-
------------
-
-[alexBoldea](https://github.com/alexBoldea) 2020-10-15T19:44:28Z
-
-
-
-
-
------------
-
-[gregorystorer](https://github.com/gregorystorer) 2020-10-14T07:03:30Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-12T16:33:55Z
-
-
-
-
-
------------
-
-[amantotek](https://github.com/amantotek) 2020-10-12T14:56:34Z
-
-
-
------------
-
-[holypython](https://github.com/holypython) 2020-10-05T20:03:05Z
-
-
-
-
------------
-
-[aajshaw](https://github.com/aajshaw) 2020-09-26T13:25:57Z
-
-
-
------------
-
-[PySimpleSQL](https://github.com/PySimpleSQL) 2020-08-25T20:27:00Z
-
-
-
-
------------
-
-[moabdali](https://github.com/moabdali) 2020-08-12T05:31:19Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-08T11:11:29Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-05T13:31:05Z
-
-
-
-
------------
-
-[dfatka](https://github.com/dfatka) 2020-08-03T22:01:21Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-02T17:28:23Z
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-07-05T16:45:42Z
-
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-07-04T15:43:31Z
-
-
-
------------
-
-[kovadarra](https://github.com/kovadarra) 2020-06-17T10:28:51Z
-
-
-
-
------------
-
-[martinmeteor](https://github.com/martinmeteor) 2020-06-14T15:36:26Z
-
-
-
-
-
-
-
------------
-
-[sharathraj-tech](https://github.com/sharathraj-tech) 2020-06-08T03:38:01Z
-
-
-
-
-
-
-
------------
-
-[mbilalakmal](https://github.com/mbilalakmal) 2020-06-07T02:07:48Z
-
-
-
-
------------
-
-[ChristianReizner](https://github.com/ChristianReizner) 2020-06-06T15:50:19Z
-
-
-
-
-
-
-
-
------------
-
-[Zain-Bin-Arshad](https://github.com/Zain-Bin-Arshad) 2020-05-31T07:43:59Z
-
-
-
-
------------
-
-[Ruakuu](https://github.com/Ruakuu) 2020-04-30T09:07:13Z
-
-
-
-
------------
-
-[sharathraj-tech](https://github.com/sharathraj-tech) 2020-03-27T17:06:56Z
-
-
-
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2020-01-02T21:30:42Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-12-06T16:10:09Z
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-11-22T15:39:35Z
-
-
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-10-31T02:23:51Z
-
-
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-08-25T22:30:11Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-08-24T03:27:25Z
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-08-23T23:32:40Z
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-08-11T09:52:53Z
-
-
-
-
-
------------
-
-[IsaacLance](https://github.com/IsaacLance) 2019-08-10T03:43:47Z
-
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-08-07T23:34:58Z
-
-
-
------------
-
-[killyone](https://github.com/killyone) 2019-06-20T04:15:02Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-03-25T15:44:50Z
-
-
-
-
-
-
------------
-
-[btnpushnmunky](https://github.com/btnpushnmunky) 2018-12-14T16:50:36Z
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-28T15:43:40Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-24T05:46:53Z
-
-
-
-
-
-
-
-
------------
-
-[john144](https://github.com/john144) 2018-11-20T20:12:20Z
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-18T16:55:15Z
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-18T16:54:32Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-16T03:08:43Z
-
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-12T17:58:27Z
-
-
-
-
------------
-
-[john144](https://github.com/john144) 2018-11-04T03:03:06Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-04T00:22:20Z
-
-
-
------------
-
-[AltoRetrato](https://github.com/AltoRetrato) 2018-10-29T17:45:47Z
-
-
-
------------
-
-[iris-chang](https://github.com/iris-chang) 2018-10-24T07:04:44Z
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-10-03T21:54:34Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-10-02T20:18:39Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-09-30T21:37:08Z
-
-
-
-
-
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-09-16T21:26:51Z
-
-
-
------------
-
diff --git a/docs/Screens2.md b/docs/Screens2.md
deleted file mode 100644
index 43e8598c..00000000
--- a/docs/Screens2.md
+++ /dev/null
@@ -1,5497 +0,0 @@
-[splatert](https://github.com/splatert) 2023-11-19T04:48:55Z
-Hello. I would like to thank you for the awesome UI framework you built as it really does help create interfaces in a really simple manner. I've given credit to you on my project's readme file and provided a link that leads to your github page.
-
-With the power of your library, I've created an alternative UI frontend for SpotDL. A tool for downloading Spotify tracks using URLs that you provide. Now SpotDL does have their own interface which is loaded onto the web browser but It felt like it was slow as it took a couple of seconds to start up, which is why I wanted to create my own.
-
-
-
-The way this frontend is used is that you provide each link into the interface's textbox then hit the plus button to pass them to a list of URLs (which then the listbox shown above displays the urls list).
-
-Upon providing URLs, you then press the download button to initiate the download process (given that you provide the SpotDL executable).
-
-
-If the control shown above is checked, the program would ask you to provide a name for the folder you want to create and send downloaded songs to. Prompt dialog is shown below.
-
-
-Pressing **OK** will assign the folder name to a string variable then tell the program that you want to create a folder.
-Pressing **Cancel** or having the checkbox mentioned above unmarked would not tell the program to create any folders.
-
-
-After information is provided, the program executes SpotDL with the links you entered passed as arguments and will wait for it to complete the download job.
-
-
-
-After the download job is finished, songs get transferred over to the frontend's music directory and you will get a message saying that the download process has been completed.
-
-
-
-
-Here's a link to the project repository.
-https://github.com/splatert/spotdl-ui
-
------------
-
-[SaSp73](https://github.com/SaSp73) 2023-11-07T15:52:58Z
-Thanks for your kind words. I will send you the code in a couple of days when I return back home.
-It need some extra hardware (PICAN-M board, Adafruit ADC and BME280 barometer), but you will manage to get around this with a little bit of tinkering.
-Basically the whole control is a graph with elements redrawing according to the calculated data...
-
-BTW, a Rotate_Figure(figure_id, center_point, degrees_of_rotation) would be very helpful (I will open a suggestion later)
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-11-07T14:22:15Z
-WOW @SaSp73 !!
-
-
-
-Truly mind-blowing and very inspiring to see. I've never seen anything like this done with PySimpleGUI! One of the things I love about this project are the surprises by what people create.
-
-I would love to see how you did some of the things you did if you ever care to share the code (even privately would be great.... I'll be confidential. I'm curious what features were helpful).
-
-Thank you so so much for sharing.
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2023-11-07T11:01:09Z
-Wow
-Those graphics are fantastic. Thanks for sharing.
-
-
------------
-
-[SaSp73](https://github.com/SaSp73) 2023-11-07T09:35:57Z
-This is my use of PySimpleGUI, a program reading NMEA200 networks, running on raspberry pi 4, and presenting various data used for sail racing.
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-10-26T09:38:54Z
-We're on very similar wavelengths @ikeman32. It's great to see some add-on tools to help users.
-
-As part of the PySimpleGUI 5 release of the PySimpleGUI applications and add-on modules, I've written a GUI tool that creates all of the necessary files to upload a PySimpleGUI application to PyPI, opening up distribution of Python applications to PySimpleGUI users. We've been releasing tools via PyPI for some time. "psgresizer" is a good example. Users can pip install it and then once installed it can be run by typing "psgresizer" from the command line. There's already a tool, psgshortcut, that takes it all a start further by making shortcuts (icons) that can be pinned to the taskbar or double-clicked.
-
-The idea is to make distribution easy as well as the result be familiar feeling. The command line isn't a normal part of a normal Windows user's world, so getting it out of the way entirely makes a lot of sense. I've just about got the final tool finished that will make it all work end to end.
-
-
-
-
------------
-
-[ikeman32](https://github.com/ikeman32) 2023-10-25T21:58:09Z
-I have created a simple bash script to initialize a PySimpleGUI project. It can be found here: https://github.com/ikeman32/ScriptHelpers/tree/main/devscripts
-
-It's very basic at the moment, but functional. For Windows users, I do have an AI-generated port, but it remains untested as I gave up my Windows addiction in 2017. I may eventually create a platform-independent version of the script using Python.
-
-I do accept code contributions, so if there are Windows users that want to develop a Windows batch equivalent or a Python version of this script, see the README. Or you can code your own.
-
-PySimpleGUI is an absolute God-sent for me. I like simplicity, and I am also lazy, so if there is an easier way to do something, I'm all for it. I'm also in the planning stages for a visual editor/IDE for PySimpleGUI applications.
-
-
-
-
-
-
-
------------
-
-[maria-korosteleva](https://github.com/maria-korosteleva) 2023-10-23T09:26:11Z
-@PySimpleGUI Thank you very much for your kind words! 🥰
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-10-21T16:11:14Z
-Wow @maria-korosteleva what an incredible application! I love what you've created! 
-
-I've never seen anything like what you've made. There's clearly a **lot** going on with your work than just a GUI. I had never thought about the intersection of CAD and making garments. It's a fascinating use of technology. I really appreciate you taking the time to post a screenshot and letting us know about your project.
-
------------
-
-[maria-korosteleva](https://github.com/maria-korosteleva) 2023-10-20T11:52:13Z
-I've used the framework to build a garment design configurator in my latest research paper on programmable garments =)
-https://github.com/maria-korosteleva/GarmentCode
-https://igl.ethz.ch/projects/garmentcode/
-
-
-
-
------------
-
-[onyx-and-iris](https://github.com/onyx-and-iris) 2023-09-06T00:00:13Z
-A small remote utility for Voicemeeter, designed to work with the NVDA screen reader.
-
-
-https://github.com/onyx-and-iris/nvda-voicemeeter
-
-Thanks for creating PYSimpleGUI, first time using but very impressed!
-
-
-
------------
-
-[definite-d](https://github.com/definite-d) 2023-08-26T16:34:23Z
-[Themera](https://github.com/definite-d/Themera) v2.1.0 has been released (available [here](https://github.com/definite-d/Themera/releases/tag/v2.1.0)). I'd like to share screenshots and point out that with Windows 11, the color of the "built-in" titlebar can be customized. I accomplished it within Themera with a bit of a non-standard solution, but it's proof of concept.
-
-
-
-
-
------------
-
-[luisegarduno](https://github.com/luisegarduno) 2023-06-25T05:18:40Z
-**Chess (updated!)**
-
-Originally added/created by @MikeTheWatchGuy, the chess demos (player vs. player & player vs. Ai) were included in PySimpleGUI ([see here](https://github.com/PySimpleGUI/PySimpleGUI/tree/8b23740fca08b7f5bad3f0d32760f42a5202d3e1/Chess)), but were removed from the main branch towards the end of 2022.
-
-In terms of the changes that I made to the original code (see #5052):
-
-I updated **requirements.txt** to include the latest versions:
-```
-PySimpleGUI==4.60.5
-python-chess==1.999
-```
-I then made changes within both of the demo files to remove any outdated or deprecated code causing errors. I also added compatibility for Linux, allowing users to import files that do not end in ".exe".
-
-Both chess demos have only been tested on Ubuntu 20.04 but should also work on Windows since not much was changed from the original code. Lastly, for the engine, I resulted in having to use Stockfish 13, since there was several issues when trying to use Stockfish 14 or Stockfish 15.
-
-https://github.com/luisegarduno/ChessGUI
-
-
-
------------
-
-[mrtnbm](https://github.com/mrtnbm) 2023-05-25T16:24:22Z
-Thanks to PSG, I've created the nicest GUI I've ever made that I'm now using for my own little naive prompt lib.
-
-- Main window:
-
-
-- Edit Window:
-
-
-The heart can be clicked and will change to outline or fill mode.
-
- - For reference, here is a screenshot without rescaling:
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2023-05-24T04:03:28Z
-Started this a few days ago. Thanks to PSG it has already proven the hypothesis as valid - Streamlining novel development in a curated parameter driven manner with op3nAI API. Much more functionality to add in, but what an amazing GUI framework <3 <3 <3 And thanks to @jason990420 for all of the tkinter hacks he's posted which has always covered everything I've needed :)
-
-
-
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2023-05-24T02:35:07Z
-
-not finish yet
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-05-12T09:55:03Z
-I saw this awesome screenshot:
-
-
-
-posted in the readme for this project:
-
-https://github.com/bsanders2/FrosthavenApp
-
-It's got a nice design and the custom buttons look great.
-
------------
-
-[zaricj](https://github.com/zaricj) 2023-04-19T09:55:26Z
-I've been using PySimpleGUI to make a GUI for the Chocolatey Package Manager, thought of sending a screenshot of it here.
-
-
-
-Thanks for this amazing module, I'm really having fun learning it!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-03-16T18:56:49Z
-@ssweber the color scheme looks like the `GrayGrayGray` theme to me which means no colors will be added (all system defaults will be used). The important feature that's adding the images is either `Image` elements or `Button` elements. Using a Base64 version of images will enable you to drop them directly into your source code. The PySimpleGUI application `psgresizer` is very helpful in enabling you to quickly add button graphics to your application.
-
-Here are some steps I followed:
-
-- I made a video of a session where I took images that I clipped from @lucasmartins19 's application and saved them as PNG files
-- Used `psgresizer` to convert each PNG file into a Base64 string
-- Pasted the Base64 string into my test program
-- Created a layout that used these Base64 images using the `Image` element.
-
-My layout looked liket his:
-```python
- layout = [ [sg.Text('Base64 Images Example')],
- [sg.Image(b1, key='-I1-')],
- [sg.Image(b2, key='-I2-')],
- [sg.Image(b3, key='-I3-')],
- [sg.Button('Go'), sg.Button('Exit')] ]
-```
-
-When I ran the code, this is the window I saw:
-
-
-
-If you enable events on the `Image` elements, then you'll get an event when the image is clicked.
-
-```python
- layout = [ [sg.Text('Base64 Images Example')],
- [sg.Image(b1, key='-I1-', enable_events=True)],
- [sg.Image(b2, key='-I2-', enable_events=True)],
- [sg.Image(b3, key='-I3-', enable_events=True)],
- [sg.Button('Go'), sg.Button('Exit')] ]
-```
-
-Here's how the process to do all this looked:
-
-
-https://user-images.githubusercontent.com/46163555/225724860-33b5b5ba-9e63-4159-9ccc-825b72aef11a.mp4
-
-
-
------------
-
-[lucasmartins19](https://github.com/lucasmartins19) 2023-03-16T14:04:53Z
-> @lucasmartins19 That looks amazing. Would you mind uploading that to a repository? I’m working on a general purpose pysimplegui toolkit and I really like your color-scheme /buttons. Would like to see how you put that all together.
-
-Thank you!
-
-Currently, I have a private one to manage everything and provide updates through GitHub. However, I will create a new private repository and invite you as a collaborator. Please feel free to ask me if you need any help understanding anything.
-
------------
-
-[ssweber](https://github.com/ssweber) 2023-03-16T13:22:48Z
-@lucasmartins19 That looks amazing. Would you mind uploading that to a repository? I’m working on a general purpose pysimplegui toolkit and I really like your color-scheme /buttons. Would like to see how you put that all together.
-
------------
-
-[lucasmartins19](https://github.com/lucasmartins19) 2023-03-14T21:50:57Z
-Hi!
-I developed this simple application using PySimpleGUI to help my cousin manage his optics lab.
-Don't mind the data, it was randomly generated for testing purposes.
-
-
-
-
-
-
-
-
-
-
-
-
-
------------
-
-[J-Josu](https://github.com/J-Josu) 2023-02-14T12:29:42Z
-> Thank you @J-Josu  for sharing your program and your story. I love hearing when students use PySimpleGUI! I'm glad it went well. The screenshots look great!
->
-> Code annotation too? Do you have a GitHub Repo with your code?
->
-> I'm impressed by bi-lingual programmers. It's hard enough coding, reading, writing, and thinking just in English. Throwing another language on top of all that is next-level stuff. Really happy you posted what you've made!
-
-Hi @PySimpleGUI, yes i have uploaded the project to the following [repository](https://github.com/J-Josu/FiguRace)
-
-Thanks you for all!
-
------------
-
-[chanon-kr](https://github.com/chanon-kr) 2023-02-14T06:27:10Z
-Hi, I use PySimpleGUI to make a Simple Object Detection GUI with YOLOv8.
-
-Check my GitHub repo from this link.
-
-[Simple Object Detection GUI](https://github.com/chanon-kr/simple_imagui_app)
-
-And here is a screenshot of the GUI.
-
-
-
-Thanks to @PySimpleGUI for suggestions and improvement!!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-02-08T22:16:35Z
-Thank you @J-Josu  for sharing your program and your story. I love hearing when students use PySimpleGUI! I'm glad it went well. The screenshots look great!
-
-Code annotation too? Do you have a GitHub Repo with your code?
-
-I'm impressed by bi-lingual programmers. It's hard enough coding, reading, writing, and thinking just in English. Throwing another language on top of all that is next-level stuff. Really happy you posted what you've made!
-
------------
-
-[J-Josu](https://github.com/J-Josu) 2023-01-30T13:20:08Z
-Hi! I'm a stundent of Computer Science in Argentina and i`ve had to do a Final project for my Python Course. The project its about a card game where you can choose between availible themes to try to guess the correct option. The data is automtically loaded from cvs.
-
-Here are some screenshoots of the final result:
-
-
-
-
-
-
-
-
-
-And other pages...
-
-All the ui its in spanish, but the code all written in english.
-The project includes a mini-framework to build pages easly and some cli utilities.
-Also the code have all the corresponding typing annotations and more interesting stuff.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2023-01-29T15:31:26Z
-@eagleEggs I briefly saw a version of this GUI and then it disappeared. I'm THRILLED you've posted it. 
-
-Thank you so very much for sharing your talent in using PySimpleGUI. You're such an expert now and I SO appreciate you being here since the early days.
-
-That's a beautiful window.... just plain beautiful!
-
-Your support and encouragement have been really appreciated.
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2023-01-28T02:30:37Z
-PSG WOOOHOOOO. Super fast implementation of this thanks to PSG. We were able to jump straight into core code, and add new things on the fly in minutes. This is a vulnerability management / parser, scanner... and moreeeee.
-
-
-
-
-Thanks again PSG <3
-
------------
-
-[hseera](https://github.com/hseera) 2023-01-04T23:30:35Z
-Using PySimpleGUI framework, I built an opernsource tool called "CloudWatch Dashboard Builder" for SRE, Performance Engineers and Operations teams, who work with AWS services. It gives them capability to build CloudWatch Dashboard from different Namespace templates. The tool lets you modify the template too.
-
-
-
-
-And here is a link to youtube video showing how I am using this tool built with PySimpleGUI framework to create dashboard through the tool or through the generated JSON.
-
-https://www.youtube.com/watch?v=tPCHCc-GiHM
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-12-19T00:24:35Z
-@kubilayyalcinyt Let's move the detailed discussion of your questions over to your previously opened issue #6028 rather than this issue which is for users to post screenshots of applications.
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2022-12-18T21:41:57Z
-
-this is what ı say ı can't do like my tiling manager
-
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2022-12-18T21:05:02Z
-okay ı try example finish ı ask again
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-12-18T20:23:37Z
-@kubilayyalcinyt - this looks similar to the window you posted in an issue a month ago. A bit more information about what you're trying to do would be helpful. Feel free to re-open the issue you closed and we'll do our best to help.
-
------------
-
-[gnuchanos](https://github.com/gnuchanos) 2022-12-18T19:36:12Z
-
-
-how ı create like this window first login screen second normal window ı try but ı can't do
-
------------
-
-[kevinsmia1939](https://github.com/kevinsmia1939) 2022-11-27T20:08:24Z
-I upload my first app, PySimpleCV to Flathub! Thanks to PySimpleGUI.
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2022-11-21T04:13:28Z
-@definite-d Could you share the code for your login screen screenshot? Is that with TK??? I'm very curious of how you approached the design for that if it is TK version of PSG - ty.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-11-20T17:25:00Z
-Noticed a couple of screenshots appeared in the readme for @kevinsmia1939 [PySimpleCV project](https://github.com/kevinsmia1939/PySimpleCV) and am copying them to here since the one in the original post has gone missing.
-
-
-
-
-
-
------------
-
-[grahamperrin](https://github.com/grahamperrin) 2022-11-19T02:38:40Z
-A shot of the title bar for the front page of this repo:
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-11-07T00:31:32Z
-@kevinsmia1939 it appears your screenshot has disappeared.
-
-A quick reminder to everyone to feel free to copy and paste your images directly into the issue comment. This will make a copy that's permanent to this issue. You can drag and drop an image or copy and paste it from your clipboard. GitHub automatically uploads the image and stores it as part of this repo.
-
------------
-
-[kevinsmia1939](https://github.com/kevinsmia1939) 2022-11-06T02:26:54Z
-I use PySimpleGUI to create PySimpleCV. PySimpleCV is use for calculation cyclic voltammetry chemical reaction reversibility and battery cycling performance.
-https://github.com/kevinsmia1939/PySimpleCV
-Very awesome project, thank you.
-
-
-
-
------------
-
-[dwelden](https://github.com/dwelden) 2022-10-21T19:16:53Z
-[SnowQuery](https://github.com/dwelden/SnowQuery)
-Simple Snowflake query application created with:
-
- 🐍 PySimpleGUI https://pysimplegui.org/
- ❄ Snowflake Connector for Python https://www.snowflake.com/
- ❖ PrettyTable https://github.com/jazzband/prettytable
-
-
-
-
-
-Without PySimpleGUI I never would have attempted such an application. Thanks Mike!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-20T17:00:32Z
-> It's using the main thread and an additional thread to consume the piped process leveraging PySimpleGUI's way to send data back to the main thread.
-
-Reading this triggered me to do a search to see if this design pattern is published as one and I do not believe it has been. I'm _**thrilled**_ to hear you're doing this!
-
-The PySimpleGUI utility `psgtest` uses this kind of design pattern. It was use twice before in 2 utilities that @Chr0nicT worked on, `psgcompiler` and the "Jump Cutter" project. Jump Cutter was for sure the first time we used it in a psg released program. It's a really powerful kind of pattern! It's certainly worthy of being in the Cookbook and a Demo Program in the future.
-
-Very nice when you can do something that's very time consuming and have the main GUI remain responsive. Great window design too BTW. That's a 5 star program!!
-    
-
-
------------
-
-[deckarep](https://github.com/deckarep) 2022-10-19T18:47:10Z
-Created a simple app for my wife to sync her local drives to the cloud. The app takes advantage of PySimpleGUI (of course) along with `rclone` under the hood by opening it as a subprocess and piping it's data into the app.
-
-The app is designed to be a safe way that she can sync the drives while managing Mac's power management during such a process. She's able to prematurely stop the process, restart it, capture log files and check tail the logs.
-
-It's using the main thread and an additional thread to consume the piped process leveraging PySimpleGUI's way to send data back to the main thread.
-
-Works great so far! (in the prototype state)...will be opening sourcing this at some point.
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-06T20:52:05Z
-@kcl1s ... Never doubted for a moment you appreciate what we're doing. I didn't do a good job of communicating that I could use a hand in flagging when there are problems, via GitHub issues, and also in finding out the root cause. That's what we're after ultimately... a fix to the problem.
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-10-06T20:18:51Z
-@PySimpleGUI. I appreciate all you do with this project as attested by my Paypal contribution a couple weeks ago.
-Regards
-Keith Lohmeyer
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-06T17:12:16Z
-Hiya @kcl1s I'm as frustrated with the current documentation situation as any/all other users.
-
-
-The search bug that happens in Chrome that evidently is back is particularly frustrating. The less time I spend on the current ReadTheDocs site, the better overall. These sceenshots in this issue have been added as a couple of tabs, but I'm otherwise putting all of my efforts into the next-generation docs.
-
-It's taking me a very long time to get the work completed, and released, but rest assured that new documentation is coming.
-
-
-It's the largest and most costly effort in the project's history. A _few_ examples, in addition to a complete overhaul of the format - the other 3 ports have call reference documentation/docstrings the eCookbook is integrated into the documentation as a tab, and significantly more. The search feature is working perfectly. You'll be happy with the results... this I'm sure.
-
-Hint - an Issue about the search is going to be of more help to the project than a hint in the screenshots area.
-
-It's great to see more of your work!  Keep building!!
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-10-06T13:16:36Z
-I am a hobbyist learning Python and have been looking at Beautiful Soup and web scraping. Since the search feature is down again for the psg docs (hint hint!) I thought it would be a good bs4 exercise to try scraping all the internal links on pysimplegui.org and make a crude search engine. Not really a great psg project but I thought I would share some shots. Code can be found here https://github.com/kcl1s/python/blob/master/psgSearch.py
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-10-05T09:10:12Z
-Hi all! Really sorry for the delay in responding... there is so much to be excited about.
-
--------------
-
-@definite-d LOVE IT! Haven't forgotten about your open issues and please be sure and look at the change made to menus recently so your theme changing picks up that change. You have nailed the point about "simple "not being limiting. In the docs I'm working on, I'm describing this "emergent" effect that simplifying has triggered. These user screenshots are an important part of explaining the point. Making operations simple, approachable, and accessible has enabled users to customize applications in ways far beyond what's normally accomplished in Python GUIs. **_The Simple Syntax has resulted in Complex Interfaces._**
-
-------------
-
-@kcl1s You continue to crank our some incredible projects! Thank you for posting them here! They're getting seen by quite a lot of people that use the documentation. People love seeing pictures and what a beautiful one you posted. Simple but beautiful just the same. And **what** it does is incredible!
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-10-03T19:01:04Z
-This is my latest project using PySimpleGUI. I just got a laser engraver and needed a way to convert .jpg clipart to .png and remove the backgrounds without dealing with a graphics program or online converter. I had luck creating a 12 line "proof of concept" script so I decided to use my favorite GUI to make it easy to use. I can remove white or black backgrounds with a slider to give some tolerance. I did a video of the process https://youtu.be/MZuxuoPsHcw I then found a way to do the conversion 100+ times faster with Numpy instead of Python loops so I documented that in this video https://youtu.be/WXISlAzddFA I also put the code on gitHub https://github.com/kcl1s/python/blob/master/TBGpsgNP.py
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-10-03T12:02:17Z
-That reskinner may be useful when paired with [darkdetect](https://github.com/albertosottile/darkdetect) :)
-
------------
-
-[definite-d](https://github.com/definite-d) 2022-10-01T16:38:20Z
-Hello @PySimpleGUI.
-
-I'd like to show you my latest attempt at a modern GUI, built with PySimpleGUI, featuring a custom modern HTML-style input element, [rounded buttons](https://github.com/PySimpleGUI/PySimpleGUI/issues/3412), a [custom theme](https://github.com/definite-d/themera) and [real-time theme changing](https://github.com/definite-d/psg_reskinner/).
-
-
-
-I can bet people would fail to realize that that's a PSG program without prior context.
-
-You were right when you said in the docs that the 'simple' in PySimpleGUI doesn't mean one can't make fantastic things with it.
-
------------
-
-[physcofury](https://github.com/physcofury) 2022-09-25T10:00:25Z
-> Here is the MP4 converted to GIF for the screenshot that @physcofury posted. GIF is required for the screenshot to appear in the screenshots tab of the docs.
->
-> 
-
-Ah thankyou didn't think i could make a gif, i'll be sure to post a gif of my POS when it's finished
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-24T15:34:14Z
-@physcofury why didn't you pick something a little more ambitious for your first project? A multi-window point of sale system with an onscreen keyboard? That's really incredible actually!
-
-
-7 months since **_starting_** to learn Python? Wow.... fast learner!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-24T15:11:30Z
-Here is the MP4 converted to GIF for the screenshot that @physcofury posted. GIF is required for the screenshot to appear in the screenshots tab of the docs.
-
-
-
-
------------
-
-[physcofury](https://github.com/physcofury) 2022-09-22T13:03:58Z
-https://user-images.githubusercontent.com/69250387/191753453-903bb44f-95a4-4992-8f9e-3c30add7af14.mp4
-I using PSG to create a POS system as my first coding project
-started learning python roughly 7 months ago
-the entire program is definitly still work in progress
-also im designing this to be used on windows touchscreen
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-09-20T16:21:44Z
-The newest test harness with location of python executable
-
-
-
-
------------
-
-[vasja34](https://github.com/vasja34) 2022-08-26T10:39:11Z
-Hi there,
-Here are some screenshots of my Chat Rooms Project.
-https://github.com/vasja34/Chat-Rooms-Project
-
-
-
-
-
-
-
-
-
-
------------
-
-[dennisbyington](https://github.com/dennisbyington) 2022-08-24T17:45:32Z
-Hi all,
-
-Here's a screenshot from a Wordle clone I made to learn GUIs. I used PSG after a few failed attempts with other GUI libraries - luckily PSG was far easier to understand and implement. Thank you for building a great product!
-
-Repo: https://github.com/dennisbyington/wordle_gui
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-08-12T17:48:51Z
-Very nice @kcl1s !! Love it! 
-
-It's not common to see screenshots from a Pi. The bonus of it being used to teach students AND having an accompanying YouTube video gets you extra credit!
-
-Thank you so much for sharing it. I've passed it around to several friends and other people working on the project that don't follow the GitHub.
-
-And of course, thank you for the kind words... they help a lot!
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-08-11T18:55:00Z
-Been a while since I have posted a project using my favorite GUI.
-This is Python on a RPi. I created a stand alone lab project to help students measure the speed of sound using an ultrasonic sensor. I have an explainer video on YT https://youtu.be/uA4RKeCI7r4
-Thanks for the great library!
-
-
-
------------
-
-[pithoner](https://github.com/pithoner) 2022-07-30T01:07:47Z
-Hi there, here are some screenshots of a fairly simple inventory manager that I'm working on. It uses an sql database to store the information.
-
-
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-07-17T10:53:53Z
-The new MSIX version of my application is now in the Microsoft Store! Feel free to check out the first PySimpleGUI program packaged into MSIX 🙂 https://www.microsoft.com/store/apps/9NMFSJB25QJR
-
-(You need Windows 11 or else it won't let you install.)
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-07-10T06:13:54Z
-@schlopp96
-> As you can see, I've developed a rather simplistic style prioritizing functionality and simplicity... Maybe not the prettiest of GUIs, but very functional and to-the-point!
-
-Py**Simple**GUI
-You're right in my groove, my way of looking at the world. Sometimes the pretty part gets so in the way that the functional part never happens. Personally, I like software that runs and does the job much more than software that's pretty but only runs in my head, never to be seen by others. An author friend from decades ago used to say that shipping something that's not perfect is a lot better than never shipping something that is perfect.
-
-Over the past 4 years, the overall "beauty" of PySimpleGUI has improved at a steady pace as can be seen in the screenshots from the initial release.
-
-
-I had SO much to learn and still have more to learn. These were on day 2 of PySimpleGUI's release.
-
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-07-10T05:21:41Z
-> > Working on packaging my app into MSIX for Microsoft Store distribution and the results are looking really promising! Just need to fix some working directory related issues.
-> > The benefit of packaging into MSIX is seamless installation, updating and uninstallation.
-> > 2022-07-06.20-39-16.mp4
-> > I will probably publish a tutorial soon on how to package your Python project into MSIX as there's hardly any information about it.
->
-> @infinitepower18 That looks _dope_!
->
-> I've personally had a lot of issues trying to use **pyinstaller** with several of my applications that utilize **PSG**, _especially_ if they involve multiple other packages; I'll definitely be looking forward to any tutorials you decide to upload!
->
-> I really like the easy-looking install/uninstall process and smooth setup that MSIX appears to have.
-
-Pyinstaller has issues related to being falsely detected by antivirus software, which is why I use Nuitka instead. Yes, it may take time to compile the application (takes nearly 10 mins on my laptop) but it's worth it and you won't face any false virus detections.
-
-I submitted it to the Microsoft Store and right now it's awaiting approval, but I can give an explanation of what I did:
-
-1. Compile the application using Nuitka, for a general idea of how to do it you can refer to this: https://nuitka.net/doc/user-manual.html#use-case-4-program-distribution
-
-2. Once the application is compiled, the dist folder contains the files that you package for distribution. Create an installer using [Inno Setup](https://jrsoftware.org/isinfo.php)
-
-3. Once you have the installer created, you then create a virtual machine and get all the updates installed. This is important because it's not gonna create the MSIX properly if you run the packaging tool on your main OS, you have to do it on a VM. Also, make sure you created a snapshot of the VM before packaging your app as you will need to revert to it once the process is over.
-
-4. Download [MSIX Packaging Tool](https://apps.microsoft.com/store/detail/msix-packaging-tool/9N5LW3JBCXKF) on the VM and follow the instructions to create a package. For the certificate part follow [these instructions](https://docs.microsoft.com/en-us/windows/msix/package/create-certificate-package-signing#use-new-selfsignedcertificate-to-create-a-certificate)
-
-5. Install the generated certificate so that you can install the MSIX, watch the below video to see how it's done properly:
-
-https://user-images.githubusercontent.com/44692189/178132315-a79300b9-e9dc-4bd3-b5d6-532ea5a2d8a3.mov
-
-The generated certificate is mainly for testing purposes. Once it's uploaded to the Microsoft Store it will sign it for you and users can download it from Microsoft Store without any issue. Yes, sideloading is possible but it will need a trusted certificate, I think MS Store will let you download a signed version afterwards that will install fine but will need to see once my app is approved.
-
-If I recall I didn't have to make any changes to my code for Nuitka to compile properly but for MSIX I did face issues related to working directory due to the way they're run. So it depends on how your app works and you may need to refer to Microsoft docs. In the end I could get my app to run properly but it took some time to figure things out.
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-07-10T02:17:23Z
-> Working on packaging my app into MSIX for Microsoft Store distribution and the results are looking really promising! Just need to fix some working directory related issues.
->
-> The benefit of packaging into MSIX is seamless installation, updating and uninstallation.
->
-> 2022-07-06.20-39-16.mp4
-> I will probably publish a tutorial soon on how to package your Python project into MSIX as there's hardly any information about it.
-
-@infinitepower18 That looks _dope_!
-
-I've personally had a lot of issues trying to use **pyinstaller** with several of my applications that utilize **PSG**, _especially_ if they involve multiple other packages; I'll definitely be looking forward to any tutorials you decide to upload!
-
-I really like the easy-looking install/uninstall process and smooth setup that MSIX appears to have.
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-07-06T14:42:25Z
-Working on packaging my app into MSIX for Microsoft Store distribution and the results are looking really promising! Just need to fix some working directory related issues.
-
-The benefit of packaging into MSIX is seamless installation, updating and uninstallation.
-
-https://user-images.githubusercontent.com/44692189/177577315-e297e19c-661b-4531-bdea-a7cb3a2e1bea.mp4
-
-I will probably publish a tutorial soon on how to package your Python project into MSIX as there's hardly any information about it.
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-06-27T04:35:24Z
-Yo! Here's some quick screenshots of several applications I've created lately:
-
-From [PyFiTransfer](https://github.com/schlopp96/PyFiTransfer):
-
-
-From [V2Mp3](https://github.com/schlopp96/V2Mp3):
-
-
-As you can see, I've developed a rather simplistic style prioritizing functionality and simplicity... Maybe not the _prettiest_ of GUIs, but very functional and to-the-point!
-
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-24T23:21:02Z
-A quick demo differentiating 'release', 'down' and 'drag' events from the graph. Perhaps there is a simpler way to do this?
-
-
-```py
-import PySimpleGUI as sg
-
-
-def draw_points(points, connections, canvas: sg.Graph):
- for p in points:
- canvas.draw_circle(p, 2, 'black')
-
- for c in connections:
- canvas.draw_line(c[0], c[1], 'red')
-
-
-def find_closest_point(xy, points) -> tuple:
- x_1, y_1 = xy
- dists = [
- sum(
- map(
- lambda x:x*x,
- (x_1 - x_2, y_1 - y_2)
- )
- )
- for x_2, y_2 in points
- ]
- return points[dists.index(min(dists))]
-
-
-points = (
- (-80, 0),
- (-80, 80),
- (-80, -80),
-
- ( 80, 0),
- ( 80, 80),
- ( 80, -80),
-)
-
-connections = []
-
-layout = [
- [
- sg.Graph(
- canvas_size=(500, 500),
- graph_top_right=(-100, -100),
- graph_bottom_left=(100, 100),
- background_color='white',
- enable_events=True,
- drag_submits=True,
- key='GRAPH'
- )
- ],
-]
-
-window = sg.Window("Test window", layout=layout, finalize=True)
-draw_points(points, connections, window['GRAPH'])
-
-BUTTON_STATE = 'up' # set initial button state
-while True:
- event, values = window.Read()
- canvas: sg.Graph = window['GRAPH']
- xy = values['GRAPH']
-
- if event == sg.WIN_CLOSED:
- break
-
- if event == 'GRAPH' or event == 'GRAPH+UP':
- if event == 'GRAPH+UP':
- BUTTON_STATE = 'up'
- event = "GRAPH+RELEASE"
-
- elif BUTTON_STATE == 'up':
- BUTTON_STATE = 'down'
- event = "GRAPH+DOWN"
-
- elif BUTTON_STATE == 'down':
- event = "GRAPH+DRAG"
-
- if event == 'GRAPH+DOWN':
- start_point = find_closest_point(xy, points)
- canvas.erase()
- canvas.draw_line(start_point, xy, 'red')
- draw_points(points, connections, canvas)
-
- if event == 'GRAPH+DRAG':
- canvas.erase()
- canvas.draw_line(start_point, xy, 'red')
- draw_points(points, connections, canvas)
-
- if event == 'GRAPH+RELEASE':
- end_point = find_closest_point(xy, points)
- canvas.erase()
- canvas.draw_line(start_point, end_point, 'red')
- draw_points(points, connections, canvas)
- connections.append((start_point, end_point))
-```
-
------------
-
-[jerrylususu](https://github.com/jerrylususu) 2022-06-23T13:21:50Z
-> Thank you SO much for posting the screenshots @jerrylususu !
->
-> Your code inspired the new section that I just created in the eCookbook!
->
-> Here's the page with your code. We still need to solve the character set problem.... and I definitely want to get your information into the header of the code.
->
-> https://pysimplegui.trinket.io/demo-programs#/user-submitted-examples/language-selection
->
-> Thanks for the inspiration!
-
-Good to know! The problem of not display Chinese characters is probably caused by missing fonts. To workaround this and show the usefulness of my snippet, I added a French selection which seems to work in the online environment. Hope that helps!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-23T13:13:46Z
-Thank you SO much for posting the screenshots @jerrylususu !
-
-Your code inspired the new section that I just created in the eCookbook!
-
-Here's the page with your code. We still need to solve the character set problem.... and I definitely want to get your information into the header of the code.
-
-https://pysimplegui.trinket.io/demo-programs#/user-submitted-examples/language-selection
-
-Thanks for the inspiration!
-
------------
-
-[jerrylususu](https://github.com/jerrylususu) 2022-06-23T13:05:19Z
-Simple i18n technique for PySimpleGUI programs: Show a language selection window when program starts, then load the translated strings in the selected language.
-
-Code: https://github.com/jerrylususu/PySimpleGUI-Demo-LangSelect
-
-Screenshot
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-20T16:42:25Z
-```
-M""MMM""MMM""M MMP"""""YMM M""MMM""MMM""M dP dP dP
-M MMM MMM M M' .mmm. `M M MMM MMM M 88 88 88
-M MMP MMP M M MMMMM M M MMP MMP M 88 88 88
-M MM' MM' .M M MMMMM M M MM' MM' .M dP dP dP
-M `' . '' .MM M. `MMM' .M M `' . '' .MM
-M .d .dMMM MMb dMM M .d .dMMM oo oo oo
-MMMMMMMMMMMMMM MMMMMMMMMMM MMMMMMMMMMMMMM
-```
-
-
-
-What a way to show the love! 
-
-That's incredible!!
-
-I'll be smiling bigger than the Emoji the rest of the day!
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-20T16:22:36Z
-
-i did something like this
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-20T11:28:20Z
-
-
-Hi @ArchKubi .... I suppose you could call this little fella our "mascot". I had a set of emoji's created a while back with the PySimpleGUI logo on the chest so I can use them within PySimpleGUI for testing, error messages, etc. They've added some personality to the project.
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-18T12:50:10Z
-
-is this pysimplegui mascot right?
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-15T10:41:07Z
-
-is this bug icon not change ?
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-13T11:49:29Z
-
-ı lose my hope ı don't know how ı write like this and ı try autocomplete but ı feel ı'm idiot please someone help my code
-[gnuchan-textEditor.txt](https://github.com/PySimpleGUI/PySimpleGUI/files/8890737/gnuchan-textEditor.txt)
-
------------
-
-[lonewanderer27](https://github.com/lonewanderer27) 2022-06-12T17:56:41Z
- Wow I did not expected a core dev to reply to my post! Thank you so much @PySimpleGUI! You made my day after I just worked through a whole day in implementing all the functionalities in Extracting Scripts Tab
-
-The app is sort of complete now but I haven't tested it on Windows as I daily drive Linux so I need to make sure it works there as most of Camp Buddy players are Windows users 😭
-
-And I did what you said about the screenshots, I modified a great looking readme template and I put the Extract Assets tab screenshot in there, thanks for the tip by the way!
-
-Keep it up dev!!! and code contributors ofc, who ever you are, with what you're doing with PySimpleGUI. You're making the lives of newbie GUI devs easy with it!
-
-Honestly I've never had so much fun making a GUI application than this in the span of two weeks. Everything was straightforward to implement and everything was in the documentation too. Might be one of the best out there!
-
-You (and other devs) might have possibly thought of every situation a developer might want to implement their app because there is a lot of examples 😭 and I just love it 💕
-
-Especially the cookbook, that's where I learned how to combine window.long_operation_operation and window.write_event_value to make a responsive GUI which by the way I haven't even done in my previous experience with Visual C#, it was a new territory for me but those two methods made it easy to implement a multi-threaded GUI.
-
-Many thanks again!! 😁
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-11T21:59:48Z
-@VatsalP I totally get wanting to write your own PDF utilities.
-
-One of the first group of utilities I made using PySimpleGUI were for extracting images from PDF files.
-
-
-
-A surprising amount of the code still works. The unpacking of the values dictionary doesn't because of how the Browse buttons work now. Windows were not called `Window`.... they were `FlexForm` back then. You can still use the `FlexForm` name as PySimpleGUI tries to be backward compatible as much as possible. The overall PySimpleGUI look of the layout and the names were really close to what's used today.
-
-
-
-
-```python
-import PySimpleGUI as gg
-form_rows = [[gg.Text('PDF Image Extraction')],
- [gg.Text('Choose Source and Destination Folders')],
- [gg.Text('Source Folder', size=(15, 1)), gg.InputText('Source'), gg.FolderBrowse()],
- [gg.Text('Destination Folder', size=(15, 1)), gg.InputText('Dest'), gg.FolderBrowse()],
- [gg.Submit(), gg.Cancel()]]
-
-# (button, (source, dest)) = gg.FlexForm('PDF Image Extract', auto_size_text=True).LayoutAndShow(form_rows)
-event, values = gg.FlexForm('PDF Image Extract', form_rows, auto_size_text=True).read()
-print(event, values)
-```
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-11T21:43:40Z
-Hi @lonewanderer27 !
-
-WOW you have a LOT of windows in your application
-
-Love  seeing all those screenshots! If you have a moment, can you perhaps add them to your readme? You can use the links already created in this GitHub Issue. You just need to copy and paste the lines that look like this:
-``
-and paste them into your readme.md file.
-
-Hearing your program is for a game is honestly **_thrilling_**!
-
-There's a lot in your post..... You're using the `perform_long_operation` method with `write_event_value` so that you can have a multi-threaded GUI.
-
-
-That's a smart way to do it.
-
-By the way, I finally wisened up that since there are developers using threading in PySimpleGUI that understands the concept of threading, it may be clearer to use the word "thread".... so.... I created an alias `start_thread` that is the same as `perform_long_operation`.
-
-Thank you for taking the time to come share your creation! These stories, screenshots, and hearing what you're all making, is **_incredibly motivating_**. It's what keeps me working hard on PySimpleGUI. It results in me wanting to make PySimpleGUI better
-
------------
-
-[VatsalP](https://github.com/VatsalP) 2022-06-11T00:30:56Z
-Made a small gui utility to merge pdf(didn't like idea of using some website to do it)
-
-
-
-link to repo in case anyone to download or view source: https://github.com/VatsalP/pdf_utility
-
------------
-
-[lonewanderer27](https://github.com/lonewanderer27) 2022-06-09T09:12:22Z
-Hi everyone!
-I'm currently writing a tool of some sort for a Visual Novel game. It mainly targets those who want to make a python chat bot that speaks exactly like the characters from the Visual Novel.
-
-### Extracting Assets Tab
-
-
-The GUI doesn't become unresponsive thanks to perform_long_operation. And the write_event_value made it easy to pass the current file that is being extracted, as well as the current progress of the extraction from a separate python program:
-
-Though I kinda wish this also works in the QT port as I prefer the look of that instead of Tkinter. But this will do for now!
-
-
-### Extracting Scripts Tab
-
-
-The layout tools worked very well in keeping the check boxes organized:
-
-
-
-### About Window
-I really like the About window of GNOME / GTK apps so I made mine look similar to it:
-
-
-
-The Github Repo link is here for anyone who wants to look at the code, warning it's spaghetti code:
-https://github.com/lonewanderer27/Camp-Buddy-Toolbox
-And I am legally required to disclose the code anyway since I used and modified (a bit) the code of the extractor program (which is GPL-3 licensed)
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-08T11:33:09Z
-> its a bit of a pain when it comes to backwards compatibility.
-
-This is the exact problem with using language features that are specific to a version of Python. It causes one to ponder "what % of the Python community am I willing to leave behind".
-
-Using "All Packages" as a gauge, this was the distribution last December:
-
-
-And this was in May
-
-
-
-If I look at PySimpleGUI users specifically, it was this recently:
-
-
-It changes day to day. Opinions vary, but I've always felt like users are more likely to pass on trying a package or program than they are to upgrade their Python environment in order to run it.
-
-I've mentioned this a few times over the years. I chose to support 3.4+ to get the most users possible. For Demo Programs, I'm a bit more open to 3.6+ for the Demo Programs and other repos, but don't go any higher than that for the same reason of wanting a big tent.
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-07T20:23:54Z
-Thats awesome @PySimpleGUI ! I hadn't heard of Trinket before.
-
-`match` was new to me for this project - quite a nice addition to the language but being new its a bit of a pain when it comes to backwards compatibility.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-07T12:48:16Z
-I haven't made this available publicly, but I put a hacked up version of your code up on Trinket so a few friends can play with it without having to install Python, PySimpleGUI, etc.. Sorry that I de-3.10'd the code by removing the match.. .but I needed to run the code in a lower version of Python.
-
-
-
-https://trinket.io/pygame/5cb3229fe8
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-07T12:31:48Z
-Thank you!
-
-
-
-
-I needed to modify your path to the .obj file...
-```python
-my_object = obj_reader.import_obj('../example_obj/utah_teapot.obj', ('x', 90))
-```
-
-Worked great after that.
-
-VERY nice readme file! Looking sharp!!
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-07T12:23:18Z
-@PySimpleGUI I have just created a repo for the 3D viewer. I have also added polygon rendering. This is all driven using just maths and the Graph element.
-
-
-
-
-https://github.com/EdwardChamberlain/PySimpleGUI-3D-Viewer
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-07T07:07:21Z
-@EdwardChamberlain Do you have a repo containing any of these new creations? I would love to run the teapot program for example.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-06T17:20:18Z
-WOW @EdwardChamberlain !!
-
-I sent your video to my friend Tim.... who's a veteran in the computer graphics field...
-
-He replied....
-> That's Jim Blinn's teapot. I am visiting him in July.
-
-"Surround yourself with people smarter than you" is advice I take seriously!
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-06-06T02:12:11Z
-if one day PySimpleGUI have interactive display this is make me happy alien
-
-ı use python because python have this beautiful library
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-05T21:01:07Z
-Can you Render the [Utah teapot](https://en.wikipedia.org/wiki/Utah_teapot) with PySimplyGUI? The answer is yes:
-
-https://user-images.githubusercontent.com/7659338/172070354-ad7288d5-eefb-4216-9076-f8baa4a35aae.mov
-
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-06-05T20:27:42Z
-> @infinitepower18 
->
-> WOW! You've really pushed the envelope. I liked reading about the compilation you're doing. Much to learn from your project. Very nicely done!
-
-I have written instructions on how to compile it in the project's readme. These instructions should probably work for any PySimpleGUI program. It can take a few mins depending on the speed of your computer, but it works flawlessly and I haven't faced any issues with it as of now. Definitely would recommend using it to convert their Python programs to .exe files. I think it can also convert to Mac .dmg too.
-
-Once compiled, you can use Inno Setup to bundle the compiled files into an installer for distribution.
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-05T19:45:47Z
-> I wasn't able to install planar_projection
-
-You shouldn't need to install it, its just a python script that needs to be imported. I included both scripts in the post above but the division between the two scripts isnt very clear!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T19:42:55Z
-I wasn't able to install planar_projection so I'll take your word on it working as well as you having fun
-
-
-The `Graph` element rocks! Honest... it's one of the most powerful elements and maybe one of the least used.
-
-I wrote the CPU Cores Desktop Widget a long time ago so it's far from being efficiently written. Even so, it's only 85 lines of code.
-
-
-
-It's really great for these Tableau-style grids of graphs. For this COVID tracker, I used a linechart (Graph) with a Gauge (Graph) and simply repeated them.
-
-Being able to define your own coordinate system really makes things so much easier.
-
-
-
-
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-05T19:33:58Z
-
-
-This was a fun little project to learn about the Graph element!
-
-```py
-# main.py
-import PySimpleGUI as sg
-
-import planar_projection
-
-
-# Create Scene
-cube = planar_projection.Object_3D(
- verts = planar_projection.default_cube_verts,
- edges = planar_projection.default_cube_edges,
-)
-camera = planar_projection.Camera_3D(
- focal_distance=-12,
- projection_plane_distance=-10
-)
-
-
-layout = [
- [sg.Graph((500, 500), (-1, -1), (1, 1), 'black', key='-GRAPH-')],
- [sg.Text("R:", size=3), sg.Slider((180, -180), resolution=1, default_value=0, enable_events=True, orientation='horizontal', expand_x=True, key='-SLIDER-')],
- [sg.Text("X:", size=3), sg.Slider((-8, 8), resolution=0.1, default_value=0, enable_events=True, orientation='horizontal', expand_x=True, key='-X-')],
- [sg.Text("Y:", size=3), sg.Slider((-3, 3), resolution=0.1, default_value=0, enable_events=True, orientation='horizontal', expand_x=True, key='-Y-')],
- [sg.Text("Z:", size=3), sg.Slider((-3, 3), resolution=0.1, default_value=0, enable_events=True, orientation='horizontal', expand_x=True, key='-Z-')],
-]
-
-window = sg.Window('3D Viewport', layout)
-
-while True:
- event, values = window.read()
-
- if event == sg.WIN_CLOSED:
- break
-
- if event in ['-SLIDER-', '-X-', '-Y-', '-Z-']:
- # Set rotation and position for the cube.
- cube.orientation = values['-SLIDER-']
- cube.position = (values['-X-'], values['-Y-'], values['-Z-'])
-
- # Update the graph.
- canvas = window['-GRAPH-']
- canvas.erase()
- for p1, p2 in camera.get_edges(cube):
- canvas.draw_line(p1, p2, 'white', 3)
-
-window.close()
-```
-And the maths bit:
-```py
-# planar_projection.py
-from math import sin, cos, radians
-
-
-class Object_3D:
- def __init__(self, verts, edges, position=(0, 0, 0), orientation=0, elevation=0):
- self._verts = verts
- self.edges = edges
-
- self.orientation = orientation
- self.elevation = elevation
- self.position = position
-
- @property
- def verts(self):
- result = [self.roatate_point_z(i, self.orientation) for i in self._verts]
- result = [self.translate_point(i, self.position) for i in result]
- return result
-
- def roatate_point_z(self, p: tuple, angle: float) -> tuple:
- # |cos θ −sin θ 0| |x| |x cos θ − y sin θ| |x'|
- # |sin θ cos θ 0| |y| = |x sin θ + y cos θ| = |y'|
- # | 0 0 1| |z| | z | |z'|
- x, y, z = p
- return (
- x * cos(radians(angle)) - y * sin(radians(angle)),
- x * sin(radians(angle)) + y * cos(radians(angle)),
- z
- )
-
- def translate_point(self, p, xyz_translation) -> tuple:
- x, y, z = p
- i, j, k = xyz_translation
-
- return (x+i, y+j, z+k)
-
-class Camera_3D:
- def __init__(self, focal_distance, projection_plane_distance):
- self.focal_point = (focal_distance, 0, 0) # Focus point must on X axis due to laziness (avoids a ton of maths).
- self.projection_plane_anchor = (projection_plane_distance, 0, 0) # Projection plane centerpoint. (we will only use the x coord since this must be a plane parallel to YZ)
-
- @property
- def plane_focus_dist(self):
- return abs(self.focal_point[0] - self.projection_plane_anchor[0])
-
- def project_object(self, object: Object_3D):
- return [self.project_point(i) for i in object.verts]
-
- def project_point(self, p):
- x_len = p[0] - self.focal_point[0]
- len_ratio = self.plane_focus_dist / x_len
-
- y = len_ratio * (p[1] - self.focal_point[1])
- z = len_ratio * (p[2] - self.focal_point[2])
-
- return (self.projection_plane_anchor[0], y, z)
-
- def get_edges(self, object: Object_3D):
- points = self.project_object(object)
-
- result = []
- for i in object.edges:
- p1 = points[i[0]]
- p2 = points[i[1]]
-
- p1 = (p1[1], p1[2])
- p2 = (p2[1], p2[2])
-
- result.append((p1, p2))
-
- return result
-
-
-# Define the cube verticies. Coordinates in the form: (X, Y, Z)
-default_cube_verts = [
- (1, 1, 1),
- (1, 1, -1),
- (1, -1, 1),
- (1, -1, -1),
-
- (-1, 1, 1),
- (-1, 1, -1),
- (-1, -1, 1),
- (-1, -1, -1),
-]
-
-# Define the cubes edges. These are indicies of the verticies that are connected.
-default_cube_edges = [
- (0, 1),
- (0, 2),
- (1, 3),
- (2, 3),
-
- (4, 5),
- (4, 6),
- (5, 7),
- (6, 7),
-
- (0, 4),
- (1, 5),
- (2, 6),
- (3, 7),
-]
-```
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T12:13:02Z
-@infinitepower18
-
-
-WOW! You've really pushed the envelope. I liked reading about the compilation you're doing. Much to learn from your project. Very nicely done!
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-05T12:11:44Z
-Ah, right you are @macdeport
-
-Fixed things up and made some improvements so that it's more flexible when changes are made. It's been a while since it was updated. This one goes back to the early days.
-
-
-
-
-
------------
-
-[macdeport](https://github.com/macdeport) 2022-06-05T08:35:05Z
-https://github.com/PySimpleGUI/PySimpleGUI/issues/10#issuecomment-1146702983
-
-
-
-@PySimpleGUI IMO the caption could be `y = x1 * sin(x / x2)` ;-)
-
-
-
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-06-05T00:26:52Z
-Forgot to mention, the application now has both light and dark themes and the theme that is applied depends on your Windows settings!
-
-https://user-images.githubusercontent.com/44692189/172029887-95c41703-d396-457f-9c11-7dd3e304de81.mp4
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-06-05T00:10:14Z
-Sneak peek of my upcoming update, which includes Windows Explorer integration by associating the .apk file extension with my program!
-
-
-
-Not only that, but the application is now compiled using Nuitka, creating an executable file for better integration with the Windows OS. The big advantage of using Nuitka over something like Pyinstaller is that it won't be falsely flagged by antivirus vendors, which is a problem with Pyinstaller and hence why I avoided using it. This also opens up the possibility of creating a packaged MSIX application in the future, by converting my exe file using a program like MSIX Packaging Tool. Unfortunately I have not been able to get it to work properly yet and will focus on the stability of my application for now.
-
-Also, this seems to be a PySimpleGUI specific thing (I have a very small Tkinter based project and I don't face this issue with it) but if I pin the installed application (I package the compiled files using Inno Setup) on the Start Menu to the taskbar, and then click on the pinned application, it adds a duplicate on the taskbar which is not pinned. If you pin that duplicate and remove the previous one, then it will work the way you expect. Attaching video below:
-
-https://user-images.githubusercontent.com/44692189/172029588-76de9de9-af35-4d65-970a-32e48e3aaad9.mp4
-
-Apart from that, the update is pretty much ready and version 1.3 will be released in the next few days!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T23:34:38Z
-> Every day is a learning day
-
-Most certainly!
-
-I think you're going to like the Graph element!
-
-Your slider code reminded me of this Graph Element Demo Program as it responds in realtime to the sliders like your code does.
-
-
-Check out the Demo Programs and see if they stir your very active imagination and brilliant brain of yours
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T23:17:34Z
-One of the points of emphasis in the Udemy course's lesson on the Graph element is that it's a "Gateway Element". From it you can make all kinds of custom elements. There's an enhancement that I have about 2/3 done called PySimpleGUI+ that is a more formal way of creating these custom elements.
-
-I use one that Jason made call the "Gauge" frequently.
-
-
-
-In the lesson, I show this Dial element as one of these custom elements.
-
-
-
-The Graph element pretty much has all someone needs to make windows that look very similar to Qt for example.
-
-> PIL is that I can write out the generated image to disk for printing / emailing etc. Is that possible with the graph element here?
-
-I don't have a function or Graph element method that writes to disk that I can recall.
-
-The Graph Element demo program Demo_Graph_Drawing_And_Dragging_Figures_2_Windows.py uses PIL to save to the file to the disk. The feature that was added to PySimpleGUI a couple of releases ago to take "Window Snapshot" uses PIL. I don't require PIL be installed in order to use PySimpleGUI, but I do require it to be installed should you want to use this snapshot feature/
-
-
-
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-04T22:57:41Z
-Every day is a learning day:
-
-
-I quite like the Graph element - being able to position your 0, 0 point is a really understated feature for making clear code! Being able to return the elements to manipulate them also presents some interesting opportunities. One of the main reasons I was using PIL is that I can write out the generated image to disk for printing / emailing etc. Is that possible with the graph element here?
-
-```py
-import PySimpleGUI as sg
-
-layout = [
- [sg.Graph((300, 50), (-50, -30), (250, 20), background_color='white', key='-GRAPH-')],
- [sg.Slider((0, 200), orientation='horizontal', expand_x=True, enable_events=True, key='-SLIDER-')],
-]
-
-window = sg.Window("Live Drawing", layout)
-while True:
- event, values = window.read()
-
- if event == sg.WIN_CLOSED:
- break
-
- if event == '-SLIDER-':
- line_len = values['-SLIDER-']
- canvas = window['-GRAPH-']
-
- canvas.erase()
- canvas.draw_line((0, 0), (line_len, 0))
-
- # ADD TICK MARKS (Becasue why not?)
- for i in range(0, int(line_len) +1, 25):
- canvas.draw_line((i, 0), (i, -5))
- canvas.draw_text(str(i), (i, -16))
-
-
-window.close()
-```
-
-[I added an init to the above PIL example to generate the initial blank image]
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T22:27:46Z
-@EdwardChamberlain take a look at the posts by @neovich . He did a VU meter and custom sliders that are really beautiful and 100% done with pure PySimpleGUI. No PIL required.
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-04T22:17:00Z
-@EdwardChamberlain I love it! 
-
-
-While you're thinking along this custom-element kind of direction, keep in mind that the Graph element has the same kind of drawing primitives you're using in PIL... without needing to use PIL.
-
-For example, this round progress meter is just a Graph element.
-
-
-
-There's a nice slider posted quite some time back that uses a Graph element as well. It would be interesting to see if support for both PIL and the Graph element could be used.
-
-[EDIT - can you post the example.png image or make it into a BASE64 that can be included in your source?]
-
------------
-
-[EdwardChamberlain](https://github.com/EdwardChamberlain) 2022-06-04T21:54:53Z
-Just some proof of concept! Using Pillow to generate a line that can be updated in realtime as a response to the slider input. Im hoping to expand this to some more complex interactive graphics within pysimplegui using pillow as the 'renderer'.
-
-
-
-
-```py
-from PIL import Image, ImageDraw
-import PySimpleGUI as sg
-
-
-img = Image.new('RGB', (300, 50), 'white')
-img.save('example.png')
-
-layout = [
- [sg.Image('example.png', key='-IMAGE-')],
- [sg.Slider((0, 200), orientation='horizontal', expand_x=True, enable_events=True, key='-SLIDER-')],
-]
-
-window = sg.Window("Live Drawing", layout)
-while True:
- event, values = window.read()
-
- if event == sg.WIN_CLOSED:
- break
-
- if event == '-SLIDER-':
- line_len = values['-SLIDER-']
-
- # INIT CANVAS
- img = Image.new('RGB', (300, 50), 'white')
- canvas = ImageDraw.Draw(img)
-
- # DRAW LINE BASED ON SLIDER INPUT
- canvas.line((50, 15, 50+line_len, 15), fill='black')
-
- # ADD TICK MARKS (Becasue why not?)
- for i in range(0, int(line_len) + 1, 25):
- canvas.line((50 + i, 24, 50 + i, 18), fill='black')
- canvas.text((50 + i, 27), str(i), 'black')
-
- # UPDATE IMAGE SHOWN
- img.save('example.png')
- window['-IMAGE-'].update('example.png')
-
-
-window.close()
-```
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-02T19:20:36Z
-> Please don't add a post to the Announcements just yet
-
-No problem... it's why I asked first.
-
-I'll give it a try later for sure!
-
-Lemme know when you're ready for some attention via an announcement and I'll be happy to give a shout-out.
-
------------
-
-[wrwetzel](https://github.com/wrwetzel) 2022-06-02T19:09:14Z
-Mike,
-
-Please don't add a post to the Announcements just yet. One of your PySimpleGUI users in Germany is testing in a new environment and found several rough edges. I'd like to wait until I resolve those before talking to a wider audience.
-
-However, I would be grateful if you would try to run it and see what you come up with.
-
-I'll let you know when this is ready for a wider audience.
-
-Update 2 June 3:06 PM EDT. I have corrected the rough edges mentioned above but I'd still like to limit testing to just a few users. The code at GitHub and the tar file at my site include the corrections and a little wordsmithing on the documentation.
-
-Thanks,
-Bill
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-06-02T10:59:03Z
-Hiya @wrwetzel (Bill)! It's "mike" here with the @PySimpleGUI account name.
-
-This is indeed an ideal place to share that you're opening up your application for testing! I love it! Thank you for making your post. The WIKI is another location that you can post in, but it gets very little traffic.
-
-Congratulations on getting to this point with "Birdland Musician's Assistant". As a piano player (I don't dare go so far as to use the term "musician"), I was immediately captivated by your program. Very exciting to see music-related applications being built.
-
-If it's OK with you, I'll also add a post to the Announcements section about the availability. Made my day seeing your post!
-
-
------------
-
-[wrwetzel](https://github.com/wrwetzel) 2022-06-01T20:37:29Z
-I know that this is an issue for screenshots but perhaps a link to the site of a project using PySimpleGUI would also be welcome I believe that "Birdland Musician's Assistant" is ready for testing from a few 'friendly' users. If, in addition to being a PySimpleGUI user, you are also a musician, especially if you have a collection of PDF fakebooks, then you might find this interesting. And the person with the id of 'PySimpleGUI' specifically asked to see this several weeks ago.
-
- https://birdland.wrwetzel.com/
-
-Thanks,
-Bill
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-05-31T19:21:13Z
-> why there is no PySimpleGUI community discord server
-
-It's not how I want the project to be structured. The discussion feature isn't enabled on GitHub and the PySimpleGUI social media accounts are shut down for similar reasons.
-
------------
-
-[ghost](https://github.com/ghost) 2022-05-31T19:16:45Z
-why there is no PySimpleGUI community discord server
-
------------
-
-[ghost](https://github.com/ghost) 2022-05-31T18:48:51Z
-too much missing in my project ı'm noob python user
-1: ı don't know how ı write multiline number column ı search google and github no one use pysimplegui
-ı found solution but this is tkinter not pysimplegui
-
-2: python runner works but input() not working this is not interactive output ı mean output is like a multiline
-ı try this while True: print("test") my computer frozen
-ı try write like a real terminal but this is not possible
-3: ı don't know how ı save cd path
-can you help my project? @eagleEggs
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2022-05-31T18:14:11Z
-@ArchKubi this looks super nice.
-
-I'd also like to have a numbered line within a multiline. Looked for solutions in the past but came up with nothing. If you find any let me know - I'll also start looking at it again.
-
------------
-
-[ghost](https://github.com/ghost) 2022-05-31T06:58:52Z
-ı create my own text editor
-but not just text editor
-1- text editor 2-code editor 3-python runner 4- terminal
-1:) first question how ı write multiline number column like vscode ı can't find example
-
-
-
-
-
-
-it works yes good but input() this is impossible
-2:) is it impossible run input() ???
-
-
-yes terminal is works but
-the command line does not cause any problems if you enter it only once for the cd command
-I don't know yet how can I save cd path
-I think the project is going well now.
-
-please help my project:
-https://github.com/ArchKubi/PythonChan/tree/main/Gnuchan-TextEditor
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2022-05-14T00:51:44Z
-@infinitepower18 I like the look of your GUI; colors and buttons. Also nice to have rounded windows I'm guessing from Windows 11.
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-05-02T15:50:00Z
-Recently redesigned my PySimpleGUI based application WSA Sideloader with a modern looking UI in version 1.2!
-
-
-
-
-
-Anyone with Windows 11 can try out my program by downloading from either [GitHub releases](https://github.com/infinitepower18/WSA-Sideloader/releases) or [Microsoft Store](https://apps.microsoft.com/store/detail/wsa-sideloader/XP8K140DLVSC0L). More updates are coming over the next few months!
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2022-05-01T12:40:06Z
-Hi! Here is an update on my GUI, thanks to the awesome work of PySimpleGUI making it easy for me :)
-
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2022-05-01T11:03:33Z
-Per request from PySimpleGUI here is a screenshot of AWS Cloudfront utility I created using PySimpleGUI. It allows you to delete, invalidate, enable or disable a cloudfront distribution.
-
-.
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-04-17T01:08:06Z
-> Yo Doc @schlopp96 !
->
-> Very nice work on V2Mp3.. drop a link to your repo if you're ok with sharing your work. Thanks for taking the time to post a screenshot!
->
->  seeing what everyone's making!
->
-> Come back with anything you add too... don't be shy
-
-Sure! [Here's the repo link](https://github.com/schlopp96/V2Mp3).
-
-I really appreciate the kind words!
-
-Edit: Posted the wrong repository link.... Fixed!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-04-16T19:23:26Z
-@gfcwfzkm ... you've certainly way outdone the little psgresizer app I use to do my conversions and resizing. I really like the round color swatches!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-04-16T19:21:39Z
-Yo Doc @schlopp96 !
-
-Very nice work on V2Mp3.. drop a link to your repo if you're ok with sharing your work. Thanks for taking the time to post a screenshot!
-
- seeing what everyone's making!
-
-Come back with anything you add too... don't be shy
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-04-16T13:08:06Z
-
-
-@wrwetzel you certainly didn't post a shot of that! W.O.W. !
-
------------
-
-[wrwetzel](https://github.com/wrwetzel) 2022-04-16T12:27:46Z
-Per request from PySimpleGUI here is a screenshot of Birdland. I actually thought I posted one several months ago but I don't see it.
-
-
-
-
------------
-
-[schlopp96](https://github.com/schlopp96) 2022-04-06T21:17:33Z
-Yo @MikeTheWatchGuy ! What's up man!
-
-Recently created a video-to-audio file converter also capable of downloading videos, or _just the audio_ from said videos, from YouTube. I call it _**V2Mp3**_ (Video to Mp3).
-
-
-
-
-This is just the initial release version - I plan to add some more features such as a button to allow choosing the directory to save downloaded/converted files.
-
------------
-
-[gfcwfzkm](https://github.com/gfcwfzkm) 2022-04-06T15:08:50Z
-As promised in a 3 months old issue about image resizing, I'm posting my screenshot to the finished application here
-
-This is a tool to convert it to an image format, that I have developed to suit small microcontrollers better - check if out if you're curious! https://github.com/gfcwfzkm/PIF-Image-Format
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-25T17:24:08Z
-@eliffile as always, you're quite welcome. I hope to have The PySimpleGUI Catalog project up and running in the coming weeks so that posting screenshots will be built-in and trivial to share. I usually drag and drop or copy and paste them into the GitHub comment.
-
-Hmmmmm..... I'll do The Catalog project in multiple steps so that getting a screenshot taken and posted here, in this GitHub issue is easy. That'll be a way to get started and be useful much sooner than waiting for the entire project to complete. I'll make `psgscreenshot` place the image of your window on the clipboard so that tit can be pasted into the Issue. I recall learning how tricky it is to place images on the clipboard last year.
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-03-24T21:46:02Z
-Thank you, @PySimpleGUI . It really works well. I have updated the picture you your site (#10) but the links no longer work. Github and I don't seem to get along. I just don't get my head around it. Not a complaint. Thanks for the wonderful library that you have created. The possibilities are endless.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-24T16:02:11Z
-@eliffile ... Wow Marten... your GUIs are mind-blowing. I can't believe how much you pack into a single window!
-
-I have a suggestion/experiment for you to try....
-
-
-If you use a `Push()` element then you can right justify things easier. Try placing them either at the start of rows or in between
-
-Here's an example of a window that has inputs with labels that are varying lengths. By adding a `Push` onto the front of rows, it right justifies ("Pushes") everything on that row.
-
-
-
-```python
-import PySimpleGUI as sg
-
-layout = [ [sg.Text('My Window with a bunch of inputs........')],
- [sg.Text('Label 1'), sg.Input(size=(12,1))],
- [sg.Text('Longer Label'), sg.Input(size=(12,1))],
- [sg.Push(), sg.Text('Longer 1'), sg.Input(size=(12,1))],
- [sg.Push(), sg.Text('Longer label'), sg.Input(size=(12,1))],
- [sg.Button('Go'), sg.Button('Exit')] ]
-
-sg.Window('Window Title', layout).read(close=True)
-```
-
-Thank you for taking the time to post your work! It's always fun to see what you're making.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-24T15:53:14Z
-@NFadhlurrahman I really like what you've made and I'm learning a lot looking through your code. I'm trying to make it 3.6 compatible as the `run` call isn't available in 3.6. There are some tricks you did that I'm studying, copying learning from. I need to make sure there are clear examples in the Demo Programs that show how to get results back from the `execute_command_subprocess` call.
-
-For example, I _**think**_ this gets the right result for doing the "Get Info" operation:
-
-```python
- window.start_thread(lambda: (name, sg.execute_get_results(sg.execute_command_subprocess('pip', 'show', name, pipe_output=True))[0]),"-pkg-info-")
-
-```
-
-
-The `start_thread` is simply an alias for `perform_long_operation` that I recently added so that it's clear when used in programs like yours that are sophisticated and thus more clarity about what's going on under the hood is helpful.
-
-I've never seen some of the constructs you've used. They're quite clever.
-
-I've only seen 1 example of a front-end to pip. It was posted on Medium a couple of years ago.
-
-Thank you for posting your code! I'm learning a lot from it.
-
-https://raw.githubusercontent.com/PySimpleGUI/PySimpleGUI/master/images/emojis/thumb_112.png
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-03-22T07:14:12Z
-
-
-
------------
-
-[NFadhlurrahman](https://github.com/NFadhlurrahman) 2022-03-20T14:01:09Z
-@infinitepower18 Sure! [Here it is.](https://github.com/NFadhlurrahman/package-manager-gui)
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-03-20T13:49:41Z
-@NFadhlurrahman do you have a link to the repo? Would like to try it.
-
------------
-
-[NFadhlurrahman](https://github.com/NFadhlurrahman) 2022-03-20T13:47:20Z
-I made a tool for managing Python packages but uses GUI instead of CLI. It can install and uninstall packages, and see packages you have installed.
-
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-03-14T22:37:40Z
-How I wish universe was this simple to create!
-
-Made this demo for testing an algorithm for image distribution on a canvas
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-03-08T22:12:47Z
-SO many awesome posts! @Zilversmit , @infinitepower18 , @resnbl thank you for taking the time to share what you've made and for the kind messages. PySimpleGUI users have been so encouraging. It really helps and is greatly appreciated.
-
-
-
-Database, Android, and Image processing.... really diverse set of applications.
-
------------
-
-[resnbl](https://github.com/resnbl) 2022-03-07T22:17:13Z
-Here is something very essential (or not...) for Doctor Who fans:
-
-
-This program includes animated images (including "buttons") and playing sound clips. It does require the installation of the VLC Media Player app, as well as `pillow` and `python-vlc` packages.
-
-Available at finer GutHub repos everywhere (but mostly, just here):
-https://github.com/resnbl/pyTardis
-
-P.S.: Don't Blink!
-
------------
-
-[infinitepower18](https://github.com/infinitepower18) 2022-03-03T19:59:59Z
-My application is WSA Sideloader, which can sideload Android apps on Windows Subsystem for Android on Windows 11 with minimal effort. Thanks to PySimpleGUI and tools like pynsist which helps with distributing the program, I have been easily able to code it based on what I know about Python so far.
-
-
-
-It is currently available to download on both GitHub and Microsoft Store :)
-
-https://github.com/infinitepower18/WSA-Sideloader
-
------------
-
-[Zilversmit](https://github.com/Zilversmit) 2022-02-28T00:22:25Z
-This is the GUI I designed for a cli Python program that manipulates a database.
-There are six buttons, the first three are pre-defined searches that produce reports. The fifth button
-allows the user to submit a SQL command to the database. This button triggers a pop--up window
-where the command may be typed in. Another choice is to direct data to a CSV file for analysis in
-a spreadsheet program.
-
-Many thanks to Mike and the udemy course for the know-how.
-
-
-
-
-
-this is the pop-up window:
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-26T20:47:06Z
-Very nice Marteen! I mentioned Tabs and less than a week later I see a new GUI from you with Tabs integrated into your application. You're absolutely right..... tabs are quite useful when you've got limited real estate. I've used them where the entire window is taken up by tabs so that switching to a new tab is like switching to an entirely different window, as well as smaller portions of the window, like you've done in your latest version.
-
-I've been pondering your placement controls using sliders. Short of using a Graph element so that you're dragging items around visually with the mouse, I am not sure of a better technique than what you've implemented. A slider gives you better fine-granularity controls than using just the mouse. With just a mouse (dragging images around), it's hard to "nudge" something a few pixels in one direction or another.
-
-There may be a hybrid kind of interface possible where an item to change is selected and then a pair of sliders are used to control the selection. It's multiple steps though where your controls are a single-step... just move a slider and the right item moves. Arrow keys are another possibility but again, there's a "select" the thing to change step involved.
-
-Great stuff! Thanks for taking the time to post what you're making.
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-26T05:17:23Z
-The stamp is selected on the default Tab
-
-Then a photo is selected and manipulated for size and cropping
-
-Next the message is written in a multiline element together with added info. Positions can be manipulated with the sliders.
-
-A variation on the previous version of the Postcard Maker this time using Tabs which are very useful when dealing with the limited real estate of a computer screen. Amazing library to work with. Thanks for all the hard work.
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-21T07:05:07Z
-On 21-02-2022 12:29, PySimpleGUI wrote:
-> Absolutely LOVE 💗 what you're doing @eliffile [1]!
->
-> Using sliders the way you did for positioning is so clever.
->
-> You may like Tabs in the future should you have a lot of settings that
-> you can to be highly accessible, but yet don't need to be present all
-> the time or visible while you're working on the card. Just a
-> thought.... not that I see a use at this point, but thought I would
-> toss it out there as something for you to keep an eye out for a use
-> of.
->
-> Very different color scheme this time and it too is a really well-done
-> palette like your last one. Impressive is an understatement. It's nice
-> to see someone with your artistic skills using PySimpleGUI. I'm
-> envious... keep posting what you make!
->
-> --
-> Reply to this email directly, view it on GitHub [2], or unsubscribe
-> [3].
-> Triage notifications on the go with GitHub Mobile for iOS [4] or
-> Android [5].
-> You are receiving this because you were mentioned.Message ID:
-> ***@***.***>
->
-> Links:
-> ------
-> [1] https://github.com/eliffile
-> [2]
-> https://github.com/PySimpleGUI/PySimpleGUI/issues/10#issuecomment-1046385741
-> [3]
-> https://github.com/notifications/unsubscribe-auth/AXQEKSX24H7TEQAEGDA7GA3U4GIOBANCNFSM4FLP3TBQ
-> [4]
-> https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
-> [5]
-> https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub
-
-Hi,
-
-Thank you for the email received and also for your very kind words. The
-library is fascinating and extremely well designed. It runs beautifully
-and I love to work with it.
-
-Thank you for the Tab reccomendation I will definitely try it.
-
-I appreciate all your hard work on this library and I hope that it will
-really take off to become well supported by companies.
-
-Cheers,
-Maarten
---
-Maarten Venter
-
-NSW
-Australia
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-21T01:28:50Z
-Absolutely LOVE 💗 what you're doing @eliffile!
-
-Using sliders the way you did for positioning is **so clever**.
-
-You may like Tabs in the future should you have a lot of settings that you can to be highly accessible, but yet don't need to be present all the time or visible while you're working on the card. Just a thought.... not that I see a use at this point, but thought I would toss it out there as something for you to keep an eye out for a use of.
-
-Very different color scheme this time and it too is a really well-done palette like your last one. Impressive is an understatement. It's nice to see someone with your artistic skills using PySimpleGUI. I'm envious... keep posting what you make!
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-20T06:53:03Z
-
-
-I made the stamps with photos of my grandkids in Photoshop then turned them into buttons. Picking a stamp places it on the Card Base. The photo and writings follow when I click MakeCard. Positions are adjusted with the sliders. Just having a ton of fun. Thank you. I have Tim Tams - they go well with coffee.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-16T17:06:49Z
-Love it William ( @WAUthethird )!  I like AI GUIs, especially with being able to visually adjust parameters like you've got with the sliders. I also used sliders for Threshold and Confidence in the YOLO demo. Being able to change in real time or without having to restart the entire application is a real timesaver and advantage of using a GUI. I like seeing 3 windows in your one application. Very nice!
-
-
-
------------
-
-[WAUthethird](https://github.com/WAUthethird) 2022-02-16T04:39:00Z
-I've created a program that utilizes text generation AI to make text conversion (such as converting text between first person and second person) fast and easy. The initial window asks what AI model you'd like and determines whether your computer can run it. If you have a GPU, you're given more options to play with.
-
-After choosing a model, you're opened up to this screen. I've filled out the table with a few examples.
-
-I can press the '(Re)generate output' button to have the text generation AI create a response that matches the ones in its memory, which I can then add to the table. The more you have in the table, the more you get better responses!
-
-Since the AI model has a limited amount of space in its memory, called "tokens", (somewhat analogous to characters) I had to create a way to keep track of them and let the user activate (put in memory) and deactivate (remove from memory) them. Since I've optimized it for fast work, all entries by default are activated, and when the memory limit is hit, the top rows in the table that are not permanently activated begin to be deactivated to make space. All of this is helpfully color-coded and updates a number of parameters on the fly. You can also edit entries (which disables most of the program until editing is complete) and do bulk operations - selecting multiple rows at a time and hitting something like 'activate' works seamlessly.
-
-I've also made a settings screen with good defaults and highly configurable parameters:
-
-
-I'm really happy I used PySimpleGUI for this project. I definitely ended up using the table element in some really interesting ways, and I learned a ton about Python/Tkinter GUI management and creation.
-
-[Code](https://github.com/WAUthethird/gpt-fewshot-batcher)
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-02-08T16:07:11Z
-@PySimpleGUI
-POD aka print on demand websites are sites where you can sell/buy artwok to be placed on products, that are printed when bought
-
-The site where I to sell my artworks don't features a multiple images uploading and it's a slow process to upload many variants or same category images
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-08T14:07:12Z
-I like the look @DeusAres and the description of your journey in making a highly responsive app using background processing.
-
-I did some searching and still can't quite figure out the specific description of:
-> POD website uploader
-
-
-
-
-It's clear assets are to be uploaded from what I see, but I am ignorant on what PODs are in this context.
-
-That's one unhappy "rocketman" 
-
-Threading & subprocessing has/was/is/will be a challenge to continue to work into PySimpleGUI in a simple and effective manner. The `Window.write_event_value` addition, at the very least, put an end to polling which means less latency, less CPU time, more responsive and clearer designs. The Exec SDK has helped simplify subprocessing (in my opinion, or for me it has)
-
-Thanks for taking the time to not just upload a screenshot, but a description of the overall effort and type of design you're using.
-
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-02-08T08:58:44Z
-I'm currently working on a POD website uploader, good for niches and when uploading same type of content in dimensions and "category" and oh boy, it was a journey, but I am 90% done!
-
-It features a listbox that it's linked to an image previewer, that gets loaded through a thread
-
-Every task gets in a queue that will show the status, and it's sent to a selenium instance, that can be paused, resumed or stopped in any moment (obv any is tied to waiting for line of code to be completed)
-
-Not gonna lie, threading library needed some sort of stop directly calling from the object but I managed to get my implementation done
-
-But I learned a lot of new things while working at this, and threading/multiprocessing is a must have knowledge when GUIs are used. This way, your GUIs will never be unresponsive!
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-07T01:20:01Z
-@bouc79 Wowwwwww! With Pygame 2.0 even! YESSSSSSSSSSSSSssssssssssssss! (with a snake-hiss-accent )
-
-
-I've had an outstanding issue that it's not working, but evidently is now! What to go!!! Woohooo!
-
-
------------
-
-[bouc79](https://github.com/bouc79) 2022-02-06T22:41:19Z
-Example of integration between pysimplegui and pygame with real-time interaction between the two windows
-[Link](https://gitlab.com/_BOUC_/pysimplegui-pygame-integration-demo)
-
-
-
-
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-06T21:04:27Z
-@eliffile Maarten, you cannot reply to the GitHub emails. You need to click the link at the bottom that says "view it on github".
-
-Click the link in this message that you get and you'll see that your email replies have a lot of trash that shows up and the images (if you included any) will not be visible. You must use the GitHub site to reply to Issues if you want to avoid the trash and especially if you want any images to show up.
-
-I do see you've uploaded your project to GitHub! Very nice! You're doing great! Just be sure to use the GitHub site to reply to comments that you see arrive in email.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-06T14:32:34Z
-@eliffile You must come back to GitHub in order to post images. Replying to an email will not include them in the GitHub issue you're replying to. If you follow the link at the bottom, then you can see what your email replies look like. I suggest **_always_** clicking the link at the bottom of the email if you are going to reply so that you can paste images in and the other "junk" doesn't get posted that emails often include.
-
-Anytime you get an email from GitHub about an issue, and you want to "reply", click this link at the bottom of the email so that you are replying on the GitHub site itself:
-
-
-
-
-BTW - you're doing **_GREAT_**... you're a **genius** if you've not been told (I have a feeling you have). You're WAY ahead of schedule in your learning. I don't believe you are struggling in the least bit. You're thriving. I find programming difficult, every day. As you pointed out, reading other people's code is challenging. It's one of the most difficult things you can do in programming.
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-02-06T14:15:24Z
-Hi @eliff, where did you upload the files? I couldn't find them on your repositories
-
-I suppose you attached the files to the email, but it didn't work.
-You need to create a repository on your account and upload the files through GIT or your browser
-
-If you are not used to this you can find guides online that could help
-[Guide to upload files through browser](https://docs.github.com/en/repositories/working-with-files/managing-files/adding-a-file-to-a-repository)
-
-
-Also @PySimpleGUI maybe this messagess need to be edited, I see a token in the unsubscribe link, can you help him?
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-06T09:04:59Z
-On 04-02-2022 23:42, Mattia wrote:
-> @eliffile [1] that's a great project! 😍
-> Can I ask you to upload it on a repository? I would love to take a
-> look at the code on how you managed the card previewing
->
-> --
-> Reply to this email directly, view it on GitHub [2], or unsubscribe
-> [3].
-> Triage notifications on the go with GitHub Mobile for iOS [4] or
-> Android [5].
-> You are receiving this because you were mentioned.Message ID:
-> ***@***.***>
->
-> Links:
-
-> ------
-
-Regards,
---
-Maarten Venter
-
-NSW
-Australia
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-05T13:09:31Z
-Hi Maarten! It was your GUI that finally made the connection in my head that I've been searching for. I've noted a phenomenon over the past 3 years about PySimpleGUI and users that have not made GUIs before, but from seemingly nowhere arrive, as you have, with a massively complex GUI that's mindblowing in the genius of it all. The way you used sliders for positioning was so clever.
-
-What I've noticed is that the PySimpleGUI building blocks are simple, easy to understand, and as you're finding with some practice, simple to assemble. With enough time and patience large, complex creations are not only possible, but I've seen them happen numerous times. Your GUI in particular made the connection.
-
-### Minecraft!
-
-Minecraft is the analogy I've been searching for. I kept thinking "Legos" for all this time, but that's a physical not a computing world concept. I've been missing the computer model and Minecraft is that model.
-
-Thank you for the inspiration! As I've scribbled in my lab book many times... it's circular.
-
-
-
- We all are exchanging ideas and inspiration equally. I get back just as much as you're getting. Thank you!
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-05T10:34:17Z
-Hi,
-
-Thank you for the very kind words. It was extremely difficult when I
-started. I installed PySimpleGUI at the beginning of December and had to
-copy and paste the examples because I could not make out from the code
-what the result would be. I still find it hard to understand a lot of
-the elements but since I don't use them at the moment I let them be
-until I need them.
-
-It is hard to get the brackets right but I must compliment you on the
-perfection of it all. All the errors were my fault. Somebody asked me to
-to upload the code to my repo and I will do it tomorrow evening if I can
-understand how to do it. I tell you about this so you don't cringe if
-you get to see the code. Many things are still lacking but I am still
-working on it.
-
-Thank you for the amazing building blocks.
---
-Maarten Venter
-
-NSW
-Australia
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-05T10:16:38Z
-
-Hi Mattia,
-
-Sure I will do that. I will not be home tomorrow but when I get back I
-will attempt to upload it. You will cringe at my code since there are so
-many things that I do not understand yet. I am new to this game. I have
-trouble placing an animated GIF on the card (re-sizing it actually) but
-you might have a solution for it. Because of real estate constraints on
-the window I use checkboxes as buttons. Printing currently work only by
-calling photoshop since I still cannot get python to print the card
-correctly.
-
-Regards,
---
-Maarten
-
-NSW
-Australia
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-02-04T12:41:58Z
-@eliffile that's a great project! 😍
-Can I ask you to upload it on a repository? I would love to take a look at the code on how you managed the card previewing
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-04T10:50:50Z
-@eliffile wow a beautiful message to wake to and begin the day! I'm thrilled it's the first thing I read. Ever since seeing your post the other day your story has been on my mind and how remarkable it is that you've built this incredibly detailed application. I've never seen a beginner at programming do something like this right out of the gates! Honestly, never. Please keep building! Your pace of learning is genius. Thank you so much for sharing your work and your story. I'm inspired!
-
-
------------
-
-[eliffile](https://github.com/eliffile) 2022-02-04T09:56:34Z
-Greeting Card Maker
-
-Since I retired (68y) I found it necessary to combat my flailing memory. I decided to take up learning pythom but it was rather meaningless since I hate doing uninteresting exercises. I discovered PySimpleGUI. I found it difficult at first until I read Mike's note to design the window line by line and it all fell into place for me. I had a real project since I wanted to send cards to family and especially my grandkids. Now comes the real crunch. I have to learn python but I am sorting it out as I go
-
-.
-
------------
-
-[cosme12](https://github.com/cosme12) 2022-02-02T01:50:45Z
-Well, here is the small project I'm working on with PySimpleGUI. There is a small Tennis Club that wanted to stop using excel sheets to track reservations and the small shop sells. The software uses 2 screens. The main screen where you track all the sales and the second screen where you book the reservations. Note: everything is in Spanish
-
-
-
-In the main screen keeps tracks of the sales, how much money was earned during the day, how much is missing when closing and more.
-
-
-
-In the second screen you keep track of all the free hour times. Who book it, the state (canceled, played, waiting confirmation, rainny), if there is more than one player and the type of match (teacher, normal reservation, ...). In the gray columns you have recurrent reservations so you dont have to add them manually.
-
-
-
-
-You also have several other sections where you have the day and month statistics that can be seen depending if you are a normal employee or the owner.
-
-
-
-The you have another section where you keep track of how much people owes you (if they didn't pay)
-
-
-
-You can add new productos with their cost and sell price (like balls and fresh water) and another section where you can load products you bought from Wallmart or any other place
-
-
-
-
-
-On the main screen, when the people finish their match, you click their reservation and add all the items they bought to get the total. Click on the small list in the left and select the products
-
-
-
-There are several other sections, to load payments, make backup, add new players, edit, add notes and more. Overall PySimpleGUI is a fking awesome library. I wish I could make a donation but I'm getting paid $2.5/h, hopefully one day (3rd world problems :P)
-
-Keep it up with the great work, and know this work gets people jobs!!
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-02T01:13:44Z
-@kcl1s thank you for taking the time to post these screenshots! They're so inspirational to see.
-
-They're genuinesly the kind of things that makes me want to wake up and get started every day.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-02-02T01:01:39Z
-> GUI in 7 lines of code
-
-
-
-That's stunning to hear... wow!!
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-02-02T01:01:13Z
-My in progress OpenCV robot mobile platform
-Control tab using graph element to display an echo return from servo sweep with ultrasonic sensor.
-
-Face mesh tab showing 2 different frame images
-
-
-
------------
-
-[kcl1s](https://github.com/kcl1s) 2022-02-02T00:35:46Z
-A little OpenCV gesture detection exercise. GUI in 7 lines of code with list comprehension.
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-27T23:21:27Z
-Yes yes yes yes and yes on screen shot images.
-
-I'm working on a gallery feature to make it easier for us all to share screenshots.
-
-Glad you figured out the graph movement trick.
-
-I've got the same line of code in the Demo_Desktop_Widget_CPU_Dashboard
-
-```python
- self.graph_elem.move(-1,0)
-```
-
-It's so much more **fun** when it's easy. 😃
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2022-01-27T23:00:52Z
-Mike,
-
-the checkbox indicators are very useful, and we take it a step further in testing. While that screen above produces logic driven status indicators, our other process windows take a different approach....
-
-Although logic controls when devices are turned on/off, the status indicators are not driven by the controlling logic - instead the status indicators are directly tied to IO pin status for the pin controlling the relay as an example. This means that even if the control logic was 'supposed' to do X, the indicators show the actual physical status of the relay. So if there is a logic conflict it is easy to see an error during testing.
-
-There will be more examples. We are still learning / imagining what is possible. One suggestion for pysimplegui is to implement text alignment on buttons / radio buttons. We will do the tkinter calls to achieve this now, but it could be much easier.........
-
-I am hopeful the vast majority of our pysimplegui work will be completed within 4 - 6 weeks, I'd be more than happy to put a pack of images together that you could use for whatever promotional use that benefits pysimplegui - if it helps.
-
-Thanks again for your work! I am still blown away that we can achieve so much with comparatively little code.
-
-ps. for others reading this, there is not much easier to do than setting up scrolling displays - like an oscilloscope.
-
-Just move the contents of the graph left by 1 px each time, and draw your new Y point at the right extents of the chart.
-
-draw_point3 = irrigation_pressure_graph.move(-1,0)
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-27T21:31:02Z
-@WaterReNu your work is _**incredible**_!
-
-Thank you **SO much** for the support and for posting screenshots. What an amazing application to have completed!
-
-120 lines of code for the entire layout?! And that includes the oscilloscope displays, 24 LEDs? Wow... just... wow....
-
-It looks like maybe you used checkboxes for the LED displays for the valve tests. If so, I think that's a first. I've never used checkboxes to display status like that.... but I will now...
-
-I'm really impressed that your team did so well with this when you started being so resource bound. Those are non-trivial challenges. Hardware, software, GUI, realtime, .... you pretty much checked every box you could have. THIS... this right here is what gets me up and going every day.
-
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2022-01-27T20:10:58Z
-Hi Mike,
-
-this is 99% complete, some buttons to be added. Shows the ability of pysimplegui. All of the layout is done in about 120 code lines, without compressing lines into each other.
-
-The top 3 charts are static, showing how much power system motorized valves use.
-
-The bottom 6 charts scroll to the left, like an oscilloscope. Where there are 3 different legend colors the charts are auto ranging in the y scale for the color band. This allows us to show small values in detail, while still being to draw biy y numbers on the same chart.
-
-The right hand side with the multiple chck box colors shows the results of automated system tests. There are over 90 keys in this screen.
-
-I will get around to watching your course - bought it as one way to show support for your excellent work.
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-24T15:28:45Z
-@DeusAres WHOA!
-
-> Obviously the GUI was the easy part!
-
-
-
-You know the way to my heart 😃
-
-What a surprise! I 💗 it!!
-
-Games are potentially a new frontier for PySimpleGUI. Nothing in particular has changed to make it any more or less easy to write a game using PySimpleGUI that I can think of. But I am seeing more and more games starting to show up.
-
-Your cards are beautiful. I've never seen any like them before. Love the color scheme. Looks fantastic and posting a GIF really makes the window come to life.
-
-As I ponder the "Gallery" feature, I'm feeling the urge to include the ability to not just take a static screenshot, but to record a GIF if possible. That may prove to be too much... we'll see when I get further down the road. Thanks for the inspiration! What a great way to start a Monday!
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-24T15:23:32Z
-@vohe Nice! I was going to comment over the weekend that the link provided is giving a 404 error, but waited, and glad I did since it now works, wish a screenshot and everything! NICELY DONE!
-
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-01-24T12:06:52Z
-https://github.com/DeusAres/python-poker-game
-
-
-
-Obviously the GUI was the easy part!
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2022-01-23T13:53:09Z
-The Januar Version is ready to go.
-I manged it , finally, to work without lastfm. For everyone who can use this:
-Audiorecorder,, records (e.g.) spotify web player - with free account.
-
-
-Never thought i got this work as a "klick and run" program.
-Thanks also to : PySimpleGui
-
-vohe
-
-feel free to download at: https://github.com/vohe/Audiorecorder
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-17T18:34:55Z
-Hi @WaterReNu !! Definitely don't delete anything! And thank you for posting the screenshot and images! I'm so happy things are going in a positive direction for your team.
-
-
-
-You faced and tackled some thorny issues. Congratulations on the massive progress. And you did it on your own.... very nicely done!
-
-Post more images as your project moves forward if you would like.
-
-You've got a really clean-looking product. Certainly doesn't look like a prototype. Really happy things took a turn for the better! Thank you for getting the week off to a fantastic start. Nothing like a success story to get the ball rolling in a positive direction.
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2022-01-16T21:53:25Z
-Hi Mike, looks like we have solved our issues - it was related to core over utlization, so we had to go down the path of asynchronous threading, plus a lot better non blocking handling of timing loops.
-
-1 week to go before first customer uses the new controller as a replacement for the old technology. Still a lot to do of course.
-
-2 Main screens plus a whole lot of 'macro operation' guis to be done. Luckily pysimplegui makes the gui fast and relatively easy.
-
-I thought i'd add these photos for the raspberry pi guys reading this. 40 relays, 4 pwm, 8 interrupt pulse counters, 16 analog inputs, 16 digital inputs. PI 3 /3b running at 15% cpu average across cores, refined sensor value updates 10 per second, from raw measurements of 2,000 per second, across all the inputs.
-
-
-
-
-
-An example of complex logic execution with color status indicators, with non blocking timer delays for the cancel button.
-
-
-
-Let me know (or delete if you think this post is not appropriate). I know a lot of PI people, and a substantial majority dont know about python/pysimplegui/pi.
-
-And for the PI people, yes that is our own board design. We packed in as much as we could in the available space. Both the front and motherboards are double sided, SMT for IC's and passives etc, and we pick and place and bake in house.
-
-Best Regards
-
-Paul
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-16T15:10:43Z
-@DeusAres beautiful work! I love the custom highlighting you added. It added a level of sophistication and attractiveness that is not typical. Nice job!
-
------------
-
-[DeusAres](https://github.com/DeusAres) 2022-01-16T15:01:47Z
-[round buttons implementation](https://github.com/DeusAres/roundButtons) with highlight, idling and disabled state on tk version
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-14T10:41:47Z
-@shullaw tip for ya in case you've not discover it.... if you use `set_options` to set the icon for your application, rather than specifying in the `Window` creation, then ALL windows, including popups, will use this icon. I recommend using a Base64 encoded PNG files for this icon as it works across all Operating systems when using base64 strings. Glad you got it sorted out!
-
-@tostos5963 NICE GIF! ShareX is what I use to make GIFs for readmes, etc, because they are tiny somehow. Brilliant idea to show a GIF for your game.... nice work indeed!
-
-This is the most enjoyable Issue on any PySimpleGUI repo!
-
------------
-
-[tostos5963](https://github.com/tostos5963) 2022-01-13T22:13:15Z
-This is a gif animated version of Mahjong solitaire.
-https://github.com/tostos5963/PySimpleGUI-MahjongSolitaire
-
-
-
------------
-
-[shullaw](https://github.com/shullaw) 2022-01-13T21:27:25Z
-For sure I'll check it out!
-
-Edit:
-
-I'm seeing you use a base 64 string for an icon, could be my issue. I'm using the actual .ico file. I'll mess around and see if I can figure it out.
-
-Final edit (I promise):
-
-I guess I was incorrect! It does appear in the task bar. I do remember Windows initially not showing, but I think that is a Windows specific problem with storing an icon cache.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-13T20:20:56Z
-@shullaw those are some buttons to envy! What fun! The text and buttons pop straight out of the window.
-
-To answer your question about icons in your EXE file, take a look at the `psgcompiler` project. It shows where you can put the icon file so that the EXE has it. The icon on the taskbar should match the windows already though. hmmmm... feel free to open an issue.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-13T20:19:36Z
-I stumbled onto @tostos5963 Mahjong Solitaire recently and am glad to see it posted here!
-
-I also recently stumbled onto another game that @jason990420 wrote a long time ago but I don't think it's been posted here anywhere. I'm seeing more and more games written with PySimpleGUI and they're really well done! I recall Jason being the first to published a real game... it was a Klondike Solitaire game, it came from nowhere and was shocking to see as he extended PySimpleGUI considerably in order to write it. Card animations, etc, had never been done in PySimpleGUI before and I couldn't believe what I was seeing.
-
------------
-
-[tostos5963](https://github.com/tostos5963) 2022-01-13T15:26:56Z
-Mahjong solitaire programmed with PySimpleGUI.
-
-
-
-
------------
-
-[shullaw](https://github.com/shullaw) 2022-01-13T02:19:24Z
-A data retrieval application I've been working on. Inserts data into an excel template. The (custom) buttons react on hover and console output is routed to the multiline object. Used the PSG multithread method. Comes out to 48MB once packaged with `pyinstaller`. Only thing that I really would like to fix is the actual text in the multiline to expand on event and the icon on the task bar to be my .ico file (probably a Windows issue).
-
-I’m just seeing the psgtray repo so that might be my answer!
-
-Thanks!
-
-
-
-
------------
-
-[autostatic](https://github.com/autostatic) 2022-01-08T10:07:56Z
-Thanks! Got the inspiration from KeepassXC and also QJackCtl I think. The latter uses images but that doesn't work (yet?) in PySimpleGuiQt. Keep up the amazing work!
-
-Jeremy
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-07T21:29:49Z
-@autostatic Thank you for the rare PySimpleGUIQt screenshot! You posted while I was very distracted, I'm sorry for only now commenting.
-
-I like that you used the Tab title to show status. I've not seen that done.... anywhere that comes to mind, forgetting PySimpleGUI. Thank you for teaching me another trick/technique that can be used in any implementation. Simply had never come to mind as something that could be done.
-
-Thank you for taking the time to post your GUIs here!
-
------------
-
-[Cornbrother](https://github.com/Cornbrother) 2022-01-07T20:09:09Z
-> @Cornbrother .... I LOVE those fonts!! And I've never seen someone make a Frame Title like that. It's a thrill (I'm serious, it's a thrill) to learn from PySimpleGUI users ways PySimpleGUI can be used. Thank you for posting a screenshot!!
-
-yeah it was something I kinda visualised in my head to spice things up a bit and I thought it worked out. It would be neat if you could place multiple titles within a frame so that you could create either vertical row labels, or do more complex versions of this kind of detailing.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2022-01-07T18:56:17Z
-@Cornbrother .... I LOVE those fonts!! And I've never seen someone make a Frame Title like that. It's a thrill (I'm serious, it's a thrill) to learn from PySimpleGUI users ways PySimpleGUI can be used. Thank you for posting a screenshot!!
-
------------
-
-[Cornbrother](https://github.com/Cornbrother) 2022-01-07T18:47:55Z
-Honestly such a great resource, so many engineers forget that their projects need to be used by humans..
-
-https://github.com/Cornbrother/Pfennig-Pouch
-
-
-
-
------------
-
-[autostatic](https://github.com/autostatic) 2021-12-27T15:43:43Z
-Thanks for this library and all the best for 2022! [rtcqs](https://github.com/autostatic/rtcqs) is using PySimpleGUIQt for the GUI to show the results of the checks.
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-21T22:25:55Z
-I haven't found anything that runs on my iPad. I've got a Chromebook that won't install the PyDroid3 security check that would enable the pro features so even Android is far from perfect. Hoping to get a native APK solution down the road. It's the next big step for PySimpleGUI.
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-20T19:25:31Z
-yes @PySimpleGUI, stunning and crazy. Then 3 days later I found out that iOS doesn't even have python. And if you somehow install it, there is no tkinter. Very walled. I find that hard to believe. Is there a way to cope with that?
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-20T15:41:30Z
-WWWOOOOOOWWWWW @johanjohan thank you for that photo!!
-
-
-
-
-Yea, PyDriod3 rocks! I don't have many demos for it posted under the [PyDroid3 demos](https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms/PyDroid3) and was STUNNED just as you were when things required zero changes. OpenCV's camera worked on my phone just like my PC. CRAZY!
-
-
-
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-20T15:25:43Z
-@pamoroso thanks! Manually copied the files over. Didn't check whether git was there. I open the main python file in Pydroid3 (10$ or free with ads) and run it. Need to install needed modules via pip before, but so far no issues, even cv2, numpy etc is there. You may need to set PYTHONPATH etc in the code before importing any modules as the filesystem is different.
-Then some more font sizes need to be changed. That was all.
-I was amazed to find out, that even an aged tablet running _Android 5_ runs the app fine. So happy to save another unsupported piece of electro-junk from the mountain of eternal scrap.
-
-```python
-if __name__ == "__main__":
- def set_python_code_dir(script):
- import os
- import sys
- python_code_dir = os.path.dirname(os.path.realpath(script))
- python_code_dir = os.path.dirname(python_code_dir) # ../
- python_code_dir = os.path.join(python_code_dir, '') # add / --> whereever your code remains
- os.environ["PYTHONPATH"] = python_code_dir
- sys.path.append(python_code_dir)
- sys.path.append(os.path.abspath(os.path.join(python_code_dir, os.pardir))) # parent dir
-
- print("\n")
- print("python_code_dir:", python_code_dir)
- print("PYTHONPATH :", os.environ["PYTHONPATH"])
- print("sys.path :")#, sys.path)
- for p in sys.path:
- print("\t", p)
- print("\n")
-
- return python_code_dir
- set_python_code_dir(__file__)
-
-import abcxyz
-import my_file_in_a_folder
-```
-
-For internal prototypes that is perfect. To my knowledge, one cannot release it as an apk like this.
-
-
-
-
------------
-
-[pamoroso](https://github.com/pamoroso) 2021-12-20T14:47:24Z
-@johanjohan Great interface. How do you run it on Android?
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-20T14:44:04Z
-wow @PySimpleGUI , you amaze me. As you say, all are standard elements stripped of their decorations. I added exponential scales to the sliders, so they have more room in the lower ranges. What really hooked me, is that it just looks the same on Android and works out of the box. Totally amazing!! Well done @PySimpleGUI.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-20T13:15:26Z
-WOOOOWWWWW! @johanjohan what a BEAUTIFUL window!
-
-I assumed when I first saw it that you made your own sliders, much like shown in another screenshot above. It may be worth me looking into adding more of the Graph Element based elements in the future (the PySimpleGUI+ project that has the Dial element).
-
-Thank you for taking the time to post it here. It's been super-motivating to see what everyone is making and this past week the outpouring of support has been incredible.... overwhelmingly joyful messages that have made getting the Udemy course's final days of creation go by so much more pleasant.
-
-I think this window shows just how not-ugly tkinter can be. Yes, it takes work. Yes, it takes a good design. But that's the difference between a good interface and a truly GREAT one!
-
-Thank you so much.... this one post has given me so many ideas to work with.
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-19T17:24:12Z
-> The code is straight forward. Basically I got rid of all decorations, where the slider-'knobs' were the hardest to find...
-
-I like the flat look. Very modern.
-
------------
-
-[johanjohan](https://github.com/johanjohan) 2021-12-19T17:07:16Z
-Hey all,
-
-here is the gui for control of smart led lights. It is my first PSG project, still it was very possible to find all information needed. Thanks!
-
-
-
-I created the colors via https://color.adobe.com/create/color-wheel
-
-The code is straight forward. Basically I got rid of all decorations, where the slider-'knobs' were the hardest to find...
-
-```python
-def get_keys_by_instance(_window, instance_type):
- return [key for key, value in _window.key_dict.items() if isinstance(value, instance_type)]
-
-def get_keys_all(_window):
- return [key for key, value in _window.key_dict.items()]
-
-def get_color_select():
- return '#68868c'
-
-def get_color_button():
- return '#176477'
-
-def get_color_button_pressed():
- return '#C4B61B'
-
-def get_color_green():
- return '#4E7811'
-
-def get_color_purple():
- return '#672378'
-
-def get_color_red():
- return '#AB2D0F'
-
-def get_color_orange():
- return '#85533A'
-
-def get_colors_button_pressed():
- return ('white', get_color_button_pressed())
-
-def get_colors_text():
- return '#ededed' # cccccc
-
-def get_theme():
- return {
- "BACKGROUND": "#000000" if m_system.is_android() else "#1e1e1e",
- "TEXT": get_colors_text(),
- "INPUT": get_color_button(),
- "TEXT_INPUT": get_colors_text(),
- "SCROLL": get_color_button(), # same as INPUT
- "BUTTON": (get_colors_text(), get_color_button()),
- "PROGRESS": ("red", 'green'),
- "BORDER": 0,
- "SLIDER_DEPTH": 0,
- "PROGRESS_DEPTH": 0,
- "COLOR_LIST": ["#3e3e3e", get_color_button(), "#68868c", "#ededed"],
- "DESCRIPTION": ["Grey", "Turquoise", "Winter"],
- }
-
-def set_theme(key='m_psg'):
- sg.theme_add_new(key, get_theme())
- sg.theme(key)
-
-def prettify(window):
-
- # https://www.tutorialspoint.com/python/tk_scale.htm
- slider_keys = get_keys_by_instance(window, sg.Slider)
- for key in slider_keys:
- window[key].Widget.config(borderwidth=-2) # bd that is the relief bugger!!!!!!
- window[key].Widget.config(highlightthickness=0)
- window[key].Widget.config(background=get_color_select()) # slider button
- window[key].Widget.config(troughcolor=get_color_button())
-
- # https://www.tutorialspoint.com/python/tk_checkbutton.htm
- cb_keys = get_keys_by_instance(window, sg.Checkbox)
- for key in cb_keys:
- window[key].Widget.config(borderwidth=-2) # bd that is the relief bugger!!!!!!
- window[key].Widget.config(highlightthickness=0)
- import tkinter as tk
- window[key].Widget.config(relief=tk.FLAT)
- window[key].Widget.config(highlightthickness=0)
- window[key].Widget.config(selectcolor=get_color_button_pressed()) # get_color_button
- window[key].Widget.config(indicatoron=0) # no box !!!!
-
-
-
-```
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-19T13:29:03Z
-Simple GUI for using wget to download individual web pages or spider whole web sites. Use with caution against other people's servers - play nicely. Someone asked if I could archive 3400 web pages at work the other day. I used CLI wget but wished I had this.
-
-[[Edited: I've added Linux compatibility.]]
-
-
-
-[GitHub repository](https://github.com/andrewmk/wget_gui)
-
-```python
-import PySimpleGUI as sg
-
-import os
-import psutil
-import subprocess
-import sys
-import threading
-
-def resource_path(relative_path):
- try:
- base_path = sys._MEIPASS
- except Exception:
- base_path = os.path.abspath(".")
- return os.path.join(base_path, relative_path)
-
-def kill(proc_pid):
- process = psutil.Process(proc_pid)
- for proc in process.children(recursive=True):
- proc.kill()
- process.kill()
-
-def wget_thread(window: sg.Window, sp: subprocess.Popen, tnum: int):
- global running
- running = True
- for line in sp.stdout:
- oline = line.decode().rstrip()
- window.write_event_value('-WGET-THREAD-OUT-', oline)
- if running == False:
- kill(sp.pid)
- break
- if running:
- window.write_event_value('-WGET-THREAD-DONE-', f'==== THEAD {tnum} DONE ====')
- else:
- window.write_event_value('-WGET-THREAD-KILLED-', f'==== THEAD {tnum} KILLED ====')
-
-def fetch_next_url(curr):
- url = urls[curr].strip()
- if 'Single' in values['-MODE-']:
- args = []
- else:
- args = ['-r']
- args = args + ['--no-cookies', '--adjust-extension', '-v', '-H', '-E', '-k', '-K', '-p',
- '-N', '-np', '-e robots=off', '--html-extension', f'-P {values["-OUTPUT-DIR-"]}']
- args = [wget] + args + [f'"{url}"']
- window['-OUT-'].print(f'==== Starting {urls[curr]} ====')
- sp = sg.execute_command_subprocess(args[0], *args[1:], wait=False, stdin=subprocess.PIPE, pipe_output=True, merge_stderr_with_stdout=True)
- threading.Thread(target=wget_thread, args=(window, sp, curr), daemon=True).start()
-
-if sg.platform.system() == 'Windows':
- wget = resource_path('wget.exe')
- tmp = 'C:/Temp'
-else:
- wget = 'wget'
- tmp = '/tmp'
-
-layout = [
- [sg.Text('Starter URLs, one per line')],
- [sg.Multiline(expand_x=True, expand_y=True, key='-URLS-')],
- [sg.Text('Mode:'), sg.Combo(('Single page(s)', 'Recursively spider site(s)'), default_value='Single page(s)', key='-MODE-', readonly=True)],
- [sg.Text('Output folder:'), sg.Input(tmp, key='-OUTPUT-DIR-'), sg.FolderBrowse(initial_folder=tmp)],
- [sg.Multiline(size=120, expand_x=True, expand_y=True, key='-OUT-')],
- [sg.Button('RUN', key='-RUN-', button_color='white on red', bind_return_key=True), sg.Text(key='-FILE-', expand_x=True, justification='left'), sg.Push()]
-]
-
-window = sg.Window('GUI for wget', layout, finalize=True, resizable=True, size=(800, 400))
-curr_url = -1
-urls = []
-count = 0
-running = False
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- if (event == '-RUN-') and (curr_url == -1):
- # Start from beginning of list
- window['-OUT-'].update('')
- urls = values['-URLS-'].replace('\n\n', '\n').split('\n')
- count = len(urls)
- os.chdir(values['-OUTPUT-DIR-'])
- curr_url = 0
- sg.one_line_progress_meter("Progress on starter URLs...", 0, count, keep_on_top=True)
- window['-RUN-'].update('STOP')
- fetch_next_url(curr_url)
- elif (event == '-RUN-') and (curr_url >= 0):
- # Stop button pressed while running
- window['-OUT-'].print(f'\n==== Stopping fetching process ====\n', colors='red on white')
- sg.one_line_progress_meter_cancel()
- running = False
- curr_url = -1
- elif event == '-WGET-THREAD-OUT-':
- # Show something is happening
- if running:
- if not sg.one_line_progress_meter("Progress on starter URL list...", curr_url, count, keep_on_top=True):
- # Cancel button pressed while running
- window['-OUT-'].print(f'\n==== Stopping fetching process ====\n', colors='red on white')
- running = False
- curr_url = -1
- else:
- line = values['-WGET-THREAD-OUT-']
- if 'Saving to' in line:
- # Show current file being saved
- window['-FILE-'].update(line)
- elif event == '-WGET-THREAD-DONE-':
- window['-OUT-'].print(f'==== Finished {urls[curr_url]} ====')
- curr_url += 1
- if (curr_url < count) and running:
- # Part way through list so start next one
- fetch_next_url(curr_url)
- else:
- window['-OUT-'].print(f'==== Finished all URLs ====')
- sg.one_line_progress_meter_cancel()
- curr_url = -1
- window['-RUN-'].update('RUN')
- window['-FILE-'].update('')
- running = False
- elif event == '-WGET-THREAD-KILLED-':
- window['-OUT-'].print(f'==== Stopped fetching all URLs ====')
- curr_url = -1
- window['-RUN-'].update('RUN')
- window['-FILE-'].update('')
- running = False
-
-window.close()
-```
-
------------
-
-[dmitrijbes](https://github.com/dmitrijbes) 2021-12-13T12:43:43Z
-Small tool for screenshot comparison: [Detailist](https://github.com/dmitrijbes/detailist)
-
-Thank You for a great library!
-While severely lacking responsive, dynamic layouts support (suppose due to the complexity of implementation), it's easy and enjoyable to use.
-Definitely my future go-to for a simple, internally used interfaces!
-
-
-
------------
-
-[WaterReNu](https://github.com/WaterReNu) 2021-12-08T17:34:51Z
-
-Work in progress, it is a dynamic display, refreshing ever 1/2 second.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-07T13:57:09Z
-I forgot to put MikeTheWatchGuy on the whitelist
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-05T00:39:31Z
-GUI for the xkcd_password module (https://github.com/redacted/XKCD-password-generator).
-
-This code reaches through the chain link fence around PySimpleGUI and does some unpleasant things... I can't help thinking that there might be a better way of doing it but I couldn't find one.
-
-
-
-```python
-import PySimpleGUI as sg
-
-import tkinter
-from xkcdpass import xkcd_password as xp
-
-def C(height):
- return [sg.Col(layout=[[]], s=(None, height))]
-
-def W(k, fs=20, w=20, just='left'):
- return [sg.Input(k=f'-{k}-', p=0, s=w, font=f'Courier {fs}', justification=just)],
-
-layout = [
- C(80),
- [sg.Text('XKCD Password Generator', k='-TITLE-', p=0, s=30, font='Courier 20', justification='centre')],
- C(80),
- W(1),
- C(80),
- W(2),
- C(80),
- W(3),
- C(80),
- W(4),
- C(100),
- W('out', fs=18, w=32, just='centre'),
- C(60),
- [sg.Button('Generate', k='-GEN-', p=0, button_color='white on red')]
-]
-
-window = sg.Window('XKCD password generator', layout, element_justification='centre', size=(870, 1028), finalize=True)
-
-# Insert background image via tkinter
-filename = tkinter.PhotoImage(file = "battery.png")
-background_label = tkinter.Label(window.TKroot, image=filename)
-background_label.place(x=0, y=0, relwidth=1, relheight=1)
-background_label.lift()
-
-window['-TITLE-'].ParentRowFrame.lift()
-window['-1-'].ParentRowFrame.lift()
-window['-2-'].ParentRowFrame.lift()
-window['-3-'].ParentRowFrame.lift()
-window['-4-'].ParentRowFrame.lift()
-window['-out-'].ParentRowFrame.lift()
-window['-GEN-'].ParentRowFrame.lift()
-
-while True:
- event, values = window.read()
- if event == sg.WIN_CLOSED:
- break
- if event == '-GEN-':
- # create a wordlist from the default wordfile
- # use words between 5 and 8 letters long
- wordfile = xp.locate_wordfile()
- mywords = xp.generate_wordlist(wordfile=wordfile, min_length=5, max_length=8)
- passwords = xp.generate_xkcdpassword(mywords, numwords=4)
- password_list = passwords.split(' ')
- window['-out-'].update(''.join(password_list))
- for i in range(4):
- window[f'-{i + 1}-'].update(password_list[i])
-window.close()
-```
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-02T17:08:31Z
-> I would like to point out that @andrewmk went from never hearing of PySimpleGUI, from starting from scratch to being DONE in 3 days. That's an incredible achievement! AND he wrote a nice piece of code I'm turning into a Recipe and a Demo Program too! AND it involved multiprocessing and multithreading. That's brain-surgery level stuff.
-
-If there's one thing I'm good at it's learning from examples. And you've provided all the examples, so thank you!
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-12-02T16:14:05Z
-I would like to point out that @andrewmk went from never hearing of PySimpleGUI, from starting from scratch to being DONE in 3 days. That's an incredible achievement! AND he wrote a nice piece of code I'm turning into a Recipe and a Demo Program too! AND it involved multiprocessing and multithreading. That's brain-surgery level stuff.
-
-
-Major accomplishment stuff in a short period of time. For seasoned developers, I think this is tremendous "fun". Being able to do something trivially that used to be tedious is fun, enjoyable.
-
-Thanks so much for stopping in @andrewmk and sharing your experience. It was really helpful, very motivating to hear your story.
-
-
-
------------
-
-[andrewmk](https://github.com/andrewmk) 2021-12-02T16:07:45Z
-A utility to remotely administer websites by running commands over SSH, and generate templated text from a structured input form. I'll no doubt be adding more functionality to this as we come up with new ideas.
-
-
-
-
-
------------
-
-[Vresod](https://github.com/Vresod) 2021-11-23T23:47:10Z
-Here is my program! It edits Among Us files. 👍
-
-
-
------------
-
-[frici11](https://github.com/frici11) 2021-11-23T18:32:26Z
-Sorry, now I have uploaded it into my repo. Hope that it can be accessed.
-(If someone would use it, some documentation can be useful - but until now I didn't write anything...)
-
-________________________________
-Feladó: PySimpleGUI ***@***.***>
-Elküldve: 2021. november 23., kedd 18:41
-Címzett: PySimpleGUI/PySimpleGUI ***@***.***>
-Másolatot kap: Frigyes Gábor ***@***.***>; Mention ***@***.***>
-Tárgy: Re: [PySimpleGUI/PySimpleGUI] Post your screen shots here! (#10)
-
-
-
-CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.
-
-
-Your attachment didn't come through because you're replying to a GitHub email. It'll post the text here in the issue but won't include any attachments. You'll have to follow the link at the bottom of the email and post the code in the issue, or post it in a GitHub repo or a Gist. I'm CERTAINLY interested and I'm sure other users would be too!
-
-—
-You are receiving this because you were mentioned.
-Reply to this email directly, view it on GitHub, or unsubscribe.
-Triage notifications on the go with GitHub Mobile for iOS or Android.
-
-FELHÍVÁS AZ ÜZENET BIZALMAS JELLEGÉRE
-Ez az elektronikus levél, s bármely melléklete bizalmas és/vagy jogilag védett információkat tartalmazhat, és kizárólag a címzettnek szól. Amennyiben Ön tévedésből kapta meg az elektronikus levelet, kérjük, haladéktalanul értesítse erről a feladót és az üzenetet, valamint annak minden másolatát azonnal törölje rendszeréből. Amennyiben Ön tévedésből kapta meg ezt a levelet, annak engedély nélküli másolása, sokszorosítása, módosítása, közzététele, terjesztése, és nyilvánosságra hozatala szigorúan tiltott.
-CONFIDENTIAL INFORMATION
-This e-mail and any attachment may contain confidential and/or privileged information and is intended exclusively for the addressee. If you are not the intended recipient, please notify the sender immediately and delete this e-mail and any copies of it from your system. If you have received this email in error, any form of copying, dissemination, modification, disclosure, distribution and/or publication of this e-mail message without preliminary permission is strictly prohibited.
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-23T17:41:29Z
-Your attachment didn't come through because you're replying to a GitHub email. It'll post the text here in the issue but won't include any attachments. You'll have to follow the link at the bottom of the email and post the code in the issue, or post it in a GitHub repo or a Gist. I'm CERTAINLY interested and I'm **sure** other users would be too!
-
-
------------
-
-[frici11](https://github.com/frici11) 2021-11-23T16:26:01Z
-Thank you so much, your words mean much to me.
-I really appreciate the concept and amazing work behind PySimpleGUI.
-
-Yes, all the graphs (even the marker on the Line chart) are PySimpleGUI, so this is not my work but yours. :)
-Just some tkinter "hacking" is added where it is can't be avoiding.
-
-All the charts are a bit interactive, that's why I didn't want to use another existing lib.
-(It's disadvantage is the too long source, all the classes are 200-250 lines.)
-
-I have attached the code with a little test program if you are interested.
-
-________________________________
-Feladó: PySimpleGUI ***@***.***>
-Elküldve: 2021. november 23., kedd 16:29
-Címzett: PySimpleGUI/PySimpleGUI ***@***.***>
-Másolatot kap: Frigyes Gábor ***@***.***>; Mention ***@***.***>
-Tárgy: Re: [PySimpleGUI/PySimpleGUI] Post your screen shots here! (#10)
-
-
-
-CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.
-
-
-I LOVE what you did with the Graph Element too!
-
-I just finished recording that lesson and you've shown exactly what I was explaining in that lesson... that the Graph Element is a "Gateway Element"... you can make new elements, new types of graphs, it's a blank canvas ready to be painted.... I really like that Donut Chart. It's incredible how you've got a piece that's selected and pulled out to show it.
-
-Absolutely 💗 what you're making!
-
-Are all of your Graphs from PySimpleGUI??? Even the one with the marker?
-
-[image]
-
-—
-You are receiving this because you were mentioned.
-Reply to this email directly, view it on GitHub, or unsubscribe.
-Triage notifications on the go with GitHub Mobile for iOS or Android.
-
-FELHÍVÁS AZ ÜZENET BIZALMAS JELLEGÉRE
-Ez az elektronikus levél, s bármely melléklete bizalmas és/vagy jogilag védett információkat tartalmazhat, és kizárólag a címzettnek szól. Amennyiben Ön tévedésből kapta meg az elektronikus levelet, kérjük, haladéktalanul értesítse erről a feladót és az üzenetet, valamint annak minden másolatát azonnal törölje rendszeréből. Amennyiben Ön tévedésből kapta meg ezt a levelet, annak engedély nélküli másolása, sokszorosítása, módosítása, közzététele, terjesztése, és nyilvánosságra hozatala szigorúan tiltott.
-CONFIDENTIAL INFORMATION
-This e-mail and any attachment may contain confidential and/or privileged information and is intended exclusively for the addressee. If you are not the intended recipient, please notify the sender immediately and delete this e-mail and any copies of it from your system. If you have received this email in error, any form of copying, dissemination, modification, disclosure, distribution and/or publication of this e-mail message without preliminary permission is strictly prohibited.
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-23T15:28:51Z
-I LOVE what you did with the Graph Element too!
-
-I just finished recording that lesson and you've shown exactly what I was explaining in that lesson... that the Graph Element is a "Gateway Element"... you can make new elements, new types of graphs, it's a blank canvas ready to be painted.... I really like that Donut Chart. It's incredible how you've got a piece that's selected and pulled out to show it.
-
-Absolutely 💗 what you're making!
-
-Are **all of your Graphs from PySimpleGUI???** Even the one with the marker?
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-23T14:57:40Z
-
-
-What a way to start my day!
-
-@frici11 you've come out of nowhere with this! I don't see any issues where you've asked a question. This is a really incredible piece of work! Oh, AND you're multi-lingual on top of it so you're reading English documentation, and writing for use in another language. WAY over my head in skills. Wow... just.... wow.... Going to take it all in and enjoy what you've created. There's so much here to enjoy!
-
-I'm thrilled you've made something so useful to you and inspirational to me and others!
-
-
------------
-
-[frici11](https://github.com/frici11) 2021-11-23T13:41:00Z
-I have just finished an app in PySimpleGUI. (portfolio evaluation with analyzing cash flows, calculating yield rates, currency effects etc.)
-Although they are not in english (sorry), but I share 3 screens, with two comments:
-1.) The charts you can see are also in PSG. I made three classes upon sg.Graph: column, line, pie/donut.
-2.) I had to solve the numeric input issue: have written a class inherited from sg.Input which needs an extra "mask" argument. This argument determines either the input (user entry) and the output (display formatting) too. It works fine for me.
-
-
-
-
-
-I love PSG, it's a huge help. Thank you!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-22T15:50:58Z
-@luflopes - I had just finished making a lesson that made a bar chart so I had the code literally open in PyCharm. All I had to do was add labels and draw the axes. I kept it super simple in the lesson and drew the bars and values on top. All I did was copy your colors (love those colors) and data.
-
-I did a tiny sliver compared to what you've accomplished. I like your icon for the calendar too. Lots to like about what you posted. Thank you for sharing your work! No doubt, it will be helpful to others (I've already benefited by seeing it and taking ideas from you 😀)
-
------------
-
-[luflopes](https://github.com/luflopes) 2021-11-21T20:02:49Z
-Thank you @PySimpleGUI.
-This way to create with the graph element is much simple and very good. I love it!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-20T12:17:53Z
-Totally agree! Very nice use of color! I like it!
-
-Thank you @luflopes for taking the time to post it! Love seeing these. Really helps with motivation to see many things being built!
-
-Last week I recorded the Graph Element lesson.... the first example of the lesson was drawing a bar chart.
-
-I mocked up a quick little example using your data, colors. The point of the exercise was to demonstrate how to draw these kinds of graphs using a Graph element. They're surprisingly easy when you do two things:
-1. Sketch the layout of the graph so you know each component
-* A component can be a label, an axis, a bar, etc.
-2. Get the units of your graph to match your design / data
-
-In my mockup, I used an X-axist that a simple counting from 1 to 15 to give me simple formula for drawing bars. There are 7 bars, so each bar will take up 2 units.
-
-In the Y-axis, I looked at your data and determined it should be 0 to .06.
-
-For both axis, I actually made them start at a negative value so I could draw axis and labels. The final units were -1 to 15 on the X and from -.01 to .07 on the Y.
-
-This technique may be good in some situations where Matplotlib is going to be difficult to integrate or maybe your data is really simple. I've cheated a bit by looking at your data. I should have computed these values based on the max and min values of your data, but I only took 10 minutes to throw it togethert. and it seemed like maybe hard coding them would be more illustrative.
-
-This code:
-
-```python
-import PySimpleGUI as sg
-
-sg.theme_background_color('white')
-sg.theme_element_background_color('white')
-
-def main_bar_example():
- data_points = [.019, .026, .021, .051, .024, .058, .026]
- colors = ['#cb3ce3', '#b758e7', '#a374eb', '#8f90ef', '#73a4eb', '#57b8e7', '#3bcce3']
- dates = ['2021-01-01','2021-02-01', '2021-03-01', '2021-04-01', '2021-05-01', '2021-06-01', '2021-07-01']
-
- graph = sg.Graph((600, 600), (-1,-.01), (15, .07), k='-GRAPH-')
-
- layout = [[graph], [sg.Button('Exit')]]
-
- window = sg.Window('Graph Element - Example 1', layout, finalize=True)
-
- graph.draw_line((0,0), (14,0), width=3)
- graph.draw_line((0,0), (0,0.06), width=3)
- for i in range(7):
- graph.draw_text(f'{i*.01}', (-.5, i*.01), font='_ 10')
- graph.draw_line((-.1,i*.01), (0, i*.01), width=3)
- while True:
-
- for i, data in enumerate(data_points):
- color = colors[i]
- label = dates[i]
- graph.draw_rectangle((i*2+.1, data), (i*2+1.5, 0), fill_color=color, line_width=0)
- graph.draw_text(f' {data}', (i*2+.2, data+.002), font='_ 15')
- graph.draw_text(f' {label}', (i*2+.3, -.001), font='_ 10')
-
- event, values = window.read()
- if event in (sg.WIN_CLOSED, 'Exit'):
- break
-
- window.close()
-
-main_bar_example()
-```
-
-
-Produced this window:
-
-
-
-
-[ EDIT ] - I liked your no-line around your bars! Nice touch...
-
-
-[ EDIT 2 ] - Oh wow, you did a lot of windows I didn't scroll back far enough the first time to see all FIVE windows! Very nice!
-
------------
-
-[luflopes](https://github.com/luflopes) 2021-11-19T21:40:50Z
-> @luflopes Love the design and color palette.
-
-Thank you @pamoroso .
-I'm happy you liked this.
-
------------
-
-[pamoroso](https://github.com/pamoroso) 2021-11-19T21:33:35Z
-@luflopes Love the design and color palette.
-
------------
-
-[luflopes](https://github.com/luflopes) 2021-11-19T21:30:33Z
-I made a small system to control and report performance indicators data for a "company" using PySimpleGUI. **Thank all you!**
-
-**1) Login page:**
-
-
-
-**2) Register page:**
-
-
-
-**3) A page to retrieve data and post:**
-
-
-
-**4) An user administrator page:**
-
-
-
-**5) An interactive dashboard using seaborn and matplotlib:**
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-11-04T18:35:41Z
-Very nice!
-
-Love all the graphics you're including your GUIs. It adds a level up from the basic elements. Great work! Thank you for posting them. I get a motivational boost every time I see something new created. Keep building! 💗💗💗
-
------------
-
-[Pranav-P-16](https://github.com/Pranav-P-16) 2021-11-04T02:55:59Z
-Created a Simple Youtube Downloader using PySimpleGUI :blush:
-
-
-
-
-
-
-
-
-
-:heart::heart::heart::heart::heart: PySimpleGUI :heart::heart::heart::heart::heart:
-
------------
-
-[Pranav-P-16](https://github.com/Pranav-P-16) 2021-11-01T04:11:56Z
-> You're quite welcome.
->
-> **Thank you** @Scania-Creations-16 for posting your screenshot! Awesome awesome creation! I'm impressed!
->
-> And a thank you to @jason990420 for helping everyone be successful.
->
-> Can you post a link to your code?
->
-> I'm sure there are things that others can learn. If you're a beginner, then I'm definitely interested in seeing what you did. Beginners tend to do crazy things that others (including me) wouldn't think to do. I've learned a lot from beginners. Don't worry about showing your code. We've all, every one of us, have been where you are in your education of Python.
-
-I don't know what to say, I'm extremely happy by seeing your comment. :smiley: :smiley: :smiley: :smiley: :smiley: :smiley:
-
-Actually I'm a Newbie to GUI Programming,although I've started this about 2 years back (simple ones like clock,calculator etc.), It's been only a few months since I've actually put my mind into it.
-
-**The most satisfying part of Programming is the joy we get when we are using our own Program for needs than depending on other softwares :smile::smile::smile::smile::smile::smile:**
-
-I will surely post my code when the project is completed :100:
-
-and Once again, Thank You Sooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo much PySimpleGUI :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart: :heart:
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-10-31T19:16:54Z
-You're quite welcome.
-
-**Thank you** @Scania-Creations-16 for posting your screenshot! Awesome awesome creation! I'm impressed!
-
-And a thank you to @jason990420 for helping everyone be successful.
-
-Can you post a link to your code?
-
-I'm sure there are things that others can learn. If you're a beginner, then I'm definitely interested in seeing what you did. Beginners tend to do crazy things that others (including me) wouldn't think to do. I've learned a lot from beginners. Don't worry about showing your code. We've all, every one of us, have been where you are in your education of Python.
-
------------
-
-[Pranav-P-16](https://github.com/Pranav-P-16) 2021-10-31T04:14:25Z
-I made a Music Player using PySimpleGUI
-
-
-
-
-
-
-
-Thanks a lot PySimpleGUI :smiley:
-
-Without You,I would've made no GUI programs :heart: :heart: :heart: :heart: :heart:
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-10-22T14:51:31Z
-@mechanicalnull THANK YOU!!
-
-
-
-Nothing motivates me more than seeing screenshots!
-
-(Jason yelling (he doesn't yell...he's too nice to yell....) at me comes in at a close second)
-
-
-
------------
-
-[mechanicalnull](https://github.com/mechanicalnull) 2021-10-22T12:04:54Z
-I used PySimpleGUI for a [recent project](https://github.com/mechanicalnull/fuzzwatch) to illustrate what a fuzzer is doing, and it made things look pretty good without a ton of code. It was able to handle all the things I wanted to do and wasn't too hard to figure out. Just wanted to share and say thanks!
-
-
-
-
-
------------
-
-[hseera](https://github.com/hseera) 2021-09-25T22:55:50Z
-> Love it @hseera !
->
-> I detect the Reddit Theme I believe in your window if I'm seeing it correctly.
->
-> Very nice look. A friend was talking on Friday to me about this S3 Region problem...of finding where things are located.
-
-Yes, I am using Reddit theme. I feel it is easier on the eyes.
-
-Yes that was another of my reason to build this tool. Now just trying to figure out how to delete the data in the tree and repaint it when I select a different region.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-09-25T18:13:19Z
-Love it @hseera !
-
-I detect the Reddit Theme I believe in your window if I'm seeing it correctly.
-
-Very nice look. A friend was talking on Friday to me about this S3 Region problem...of finding where things are located.
-
------------
-
-[hseera](https://github.com/hseera) 2021-09-25T11:30:05Z
-Just developed an AWS S3 Viewer application using PySimpleGUI. You can navigate all the buckets in S3 in your account. You can search for a file name. If it exists, it prints the full path in the console.
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-09-04T14:37:53Z
-@hseera AWESOME software! I yesterday discovered your work and was showed some of it to @Chr0nicT yesterday afternoon on Discord!
-
-
-
-
-This is the link I was sharing for users that may be interested in finding this repo quickly:
-https://github.com/hseera/aws-python-utilities#13-sqs-workbench
-
-Thank you so much for posting a screenshot here! It is so very helpful for others to see the universe of possibilities.
-
------------
-
-[hseera](https://github.com/hseera) 2021-09-04T07:29:45Z
-Recently developed an AWS SQS workbench utility using PySimpleGUI for Windows that allows sending and viewing messages to AWS SQS. It is useful for those whom don't have much knowledge of how to use AWS CLI/SDK. OR find annoying logging into AWS console every time they want to do work with SQS.
-
-I have used multiple facets of PySimpleGUI for this utility. It uses multithreading, File browse/save, table, layout, using eventing to display console msg in a multiline text etc features provided by PySimpleGUI.
-
-
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-31T13:09:22Z
-@readicculus I'm not sure if you're trying for a retro look with the ------- lines between sections. If you prefer a solid line, you can use a HorizonalSeparator element
-
-Here's how they look different:
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-31T00:40:51Z
-> Thanks again for all you do!
-
-Seeing results like these make it really really easy to do my part. You're the one making the hard stuff!
-
-STUNNED.... I'm genuinely stunned every time I see one of these GUIs you fine guys and gals are creating. "I've seen it all", and then the next day happens....
-
-You make it FUN and yet it's serious research and work that's getting accomplished.
-
-Thank you so so much for sharing!
-
-
------------
-
-[readicculus](https://github.com/readicculus) 2021-08-30T22:16:48Z
-I made a GUI for creating batch jobs that run detection pipelines against many pre-defined datasets. This work is to help support aerial surveys of seals and polar bears. We collect millions of images per year, and this GUI is intended to make it easier for the researchers to run detection(and some day tracking or other pipelines).
-
-
-Picture of the initial page where you can setup your Job by selecting datasets, which detection pipeline to run, and configuring the detection hyperparameters.
-
-
-Validates incorrect user input
-
-
-Picture of the progress page that lists all the tasks in a job, the output from the detection process, and progress/time estimations.
-
-
-Picture of some seal detections :)
-
-If for some reason things crash, the application saves state making it easy to resume a partially completed job.
-
-Also made an About page to show off the sweet icon for the app ;)
-
-
-
-PySimpleGUI is sweet! It's designed to be easy for beginners but still allows for advanced feature development. The api is very featured while staying consistent and intuitive. It is clear that a lot of thought, effort, and care has been put into this project. Thanks again for all you do!
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-12T01:42:20Z
-https://github.com/PySimpleGUI/PySimpleGUI/wiki
-
-The GitHub Wiki!
-
-Totally get that humbled thing... I feel that way every morning. It's all pretty nuts, but FUN, so we're meeting that goal. What a fun goal to have... fun.... pretty sneaky huh? "You're having way too much fun!" "Yea, but that's the goal!" "Oh oh yea... carry on..."
-
------------
-
-[AyhamSaffar](https://github.com/AyhamSaffar) 2021-08-12T01:37:41Z
-All this positivity has really made my week!
-
-Yea i mean i tried getting into TKinter at the start but it just felt like there where way too many steps to do anything and the code wasn't super intuitive. I never felt confident enough to start anything.
-
-Being able to make a GUI is one of those really neglected skills that us science & engineering students would really benefit from. I think PSG is simple enough that it should be taught alongside libraries like Pandas and MatPlotLib. I have shared [this video](https://www.youtube.com/watch?v=svcv8uub0D0&t=15s) alot but ill have to do a talk on PSG once uni starts again.
-
-I didn't realise PSG had a wiki. Is [this](https://en.everybodywiki.com/PySimpleGUI) what you mean?
-
-Also i think the project details section is a great idea. It has been really interesting and humbling scrolling through this thread.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-11T20:28:32Z
-UUhhhh..... @AyhamSaffar I should have asked permission I think.... maybe I should put a disclaimer on this issue:
-
-"Warning - I will show off your work and be proud of what you make"
-
-I'm glad it wasn't a problem to show it.
-
-You've got a lot of reasons to be proud of this accomplishment! I mean, just look at that window! My head explodes thinking what it would have taken if written in ANY of the other GUI frameworks. I'm not the best Python programmer (by a LONG ways) and I'm not the best tkinter developer either, but I know enough about both to know it would take a lot of code to duplicate what you built using tktiner directly.
-
-Your story is also really awesome.
-
-It motivated me to add this new section to the Issues.
-
-https://github.com/PySimpleGUI/PySimpleGUI/issues/4608
-
-
-
-
-All of these Windows are motivating for me and I think for other users.
-
-I wish the Wiki was used more. There needs to be something written to make it trivial or something done that I've not yet done because it's rather empty.
-
-I keep trying to find the words to describe the elation at seeing what's being made. It's also a lot of fun just talking to the PySimpleGUI users. You're a great group of people even though your backgrounds are SO different. Many or most are not "software engineers". I'm reminded of this when I see all of these highly scientific programs.
-
-Thank you for being OK with me Tweeting out your creation!!
-
------------
-
-[AyhamSaffar](https://github.com/AyhamSaffar) 2021-08-11T20:12:34Z
-omd u put my thing on ur twitter. I am so flattered, especially by the deathstar analogy. Cheers Mike!
-
------------
-
-[AyhamSaffar](https://github.com/AyhamSaffar) 2021-08-11T00:21:44Z
-I made a scientific app <:
-
-
-
-It finds the average grain size in a microscope image.
-
-I always wanted to make this app ever since we did this process manually in a lab. I am so lucky i stumbled across a PySimpleGUI video on my youtube and realised it was actually possible!
-
-I am so grateful for the library and all the support. Mike & Jason u guys are amazing.
-
-Cant wait to show this off when i get back to uni!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-07T16:34:34Z
-@vinniec
-
-> I was wondering if there is a way to make an interface that dynamically changes the size also adapting its content.
-
-Please open an issue so we can discuss ways to maybe make this happen.
-
-You're in an environment that's really unique. I don't have an answer that's at my fingertips. Please post an issue, include those great screenshots, a simple layout that will maybe be representative of what you're wanting to do, etc.
-
-These are always really really great to see!!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-08-07T16:30:26Z
-There's a demo `Demo_Column_Collapsible_Sections.py` that shows the collapsable sections that are used in a number of built-in PySimpleGUI windows. The test harness `sg.main()` uses one and the open github issue window `sg.main_open_github_issue()` also uses on.
-
-To get the entire window to grow and shrink, the critical piece is the use of the `pin()` helper function. It is `pin` that both reserves the space and also enables a nearly complete collapse of the layout/window.
-
-## Demo Program
-
-https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Column_Collapsible_Sections.py
-
-
-
-
-## sg.main()
-
-
-
-
-## sg.main_open_github_issue()
-
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2021-08-07T11:00:56Z
-User defined element: [class Fold](https://github.com/jason990420/PySimpleGUI-Solution/issues/88)
-
-
-
------------
-
-[vinniec](https://github.com/vinniec) 2021-08-07T07:57:36Z
-I tried [my past application](https://github.com/PySimpleGUI/PySimpleGUI/issues/10#issuecomment-791053626) on pinephone (this is one of the reasons why I had wanted to try pysimplegui a while ago). It works fine:
-
-
-
-But there is some problem:
-When I open the keyboard the window doesn't resize and moves all at the top outside the screen
-
-
-
-The same when I change the screen to the horizontal orientation, instead of resizing the gui is cutted on top and on the bottom.
-
-
-
-I was wondering if there is a way to make an interface that dynamically changes the size also adapting its content.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-06-25T23:17:59Z
-Keep making stuff @LP-Codes !
-There's a new clipboard function you might find useful in the latest released PySimpleGUI, but it's only "safe" on Windows as the contents may not remain on other platforms. Tkinter still doesn't retain the clipboard contents after the window exits except on Windows.
-
-
------------
-
-[ghost](https://github.com/ghost) 2021-06-24T05:44:57Z
-### A Simple Random-Password Generator
-
-https://github.com/LP-Codes/Python-Random-Password-GUI
-
-
-
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2021-05-27T07:20:01Z
-A Small Utility Made Using pysimplegui For Quickly Editing Text Cases Comes Handy When Dealing With Large Text
-[https://github.com/LP-Codes/Text-Case-Converter-Editor](https://github.com/LP-Codes/Text-Case-Converter-Editor)
-
-
-
------------
-
-[Fethbita](https://github.com/Fethbita) 2021-05-20T15:10:13Z
-I created an Electronic Machine Readable Travel Document (eMRTD) reader and verifier with face recognition included. I used PySimpleGUI. Here is a gif of [eMRTD_face_access](https://github.com/Fethbita/eMRTD_face_access):
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-05-02T04:31:22Z
-The taskbar is a difficult challenge. I make one when the window is minimized. It was just a thought. Was I said, not all good ideas. But, every now and then a good one happens.
-
-Congrats on fabulous GUI! Thank you for sharing.
-
------------
-
-[elibroftw](https://github.com/elibroftw) 2021-05-02T03:29:23Z
-The dark theme is based on the matte black color scheme. It's actually the number one Firefox theme.
-
-I tried the custom bar before and the biggest problem is that the window icon does not show up in the taskbar as one would expect. The other issue is that although the title bar is dark, it looks fake. The font looked weird (probably my fault) and the disabled maximize button was misaligned. I just need the taskabr icon issue fixed. Fix should be easy (I think deiconify or something, googling the issue yields a stackoverflow.com answer).
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-05-02T03:02:42Z
-To be clear, these are already homeruns! LOL
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-05-02T03:01:47Z
-@elibroftw INCREDIBLE. Instant smile and admiration.
-
-I rarely, never actually , make suggestions, but I'm gonna go out on a limb just for fun because you've embraced dark so well.
-
-Consider trying a version with a custom titlebar added. You can do that with a simple part in the Window call. It's an easy test, and you may have very well done it. Keep in mind that I have tons of ideas, and they're mostly not good, so try at your own peril.
-
-
------------
-
-[elibroftw](https://github.com/elibroftw) 2021-05-02T00:27:51Z
-Here is 1.5 years of developing my [Music Player ](https://github.com/elibroftw/music-caster) using PySimpleGUI.
-
-mini-mode
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-28T20:43:34Z
-@daemon2021 It was MORE than a fair trade.... appreciate your help.
-
-It's easy to work on this project when these kinds of images are posted. Twitter had a couple of nice ones this week too. It's hard not to want to help you fine, grateful, guys and gals make the software you dream of making. It's a shared accomplishment. I feel some of the happiness you feel. It's a truly joyful experience in the end. I've not had products that have been as rewarding as this project has been. It's different being an 'enabling' technology.
-
-Keep on building and posting!!
-
------------
-
-[daemon2021](https://github.com/daemon2021) 2021-04-28T08:26:39Z
-Hi all,
-I've just made a good use of the "Gray Gray Gray" theme defined in PySimpleGUI 4.40.0.
-Together with the options `ttk_theme = sg.THEME_VISTA` and `use_ttk_buttons = True` I finally got a "look&feel" that is close to native on Windows 10.
-See below a screenshot of the app that I'm currently developing (the images are a temporary unbranding, just for fun!).
-It is a custom tool for firmware programming of external hardware connected to USB ports.
-The table of attached devices is dynamic and autosizing and there is an option to scale the window for matching the display size.
-I'm running PySimpleGUI in a dedicated process, with the logic controlling the external hardware executed by another process.
-The two processes communicate using JSON RPC messages sent through queues. This is for a fully non-blocking and scalable performance.
-There is a unified logging systems routed both to file and GUI console.
-It's my first project with PySimpleGUI and therefore I "tortured" Mike and Jason with a lot of questions...
-Finally I implemented what I had in mind, thanks to the tons of features and flexibility that PySimpleGUI offers.
-Thank you guys! PySimpleGUI is a fantastic platform and the level of your support is awesome.
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-21T15:07:41Z
-@pamoroso I LOVE what you've been doing with PySimpleGUI on replit. Blows me away what you're doing! And thank you for the support over the years. 🙏
-
------------
-
-[pamoroso](https://github.com/pamoroso) 2021-04-21T14:05:25Z
-Here's a screenshot of [Spacestills](https://github.com/pamoroso/spacestills), a NASA TV still frame viewer.
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-05T23:32:07Z
-Thank you for the kind words. In response to the above comment. Is this Tkinter only ? My word it is.
-100 percent is ONLY PySimpleGUI. I don't even know what ttk is really. Can I post code here or some other pages to prove this.
-There are no other dependancies in my code either.
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-05T14:29:46Z
-> I owe him many coffees yet !
-
-These screenshots are a fantastic trade! No coffee required. You've given me something coffee will never be able to actually provide... pure joy.
-
-I'm dying to know if the shot that says "This is Tkinter Only" is PySimpleGUI or tkinter. I have a feeling it's not PySimpleGUI, but, I can't tell.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-05T14:09:21Z
-@neovich please email me! mike@PySimpleGUI.org.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-05T13:47:19Z
-@neovich I might cry... ok, maybe iI did a little....
-
-This SO BEAUTIFUL!
-
-It looks like you're using ttk sliders. This isn't PySimpleGUI I would assume as I don't yet support ttk sliders.
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-05T13:31:15Z
-Hi All PySimpleGUIans,
-A screenshot using Tkinter only. Demos sliders and a VU meter . This is a demo example from actual code that I use.
-The VU meter and slider(s) integrates into a DSP unit ( via lan ) , a BSS Blu 100 DSP unit to be exact.
-It subscribes to the Blu 100 unit and get feedback from the meters and volume controls. Works like a charm.
-I will extract my working code from that system and post it soon. This will show the slider and basic VU meter code.
-This package for python is more powerful than you think. Get to know it. Seriously, its opening many new doors for me.
-As I keep saying, Mike is the best and I don't actually know him ! I owe him many coffees yet !
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-05T05:28:37Z
-Another screen shot of other projects... ( yes, I have a few )
-
-
-
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-04T22:59:10Z
-*Bravo, extraordinary work sir! I have a couple of quick questions that
-others may find important.*
-
-*Namely, which PySimpleGUI toolkit (Qt or Tk) did you use?*
-
-*and how long did it take you to create the GUI code from start to finish?*
-
-Thanks for the kind words :-)
-
-I used PySimpleGUI only , not the Qt version. I actually finished this late
-2019. I was working on many projects at once so it did take a while
-
-for me to finish, so over 2 months roughly. You have to understand the main
-engine code took me many redesigns before it got to the shown version.
-
-The GUI did change with each mod I did. As you repeat the procedures , you
-do get faster at it I suppose.
-
-Because of the way PySimpleGUI is set out, it allows me to concentrate
-purely on getting the core functionality happening, which is golden to me.
-
-Cheers
-
-
-
-
-On Mon, Apr 5, 2021 at 1:25 AM Thomas Freedman ***@***.***>
-wrote:
-
->
-> - @neovich DMX example -
->
-> Bravo, extraordinary work sir! I have a couple of quick questions that
-> others may find important.
->
-> Namely, which PySimpleGUI toolkit (Qt or Tk) did you use?
->
-> and how long did it take you to create the GUI code from start to finish?
->
-> —
-> You are receiving this because you were mentioned.
-> Reply to this email directly, view it on GitHub
-> ,
-> or unsubscribe
->
-> .
->
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-04T22:05:55Z
-@neovich .... your dedication to your project is really impressive.... and your patience of dealing with PySimpleGUI (ahem,,and me) is commendable.
-
-
-
-
-You've been at this for a good stretch. I'm really happy you've stuck with it and have gotten the results you have!
-
-I hope it's OK that I Tweeted out your screenshot this evening. It's a good thing for the Python community to see. The "tkinter is ugly" mantra I think you've proven to be incorrect.
-
-Thanks for sticking with PySimpleGUI and with your project. It looks fantastic and I hope that it can get even better.
-
-The Dial element that is part of PySimpleGUI+ coming later this year may be a good addition. And the Gauge could be a winner too. Both are creations of @jason990420 . Keep on making stuff! It's good for everyone.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-04T21:46:26Z
-@ThomasFreedman your work is on fire too! 🔥 It's not like you're slacking off.
-
------------
-
-[ThomasFreedman](https://github.com/ThomasFreedman) 2021-04-04T15:25:45Z
-- @neovich DMX example -
-
-Bravo, extraordinary work sir! I have a couple of quick questions that others may find important.
-
-Namely, which PySimpleGUI toolkit (Qt or Tk) did you use?
-How long did it take you to create the GUI code from start to finish?
-As a RaspPi 4 user myself, did you find any noteworthy obstacles you had to overcome on that platform?
-
-Thx for posting this, very impressive!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-04-04T12:37:46Z
-Hi @neovich I'm.... stunned.... STUNNED
-
-
------------
-
-[neovich](https://github.com/neovich) 2021-04-04T08:23:29Z
-Hi Guys,
-
-I thought this might interest people. This is a screenshot of something unique .
-So about this example screen shot . It is taken from my raspbian/ raspberry pi 4 screen . running Buster
-To sum this up , it is a midi to dmx realtime convertor used for intelligent lighting ( DMX )
-My raspberry pi 4 unit has a cheap 20 dollar uDMX / USB interface ( for DMX lighting ).
-and i built a midi (serial input into the raspberry pi ) into it.
- So, I managed to create a real time , live MIDI input interface ( GPIO serial with opto isolator
-etc... ) which accepts the incoming midi serial. Note data to trigger preset DMX scenes.
- The midi serial is coming from a laptop, (audio DAW called reaper )
-This generates all the midi according to the back up songs played lived. the midi essentially
-triggers events in the raspberry pi 4.
-What you are seeing in this screen shot is the page i use to create the presets and save them using python.
-I am using Mikes brilliant PySimpleGUI code. Mike you are the best !!! I swear !
- The code that runs this is quite complex and is specific to my lighting rig I have.
-It uses many import files and dependancies that would be impossible to just run it by itself. ( well it is possible but fiddly )
-In future I intend making this as an OSC version , running nodal PIs for dmx distribution.
-( Anyone else interested in doing this with me . let me know? )
-
-
-
------------
-
-[pgbowers](https://github.com/pgbowers) 2021-03-25T14:59:48Z
-Hi again, my second effort with PSG is an app to monitor the temperature of the CPU on a Raspberry PI 4b:
-
-### Raspi_CPU_Temperature_Monitor
-
-
-A GUI temperature monitor developed with PySimpleGUI.
-
-- This app will monitor the CPU temperature on your Pi and will alert if the temperature exceeds 70 degrees C.
-
-- Temperature is selectable - Fahrenheit/Celsius
-
-- Includes a progress bar to display current temperature
-
-- Includes code to log the readings to a local file if desired.
-
-Check it out here: https://github.com/pgbowers/Raspi_CPU_Temperature_Monitor
-
-
------------
-
-[ThomasFreedman](https://github.com/ThomasFreedman) 2021-03-17T14:40:26Z
-Here's my contribution, my 1st real app using PySimpleGUI. It's a custom query builder to search for content on IPFS:
-
-
-
-
-
- Start to finish 1 month to produce the prototype, including a rework from a single wide multi-pane window to this one with separate windows.
-
- It was truly a pleasure working with PSG. Mike has done some fantastic work bringing this to us to use. Thank you Mike!!!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-03-10T16:42:53Z
-
-
-
-I didn't have much time this morning to spend on this but wanted to give @EntPyle an idea of what's involved.
-
-I kept the code strictly to features available in the plain PySimpleGUI API calls. Did not use the .Widget variable to attempt anything like button highlights on mouseover. I also didn't do the theme switch, but code demonstrating how to do this is in many Demo Programs.
-I've posted it as a demo program:
-https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Simple_Material_Feel.py
-
-It is also on Trinket:
-
-https://pysimplegui.trinket.io/demo-programs#/layouts/centered-and-simple
-
-
-Here it is for your ease of downloading.
-
-```python
-import PySimpleGUI as sg
-
-"""
- Demo - A simple minimal window with a material design feel
-
- Copyright 2021 PySimpleGUI
-"""
-
-def main():
- sg.theme('light grey')
- 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()), sg.B(image_data=T_ON, k='-TOGGLE2-', button_color=sg.theme_background_color(), 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(data=BLANK, k='-GIF-', metadata=0)],
- [sg.T('The end of "my App"')]
- ], element_justification='c', k='-TOP COL-')]]
-
- window = sg.Window('Window Title', layout, no_titlebar=True, grab_anywhere=True)
- show_animation = False
-
- 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)
- elif event == 'Do Something':
- show_animation = True
- window['-GIF-'].metadata = 0
- elif event == 'Upgrade':
- sg.popup_no_titlebar('This is where you would do', 'the updagrade window code', background_color='black', text_color='white')
- # 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=BLANK)
-
-
- window.close()
-
-if __name__ == '__main__':
- BLANK = b'iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB7SURBVHhe7cExAQAAAMKg9U9tDQ8gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADtQAkK8AAT0JXwIAAAAASUVORK5CYII='
- T_OFF = b'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'
- 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()
-```
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-03-09T20:55:32Z
-@ill13 VERY nice work indeed!
-
-Would love to see your code!
-
------------
-
-[EntPyle](https://github.com/EntPyle) 2021-03-09T20:46:19Z
-@ill13 Love that look. Would be great if you could share a gist or repo
-
------------
-
-[ill13](https://github.com/ill13) 2021-03-08T22:03:07Z
-Just some UI testing stuff!
-
-
-All PySimpleGUI, with a bit of recoloring with tkinter (and at least one frame of ms vscode!)
-
------------
-
-[vinniec](https://github.com/vinniec) 2021-03-05T08:50:42Z
-Yes I have tried pydroid3 and it is able to start the second application in tk, but I feel that the solution with termux is more independent.
-One interesting thing would be to understand if the applications you make with pysimpleguiqt can be compiled for android as well, I had read that both pyside and pyqt5 had this possibility.
-if I have well understood what they are for, trinket and repl.it are a good thing, but I would use them more as a demonstration because usually I would prefer that what I use is not network dependent (of course it depends on what I want to do).
-Anyway thanks to you for working on this library, I also saw your music project on youtube and it's really fabulous :)
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-03-05T00:31:16Z
-@vinniec thanks for the screenshots!
-
-Have you tried pydroid3? It's what I recommend for Android. I've been able to use OpenCV with it. Lately, I noticed the rotating the phone no longer causes the program to restart. There was something before that caused this to happen but it seems to be fixed now.
-
-It's crazy that the same 4 line program for displaying a camera in a window works for Android too.
-
-Another option for you on your phone is to use Trinket. Special code was added specifically for Trinket support. Normally Trinket windows lack a titlebar. A few releases back I added a PySimpleGUI custom titlebar automatically on Trinket programs. You can "publish" Trinkets so that they are standalone programs without the IDE being shown. Here's an example:
-https://pysimplegui.trinket.io/sites/togglebuttonwithmetadatastate
-
-Another online possibility is repl.it.
-
-Great to see you're pushing the envelope and trying lots of new ways of doing things. Thanks for taking a moment to share what you're doing.
-
-
------------
-
-[vinniec](https://github.com/vinniec) 2021-03-04T20:44:34Z
-A project from a year ago, a gui to test all the methods of re.
-All flags are present, there is a help for the syntax and you can save all experiments.
-i wanted to add annotations, tests, and also some kind of gamification but in the end i didn't do it.
-
-
-the second one i made a few days ago, it's to estimate when you will finish a series of steps, it works with both pysimplegui and pysimpleguiweb.
-What's special is only the horizontal bar implemented in pysimpleguiweb with a text bar, and the fact that it works on android through termux, just by pressing an icon on the desk.
-Unfortunately on my phone the "termux-api" doesn't work, so I can't push myself to do much more fun stuff, but I hope pysimpleguiweb will be continued, because it allows me to make these simple apps in python without having to compile anything or study how android works.
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-03-02T15:23:56Z
-Love it @pgbowers! Keep making stuff!! Made my day with this post.
-
------------
-
-[pgbowers](https://github.com/pgbowers) 2021-03-02T14:55:14Z
-
-Hi, I have just opened a new repo for my PySimpleGui explorations:
-https://github.com/pgbowers/PySimpleGUI
-Not much but it's a start !
-
-
------------
-
-[frici11](https://github.com/frici11) 2021-02-09T22:59:20Z
-I have just created a repo: https://github.com/frici11/ticker
-(tickerpy is the point itself, tickertest.py is just for testing it)
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2021-02-09T22:39:11Z
-@techtanic and @frici11 ! Thank you for the posts!! LOVE seeing PySimpleGUI windows. Without failure, there's something to learn from every post.
-
-@frici11 - do you have a link to a repo you can share?
-
-@techtanic - I like that you used the multiline.print method. I don't see it used all that often in code other than my own. If you print from a number of different functions, you may like the sg.cprint function. It will enable you to set the output to a particualr multiline, then throughout you entire application, you can call sg.cprint() without having to know the name of the window nor the key of the multilne.
-
------------
-
-[frici11](https://github.com/frici11) 2021-02-09T19:52:20Z
-I made a ticker (news and/or data, e.g. stock exchange) and I hope it can be inserted into any kind of window,
-Attached a short video with first test window embedded the ticker.
-
-https://user-images.githubusercontent.com/78821165/107419822-833afb80-6b18-11eb-977f-d3f9884e8e02.mp4
-
-
-
------------
-
-[techtanic](https://github.com/techtanic) 2021-02-03T16:11:53Z
-# A script/software for automatically enrolling/joining 100% discounted Udemy courses for free. Get Paid Udemy courses for free with just a few clicks.
-
-## Repo: https://github.com/techtanic/Udemy-Course-Grabber
-
-
-
-
-
-@MikeTheWatchGuy how is it.
-
------------
-
-[jason990420](https://github.com/jason990420) 2021-02-02T10:18:38Z
-Binary Viewer
-
-
-
-Source code: https://github.com/jason990420/PySimpleGUI-Projects/blob/master/Binary%20Viewer.pyw
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-12-31T20:08:31Z
-One script to create a table with some dynamic functions, tkinter code reuqired. No full test !
-
-[Source Code](https://github.com/jason990420/PySimpleGUI-Solution/issues/17)
-
-
-
------------
-
-[ingoogni](https://github.com/ingoogni) 2020-12-28T13:30:50Z
-
-
-
------------
-
-[d-flood](https://github.com/d-flood) 2020-12-23T13:20:24Z
-I have been very pleased to rewrite a tkinter app of mine with PySimpleGUIQt. The app loads an XML file and facilitates easy viewing of the XML TEI encoded data and editing of specific attributes and elements in the file. Since I need a dynamic layout, I thought PSG might be off the table. Fortunately, I tried out Mike's suggestion to others to change the visibility parameter to make it _appear_ dynamic. In the GIFs below, the "Variation Units" and "Basetext" frames are behaving just like the dynamic layout I had previously coded with pure tkinter. Previously, I was destroying and repacking text labels. This PSG version simply hides any text that is not currenlty needed. In the "Basetext" frame, each Greek word with an index number under it is a single Text element. Each number in the "Variation Units" frame is also an individual Text element. I can't know how many Text elements will be needed, but programmatically hiding and unhiding them is working very well. I also appreciate how easy it was to add color themes. These are two that I came up with. The first one is "Parchment" and uses the real parchment and ink colors of the ancient manuscripts I study. The second one is my ideal "Dark Mode."
-
-I appreciate PSG because I had really wanted to rewrite this tool so that it was more reliable for my own research, but it takes me (a humanities research with a little self-taught knowledge of Python) too long to build a tkinter layout.
-
-
-
-
-https://github.com/d-flood/apparatus-explorer
-
------------
-
-[mo-han](https://github.com/mo-han) 2020-12-09T00:47:23Z
-a simple yet convenient file rename dialog:
-
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-11-25T21:26:16Z
-Work for multi-Graph now, but more slow, may take couple seconds ... depend on how much the content and how many Graph.
-Scrollbar still work, but not shown here (not automatical).
-
-
-
------------
-
-[jason990420](https://github.com/jason990420) 2020-11-25T12:56:45Z
-One script to add paragraphs with justy text into sg.Graph, the speed to show the result take time longer than normal, maybe one second, for each character processed and printed on Graph. Now setting, only for full a paragraph, are font, color, location and line spacing. View function only.
-
-
-
-
------------
-
-[Kodikuu](https://github.com/Kodikuu) 2020-11-06T18:01:53Z
-
-A small widget showing the currently playing song, powered by WebNowPlaying
-
-Requirements at the top of the gist
-https://gist.github.com/Kodikuu/ead98c53a4dfad4631959e57ce1fad3a
-
-Edit; It occurs to me that i'm using a font most people won't have. This is the font; https://fonts.google.com/specimen/Oxanium
-
------------
-
-[Kodikuu](https://github.com/Kodikuu) 2020-11-06T12:18:24Z
-My completed audio visualiser, and the start of my next project, a system monitor (specific to my PC unfortunately).
-
-
-
-
-The visualiser renders at 200FPS blocking on audio capture, the monitor renders at 100FPS blocking on timeout with time.time()-based 1-second gaps in polling
-
-Edit; I completely eschew things like layouts, window borders, buttons, etc, in favour of just a raw transparent graph layer that I draw to.
-
------------
-
-[PyICoder](https://github.com/PyICoder) 2020-11-06T04:35:52Z
-@PySimpleGUI I don't have a repo for the player, but here is the gist! https://gist.github.com/PyICoder/e5437d6fa7a9d3fea785138a762dacad
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-11-06T03:58:25Z
-wow !! What a month!!!
-
-@d-flood
-I have to configure the PySimpleGUI WIKI soon so that posts like these can be properly layed out. Just the same, it's already an incredible list. Look at all those gorgeous windows!! They're window all user created. I get ideas from you guys/gals.... eveyry single time, so keep posting and I'll keep learning.
-
-The Manuscript Notepad app that wants to store settings across application runs, there's a simple user_settings interface made that will create and manage the contents of the json file for you., Your application doesn't even know it's a JSON file. I'm changing the interface a little, but the current one is quite useful now. There are some great demos on this feature posted.
-
-@PyICoder
-Do you have a ULR to your GitHub?
-
-
-University as the last time I interacted with an NPN calculator. They drove me crazy, but yet were mega powerful.
-
-Are there any values that you want to save between runs? I am thinking about the values shown on the Storage tab. You can use the `user_settings` APIs to save values across runs
-
-----------------------------
-
-Keep the pictures and your wonderful stories coming!
-
------------
-
-[PyICoder](https://github.com/PyICoder) 2020-11-02T07:27:14Z
-My own youtube playlist player, input a playlist url and play the playlist.
-
-
-
------------
-
-[d-flood](https://github.com/d-flood) 2020-11-01T23:49:39Z
-I started to pick up some programming for the first-time during lockdown. My goal was to enhance my research. I made a few straight tkinter apps before discovering PSG. I am very happy with PSG--it has made is possible for a humanities PhD student to create a few handy tools for myself in hours rather than days. This is just a note taking app--I wanted to make something that stored specific tags for each note. I study ancient Greek manuscripts and I have been experimenting with the best way to store and organize my observations. Perhaps this custom solution will suit me best. The app builds Tree element data from a json file. I found it has been helpful to make the DPI awareness load from a settings file that can be edited from the menu bar.
-
-https://github.com/d-flood/Manuscript_Notepad
-
-
-
-
------------
-
-[mainer-hat](https://github.com/mainer-hat) 2020-10-27T15:56:03Z
-Here are screenshots of a reverse polish calculator that uses PySimpleGUI as the front end to a text mode python program. Both the calculator and GUI programs are about 850 lines of code and comments. The combination runs, and looks almost identical, under Linux, MS Windows 10, and MAC OS! In Linux it runs on both intel and arm based systems. The only real problem has been with keyboard input under all of those systems. I have had to create a "key translator" to deal with all of the various key codes returned.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-16T14:23:36Z
-You've sparked my interest in themes and user settings so I created a new design pattern/demo that shows how to easily add a theme button to switch themes on programs. I'm pushing a more modular demo program design now too with the window creation in one function and the event loop in a `main()` function. This will solve some problems people are hitting by not having their code inside of a function.
-
-Thanks for the great inspiration. I'm able to learn something new from every user.
-
------------
-
-[alexBoldea](https://github.com/alexBoldea) 2020-10-16T09:19:12Z
-I love the demo copier, it gives me the idea to add on the duplicate finder a window to scan the extensions of all files and have the user add what they want to remove. Glad you liked the watermark!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-16T03:26:07Z
-Thank you @alexBoldea !
-
-I love the watermark! I like the theme, but I wasn't able to pick it out from the list. I cheated and sampled the background. To verify it, I switched the test harness's theme with Dark Grey 6, which of course matched.
-
-
-
-In some ways your program is like the Demo Programs Organizer/Editor/Launcher I posted this week. IT shows 2 folders side by side and enables you to copy item from the left to the right.
-
-Here's the new demo with the color changed to Dark Grey 6.
-
-
-
-We have a similar overall layout, use vertical separators, manage 2 lists of files, etc.
-
-One next step for me is to add some user settings such as the location for each folder. I'm probably going to sneak theme settings into stuff. I like the watermark so I'll be stealing that, thank you!
-
-Thanks for sharing.
-
-I want to make posts your likes happen as an ongoing thing that'is easy for everyone.
-
------------
-
-[alexBoldea](https://github.com/alexBoldea) 2020-10-15T19:44:28Z
-Hey hey, first app all done.
-Huge "Thank you" to the whole PySimpleGUI team, you guys are awesome!!
-
-
-
-
-
-
-
-
------------
-
-[gregorystorer](https://github.com/gregorystorer) 2020-10-14T07:03:30Z
-
-I needed a way to quickly subscribe to RSS feeds in my RSS reader, some sites no longer provide RSS feeds, and using RSS Bridge, Tiny Tiny RSS and a shell script, I created an easier way to combine the various strings together.
-Then I wanted a GUI instead of having to go to the terminal, went searching and found PySimpleGUI and was quickly able to convert the script and provide a GUI front end.
-At the testing stage, I found I right-clicked in the username box and the context menu didn't pop up as expected. So I did a little (well, a lot) of reading and installed pyperclip, added it to my code and now I can cut, copy and paste using the right click.
-
-It's true I didn't need the right click - but it was great to work it out and pull it all together. I've now got a natty little GUI that I can start up, paste in a username, click Subscribe and have it automatically open a new tab in my web browser and subscribe to the feed.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-12T16:33:55Z
-Thanks for your addition @amantotek.
-
-I see your technique is to directly access the underlying tkinter widget to insert tags. I'm wondering if maybe the color handling code wasn't present when you wrote your code. The `cprint` and other [techniques presented in the Cookbook](https://pysimplegui.readthedocs.io/en/latest/cookbook/#recipe-printing-4a4-using-cprint-function-color-printing-to-print-to-multiline) will do the tag insert for you.
-
-Your example of mixing colored text with plain text would be good to add to the Multiline Demo as I don't think there are any examples of mixing colors on a single line in any of the Demos or the Cookbook. I'll make sure one gets added.
-
-This line:
-
-
-
-can be created using `cprint` with end set to `''` so that the individual calls to `cprint` will result in the output being on a single line. The code to produce a similar line of text in a Multiline could be:
-
-```python
- sg.cprint('Logging ', end='')
- sg.cprint('Off ', colors='green on gray', end='')
- sg.cprint(', Internet ', end='')
- sg.cprint('ON', colors=('red', 'yellow'), end='') # there are 2 formats that can be used for colors (string or tuple)
- sg.cprint(', Alarm ', end='')
- sg.cprint('ON', colors='red on yellow')
-```
-
-It would produce output similar to this:
-
-
-
-The pattern to follow for individual words using cprint is to call cprint for each portion that has a different color. Each of those `cprint` calls sets `end` to `''` so that they all result in a single line of output.
-
-One advantage of using cprint is that the code is portable across the PySimpleGUI ports. The same code runs on PySimpleGUIQt and produces the same results. Literally changed only the import statement and got the same output, except running on Qt.
-
-
-
-
------------
-
-[amantotek](https://github.com/amantotek) 2020-10-12T14:56:34Z
-
-Python source code here: https://github.com/amantotek/python-hal/releases/tag/v06
-Run with: python3 PSGegMultilineColor.py
-Demonstrates PySimpleGUI Multiline getting coloured
- a) using preset colours for certain character strings/words
- b) using tags specifying colours as each line is appended to the Multiline
-
------------
-
-[holypython](https://github.com/holypython) 2020-10-06T15:21:20Z
-@PySimpleGUI Thank you for such a great GUI library, it really did add a new dimension to our work and bridged the gaps. Also thanks for the kind words! 👍
-
-We'll be looking into further synergies with GUI applications such as combining it with Database applications. Seems to be another fantastic match with PySimpleGUI in general.
-
-If you have any suggestions, ideas or synergies that you'd like to explore further with Holypython.com we'd love to hear them any time! 👍
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-10-06T12:40:09Z
-@holypython Nice! And congrats!
-
-Some of my favorite utilities that I've written have similarly simple interfaces. The new readme talks about a "GUI Gap". Your program is a great example. If a typical user wanted to add a watermark, and the problem was solved using Python, the potential users would be perhaps limited due to the command line requirement for usage. But adding a GUI, even a simple one, bridges that gap and opens up the program to anyone.
-
-You've got a ton of interesting tutorials as well. PIL is a great library that works really well with PySimpleGUI. Nice work on the tutorials on ways to integrate the two.
-
------------
-
-[holypython](https://github.com/holypython) 2020-10-05T20:03:05Z
-Hi everyone,
-
-We have just published our first Python Library: [Watermarkd](https://github.com/holypython/Watermarkd). It's in alpha stage and it allows batch watermarking photos with GUI component in addition to watermarking individual photos, something bloggers, entrepreneurs and photographers may find useful. (Watermark spreading algorithm improvement is in the works!)
-
-I'm pleased to share that we have enjoyed building GUI component of our library via PySimpleGui and we appreciate the library, its simplicity, minimalist ways and overall philosophy so very much.
-
-A post about how to use Watermarkd can be found on HolyPython's website: [here ](https://holypython.com/watermarkd/)
-
-We also have a series of posts about how to use PySimpleGui, although it already has a great Readme, to spread it further and share with everyone. Some of these articles can be found: [here](https://holypython.com/how-to-watermark-images-w-python-pil/), [here](https://holypython.com/gui-with-python-checkboxes-and-radio-buttons-pysimplegui-part-ii/) and [here](https://holypython.com/gui-with-python-file-browser-and-input-form-pysimplegui-part-iii/).
-
-
-Screenshot 1 from Watermarkd's **single() function**:
-
-[](https://github.com/holypython/Watermarkd)
-
-Screenshot 2 from Watermarkd's **batch() function**:
-
-[](https://github.com/holypython/Watermarkd)
-
-Our GUI interface is not as fancy as some of the sophisticated designs here. Nevertheless, it came super handy to get the intended job done in a smooth way for our users.
-
-Finally, a big thank you to the creators and contributors of PySimpleGui and everyone who cared to share their beautiful GUI work here.
-
-Happy and productive coding everyone!
-Have a great week,
-
-Holypython Team
-
------------
-
-[aajshaw](https://github.com/aajshaw) 2020-09-28T16:33:39Z
-The link to the bell ringing simulator is [https://github.com/aajshaw/Ensenble](url), in the comments there is some bell ringing terminology but it means something to other bell ringers.
-
-FYI: The heaviest bell in the tower where I ring is 2599lb or 1179Kg if you work in these new-fangled units, it does take a bit of puff to get it going.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-09-27T10:36:55Z
-@PySimpleSQL was a beautiful window! I love the layouts. Clean and you're using button graphic, something rarely done.
-
-The application of PySimpleGUI with databases hasn't been very thoroughly explored. I think one problem is the Table element lack of advanced features like clicking columns to sort. It's far from being an Excel-like experience.
-
-Your story is quite an inspiration. It's these stories that fuel this project. I get as much or more satisfaction at seeing users be successful as the users do.
-
-You've got a great eye for design and layouts, and clearly can write compact code if you managed to get those layouts done in 200 lines of code.
-
-I really want to get a more formal user gallery going soon. There's a massive dump of screenshots in another PySimpleGUI repo. What I want to get set up is a Wiki that has these screenshots and information about the repos along with them. Soon.... it's a high priority to get the docs cleaned up and the gallery done.
-
-Love what you're doing! I'm sure you're likely already doing it, but be sure and put screenshots in your readme. I know users love seeing GUIs in Python as they're a rare find.
-
-Thanks for taking the time to share!! Highly motivational on many fronts.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-09-27T10:26:20Z
-Thanks @aajshaw for the really unusual use of PySimpleGUI! That's most certainly a first. Bonus points for using multi-threading to get the overlapping tones.
-
-The first time I ever saw how bells work was in this video about a song I play on the piano that was played using a clock tower:
-https://youtu.be/6CQgzqYuo04
-
-That must feel pretty amazing to play an instrument that has such massive reach!! TERRIFYING is how I would feel.
-
-If you don't mind sharing your code, please post a link to your Repo. I'm sure others could learn something from what you did. I know I would learn something.
-
------------
-
-[aajshaw](https://github.com/aajshaw) 2020-09-26T13:25:57Z
-At the start of lockdown in the UK I had been learning church bell ringing for about a year and wanted to carry on practising and learning the methods even though all bell ringing was on hold. I started developing an app on Raspberry Pi that would play some of the bells but leave me the option to play others and hopefully get them in the right places. I had all of the components in place and working using Q&A character cell interface and was trying to get a useful GUI going with tkinter when I more or less stumbled across MySimpleGUI.
-
-The ropes have a simple 2 frame animation and a red bell is displayed above each rope as it should be rung, think bouncing ball for sing-along.
-
-On the technical side the images are updated by a thread calling the write_event_value() method of the window, the bells that are rung by the application are controlled by a separate process as is the actual playing of the sounds, data is passed back and forth between these processes using sockets and pipes. The bell sounds are played using mixer from pygame, the allows multiple bells to be playing at the same time.
-
-
-
-
------------
-
-[PySimpleSQL](https://github.com/PySimpleSQL) 2020-08-25T20:27:00Z
-Well, where to start?? I started using PySimpleGUI in the last week or so. I'm absolutely hooked! What a breath of fresh air it's been. I'm fairly new to programming in python and I've always avoided it due to the lack of rapid GUI development tools. PySimpleGUI sucked me right it, and now I'm picking up python at a blistering pace and absolutely loving the language. Thanks for such a simple, straight forward tool!
-
-With that said, in the last week I've been brushing up on Python, learning PySimpleGUI inside and out, learning about Git (I'm a Subversion user from way back, so Git is new to me as well). Add to that researching packaging in python and a host of other things that are still a bit foreign to me. I use MS Access a lot, as well as LibreOffice base (and don't really care for either of them!). Now that I found this incredible PySimpleGUI, I absolutely had to have a good, simple to use database binding but couldn't find one. Your hard work has inspired me to create a companion module, PySimplSQL that makes writing database front-ends amazingly simple along with PySimpleGUI. With the addition of 3 or 4 lines of code, PySimpleSQL allows for full add/edit/delete of records while managing and respecting foreign key relationships in the database.
-
-I have a very long way to go when it comes to getting my docstrings and documentation up to snuff, handling exceptions and general tidying, but it is already at a very usable point and I plan to polish up everything that is lacking. I literally just set up a GitHub for it today (I truly have a lot to learn about this whole ecosystem, but I'm getting there)
-
-Here is a screenshot of a simple example database front-end coded with PySimpleGUI in combination with PySimpleSQL.
-
-This was done in just over 30 lines of code (and could be well under 30 lines of code by removing comments and compacting the layout). 30 lines of code!! (you can grab it from the GitHub here https://github.com/PySimpleSQL/PySimpleSQL (I'll get more/better examples up soon). Try the code- practice adding, removing and editing records. There is a lot going on behind the scenes (managing when to show Add or Delete buttons for example, or automatically populating comboboxes with data from a child table, etc.). But like PySimpleGUI, my main goal for PySimpleSQL is to be very simple to use, yet have enough power and flexibility to handle complex tasks elegantly.
-
-
-Here is a more capable screenshot - This was written in under 200 lines of code using PySimpleGUI in combination with PySimpleSQL (most of which is layout code)
-
-I look forward to learning more and contributing so that others can enjoy fast, easy database GUI interface programming. I just wanted to share the project now that it's starting to take shape. There's plenty of bugs yet and a lot to do, but the early promise is amazing so far!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-08-12T11:03:50Z
-Megacheckers looks awesome! All of the stuff people are making are impressive. This game is really advanced looking. I'm super-impressed. Lots of stuff happening.
-
------------
-
-[moabdali](https://github.com/moabdali) 2020-08-12T05:31:19Z
-
-
-
-MegaCheckers! Essentially a grid of buttons, but dynamic enough to technically be a real game.
-
-GitHub.com/MOABdali/megaCheckers if anyone wants to try it. Please keep in mind it's only intended for windows computers running at 1080p or bigger. Linux seems to be incompatible.
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-08-09T18:44:38Z
-@vohe you've been busy!
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-08T11:11:29Z
-Ready to go,
-I found that putting move than 3000 elements in a sg.treedata() structure works, but as i close that there'll be a huge garbage collection of tkinter under the hood.
-So my directory popup window isn't usable for a 'normal' user directory, especially if the show hidden files option is active.
-I decide to use another method to collect all the files and directorys than [this](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Tree_Element.py) one.
-Today i get it. Take a look:
-
-or check it out yourself:
-https://gitlab.com/iamvohegg/dirbrowserpopup
-Have Fun, stay healthy.
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-05T13:31:05Z
-In addition to get a Folder Browser running , which does not
-- show hidden files,
-- throws errors on Permissions
-- have another thema than the main program itself.
-i wrote my own....
-
-
-
-
-
------------
-
-[dfatka](https://github.com/dfatka) 2020-08-03T22:01:21Z
-My first software [project](https://github.com/dfatka/paletteswapper) that deserves a mention (and that populated my fresh Github account... did I say I'm quite new?).
-The bars for each color have the color of the original image and the other-colored text elements actually update, so it directly shows which color should turn to which. Wanted to enclose them in the Column element, but that can't change its `background_color` with `update` function.
-***
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-08-02T17:28:23Z
-Hi folks,
-here is another one i playing with....
-The TreeElement is not as flexible as i want it. But many things are possible.
-
-
-I got the functionallity i want, but the interface isn't that what i like to get. I test another way, may i think of a a cloud of hierarchical buttons ... lets see.. later
-
------------
-
-[ghost](https://github.com/ghost) 2020-07-05T16:45:42Z
-Thank you,
-first of all i got it as i like (but not so elegant) First of all it works.
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-07-04T23:41:41Z
-You can open an Issue to request enhancements, ask questions, report problems, etc.
-
-There are instructions posted here:
-https://github.com/PySimpleGUI/PySimpleGUI/issues/1646
-
-And you can open a new issue here:
-
-https://github.com/PySimpleGUI/PySimpleGUI/issues/new?assignees=&labels=&template=issue-form---must-fill-in-this-form-with-every-new-issue-submitted.md&title=%5B+Enhancement%2FBug%2FQuestion%5D+My+problem+is...
-
-
-
-
------------
-
-[ghost](https://github.com/ghost) 2020-07-04T21:28:44Z
-> Very nice @vohe ! Thanks for posting it!
-> I like they use of tabs. Great , simple layout. I might have to use that idea for settings sometime. It's never dawned on me before to put them into a tab like that.
-
-Thanks for reply, i don't expect that (so fast) ;-)
-Please can u tell me where i can post a Question/Featurerequest...?
-I mess around with the gettext.py (locale settings)...
-Nice time, stay healthy
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-07-04T19:46:19Z
-Very nice @vohe ! Thanks for posting it!
-I like they use of tabs. Great , simple layout. I might have to use that idea for settings sometime. It's never dawned on me before to put them into a tab like that.
-
------------
-
-[ghost](https://github.com/ghost) 2020-07-04T15:43:31Z
-
-
-A little Programm, that records files form a webside (actually open.spotify) store them as mp3, tag them, sort them into directorys , notify the user when a new song is beginning.
-Just like the old compact cassette recorder but with cutting the songs in single files
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-06-26T14:23:44Z
-I really like this UI! The circular "Add Vocabulary" parts of your window are really nice. Excellent job polishing that portion.
-
-The mainloop not in the main thread is a known problem and there is a suggested workaround along with an explanation for when this will happen.
-
-https://pysimplegui.readthedocs.io/en/latest/#multiple-threads
-
-
-
------------
-
-[kovadarra](https://github.com/kovadarra) 2020-06-17T10:28:51Z
-
-[Pup Quiz](https://github.com/kovadarra/pupquiz) facilitates vocabulary acquisition by quizzing words using spaced repetition principles: words just learned / which user recently got wrong are quizzed more often than those which they've guessed correctly. On the side it shows pictures of puppies that cheer you on. :)
-
-It's not stable yet (I get, what seems at random occasions, repeated messages about main loop not being in main thread), but the visual appearance is about final.
-Edit: [Demo video](https://www.youtube.com/watch?v=l-omUDVW778).
-
------------
-
-[mbilalakmal](https://github.com/mbilalakmal) 2020-06-16T06:47:32Z
-> @mbilalakmal If forgot to comment on your awesome looking GUI and ask for your GitHub address. You mention one exists in your screenshot post, but don't provide the address. I'm sure others would enjoy seeing your work.
->
-> Thank you for taking the time to post screenshots and info!
-
-I have added the repo link in my original comment. I'm glad you liked it.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-06-15T11:05:45Z
-@mbilalakmal If forgot to comment on your awesome looking GUI and ask for your GitHub address. You mention one exists in your screenshot post, but don't provide the address. I'm sure others would enjoy seeing your work.
-
-Thank you for taking the time to post screenshots and info!
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-06-15T10:45:26Z
-WOW!
-
-Another 2 more apps added to the parade of impressive creations. These are so very exciting to see and demonstrate the crazy span of applications PySimpleGUI is being used for. Just look at these last 2 posts:
-1. Iris scanning for security of ATMs
-2. Analyzing meteor spectra
-
-Love them both!
-Thank you for taking the time to post these. Be sure and put screenshots in your GitHub';s readme.
-
-REALLY REALLY want / need to get a user gallery going so these can be properly shown off to everyone.
-
-I'm wowed every time!
-
------------
-
-[martinmeteor](https://github.com/martinmeteor) 2020-06-14T15:36:26Z
-Hello @PySimpleGUI,
-I have made this GUI for analyzing meteor spectra. You can read video files with meteor spectra, transform the images to an orthographic projection, register meteor images and add them, convert to 1-dim spectra and calibrate them and plot the final result. You can look at the code [here](https://github.com/meteorspectroscopy/meteor-spectrum), but I warn you, the code is quite a mess. To see how it works, look [here](https://meteorspectroscopy.org/2020/03/27/meteor-spectra-analysis-new-version/)
-the theory behind it is found at https://meteorspectroscopy.org/
-Setup:
-
-add rows:
-
-Calibration:
-
-plotting:
-
-final result:
-
-I hope, somebody else may find this useful.
-
-
------------
-
-[sharathraj-tech](https://github.com/sharathraj-tech) 2020-06-08T03:38:01Z
-This project was developed as a prototype on ATM Transactions. Users need to Upload their Iris Image and later while they withdraw amount they need to upload their iris image again. After algorithm processes the iris data. The amount will be successfully withdrawn.
-
-**This is the Customer Dashboard**
-
-
-**Iris Image Upload Window**
-
-
-**While the user selects the Iris Image**
-
-
-**Amount Withdrawal Window**
-
-
-**After Successful Iris Verification**
-
-
-It takes some time to complete the algorithm process. Anyhow i'm feeling good and comfortable at using @PySimpleGUI .
-Thank You For such a wonderful Package.
-Hope to get more components Soon.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-06-07T10:48:55Z
-Wow! Just WOW to the posts over the past few weeks from users.
-
-I'm so impressed by what people are making! Thrilled for everyone!
-
-Thank you SO much for taking time to share. I'm hoping to have a "Gallery of User Creations" happening soon. There are 712 projects listed at the moment on GitHub alone that use PySimpleGUI. Have no idea how many that are not listed on GitHub.
-
-Thank you to @thesoftbincoder @Ruakuu @Zain-Bin-Arshad @ChristanReizner for posting!!
-
-Fantastic users here!
-
------------
-
-[mbilalakmal](https://github.com/mbilalakmal) 2020-06-07T02:07:48Z
-**Hope you are having a good day @PySimpleGUI**
-I made this for a course assignment about genetic algorithms and their performance.
-I have published this on my [GitHub](https://github.com/mbilalakmal/SimpleGA) if someone is curious.
-
-
-
-
-
-
-Basically you specify all the parameters and after running the algorithm multiple times it displays the performance graph in a new window.
-
-
------------
-
-[ChristianReizner](https://github.com/ChristianReizner) 2020-06-06T15:50:19Z
-Hello to everyone,
-
-i am not really a software developer, so i am all the more grateful for any simplification. My partner sometimes gives astrological consultations and the online platform she uses limited her database to 100 entries. Since this database gets very full very quickly, I promised to write a small program that will pull her client data from the platform into a local database (sqlite3) for her. This escalated quickly. Now it has become a tool for the whole consulting business and it grows with her demands.
-
-
-(The texts are in german, but I think the program is still understandable)
-
-
-(A typical database with ADD, DELETE, EDIT, SHOW)
-
-
-(Multiline element as an output for obtaining data from the astrology platform)
-
-
-(The astrocharts. I used the PySimpleGUIQt version so that I could use antialiasing for the QGraphicsView aka .graph to avoid eye cancer. For the display I had to use the QGraphicScene from PySide2 via .graph().widget (headache). The Pixmap transformation still looks pixelated.)
-
-
-(She can have a consultation page printed. The notes will be generated depending on the client's planet positions at birth.)
-
-
-(Finally, it can search for clients with the same planet constellations to make comparisons.)
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-05-31T17:38:58Z
-@Zain-Bin-Arshad I am genuinely thrilled at your success! Thank you for taking the time to not only share your creation but for providing some extremely helpful feedback. 👍
-
------------
-
-[Zain-Bin-Arshad](https://github.com/Zain-Bin-Arshad) 2020-05-31T07:43:59Z
-Hello @PySimpleGUI, I have created a PDF-Viewer using THE AWESOME PSG.
-
-
-
-The GUI is 100% ready, there are some things that I am working on right now like:
-
-1. Convert application language into English
-2. Fix bugs for searching feature
-3. Add zooming etc
-4. Code is mess (trust me I know), I will be beautifying it very soon
-
-You can find the project [here](https://github.com/Zain-Bin-Arshad/PDF-Viewer)
-
-**How long did it take to make this?**
-I think if we talk about GUI, one the first 2 days I made almost 60% of the GUI. The CookBook and extensive documentation was key for my success.
-
-**What was the most and least helpful?**
-I didn't understand this question, but I will answer to the best of my knowledge. The most helpful thing was the **Simplicity** of PSG. Everything is very simple and pythonic to develop.
-As a python programmer, we are inclined to find simple and elegant solutions, its the core nature of python language.
-
-> Simple is better than complex
-
-The least helpful part would be that often now and then, we want to implement a feature, that is not present in PSG (It is in development phase we understand). So, we have to find a way around or completely leave that feature because of this limitation. But, again this limitation is not going to keep us from using PSG.
-
-**What was your experience like?**
-My experience was great, believe me I have left working on it because I couldn't find my way into Tkinter, pyQT etc. I just don't like them (sorry). But, as soon as I came across PSG, I knew that I am going to make use of it, its just what I want **Simple and Pythonic**
-
-Thanks @PySimpleGUI, this is for you
-
-
-
-
------------
-
-[Ruakuu](https://github.com/Ruakuu) 2020-04-30T09:07:13Z
-
-
-I love this framework so much, it allowed me to start programming GUI very fast. I'm building an image managing system much like DigiKam but more focused on the image tagging, this will specialize on metadata handling and image clasification.
-
-What I also wanted to share is that, in the need of a treeview with checkboxes and seeing that it would be very complicated to code it from outside, decided to implement the functionality directly in PySimpleGUI so I now have a native Tree element with working checkboxes if you guys are interested.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-03-27T17:36:18Z
-@thesoftbincoder
-
-### Thank you so much for sharing!
-
-It looks like more than "a great start". There are a lot of people that would love to have GUIs that look this nice.
-
-I don't recall you posting any Issues here looking for help. I hope that means you didn't run into too many problems. I see frames, images, aligned elements. You've spent time thinking about your design and it shows.
-
-I'm really happy you have had some success using PySimpleGUI! Made my day 🙂 at a time where good news is so nice to hear.
-
-When you think you're ready, post it on Reddit too. People love to see projects, success stories, especially when there's something visual.
-
-Thank you for taking the time to post something.
-
------------
-
-[sharathraj-tech](https://github.com/sharathraj-tech) 2020-03-27T17:06:56Z
-
-
-
-
-
-It was a great start anyhow! Loved using PySimpleGUI. Wish to learn more on other controls. Made a great help for my ML Project
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2020-01-03T00:53:45Z
-WOW @SuperMechaDeathChrist another amazing thing! That's incredible! Especially since it's the plain PySimpleGUI, not Qt.
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2020-01-02T21:30:42Z
-This is a PySimpleGUI-tk app with an embedded internet browser based on cefpython. Needs a little tkinter tweaking for entry elements to work normally, but it works surprisingly well and in less than 100 lines of code. I guess now the sky is the limit if you combine it with flask/django or anything web-based.
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-12-06T16:10:09Z
-Recently posted screenshots by @JitsuP who has only been using Python for 3 months (astounding). Even more impressive is that this multi-windowed GUI took only 3 days in total to write. WOW!
-
-It's even multithreaded....
-
-
-
-
-
-
-
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-11-22T15:39:35Z
-## A serial oscilloscope
-
-I had forgotten about this project, but stumbled back onto it today. I think a screenshot is certainly in order for this one. VERY nice.
-
-Project's GitHub https://github.com/dilawar/SerialScope
-
-
-
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-10-31T02:23:51Z
-This is a "splash screen"-like function using PySimpleGUI (tkinter, Windows). It basically is just a program with an animated picture and a cancel option that interrupts the execution of the whole program. It supports transparency and fast load of the animated picture. You can adjust the speed of the animation, the wait time, and other options.
-
-
-You can call this function at the start of your program to emulate a splash screen.
-link to code: https://github.com/SuperMechaDeathChrist/Widgets/blob/master/Splash.py
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-10-02T23:31:59Z
-I just assumed you guys had done your communicating. This isn't a forum, it's a place to post screenshots. That's why the comments are being deleted.
-
------------
-
-[viniciushenr](https://github.com/viniciushenr) 2019-10-02T23:13:24Z
-@killyone I don't understand why was excluded my comment, but my email are in my profile, so if you still would wish send me the code, I thank you.
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-08-27T09:54:13Z
-@PySimpleGUI I sent you the code for the video player, let me know if you can get it to run
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-08-26T19:06:38Z
-I understand if you don't want to share your code publicly until it's in the state you want it to be in. You can send it privately if you want. I don't need the entire program. I'm just interested in your layout and your event loop / drawing calls. It doesn't need to run. You don't need, of course, to include any Keys that you may need to get access to YouTube APIs.
-
-I'm working on another project that could really benefit from this is why I'm asking. If you feel more comfortable, email just those bits to sourcecode@PySimpleGUI.org
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-08-26T13:33:07Z
-@killyone Have you released your software anywhere? The screenshot you posted is unique among PSG applications I've seen. It would be awesome to see your code & graphic assets. There continues to be questions, over and over, about "How can I make tkinter not look ugly?" (-sigh-)
-
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-08-25T23:56:16Z
-@PySimpleGUI I get the direct link to a video from a normal youtube link using pafy (I made another program to scrap my playlist that had 400+ videos). The video is being played using the python bindings for vlc (you also need to install vlc but that can be done in any platform). With that, you can create and control a video window that you can also embed into a tkinter canvas element. The rest is just the classic gui scheme. It works very well, although it's still a little messy, I can share the code when it's cleaner.
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-08-25T22:32:31Z
-Uhhhh.,..... no.... this isn't a cruel joke?
-
-How are you getting sound?
-
-No one's posted anything like it. I'm dying to see the code!! WOW. This is a first as far as I know.
-
------------
-
-[SuperMechaDeathChrist](https://github.com/SuperMechaDeathChrist) 2019-08-25T22:30:11Z
-I'm not sure if someone already tried something similar, but here is a mini video player that plays my favorite music videos from youtube.
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-08-24T03:27:25Z
-Ok, now it's getting there. Here I'm using PSGWeb for a powershell management concept (Everything is procedural - No hardcoding any of the data):
-
-
-
-
------------
-
-[PySimpleGUI](https://github.com/PySimpleGUI) 2019-08-23T23:32:40Z
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-08-11T09:52:53Z
-Here are a few that can be found on this download manager's GitHub site:
-https://github.com/Aboghazala/Hanash
-
-
-
-
-
-
------------
-
-[IsaacLance](https://github.com/IsaacLance) 2019-08-10T03:43:47Z
-I used PySimpleGUI to display information over my automated Twitch stream. (Twitch Plays Chess) (https://www.twitch.tv/chess_magnet)
-
-
-This is just the GUI shapes on their own with no text/nothing happening.
-
-
-
-Here it is on my screen,
-
-
-
-And here it is on stream after further manipulation by OBS ,automated by janky Python-OBS file saving stuff.
-
-
-There are some features that aren't represented due to taking the screenshots when I'm the only player. If there were active players when I took the screenshot, the bottom right would be filled with chats from viewers instead of an automated message. There can be up to 10 bars on the left that represent the percentage of votes for a given move. The length of the bar and shade of blue are determined by the % of votes. The green bar recedes as an internal timer counts down, I am impressed with how smooth it can move! I did it by hand with a graph instead of a progress bar because I don't like the aesthetic of the edges of the progress bar and I couldn't get rid of them.
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-08-07T23:34:58Z
-This one is from @SuperMechaDeathChrist. Hoping to get more soon!
-
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-06-27T02:43:56Z
-@killyone Do you have any more screen shots you can share? You app was looking REALLY good and I Can't wait to see how it turns out, or even what it look like along the way. I'm SURE lots of us will find inspiration in what you did. I know I have a lot of ideas now about layout, font sizes, etc. You've made a nice looking "pattern" of sorts.
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-06-26T19:38:03Z
-@killyone if you find places in the documentation http://www.PySimpleGUI.org that is lacking, please post it as an Issue. As you may have read over the past few weeks, there's is a lot of effort being spent on the documentation.
-
-
------------
-
-[killyone](https://github.com/killyone) 2019-06-20T04:15:02Z
-
-
-
-Hello, it's my first exercise with PySimpleGUI and I'm very happy with the results, if you get creative you can get good results, the only thing I had problems with was the transparency of the images, I will continue studying, I was with Kivy because of his ability to export to mobile systems, I really like the approach of this library, I thank the creators, and it would be really great to have something like this for mobile, in the end I could solve my doubts by reviewing the code of the library, since in the documentation there is still no information of some things in specific, greetings!
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-03-26T14:44:22Z
-Yea! It was an amazing feeling when I walked into the office last week and didn't know that a new build had dropped. I started chatting with my coworker and he said that he ran it right when it dropped that morning and it all passed; logs, sql data, and report was made. I was like, oh cool. But then it hit me that he just clicked a button and in 11 minutes it was done. Usually it's a whole process across two weeks where the whole team allocates a full schedule to test it. That's when we fully felt the magnitude of what it was :D Amazing.
-
-Ironically, it was the testers who used the app to build the scripts. Which may get a bit awkward... But this just means they can focus on more complex manual testing and not the mundane repetitions.
-
-Also I'm in talks right now actually about what you're saying, thanks for the advice.
-And I think you're right about using python packages :)
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-03-26T14:34:35Z
-Woowww! (again). You're saving the company a FORTUNE and you're also stepping the quality level up a LOT. If your 2 weeks turned into 11 minutes, then holy shit, you've not only done the work, but now you've got a team available for 2 full weeks. OMG, companies would kill for that kind of return.
-
-Your boss better step up at bonus time, or before. I would consider broaching the subject in some manner with him / the company. "You can't get when you don't ask for" has served me very well in business. And you sure as hell deserve something special for what you've done.
-
-I don't think you're wrapping anything. You've built a full application that uses some available Python packages. That's just plain ole Python (done wisely to take the advantage of other people's prior work).
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-03-26T14:19:29Z
-Haha it has gone beyond original scope definitely. Now I think of it as an application, not just a tool or script.
-
-Essentially it's a wrapper around Selenium and PyAutoGUI. But I've added lots of custom functionality and flexibility for the purpose of cutting out a lot of flak, so a user doesn't need to know how to code or understand loops, functions, variables, and such but still build maintainable code. All of that complex logic is built into the backend so they just need to pass basic info to it from the scripts they make.
-
-Our team has used it and actually just finished the first project it's using. The team had zero coding knowledge and built out thousands of lines of automation code with it and we now save what once took two physical weeks of testing into 11 minutes. We've already saved a month this year across two builds of what we develop there. The next project is for a larger project which will save even more time overall through the year. I'm estimating once a year we'll save 2.5 months of time we used to pay people to test, and potentially 3.5 months if there happens to be more builds than usual. That's a lot of dough. And the fact that you don't need an automation engineer to understand the code, that's a bonus for maintaining it going forward.
-
-It's browser agnostic, customizable, flexible, and gives full control over the process. Which was important to me to have something custom that we understand and can fully control as opposed to using a closed source automation tool, or complex scripts and requirements using an existing framework or an app that we have no idea what is going on in the backend. Basically just abstracted the complexity into a custom test framework and put it in the background so creating, modifying, and understanding the scripts is simple. Also this way if there are issues or changes to be made they can simply be made.
-
-There have been some development issues due to time restraints that I'm not happy about but will get to them later. Like I have one global variable that really pisses me off! They became a bit impatient so I had to cut a few corners and now I'm like ahhhh whyyy. Also there is a hardcoded variable from the main loop I did to save time and a few arguments I threw in that are too reliant on the main loop for my taste :P It works fine I just don't like how I bandaged it up and left it - Might make future changes more difficult and less flexible.
-
-But I'm not sure why people think that about PSG at all, but I suppose it's in how you use anything really it's up to how you implement it. My main loop is ~1900 lines, total app is ~3600. There is no reason PSG can't be used in higher capacity as it's up to the dev to build logic around what you've provided that is very easy to use.
-
-Thanks again for the kind words!
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-03-26T13:49:46Z
-It's beautiful stuff you've done.
-
-This sounds like the project went WAY WAY WAY beyond your initial vision for it. You've continued to iterate and make it better every time I see it.
-
-Graphs?! Show some windows doing their thing, filled in too!
-
-You may want to keep PySimpleGUI out of the title of a Reddit post however. But feel free to mention in your post itself. Tired of the comments claiming PySimpleGUI is only good for prototyping, nothing complex and be built with it. It'll be nice to have a great looking project to link to.
-
-But beyond the GUI advertising that I'm requesting, there is the seriously cool nature of the thing you've built. I dunno, but I get a sense this is an impressive product you've created.
-
-If this guy's software is getting up-votes....
-https://www.reddit.com/r/Python/comments/b5nmkx/i_made_a_gui_for_youtubedl_but_its_just_entry/
-
-Then sure as hell your's will!
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-03-26T13:30:45Z
-Thanks! I'll put up a post here this week.
-
-There are also a few other windows used from the main window, which is for customizing reports, viewing graphs, and viewing license. The build window also has that sl button which converts the window to include some extended optional functionality. It stands for sideload which loads a module that is not packaged in the build so you can modify functions and reimport at runtime. So in total there are 8 windows that work perfectly!
-
-Using PSG has been really fluid. It's been a lot of fun, thanks for continuing support!
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2019-03-25T19:53:34Z
-Woooooowwwwwww!
-
-This is Reddit post territory for sure. OMG, this looks amazing.
-
-People often post asking "is it possible to make tkinker look good". Stuff like that. You can also plug PSG of course ;-)
-
-This was beautifully done. Nice job. I'm sure your users love it.
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2019-03-25T15:44:50Z
-Just an update. PSG rules.
-
-
-
-
-
-
-
------------
-
-[btnpushnmunky](https://github.com/btnpushnmunky) 2018-12-15T00:26:31Z
-Nope. Just rows and set sizes for the elements.
-
-And thank you. :-)
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-12-14T23:09:55Z
-Did you use Columns to lay out your window?
-
-It looks great.
-
------------
-
-[btnpushnmunky](https://github.com/btnpushnmunky) 2018-12-14T16:50:36Z
-Box calculator for print jobs:
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-28T15:56:18Z
-Open a new issue and post it.
-
-https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/new
-
-
------------
-
-[kennard42](https://github.com/kennard42) 2018-11-28T15:54:53Z
->
->
-> Very cool.. I like the Make More Readable... it does that well!
-
-Thanks, I am confronted with a challenge though and I don't know where to ask my question. I want some semi-complicated rules to apply to the input numbers. I felt I was on the right path until I added the keybinding so that I could capture pageup and down to advance the records. Where would I pose this question in detail?
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-28T15:48:19Z
-Very cool.. I like the Make More Readable... it does that well!
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-28T15:43:40Z
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-24T05:46:53Z
-Just finalized and released EHX tool officially. Thanks again for a great tool to quickly build GUI's. It definitely played a part in completing this project with it's flexibility and your active support.
-
-Again here is a screenshot and a few from the larger tool that this derives from this which is near completion. I'm looking forward to using PSG again on my next project :D
-
-
-
-
-
-
-
-
-
-
-
-
-
-Working on graph visualizations... But I love the heat map and need to get it more condensed.
-
-Also very cool MIT license icons used: https://octicons.github.com/
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-20T22:08:30Z
-I typically named tkinter variables consistently. For the elements', their base widget object starts with TK. For example, the slider's tkinter widget is a Scale.
-
-The scale object that's used for a slider is named element.TKScale.
-Spinbox is TKSpinBox.
-Radiobutton is TKRadio.
- Checkbox is TKCheckbutton.
-etc
-
-You can easily "go around" the PySimpleGUI SDK to access a variety of features. There was an officially sanctioned one that I recently gave to someone that I have now forgotten.
-
------------
-
-[john144](https://github.com/john144) 2018-11-20T20:12:20Z
-I needed a log window that supported multi-colored text. I was using the TKinter Text widget, but that required me to write my entire UI using TKinter, even though I wanted to use PySimpleGUI. I tried subclassing the PySimpleGUI Multiline element and adding a couple of methods that access the `TKText` attribute. Taking the program I wrote using TKinter, I rewrote my entire GUI using PySimpleGUI and this subclass. It cut the lines of GUI code by 50%. The only thing I lost was the ability to resize the window and the widgets it contained. The learning value is that if a PySimpleGUI doesn't do exactly what you want, you can still sub-class it and add your own functionality, without disturbing the base code.
-
-Here is a quick sample screen shot using this subclassed Multiline element. If there is any interest, I can upload a small demo program consisting of about 80 lines of code. I figured this might be useful where you are logging test cases and want to highlight critical results.
-
-I am also including a screen shot of my SynchDir program, which synchronizes directories (now with PySimpleGui, not TKinter). I use different colors to indicate copy, move, delete, etc. What's unique is the window consists of two frames. I defined the frames separately, then combined them into one layout. I also found out that adding hotkeys is a snap using `return_keyboard_events=True`. I saved about 5 lines of code over using TKinter.
-
-
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-18T16:55:15Z
-
-
-Another GUI found on GitHub
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-18T16:54:32Z
-
-
-
-Ran into this one while cruising GitHub. I'm seeing some nice looking GUIs!
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-16T03:08:43Z
-Here are some new screenshots of a major UI overhaul in making a test framework on top of Selenium:
-
-
-
-Config:
-
-
-
-Build:
-
-
-Yes, that is a temp password for a local DB - No worries.
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-12T18:52:03Z
-Haha thanks. Yea they all expect mobile stuff now and if it doesn't look clean and obvious no one will use it :/ It does help to simplify your app though when thinking about it from their perspective!
-
-I took what was 11 tabs and a big window, into 3 buttons on a smaller window. Phew.
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-12T18:05:10Z
-Woooowww! Are those "real" screenshots?? You did images on your buttons and made them really big. They like a mobile interface. Very nice. All of this will translate over to Qt easily should you ever go that way. Even button images should work. The downside is all that sizing you did will have to be redone.
-
-I really like the looks of theses.
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-12T17:58:27Z
-Completely revamping my GUI as when I gave it to users it was way too convoluted. Here are a few shots of an extremely simplified main menu, and pop out windows for those options. I'm learning a lot about how to design for users now, which actually simplifies the application overall and makes less work lol:
-
-
-
-Also, spun off functionality from that tool to make htis GUI as well. Super easy with PSG :)
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-11-04T03:06:11Z
-Ah, yes, double clicking. Let me look at how to make that happen. It'll be another version of select submits.
-
-DONE... added... if you set the parameter `bind_return_key` to True then it will return an event for both the return key and double-clicks, just like listbox does.
-
-
-See issue which was opened as an enhancement request...
-https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/654
-
-
------------
-
-[john144](https://github.com/john144) 2018-11-04T03:03:06Z
-A program I wrote in Python using PSG. I use the old-fashioned `descript.ion` files from the MSDOS days. (Old, but I don't know any better alternative for Windows.) I use comments to label my code, audio, and video files, but need a way to search for them by comment. This is my home-grown solution.
-
-The back end of the screenshot of the program you see is a SQLite database that maps files to their respective descriptions. The database was built by another Python program. (There are three separate Python programs, and I need to integrate them.) The front end to this query program is PySimpleGUI using the latest version of the Table element to display the result set. The PySimpleGUI code is only 70 lines in a 118-line program, including comments and blank lines. You can customize the result set by choosing different databases, and customizing your search using custom queries using SQL or full text search. You can further filter your results using the filter pattern that I picked up from another of Mike's examples. You are looking here at part of my Projects/Python folder, filtered by the keyword 'simple'.
-
-You can select a folder or a file and click on `Open`. Opening a folder opens the folder in Windows File Explorer. Opening a file opens the file in its default app. I wish there was the ability in PySimpleGUI to capture the double-click event in the Table element and open the file, like you can in Windows File Explorer, or in the PySimpleGUI List element. I actually wrote three versions of this program, trying to get as much functionality of a Win32 ListBox as I could:
-
-1. Using PySimpleGUI and the List element
-2. Using PySimpleGui and the Table element
-3. Using TKinter and the Treeview element used as a multi-column list
-
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-11-04T00:22:20Z
-Spun off some functionality from my larger testing tool for easy use of specific functionality still using PSG :)
-
-
-
-
------------
-
-[AltoRetrato](https://github.com/AltoRetrato) 2018-10-29T17:45:47Z
-I didn't see any tree element screenshot, so here's a sample from a program I'm writing:
-
-
-
-
-
------------
-
-[iris-chang](https://github.com/iris-chang) 2018-10-24T07:04:44Z
-The most interesting thing I've got in my program:
-
-
-Basically a fancied up version of listBox where the user can choose multiple options. Saw it in other programs and wanted one for my own. It also has an advantage over listbox (I think) because when I had a lot of fields on a form, the regular listbox doesn't keep track of the selected values when the focus moves away. So instead, I use this like a popup to keep track of what was selected and allow modifications.
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-10-04T01:55:57Z
-That is pretty cool. Will be looking into it.
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-10-03T21:54:34Z
-@eagleEggs Just thought of a cool feature for you to use. Maybe your buttons already take care of this, but could work out nicely.... that feature is Menus. And in particular the tear-off menus. They essentially become floating toolbars without icons and instead use text.
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-10-02T20:18:39Z
-Here's another screenshot with a new theme I'm still working on...
-
-
-
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-09-30T22:01:09Z
-Haha no problem and thanks for the tool itself. About the icon.... don't look too hard at these screenshots!
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-09-30T21:51:14Z
-Thank you! This is SO helpful to us all. I've already picked up several ideas from what you've done and I'm sure others will too. And thank you for downloading and using the PSG logo 👍 It's better than the default tkinter logo in my opinion.
-This kind of post is greatly appreciated to say the least!
-
------------
-
-[eagleEggs](https://github.com/eagleEggs) 2018-09-30T21:37:08Z
-Hey! Here are some screenshots of a web automation tool overlay I'm building with with PSG. It is letting me quickly implement without clunky nuance requirements, and provide nice functionality that I really wasn't planning on doing before finding PSG. Thanks!
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-[topanga - Test Anatomy](https://github.com/eagleEggs/topanga)
-
-PSG is awesome!
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-09-16T21:26:51Z
-I'm finding some cool examples being posted on GitHub.... if user's won't post them, I sure will! What I'm finding are surprising. The calculator example isn't just a calculator, the author created a new button class based on PySimpleGUI.ReadFormButton
-
-
-
-
-
------------
-
-[MikeTheWatchGuy](https://github.com/MikeTheWatchGuy) 2018-09-02T17:23:57Z
-OK, so this didn't catch on the way I had hoped....
-
------------
-
diff --git a/docs/call reference.md b/docs/call reference.md
index e909d3e7..898e542a 100644
--- a/docs/call reference.md
+++ b/docs/call reference.md
@@ -25,9 +25,9 @@
apply coupon for discount:
- 522B20BF5EF123C4AB30.
+ 4FD91A459D56B1029FF8
-
\ No newline at end of file
diff --git a/mkdocs_ivory/search.html b/mkdocs_ivory/search.html
new file mode 100644
index 00000000..08fddf22
--- /dev/null
+++ b/mkdocs_ivory/search.html
@@ -0,0 +1,16 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+
Search Results
+
+
+
+
+ Searching...
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/mkdocs_ivory/searchbox.html b/mkdocs_ivory/searchbox.html
new file mode 100644
index 00000000..04d935d6
--- /dev/null
+++ b/mkdocs_ivory/searchbox.html
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/mkdocs_ivory/toc.html b/mkdocs_ivory/toc.html
new file mode 100644
index 00000000..fedfec3f
--- /dev/null
+++ b/mkdocs_ivory/toc.html
@@ -0,0 +1,7 @@
+{%- for toc_item in page.toc %}
+{%- if toc_item.children %}
+{%- for toc_item in toc_item.children %}
+
@@ -73,8 +73,6 @@ PySimpleGUI needs your support. If you find PySimpleGUI useful, please consider
-
-
# What Is PySimpleGUI ❓
PySimpleGUI is a Python package that enables Python programmers of all levels to create GUIs. You specify your GUI window using a "layout" which contains widgets (they're called "Elements" in PySimpleGUI). Your layout is used to create a window using one of the 4 supported frameworks to display and interact with your window. Supported frameworks include tkinter, Qt, WxPython, or Remi. The term "wrapper" is sometimes used for these kinds of packages.
diff --git a/readme_creator/markdown input files/1_HEADER_top_part.md b/readme_creator/markdown input files/1_HEADER_top_part.md
index f1232855..79f84dee 100644
--- a/readme_creator/markdown input files/1_HEADER_top_part.md
+++ b/readme_creator/markdown input files/1_HEADER_top_part.md
@@ -27,8 +27,8 @@ HOW DO I INSERT IMAGES ???
-
-
User Interfaces for HumansTM
+
+
Python GUIs for Humans
@@ -52,9 +52,9 @@ HOW DO I INSERT IMAGES ???
apply coupon for discount:
- 522B20BF5EF123C4AB30
+ 4FD91A459D56B1029FF8
-
+
click here to visit course page
@@ -63,6 +63,22 @@ HOW DO I INSERT IMAGES ???
+
+
+
+
+
## PyPI Statistics & Versions
@@ -96,7 +112,7 @@ HOW DO I INSERT IMAGES ???
# PySimpleGUI User's Manual
-## User Interfaces for Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces
+## Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces
## The Call Reference Section Moved to here
diff --git a/readme_creator/markdown input files/2_readme.md b/readme_creator/markdown input files/2_readme.md
index bdd7cebe..a204167c 100644
--- a/readme_creator/markdown input files/2_readme.md
+++ b/readme_creator/markdown input files/2_readme.md
@@ -1340,14 +1340,13 @@ You can learn more about these async / non-blocking windows toward the end of th
In Dec 2019 the function `change_look_and_feel` was replaced by `theme`. The concept remains the same, but a new group of function calls makes it a lot easier to manage colors and other settings.
-By default the PySimpleGUI color theme is now `Dark Blue 3`. Gone are the "system default" gray colors. If you want your window to be devoid of all colors so that the system chooses the colors (gray) for you, then set the theme to 'gray gray gray'. This tells PySimpleGUI that you're a boring person.... no no no... I'm **just kidding!**.... it just means you want PySimpleGUI to not set any colors so that the default colors provided by the OS/tkinter will be used. It's a memorable theme name. There are several with "default" in the name and it got confusing which was the full-on-add-no-color name, so 'gray gray gray' was added to make it easy to recall.
+By default the PySimpleGUI color theme is now `Dark Blue 3`. Gone are the "system default" gray colors. If you want your window to be devoid of all colors so that the system chooses the colors (gray) for you, then set the theme to 'SystemDefault1' or `Default1`.
-There are 154 themes available. You can preview these themes by calling `theme_previewer()` which will create a LARGE window displaying all of the color themes available.
+There are 130 themes available. You can preview these themes by calling `theme_previewer()` which will create a LARGE window displaying all of the color themes available.
-You can see the current available themes by calling `sg.theme_previewer()`. It creates a window that looked like this in June 2022:
-
-
+As of this writing, these are your available themes.
+
## Default is `Dark Blue 3`
@@ -1389,33 +1388,19 @@ The basic theme function call is `theme(theme_name)`. This sets the theme. Cal
If you want to get or modify any of the theme settings, you can do it with these functions that you will find detailed information about in the function definitions section at the bottom of the document. Each will return the current value if no parameter is used.
-You'll find a detailed list of the theme calls in the SDK Call Reference in this section:
-
-https://pysimplegui.readthedocs.io/en/latest/call%20reference/#themes
-
```python
-theme
-theme_add_new
theme_background_color
theme_border_width
theme_button_color
-theme_button_color_background
-theme_button_color_text
theme_element_background_color
theme_element_text_color
-theme_global
theme_input_background_color
theme_input_text_color
-theme_list
-theme_previewer
-theme_previewer_swatches
theme_progress_bar_border_width
theme_progress_bar_color
theme_slider_border_width
theme_slider_color
theme_text_color
-theme_text_element_background_color
-theme_use_custom_titlebar
```
These will help you get a list of available choices.
@@ -2058,6 +2043,20 @@ Your Window's layout is composed of lists of Elements. In addition to elements,
+
+
+- Text
+- Single Line Input
+- Buttons including these types:
+ - File Browse
+ - Folder Browse
+ - Calendar picker
+ - Date Chooser
+ - Read window
+ - Close window ("Button" & all shortcut buttons)
+ - Realtime
+
+
## Keys
***Keys are a super important concept to understand in PySimpleGUI.***
@@ -3871,20 +3870,20 @@ This is a blocking call so expect it to take a few seconds if you're fading the
# Global Settings
-There are multiple ways to customize PySimpleGUI. You can think of customizations as being done in a hierarchical manner
+There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
+
+**Mac Users** - You can't call `ChangeLookAndFeel` but you can call `SetOptions` with any sets of values you want. Nothing is being blocked or filtered.
+
+**These settings apply to all windows that are created in the future.**
+
+ `SetOptions`. The options and Element options will take precedence over these settings. Settings can be thought of as levels of settings with the window-level being the highest and the Element-level the lowest. Thus the levels are:
- Global
- Window
- Element
-The function `set_options` is used to change settings that will apply globally. If it's a setting that applies to Windows, then that setting will apply not only to Windows that you create, but also to popup Windows.
-
Each lower level overrides the settings of the higher level. Once settings have been changed, they remain changed for the duration of the program (unless changed again).
-After Global settings are settings made at Window level. These settings apply to a single `Window`. Fonts are a good example of a Windows-level setting. All elements within that `Window` will use the specified font.
-
-The lowest level of setting is the element-level. It will modify one particular element's setting. Again using font as an example, if you set the `font` parameter on a `Text` element, then only that specific `Text` element will use the specified font.
-
# Persistent windows (Window stays open after button click)
Early versions of PySimpleGUI did not have a concept of "persisent window". Once a user clicked a button, the window would close. After some time, the functionality was expanded so that windows remained open by default.
@@ -3918,7 +3917,7 @@ window.close()
```
-## read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
+## Read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
@@ -4049,8 +4048,8 @@ import PySimpleGUI as sg
import time
# ---------------- Create Form ----------------
-sg.theme('Black')
-sg.set_options(element_padding=(0, 0))
+sg.ChangeLookAndFeel('Black')
+sg.SetOptions(element_padding=(0, 0))
layout = [[sg.Text('')],
[sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
@@ -4200,7 +4199,7 @@ window['spin'].update(sz)
Remember this design pattern because you will use it OFTEN if you use persistent windows.
-It works as follows. The expression `window[key]` returns the Element object represented by the provided `key`. This element is then updated by calling it's `update` method. This is another example of Python's "chaining" feature. We could write this code using the long-form:
+It works as follows. The expresion `window[key]` returns the Element object represented by the provided `key`. This element is then updated by calling it's `update` method. This is another example of Python's "chaining" feature. We could write this code using the long-form:
text_element = window['text']
text_element.update(font=font)
@@ -5574,60 +5573,13 @@ There are a number of demo programs that show how to use UserSettings to create
If you're using the default path, remember that previous runs of your file may have old settings that are still in your settings file. It can get confusing when you've forgotten that you previously wrote a setting. Not seeing the filename can have drawbacks like this.
-Also, because the settings automatically save after every update, it can be easy to accidentally overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
+Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
To save your Python dictionary to a settings file, simply call `user_settings_write_new_dictionary(dict)`, passing in your dictionary as the parameter.
-------------------------
-# Timer API
-
-The Timer API calls are in version 4.61.0 that is currently only available on the PySimpleGUI GitHub. It has not been released to PyPI yet.
-
-## Do Not Use Sleeps In Your Event Loop...
-
-Instead of sleeping, you can request that an event be generated after some period of time. If you need to "Sleep for 3 seconds" as part of some operation, instead schedule a timer for 3 seconds. Your `window.read` call will return a value of `sg.TIMER_KEY` or `sg.EVENT_TIMER` (they are aliases and thus have the same value).
-
-
-## Timer API Calls
-
-These are the API calls that you'll use to manage timers:
-
-
-`window.timer_start` starts a timer
-
-`window.timer_stop` stops a single timer
-
-`window.timer_stop_all` stops all timers
-
-`window.timer_get_active_timers` returns a list of active timer IDs
-
-Example - start a 3 second timer that does not repeat:
-
-```python
-window.timer_start(3000, repeating=False) # start a 3-second timer
-```
-
-When this timer expires, you'll get an event `sg.EVENT_TIMER`. If you want to specify your own key to be returned, then use the `key` parameter:
-
-```python
-window.timer_start(3000, key='-MY TIMER KEY-', repeating=False)
-```
-
-
-See the call reference for the details of each call.
-
-## Timer Demo Programs
-
-Using the PySimpleGUI Demo Browser, search for `window.timer_` to find Demo Programs that use the Timer API calls.
-
-The program `Demo_WindowTimer.py` demonstrates both repeating and non-repeating timers as well as using custom keys. It's a simple set of API calls to use and the docstrings in combination with the Demo Programs should give you all you need to start using this capability.
-
-
-
----------------------------
-
# Extending PySimpleGUI
diff --git a/readme_creator/markdown input files/3_FOOTER.md b/readme_creator/markdown input files/3_FOOTER.md
index 53bf11f0..5e4bc798 100644
--- a/readme_creator/markdown input files/3_FOOTER.md
+++ b/readme_creator/markdown input files/3_FOOTER.md
@@ -2,17 +2,6 @@
---
-# Debug Output
-
-Be sure and check out the EasyPrint (Print) function described in the high-level API section. Leave your code the way it is, route your stdout and stderror to a scrolling window.
-
-For a fun time, add these lines to the top of your script
-
-```python
- import PySimpleGUI as sg
- print = sg.Print
-```
-This will turn all of your print statements into prints that display in a window on your screen rather than to the terminal.
# "Demo Programs" Applications
@@ -115,6 +104,119 @@ Another also mentioned it may be helpful to add the "windowed" option so that a
This info was located on Reddit with the source traced back to:
https://github.com/pyinstaller/pyinstaller/issues/1350
+# Debug Output
+
+Be sure and check out the EasyPrint (Print) function described in the high-level API section. Leave your code the way it is, route your stdout and stderror to a scrolling window.
+
+For a fun time, add these lines to the top of your script
+
+```python
+ import PySimpleGUI as sg
+ print = sg.Print
+```
+This will turn all of your print statements into prints that display in a window on your screen rather than to the terminal.
+
+# Look and Feel
+
+You can change defaults and colors of a large number of things in PySimpleGUI quite easily.
+
+## `ChangleLookAndFeel`
+
+Want a quick way of making your windows look a LOT better? Try calling `ChangeLookAndFeel`. It will, in a single call, set various color values to widgets, background, text, etc.
+
+Or dial in the look and feel (and a whole lot more) that you like with the `SetOptions` function. You can change all of the defaults in one function call. One line of code to customize the entire GUI.
+
+
+```python
+ sg.ChangeLookAndFeel('GreenTan')
+```
+
+Valid look and feel values are currently:
+
+```python
+SystemDefault
+Reddit
+Topanga
+GreenTan
+Dark
+LightGreen
+Dark2
+Black
+Tan
+TanBlue
+DarkTanBlue
+DarkAmber
+DarkBlue
+Reds
+Green
+BluePurple
+Purple
+BlueMono
+GreenMono
+BrownBlue
+BrightColors
+NeutralBlue
+Kayak
+SandyBeach
+TealMono
+```
+
+
+The way this call actually works is that it calls `SetOptions` with a LOT of color settings. Here is the actual call that's made. As you can see lots of stuff is defined for you.
+
+
+
+```python
+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'],
+ 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'])
+```
+
+
+
+
+
+
+
+
+
+To see the latest list of color choices you can call `ListOfLookAndFeelValues()`
+
+You can also combine the `ChangeLookAndFeel` function with the `SetOptions` function to quickly modify one of the canned color schemes. Maybe you like the colors but was more depth to your bezels. You can dial in exactly what you want.
+
+
+
+**ObjToString**
+Ever wanted to easily display an objects contents easily? Use ObjToString to get a nicely formatted recursive walk of your objects.
+This statement:
+
+ print(sg.ObjToSting(x))
+
+And this was the output
+
+
+ abc = abc
+ attr12 = 12
+ c =
+ b =
+ a =
+ attr1 = 1
+ attr2 = 2
+ attr3 = three
+ attr10 = 10
+ attrx = x
+
+You'll quickly wonder how you ever coded without it.
---
# Known Issues
diff --git a/readme_creator/markdown input files/4_Release_notes.md b/readme_creator/markdown input files/4_Release_notes.md
index 7aa73856..18766c25 100644
--- a/readme_creator/markdown input files/4_Release_notes.md
+++ b/readme_creator/markdown input files/4_Release_notes.md
@@ -2574,41 +2574,6 @@ Test Harness and Settings Windows fit on small screens better
* Auto-correct file_types problems for Browse buttons. Automatically change the formatting from (str, str) to ((str, str),) and warns the user
* Docstring typo fixes for file_types parm
-## 4.60.1 PySimpleGUI 22-May-2022
-
-* A patch-release that fixes crash if `horizontal_scrollbar=True` when making a `Listbox` element
-
-
-## 4.60.2 PySimpleGUI 26-Jul-2022
-
-* Emergency Patch Release for Mac OS 12.3 and greater
- * Adds a PySimpleGUI Mac Control Panel Controlled patch that sets the Alpha channel to 0.99 by default for these users
- * Is a workaround for a bug that was introduced into Mac OS 12.3
-
-## 4.60.3 PySimpleGUI 27-Jul-2022
-
-* Emergency Patch Release for Mac OS 12.3 and greater
- * Fixed bug in Mac OS version check in yesterday's 4.60.2 release
-
-## 4.60.4 PySimpleGUI 10-Oct-2022
-
-* Dot release to quickly fix the Trinket detection which stopped working recently
-
-
-## 4.60.5 PySimpleGUI 21-May-2023
-
-* Mac fixes
- * Fix for Input Element not working in no-titlebar windows on MacOs 13.2.1
- * Change to the 0.99 Alpha fix made in 4.60.2. Now only applies patch when running on 8.6.12, regardless of Mac Control Panel setting in PySimpleGUI Global Settings. Removes the need for users to disable when upgrading tkinter.
-* Added Intelligent Upgrade Service - inform users when there are releases of PySimpleGUI that fix a problem that may be unique to their combination of components
-* Change to GitHub Issue GUI
- * Added checkbox for checking if running latest PyPI version
- * Recommended using Demo Browser to search Demo Programs
- * Use platform module to fill in the OS information field
-* SDK Help Window - changed all readthedocs links to use the PySimpleGUI.org hostname for better portability
-
-
-
## Code Condition
diff --git a/readme_creator/markdown input files/5_call_reference.md b/readme_creator/markdown input files/5_call_reference.md
index 24c9e48c..693fcfe3 100644
--- a/readme_creator/markdown input files/5_call_reference.md
+++ b/readme_creator/markdown input files/5_call_reference.md
@@ -25,9 +25,9 @@
apply coupon for discount:
- 522B20BF5EF123C4AB30.
+ 4FD91A459D56B1029FF8
-
+
click here to visit course page
@@ -36,6 +36,22 @@
+
+
+
+
+
# ELEMENT AND FUNCTION CALL REFERENCE
@@ -1111,9 +1127,6 @@ The following methods are here for backwards compatibility reference. You will
### set_focus
-### set_ibeam_color
-
-
### set_size
@@ -1207,18 +1220,12 @@ The following methods are here for backwards compatibility reference. You will
### metadata
-### select_index
-
-
### set_cursor
### set_focus
-### set_index_color
-
-
### set_size
@@ -1430,9 +1437,6 @@ See the Column element to get a list of method calls available. The function re
### set_focus
-### set_ibeam_color
-
-
### set_size
@@ -1569,11 +1573,11 @@ The following methods are here for backwards compatibility reference. You will
---------
-## Output Element
+## Output Element (No longer recommended - USE `Multiline` instead)
-Output Element - a multi-lined text area to where stdout, stderr, cprint are rerouted.
+Rather than use the `Output` element, it's recommended that you use the `Multiline` element instead. The reason for this is that more controls have been added to the Multiline and in the future you can expect more features will be added to the Multiline while the `Output` element has stopped being enhanced.
-Now based on the `Multiline` element
+You can control which Multiline Element receives your stdout output as well as use the color-print (`cprint`) with a Multiline.
@@ -1661,6 +1665,8 @@ The following methods are here for backwards compatibility reference. You will
### SetTooltip
+### TKOut
+
### Update
@@ -2174,9 +2180,6 @@ The following methods are here for backwards compatibility reference. You will
### set_focus
-### set_ibeam_color
-
-
### set_size
@@ -3004,6 +3007,7 @@ Example: If first row has a `VPush`, then your layout will be At the bottom of
### move_to_center
+
### normal
@@ -3040,9 +3044,6 @@ Example: If first row has a `VPush`, then your layout will be At the bottom of
### set_min_size
-### set_size
-
-
### set_title
@@ -3055,18 +3056,6 @@ Example: If first row has a `VPush`, then your layout will be At the bottom of
### start_thread
-### timer_get_active_timers
-
-
-### timer_start
-
-
-### timer_stop
-
-
-### timer_stop_all
-
-
### un_hide
@@ -3368,7 +3357,6 @@ Don't use these. They are here in case you're searching for them. Instead use
-
diff --git a/readme_creator/markdown input files/README.md b/readme_creator/markdown input files/README.md
new file mode 100644
index 00000000..7f43bb11
--- /dev/null
+++ b/readme_creator/markdown input files/README.md
@@ -0,0 +1,76 @@
+
+
+
+
Windows Shortcut Creation
+
+
+Create Windows Shortcuts to your python programs and any other file easily using this application created using PySimpleGUI.
+
+
+
+
+
+
+## Installation
+
+### Old-school Straight Pip
+
+pip install psgshortcut
+
+### pip via `python -m pip` the python recommended way
+
+#### If `python` is your command
+
+python -m pip install psgshortcut
+
+#### If `python3` is your command
+
+python3 -m pip install psgshortcut
+
+## Usage
+
+Open a command window and type:
+
+psgshortcut
+
+
+## Create a Shortcut To This Program
+
+
+Use this program to make a shortcut to itself so that you can then put on your desktop or pin to your taskbar or ???
+
+
+To do this, follow these steps:
+
+1. Open a command window (I promise, it's the last time you'll need to for this program)
+2. Type - `where psgshortcut`
+3. Copy the line that `where psgshortcut` gave you into the first input of the shortcut maker program
+4. Run psgshortcut by typing `psgshortcut` in your command window
+5. Right click and choose "File Location"
+6. Copy the file location results, but change the extension from .py to .ico and paste into the Icon file input of the shortcut maker
+7. Click "Create Shortcut"
+
+This will create a shortcut in the same folder as the target file. You can safely move this shortcut file to any place you want (like to your desktop). Double-click the shortcut and your program should launch.
+
+## Make Shortcuts To Anything
+
+You can not only make shortcuts to Python programs, but you can make shortcuts to EXE and other files. The GUI is self-explanatory. Fill in the inputs, click the Make Shortcut button and you'll find the shortcut in the same folder as the target program.
+
+## License
+
+Licensed under an LGPL3 License
+
+## This PyPI Was Designed and Written By
+
+This program originated from the PySimpleGUI Demo Programs. You'll find it here:
+[Demo_Make_Windows_Shortcut](https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_Make_Windows_Shortcut.pyw)
+
+Mike from PySimpleGUI.org
+
+## Contributing
+
+Like the PySimpleGUI project, this project is currently licensed under an open-source license, the project itself is structured like a proprietary product. Pull Requests are not accepted.
+
+## Copyright
+
+Copyright 2021 PySimpleGUI
diff --git a/readme_creator/output/call reference.md b/readme_creator/output/call reference.md
index e909d3e7..898e542a 100644
--- a/readme_creator/output/call reference.md
+++ b/readme_creator/output/call reference.md
@@ -25,9 +25,9 @@
apply coupon for discount:
- 522B20BF5EF123C4AB30.
+ 4FD91A459D56B1029FF8
-
+
click here to visit course page
@@ -35,6 +35,21 @@
+
+
+
+
# ELEMENT AND FUNCTION CALL REFERENCE
Here you will find the details for all Elements, Objects, and Functions that are available to you. If you want to use a complex element and don't understand the parameters, then this is the right place to come. For every element you're shown the parameters used to create it as well as all methods available to call.
@@ -71,7 +86,6 @@ Button(button_text = "",
image_data = None,
image_size = (None, None),
image_subsample = None,
- image_zoom = None,
image_source = None,
border_width = None,
size = (None, None),
@@ -104,7 +118,7 @@ Parameter Descriptions:
| int | button_type | You should NOT be setting this directly. ONLY the shortcut functions set this |
| str or (int, int) | 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 |
| str | tooltip | text, that will appear when mouse hovers over the element |
-| Tuple[(str, str), ...] | file_types | the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.* *"),). |
+| Tuple[(str, str), ...] | file_types | the filetypes that will be used to match files. To indicate all files: (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| str | initial_folder | starting path for folders and files |
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| (bool or str) | disabled | If True button will be created disabled. If BUTTON_DISABLED_MEANS_IGNORE then the button will be ignored rather than disabled using tkinter |
@@ -115,18 +129,17 @@ Parameter Descriptions:
| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
| (int, int) | image_size | Size of the image in pixels (width, height) |
| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
| int | border_width | width of border around button in pixels |
| (int or None, int or None) or (None, None) or int | 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 |
| (int or None, int or None) or (None, None) or int | 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 |
| bool | auto_size_button | if True the button size is sized to fit the text |
-| (str, str) or str | 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. |
+| (str, str) or str or (int, int) or None | 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. |
| (str, str) or str | 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 |
| (str, str) | 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 |
| (str, str) or str | 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) |
| bool | 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 |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | If True the return key will cause this button to be pressed |
| bool | focus | if True, initial focus will be put on this button |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -402,12 +415,10 @@ when made visible.
update(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)
```
@@ -416,17 +427,15 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | text | sets button text |
-| (str, str) or str | 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. |
-| (bool or str) | disabled | True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors) |
-| (str or bytes) | image_source | Image to place on button. Use INSTEAD of the image_filename and image_data. Unifies these into 1 easier to use parm |
-| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
-| str | image_filename | image filename if there is a button image. GIFs and PNGs only. |
-| (str, str) | 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 |
-| bool | visible | control visibility of element |
-| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
-| (int, int) | image_size | Size of the image in pixels (width, height) |
+| str | text | sets button text |
+| (str, str) or str or (int, int) or None | 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. |
+| (bool or str) | disabled | True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors) |
+| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
+| str | image_filename | image filename if there is a button image. GIFs and PNGs only. |
+| (str, str) | 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 |
+| bool | visible | control visibility of element |
+| int | 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 |
+| (int, int) | image_size | Size of the image in pixels (width, height) |
### visible
@@ -516,12 +525,10 @@ when made visible.
Update(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)
```
@@ -530,17 +537,15 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | text | sets button text |
-| (str, str) or str | 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. |
-| (bool or str) | disabled | True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors) |
-| (str or bytes) | image_source | Image to place on button. Use INSTEAD of the image_filename and image_data. Unifies these into 1 easier to use parm |
-| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
-| str | image_filename | image filename if there is a button image. GIFs and PNGs only. |
-| (str, str) | 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 |
-| bool | visible | control visibility of element |
-| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
-| (int, int) | image_size | Size of the image in pixels (width, height) |
+| str | text | sets button text |
+| (str, str) or str or (int, int) or None | 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. |
+| (bool or str) | disabled | True/False to enable/disable at the GUI level. Use BUTTON_DISABLED_MEANS_IGNORE to ignore clicks (won't change colors) |
+| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
+| str | image_filename | image filename if there is a button image. GIFs and PNGs only. |
+| (str, str) | 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 |
+| bool | visible | control visibility of element |
+| int | 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 |
+| (int, int) | image_size | Size of the image in pixels (width, height) |
---------
@@ -558,7 +563,6 @@ ButtonMenu(button_text,
image_data = None,
image_size = (None, None),
image_subsample = None,
- image_zoom = None,
border_width = None,
size = (None, None),
s = (None, None),
@@ -593,7 +597,6 @@ Parameter Descriptions:
| bytes or str | image_data | Raw or Base64 representation of the image to put on button. Choose either filename or data |
| (int, int) | image_size | Size of the image in pixels (width, height) |
| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
| int | border_width | width of border around button in pixels |
| (int, int) or (None, None) or int | 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 |
| (int, int) or (None, None) or int | 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 |
@@ -850,23 +853,19 @@ update(menu_definition = None,
image_source = None,
image_size = (None, None),
image_subsample = None,
- image_zoom = None,
- button_text = None,
- button_color = None)
+ button_text = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| List[List] | menu_definition | (New menu definition (in menu definition format) |
-| bool | visible | control visibility of element |
-| (str or bytes) | image_source | new image if image is to be changed. Can be a filename or a base64 encoded byte-string |
-| (int, int) | image_size | Size of the image in pixels (width, height) |
-| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
-| str | button_text | Text to be shown on the button |
-| (str, str) or str | 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. |
+| List[List] | menu_definition | (New menu definition (in menu definition format) |
+| bool | visible | control visibility of element |
+| (str or bytes) | image_source | new image if image is to be changed. Can be a filename or a base64 encoded byte-string |
+| (int, int) | image_size | Size of the image in pixels (width, height) |
+| int | 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 |
+| str | button_text | Text to be shown on the button |
### visible
@@ -948,23 +947,19 @@ Update(menu_definition = None,
image_source = None,
image_size = (None, None),
image_subsample = None,
- image_zoom = None,
- button_text = None,
- button_color = None)
+ button_text = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| List[List] | menu_definition | (New menu definition (in menu definition format) |
-| bool | visible | control visibility of element |
-| (str or bytes) | image_source | new image if image is to be changed. Can be a filename or a base64 encoded byte-string |
-| (int, int) | image_size | Size of the image in pixels (width, height) |
-| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
-| str | button_text | Text to be shown on the button |
-| (str, str) or str | 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. |
+| List[List] | menu_definition | (New menu definition (in menu definition format) |
+| bool | visible | control visibility of element |
+| (str or bytes) | image_source | new image if image is to be changed. Can be a filename or a base64 encoded byte-string |
+| (int, int) | image_size | Size of the image in pixels (width, height) |
+| int | 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 |
+| str | button_text | Text to be shown on the button |
---------
@@ -1305,7 +1300,6 @@ Checkbox(text,
background_color = None,
text_color = None,
checkbox_color = None,
- highlight_thickness = 1,
change_submits = False,
enable_events = False,
disabled = False,
@@ -1325,29 +1319,28 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | text | Text to display next to checkbox |
-| bool | default | Set to True if you want this checkbox initially checked |
-| (int, int) or (None, None) or int | 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 |
-| (int, int) or (None, None) or int | 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 |
-| bool | auto_size_text | if True will size the element to match the length of the text |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| str | checkbox_color | color of background of the box that has the check mark in it. The checkmark is the same color as the text |
-| int | highlight_thickness | thickness of border around checkbox when gets focus |
-| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
-| bool | enable_events | Turns on the element specific events. Checkbox events happen when an item changes |
-| bool | disabled | set disable state |
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
-| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| str | tooltip | text, that will appear when mouse hovers over the element |
-| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
-| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
-| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
-| bool | visible | set visibility state of the element |
-| Any | metadata | User metadata that can be set to ANYTHING |
+| str | text | Text to display next to checkbox |
+| bool | default | Set to True if you want this checkbox initially checked |
+| (int, int) or (None, None) or int | 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 |
+| (int, int) or (None, None) or int | 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 |
+| bool | auto_size_text | if True will size the element to match the length of the text |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| str | checkbox_color | color of background of the box that has the check mark in it. The checkmark is the same color as the text |
+| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
+| bool | enable_events | Turns on the element specific events. Checkbox events happen when an item changes |
+| bool | disabled | set disable state |
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
+| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
+| str | tooltip | text, that will appear when mouse hovers over the element |
+| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
+| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
+| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
+| bool | visible | set visibility state of the element |
+| Any | metadata | User metadata that can be set to ANYTHING |
### bind
@@ -1754,8 +1747,8 @@ Parameter Descriptions:
| float | 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.. |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| bool | 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 |
-| bool | vertical_scroll_only | if True then no horizontal scrollbar will be shown if a scrollable column |
+| bool | scrollable | if True then scrollbars will be added to the column |
+| bool | vertical_scroll_only | if Truen then no horizontal scrollbar will be shown |
| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
| str or int or tuple or object | 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 |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
@@ -2188,7 +2181,6 @@ Combo(values,
bind_return_key = False,
change_submits = False,
enable_events = False,
- enable_per_char_events = None,
disabled = False,
key = None,
k = None,
@@ -2216,10 +2208,9 @@ Parameter Descriptions:
| str | text_color | color of the text |
| str | button_background_color | The color of the background of the button on the combo box |
| str | button_arrow_color | The color of the arrow on the button on the combo box |
-| bool | bind_return_key | If True, then the return key will cause a the Combo to generate an event when return key is pressed |
+| bool | bind_return_key | If True, then the return key will cause a the Combo to generate an event |
| bool | change_submits | DEPRICATED DO NOT USE. Use `enable_events` instead |
| bool | enable_events | Turns on the element specific events. Combo event is when a choice is made |
-| bool | enable_per_char_events | Enables generation of events for every character that's input. This is like the Input element's events |
| bool | disabled | set disable state for element |
| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
@@ -2482,27 +2473,21 @@ update(value = None,
readonly = None,
font = None,
visible = None,
- size = (None, None),
- select = None,
- text_color = None,
- background_color = None)
+ size = (None, None))
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | value | change which value is current selected based on new list of previous list of choices |
-| List[Any] | values | change list of choices |
-| int | set_to_index | change selection to a particular choice starting with index = 0 |
-| bool | disabled | disable or enable state of the element |
-| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | visible | control visibility of element |
-| (int, int) | size | width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list |
-| bool | select | if True, then the text will be selected, if False then selection will be cleared |
-| str | background_color | color of background |
-| str | text_color | color of the text |
+| Any | value | change which value is current selected based on new list of previous list of choices |
+| List[Any] | values | change list of choices |
+| int | set_to_index | change selection to a particular choice starting with index = 0 |
+| bool | disabled | disable or enable state of the element |
+| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | visible | control visibility of element |
+| (int, int) | size | width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list |
### visible
@@ -2591,27 +2576,21 @@ Update(value = None,
readonly = None,
font = None,
visible = None,
- size = (None, None),
- select = None,
- text_color = None,
- background_color = None)
+ size = (None, None))
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | value | change which value is current selected based on new list of previous list of choices |
-| List[Any] | values | change list of choices |
-| int | set_to_index | change selection to a particular choice starting with index = 0 |
-| bool | disabled | disable or enable state of the element |
-| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | visible | control visibility of element |
-| (int, int) | size | width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list |
-| bool | select | if True, then the text will be selected, if False then selection will be cleared |
-| str | background_color | color of background |
-| str | text_color | color of the text |
+| Any | value | change which value is current selected based on new list of previous list of choices |
+| List[Any] | values | change list of choices |
+| int | set_to_index | change selection to a particular choice starting with index = 0 |
+| bool | disabled | disable or enable state of the element |
+| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | visible | control visibility of element |
+| (int, int) | size | width, height. Width = characters-wide, height = NOTE it's the number of entries to show in the list |
---------
@@ -4440,7 +4419,6 @@ Image(source = None,
k = None,
tooltip = None,
subsample = None,
- zoom = None,
right_click_menu = None,
expand_x = False,
expand_y = False,
@@ -4465,7 +4443,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| str | tooltip | text, that will appear when mouse hovers over the element |
| int | 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 |
-| int | zoom | amount to increase the size of the image. |
| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
@@ -4708,7 +4685,6 @@ update(source = None,
data = None,
size = (None, None),
subsample = None,
- zoom = None,
visible = None)
```
@@ -4721,7 +4697,6 @@ Parameter Descriptions:
| str or tkPhotoImage | data | Base64 encoded string OR a tk.PhotoImage object |
| Tuple[int,int] | size | (width, height) size of image in pixels |
| int | 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 |
-| int | zoom | amount to increase the size of the image |
| bool | visible | control visibility of element |
### update_animation
@@ -4829,7 +4804,6 @@ Update(source = None,
data = None,
size = (None, None),
subsample = None,
- zoom = None,
visible = None)
```
@@ -4842,7 +4816,6 @@ Parameter Descriptions:
| str or tkPhotoImage | data | Base64 encoded string OR a tk.PhotoImage object |
| Tuple[int,int] | size | (width, height) size of image in pixels |
| int | 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 |
-| int | zoom | amount to increase the size of the image |
| bool | visible | control visibility of element |
### UpdateAnimation
@@ -4891,8 +4864,6 @@ Input(default_text = "",
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,
@@ -4927,8 +4898,6 @@ Parameter Descriptions:
| bool | 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 |
| str | disabled_readonly_background_color | If state is set to readonly or disabled, the color to use for the background |
| str | disabled_readonly_text_color | If state is set to readonly or disabled, the color to use for the text |
-| str | selected_text_color | Color of text when it is selected (using mouse or control+A, etc) |
-| str | selected_background_color | Color of background when it is selected (using mouse or control+A, etc) |
| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
@@ -5110,22 +5079,6 @@ Parameter Descriptions:
|--|--|--|
| bool | force | if True will call focus_force otherwise calls focus_set |
-### set_ibeam_color
-
-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.
-
-```
-set_ibeam_color(ibeam_color = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| str | ibeam_color | color to set the "I-Beam" used to indicate where characters will be inserted |
-
### set_size
Changes the size of an element to a specific size.
@@ -5208,28 +5161,24 @@ update(value = None,
visible = None,
text_color = None,
background_color = None,
- font = None,
move_cursor_to = "end",
password_char = None,
- paste = None,
- readonly = None)
+ paste = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | value | new text to display as default text in Input field |
-| bool | disabled | disable or enable state of the element (sets Entry Widget to readonly or normal) |
-| bool | select | if True, then the text will be selected |
-| bool | visible | change visibility of element |
-| str | text_color | change color of text being typed |
-| str | background_color | change color of the background |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| int or str | move_cursor_to | Moves the cursor to a particular offset. Defaults to 'end' |
-| str | password_char | Password character if this is a password field |
-| bool | 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. |
-| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
+| str | value | new text to display as default text in Input field |
+| bool | disabled | disable or enable state of the element (sets Entry Widget to readonly or normal) |
+| bool | select | if True, then the text will be selected |
+| bool | visible | change visibility of element |
+| str | text_color | change color of text being typed |
+| str | background_color | change color of the background |
+| int or str | move_cursor_to | Moves the cursor to a particular offset. Defaults to 'end' |
+| str | password_char | Password character if this is a password field |
+| bool | 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. |
### visible
@@ -5312,28 +5261,24 @@ Update(value = None,
visible = None,
text_color = None,
background_color = None,
- font = None,
move_cursor_to = "end",
password_char = None,
- paste = None,
- readonly = None)
+ paste = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | value | new text to display as default text in Input field |
-| bool | disabled | disable or enable state of the element (sets Entry Widget to readonly or normal) |
-| bool | select | if True, then the text will be selected |
-| bool | visible | change visibility of element |
-| str | text_color | change color of text being typed |
-| str | background_color | change color of the background |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| int or str | move_cursor_to | Moves the cursor to a particular offset. Defaults to 'end' |
-| str | password_char | Password character if this is a password field |
-| bool | 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. |
-| bool | readonly | if True make element readonly (user cannot change any choices). Enables the element if either choice are made. |
+| str | value | new text to display as default text in Input field |
+| bool | disabled | disable or enable state of the element (sets Entry Widget to readonly or normal) |
+| bool | select | if True, then the text will be selected |
+| bool | visible | change visibility of element |
+| str | text_color | change color of text being typed |
+| str | background_color | change color of the background |
+| int or str | move_cursor_to | Moves the cursor to a particular offset. Defaults to 'end' |
+| str | password_char | Password character if this is a password field |
+| bool | 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. |
---------
@@ -5352,7 +5297,6 @@ Listbox(values,
size = (None, None),
s = (None, None),
disabled = False,
- justification = None,
auto_size_text = None,
font = None,
no_scrollbar = False,
@@ -5389,11 +5333,10 @@ Parameter Descriptions:
| [enum] | 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 |
| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
| bool | enable_events | Turns on the element specific events. Listbox generates events when an item is clicked |
-| bool | bind_return_key | If True, then the return key will cause a the Listbox to generate an event when return key is pressed |
+| bool | bind_return_key | If True, then the return key will cause a the Listbox to generate an event |
| (int, int) or (int, None) or int | size | w=characters-wide, h=rows-high. If an int instead of a tuple is supplied, then height is auto-set to 1 |
| (int, int) or (None, None) or int | 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 |
| bool | disabled | set disable state for element |
-| str | justification | justification for items in listbox. Valid choices - left, right, center. Default is left. NOTE - on some older versions of tkinter, not available |
| bool | auto_size_text | True if element should be the same size as the contents |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| bool | no_scrollbar | Controls if a scrollbar should be shown. If True, no scrollbar will be shown |
@@ -5583,24 +5526,6 @@ Metadata is an Element property that you can use at any time to hold any value
|---|---|---|
|(Any)| **return** | the current metadata value |
-### select_index
-
-Selects an index while providing capability to setting the selected color for the index to specific text/background color
-
-```
-select_index(index,
- highlight_text_color = None,
- highlight_background_color = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| int | index | specifies which item to change. index starts at 0 and goes to length of values list minus one |
-| str | highlight_text_color | color of the text when this item is selected. |
-| str | highlight_background_color | color of the background when this item is selected |
-
### set_cursor
Sets the cursor for the current Element.
@@ -5634,28 +5559,6 @@ Parameter Descriptions:
|--|--|--|
| bool | force | if True will call focus_force otherwise calls focus_set |
-### set_index_color
-
-Sets the color of a specific item without selecting it
-
-```
-set_index_color(index,
- text_color = None,
- background_color = None,
- highlight_text_color = None,
- highlight_background_color = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| int | index | specifies which item to change. index starts at 0 and goes to length of values list minus one |
-| str | text_color | color of the text for this item |
-| str | background_color | color of the background for this item |
-| str | highlight_text_color | color of the text when this item is selected. |
-| str | highlight_background_color | color of the background when this item is selected |
-
### set_size
Changes the size of an element to a specific size.
@@ -5898,8 +5801,6 @@ Parameter Descriptions:
['&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.
@@ -5926,15 +5827,15 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
| List[List[Tuple[str, List[str]]] | menu_definition | The Menu definition specified using lists (docs explain the format) |
-| str | background_color | color of the background of menus, NOT the Menubar |
-| str | text_color | text color for menus, NOT the Menubar. Can be in #RRGGBB format or a color name "black". |
-| str | 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" |
+| str | background_color | color of the background |
+| str | text_color | element's text color. Can be in #RRGGBB format or a color name "black" |
+| str | disabled_text_color | color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black" |
| (int, int) | size | Not used in the tkinter port |
| (int, int) or (None, None) | 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 |
| bool | tearoff | if True, then can tear the menu off from the window ans use as a floating window. Very cool effect |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| (str or (str, int[, str]) or None) | 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 |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str or int or tuple or object | 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 |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set visibility state of the element |
@@ -6314,15 +6215,12 @@ Multiline(default_text = "",
enter_submits = False,
disabled = False,
autoscroll = False,
- autoscroll_only_at_bottom = False,
border_width = None,
size = (None, None),
s = (None, 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,
@@ -6342,7 +6240,6 @@ Multiline(default_text = "",
tooltip = None,
justification = None,
no_scrollbar = False,
- wrap_lines = None,
sbar_trough_color = None,
sbar_background_color = None,
sbar_arrow_color = None,
@@ -6362,52 +6259,48 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | default_text | Initial text to show |
-| bool | enter_submits | if True, the Window.read call will return is enter key is pressed in this element |
-| bool | disabled | set disable state |
-| bool | autoscroll | If True the contents of the element will automatically scroll as more data added to the end |
-| bool | 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 |
-| int | border_width | width of border around element in pixels |
-| (int, int) or (None, None) or int | 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 |
-| (int, int) or (None, None) or int | 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 |
-| bool | auto_size_text | if True will size the element to match the length of the text |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| str | selected_text_color | Color of text when it is selected (using mouse or control+A, etc) |
-| str | selected_background_color | Color of background when it is selected (using mouse or control+A, etc) |
-| bool | horizontal_scroll | Controls if a horizontal scrollbar should be shown. If True a horizontal scrollbar will be shown in addition to vertical |
-| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
-| bool | enable_events | If True then any key press that happens when the element has focus will generate an event. |
-| bool | do_not_clear | if False the element will be cleared any time the Window.read call returns |
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element |
-| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
-| bool | write_only | If True then no entry will be added to the values dictionary when the window is read |
-| bool | auto_refresh | If True then anytime the element is updated, the window will be refreshed so that the change is immediately displayed |
-| bool | reroute_stdout | If True then all output to stdout will be output to this element |
-| bool | reroute_stderr | If True then all output to stderr will be output to this element |
-| bool | reroute_cprint | If True your cprint calls will output to this element. It's the same as you calling cprint_set_output_destination |
-| bool | echo_stdout_stderr | If True then output to stdout and stderr will be output to this element AND also to the normal console location |
-| bool | focus | if True initial focus will go to this element |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| str | tooltip | text, that will appear when mouse hovers over the element |
-| str | justification | text justification. left, right, center. Can use single characters l, r, c. |
-| bool | no_scrollbar | If False then a vertical scrollbar will be shown (the default) |
-| bool | 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. |
-| str | sbar_trough_color | Scrollbar color of the trough |
-| str | 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 |
-| str | 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 |
-| int | sbar_width | Scrollbar width in pixels |
-| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
-| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
-| str | 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 |
-| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
-| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
-| bool | rstrip | If True the value returned in will have whitespace stripped from the right side |
-| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
-| bool | visible | set visibility state of the element |
-| Any | metadata | User metadata that can be set to ANYTHING |
+| Any | default_text | Initial text to show |
+| bool | enter_submits | if True, the Window.Read call will return is enter key is pressed in this element |
+| bool | disabled | set disable state |
+| bool | autoscroll | If True the contents of the element will automatically scroll as more data added to the end |
+| int | border_width | width of border around element in pixels |
+| (int, int) or (None, None) or int | 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 |
+| (int, int) or (None, None) or int | 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 |
+| bool | auto_size_text | if True will size the element to match the length of the text |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | horizontal_scroll | Controls if a horizontal scrollbar should be shown. If True a horizontal scrollbar will be shown in addition to vertical |
+| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
+| bool | enable_events | Turns on the element specific events. Spin events happen when an item changes |
+| bool | do_not_clear | if False the element will be cleared any time the Window.Read call returns |
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element |
+| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
+| bool | write_only | If True then no entry will be added to the values dictionary when the window is read |
+| bool | auto_refresh | If True then anytime the element is updated, the window will be refreshed so that the change is immediately displayed |
+| bool | reroute_stdout | If True then all output to stdout will be output to this element |
+| bool | reroute_stderr | If True then all output to stderr will be output to this element |
+| bool | reroute_cprint | If True your cprint calls will output to this element. It's the same as you calling cprint_set_output_destination |
+| bool | echo_stdout_stderr | If True then output to stdout and stderr will be output to this element AND also to the normal console location |
+| bool | focus | if True initial focus will go to this element |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
+| str | tooltip | text, that will appear when mouse hovers over the element |
+| str | justification | text justification. left, right, center. Can use single characters l, r, c. |
+| bool | no_scrollbar | If False then a vertical scrollbar will be shown (the default) |
+| str | sbar_trough_color | Scrollbar color of the trough |
+| str | 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 |
+| str | 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 |
+| int | sbar_width | Scrollbar width in pixels |
+| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
+| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
+| str | 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 |
+| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
+| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
+| bool | rstrip | If True the value returned in will have whitespace stripped from the right side |
+| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
+| bool | visible | set visibility state of the element |
+| Any | metadata | User metadata that can be set to ANYTHING |
### bind
@@ -6666,22 +6559,6 @@ Parameter Descriptions:
|--|--|--|
| bool | force | if True will call focus_force otherwise calls focus_set |
-### set_ibeam_color
-
-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.
-
-```
-set_ibeam_color(ibeam_color = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| str | ibeam_color | color to set the "I-Beam" used to indicate where characters will be inserted |
-
### set_size
Changes the size of an element to a specific size.
@@ -6750,7 +6627,7 @@ unhide_row()
### update
-Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
+Changes some of the settings for the Multiline 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.
@@ -6857,7 +6734,7 @@ Parameter Descriptions:
### Update
-Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
+Changes some of the settings for the Multiline 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.
@@ -7292,25 +7169,25 @@ Parameter Descriptions:
---------
-## Output Element
+## Output Element (No longer recommended - USE `Multiline` instead)
-Output Element - a multi-lined text area to where stdout, stderr, cprint are rerouted.
+Rather than use the `Output` element, it's recommended that you use the `Multiline` element instead. The reason for this is that more controls have been added to the Multiline and in the future you can expect more features will be added to the Multiline while the `Output` element has stopped being enhanced.
-Now based on the `Multiline` element
+You can control which Multiline Element receives your stdout output as well as use the color-print (`cprint`) with a Multiline.
- Output Element - a multi-lined text area to where stdout, stderr, cprint are rerouted.
+ ** NOTE - It's recommended to use Multiline Element instead **
- 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
+ Output Element - a multi-lined text area where stdout and stderr are re-routed to.
- 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
+ The Multiline Element is the superior and recommended method for showing the output of stdout.
+ The Multiline Element has been added to significantly while the Output element has not.
+ If you choose to use a Multiline element to replace an Output element, be sure an turn on the write_only paramter in the Multline
+
+ Of course, Output Element continues to operate and be backwards compatible, but you're missing out on
+ features such as routing the cprint output to the element.
+
+ In Apr 2022, the Output Element was switched to be a subclass of the Multiline so that more code will be in common. Nowever
+ you will not get all of the parms unless you switch to the Multline Specifically
```
Output(size = (None, None),
@@ -7319,7 +7196,6 @@ Output(size = (None, None),
text_color = None,
pad = None,
p = None,
- autoscroll_only_at_bottom = False,
echo_stdout_stderr = False,
font = None,
tooltip = None,
@@ -7330,8 +7206,6 @@ Output(size = (None, None),
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,
@@ -7345,32 +7219,29 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| (int, int) or (None, None) or int | 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 |
-| (int, int) or (None, None) or int | 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 |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
-| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| bool | 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 |
-| bool | echo_stdout_stderr | If True then output to stdout will be output to this element AND also to the normal console location |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str | tooltip | text, that will appear when mouse hovers over the element |
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element |
-| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
-| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
-| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
-| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
-| bool | visible | set visibility state of the element |
-| Any | metadata | User metadata that can be set to ANYTHING |
-| bool | 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. |
-| bool | horizontal_scroll | Controls if a horizontal scrollbar should be shown. If True, then line wrapping will be off by default |
-| str | sbar_trough_color | Scrollbar color of the trough |
-| str | 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 |
-| str | 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 |
-| int | sbar_width | Scrollbar width in pixels |
-| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
-| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
-| str | 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 |
+| (int, int) or (None, None) or int | 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 |
+| (int, int) or (None, None) or int | 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 |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
+| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
+| bool | echo_stdout_stderr | If True then output to stdout will be output to this element AND also to the normal console location |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str | tooltip | text, that will appear when mouse hovers over the element |
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element to uniquely identify this element |
+| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
+| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
+| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
+| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
+| bool | visible | set visibility state of the element |
+| Any | metadata | User metadata that can be set to ANYTHING |
+| str | sbar_trough_color | Scrollbar color of the trough |
+| str | 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 |
+| str | 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 |
+| int | sbar_width | Scrollbar width in pixels |
+| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
+| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
+| str | 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 |
### bind
@@ -7607,7 +7478,7 @@ unhide_row()
### update
-Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
+Changes some of the settings for the Multiline 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.
@@ -7712,9 +7583,11 @@ Parameter Descriptions:
|--|--|--|
| str | tooltip_text | the text to show in tooltip. |
+### TKOut
+
### Update
-Changes some of the settings for the Multiline Element. Must call `Window.read` or set finalize=True when creating window.
+Changes some of the settings for the Multiline 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.
@@ -8152,7 +8025,7 @@ Parameter Descriptions:
| (int, int) or (None, None) | 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 |
| (int, int) or (None, None) | size_px | Size in pixels (length, width). Will be used in place of size parm if specified |
| bool | auto_size_text | Not sure why this is here |
-| (str, str) or str | 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. |
+| (str, str) or str | 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". |
| str | style | Progress bar style defined as one of these 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' |
| int | border_width | The amount of pixels that go around the outside of the bar |
| str | 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) |
@@ -8996,7 +8869,7 @@ Parameter Descriptions:
|--|--|--|
| int | h_pixels | number of horizontal pixels |
| int | v_pixels | number of vertical pixels |
-| (Canvas) | **RETURN** | (Canvas) A canvas element that has a pad setting set according to parameters
+| (Column) | **RETURN** | (Column) A column element that has a pad setting set according to parameters
-------
@@ -9688,7 +9561,6 @@ Spin(values,
k = None,
pad = None,
p = None,
- wrap = None,
tooltip = None,
right_click_menu = None,
expand_x = False,
@@ -9706,11 +9578,11 @@ Parameter Descriptions:
| bool | disabled | set disable state |
| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
| bool | enable_events | Turns on the element specific events. Spin events happen when an item changes |
-| bool | readonly | If True, then users cannot type in values. Only values from the values list are allowed. |
+| bool | readonly | Turns on the element specific events. Spin events happen when an item changes |
| (int, int) or (None, None) or int | 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 |
| (int, int) or (None, None) or int | 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 |
| bool | auto_size_text | if True will size the element to match the length of the text |
-| bool | bind_return_key | If True, then the return key will cause a the element to generate an event when return key is pressed |
+| bool | bind_return_key | If True, then the return key will cause a the element to generate an event |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str | background_color | color of background |
| str | text_color | color of the text |
@@ -9718,7 +9590,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
-| bool | wrap | Determines if the values should "Wrap". Default is False. If True, when reaching last value, will continue back to the first value. |
| str | tooltip | text, that will appear when mouse hovers over the element |
| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
@@ -9903,22 +9774,6 @@ Parameter Descriptions:
|--|--|--|
| bool | force | if True will call focus_force otherwise calls focus_set |
-### set_ibeam_color
-
-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.
-
-```
-set_ibeam_color(ibeam_color = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| str | ibeam_color | color to set the "I-Beam" used to indicate where characters will be inserted |
-
### set_size
Changes the size of an element to a specific size.
@@ -10511,7 +10366,6 @@ Tab(title,
element_justification = "left",
image_source = None,
image_subsample = None,
- image_zoom = None,
metadata = None)
```
@@ -10538,7 +10392,6 @@ Parameter Descriptions:
| str | element_justification | All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values |
| str or bytes or None | image_source | A filename or a base64 bytes of an image to place on the Tab |
| int | 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 |
-| int | image_zoom | amount to increase the size of the image. 2=twice size, 3=3 times, etc |
| Any | metadata | User metadata that can be set to ANYTHING |
### add_row
@@ -10998,7 +10851,7 @@ Parameter Descriptions:
| List[List[ List[str] or str ]] | right_click_menu | A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. |
| bool | expand_x | If True the element will automatically expand in the X direction to fill available space |
| bool | expand_y | If True the element will automatically expand in the Y direction to fill available space |
-| bool | visible | DEPRECATED - Should you need to control visiblity for the TabGroup as a whole, place it into a Column element |
+| bool | visible | set visibility state of the element |
| Any | metadata | User metadata that can be set to ANYTHING |
### add_tab
@@ -11090,14 +10943,14 @@ Parameter Descriptions:
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
+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?
`get()`
|Type|Name|Meaning|
|---|---|---|
-|Any | None| **return** | The key of the currently selected tab or None if there is an error |
+|Any | None| **return** | The key of the currently selected tab or the tab's text if it has no key |
### get_next_focus
@@ -11322,14 +11175,14 @@ Parameter Descriptions:
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
+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?
`Get()`
|Type|Name|Meaning|
|---|---|---|
-|Any | None| **return** | The key of the currently selected tab or None if there is an error |
+|Any | None| **return** | The key of the currently selected tab or the tab's text if it has no key |
### SetFocus
@@ -11368,13 +11221,11 @@ Table(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,
@@ -11426,13 +11277,11 @@ Parameter Descriptions:
| List[str] | headings | The headings to show on the top line |
| List[bool] | visible_column_map | One entry for each column. False indicates the column is not shown |
| List[int] | col_widths | Number of characters that each column will occupy |
-| List[str] or Tuple[str] or None | 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 |
| int | def_col_width | Default column width in characters |
| bool | auto_size_columns | if True columns will be sized automatically |
| int | max_col_width | Maximum width for all columns in characters |
| enum | 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 |
| bool | display_row_numbers | if True, the first column of the table will be the row # |
-| int | 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. |
| int | num_rows | The number of rows of the table to display at a time |
| int | row_height | height of a single row in pixels |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
@@ -11530,13 +11379,15 @@ Parameter Descriptions:
### get
-Get the selected rows using tktiner's selection method. Returns a list of the selected rows.
+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.
`get()`
|Type|Name|Meaning|
|---|---|---|
-|List[int]| **return** | a list of the index of the selected rows (a list of ints) |
+|List[List[Any]]| **return** | the current table values (for now what was originally provided up updated) |
### get_next_focus
@@ -11760,13 +11611,15 @@ The following methods are here for backwards compatibility reference. You will
### Get
-Get the selected rows using tktiner's selection method. Returns a list of the selected rows.
+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.
`Get()`
|Type|Name|Meaning|
|---|---|---|
-|List[int]| **return** | a list of the index of the selected rows (a list of ints) |
+|List[List[Any]]| **return** | the current table values (for now what was originally provided up updated) |
### SetFocus
@@ -11868,7 +11721,7 @@ Parameter Descriptions:
| bool | auto_size_text | if True size of the Text Element will be sized to fit the string provided in 'text' parm |
| bool | click_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
| bool | enable_events | Turns on the element specific events. Text events happen when the text is clicked |
-| str | 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 |
+| (str/enum) | 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 |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str | text_color | color of the text |
| str | background_color | color of background |
@@ -12132,7 +11985,7 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | value | new text to show |
+| str | value | new text to show |
| str | background_color | color of background |
| str | text_color | color of the text |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
@@ -12225,7 +12078,7 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | value | new text to show |
+| str | value | new text to show |
| str | background_color | color of background |
| str | text_color | color of the text |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
@@ -12300,7 +12153,6 @@ Tree(data = None,
show_expanded = False,
change_submits = False,
enable_events = False,
- click_toggles_select = None,
font = None,
justification = "right",
text_color = None,
@@ -12352,7 +12204,6 @@ Parameter Descriptions:
| bool | show_expanded | if True then the tree will be initially shown with all nodes completely expanded |
| bool | change_submits | DO NOT USE. Only listed for backwards compat - Use enable_events instead |
| bool | enable_events | Turns on the element specific events. Tree events happen when row is clicked |
-| bool | click_toggles_select | If True then clicking a row will cause the selection for that row to toggle between selected and deselected |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str | justification | 'left', 'right', 'center' are valid choices |
| str | text_color | color of the text |
@@ -13112,7 +12963,7 @@ Window(title,
auto_close_duration = 3,
icon = None,
force_toplevel = False,
- alpha_channel = None,
+ alpha_channel = 1,
return_keyboard_events = False,
use_default_focus = True,
text_justification = None,
@@ -13138,7 +12989,6 @@ Window(title,
use_ttk_buttons = None,
modal = False,
enable_close_attempted_event = False,
- enable_window_config_events = False,
titlebar_background_color = None,
titlebar_text_color = None,
titlebar_font = None,
@@ -13152,7 +13002,6 @@ Window(title,
sbar_arrow_width = None,
sbar_frame_color = None,
sbar_relief = None,
- watermark = None,
metadata = None)
```
@@ -13167,7 +13016,7 @@ Parameter Descriptions:
| bool | auto_size_text | True if Elements in Window should be sized to exactly fir the length of text |
| bool | auto_size_buttons | True if Buttons in this Window should be sized to exactly fit the text on this. |
| (int, int) | 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. |
-| (int, int or None, None) or None | 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 |
+| (int, int) | location | (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen. |
| (int, int) | 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 |
| (int, int or (int, int),(int,int)) or int | 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) |
| (int, int) | margins | (left/right, top/bottom) Amount of pixels to leave inside the window's frame around the edges before your elements are shown. |
@@ -13206,7 +13055,6 @@ Parameter Descriptions:
| bool | 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 |
| bool | modal | If True then this window will be the only window a user can interact with until it is closed |
| bool | 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 |
-| bool | 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. |
| (str or None) | titlebar_background_color | If custom titlebar indicated by use_custom_titlebar, then use this as background color |
| (str or None) | titlebar_text_color | If custom titlebar indicated by use_custom_titlebar, then use this as text color |
| (str or (str, int[, str]) or None) | titlebar_font | If custom titlebar indicated by use_custom_titlebar, then use this as title font |
@@ -13220,7 +13068,6 @@ Parameter Descriptions:
| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
| str | 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 |
-| bool | watermark | If True, then turns on watermarking temporarily for ALL windows created from this point forward. See global settings doc for more info |
| Any | metadata | User metadata that can be set to ANYTHING |
### add_row
@@ -13309,19 +13156,16 @@ Sometimes, depending on the environment, the value returned does not include the
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.
```
-current_location(more_accurate = False, without_titlebar = False)
+current_location(more_accurate = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| bool | more_accurate | If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account |
-| bool | without_titlebar | If True, return location of top left of main window area without the titlebar (may be OS dependent?) |
+| bool | more_accurate | If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account |
| Tuple[(int or None), (int or None)] | **RETURN** | The x and y location in tuple form (x,y)
### ding
@@ -13454,7 +13298,7 @@ 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!):
+find_element is yypically 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"
@@ -13468,21 +13312,16 @@ Rememeber that this call will return None if no match is found which may cause y
checked for.
```
-find_element(key,
- silent_on_error = False,
- supress_guessing = None,
- supress_raise = None)
+find_element(key, silent_on_error = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
-| bool | silent_on_error | If True do not display popup nor print warning of key errors |
-| (bool or None) | supress_guessing | Override for the global key guessing setting. |
-| (bool or None) | supress_raise | Override for the global setting that determines if a key error should raise an exception |
-| Element or ErrorElement or 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
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
+| bool | silent_on_error | If True do not display popup nor print warning of key errors |
+| Element or Error Element or 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;
### find_element_with_focus
@@ -13725,15 +13564,15 @@ IMPORTANT - This method uses THREADS... this means you CANNOT make any PySimpleG
the function you provide with the exception of one function, Window.write_event_value.
```
-perform_long_operation(func, end_key = None)
+perform_long_operation(func, end_key)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | func | A lambda or a function name with no parms |
-| (Any or None) | end_key | Optional key that will be generated when the function returns |
+| Any | func | A lambda or a function name with no parms |
+| Any | end_key | The key that will be generated when the function returns |
| threading.Thread | **RETURN** | The id of the thread
### read
@@ -13878,21 +13717,6 @@ Parameter Descriptions:
|--|--|--|
| (int, int) | size | (width, height) tuple (int, int) of the desired window size in pixels |
-### set_size
-
-Changes the size of the window, if possible. You can also use the Window.size prooerty
-to set/get the size.
-
-```
-set_size(size)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| (int, int) | size | (width, height) of the desired window size |
-
### set_title
Change the title of the window
@@ -13947,71 +13771,17 @@ IMPORTANT - This method uses THREADS... this means you CANNOT make any PySimpleG
the function you provide with the exception of one function, Window.write_event_value.
```
-start_thread(func, end_key = None)
+start_thread(func, end_key)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | func | A lambda or a function name with no parms |
-| (Any or None) | end_key | Optional key that will be generated when the function returns |
+| Any | func | A lambda or a function name with no parms |
+| Any | end_key | The key that will be generated when the function returns |
| threading.Thread | **RETURN** | The id of the thread
-### timer_get_active_timers
-
-Returns a list of currently active timers for a window
-
-`timer_get_active_timers()`
-
-|Type|Name|Meaning|
-|---|---|---|
-|List[int]| **return** | List of timers for the window |
-
-### timer_start
-
-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.
-
-```
-timer_start(frequency_ms,
- key = "__TIMER EVENT__",
- repeating = True)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| int | frequency_ms | How often to generate timer events in milliseconds |
-| str or int or tuple or object | key | Key to be returned as the timer event |
-| bool | repeating | If True then repeat timer events until timer is explicitly stopped |
-| int | **RETURN** | Timer ID for the timer
-
-### timer_stop
-
-Stops a timer with a given ID
-
-```
-timer_stop(timer_id)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| int | timer_id | Timer ID of timer to stop |
-
-### timer_stop_all
-
-Stops all timers for THIS window
-
-```python
-timer_stop_all()
-```
-
### un_hide
Used to bring back a window that was previously hidden using the Hide method
@@ -14144,19 +13914,16 @@ Sometimes, depending on the environment, the value returned does not include the
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.
```
-CurrentLocation(more_accurate = False, without_titlebar = False)
+CurrentLocation(more_accurate = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| bool | more_accurate | If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account |
-| bool | without_titlebar | If True, return location of top left of main window area without the titlebar (may be OS dependent?) |
+| bool | more_accurate | If True, will use the window's geometry to get the topmost location with titlebar, menubar taken into account |
| Tuple[(int or None), (int or None)] | **RETURN** | The x and y location in tuple form (x,y)
### Disable
@@ -14198,7 +13965,7 @@ 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!):
+find_element is yypically 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"
@@ -14212,21 +13979,16 @@ Rememeber that this call will return None if no match is found which may cause y
checked for.
```
-Elem(key,
- silent_on_error = False,
- supress_guessing = None,
- supress_raise = None)
+Elem(key, silent_on_error = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
-| bool | silent_on_error | If True do not display popup nor print warning of key errors |
-| (bool or None) | supress_guessing | Override for the global key guessing setting. |
-| (bool or None) | supress_raise | Override for the global setting that determines if a key error should raise an exception |
-| Element or ErrorElement or 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
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
+| bool | silent_on_error | If True do not display popup nor print warning of key errors |
+| Element or Error Element or 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;
### Element
@@ -14241,7 +14003,7 @@ 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!):
+find_element is yypically 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"
@@ -14255,21 +14017,16 @@ Rememeber that this call will return None if no match is found which may cause y
checked for.
```
-Element(key,
- silent_on_error = False,
- supress_guessing = None,
- supress_raise = None)
+Element(key, silent_on_error = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
-| bool | silent_on_error | If True do not display popup nor print warning of key errors |
-| (bool or None) | supress_guessing | Override for the global key guessing setting. |
-| (bool or None) | supress_raise | Override for the global setting that determines if a key error should raise an exception |
-| Element or ErrorElement or 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
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
+| bool | silent_on_error | If True do not display popup nor print warning of key errors |
+| Element or Error Element or 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;
### Enable
@@ -14327,7 +14084,7 @@ 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!):
+find_element is yypically 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"
@@ -14341,21 +14098,16 @@ Rememeber that this call will return None if no match is found which may cause y
checked for.
```
-Find(key,
- silent_on_error = False,
- supress_guessing = None,
- supress_raise = None)
+Find(key, silent_on_error = False)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
-| bool | silent_on_error | If True do not display popup nor print warning of key errors |
-| (bool or None) | supress_guessing | Override for the global key guessing setting. |
-| (bool or None) | supress_raise | Override for the global setting that determines if a key error should raise an exception |
-| Element or ErrorElement or 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
+| str or int or tuple or object | key | Used with window.find_element and with return values to uniquely identify this element |
+| bool | silent_on_error | If True do not display popup nor print warning of key errors |
+| Element or Error Element or 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;
### FindElement
@@ -14643,11 +14395,6 @@ VisibilityChanged()
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.
-
```
pin(elem,
vertical_alignment = None,
@@ -14672,18 +14419,16 @@ Align an element or a row of elements to the bottom of the row that contains it
```
vbottom(elem_or_row,
expand_x = None,
- expand_y = None,
- background_color = None)
+ expand_y = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
-| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
-| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
-| str or None | background_color | Background color for container that is used by vcenter to do the alignment |
+| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
+| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
+| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
| Column or List[Column] | **RETURN** | A column element containing the provided element aligned to the bottom or list of elements (a row)
Align an element or a row of elements to the center of the row that contains it
@@ -14691,18 +14436,16 @@ Align an element or a row of elements to the center of the row that contains it
```
vcenter(elem_or_row,
expand_x = None,
- expand_y = None,
- background_color = None)
+ expand_y = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
-| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
-| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
-| str or None | background_color | Background color for container that is used by vcenter to do the alignment |
+| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
+| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
+| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
| Column or List[Column] | **RETURN** | A column element containing the provided element aligned to the center or list of elements (a row)
Align an element or a row of elements to the top of the row that contains it
@@ -14710,18 +14453,16 @@ Align an element or a row of elements to the top of the row that contains it
```
vtop(elem_or_row,
expand_x = None,
- expand_y = None,
- background_color = None)
+ expand_y = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
-| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
-| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
-| str or None | background_color | Background color for container that is used by vtop to do the alignment |
+| Element or List[Element] or Tuple[Element] | elem_or_row | the element or row of elements |
+| bool | expand_x | If True/False the value will be passed to the Column Elements used to make this feature |
+| bool | expand_y | If True/False the value will be passed to the Column Elements used to make this feature |
| Column or List[Column] | **RETURN** | A column element containing the provided element aligned to the top or list of elements (a row)
-----------------
@@ -14977,9 +14718,7 @@ Parameter Descriptions:
Returns a human-readable string of version numbers for:
Python version
-Platform (Win, Mac, Linux)
-Platform version (tuple with information from the platform module)
-PySimpleGUI Port (PySimpleGUI in this case)
+PySimpleGUI Port (tkinter in this case)
tkinter version
PySimpleGUI version
The location of the PySimpleGUI.py file
@@ -15050,9 +14789,7 @@ CalendarButton(button_text,
title = "Choose Date",
no_titlebar = True,
location = (None, None),
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15075,7 +14812,7 @@ Parameter Descriptions:
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15083,7 +14820,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| str | locale | defines the locale used to get day names |
| str | format | formats result using this strftime format |
-| int | begin_at_sunday_plus | Determines the left-most day in the display. 0=sunday, 1=monday, etc |
| List[str] | month_names | optional list of month names to use (should be 12 items) |
| List[str] | day_abbreviations | optional list of abbreviations to display as the day of week |
| str | title | Title shown on the date chooser window |
@@ -15091,8 +14827,6 @@ Parameter Descriptions:
| (int, int) | location | Location on the screen (x,y) to show the calendar popup window |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15111,9 +14845,7 @@ Cancel(button_text = "Cancel",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15128,7 +14860,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15136,8 +14868,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15161,11 +14891,8 @@ ColorChooserButton(button_text,
p = None,
key = None,
k = None,
- default_color = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15186,17 +14913,14 @@ Parameter Descriptions:
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | If True, then the return key will cause a the Listbox to generate an event |
| bool | focus | Determines if initial focus should go to this element. |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
| str or int or tuple or object | key | key for uniquely identify this element (for window.find_element) |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
-| str | default_color | Color to be sent to tkinter to use as the default color |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | User metadata that can be set to ANYTHING |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
This Button has been changed in how it works!!
@@ -15220,9 +14944,7 @@ Debug(button_text = "",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15237,7 +14959,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str | tooltip | text, that will appear when mouse hovers over the element |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15245,8 +14967,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
This is a special type of Button.
@@ -15277,9 +14997,7 @@ DummyButton(button_text,
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15299,7 +15017,7 @@ Parameter Descriptions:
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15307,8 +15025,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15327,9 +15043,7 @@ Exit(button_text = "Exit",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15344,7 +15058,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15352,8 +15066,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15375,9 +15087,7 @@ FileBrowse(button_text = "Browse",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15386,7 +15096,7 @@ Parameter Descriptions:
|--|--|--|
| str | button_text | text in the button (Default value = 'Browse') |
| str or (int, int) | target | key or (row,col) target for the button (Default value = (ThisRow, -1)) |
-| Tuple[(str, str), ...] | file_types | filter file types Default value = (("ALL Files", "*.* *"),). |
+| Tuple[(str, str), ...] | file_types | filter file types Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| | initial_folder | starting path for folders and files |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
@@ -15403,8 +15113,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15427,9 +15135,7 @@ FileSaveAs(button_text = "Save As...",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15438,7 +15144,7 @@ Parameter Descriptions:
|--|--|--|
| str | button_text | text in the button (Default value = 'Save As...') |
| str or (int, int) | target | key or (row,col) target for the button (Default value = (ThisRow, -1)) |
-| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). |
+| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| str | initial_folder | starting path for folders and files |
| bool | disabled | set disable state for element (Default = False) |
@@ -15456,8 +15162,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool) :return: returns a button | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
Allows browsing of multiple files. File list is returned as a single list with the delimiter defined using the files_delimiter parameter.
@@ -15482,9 +15186,7 @@ FilesBrowse(button_text = "Browse",
k = None,
visible = True,
files_delimiter = ";",
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15493,7 +15195,7 @@ Parameter Descriptions:
|--|--|--|
| str | button_text | text in the button (Default value = 'Browse') |
| str or (int, int) | target | key or (row,col) target for the button (Default value = (ThisRow, -1)) |
-| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). |
+| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| bool | disabled | set disable state for element (Default = False) |
| str | initial_folder | starting path for folders and files |
| str | tooltip | text, that will appear when mouse hovers over the element |
@@ -15511,8 +15213,6 @@ Parameter Descriptions:
| bool | visible | set initial visibility state of the Button |
| str | files_delimiter | String to place between files when multiple files are selected. Normally a ; |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15533,9 +15233,7 @@ FolderBrowse(button_text = "Browse",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15549,7 +15247,7 @@ Parameter Descriptions:
| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
| (int, int) or (None, None) or int | 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 |
| bool | auto_size_button | True if button size is determined by button text |
-| (str, str) or str | button_color | button color (foreground, background) |
+| | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
| bool | change_submits | If True, pressing Enter key submits window (Default = False) |
| bool | enable_events | Turns on the element specific events.(Default = False) |
@@ -15560,8 +15258,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | The Button created
```
@@ -15580,9 +15276,7 @@ Help(button_text = "Help",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15597,7 +15291,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| str | tooltip | text, that will appear when mouse hovers over the element |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15605,8 +15299,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15625,9 +15317,7 @@ No(button_text = "No",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15650,8 +15340,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15670,9 +15358,7 @@ OK(button_text = "OK",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15685,7 +15371,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| idk_yetReally | focus | if focus should be set to this |
@@ -15695,8 +15381,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15715,9 +15399,7 @@ Ok(button_text = "Ok",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15730,7 +15412,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| idk_yetReally | focus | if focus should be set to this |
@@ -15740,8 +15422,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15760,9 +15440,7 @@ Open(button_text = "Open",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15775,7 +15453,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| idk_yetReally | focus | if focus should be set to this |
@@ -15785,8 +15463,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15805,9 +15481,7 @@ Quit(button_text = "Quit",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15822,7 +15496,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15830,8 +15504,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15855,9 +15527,7 @@ RealtimeButton(button_text,
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15877,7 +15547,7 @@ Parameter Descriptions:
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -15885,8 +15555,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | Button created
```
@@ -15905,9 +15573,7 @@ Save(button_text = "Save",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15919,7 +15585,7 @@ Parameter Descriptions:
| (int, int) or (None, None) or int | 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 |
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| bool | disabled | set disable state for element (Default = False) |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
@@ -15930,8 +15596,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -15954,9 +15618,7 @@ SaveAs(button_text = "Save As...",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -15965,7 +15627,7 @@ Parameter Descriptions:
|--|--|--|
| str | button_text | text in the button (Default value = 'Save As...') |
| str or (int, int) | target | key or (row,col) target for the button (Default value = (ThisRow, -1)) |
-| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). |
+| Tuple[(str, str), ...] | file_types | Default value = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| str | initial_folder | starting path for folders and files |
| bool | disabled | set disable state for element (Default = False) |
@@ -15982,8 +15644,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -16002,9 +15662,7 @@ Submit(button_text = "Submit",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16017,7 +15675,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| bool | disabled | set disable state for element (Default = False) |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
| idk_yetReally | focus | if focus should be set to this |
@@ -16027,8 +15685,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
```
@@ -16047,9 +15703,7 @@ Yes(button_text = "Yes",
key = None,
k = None,
visible = True,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16064,7 +15718,7 @@ Parameter Descriptions:
| bool | disabled | set disable state for element (Default = False) |
| str | tooltip | text, that will appear when mouse hovers over the element |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = True) If True, then the return key will cause a the Listbox to generate an event |
| | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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 |
@@ -16072,8 +15726,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| bool | visible | set initial visibility state of the Button |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
## Button Functions No Longer Used (DO NOT USE)
@@ -16101,9 +15753,7 @@ RButton(button_text,
p = None,
key = None,
k = None,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16121,7 +15771,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | disabled | set disable state for element (Default = False) |
| idk_yetReally | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
@@ -16130,8 +15780,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| int | border_width | width of border around element |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | Button created
```
@@ -16154,9 +15802,7 @@ ReadButton(button_text,
p = None,
key = None,
k = None,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16174,7 +15820,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | disabled | set disable state for element (Default = False) |
| idk_yetReally | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
@@ -16183,8 +15829,6 @@ Parameter Descriptions:
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| int | border_width | width of border around element |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | Button created
DEPRICATED
@@ -16212,9 +15856,7 @@ CButton(button_text,
p = None,
key = None,
k = None,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16232,7 +15874,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | disabled | set disable state for element (Default = False) |
| idk_yetReally | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
@@ -16240,8 +15882,6 @@ Parameter Descriptions:
| str or int or tuple or object | key | key for uniquely identify this element (for window.find_element) |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
DEPRICATED
@@ -16269,9 +15909,7 @@ CloseButton(button_text,
p = None,
key = None,
k = None,
- metadata = None,
- expand_x = False,
- expand_y = False)
+ metadata = None)
```
Parameter Descriptions:
@@ -16289,7 +15927,7 @@ Parameter Descriptions:
| bool | auto_size_button | True if button size is determined by button text |
| (str, str) or str | button_color | button color (foreground, background) |
| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | 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 |
+| bool | bind_return_key | (Default = False) If True, then the return key will cause a the Listbox to generate an event |
| bool | disabled | set disable state for element (Default = False) |
| idk_yetReally | focus | if focus should be set to this |
| (int, int or (int, int),(int,int) or int,(int,int)) or ((int, int),int) or int | 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) |
@@ -16297,8 +15935,6 @@ Parameter Descriptions:
| str or int or tuple or object | key | key for uniquely identify this element (for window.find_element) |
| str or int or tuple or object | k | Same as the Key. You can use either k or key. Which ever is set will be used. |
| Any | metadata | Anything you want to store along with this button |
-| bool | expand_x | If True Element will expand in the Horizontal directions |
-| bool | expand_y | If True Element will expand in the Vertical directions |
| (Button) | **RETURN** | returns a button
-----------
@@ -16672,8 +16308,7 @@ cprint(args=*<1 or N object>,
window = None,
key = None,
justification = None,
- autoscroll = True,
- erase_all = False)
+ autoscroll = True)
```
Parameter Descriptions:
@@ -16736,13 +16371,13 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | title | text to display in titlebar of window |
+| str | title | text to display in eleemnt |
| int | current_value | current value |
-| int | max_value | max value of progress meter |
-| Any | *args | stuff to output as text in the window along with the meter |
-| str or int or tuple or object | key | Used to differentiate between multiple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
+| int | max_value | max value of QuickMeter |
+| Any | *args | stuff to output |
+| str or int or tuple or object | key | Used to differentiate between mutliple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
| str | orientation | 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') |
-| (str, str) or str | 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. |
+| Tuple(str, str) | bar_color | color of a bar line |
| (str, str) or str | button_color | button color (foreground, background) |
| (int, int) | size | (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) |
| int | border_width | width of border around element |
@@ -16790,13 +16425,13 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | title | text to display in titlebar of window |
+| str | title | text to display in eleemnt |
| int | current_value | current value |
-| int | max_value | max value of progress meter |
-| Any | *args | stuff to output as text in the window along with the meter |
-| str or int or tuple or object | key | Used to differentiate between multiple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
+| int | max_value | max value of QuickMeter |
+| Any | *args | stuff to output |
+| str or int or tuple or object | key | Used to differentiate between mutliple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
| str | orientation | 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') |
-| (str, str) or str | 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. |
+| Tuple(str, str) | bar_color | color of a bar line |
| (str, str) or str | button_color | button color (foreground, background) |
| (int, int) | size | (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) |
| int | border_width | width of border around element |
@@ -16848,39 +16483,34 @@ popup(args=*<1 or N object>,
relative_location = (None, None),
any_key_closes = False,
image = None,
- modal = True,
- button_justification = None,
- drop_whitespace = True)
+ modal = True)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
-| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
-| (str, str) or str | button_color | Color of the buttons shown (text color, button color) |
-| str | background_color | Window's background color |
-| str | text_color | text color |
-| int | button_type | 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. |
-| bool | auto_close | If True the window will automatically close |
-| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
-| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
-| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
-| str or bytes | icon | icon to display on the window. Same format as a Window call |
-| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
-| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
-| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
-| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
-| (int, int) | 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. |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | right_justify_buttons | If True then the buttons will be "pushed" to the right side of the Window |
-| str | button_justification | Speficies if buttons should be left, right or centered. Default is left justified |
-| bool | drop_whitespace | Controls is whitespace should be removed when wrapping text. Parameter is passed to textwrap.fill. Default is to drop whitespace (so popup remains backward compatible) |
+| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
+| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
+| (str, str) or None | button_color | Color of the buttons shown (text color, button color) |
+| str | background_color | Window's background color |
+| str | text_color | text color |
+| int | button_type | 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. |
+| bool | auto_close | If True the window will automatically close |
+| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
+| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
+| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
+| str or bytes | icon | icon to display on the window. Same format as a Window call |
+| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
+| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
+| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
+| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
+| (int, int) | 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. |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency
@@ -16903,8 +16533,7 @@ popup_animated(image_source,
time_between_frames = 0,
transparent_color = None,
title = "",
- icon = None,
- no_buffering = False)
+ icon = None)
```
Parameter Descriptions:
@@ -16926,7 +16555,6 @@ Parameter Descriptions:
| str | transparent_color | This color will be completely see-through in your window. Can even click through |
| str | title | Title that will be shown on the window |
| str or bytes | icon | Same as Window icon parameter. Can be either a filename or Base64 byte string. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO |
-| bool | no_buffering | If True then no buffering will be used for the GIF. May work better if you have a large animation |
| bool | **RETURN** | True if the window updated OK. False if the window was closed
Popup that closes itself after some time period
@@ -17072,26 +16700,6 @@ Parameter Descriptions:
| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
-Show an error message and as many additoinal lines of messages as you want.
-Will show the same error window as PySimpleGUI uses internally. Has a button to
-take the user to the line of code you called this popup from.
-If you include the Exception information in your messages, then it will be parsed and additional information
-will be in the window about such as the specific line the error itself occurred on.
-
-```
-popup_error_with_traceback(title,
- messages,
- emoji = None)
-```
-
-Parameter Descriptions:
-
-|Type|Name|Meaning|
-|--|--|--|
-| str | title | The title that will be shown in the popup's titlebar and in the first line of the window |
-| Any | *messages | A variable number of lines of messages you wish to show your user |
-| bytes | emoji | An optional BASE64 Encoded image to shows in the error window |
-
Display a calendar window, get the user's choice, return as a tuple (mon, day, year)
```
@@ -17109,9 +16717,6 @@ popup_get_date(start_mon = None,
locale = None,
month_names = None,
day_abbreviations = None,
- day_font = "TkFixedFont 9",
- mon_year_font = "TkFixedFont 10",
- arrow_font = "TkFixedFont 7",
modal = True)
```
@@ -17133,9 +16738,6 @@ Parameter Descriptions:
| bool | keep_on_top | If True the window will remain above all current windows |
| List[str] | month_names | optional list of month names to use (should be 12 items) |
| List[str] | day_abbreviations | optional list of abbreviations to display as the day of week |
-| str or tuple | day_font | Font and size to use for the calendar |
-| str or tuple | mon_year_font | Font and size to use for the month and year at the top |
-| str or tuple | arrow_font | Font and size to use for the arrow buttons |
| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| None or (int, int, int) | **RETURN** | Tuple containing (month, day, year) of chosen date or None if was cancelled
@@ -17180,7 +16782,7 @@ Parameter Descriptions:
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| bool | save_as | if True, the "save as" dialog is shown which will verify before overwriting |
| bool | multiple_files | if True, then allows multiple files to be selected that are returned with ';' between each filename |
-| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). |
+| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| bool | no_window | if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown |
| (int, int) | size | (width, height) of the InputText Element or Combo element if using history feature |
| (str, str) or str | button_color | Color of the button (text, background) |
@@ -17272,8 +16874,6 @@ popup_get_text(message,
location = (None, None),
relative_location = (None, None),
image = None,
- history = False,
- history_setting_filename = None,
modal = True)
```
@@ -17281,25 +16881,23 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | message | message displayed to user |
-| str | title | Window title |
-| str | default_text | default value to put into input area |
-| str | password_char | character to be shown instead of actually typed characters. WARNING - if history=True then can't hide passwords |
-| (int, int) | size | (width, height) of the InputText Element |
-| (str, str) or str | button_color | Color of the button (text, background) |
-| str | background_color | background color of the entire window |
-| str | text_color | color of the message text |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
-| (int, int) | 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. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | history | If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided |
-| str | history_setting_filename | Filename to use for the User Settings. Will store list of previous entries in this settings file |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| str | message | message displayed to user |
+| str | title | Window title |
+| str | default_text | default value to put into input area |
+| str | password_char | character to be shown instead of actually typed characters |
+| (int, int) | size | (width, height) of the InputText Element |
+| (str, str) or str | button_color | Color of the button (text, background) |
+| str | background_color | background color of the entire window |
+| str | text_color | color of the message text |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
+| (int, int) | 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. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Text entered or None if window was closed or cancel button clicked
Makes a "popup menu"
@@ -17652,7 +17250,7 @@ popup_quick_message(args=*<1 or N object>,
font = None,
no_titlebar = True,
grab_anywhere = False,
- keep_on_top = True,
+ keep_on_top = None,
location = (None, None),
relative_location = (None, None),
image = None,
@@ -17694,8 +17292,6 @@ popup_scrolled(args=*<1 or N object>,
background_color = None,
text_color = None,
yes_no = False,
- no_buttons = False,
- button_justification = "l",
auto_close = False,
auto_close_duration = None,
size = (None, None),
@@ -17716,28 +17312,26 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of items to display |
-| str | title | Title to display in the window. |
-| (str, str) or str | button_color | button color (foreground, background) |
-| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
-| bool | no_buttons | If True, no buttons will be shown. User will have to close using the "X" |
-| str | button_justification | How buttons should be arranged. l, c, r for Left, Center or Right justified |
-| bool | auto_close | if True window will close itself |
-| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
-| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
-| (int, int) | location | Location on the screen to place the upper left corner of the window |
-| (int, int) | 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. |
-| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str or bytes | image | Image to include at the top of the popup window |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
+| Any | *args | Variable number of items to display |
+| str | title | Title to display in the window. |
+| (str, str) or str | button_color | button color (foreground, background) |
+| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
+| bool | auto_close | if True window will close itself |
+| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
+| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
+| (int, int) | location | Location on the screen to place the upper left corner of the window |
+| (int, int) | 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. |
+| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str or bytes | image | Image to include at the top of the popup window |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Display Popup with Yes and No buttons
@@ -17799,8 +17393,6 @@ sprint(args=*<1 or N object>,
background_color = None,
text_color = None,
yes_no = False,
- no_buttons = False,
- button_justification = "l",
auto_close = False,
auto_close_duration = None,
size = (None, None),
@@ -17821,28 +17413,26 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of items to display |
-| str | title | Title to display in the window. |
-| (str, str) or str | button_color | button color (foreground, background) |
-| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
-| bool | no_buttons | If True, no buttons will be shown. User will have to close using the "X" |
-| str | button_justification | How buttons should be arranged. l, c, r for Left, Center or Right justified |
-| bool | auto_close | if True window will close itself |
-| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
-| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
-| (int, int) | location | Location on the screen to place the upper left corner of the window |
-| (int, int) | 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. |
-| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str or bytes | image | Image to include at the top of the popup window |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
+| Any | *args | Variable number of items to display |
+| str | title | Title to display in the window. |
+| (str, str) or str | button_color | button color (foreground, background) |
+| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
+| bool | auto_close | if True window will close itself |
+| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
+| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
+| (int, int) | location | Location on the screen to place the upper left corner of the window |
+| (int, int) | 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. |
+| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str or bytes | image | Image to include at the top of the popup window |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you
@@ -17855,8 +17445,6 @@ ScrolledTextBox(args=*<1 or N object>,
background_color = None,
text_color = None,
yes_no = False,
- no_buttons = False,
- button_justification = "l",
auto_close = False,
auto_close_duration = None,
size = (None, None),
@@ -17877,28 +17465,26 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of items to display |
-| str | title | Title to display in the window. |
-| (str, str) or str | button_color | button color (foreground, background) |
-| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
-| bool | no_buttons | If True, no buttons will be shown. User will have to close using the "X" |
-| str | button_justification | How buttons should be arranged. l, c, r for Left, Center or Right justified |
-| bool | auto_close | if True window will close itself |
-| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
-| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
-| (int, int) | location | Location on the screen to place the upper left corner of the window |
-| (int, int) | 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. |
-| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str or bytes | image | Image to include at the top of the popup window |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
+| Any | *args | Variable number of items to display |
+| str | title | Title to display in the window. |
+| (str, str) or str | button_color | button color (foreground, background) |
+| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
+| bool | auto_close | if True window will close itself |
+| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
+| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
+| (int, int) | location | Location on the screen to place the upper left corner of the window |
+| (int, int) | 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. |
+| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str or bytes | image | Image to include at the top of the popup window |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
## Popup Not PEP8 Compliant names
@@ -17934,39 +17520,34 @@ Popup(args=*<1 or N object>,
relative_location = (None, None),
any_key_closes = False,
image = None,
- modal = True,
- button_justification = None,
- drop_whitespace = True)
+ modal = True)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
-| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
-| (str, str) or str | button_color | Color of the buttons shown (text color, button color) |
-| str | background_color | Window's background color |
-| str | text_color | text color |
-| int | button_type | 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. |
-| bool | auto_close | If True the window will automatically close |
-| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
-| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
-| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
-| str or bytes | icon | icon to display on the window. Same format as a Window call |
-| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
-| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
-| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
-| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
-| (int, int) | 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. |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | right_justify_buttons | If True then the buttons will be "pushed" to the right side of the Window |
-| str | button_justification | Speficies if buttons should be left, right or centered. Default is left justified |
-| bool | drop_whitespace | Controls is whitespace should be removed when wrapping text. Parameter is passed to textwrap.fill. Default is to drop whitespace (so popup remains backward compatible) |
+| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
+| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
+| (str, str) or None | button_color | Color of the buttons shown (text color, button color) |
+| str | background_color | Window's background color |
+| str | text_color | text color |
+| int | button_type | 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. |
+| bool | auto_close | If True the window will automatically close |
+| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
+| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
+| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
+| str or bytes | icon | icon to display on the window. Same format as a Window call |
+| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
+| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
+| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
+| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
+| (int, int) | 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. |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency
@@ -17989,8 +17570,7 @@ PopupAnimated(image_source,
time_between_frames = 0,
transparent_color = None,
title = "",
- icon = None,
- no_buffering = False)
+ icon = None)
```
Parameter Descriptions:
@@ -18012,7 +17592,6 @@ Parameter Descriptions:
| str | transparent_color | This color will be completely see-through in your window. Can even click through |
| str | title | Title that will be shown on the window |
| str or bytes | icon | Same as Window icon parameter. Can be either a filename or Base64 byte string. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO |
-| bool | no_buffering | If True then no buffering will be used for the GIF. May work better if you have a large animation |
| bool | **RETURN** | True if the window updated OK. False if the window was closed
Display a Popup without a titlebar. Enables grab anywhere so you can move it
@@ -18246,7 +17825,7 @@ Parameter Descriptions:
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| bool | save_as | if True, the "save as" dialog is shown which will verify before overwriting |
| bool | multiple_files | if True, then allows multiple files to be selected that are returned with ';' between each filename |
-| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). |
+| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| bool | no_window | if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown |
| (int, int) | size | (width, height) of the InputText Element or Combo element if using history feature |
| (str, str) or str | button_color | Color of the button (text, background) |
@@ -18338,8 +17917,6 @@ PopupGetText(message,
location = (None, None),
relative_location = (None, None),
image = None,
- history = False,
- history_setting_filename = None,
modal = True)
```
@@ -18347,25 +17924,23 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | message | message displayed to user |
-| str | title | Window title |
-| str | default_text | default value to put into input area |
-| str | password_char | character to be shown instead of actually typed characters. WARNING - if history=True then can't hide passwords |
-| (int, int) | size | (width, height) of the InputText Element |
-| (str, str) or str | button_color | Color of the button (text, background) |
-| str | background_color | background color of the entire window |
-| str | text_color | color of the message text |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
-| (int, int) | 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. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | history | If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided |
-| str | history_setting_filename | Filename to use for the User Settings. Will store list of previous entries in this settings file |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| str | message | message displayed to user |
+| str | title | Window title |
+| str | default_text | default value to put into input area |
+| str | password_char | character to be shown instead of actually typed characters |
+| (int, int) | size | (width, height) of the InputText Element |
+| (str, str) or str | button_color | Color of the button (text, background) |
+| str | background_color | background color of the entire window |
+| str | text_color | color of the message text |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
+| (int, int) | 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. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Text entered or None if window was closed or cancel button clicked
Display a Popup without a titlebar. Enables grab anywhere so you can move it
@@ -18761,7 +18336,7 @@ PopupQuickMessage(args=*<1 or N object>,
font = None,
no_titlebar = True,
grab_anywhere = False,
- keep_on_top = True,
+ keep_on_top = None,
location = (None, None),
relative_location = (None, None),
image = None,
@@ -18803,8 +18378,6 @@ PopupScrolled(args=*<1 or N object>,
background_color = None,
text_color = None,
yes_no = False,
- no_buttons = False,
- button_justification = "l",
auto_close = False,
auto_close_duration = None,
size = (None, None),
@@ -18825,28 +18398,26 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of items to display |
-| str | title | Title to display in the window. |
-| (str, str) or str | button_color | button color (foreground, background) |
-| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
-| bool | no_buttons | If True, no buttons will be shown. User will have to close using the "X" |
-| str | button_justification | How buttons should be arranged. l, c, r for Left, Center or Right justified |
-| bool | auto_close | if True window will close itself |
-| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
-| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
-| (int, int) | location | Location on the screen to place the upper left corner of the window |
-| (int, int) | 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. |
-| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str or bytes | image | Image to include at the top of the popup window |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
+| Any | *args | Variable number of items to display |
+| str | title | Title to display in the window. |
+| (str, str) or str | button_color | button color (foreground, background) |
+| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
+| bool | auto_close | if True window will close itself |
+| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
+| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
+| (int, int) | location | Location on the screen to place the upper left corner of the window |
+| (int, int) | 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. |
+| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str or bytes | image | Image to include at the top of the popup window |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Popup that closes itself after some time period
@@ -19447,17 +19018,14 @@ then a default filename will be used.
After value has been deleted, the settings file is written to disk.
```
-delete_entry(key,
- section = None,
- silent_on_error = None)
+delete_entry(key, section = None)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | key | Setting to be deleted. Can be any valid dictionary key type (i.e. must be hashable) |
-| bool | silent_on_error | Determines if error should be shown. This parameter overrides the silent on error setting for the object. |
+| Any | key | Setting to be deleted. Can be any valid dictionary key type (i.e. must be hashable) |
### delete_file
@@ -19699,15 +19267,14 @@ then a default filename will be used.
After value has been deleted, the settings file is written to disk.
```
-user_settings_delete_entry(key, silent_on_error = None)
+user_settings_delete_entry(key)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | key | Setting to be saved. Can be any valid dictionary key type (hashable) |
-| bool | silent_on_error | Determines if an error popup should be shown if an error occurs. Overrides the silent onf effort setting from initialization |
+| Any | key | Setting to be saved. Can be any valid dictionary key type (hashable) |
Deltes the filename and path for your settings file. Either paramter can be optional.
If you don't choose a path, one is provided for you that is OS specific
@@ -19879,7 +19446,7 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | command | The command/file to execute. What you would type at a console to run a program or shell command. |
+| str | command | Filename to load settings from (and save to in the future) |
| Any | *args | Variable number of arguments that are passed to the program being started as command line parms |
| bool | wait | If True then wait for the subprocess to finish |
| str | cwd | Working directory to use when executing the subprocess |
@@ -19922,7 +19489,7 @@ Parameter Descriptions:
| str | folder_to_open | The path to open in the explorer program |
| (subprocess.Popen) or None | **RETURN** | Popen object
-Returns the first filename found in a traceback that is not the name of this file (__file__)
+Returns the first filename found in a traceback that is not the nsame of this file (__file__)
Used internally with the debugger for example.
```
@@ -19933,7 +19500,7 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | **RETURN** | filename of the caller, assumed to be the first non PySimpleGUI file
+| str | **RETURN** | filename of the caller, asseumed to be the first non PySimpleGUI file
Get the text results of a previously executed execute call
Returns a tuple of the strings (stdout, stderr)
@@ -20132,11 +19699,7 @@ set_options(icon = None,
sbar_width = None,
sbar_arrow_width = None,
sbar_frame_color = None,
- sbar_relief = None,
- alpha_channel = None,
- hide_window_when_creating = None,
- use_button_shortcuts = None,
- watermark_text = None)
+ sbar_relief = None)
```
Parameter Descriptions:
@@ -20206,10 +19769,6 @@ Parameter Descriptions:
| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
| str | 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 |
-| float | alpha_channel | Default alpha channel to be used on all windows |
-| bool | hide_window_when_creating | If True then alpha will be set to 0 while a window is made and moved to location indicated |
-| bool | use_button_shortcuts | If True then Shortcut Char will be used with Buttons |
-| str | watermark_text | Set the text that will be used if a window is watermarked |
| None | **RETURN** | None
### Non PEP8 versions
@@ -20290,11 +19849,7 @@ SetOptions(icon = None,
sbar_width = None,
sbar_arrow_width = None,
sbar_frame_color = None,
- sbar_relief = None,
- alpha_channel = None,
- hide_window_when_creating = None,
- use_button_shortcuts = None,
- watermark_text = None)
+ sbar_relief = None)
```
Parameter Descriptions:
@@ -20364,10 +19919,6 @@ Parameter Descriptions:
| int | sbar_arrow_width | Scrollbar width of the arrow on the scrollbar. It will potentially impact the overall width of the scrollbar |
| str | sbar_frame_color | Scrollbar Color of frame around scrollbar (available only on some ttk themes) |
| str | 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 |
-| float | alpha_channel | Default alpha channel to be used on all windows |
-| bool | hide_window_when_creating | If True then alpha will be set to 0 while a window is made and moved to location indicated |
-| bool | use_button_shortcuts | If True then Shortcut Char will be used with Buttons |
-| str | watermark_text | Set the text that will be used if a window is watermarked |
| None | **RETURN** | None
## Old Themes (Look and Feel) - Replaced by theme()
diff --git a/readme_creator/output/index.md b/readme_creator/output/index.md
index fd28ee9a..132e4406 100644
--- a/readme_creator/output/index.md
+++ b/readme_creator/output/index.md
@@ -1,7 +1,7 @@
+
+
+
+
## PyPI Statistics & Versions
| TK | TK 2.7 | Qt| WxPython | Web (Remi) |
@@ -57,7 +72,7 @@
# PySimpleGUI User's Manual
-## User Interfaces for Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces
+## Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces
## The Call Reference Section Moved to here
@@ -1595,39 +1610,34 @@ popup(args=*<1 or N object>,
relative_location = (None, None),
any_key_closes = False,
image = None,
- modal = True,
- button_justification = None,
- drop_whitespace = True)
+ modal = True)
```
Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
-| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
-| (str, str) or str | button_color | Color of the buttons shown (text color, button color) |
-| str | background_color | Window's background color |
-| str | text_color | text color |
-| int | button_type | 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. |
-| bool | auto_close | If True the window will automatically close |
-| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
-| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
-| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
-| str or bytes | icon | icon to display on the window. Same format as a Window call |
-| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
-| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
-| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
-| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
-| (int, int) | 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. |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | right_justify_buttons | If True then the buttons will be "pushed" to the right side of the Window |
-| str | button_justification | Speficies if buttons should be left, right or centered. Default is left justified |
-| bool | drop_whitespace | Controls is whitespace should be removed when wrapping text. Parameter is passed to textwrap.fill. Default is to drop whitespace (so popup remains backward compatible) |
+| Any | *args | Variable number of your arguments. Load up the call with stuff to see! |
+| str | title | Optional title for the window. If none provided, the first arg will be used instead. |
+| (str, str) or None | button_color | Color of the buttons shown (text color, button color) |
+| str | background_color | Window's background color |
+| str | text_color | text color |
+| int | button_type | 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. |
+| bool | auto_close | If True the window will automatically close |
+| int | auto_close_duration | time in seconds to keep window open before closing it automatically |
+| (str, str) or str | custom_text | A string or pair of strings that contain the text to display on the buttons |
+| bool | non_blocking | If True then will immediately return from the function without waiting for the user's input. |
+| str or bytes | icon | icon to display on the window. Same format as a Window call |
+| int | line_width | Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH |
+| str or Tuple[font_name, size, modifiers] | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True will not show the frame around the window and the titlebar across the top |
+| bool | grab_anywhere | If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too |
+| (int, int) | location | Location on screen to display the top left corner of window. Defaults to window centered on screen |
+| (int, int) | 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. |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| bool | any_key_closes | If True then will turn on return_keyboard_events for the window which will cause window to close as soon as any key is pressed. Normally the return key only will close the window. Default is false. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
The other output Popups are variations on parameters. Usually the button_type parameter is the primary one changed.
@@ -1658,8 +1668,6 @@ popup_scrolled(args=*<1 or N object>,
background_color = None,
text_color = None,
yes_no = False,
- no_buttons = False,
- button_justification = "l",
auto_close = False,
auto_close_duration = None,
size = (None, None),
@@ -1680,28 +1688,26 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| Any | *args | Variable number of items to display |
-| str | title | Title to display in the window. |
-| (str, str) or str | button_color | button color (foreground, background) |
-| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
-| bool | no_buttons | If True, no buttons will be shown. User will have to close using the "X" |
-| str | button_justification | How buttons should be arranged. l, c, r for Left, Center or Right justified |
-| bool | auto_close | if True window will close itself |
-| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
-| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
-| (int, int) | location | Location on the screen to place the upper left corner of the window |
-| (int, int) | 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. |
-| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
-| str | background_color | color of background |
-| str | text_color | color of the text |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| str or bytes | image | Image to include at the top of the popup window |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
-| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
+| Any | *args | Variable number of items to display |
+| str | title | Title to display in the window. |
+| (str, str) or str | button_color | button color (foreground, background) |
+| bool | yes_no | If True, displays Yes and No buttons instead of Ok |
+| bool | auto_close | if True window will close itself |
+| int or float | auto_close_duration | Older versions only accept int. Time in seconds until window will close |
+| (int, int) | size | (w,h) w=characters-wide, h=rows-high |
+| (int, int) | location | Location on the screen to place the upper left corner of the window |
+| (int, int) | 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. |
+| bool | non_blocking | if True the call will immediately return rather than waiting on user input |
+| str | background_color | color of background |
+| str | text_color | color of the text |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True, than can grab anywhere to move the window (Default = False) |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| str or bytes | image | Image to include at the top of the popup window |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| bool | no_sizegrip | If True no Sizegrip will be shown when there is no titlebar. It's only shown if there is no titlebar |
| str or None or TIMEOUT_KEY | **RETURN** | Returns text of the button that was pressed. None will be returned if user closed window with X
Typical usage:
@@ -1812,8 +1818,6 @@ popup_get_text(message,
location = (None, None),
relative_location = (None, None),
image = None,
- history = False,
- history_setting_filename = None,
modal = True)
```
@@ -1821,25 +1825,23 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | message | message displayed to user |
-| str | title | Window title |
-| str | default_text | default value to put into input area |
-| str | password_char | character to be shown instead of actually typed characters. WARNING - if history=True then can't hide passwords |
-| (int, int) | size | (width, height) of the InputText Element |
-| (str, str) or str | button_color | Color of the button (text, background) |
-| str | background_color | background color of the entire window |
-| str | text_color | color of the message text |
-| bytes or str | icon | filename or base64 string to be used for the window's icon |
-| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
-| bool | no_titlebar | If True no titlebar will be shown |
-| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
-| bool | keep_on_top | If True the window will remain above all current windows |
-| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
-| (int, int) | 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. |
-| str or bytes | image | Image to include at the top of the popup window |
-| bool | history | If True then enable a "history" feature that will display previous entries used. Uses settings filename provided or default if none provided |
-| str | history_setting_filename | Filename to use for the User Settings. Will store list of previous entries in this settings file |
-| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
+| str | message | message displayed to user |
+| str | title | Window title |
+| str | default_text | default value to put into input area |
+| str | password_char | character to be shown instead of actually typed characters |
+| (int, int) | size | (width, height) of the InputText Element |
+| (str, str) or str | button_color | Color of the button (text, background) |
+| str | background_color | background color of the entire window |
+| str | text_color | color of the message text |
+| bytes or str | icon | filename or base64 string to be used for the window's icon |
+| (str or (str, int[, str]) or None) | font | specifies the font family, size, etc. Tuple or Single string format 'name size styles'. Styles: italic * roman bold normal underline overstrike |
+| bool | no_titlebar | If True no titlebar will be shown |
+| bool | grab_anywhere | If True can click and drag anywhere in the window to move the window |
+| bool | keep_on_top | If True the window will remain above all current windows |
+| (int, int) | location | (x,y) Location on screen to display the upper left corner of window |
+| (int, int) | 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. |
+| str or bytes | image | Image to include at the top of the popup window |
+| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | Text entered or None if window was closed or cancel button clicked
```python
@@ -1897,7 +1899,7 @@ Parameter Descriptions:
| str | default_extension | If no extension entered by user, add this to filename (only used in saveas dialogs) |
| bool | save_as | if True, the "save as" dialog is shown which will verify before overwriting |
| bool | multiple_files | if True, then allows multiple files to be selected that are returned with ';' between each filename |
-| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). |
+| Tuple[Tuple[str,str]] | file_types | List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.* *"),). NOT avoilable on the MAC |
| bool | no_window | if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown |
| (int, int) | size | (width, height) of the InputText Element or Combo element if using history feature |
| (str, str) or str | button_color | Color of the button (text, background) |
@@ -2028,8 +2030,7 @@ popup_animated(image_source,
time_between_frames = 0,
transparent_color = None,
title = "",
- icon = None,
- no_buffering = False)
+ icon = None)
```
Parameter Descriptions:
@@ -2051,7 +2052,6 @@ Parameter Descriptions:
| str | transparent_color | This color will be completely see-through in your window. Can even click through |
| str | title | Title that will be shown on the window |
| str or bytes | icon | Same as Window icon parameter. Can be either a filename or Base64 byte string. For Windows if filename, it MUST be ICO format. For Linux, must NOT be ICO |
-| bool | no_buffering | If True then no buffering will be used for the GIF. May work better if you have a large animation |
| bool | **RETURN** | True if the window updated OK. False if the window was closed
***To close animated popups***, call PopupAnimated with `image_source=None`. This will close all of the currently open PopupAnimated windows.
@@ -2080,13 +2080,13 @@ Parameter Descriptions:
|Type|Name|Meaning|
|--|--|--|
-| str | title | text to display in titlebar of window |
+| str | title | text to display in eleemnt |
| int | current_value | current value |
-| int | max_value | max value of progress meter |
-| Any | *args | stuff to output as text in the window along with the meter |
-| str or int or tuple or object | key | Used to differentiate between multiple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
+| int | max_value | max value of QuickMeter |
+| Any | *args | stuff to output |
+| str or int or tuple or object | key | Used to differentiate between mutliple meters. Used to cancel meter early. Now optional as there is a default value for single meters |
| str | orientation | 'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical' / 'v') |
-| (str, str) or str | 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. |
+| Tuple(str, str) | bar_color | color of a bar line |
| (str, str) or str | button_color | button color (foreground, background) |
| (int, int) | size | (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE) |
| int | border_width | width of border around element |
@@ -3117,13 +3117,13 @@ You can learn more about these async / non-blocking windows toward the end of th
In Dec 2019 the function `change_look_and_feel` was replaced by `theme`. The concept remains the same, but a new group of function calls makes it a lot easier to manage colors and other settings.
-By default the PySimpleGUI color theme is now `Dark Blue 3`. Gone are the "system default" gray colors. If you want your window to be devoid of all colors so that the system chooses the colors (gray) for you, then set the theme to 'gray gray gray'. This tells PySimpleGUI that you're a boring person.... no no no... I'm **just kidding!**.... it just means you want PySimpleGUI to not set any colors so that the default colors provided by the OS/tkinter will be used. It's a memorable theme name. There are several with "default" in the name and it got confusing which was the full-on-add-no-color name, so 'gray gray gray' was added to make it easy to recall.
+By default the PySimpleGUI color theme is now `Dark Blue 3`. Gone are the "system default" gray colors. If you want your window to be devoid of all colors so that the system chooses the colors (gray) for you, then set the theme to 'SystemDefault1' or `Default1`.
-There are 154 themes available. You can preview these themes by calling `theme_previewer()` which will create a LARGE window displaying all of the color themes available.
+There are 130 themes available. You can preview these themes by calling `theme_previewer()` which will create a LARGE window displaying all of the color themes available.
-You can see the current available themes by calling `sg.theme_previewer()`. It creates a window that looked like this in June 2022:
+As of this writing, these are your available themes.
-
+
## Default is `Dark Blue 3`
@@ -3161,33 +3161,19 @@ The basic theme function call is `theme(theme_name)`. This sets the theme. Cal
If you want to get or modify any of the theme settings, you can do it with these functions that you will find detailed information about in the function definitions section at the bottom of the document. Each will return the current value if no parameter is used.
-You'll find a detailed list of the theme calls in the SDK Call Reference in this section:
-
-https://pysimplegui.readthedocs.io/en/latest/call%20reference/#themes
-
```python
-theme
-theme_add_new
theme_background_color
theme_border_width
theme_button_color
-theme_button_color_background
-theme_button_color_text
theme_element_background_color
theme_element_text_color
-theme_global
theme_input_background_color
theme_input_text_color
-theme_list
-theme_previewer
-theme_previewer_swatches
theme_progress_bar_border_width
theme_progress_bar_color
theme_slider_border_width
theme_slider_color
theme_text_color
-theme_text_element_background_color
-theme_use_custom_titlebar
```
These will help you get a list of available choices.
@@ -3802,6 +3788,17 @@ Your Window's layout is composed of lists of Elements. In addition to elements,
| vbottom | Vertically align element or row of elements to the bottom of the row |
| vcenter | Vertically align element or row of elements to the center of the row |
+- Text
+- Single Line Input
+- Buttons including these types:
+ - File Browse
+ - Folder Browse
+ - Calendar picker
+ - Date Chooser
+ - Read window
+ - Close window ("Button" & all shortcut buttons)
+ - Realtime
+
## Keys
***Keys are a super important concept to understand in PySimpleGUI.***
@@ -5483,20 +5480,20 @@ This is a blocking call so expect it to take a few seconds if you're fading the
# Global Settings
-There are multiple ways to customize PySimpleGUI. You can think of customizations as being done in a hierarchical manner
+There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
+
+**Mac Users** - You can't call `ChangeLookAndFeel` but you can call `SetOptions` with any sets of values you want. Nothing is being blocked or filtered.
+
+**These settings apply to all windows that are created in the future.**
+
+ `SetOptions`. The options and Element options will take precedence over these settings. Settings can be thought of as levels of settings with the window-level being the highest and the Element-level the lowest. Thus the levels are:
- Global
- Window
- Element
-The function `set_options` is used to change settings that will apply globally. If it's a setting that applies to Windows, then that setting will apply not only to Windows that you create, but also to popup Windows.
-
Each lower level overrides the settings of the higher level. Once settings have been changed, they remain changed for the duration of the program (unless changed again).
-After Global settings are settings made at Window level. These settings apply to a single `Window`. Fonts are a good example of a Windows-level setting. All elements within that `Window` will use the specified font.
-
-The lowest level of setting is the element-level. It will modify one particular element's setting. Again using font as an example, if you set the `font` parameter on a `Text` element, then only that specific `Text` element will use the specified font.
-
# Persistent windows (Window stays open after button click)
Early versions of PySimpleGUI did not have a concept of "persisent window". Once a user clicked a button, the window would close. After some time, the functionality was expanded so that windows remained open by default.
@@ -5528,7 +5525,7 @@ while True:
window.close()
```
-## read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
+## Read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
@@ -5653,8 +5650,8 @@ import PySimpleGUI as sg
import time
# ---------------- Create Form ----------------
-sg.theme('Black')
-sg.set_options(element_padding=(0, 0))
+sg.ChangeLookAndFeel('Black')
+sg.SetOptions(element_padding=(0, 0))
layout = [[sg.Text('')],
[sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
@@ -5795,7 +5792,7 @@ window['spin'].update(sz)
Remember this design pattern because you will use it OFTEN if you use persistent windows.
-It works as follows. The expression `window[key]` returns the Element object represented by the provided `key`. This element is then updated by calling it's `update` method. This is another example of Python's "chaining" feature. We could write this code using the long-form:
+It works as follows. The expresion `window[key]` returns the Element object represented by the provided `key`. This element is then updated by calling it's `update` method. This is another example of Python's "chaining" feature. We could write this code using the long-form:
text_element = window['text']
text_element.update(font=font)
@@ -7114,54 +7111,12 @@ There are a number of demo programs that show how to use UserSettings to create
If you're using the default path, remember that previous runs of your file may have old settings that are still in your settings file. It can get confusing when you've forgotten that you previously wrote a setting. Not seeing the filename can have drawbacks like this.
-Also, because the settings automatically save after every update, it can be easy to accidentally overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
+Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
To save your Python dictionary to a settings file, simply call `user_settings_write_new_dictionary(dict)`, passing in your dictionary as the parameter.
-------------------------
-# Timer API
-
-The Timer API calls are in version 4.61.0 that is currently only available on the PySimpleGUI GitHub. It has not been released to PyPI yet.
-
-## Do Not Use Sleeps In Your Event Loop...
-
-Instead of sleeping, you can request that an event be generated after some period of time. If you need to "Sleep for 3 seconds" as part of some operation, instead schedule a timer for 3 seconds. Your `window.read` call will return a value of `sg.TIMER_KEY` or `sg.EVENT_TIMER` (they are aliases and thus have the same value).
-
-## Timer API Calls
-
-These are the API calls that you'll use to manage timers:
-
-`window.timer_start` starts a timer
-
-`window.timer_stop` stops a single timer
-
-`window.timer_stop_all` stops all timers
-
-`window.timer_get_active_timers` returns a list of active timer IDs
-
-Example - start a 3 second timer that does not repeat:
-
-```python
-window.timer_start(3000, repeating=False) # start a 3-second timer
-```
-
-When this timer expires, you'll get an event `sg.EVENT_TIMER`. If you want to specify your own key to be returned, then use the `key` parameter:
-
-```python
-window.timer_start(3000, key='-MY TIMER KEY-', repeating=False)
-```
-
-See the call reference for the details of each call.
-
-## Timer Demo Programs
-
-Using the PySimpleGUI Demo Browser, search for `window.timer_` to find Demo Programs that use the Timer API calls.
-
-The program `Demo_WindowTimer.py` demonstrates both repeating and non-repeating timers as well as using custom keys. It's a simple set of API calls to use and the docstrings in combination with the Demo Programs should give you all you need to start using this capability.
-
----------------------------
-
# Extending PySimpleGUI
PySimpleGUI doesn't and can't provide every single setting available in the underlying GUI framework. Not all tkinter options are available for a `Text` Element. Same with PySimpleGUIQt and the other ports.
@@ -7420,18 +7375,6 @@ Process finished with exit code 1
---
-# Debug Output
-
-Be sure and check out the EasyPrint (Print) function described in the high-level API section. Leave your code the way it is, route your stdout and stderror to a scrolling window.
-
-For a fun time, add these lines to the top of your script
-
-```python
- import PySimpleGUI as sg
- print = sg.Print
-```
-This will turn all of your print statements into prints that display in a window on your screen rather than to the terminal.
-
# "Demo Programs" Applications
There are too many to list!!
@@ -7523,6 +7466,106 @@ Another also mentioned it may be helpful to add the "windowed" option so that a
This info was located on Reddit with the source traced back to:
https://github.com/pyinstaller/pyinstaller/issues/1350
+# Debug Output
+
+Be sure and check out the EasyPrint (Print) function described in the high-level API section. Leave your code the way it is, route your stdout and stderror to a scrolling window.
+
+For a fun time, add these lines to the top of your script
+
+```python
+ import PySimpleGUI as sg
+ print = sg.Print
+```
+This will turn all of your print statements into prints that display in a window on your screen rather than to the terminal.
+
+# Look and Feel
+
+You can change defaults and colors of a large number of things in PySimpleGUI quite easily.
+
+## `ChangleLookAndFeel`
+
+Want a quick way of making your windows look a LOT better? Try calling `ChangeLookAndFeel`. It will, in a single call, set various color values to widgets, background, text, etc.
+
+Or dial in the look and feel (and a whole lot more) that you like with the `SetOptions` function. You can change all of the defaults in one function call. One line of code to customize the entire GUI.
+
+```python
+ sg.ChangeLookAndFeel('GreenTan')
+```
+
+Valid look and feel values are currently:
+
+```python
+SystemDefault
+Reddit
+Topanga
+GreenTan
+Dark
+LightGreen
+Dark2
+Black
+Tan
+TanBlue
+DarkTanBlue
+DarkAmber
+DarkBlue
+Reds
+Green
+BluePurple
+Purple
+BlueMono
+GreenMono
+BrownBlue
+BrightColors
+NeutralBlue
+Kayak
+SandyBeach
+TealMono
+```
+
+The way this call actually works is that it calls `SetOptions` with a LOT of color settings. Here is the actual call that's made. As you can see lots of stuff is defined for you.
+
+```python
+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'],
+ 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'])
+```
+
+To see the latest list of color choices you can call `ListOfLookAndFeelValues()`
+
+You can also combine the `ChangeLookAndFeel` function with the `SetOptions` function to quickly modify one of the canned color schemes. Maybe you like the colors but was more depth to your bezels. You can dial in exactly what you want.
+
+**ObjToString**
+Ever wanted to easily display an objects contents easily? Use ObjToString to get a nicely formatted recursive walk of your objects.
+This statement:
+
+ print(sg.ObjToSting(x))
+
+And this was the output
+
+
+ abc = abc
+ attr12 = 12
+ c =
+ b =
+ a =
+ attr1 = 1
+ attr2 = 2
+ attr3 = three
+ attr10 = 10
+ attrx = x
+
+You'll quickly wonder how you ever coded without it.
+
---
# Known Issues
@@ -10121,37 +10164,6 @@ Test Harness and Settings Windows fit on small screens better
* Auto-correct file_types problems for Browse buttons. Automatically change the formatting from (str, str) to ((str, str),) and warns the user
* Docstring typo fixes for file_types parm
-## 4.60.1 PySimpleGUI 22-May-2022
-
-* A patch-release that fixes crash if `horizontal_scrollbar=True` when making a `Listbox` element
-
-## 4.60.2 PySimpleGUI 26-Jul-2022
-
-* Emergency Patch Release for Mac OS 12.3 and greater
- * Adds a PySimpleGUI Mac Control Panel Controlled patch that sets the Alpha channel to 0.99 by default for these users
- * Is a workaround for a bug that was introduced into Mac OS 12.3
-
-## 4.60.3 PySimpleGUI 27-Jul-2022
-
-* Emergency Patch Release for Mac OS 12.3 and greater
- * Fixed bug in Mac OS version check in yesterday's 4.60.2 release
-
-## 4.60.4 PySimpleGUI 10-Oct-2022
-
-* Dot release to quickly fix the Trinket detection which stopped working recently
-
-## 4.60.5 PySimpleGUI 21-May-2023
-
-* Mac fixes
- * Fix for Input Element not working in no-titlebar windows on MacOs 13.2.1
- * Change to the 0.99 Alpha fix made in 4.60.2. Now only applies patch when running on 8.6.12, regardless of Mac Control Panel setting in PySimpleGUI Global Settings. Removes the need for users to disable when upgrading tkinter.
-* Added Intelligent Upgrade Service - inform users when there are releases of PySimpleGUI that fix a problem that may be unique to their combination of components
-* Change to GitHub Issue GUI
- * Added checkbox for checking if running latest PyPI version
- * Recommended using Demo Browser to search Demo Programs
- * Use platform module to fill in the OS information field
-* SDK Help Window - changed all readthedocs links to use the PySimpleGUI.org hostname for better portability
-
## Code Condition
Make it run
diff --git a/readthedocs.yml b/readthedocs.yml
index d05298fb..cd810583 100644
--- a/readthedocs.yml
+++ b/readthedocs.yml
@@ -1,14 +1,8 @@
-version: 2
version: 2
-build:
- os: "ubuntu-22.04"
- tools:
- python: "3.11"
-
+
python:
- install:
- - requirements: docs/requirements.txt
+ version: 3.6
mkdocs:
- configuration: mkdocs.yml
\ No newline at end of file
+ configuration: mkdocs.yml
diff --git a/rtd_dropdown/404.html b/rtd_dropdown/404.html
new file mode 100644
index 00000000..a13ad467
--- /dev/null
+++ b/rtd_dropdown/404.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+