From 77cd722615efb431c1ff12a6e95fcf95e6d5a8c1 Mon Sep 17 00:00:00 2001 From: AustinTurney Date: Fri, 19 May 2023 09:59:34 -0400 Subject: [PATCH] Changes to all boxes to allow user to change window/taskbar icon --- easygui/boxes/button_box.py | 18 ++++++++---- easygui/boxes/choice_box.py | 15 ++++++---- easygui/boxes/derived_boxes.py | 45 ++++++++++++++++------------- easygui/boxes/diropen_box.py | 3 +- easygui/boxes/fileopen_box.py | 3 +- easygui/boxes/filesave_box.py | 3 +- easygui/boxes/fillable_box.py | 3 +- easygui/boxes/multi_fillable_box.py | 24 +++++++++------ easygui/boxes/text_box.py | 16 ++++++---- 9 files changed, 82 insertions(+), 48 deletions(-) diff --git a/easygui/boxes/button_box.py b/easygui/boxes/button_box.py index 53545ac..f9d632b 100644 --- a/easygui/boxes/button_box.py +++ b/easygui/boxes/button_box.py @@ -71,7 +71,8 @@ def buttonbox(msg="", default_choice=None, cancel_choice=None, callback=None, - run=True): + run=True, + icon = None): """ Display a message, a title, an image, and a set of buttons. The buttons are defined by the members of the choices argument. @@ -99,7 +100,8 @@ def buttonbox(msg="", images=images, default_choice=default_choice, cancel_choice=cancel_choice, - callback=callback) + callback=callback, + icon = icon) if not run: return bb else: @@ -117,7 +119,7 @@ class ButtonBox(object): library can be used (wx, qt) without breaking anything for the user. """ - def __init__(self, msg, title, choices, images, default_choice, cancel_choice, callback): + def __init__(self, msg, title, choices, images, default_choice, cancel_choice, callback, icon): """ Create box object Parameters @@ -144,7 +146,7 @@ def __init__(self, msg, title, choices, images, default_choice, cancel_choice, c """ self.callback = callback - self.ui = GUItk(msg, title, choices, images, default_choice, cancel_choice, self.callback_ui) + self.ui = GUItk(msg, title, choices, images, default_choice, cancel_choice, self.callback_ui, icon) def run(self): """ Start the ui """ @@ -224,7 +226,7 @@ def to_string(self, something): class GUItk(object): """ This is the object that contains the tk root object""" - def __init__(self, msg, title, choices, images, default_choice, cancel_choice, callback): + def __init__(self, msg, title, choices, images, default_choice, cancel_choice, callback, icon): """ Create ui object Parameters @@ -272,6 +274,8 @@ def __init__(self, msg, title, choices, images, default_choice, cancel_choice, c self.configure_root(title) + self.config_icon(icon) + self.create_msg_widget(msg) self.create_images_frame() @@ -398,6 +402,10 @@ def configure_root(self, title): self.boxRoot.iconname('Dialog') self.boxRoot.attributes("-topmost", True) # Put the dialog box in focus. + def config_icon(self, icon): + if icon: + self.boxRoot.iconbitmap(icon) + def create_msg_widget(self, msg): if msg is None: diff --git a/easygui/boxes/choice_box.py b/easygui/boxes/choice_box.py index 3fe8007..142abde 100644 --- a/easygui/boxes/choice_box.py +++ b/easygui/boxes/choice_box.py @@ -25,7 +25,7 @@ def choicebox(msg="Pick an item", title="", choices=None, preselect=0, callback=None, - run=True): + run=True, icon=None): """ The ``choicebox()`` provides a list of choices in a list box to choose from. The choices are specified in a sequence (a tuple or a list). @@ -44,7 +44,7 @@ def choicebox(msg="Pick an item", title="", choices=None, preselect=0, """ mb = ChoiceBox(msg, title, choices, preselect=preselect, multiple_select=False, - callback=callback) + callback=callback, icon=icon) if run: reply = mb.run() return reply @@ -117,7 +117,7 @@ def make_list_or_none(obj, cast_type=None): class ChoiceBox(object): - def __init__(self, msg, title, choices, preselect, multiple_select, callback): + def __init__(self, msg, title, choices, preselect, multiple_select, callback, icon): self.callback = callback @@ -132,7 +132,7 @@ def __init__(self, msg, title, choices, preselect, multiple_select, callback): raise ValueError("Multiple selections not allowed, yet preselect has multiple values:{}".format(preselect_list)) self.ui = GUItk(msg, title, self.choices, preselect_list, multiple_select, - self.callback_ui) + self.callback_ui, icon) def run(self): """ Start the ui """ @@ -200,7 +200,7 @@ class GUItk(object): It also accepts commands from Multibox to change its message. """ - def __init__(self, msg, title, choices, preselect, multiple_select, callback): + def __init__(self, msg, title, choices, preselect, multiple_select, callback, icon): self.callback = callback @@ -219,6 +219,7 @@ def __init__(self, msg, title, choices, preselect, multiple_select, callback): self.boxFont = tk_Font.nametofont("TkTextFont") self.config_root(title) + self.config_icon(icon) self.set_pos(global_state.window_position) # GLOBAL POSITION @@ -336,6 +337,10 @@ def config_root(self, title): self.boxRoot.bind("", self.cancel_pressed) self.boxRoot.attributes("-topmost", True) # Put the dialog box in focus. + + def config_icon(self, icon): + if icon: + self.boxRoot.iconbitmap(icon) def create_msg_widget(self, msg): diff --git a/easygui/boxes/derived_boxes.py b/easygui/boxes/derived_boxes.py index e8c92d0..22d0cdd 100644 --- a/easygui/boxes/derived_boxes.py +++ b/easygui/boxes/derived_boxes.py @@ -28,7 +28,7 @@ def ynbox(msg="Shall I continue?", title=" ", choices=("[]Yes", "[]No"), image=None, - default_choice='[]Yes', cancel_choice='[]No'): + default_choice='[]Yes', cancel_choice='[]No', icon=None): """ The ``ynbox()`` offers a choice of Yes and No, and returns either ``True`` or ``False``. @@ -56,7 +56,8 @@ def ynbox(msg="Shall I continue?", title=" ", choices=choices, image=image, default_choice=default_choice, - cancel_choice=cancel_choice) + cancel_choice=cancel_choice, + icon = icon) # ----------------------------------------------------------------------- # ccbox @@ -65,7 +66,7 @@ def ynbox(msg="Shall I continue?", title=" ", def ccbox(msg="Shall I continue?", title=" ", choices=("C[o]ntinue", "C[a]ncel"), image=None, - default_choice='Continue', cancel_choice='Cancel'): + default_choice='Continue', cancel_choice='Cancel', icon = None): """ The ``ccbox()`` function offers a choice of Continue and Cancel, and returns either True (for continue) or False (for cancel). @@ -93,7 +94,8 @@ def ccbox(msg="Shall I continue?", title=" ", choices=choices, image=image, default_choice=default_choice, - cancel_choice=cancel_choice) + cancel_choice=cancel_choice, + icon = icon) # ----------------------------------------------------------------------- # boolbox @@ -102,7 +104,7 @@ def ccbox(msg="Shall I continue?", title=" ", def boolbox(msg="Shall I continue?", title=" ", choices=("[T]rue", "[F]alse"), image=None, - default_choice='[T]rue', cancel_choice='[F]alse'): + default_choice='[T]rue', cancel_choice='[F]alse', icon=None): """ The ``boolbox()`` (boolean box) displays two buttons. Returns returns ``True`` if the first button is chosen. Otherwise returns ``False``. @@ -135,7 +137,8 @@ def boolbox(msg="Shall I continue?", title=" ", choices=choices, image=image, default_choice=default_choice, - cancel_choice=cancel_choice) + cancel_choice=cancel_choice, + icon=icon) if reply == choices[0]: return True # The first button (True) was selected. @@ -152,7 +155,7 @@ def boolbox(msg="Shall I continue?", title=" ", # ----------------------------------------------------------------------- def indexbox(msg="Shall I continue?", title=" ", choices=("Yes", "No"), image=None, - default_choice='Yes', cancel_choice='No'): + default_choice='Yes', cancel_choice='No', icon = None): """ The ``indexbox()`` function displays a set of buttons, and returns the index of the selected button. For example, if you invoked index box with @@ -181,7 +184,8 @@ def indexbox(msg="Shall I continue?", title=" ", choices=choices, image=image, default_choice=default_choice, - cancel_choice=cancel_choice) + cancel_choice=cancel_choice, + icon=icon) if reply is None: return None for i, choice in enumerate(choices): @@ -197,7 +201,7 @@ def indexbox(msg="Shall I continue?", title=" ", # msgbox # ----------------------------------------------------------------------- def msgbox(msg="(Your message goes here)", title=" ", - ok_button="OK", image=None, root=None): + ok_button="OK", image=None, root=None, icon=None): """ The ``msgbox()`` function displays a text message and offers an OK button. The message text appears in the center of the window, the title @@ -232,7 +236,8 @@ def msgbox(msg="(Your message goes here)", title="", ok_button="OK"): choices=[ok_button], image=image, default_choice=ok_button, - cancel_choice=ok_button) + cancel_choice=ok_button, + icon=icon) def convert_to_type(input_value, new_type, input_value_name=None): @@ -262,7 +267,7 @@ def convert_to_type(input_value, new_type, input_value_name=None): # integerbox # ------------------------------------------------------------------- def integerbox(msg="", title=" ", default=None, - lowerbound=0, upperbound=99, image=None, root=None): + lowerbound=0, upperbound=99, image=None, root=None, icon=None): """ Show a box in which a user can enter an integer. @@ -303,7 +308,7 @@ def integerbox(msg="", title=" ", default=None, upperbound = convert_to_type(upperbound, int, "upperbound") while True: - reply = enterbox(msg, title, default, image=image, root=root) + reply = enterbox(msg, title, default, image=image, root=root, icon = icon) if reply is None: return None try: @@ -334,7 +339,7 @@ def integerbox(msg="", title=" ", default=None, # enterbox # ------------------------------------------------------------------- def enterbox(msg="Enter something.", title=" ", default="", - strip=True, image=None, root=None): + strip=True, image=None, root=None, icon=None): """ Show a box in which a user can enter some text. @@ -359,14 +364,14 @@ def enterbox(msg="Enter something.", title=" ", default="", the operation. """ result = __fillablebox( - msg, title, default=default, mask=None, image=image, root=root) + msg, title, default=default, mask=None, image=image, root=root, icon=icon) if result and strip: result = result.strip() return result def passwordbox(msg="Enter your password.", title=" ", default="", - image=None, root=None): + image=None, root=None, icon=None): """ Show a box in which a user can enter a password. The text is masked with asterisks, so the password is not displayed. @@ -378,13 +383,13 @@ def passwordbox(msg="Enter your password.", title=" ", default="", the operation. """ return __fillablebox(msg, title, default, mask="*", - image=image, root=root) + image=image, root=root, icon=icon) # ----------------------------------------------------------------------- # exceptionbox # ----------------------------------------------------------------------- -def exceptionbox(msg=None, title=None): +def exceptionbox(msg=None, title=None, icon=None): """ Display a box that gives information about an exception that has just been raised. @@ -405,14 +410,14 @@ def exceptionbox(msg=None, title=None): if msg is None: msg = "An error (exception) has occurred in the program." - codebox(msg, title, ut.exception_format()) + codebox(msg, title, ut.exception_format(), icon=icon) # ------------------------------------------------------------------- # codebox # ------------------------------------------------------------------- -def codebox(msg="", title=" ", text=""): +def codebox(msg="", title=" ", text="", icon=None): """ Display some text in a monospaced font, with no line wrapping. This function is suitable for displaying code and text that is @@ -425,4 +430,4 @@ def codebox(msg="", title=" ", text=""): :param str title: the window title :param str text: what to display in the textbox """ - return tb.textbox(msg, title, text, codebox=True) + return tb.textbox(msg, title, text, codebox=True, icon=icon) diff --git a/easygui/boxes/diropen_box.py b/easygui/boxes/diropen_box.py index fa626b1..e6516f2 100644 --- a/easygui/boxes/diropen_box.py +++ b/easygui/boxes/diropen_box.py @@ -25,7 +25,7 @@ # ------------------------------------------------------------------- # diropenbox # ------------------------------------------------------------------- -def diropenbox(msg=None, title=None, default=None): +def diropenbox(msg=None, title=None, default=None, icon=None): """ A dialog to get a directory name. @@ -42,6 +42,7 @@ def diropenbox(msg=None, title=None, default=None): title = ut.getFileDialogTitle(msg, title) localRoot = tk.Tk() localRoot.withdraw() + localRoot.iconbitmap(icon) localRoot.attributes("-topmost", True) if not default: default = None diff --git a/easygui/boxes/fileopen_box.py b/easygui/boxes/fileopen_box.py index ea94eaf..0367f5a 100644 --- a/easygui/boxes/fileopen_box.py +++ b/easygui/boxes/fileopen_box.py @@ -25,7 +25,7 @@ # ------------------------------------------------------------------- -def fileopenbox(msg=None, title=None, default='*', filetypes=None, multiple=False): +def fileopenbox(msg=None, title=None, default='*', filetypes=None, multiple=False, icon = None): """ Displays an "open file" dialog box and returns the selected file as a string. @@ -83,6 +83,7 @@ def fileopenbox(msg=None, title=None, default='*', filetypes=None, multiple=Fals :return: the name of a file, or None if user chose to cancel """ localRoot = tk.Tk() + localRoot.iconbitmap(icon) localRoot.withdraw() localRoot.attributes("-topmost", True) diff --git a/easygui/boxes/filesave_box.py b/easygui/boxes/filesave_box.py index 4d453b8..502d45d 100644 --- a/easygui/boxes/filesave_box.py +++ b/easygui/boxes/filesave_box.py @@ -31,7 +31,7 @@ # ------------------------------------------------------------------- -def filesavebox(msg=None, title=None, default="", filetypes=None): +def filesavebox(msg=None, title=None, default="", filetypes=None,icon=None): """ A file to get the name of a file to save. Returns the name of a file, or None if user chose to cancel. @@ -64,6 +64,7 @@ def filesavebox(msg=None, title=None, default="", filetypes=None): """ localRoot = tk.Tk() + localRoot.iconbitmap(icon) localRoot.withdraw() localRoot.attributes("-topmost", True) diff --git a/easygui/boxes/fillable_box.py b/easygui/boxes/fillable_box.py index f5fbf3b..f98cc28 100644 --- a/easygui/boxes/fillable_box.py +++ b/easygui/boxes/fillable_box.py @@ -25,7 +25,7 @@ okButton = None -def __fillablebox(msg, title="", default="", mask=None, image=None, root=None): +def __fillablebox(msg, title="", default="", mask=None, image=None, root=None, icon=None): """ Show a box in which a user can enter some text. You may optionally specify some default text, which will appear in the @@ -53,6 +53,7 @@ def __fillablebox(msg, title="", default="", mask=None, image=None, root=None): boxRoot.protocol('WM_DELETE_WINDOW', __enterboxQuit) boxRoot.title(title) + boxRoot.iconbitmap(icon) boxRoot.iconname('Dialog') boxRoot.geometry(global_state.window_position) boxRoot.bind("", __enterboxCancel) diff --git a/easygui/boxes/multi_fillable_box.py b/easygui/boxes/multi_fillable_box.py index f512add..e247c2c 100644 --- a/easygui/boxes/multi_fillable_box.py +++ b/easygui/boxes/multi_fillable_box.py @@ -25,7 +25,7 @@ def multpasswordbox(msg="Fill in values for the fields.", title=" ", fields=tuple(), values=tuple(), - callback=None, run=True): + callback=None, run=True, icon = None): r""" Same interface as multenterbox. But in multpassword box, the last of the fields is assumed to be a password, and @@ -65,7 +65,7 @@ def multpasswordbox(msg="Fill in values for the fields.", """ if run: mb = MultiBox(msg, title, fields, values, mask_last=True, - callback=callback) + callback=callback, icon=icon) reply = mb.run() @@ -74,7 +74,7 @@ def multpasswordbox(msg="Fill in values for the fields.", else: mb = MultiBox(msg, title, fields, values, mask_last=True, - callback=callback) + callback=callback, icon=icon) return mb @@ -87,7 +87,7 @@ def multpasswordbox(msg="Fill in values for the fields.", # TODO RL: Rename/alias to multienterbox? # default should be None and then in the logic create an empty liglobal_state. def multenterbox(msg="Fill in values for the fields.", title=" ", - fields=[], values=[], callback=None, run=True): + fields=[], values=[], callback=None, run=True, icon = None): r""" Show screen with multiple data entry fields. @@ -131,12 +131,12 @@ def multenterbox(msg="Fill in values for the fields.", title=" ", """ if run: mb = MultiBox(msg, title, fields, values, mask_last=False, - callback=callback) + callback=callback, icon=icon) reply = mb.run() return reply else: mb = MultiBox(msg, title, fields, values, mask_last=False, - callback=callback) + callback=callback, icon=icon) return mb @@ -155,7 +155,7 @@ class MultiBox(object): frameworks can be used without breaking anything to the user """ - def __init__(self, msg, title, fields, values, mask_last, callback): + def __init__(self, msg, title, fields, values, mask_last, callback, icon): """ Create box object Parameters @@ -184,7 +184,7 @@ def __init__(self, msg, title, fields, values, mask_last, callback): self.fields, self.values = self.check_fields(fields, values) self.ui = GUItk(msg, title, self.fields, self.values, - mask_last, self.callback_ui) + mask_last, self.callback_ui, icon) def run(self): """ Start the ui """ @@ -262,7 +262,7 @@ class GUItk(object): It also accepts commands from Multibox to change its message. """ - def __init__(self, msg, title, fields, values, mask_last, callback): + def __init__(self, msg, title, fields, values, mask_last, callback, icon): self.callback = callback @@ -270,6 +270,8 @@ def __init__(self, msg, title, fields, values, mask_last, callback): self.create_root(title) + self.config_icon(icon) + self.set_pos(global_state.window_position) # GLOBAL POSITION self.create_msg_widget(msg) @@ -335,6 +337,10 @@ def create_root(self, title): self.boxRoot.bind("", self.cancel_pressed) self.boxRoot.attributes("-topmost", True) # Put the dialog box in focus. + def config_icon(self, icon): + if icon: + self.boxRoot.iconbitmap(icon) + def create_msg_widget(self, msg): # -------------------- the msg widget ---------------------------- self.messageWidget = tk.Message(self.boxRoot, width="4.5i", text=msg) diff --git a/easygui/boxes/text_box.py b/easygui/boxes/text_box.py index 86216c5..2c14861 100644 --- a/easygui/boxes/text_box.py +++ b/easygui/boxes/text_box.py @@ -158,7 +158,7 @@ def check_answer(self, box): def textbox(msg="", title=" ", text="", - codebox=False, callback=None, run=True): + codebox=False, callback=None, run=True, icon=None): """Displays a dialog box with a large, multi-line text box, and returns the entered text as a string. The message text is displayed in a proportional font and wraps. @@ -188,7 +188,7 @@ def textbox(msg="", title=" ", text="", """ tb = TextBox(msg=msg, title=title, text=text, - codebox=codebox, callback=callback) + codebox=codebox, callback=callback, icon=icon) if not run: return tb else: @@ -207,7 +207,7 @@ class TextBox(object): library can be used (wx, qt) without breaking anything for the user. """ - def __init__(self, msg, title, text, codebox, callback=lambda *args, **kwargs: True): + def __init__(self, msg, title, text, codebox, icon, callback=lambda *args, **kwargs: True): """ Create box object Parameters @@ -230,7 +230,7 @@ def __init__(self, msg, title, text, codebox, callback=lambda *args, **kwargs: T """ self.callback = callback - self.ui = GUItk(msg, title, text, codebox, self.callback_ui) + self.ui = GUItk(msg, title, text, codebox, self.callback_ui, icon) self.text = text def run(self): @@ -315,7 +315,7 @@ class GUItk(object): """ This is the object that contains the tk root object""" - def __init__(self, msg, title, text, codebox, callback): + def __init__(self, msg, title, text, codebox, callback, icon): """ Create ui object Parameters @@ -356,6 +356,8 @@ def __init__(self, msg, title, text, codebox, callback): self.configure_root(title) + self.config_icon(icon) + self.create_msg_widget(msg) self.create_text_area(wrap_text) @@ -449,6 +451,10 @@ def configure_root(self, title): self.boxRoot.attributes("-topmost", True) # Put the dialog box in focus. + def config_icon(self, icon): + if icon: + self.boxRoot.iconbitmap(icon) + def create_msg_widget(self, msg): if msg is None: