python - Python3 tk, tooltip on canvas area -


i'm trying figure out how can make tooltip appear on canvas area bounded box. ideally, tooltip appear if user hovers on point , within margin of error of 10 pixels.

import tkinter tk; idlelib.tooltip import tooltip;  windowwidth = 960; windowheight = 720; canvaswidth = windowwidth - 10; canvasheight = windowheight - 10;  ''' main window ''' root = tk.tk(); root.resizable(width=false, height=false); root.geometry('{}x{}'.format(windowwidth, windowheight)); root.title('sample');  ''' canvas ''' canvas = tk.canvas(root,               width = canvaswidth,               height = canvasheight,               bg = 'grey'); canvas.pack(side = tk.right, padx = 5);  xo = canvaswidth / 2 yo = canvasheight / 2; point = canvas.create_rectangle(xo - 1, yo - 1, xo + 1, yo + 1,                                 fill = 'magenta',                                 outline = 'magenta'); #tooltip(point, 'origin'); root.mainloop(0); 

actually, finished testing class creates tooltips whatever draw on canvas, addressable tag or id.

import tkinter tk import tkinter.ttk ttk   class canvastooltip:     '''     creates tooltip given canvas tag or id mouse     above it.      class has been derived original tooltip class updated     , posted stackoverflow @ following link:      https://stackoverflow.com/questions/3221956/            what-is-the-simplest-way-to-make-tooltips-in-tkinter/            41079350#41079350      alberto vassena on 2016.12.10.     '''      def __init__(self, canvas, tag_or_id,                  *,                  bg='#ffffea',                  pad=(5, 3, 5, 3),                  text='canvas info',                  waittime=400,                  wraplength=250):         self.waittime = waittime  # in miliseconds, 500         self.wraplength = wraplength  # in pixels, 180         self.canvas = canvas         self.text = text         self.canvas.tag_bind(tag_or_id, "<enter>", self.onenter)         self.canvas.tag_bind(tag_or_id, "<leave>", self.onleave)         self.canvas.tag_bind(tag_or_id, "<buttonpress>", self.onleave)         self.bg = bg         self.pad = pad         self.id = none         self.tw = none      def onenter(self, event=none):         self.schedule()      def onleave(self, event=none):         self.unschedule()         self.hide()      def schedule(self):         self.unschedule()         self.id = self.canvas.after(self.waittime, self.show)      def unschedule(self):         id_ = self.id         self.id = none         if id_:             self.canvas.after_cancel(id_)      def show(self, event=none):         def tip_pos_calculator(canvas, label,                                *,                                tip_delta=(10, 5), pad=(5, 3, 5, 3)):              c = canvas              s_width, s_height = c.winfo_screenwidth(), c.winfo_screenheight()              width, height = (pad[0] + label.winfo_reqwidth() + pad[2],                              pad[1] + label.winfo_reqheight() + pad[3])              mouse_x, mouse_y = c.winfo_pointerxy()              x1, y1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]             x2, y2 = x1 + width, y1 + height              x_delta = x2 - s_width             if x_delta < 0:                 x_delta = 0             y_delta = y2 - s_height             if y_delta < 0:                 y_delta = 0              offscreen = (x_delta, y_delta) != (0, 0)              if offscreen:                  if x_delta:                     x1 = mouse_x - tip_delta[0] - width                  if y_delta:                     y1 = mouse_y - tip_delta[1] - height              offscreen_again = y1 < 0  # out on top              if offscreen_again:                 # no further checks done.                  # tip:                 # further mod might automagically augment                 # wraplength when tooltip high                 # kept inside screen.                 y1 = 0              return x1, y1          bg = self.bg         pad = self.pad         canvas = self.canvas          # creates toplevel window         self.tw = tk.toplevel(canvas.master)          # leaves label , removes app window         self.tw.wm_overrideredirect(true)          win = tk.frame(self.tw,                        background=bg,                        borderwidth=0)         label = ttk.label(win,                           text=self.text,                           justify=tk.left,                           background=bg,                           relief=tk.solid,                           borderwidth=0,                           wraplength=self.wraplength)          label.grid(padx=(pad[0], pad[2]),                    pady=(pad[1], pad[3]),                    sticky=tk.nsew)         win.grid()          x, y = tip_pos_calculator(canvas, label)          self.tw.wm_geometry("+%d+%d" % (x, y))      def hide(self):         if self.tw:             self.tw.destroy()         self.tw = none   if __name__ == '__main__':      import random      def further_text():         info_text = ('\n\ngo on rectangle mouse pointer see '                      'changing yellow , stay on long enough (less '                      'a second) let show own customized '                      'canvastooltip instance.\n\n'                       'click once using mouse left button on rectangle '                      'to start dragging desired new position , '                      'release left button when done.\n\n'                       'double click inside canvas using mouse left '                      'button redraw new set of rectangles.\n\n'                      'hth. ;) alberto vassena')          # texts generated @ http://lorem-ipsum.perbang.dk/         short_text = ('lorem ipsum dolor sit amet, mauris tellus, '                       'porttitor torquent eu. magna aliquet lorem, '                       'cursus sit ac, in in. dolor aliquet, cum integer. '                       'proin aliquet, porttitor pulvinar mauris. tellus '                       'lectus, amet cras, neque lacus quis. malesuada '                       'nibh. eleifend nam, in eget a. nec turpis, erat '                       'wisi semper')         medium_text = ('lorem ipsum dolor sit amet, suspendisse aenean '                        'ipsum sollicitudin, pellentesque nunc ultrices ac '                        'ut, arcu elit turpis senectus convallis. ac orci '                        'pretium sed gravida, tortor nulla felis '                        'consectetuer, mauris egestas est erat. ut enim '                        'tellus @ diam, ac sagittis vel proin. massa '                        'eleifend orci tortor sociis, scelerisque in pede '                        'metus phasellus, est tempor gravida nam, ante '                        'fusce sem tempor. mi diam auctor vel pede, mus '                        'non mi luctus luctus, lectus sit varius repellat '                        'eu')         long_text = ('lorem ipsum dolor sit amet, velit eu nam cursus '                      'quisque gravida sollicitudin, felis arcu interdum '                      'error quam quis massa, et velit libero ligula est '                      'donec. suspendisse fringilla urna ridiculus dui '                      'volutpat justo, quisque nisl eget sed blandit '                      'egestas, libero nullam magna sem dui nam, auctor '                      'vehicula nunc arcu vel sed dictum, tincidunt vitae '                      'id tristique aptent platea. lacus eros nec proin '                      'morbi sollicitudin integer, montes suspendisse '                      'augue lorem iaculis sed, viverra sed interdum eget '                      'ut @ pulvinar, turpis vivamus ac pharetra nulla '                      'maecenas ut. consequat dui condimentum lectus nulla '                      'vitae, nam consequat fusce ac facilisis eget orci, '                      'cras enim donec aenean sed dolor aliquam, elit '                      'lorem in nec fringilla, malesuada curabitur diam '                      'nonummy nisl nibh ipsum. in odio nunc nec porttitor '                      'ipsum, nunc ridiculus platea wisi turpis praesent '                      'vestibulum, suspendisse hendrerit amet quis vivamus '                      'adipiscing elit, ut dolor nec nonummy mauris nec '                      'libero, ad rutrum id tristique facilisis sed '                      'ultrices. convallis velit posuere mauris lectus sit '                      'turpis, lobortis volutpat et placerat leo '                      'malesuada, vulputate id maecenas @ volutpat '                      'vulputate, est augue nec proin ipsum pellentesque '                      'fringilla. mattis feugiat metus ultricies repellat '                      'dictum, suspendisse erat rhoncus ultricies in ipsum, '                      'nulla ante pellentesque blandit ligula sagittis '                      'ultricies, sed tortor sodales pede et duis platea')          text = random.choice([short_text, medium_text, long_text,                               info_text, info_text, info_text])          return 'further info: ' + text       class mycanvas(tk.canvas):          def clear(self):             self.delete('rectangle')          def draw(self):             width, height = int(self['width']), int(self['height'])              colors = ('blue', 'green', 'red',                       'brown', 'cyan', 'magenta',                       'violet', 'black', 'white')              self.tooltips = []              mask = '{} rectangle #{}.\n'             in range(20):                 x, y = random.randint(0, width - 1), random.randint(0, height - 1)                 w, h = random.randint(5, 100), random.randint(5, 100)                 tag = 'r{}'.format(i)                 color = random.choice(colors)                 text = mask.format(color.capitalize(), tag[1:]) + further_text()                  id_ = self.create_rectangle(x, y, x + w, y + h,                                             fill=color,                                             activefill='yellow',                                             tags=('rectangle', tag))                  tooltip = canvastooltip(self, id_, text=text)                  self.tooltips.append(tooltip)          def redraw(self, event):             self.clear()             self.draw()          def onclick(self, event):             coords = self.canvasx(event.x, 1), self.canvasy(event.y, 1)             found = self.find_closest(*coords)[0]              if found:                 self.target = found                 self.drag_x, self.drag_y = coords                 self.tag_raise(found)              else:                 self.target, self.drag_x, self.drag_y = none, none, none          def ondrag(self, event):             if self.target none:                 return              coords = self.canvasx(event.x, 1), self.canvasy(event.y, 1)              self.move(self.target,                       coords[0] - self.drag_x,                       coords[1] - self.drag_y)              self.drag_x, self.drag_y = coords          def onrelease(self, event):             self.target, self.drag_x, self.drag_y = none, none, none       def main():         root = tk.tk()         frame = ttk.frame(root)          c = frame.canvas = mycanvas(frame.master, width=800, height=600)         c.draw()         c.bind('<double-button-1>', c.redraw)         c.tag_bind('rectangle', '<button-1>', c.onclick)         c.tag_bind('rectangle', '<b1-motion>', c.ondrag)         c.tag_bind('rectangle', '<buttonrelease-1>', c.onrelease)         c.grid(column=0, row=0, padx=(0, 0), pady=(0, 0))          frame.grid()         root.mainloop()       main() 

hth. in post, in answer, instead, find same solution (with minor changes) can applied other widgets, such buttons, labels , checkboxes.


Comments

Popular posts from this blog

sql server - Cannot query correctly (MSSQL - PHP - JSON) -

php - trouble displaying mysqli database results in correct order -

C++ Linked List -