diff --git a/ttkwidgets/frames/balloon.py b/ttkwidgets/frames/balloon.py index 2ab1947e..7f0a3464 100644 --- a/ttkwidgets/frames/balloon.py +++ b/ttkwidgets/frames/balloon.py @@ -18,9 +18,9 @@ class Balloon(ttk.Frame): """Simple help hover balloon.""" def __init__(self, master=None, headertext="Help", text="Some great help is displayed here.", width=200, timeout=1, - background="#fef9cd", **kwargs): + background="#fef9cd", offset=(2, 2), showheader=True, static=False, **kwargs): """ - Create a Balloon. + Create a Balloon :param master: widget to bind the Balloon to :type master: widget @@ -34,6 +34,15 @@ def __init__(self, master=None, headertext="Help", text="Some great help is disp :type timeout: float :param background: background color of the Balloon :type background: str + :param offset: The offset from the mouse position the Ballon shows up + :type offset: Tuple[int, int] + :param showheader: Whether to display the header with image + :type showheader: bool + :param static: Whether to display the tooltip with static + position. When the position is set to static, the balloon + will always appear an offset from the bottom right corner of + the widget. + :type static: bool :param kwargs: keyword arguments passed on to the :class:`ttk.Frame` initializer """ ttk.Frame.__init__(self, master, **kwargs) @@ -51,11 +60,16 @@ def __init__(self, master=None, headertext="Help", text="Some great help is disp self.__headertext = headertext self.__text = text self.__width = width + self.__offset = offset + self.__showheader = showheader + self.__static = static + self.master = master self._id = None self._timeout = timeout self.master.bind("", self._on_enter) self.master.bind("", self._on_leave) + self.master.bind("", self._on_leave) def __getitem__(self, key): return self.cget(key) @@ -66,7 +80,8 @@ def __setitem__(self, key, value): def _grid_widgets(self): """Place the widgets in the Toplevel.""" self._canvas.grid(sticky="nswe") - self.header_label.grid(row=1, column=1, sticky="nswe", pady=5, padx=5) + if self.__showheader is True: + self.header_label.grid(row=1, column=1, sticky="nswe", pady=5, padx=5) self.text_label.grid(row=3, column=1, sticky="nswe", pady=6, padx=5) def _on_enter(self, event): @@ -84,9 +99,10 @@ def _on_leave(self, event): def show(self): """ - Create the Toplevel widget and its child widgets to show in the spot of the cursor. + Create the Toplevel and its children to show near the cursor - This is the callback for the delayed :obj:`` event (see :meth:`~Balloon._on_enter`). + This is the callback for the delayed :obj:`` event + (see :meth:`~Balloon._on_enter`). """ self._toplevel = tk.Toplevel(self.master) self._canvas = tk.Canvas(self._toplevel, background=self.__background) @@ -97,11 +113,17 @@ def show(self): self._toplevel.attributes("-topmost", True) self._toplevel.overrideredirect(True) self._grid_widgets() - x, y = self.master.winfo_pointerxy() + if self.__static is True: + x, y = self.master.winfo_rootx(), self.master.winfo_rooty() + w, h = self.master.winfo_width(), self.master.winfo_height() + x, y = x + w, y + h + else: + x, y = self.master.winfo_pointerxy() self._canvas.update() # Update the Geometry of the Toplevel to update its position and size - self._toplevel.geometry("{0}x{1}+{2}+{3}".format(self._canvas.winfo_width(), self._canvas.winfo_height(), - x + 2, y + 2)) + self._toplevel.geometry("{0}x{1}+{2}+{3}".format( + self._canvas.winfo_width(), self._canvas.winfo_height(), + x + self.__offset[0], y + self.__offset[1])) def cget(self, key): """ @@ -123,6 +145,10 @@ def cget(self, key): return self._timeout elif key == "background": return self.__background + elif key == "offset": + return self.__offset + elif key == "showheader": + return self.__showheader else: return ttk.Frame.cget(self, key) @@ -138,6 +164,9 @@ def config(self, **kwargs): self.__width = kwargs.pop("width", self.__width) self._timeout = kwargs.pop("timeout", self._timeout) self.__background = kwargs.pop("background", self.__background) + self.__offset = kwargs.pop("offset", self.__offset) + self.__showheader = kwargs.pop("showheader", self.__showheader) + self.__static = kwargs.pop("static", self.__static) if self._toplevel: self._on_leave(None) self.show()