Beispiel #1
0
 def __init__(self, widget: tkinter.Widget, text: str) -> None:
     widget.bind("<Enter>", self.enter, add=True)
     widget.bind("<Leave>", self.leave, add=True)
     widget.bind("<Motion>", self.motion, add=True)
     self.widget = widget
     self.got_mouse = False
     self.text = text  # can be changed after creating tooltip manager
Beispiel #2
0
 def __init__(self, widget: tkinter.Widget) -> None:
     widget.bind('<Enter>', self.enter, add=True)
     widget.bind('<Leave>', self.leave, add=True)
     widget.bind('<Motion>', self.motion, add=True)
     self.widget = widget
     self.got_mouse = False
     self.text: Optional[str] = None
Beispiel #3
0
 def bind_ci(widget: tk.Widget,
             all_: bool = False,
             *,
             modifier: str = '',
             letter: str,
             callback,
             add: bool = False):
     if modifier and letter:
         modifier += '-'
     if all_:
         widget.bind_all(f'<{modifier}{letter.lower()}>', callback, add)
         widget.bind_all(f'<{modifier}{letter.upper()}>', callback, add)
     else:
         widget.bind(f'<{modifier}{letter.lower()}>', callback, add)
         widget.bind(f'<{modifier}{letter.upper()}>', callback, add)
Beispiel #4
0
def create_tooltip(widget: tk.Widget, text: str):
    """
    Create a tooltip with text that is shown when the user hovers over widget.
    """
    tool_tip = ToolTip(widget)

    # noinspection PyUnusedLocal
    def enter(tk_event: tk.Event):
        tool_tip.show_tooltip(text)

    # noinspection PyUnusedLocal
    def leave(tk_event: tk.Event):
        tool_tip.hide_tooltip()

    widget.bind('<Enter>', enter)
    widget.bind('<Leave>', leave)
Beispiel #5
0
    def bind_data(self, widget: tkinter.Widget, property_name: str):
        """
        This method binds a function to a widgets and sets the callback
        function. For things which are sensible this is a 2-way binding.
        (Anything editable, i.e. not a Label)
        :param widget: tkinter.Widget object
        :param property_name: Property to bind
        """

        # unpythonic code, used for generic data binding as there are different
        # behaviours for different widgets

        if isinstance(widget, tkinter.Entry) or isinstance(
                widget, tkinter.ttk.Entry):
            # bind any key press to setting the contents of the widgets to the property
            widget.bind(
                "<KeyRelease>",
                lambda event: setattr(self.context, property_name,
                                      event.widget.get()))
            # insert the value in the entry
            val = getattr(self.context, property_name)
            if val:
                widget.delete(0, tkinter.END)
                widget.insert(0, val)

        if isinstance(widget, tkinter.Checkbutton) or isinstance(
                widget, tkinter.ttk.Checkbutton):
            # a binary value has to be bound to this, calls not on the value
            widget.bind(
                "<Button-1>",
                lambda event: setattr(self.context, property_name, (
                    not getattr(self.context, property_name))))

        if isinstance(widget, tkinter.Label) or isinstance(
                widget, tkinter.ttk.Label):
            # sets the label text to be the property
            val = getattr(self.context, property_name)
            widget.config(text=str(val))

        if isinstance(widget, tkinter.Listbox):
            # bind selection to store currently selected in the viewmodel
            widget.bind(
                "<<ListboxSelect>>",
                lambda event: setattr(self.context, 'current_selection',
                                      event.widget.curselection()))

            # add all items to listbox
            widget.delete(0, tkinter.END)
            for i, item in enumerate(getattr(self.context, property_name)):
                widget.insert(i, str(item))

        if isinstance(widget, tkinter.Button) or isinstance(
                widget, tkinter.ttk.Button):
            # sets the button text to be the property
            widget.config(text=str(getattr(self.context, property_name)))

        # add the widgets to the properties list
        if property_name not in self.properties:
            self.properties[property_name] = []
        self.properties[property_name].append(widget)
Beispiel #6
0
def bind_tab_key(widget: tkinter.Widget,
                 on_tab: Callable[['tkinter.Event[Any]', bool],
                                  BreakOrNone], **bind_kwargs: Any) -> None:
    """A convenience function for binding Tab and Shift+Tab.

    Use this function like this::

        def on_tab(event, shifted):
            # shifted is True if the user held down shift while pressing
            # tab, and False otherwise
            ...

        utils.bind_tab_key(some_widget, on_tab, add=True)

    The ``event`` argument and ``on_tab()`` return values are treated
    just like with regular bindings.

    Binding ``'<Tab>'`` works just fine everywhere, but binding
    ``'<Shift-Tab>'`` only works on Windows and Mac OSX. This function
    also works on X11.
    """

    # there's something for this in more_functools, but it's a big
    # dependency for something this simple imo
    def callback(shifted: bool,
                 event: 'tkinter.Event[tkinter.Misc]') -> BreakOrNone:
        return on_tab(event, shifted)

    if widget.tk.call('tk', 'windowingsystem') == 'x11':
        # even though the event keysym says Left, holding down the right
        # shift and pressing tab also works :D
        shift_tab = '<ISO_Left_Tab>'
    else:
        shift_tab = '<Shift-Tab>'

    widget.bind('<Tab>', functools.partial(callback, False),
                **bind_kwargs)  # bindcheck: ignore
    widget.bind(shift_tab, functools.partial(callback, True),
                **bind_kwargs)  # bindcheck: ignore
