Changed button update method so can change only color if desired, tweaks to scrollable columns, fixed bug in size of OptionMeny element, initial check-in of image viewer demo by Jorj
This commit is contained in:
parent
30be0e3276
commit
c7a695d2a6
|
@ -0,0 +1,115 @@
|
|||
import PySimpleGUI as sg
|
||||
import os
|
||||
from PIL import Image, ImageTk
|
||||
import io
|
||||
"""
|
||||
Simple Image Browser based on PySimpleGUI
|
||||
--------------------------------------------
|
||||
There are some improvements compared to the PNG browser of the repository:
|
||||
1. Paging is cyclic, i.e. automatically wraps around if file index is outside
|
||||
2. Supports all file types that are valid PIL images
|
||||
3. Limits the maximum form size to the physical screen
|
||||
4. When selecting an image from the listbox, subsequent paging uses its index
|
||||
5. Paging performance improved significantly because of using PIL
|
||||
|
||||
Dependecies
|
||||
------------
|
||||
Python v3
|
||||
PIL
|
||||
"""
|
||||
# Get the folder containing the images from the user
|
||||
rc, folder = sg.GetPathBox('Image Browser', 'Image folder to open', default_path='')
|
||||
if not rc or not folder:
|
||||
sg.MsgBoxCancel('Cancelling')
|
||||
raise SystemExit()
|
||||
|
||||
# PIL supported image types
|
||||
img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
|
||||
|
||||
# get list of files in folder
|
||||
flist0 = os.listdir(folder)
|
||||
|
||||
# create sub list of image files (no sub folders, no wrong file types)
|
||||
fnames = [f for f in flist0 if os.path.isfile(os.path.join(folder,f)) and f.lower().endswith(img_types)]
|
||||
|
||||
num_files = len(fnames) # number of iamges found
|
||||
if num_files == 0:
|
||||
sg.MsgBox('No files in folder')
|
||||
raise SystemExit()
|
||||
|
||||
del flist0 # no longer needed
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# use PIL to read data of one image
|
||||
#------------------------------------------------------------------------------
|
||||
def get_img_data(f, maxsize = (1200, 850), first = False):
|
||||
"""Generate image data using PIL
|
||||
"""
|
||||
img = Image.open(f)
|
||||
img.thumbnail(maxsize)
|
||||
if first: # tkinter is inactive the first time
|
||||
bio = io.BytesIO()
|
||||
img.save(bio, format = "PNG")
|
||||
del img
|
||||
return bio.getvalue()
|
||||
return ImageTk.PhotoImage(img)
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
|
||||
# create the form that also returns keyboard events
|
||||
form = sg.FlexForm('Image Browser', return_keyboard_events=True,
|
||||
location=(0, 0), use_default_focus=False)
|
||||
|
||||
# make these 2 elements outside the layout as we want to "update" them later
|
||||
# initialize to the first file in the list
|
||||
filename = os.path.join(folder, fnames[0]) # name of first file in list
|
||||
image_elem = sg.Image(data = get_img_data(filename, first = True))
|
||||
filename_display_elem = sg.Text(filename, size=(80, 3))
|
||||
file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15,1))
|
||||
|
||||
# define layout, show and read the form
|
||||
col = [[filename_display_elem],
|
||||
[image_elem]]
|
||||
|
||||
col_files = [[sg.Listbox(values = fnames, select_submits=True, size=(60,30), key='listbox')],
|
||||
[sg.ReadFormButton('Next', size=(8,2)), sg.ReadFormButton('Prev',
|
||||
size=(8,2)), file_num_display_elem]]
|
||||
|
||||
layout = [[sg.Column(col_files), sg.Column(col)]]
|
||||
|
||||
form.Layout(layout) # Shows form on screen
|
||||
|
||||
# loop reading the user input and displaying image, filename
|
||||
i=0
|
||||
while True:
|
||||
# read the form
|
||||
button, values = form.Read()
|
||||
|
||||
# perform button and keyboard operations
|
||||
if button is None:
|
||||
break
|
||||
elif button in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'):
|
||||
i += 1
|
||||
if i >= num_files:
|
||||
i -= num_files
|
||||
filename = os.path.join(folder, fnames[i])
|
||||
elif button in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'):
|
||||
i -= 1
|
||||
if i < 0:
|
||||
i = num_files + i
|
||||
filename = os.path.join(folder, fnames[i])
|
||||
elif button in ('Read', ''): # something from the listbox
|
||||
f = values["listbox"][0] # selected filename
|
||||
filename = os.path.join(folder, f) # read this file
|
||||
i = fnames.index(f) # update running index
|
||||
else:
|
||||
filename = os.path.join(folder, fnames[i])
|
||||
|
||||
# update window with new image
|
||||
image_elem.Update(data=get_img_data(filename))
|
||||
# update window with filename
|
||||
filename_display_elem.Update(filename)
|
||||
# update page display
|
||||
file_num_display_elem.Update('File {} of {}'.format(i+1, num_files))
|
||||
|
||||
|
|
@ -866,9 +866,10 @@ class Button(Element):
|
|||
_my_windows.Decrement()
|
||||
return
|
||||
|
||||
def Update(self, new_text, button_color=(None, None)):
|
||||
def Update(self, new_text=None, button_color=(None, None)):
|
||||
try:
|
||||
self.TKButton.configure(text=new_text)
|
||||
if new_text is not None:
|
||||
self.TKButton.configure(text=new_text)
|
||||
if button_color != (None, None):
|
||||
self.TKButton.config(foreground=button_color[0], background=button_color[1])
|
||||
except:
|
||||
|
@ -1618,6 +1619,7 @@ def BuildResults(form, initialize_only, top_level_form):
|
|||
form.ReturnValuesDictionary = {}
|
||||
form.ReturnValuesList = []
|
||||
BuildResultsForSubform(form, initialize_only, top_level_form)
|
||||
top_level_form.LastButtonClicked = None
|
||||
return form.ReturnValues
|
||||
|
||||
def BuildResultsForSubform(form, initialize_only, top_level_form):
|
||||
|
@ -1801,7 +1803,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form)
|
||||
col_frame.TKFrame.update()
|
||||
if element.Size == (None, None):
|
||||
col_frame.canvas.config(width=col_frame.TKFrame.winfo_reqwidth(),height=col_frame.TKFrame.winfo_reqheight())
|
||||
col_frame.canvas.config(width=col_frame.TKFrame.winfo_reqwidth()/2,height=col_frame.TKFrame.winfo_reqheight()/2)
|
||||
else:
|
||||
col_frame.canvas.config(width=element.Size[0],height=element.Size[1])
|
||||
|
||||
|
@ -1971,11 +1973,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
|
||||
max_line_len = max([len(str(l)) for l in element.Values])
|
||||
if auto_size_text is False: width=element_size[0]
|
||||
else: width = max_line_len
|
||||
element.TKStringVar = tk.StringVar()
|
||||
default = element.DefaultValue if element.DefaultValue else element.Values[0]
|
||||
element.TKStringVar.set(default)
|
||||
element.TKOptionMenu = tk.OptionMenu(tk_row_frame, element.TKStringVar ,*element.Values )
|
||||
element.TKOptionMenu.config(highlightthickness=0, font=font)
|
||||
element.TKOptionMenu = tk.OptionMenu(tk_row_frame, element.TKStringVar ,*element.Values)
|
||||
element.TKOptionMenu.config(highlightthickness=0, font=font, width=width )
|
||||
element.TKOptionMenu.config(borderwidth=border_depth)
|
||||
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
|
||||
element.TKOptionMenu.configure(background=element.BackgroundColor)
|
||||
|
|
Loading…
Reference in New Issue