right_click_menu_tearoff parm added to Window, expand_x & expand_y added to vtop vbottom vcenter, listbox has new listbox_frame member variable needed if wanting listbox to resize with the window, changed print in Image element creation if error happens to an error popup (cannot use stdout/stderr because they've been rerouted and will also cause errors), error popup wraps text better
This commit is contained in:
		
							parent
							
								
									c890ba0b63
								
							
						
					
					
						commit
						8955b9db77
					
				
					 1 changed files with 70 additions and 26 deletions
				
			
		|  | @ -1,6 +1,6 @@ | |||
| #!/usr/bin/python3 | ||||
| 
 | ||||
| version = __version__ = "4.38.0.3 Unreleased\nAdded Element.block_focus to allow blocking an element from getting focus, Listbox now sets the selected colors to be opposite of normal text/background colors, added highlight parms to Listbox so that they can be directly set, gave Mac users the abliity to override the TTK-Buttons-Only rule for Macs so that if forced, a Button CAN use tk buttons on a Mac" | ||||
| version = __version__ = "4.38.0.4 Unreleased\nAdded Element.block_focus to allow blocking an element from getting focus, Listbox now sets the selected colors to be opposite of normal text/background colors, added highlight parms to Listbox so that they can be directly set, gave Mac users the abliity to override the TTK-Buttons-Only rule for Macs so that if forced, a Button CAN use tk buttons on a Mac, exposed listbox_frame for Listbox so can expand a listbox, new parameter right_click_menu_tearoff parm added to Window, better line wrapping for error windows, show an error window if a bad Image specified in the Image element, expand_x & expand_y parms for vtop" | ||||
| 
 | ||||
| __version__ = version.split()[0]    # For PEP 396 and PEP 345 | ||||
| 
 | ||||
|  | @ -843,6 +843,22 @@ class Element(): | |||
|         if self.Type == ELEM_TYPE_GRAPH: | ||||
|             self._update_position_for_returned_values(event) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     def _tearoff_menu_callback(self, parent, menu): | ||||
|         """ | ||||
|         Callback function that's called when a right click menu is torn off. | ||||
|         The reason for this fuction is to relocate the torn-off menu. It will default to 0,0 otherwise | ||||
|         This callback moves the right click menu window to the clocation of the current window | ||||
| 
 | ||||
|         :param parent: information provided by tkinter - the parent of the Meny | ||||
|         :param menu: information provided by tkinter - the menu window | ||||
| 
 | ||||
|         """ | ||||
|         winx, winy = self.ParentForm.current_location() | ||||
|         self.ParentForm.TKroot.tk.call('wm', 'geometry', menu, "+{}+{}".format(winx, winy)) | ||||
| 
 | ||||
| 
 | ||||
|     def _MenuItemChosenCallback(self, item_chosen):  # TEXT Menu item callback | ||||
|         """ | ||||
|         Callback function called when user chooses a menu item from menubar, Button Menu or right click menu | ||||
|  | @ -1881,6 +1897,7 @@ class Listbox(Element): | |||
|         self.RightClickMenu = right_click_menu | ||||
|         self.vsb = None  # type: tk.Scrollbar | ||||
|         self.TKListbox = self.Widget = None  # type: tk.Listbox | ||||
|         self.listbox_frame = None           # type: tk.Frame | ||||
|         self.NoScrollbar = no_scrollbar | ||||
|         key = key if key is not None else k | ||||
| 
 | ||||
|  | @ -7591,7 +7608,7 @@ class Window: | |||
|                  no_titlebar=False, grab_anywhere=False, keep_on_top=False, 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_font=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, | ||||
|                  titlebar_background_color=None, titlebar_text_color=None, titlebar_font=None, titlebar_icon=None, | ||||
|                  use_custom_titlebar=None, metadata=None): | ||||
|  | @ -7668,6 +7685,8 @@ class Window: | |||
|         :type right_click_menu_disabled_text_color: (str) | ||||
|         :param right_click_menu_font: Font for right click menus | ||||
|         :type right_click_menu_font: str | Tuple[str, int] | ||||
|         :param right_click_menu_tearoff: If True then all right click menus can be torn off | ||||
|         :type right_click_menu_tearoff: bool | ||||
|         :param finalize: If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code | ||||
|         :type finalize: (bool) | ||||
|         :param element_justification: All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values | ||||
|  | @ -7784,6 +7803,7 @@ class Window: | |||
|         self.right_click_menu_text_color = right_click_menu_text_color if right_click_menu_text_color is not None else theme_input_text_color() | ||||
|         self.right_click_menu_disabled_text_color = right_click_menu_disabled_text_color if right_click_menu_disabled_text_color is not None else COLOR_SYSTEM_DEFAULT | ||||
|         self.right_click_menu_font = right_click_menu_font if right_click_menu_font is not None else self.Font | ||||
|         self.right_click_menu_tearoff = right_click_menu_tearoff | ||||
|         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 | ||||
|  | @ -10109,6 +10129,10 @@ def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None | |||
|     :type vertical_alignment: str | None | ||||
|     :param shrink: If True, then the space will shrink down to a single pixel when hidden. False leaves the area large and blank | ||||
|     :type shrink: bool | ||||
|     :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 | ||||
|     :rtype: Column | ||||
|     """ | ||||
|  | @ -10118,28 +10142,36 @@ 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): | ||||
| 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) | ||||
|     :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') 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') | ||||
|     return Column([[elem_or_row]], pad=(0,0), vertical_alignment='top', expand_x=expand_x, expand_y=expand_y) | ||||
| 
 | ||||