Beispiel #7
0
 def __init__(self, widget: Widget, text: str, side: str = 'n', **kwargs):
     """\
     Parameters
     ----------
     widget : Widget
         The parent widget
     text : str
         The tooltip text
     side : str, optional (default is "n")
         Which side of the parent widget to show the tooltip on
     **kwargs : dict, optional (default is justify="left", padx=1, pady=1)
         tkLabel Keyword Arguments for the tooltip
     """
     # verify value
     if side and side.lower() not in list('nsew'):
         raise ValueError('<side> parameter must be '
                          'one of "n", "s", "e", or "w"')
     # init vars
     self._wgt = widget
     self._side = side.lower()
     kwargs.update(justify=kwargs.pop('justify', 'left'),
                   padx=kwargs.pop('padx', 1),
                   pady=kwargs.pop('pady', 1))
     # create win
     Toplevel.__init__(self, master=widget)
     self.attributes("-alpha", 0.75)
     self.overrideredirect(True)
     # create lbl
     self._lbl = Label(master=self, text=text, **kwargs)
     self._lbl.pack()
     self.update_idletasks()
     self._tw = self.winfo_reqwidth()
     self._th = self.winfo_reqheight()
     self.withdraw()
     widget.bind("<Enter>", self.enter)
     widget.bind("<Leave>", self.close)
Beispiel #8
0
def forward_event(event_name: str,
                  from_: tkinter.Widget,
                  to: tkinter.Widget,
                  *,
                  add: bool = True) -> str:
    def callback(event: 'tkinter.Event[tkinter.Misc]') -> None:
        # make the coordinates relative to the 'to' widget
        x = event.x_root - to.winfo_rootx()
        y = event.y_root - to.winfo_rooty()
        # no need to specify rootx and rooty, because Tk can calculate them

        if isinstance(event, EventWithData):
            to.event_generate(event_name, x=x, y=y, data=event.data_string)
        else:
            to.event_generate(event_name, x=x, y=y)

    if event_name.startswith('<<'):
        # virtual events support data
        return bind_with_data(from_, event_name, callback, add=add)
    else:
        return from_.bind(event_name, callback, add=add)
Beispiel #9
0
def embed(widget:tkinter.Widget, default_size=None, allow_new=True, allow_save=True, allow_load=True):
    from tkinter import Label, Toplevel, Frame, IntVar, Spinbox, Button
    from tkinter.messagebox import showerror
    from PIL.ImageTk import PhotoImage

    matrix = []
    buttons = []

    if default_size is None:
        instructions = """n: New Map
s: Save Map
o/l: Open Map"""
    else:
        instructions = ''
    instructions = Label(widget, text=instructions)
    instructions.pack()

    def create_new_map(width, height):
        matrix[:] = create_matrix(width, height)
        instructions.destroy()
        for old_button in buttons:
            old_button.destroy()
        buttons[:] = []
        for x in range(width):
            for y in range(height):
                # new_button = Button(widget, photoimage=)
                buttons.append()

    if allow_new:
        def new_map(event):
            dialog = Toplevel(widget)
            form = Frame(dialog)
            Label(form, text='Width:').grid(row=0, column=0)
            Label(form, text='Height:').grid(row=1, column=0)
            size = [1, 1]
            comm = (lambda ix: (lambda event=None: size.__setitem__(ix, wb.get() + (event.char if event else ''))))
            wv = IntVar(value=10)
            wb = Spinbox(form, from_=1, to=65535, command=comm(0), textvariable=wv)
            wb.bind('<Key>', comm(0))
            wb.grid(row=0, column=1)
            hv = IntVar(value=10)
            hb = Spinbox(form, from_=1, to=65535, command=comm(1), textvariable=hv)
            hb.bind('<Key>', comm(1))
            hb.grid(row=1, column=1)
            form.pack()
            dialog.transient(widget)
            dialog.grab_set()
            wb.focus_set()
            widget.wait_window(dialog)
            create_new_map(wv.get(), hv.get())
        widget.bind('n', new_map)
        widget.bind('N', new_map)

    if allow_save:
        def save_map(event):
            ...
        widget.bind('s', save_map)
        widget.bind('S', save_map)

    if allow_load:
        def load_map(event):
            ...
        widget.bind('o', load_map)
        widget.bind('l', load_map)
        widget.bind('O', load_map)
        widget.bind('L', load_map)

    import glob
    images = {x: PhotoImage(file=next(glob.iglob(os.path.join('img', str(x) + '*')))) for x in matrix_labels}
    buttons = {'w': 'up', 'a': 'left', 's': 'down', 'd': 'right', '<space>': None}
Beispiel #10
0
 def bind(self, widget: Widget, action: T_ActionCallable):
     widget.bind(self.value, action)