Realtime Buttons

New type of button, the realtime button, allows buttons to be 'polled'.  They register as pushed as soon as the button goes down versus click which happens when you release the button.
This commit is contained in:
MikeTheWatchGuy 2018-07-30 23:50:52 -04:00
parent 9386ec8fc1
commit e4a9f80489
1 changed files with 45 additions and 27 deletions

View File

@ -112,10 +112,11 @@ def RGB(red,green,blue): return '#%02x%02x%02x' % (red,green,blue)
#todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality #todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality
#uncomment this line and indent to go back to using Enums #uncomment this line and indent to go back to using Enums
# class ButtonType(Enum): # class ButtonType(Enum):
BROWSE_FOLDER = 1 BUTTON_TYPE_BROWSE_FOLDER = 1
BROWSE_FILE = 2 BUTTON_TYPE_BROWSE_FILE = 2
CLOSES_WIN = 5 BUTTON_TYPE_CLOSES_WIN = 5
READ_FORM = 7 BUTTON_TYPE_READ_FORM = 7
BUTTON_TYPE_REALTIME = 9
# ------------------------- Element types ------------------------- # # ------------------------- Element types ------------------------- #
# class ElementType(Enum): # class ElementType(Enum):
@ -216,7 +217,7 @@ class InputText(Element):
for row in MyForm.Rows: for row in MyForm.Rows:
for element in row.Elements: for element in row.Elements:
if element.Type == ELEM_TYPE_BUTTON: if element.Type == ELEM_TYPE_BUTTON:
if element.BType == CLOSES_WIN or element.BType == READ_FORM: if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack() element.ButtonCallBack()
return return
@ -410,7 +411,7 @@ class Multiline(Element):
for row in MyForm.Rows: for row in MyForm.Rows:
for element in row.Elements: for element in row.Elements:
if element.Type == ELEM_TYPE_BUTTON: if element.Type == ELEM_TYPE_BUTTON:
if element.BType == CLOSES_WIN or element.BType == READ_FORM: if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack() element.ButtonCallBack()
return return
@ -569,7 +570,7 @@ class Output(Element):
# Button Class # # Button Class #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class Button(Element): class Button(Element):
def __init__(self, button_type=CLOSES_WIN, target=(None, None), button_text='', file_types=(("ALL Files", "*.*"),), image_filename=None, image_size=(None,None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None): def __init__(self, button_type=BUTTON_TYPE_CLOSES_WIN, target=(None, None), button_text='', file_types=(("ALL Files", "*.*"),), image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
''' '''
Button Element - Specifies all types of buttons Button Element - Specifies all types of buttons
:param button_type: :param button_type:
@ -601,6 +602,14 @@ class Button(Element):
super().__init__(ELEM_TYPE_BUTTON, scale, size, font=font) super().__init__(ELEM_TYPE_BUTTON, scale, size, font=font)
return return
def ButtonReleaseCallBack(self, parm):
r, c = self.Position
self.ParentForm.Results[r][c] = False # mark this button's location in results
def ButtonPressCallBack(self, parm):
r, c = self.Position
self.ParentForm.Results[r][c] = True # mark this button's location in results
# ------- Button Callback ------- # # ------- Button Callback ------- #
def ButtonCallBack(self): def ButtonCallBack(self):
global _my_windows global _my_windows
@ -622,15 +631,15 @@ class Button(Element):
else: else:
strvar = None strvar = None
filetypes = [] if self.FileTypes is None else self.FileTypes filetypes = [] if self.FileTypes is None else self.FileTypes
if self.BType == BROWSE_FOLDER: if self.BType == BUTTON_TYPE_BROWSE_FOLDER:
folder_name = tk.filedialog.askdirectory() # show the 'get folder' dialog box folder_name = tk.filedialog.askdirectory() # show the 'get folder' dialog box
try: try:
strvar.set(folder_name) strvar.set(folder_name)
except: pass except: pass
elif self.BType == BROWSE_FILE: elif self.BType == BUTTON_TYPE_BROWSE_FILE:
file_name = tk.filedialog.askopenfilename(filetypes=filetypes) # show the 'get file' dialog box file_name = tk.filedialog.askopenfilename(filetypes=filetypes) # show the 'get file' dialog box
strvar.set(file_name) strvar.set(file_name)
elif self.BType == CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window
# first, get the results table built # first, get the results table built
# modify the Results table in the parent FlexForm object # modify the Results table in the parent FlexForm object
r,c = self.Position r,c = self.Position
@ -644,7 +653,7 @@ class Button(Element):
if self.ParentForm.NonBlocking: if self.ParentForm.NonBlocking:
self.ParentForm.TKroot.destroy() self.ParentForm.TKroot.destroy()
_my_windows.NumOpenWindows -= 1 * (_my_windows.NumOpenWindows != 0) # decrement if not 0 _my_windows.NumOpenWindows -= 1 * (_my_windows.NumOpenWindows != 0) # decrement if not 0
elif self.BType == READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE
# first, get the results table built # first, get the results table built
# modify the Results table in the parent FlexForm object # modify the Results table in the parent FlexForm object
r,c = self.Position r,c = self.Position
@ -658,7 +667,7 @@ class Button(Element):
for row in MyForm.Rows: for row in MyForm.Rows:
for element in row.Elements: for element in row.Elements:
if element.Type == ELEM_TYPE_BUTTON: if element.Type == ELEM_TYPE_BUTTON:
if element.BType == CLOSES_WIN or element.BType == READ_FORM: if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack() element.ButtonCallBack()
return return
@ -1041,49 +1050,52 @@ def T(display_text, scale=(None, None), size=(None, None), auto_size_text=None,
# ------------------------- FOLDER BROWSE Element lazy function ------------------------- # # ------------------------- FOLDER BROWSE Element lazy function ------------------------- #
def FolderBrowse(target=(ThisRow, -1), button_text='Browse', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def FolderBrowse(target=(ThisRow, -1), button_text='Browse', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BROWSE_FOLDER, target=target, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_BROWSE_FOLDER, target=target, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- FILE BROWSE Element lazy function ------------------------- # # ------------------------- FILE BROWSE Element lazy function ------------------------- #
def FileBrowse(target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), button_text='Browse', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def FileBrowse(target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), button_text='Browse', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BROWSE_FILE, target, button_text=button_text, file_types=file_types, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_BROWSE_FILE, target, button_text=button_text, file_types=file_types, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- # # ------------------------- SUBMIT BUTTON Element lazy function ------------------------- #
def Submit(button_text='Submit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def Submit(button_text='Submit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- OK BUTTON Element lazy function ------------------------- # # ------------------------- OK BUTTON Element lazy function ------------------------- #
def OK(button_text='OK', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def OK(button_text='OK', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- YES BUTTON Element lazy function ------------------------- # # ------------------------- YES BUTTON Element lazy function ------------------------- #
def Ok(button_text='Ok', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def Ok(button_text='Ok', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- CANCEL BUTTON Element lazy function ------------------------- # # ------------------------- CANCEL BUTTON Element lazy function ------------------------- #
def Cancel(button_text='Cancel', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None): def Cancel(button_text='Cancel', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
# ------------------------- QUIT BUTTON Element lazy function ------------------------- # # ------------------------- QUIT BUTTON Element lazy function ------------------------- #
def Quit(button_text='Quit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None): def Quit(button_text='Quit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
# ------------------------- YES BUTTON Element lazy function ------------------------- # # ------------------------- YES BUTTON Element lazy function ------------------------- #
def Yes(button_text='Yes', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def Yes(button_text='Yes', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- NO BUTTON Element lazy function ------------------------- # # ------------------------- NO BUTTON Element lazy function ------------------------- #
def No(button_text='No', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None): def No(button_text='No', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color) return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # # ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
# this is the only button that REQUIRES button text field # this is the only button that REQUIRES button text field
def SimpleButton(button_text, image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None): def SimpleButton(button_text, image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(CLOSES_WIN, image_filename=image_filename, image_size=image_size,image_subsample=image_subsample, button_text=button_text,border_width=border_width, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font) return Button(BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, button_text=button_text, border_width=border_width, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
# ------------------------- GENERIC BUTTON Element lazy function ------------------------- # # ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
# this is the only button that REQUIRES button text field # this is the only button that REQUIRES button text field
def ReadFormButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None): def ReadFormButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(READ_FORM, image_filename=image_filename, image_size=image_size,image_subsample=image_subsample,border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font) return Button(BUTTON_TYPE_READ_FORM, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def RealtimeButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_REALTIME, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
#------------------------------------------------------------------------------------------------------# #------------------------------------------------------------------------------------------------------#
# ------- FUNCTION InitializeResults. Sets up form results matrix ------- # # ------- FUNCTION InitializeResults. Sets up form results matrix ------- #
@ -1177,6 +1189,7 @@ def BuildResults(form):
elif element.Type == ELEM_TYPE_BUTTON: elif element.Type == ELEM_TYPE_BUTTON:
if results[row_num][col_num] is True: if results[row_num][col_num] is True:
button_pressed_text = element.ButtonText button_pressed_text = element.ButtonText
if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons
results[row_num][col_num] = False results[row_num][col_num] = False
elif element.Type == ELEM_TYPE_INPUT_COMBO: elif element.Type == ELEM_TYPE_INPUT_COMBO:
value=element.TKStringVar.get() value=element.TKStringVar.get()
@ -1321,10 +1334,15 @@ def ConvertFlexToTK(MyFlexForm):
if bc == 'Random' or bc == 'random': if bc == 'Random' or bc == 'random':
bc = GetRandomColorPair() bc = GetRandomColorPair()
border_depth = element.BorderWidth border_depth = element.BorderWidth
if btype != BUTTON_TYPE_REALTIME:
tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height,command=element.ButtonCallBack, justify=tk.LEFT, foreground=bc[0], background=bc[1], bd=border_depth) tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height,command=element.ButtonCallBack, justify=tk.LEFT, foreground=bc[0], background=bc[1], bd=border_depth)
else:
tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, foreground=bc[0], background=bc[1], bd=border_depth)
tkbutton.bind('<ButtonRelease-1>', element.ButtonReleaseCallBack)
tkbutton.bind('<ButtonPress-1>', element.ButtonPressCallBack)
element.TKButton = tkbutton # not used yet but save the TK button in case element.TKButton = tkbutton # not used yet but save the TK button in case
wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels
if element.ImageFilename: if element.ImageFilename: # if button has an image on it
photo = tk.PhotoImage(file=element.ImageFilename) photo = tk.PhotoImage(file=element.ImageFilename)
if element.ImageSize != (None, None): if element.ImageSize != (None, None):
width, height = element.ImageSize width, height = element.ImageSize
@ -1336,7 +1354,7 @@ def ConvertFlexToTK(MyFlexForm):
tkbutton.image = photo tkbutton.image = photo
tkbutton.configure(wraplength=wraplen+10, font=font) # set wrap to width of widget tkbutton.configure(wraplength=wraplen+10, font=font) # set wrap to width of widget
tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
if not focus_set and btype == CLOSES_WIN: if not focus_set and btype == BUTTON_TYPE_CLOSES_WIN:
focus_set = True focus_set = True
element.TKButton.bind('<Return>', element.ReturnKeyHandler) element.TKButton.bind('<Return>', element.ReturnKeyHandler)
element.TKButton.focus_set() element.TKButton.focus_set()