| 
 | ||||
| def vcenter(elem_or_row): | ||||
| 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) | ||||
|     :return: A column element containing the provided element aligned to the center or list of elements (a row) | ||||
|     :rtype: Column | List[Column] | ||||
|     """ | ||||
|  | @ -10151,12 +10183,16 @@ def vcenter(elem_or_row): | |||
|     return Column([[elem_or_row]], pad=(0,0), vertical_alignment='center') | ||||
| 
 | ||||
| 
 | ||||
| def vbottom(elem_or_row): | ||||
| 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) | ||||
|     :return: A column element containing the provided element aligned to the bottom or list of elements (a row) | ||||
|     :rtype: Column | List[Column] | ||||
|     """ | ||||
|  | @ -11990,7 +12026,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|     def _add_right_click_menu(element): | ||||
|         if element.RightClickMenu or toplevel_form.RightClickMenu: | ||||
|             menu = element.RightClickMenu or toplevel_form.RightClickMenu | ||||
|             top_menu = tk.Menu(toplevel_form.TKroot, tearoff=False) | ||||
|             top_menu = tk.Menu(toplevel_form.TKroot, tearoff=toplevel_form.right_click_menu_tearoff, tearoffcommand=element._tearoff_menu_callback) | ||||
| 
 | ||||
|             if toplevel_form.right_click_menu_background_color not in (COLOR_SYSTEM_DEFAULT, None): | ||||
|                 top_menu.config(bg=toplevel_form.right_click_menu_background_color) | ||||
|  | @ -12729,8 +12765,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|                 listbox_frame = tk.Frame(tk_row_frame) | ||||
|                 element.TKStringVar = tk.StringVar() | ||||
|                 element.TKListbox = element.Widget = tk.Listbox(listbox_frame, height=element_size[1], width=width, | ||||
|                                                                 selectmode=element.SelectMode, font=font, | ||||
|                                                                 exportselection=False) | ||||
|                                                                 selectmode=element.SelectMode, font=font, exportselection=False) | ||||
|                 element.Widget.config(highlightthickness=0) | ||||
|                 for index, item in enumerate(element.Values): | ||||
|                     element.TKListbox.insert(tk.END, item) | ||||
|  | @ -12767,6 +12802,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|                 if element.Tooltip is not None: | ||||
|                     element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip, | ||||
|                                                     timeout=DEFAULT_TOOLTIP_TIME) | ||||
|                 element.listbox_frame = listbox_frame | ||||
|                 _add_right_click_menu(element) | ||||
|             # -------------------------  MULTILINE placement element  ------------------------- # | ||||
|             elif element_type == ELEM_TYPE_INPUT_MULTILINE: | ||||
|  | @ -12986,6 +13022,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|                 # -------------------------  IMAGE placement element  ------------------------- # | ||||
|             elif element_type == ELEM_TYPE_IMAGE: | ||||
|                 element = element  # type: Image | ||||
|                 try: | ||||
|                     if element.Filename is not None: | ||||
|                         photo = tk.PhotoImage(file=element.Filename) | ||||
|                     elif element.Data is not None: | ||||
|  | @ -12993,6 +13030,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|                     else: | ||||
|                         photo = None | ||||
|                         # print('*ERROR laying out form.... Image Element has no image specified*') | ||||
|                 except Exception as e: | ||||
|                     photo=None | ||||
|                     _error_popup_with_traceback('Your Window has an Image Element with a problem', | ||||
|                                                 'The traceback will show you the Window with the problem layout', | ||||
|                                                 'Look in this Window\'s layout for an Image element that has a key of {}'.format(element.Key), | ||||
|                                                 'The error occuring is:', e) | ||||
| 
 | ||||
|                 if photo is not None: | ||||
|                     if element_size == ( | ||||
|  | @ -13020,7 +13063,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): | |||
|                 if element.Tooltip is not None: | ||||
|                     element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip, | ||||
|                                                     timeout=DEFAULT_TOOLTIP_TIME) | ||||
|                 if element.EnableEvents: | ||||
|                 if element.EnableEvents and element.tktext_label is not None: | ||||
|                     element.tktext_label.bind('<ButtonPress-1>', element._ClickHandler) | ||||
|                 element.Widget = element.tktext_label | ||||
| 
 | ||||
|  | @ -17099,7 +17142,8 @@ def _error_popup_with_traceback(title, *args): | |||
| def _error_popup_with_code(title, filename=None, line_num=None,  *args): | ||||
|     layout = [[Text('ERROR'), Text(title)], | ||||
|               [Image(data=_random_error_emoji())]] | ||||
|     layout += [[Text(msg)] for msg in args] | ||||
|     # make max length of line be 90 chars and allow the hieight to vary based on number of needed lines | ||||
|     layout += [[Text(str(msg), size=(min(90, len(str(msg))),None))] for msg in args] | ||||
| 
 | ||||
|     layout += [[Button('Close'), Button('Take me to error')]] | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue