I'm an absolute beginner in python and trying to build a script/programm that searches images from a folder by their name (meaning that it would need a search bar) and displays these image in the same window.
Think of it as sort of a phonebook where I have stored 100 names and pictures and I want to type in "Henry" to see Henry's picture.
On my search for a software that achieves this, I've come accross something similar:
# img_viewer.py
import PySimpleGUI as sg
import os.path
# First the window layout in 2 columns
file_list_column = [
[
sg.Text("Image Folder"),
sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"),
sg.FolderBrowse(),
],
[
sg.Listbox(
values=[], enable_events=True, size=(40, 20), key="-FILE LIST-"
)
],
]
# For now will only show the name of the file that was chosen
image_viewer_column = [
[sg.Text("Choose an image from list on left:")],
[sg.Text(size=(40, 1), key="-TOUT-")],
[sg.Image(key="-IMAGE-")],
]
# ----- Full layout -----
layout = [
[
sg.Column(file_list_column),
sg.VSeperator(),
sg.Column(image_viewer_column),
]
]
window = sg.Window("Image Viewer", layout)
# Run the Event Loop
while True:
event, values = window.read()
if event == "Exit" or event == sg.WIN_CLOSED:
break
# Folder name was filled in, make a list of files in the folder
if event == "-FOLDER-":
folder = values["-FOLDER-"]
try:
# Get list of files in folder
file_list = os.listdir(folder)
except:
file_list = []
fnames = [
f
for f in file_list
if os.path.isfile(os.path.join(folder, f))
and f.lower().endswith((".png", ".gif"))
]
window["-FILE LIST-"].update(fnames)
elif event == "-FILE LIST-": # A file was chosen from the listbox
try:
filename = os.path.join(
values["-FOLDER-"], values["-FILE LIST-"][0]
)
window["-TOUT-"].update(filename)
window["-IMAGE-"].update(filename=filename)
except:
pass
window.close()
This is almost perfect, but I would need to implement a search bar instead of clicking through the names as I will have ~20.000 entries and clicking through them is just not viable.
Any idea how I would go about achieving this?
Just one file after filtered not so good, My suggestion
Add one more sg.InputText() as filter for filename.ext
Event loop
Event for New holder or new filter
Get list of filenames of all files in folder, maybe also filtered by PNG, GIF.
Build new list to update 'sg.Listbox` if filter_string.lower() in filename_lower()
Event for listbox
Update sg.Image by clicked filename in listbox.
Update - Working sample code
from pathlib import Path
from io import BytesIO
from PIL import Image
import PySimpleGUI as sg
def update_listbox(listbox_element, folder, extension, substring):
path = Path(folder)
filter_ = substring.lower()
lst = []
if folder != '' and path.is_dir():
files = list(path.glob("*.*"))
lst = [file for file in files if file.suffix.lower() in extension
and filter_ in str(file).lower() and file.is_file()]
listbox_element.update(lst)
def update_image(image_element, filename):
im = Image.open(filename)
w, h = size_of_image
scale = max(im.width/w, im.height/h)
if scale <= 1:
image_element.update(filename=filename)
else:
im = im.resize((int(im.width/scale), int(im.height/scale)),
resample=Image.CUBIC)
with BytesIO() as output:
im.save(output, format="PNG")
data = output.getvalue()
image_element.update(data=data)
sg.theme('Dark')
sg.set_options(font=('Courier New', 11))
w, h = size_of_image = (700, 600)
layout_top = [
[sg.InputText(enable_events=True, key='-FOLDER-'),
sg.FolderBrowse('Browse', size=(7, 1), enable_events=True)],
[sg.InputText(enable_events=True, key='-FILTER-'),
sg.Button('Search', size=(7, 1))],
]
layout_bottom = [
[sg.Listbox([], size=(52, 30), enable_events=True,
select_mode=sg.LISTBOX_SELECT_MODE_SINGLE, key='-LISTBOX-')],
]
layout_left = [
[sg.Column(layout_top, pad=(0, 0))],
[sg.Column(layout_bottom, pad=(0, 0))],
]
layout_right = [[sg.Image(background_color='green', key='-IMAGE-')]]
layout = [
[sg.Column(layout_left), sg.Column(layout_right, pad=(0, 0), size=(w+15, h+15), background_color='blue', key='-COLUMN-')],
]
window = sg.Window("PNG/GIF Viewer", layout, finalize=True)
window['-IMAGE-'].Widget.pack(fill='both', expand=True)
window['-IMAGE-'].Widget.master.pack(fill='both', expand=True)
window['-IMAGE-'].Widget.master.master.pack(fill='both', expand=True)
window['-COLUMN-'].Widget.pack_propagate(0)
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
# print(event, values)
if event in ('-FOLDER-', '-FILTER-', 'Search'):
update_listbox(window['-LISTBOX-'], values['-FOLDER-'],
('.png', '.gif'), values['-FILTER-'])
elif event == '-LISTBOX-':
lst = values['-LISTBOX-']
if lst != []:
update_image(window['-IMAGE-'], values['-LISTBOX-'][0])
window.close()
Related
I am using PySimpleGui's one-line progress meter to show the files processed while my main function is running. It is working for the most part, however when I change the parameter from value of 1000 to my variable total_files it just flickers and never stays on screen. It's only when I keep the parameter to a value of 1000 does the screen stay put...but I want to just show the progress of the true amount of files processed.
For example, I have 8 files I am processing as a test. I want the progress bar to stay on the screen and just show those 8 files processed. Does anyone know what I'm doing wrong?
Documentation on progress meter:
https://www.pysimplegui.org/en/latest/#progress-meters
for i in range(1,total_files):
sg.one_line_progress_meter('Loading...', i+1, 1000, 'key','Files Processed', orientation="horizontal")
Below is my code:
import PySimpleGUI as sg, pandas as pd, os, time
from pathlib import (
Path,
)
def convert_to_csv(input_folder, output_folder, dataframe2, dataframe3):
start = time.time()
# Parentsupplierbrand mapping file. Change the filepath to where the file is stored on your computer.
df2 = pd.read_csv(rf"{dataframe2}", sep="|")
# KCS Section Codes mapping file. Change the filepath to where the file is stored on your computer.
df3 = pd.read_excel(rf"{dataframe3}")
# loop through only text files in the input folder and convert data
for files in os.listdir(input_folder):
if files.endswith(".txt"):
df1 = pd.read_csv(rf"{input_folder}/{files}", sep="\t", encoding="latin-1")
df1["BrandName"] = df1["Comp_Brand"].apply(
xlookup, args=(df2["BrandID"], df2["BrandName"])
)
# map columns to the desired headers
df1.rename(
columns={
"BrandName": "Competitor_Name",
"Comp_PN": "Competitor_PartNumber",
"CQ_Brand": "AAIA_Code",
"CQ_PN": "PartNumber",
},
inplace=True,
)
remove_columns = df1.loc[
:, ~df1.columns.isin(["Comp_Brand", "CQ_Desc", "PartID"])
]
new_columns = [
"Competitor_Name",
"Competitor_PartNumber",
"AAIA_Code",
"PartNumber",
]
table_output = remove_columns[new_columns]
# below code for constructing file name convention
kcs_section_codes = df3.values.tolist()
stringtwo = table_output.loc[0][2] # stringtwo is the AAIA_Code
for code in kcs_section_codes:
if code[0] == stringtwo:
# stringone is the matching value under BrandName in the KCS_Section_Codes file
# by looking up AAIA_Code from the initial file in the BrandCode column from the KCS_Section_Codes file
stringone = "".join(
e for e in code[1] if e.isalnum()
) # replace any character that is not a letter or number with an empty character.
filename = rf"{stringone}-{stringtwo}_Interchanges.txt"
outputfile = rf"{output_folder}/{filename}"
table_output.to_csv(
outputfile,
sep="\t",
index=False,
columns=[
"Competitor_Name",
"Competitor_PartNumber",
"AAIA_Code",
"PartNumber",
],
)
# progress bar
total_files = sum([len(files) for r, d, files in os.walk(output_folder)])
for i in range(1, total_files):
sg.one_line_progress_meter(
"Loading...",
i + 1,
1000,
"key",
"Files Processed",
orientation="horizontal",
)
# code below for returning stats of main function in a popup window
total_files = sum([len(files) for r, d, files in os.walk(output_folder)])
end = time.time()
result_time = end - start
time_formatted = time.strftime("%H:%M:%S", time.gmtime(result_time))
sg.popup_no_titlebar(
f"Done! :)\nTotal Files Processed: {total_files}\nExecution Time (hh:mm:ss): {time_formatted}"
)
def xlookup(lookup_value, lookup_array, return_array, if_not_found: str = ""):
match_value = return_array.loc[lookup_array == lookup_value]
if match_value.empty:
return f'"{lookup_value}" not found!' if if_not_found == "" else if_not_found
else:
return match_value.tolist()[0]
def is_valid_path(filepath):
if filepath and Path(filepath).exists():
return True
sg.popup_error("Filepath not correct")
return False
def gui():
sg.theme("DarkBlue3") # Add a touch of color
# All the stuff inside your window.
layout = [
[
sg.Text("Input Folder: "),
sg.Input(key="-IN-"),
sg.FolderBrowse(),
],
[sg.Text("Output Folder: "), sg.Input(key="-OUT-"), sg.FolderBrowse()],
[
sg.Text("Data Mapping File: Parent Supplier Brand"),
sg.Input(key="-DF2-"),
sg.FileBrowse(),
],
[
sg.Text("Data Mapping File: KCS Section Codes"),
sg.Input(key="-DF3-"),
sg.FileBrowse(),
],
[sg.Exit(), sg.Button("Convert to CSV")],
]
# Create the Window
window = sg.Window("Data Conversion", layout)
# Event Loop to process "events" and get the "values" of the inputs
while True:
event, values = window.read()
if (
event == sg.WIN_CLOSED or event == "Cancel"
): # if user closes window or clicks cancel
break
if event in (sg.WIN_CLOSED, "Exit"):
break
if (
event == "Convert to CSV"
): # if user clicks covert to csv button then call convert_to_csv function using inputs
if (is_valid_path(values["-IN-"])) and (is_valid_path(values["-OUT-"])):
convert_to_csv(
input_folder=values["-IN-"],
output_folder=values["-OUT-"],
dataframe2=values["-DF2-"],
dataframe3=values["-DF3-"],
)
window.close()
if __name__ == "__main__":
gui()
Following code update the progressbar without any time delay, so it will show in short time and reach the maximum value immediately, then the window for progressbar closed.
for i in range(1, total_files):
sg.one_line_progress_meter(
"Loading...",
i + 1,
1000,
"key",
"Files Processed",
orientation="horizontal",
)
Reduce your code to ask question, it will help people to help.
Demo code:
from time import sleep
import PySimpleGUI as sg
from threading import Thread
def job(window):
window.write_event_value("Update", 0)
for i in range(1, 11):
sleep(0.2) # Simulate each step in the job
window.write_event_value("Update", i) # Cannot update GUI not in the main thread
window.write_event_value("Done", None)
sg.theme("DarkBlue3")
layout = [[sg.Button("Submit"), sg.Button("Exit")],]
window = sg.Window("Title", layout)
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, "Exit"):
break
elif event == "Submit":
thread = Thread(target=job, args=(window, ), daemon=True)
thread.start()
elif event == "Update":
i = values[event]
sg.one_line_progress_meter("Loading...", i, 10, "key", "Files Processed", orientation="horizontal")
elif event == "Done":
print('Job done !')
window.close()
I have a window with a tree element that shows files and folders when I enter a path. I need this tree to clear if I enter a new path. At the moment the tree appends the files/folders from each path I enter. Is there a way to refresh the tree element before entering new information into it?
My code is similar to this:
import PySimpleGUI as sg
import os
starting_path = os.getcwd()
treedata = sg.TreeData()
folder_icon = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABnUlEQVQ4y8WSv2rUQRSFv7vZgJFFsQg2EkWb4AvEJ8hqKVilSmFn3iNvIAp21oIW9haihBRKiqwElMVsIJjNrprsOr/5dyzml3UhEQIWHhjmcpn7zblw4B9lJ8Xag9mlmQb3AJzX3tOX8Tngzg349q7t5xcfzpKGhOFHnjx+9qLTzW8wsmFTL2Gzk7Y2O/k9kCbtwUZbV+Zvo8Md3PALrjoiqsKSR9ljpAJpwOsNtlfXfRvoNU8Arr/NsVo0ry5z4dZN5hoGqEzYDChBOoKwS/vSq0XW3y5NAI/uN1cvLqzQur4MCpBGEEd1PQDfQ74HYR+LfeQOAOYAmgAmbly+dgfid5CHPIKqC74L8RDyGPIYy7+QQjFWa7ICsQ8SpB/IfcJSDVMAJUwJkYDMNOEPIBxA/gnuMyYPijXAI3lMse7FGnIKsIuqrxgRSeXOoYZUCI8pIKW/OHA7kD2YYcpAKgM5ABXk4qSsdJaDOMCsgTIYAlL5TQFTyUIZDmev0N/bnwqnylEBQS45UKnHx/lUlFvA3fo+jwR8ALb47/oNma38cuqiJ9AAAAAASUVORK5CYII='
file_icon = b'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABU0lEQVQ4y52TzStEURiHn/ecc6XG54JSdlMkNhYWsiILS0lsJaUsLW2Mv8CfIDtr2VtbY4GUEvmIZnKbZsY977Uwt2HcyW1+dTZvt6fn9557BGB+aaNQKBR2ifkbgWR+cX13ubO1svz++niVTA1ArDHDg91UahHFsMxbKWycYsjze4muTsP64vT43v7hSf/A0FgdjQPQWAmco68nB+T+SFSqNUQgcIbN1bn8Z3RwvL22MAvcu8TACFgrpMVZ4aUYcn77BMDkxGgemAGOHIBXxRjBWZMKoCPA2h6qEUSRR2MF6GxUUMUaIUgBCNTnAcm3H2G5YQfgvccYIXAtDH7FoKq/AaqKlbrBj2trFVXfBPAea4SOIIsBeN9kkCwxsNkAqRWy7+B7Z00G3xVc2wZeMSI4S7sVYkSk5Z/4PyBWROqvox3A28PN2cjUwinQC9QyckKALxj4kv2auK0xAAAAAElFTkSuQmCC'
def add_files_in_folder(parent, dirname):
files = os.listdir(dirname)
for f in files:
fullname = os.path.join(dirname, f)
if os.path.isdir(fullname): # if it's a folder, add folder and recurse
treedata.Insert(parent, fullname, f, values=[], icon=folder_icon)
add_files_in_folder(fullname, fullname)
else:
treedata.Insert(parent, fullname, f, values=[os.stat(fullname).st_size], icon=file_icon)
def main_window():
column_one = sg.Column([
[sg.Tree(data=treedata,
headings=['Size', ],
auto_size_columns=True,
select_mode=sg.TABLE_SELECT_MODE_EXTENDED,
num_rows=20,
col0_width=40,
key='-TREE-',
show_expanded=False,
enable_events=True,
expand_x=True,
expand_y=True,
), ],
[sg.B('Open', k='-OPEN-'), sg.B('Add', k='-ADD-')],
])
layout = [
[sg.T('Some text')],
[sg.HorizontalSeparator()],
[sg.T('Select the files / folders')],
[column_one],
[sg.B('Cancel', k='-EXIT-')]
]
return sg.Window('some window', layout, resizable=True, finalize=True)
window = main_window()
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, '-EXIT-'):
break
print(event, values)
if event == '-OPEN-':
starting_path = sg.popup_get_folder('Folder to display')
add_files_in_folder('', starting_path)
window['-TREE-'].update(values=treedata)
window.close()
Any help is appreciated!
Following code demo how to create/clear/append data to treedata for Table element. Here all item added as children of root ''.
import PySimpleGUI as sg
def add_data(treedata, offset):
default = [[str((i+1)*(j+offset+1)) for i in range(9)] for j in range(9)]
for i, value in enumerate(default):
treedata.insert('', i+offset+1, i+offset+1, value)
return treedata
treedata = sg.TreeData()
treedata = add_data(treedata, 0)
index = 10
layout = [
[sg.Tree(
data=treedata,
headings=[str(i+1) for i in range(9)],
col0_heading='9x9',
col0_width=5,
num_rows=20,
key='-TREE-',
)],
[sg.Button('Clear'), sg.Button('Reset'), sg.Button('Append')],
]
window = sg.Window('Title', layout, finalize=True)
tree = window['-TREE-']
tree.Widget.column('#0', anchor='e')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == 'Clear':
treedata = sg.TreeData()
tree.update(values=treedata)
index = 0
elif event == 'Reset':
treedata = add_data(sg.TreeData(), 0)
tree.update(values=treedata)
index = 10
elif event == 'Append':
treedata = add_data(treedata, index)
tree.update(values=treedata)
index += 10
window.close()
I made a little barcode making GUI project for fun and when the "clear" function takes place it deletes the text in the "SaveAs" button. All other buttons have no issues with this and I was trying to avoid putting a line of code for each key to clear. I made some minor changes to the code before pasting it here so I know that the if len(values['Area']) > 0: window.perform_long_operation(lambda: get_barcode(),'Saved Pop') needs to be updated as of now this would always be true. I forgot when I added the combo box and set a default value you this would be true. Also if anyone could tell me why I have to have "lambda" above although I'm not passing a parameter?
Update 10:45 CT - I compiled the program and and the program is not saving correctly/not at all. If I put in a name like "test1" it should be saved as test1.pdf at the location I specified. When I go to the location the file does not exist but if I search the C drive it shows up but it cannot be located almost as if it is deleted the moment it is created. This only happens when I compile the program.
import PySimpleGUI as sg
import string
pixel_size = [64,128,192,256]
tab1_layout = [
[sg.Text('Area Letter:', size=(28,1)), sg.Combo(list(string.ascii_uppercase[:]), default_value= 'A',key='Area')],
[sg.Text('Start Number Range:', size=(28,1)), sg.InputText(key='start_number')],
[sg.Text('End Number Range:', size=(28,1)), sg.InputText(key='end_number')],
]
tab2_layout = [
[sg.Text('Single Barcode ABC123:', size=(28,1)), sg.InputText(key='single_bc')],
[sg.Text('Number of Single Barcode Replicas:', size=(28,1)), sg.InputText(default_text= 1,key='number_of_barcodes')],
]
layout = [
[sg.Text('Barcode Font Size in Pixels'), sg.Combo(pixel_size, default_value=64, s=(15,22), enable_events=True, readonly=True, key='PIXEL')],
[sg.TabGroup([[sg.Tab('Range of Barcodes', tab1_layout), sg.Tab('Single Barcodes', tab2_layout)]])],
[[sg.Input(key = 'input_loc'), sg.SaveAs(target= 'input_loc' , default_extension= '.pdf')]],
[sg.Submit(),sg.Button('Clear'), sg.Exit(),]
]
def get_barcode():
print('get barcode')
window = sg.Window('Barcode Maker', layout, font=("Helvetica", 12))
def clear_input():
for key in values:
window[key]('')
window['Area']('A')
window['PIXEL'](64)
window['number_of_barcodes'](1)
return None
while True:
event, values = window.read(timeout = 10)
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Clear':
clear_input()
if event == 'Submit':
save_location = values['input_loc']
if len(values['Area']) > 0:
window.perform_long_operation(lambda: get_barcode(),'Saved Pop')
elif len(values['single_bc']) >=1:
bc_size = values['PIXEL']
single_code = values['single_bc'].upper()
replicas = values['number_of_barcodes']
replicas = int(replicas)
start_rep = 0
while start_rep < replicas:
layout_borb1.add(Barcode(data=single_code, type=BarcodeType.CODE_128, width=Decimal(bc_size), height=Decimal(bc_size),))
with open(save_location, 'wb') as pdf_file_handle:
PDF.dumps(pdf_file_handle, doucment)
start_rep +=1
clear_input()```
Following code in your function clear_input clear the value of all the elements which with the key in values.
for key in values:
window[key]('')
The key of element in values not only Input, Combo elements, also Tab, TabGroup and Button elements.
>>> values
{'PIXEL': 64, 'Area': 'A', 'start_number': '', 'end_number': '', 'single_bc': '', 'number_of_barcodes': '1', 0: 'Range of Barcodes', 'input_loc': '', 'Save As...': ''}
The key in values include the key of button Save As..., that's why the text of this button also cleared.
There should be a rule to specify which elements to be cleared, like
for key, element in window.key_dict.items():
if isinstance(element, (sg.Input, sg.Combo)):
element.update(value='')
Using lambda to define a function without arguments is almost the same as the function name.
window.perform_long_operation(get_barcode,'Saved Pop')
If possible, reduce your code to only with related issues and an executable code, like
import PySimpleGUI as sg
import string
pixel_size = [64,128,192,256]
tab1_layout = [
[sg.Text('Area Letter:', size=(28,1)), sg.Combo(list(string.ascii_uppercase[:]), default_value= 'A',key='Area')],
[sg.Text('Start Number Range:', size=(28,1)), sg.InputText(key='start_number')],
[sg.Text('End Number Range:', size=(28,1)), sg.InputText(key='end_number')],
]
tab2_layout = [
[sg.Text('Single Barcode ABC123:', size=(28,1)), sg.InputText(key='single_bc')],
[sg.Text('Number of Single Barcode Replicas:', size=(28,1)), sg.InputText(default_text= 1,key='number_of_barcodes')],
]
layout = [
[sg.Text('Barcode Font Size in Pixels'), sg.Combo(pixel_size, default_value=64, s=(15,22), enable_events=True, readonly=True, key='PIXEL')],
[sg.TabGroup([[sg.Tab('Range of Barcodes', tab1_layout), sg.Tab('Single Barcodes', tab2_layout)]])],
[[sg.Input(key = 'input_loc'), sg.SaveAs(target= 'input_loc' , default_extension= '.pdf')]],
[sg.Submit(),sg.Button('Clear'), sg.Exit(),]
]
def get_barcode():
print("get bar_code function called")
window = sg.Window('Barcode Maker', layout, font=("Helvetica", 12))
def clear_input():
for key, element in window.key_dict.items():
if isinstance(element, (sg.Input, sg.Combo)):
element.update(value='')
window['Area']('A')
window['PIXEL'](64)
window['number_of_barcodes'](1)
return
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Clear':
clear_input()
elif event == 'Submit':
save_location = values['input_loc']
if len(values['Area']) > 0:
window.perform_long_operation(get_barcode,'Saved Pop')
clear_input()
elif event == 'Saved Pop':
print("get_barcode complete")
window.close()
For some conditions, like element.taget==(None, None) or element.Key is not None, "chooser" Buttons will hold the information of selection in the dictionary values which returned from window.read().
"chooser" Buttons with any one of following button_type:
BUTTON_TYPE_COLOR_CHOOSER
BUTTON_TYPE_SAVEAS_FILE
BUTTON_TYPE_BROWSE_FILE
BUTTON_TYPE_BROWSE_FILES
BUTTON_TYPE_BROWSE_FOLDER
BUTTON_TYPE_CALENDAR_CHOOSER
Function SaveAs defined as a Button element with file_types=FILE_TYPES_ALL_FILES.
I have to make a program to teach children multipliers, this is the core code of the assignment.
#include <stdio.h>
#define MIN 1
#define MAXINDEX 10
#define MAXTABLE 10
#define STEP 1
void main(void)
{
int i,j ;
for (j = MIN; j <MAXTABLE; j += STEP) {
for (i = MIN; i <= MAXINDEX; i += STEP)
printf(“%3d * %3d = %3d\n”, i, j, i*j);
printf(“\n---------------\n\n”);
}
for (i = MIN; i <= MAXINDEX; i += STEP)
printf(“%3d * %3d = %3d\n”, i, MAXTABLE, i*MAXTABLE);
}
After I have to rewrite it to a next generation language so I designed to write it in python.
Like this
j=1
i=1
for j in range(1,11):
for i in range(1,11):
print('%3d * %3d =%3d' % (i, j, i *j))
if j!=10:
print("\n---------------\n")
else:
print("\n")
And after that I have to make a UI for it so this image is what I designed to do like this This is the design of me
Since I just study python for 3 days, so I try my best to write this:
import PySimpleGUI as sg
import os.path
def Corecode():
j=1
i=1
for j in range(1,11):
for i in range(1,11):
print('%3d * %3d =%3d' % (i, j, i *j))
if j!=10:
print("\n---------------\n")
else:
print("\n")
from PySimpleGUI.PySimpleGUI import R, Image, Multiline
showrobot_column = [
[sg.Image('E:\img\robot.png',size = (300,300))],
],
show_Textbox_selectbox = [
[sg.Multiline(size=(50,20),key='-def-')],
[sg.Listbox(values=['a','b','c','d'], enable_events=True, size=(50,20), key="")]
]
layout = [
[sg.Column(showrobot_column),
sg.VSeparator(),
sg.Column(show_Textbox_selectbox)
]
]
window = sg.Window("First Test",layout)
while True:
event, value = window.read()
if event == sg.WIN_CLOSED:
break
window.close()
I designed to make it like a robot is talking and let the children interact by buttonBut, but I find out I can't insert the image, and also I can't find a way to print the Multiplier table by the core code that on the front, so someone can help me to finish the code or tell me why the sg.image get error. TY
Try this,
import PySimpleGUI as sg
def corecode(base):
return ("\n"+"-"*13+"\n").join([f'{i+1:>2d} * {base:>2d} = {(i+1)*base:>3d}' for i in range(10)])
sg.theme('DarkBlue3')
sg.set_options(font=("Courier New", 12))
showrobot_column = [
[sg.Image('E:/img/robot.png', size = (300, 300))],
]
list_values = [f'{i+1:>2d}' for i in range(10)]
show_Textbox_selectbox = [
[sg.Multiline(size=(15, 20), expand_y=True, key='-MULTILINE-')],
[sg.Listbox(values=list_values, enable_events=True, size=(15, 10), key="-LISTBOX-")],
]
layout = [
[sg.Column(showrobot_column),
sg.VSeparator(),
sg.Column(show_Textbox_selectbox),],
]
window = sg.Window("First Test", layout, finalize=True)
multiline = window['-MULTILINE-']
multiline.update(value=corecode(1))
listbox = window['-LISTBOX-']
listbox.update(set_to_index=0)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == '-LISTBOX-':
base = int(values[event][0])
multiline.update(value=corecode(base))
window.close()
This is a shameless small tweak to Jason's answer (choose his as it's correct).
Wanted to include a couple of capabilities that may be helpful to some. One is that almost all elements have an initial value that you can set in your layout instead of finalizing it and then setting them. It reduces code.
I'm also including a "Trinket" embedded in this answer as a test. This way you can run the example on this StackOverflow page.
import PySimpleGUI as sg
def corecode(base):
return ("\n"+"-"*13+"\n").join([f'{i+1:>2d} * {base:>2d} = {(i+1)*base:>3d}' for i in range(10)])
sg.theme('DarkBlue3')
list_values = [f'{i+1:>2d}' for i in range(10)]
show_Textbox_selectbox = [[sg.Multiline(default_text=corecode(1), size=(15, 20), expand_y=True, key='-MULTILINE-')],
[sg.Listbox(values=list_values, default_values=[list_values[0]], enable_events=True, size=(15, 10), key="-LISTBOX-")]]
layout = [
[sg.Image(sg.EMOJI_BASE64_HAPPY_THUMBS_UP), sg.VSeparator(), sg.Column(show_Textbox_selectbox)]
]
window = sg.Window("First Test", layout, font='Courier 12')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event == '-LISTBOX-':
base = int(values[event][0])
window['-MULTILINE-'].update(value=corecode(base))
window.close()
Here is a link to the Trinket should it not embed correctly - https://trinket.io/pygame/d59ef3b352
<iframe src="https://trinket.io/embed/pygame/d59ef3b352" width="100%" height="600" frameborder="0" marginwidth="0" marginheight="0" allowfullscreen></iframe>
I am trying to dynamically assign keys using pysimplegui. A simple example is updating a text field when a folder is selected.
When the layout contains two elements in each row, the text field updates correctly. However adding a third element results in the text box not updating.
import PySimpleGUI as sg
layout = []
elements = ["one", "two", "three"]
for element in elements:
text = f"text_{element}"
folder = f"folder_{element}"
check = f"check_{element}"
layout.append([sg.FolderBrowse(key = folder), sg.Text(key = text, size=(50, 1))])
#layout.append([sg.FolderBrowse(key = folder), sg.Text(key = text, size=(50, 1)), sg.Checkbox(element, key=check)])
#layout.append([sg.FolderBrowse(key = folder), sg.Text(key = text, size=(50, 1)), sg.Text(element, key=check)])
layout.append([sg.Button('Show'), sg.Cancel()])
window = sg.Window("GUI", layout)
while(True):
event, values = window.read()
if event in (None, 'Cancel'):
break
print(values)
for element in elements:
text = f"text_{element}"
folder = f"folder_{element}"
values[text] = values[folder]
window.close()
Thanks to MikefromPSG, using the target param worked:
layout.append([sg.FolderBrowse(target = text), sg.Text(key = text, size=(50, 1)), sg.Checkbox(element, key=check)])