| 1 | n/a | # general purpose 'tooltip' routines - currently unused in idlelib |
|---|
| 2 | n/a | # (although the 'calltips' extension is partly based on this code) |
|---|
| 3 | n/a | # may be useful for some purposes in (or almost in ;) the current project scope |
|---|
| 4 | n/a | # Ideas gleaned from PySol |
|---|
| 5 | n/a | |
|---|
| 6 | n/a | from tkinter import * |
|---|
| 7 | n/a | |
|---|
| 8 | n/a | class ToolTipBase: |
|---|
| 9 | n/a | |
|---|
| 10 | n/a | def __init__(self, button): |
|---|
| 11 | n/a | self.button = button |
|---|
| 12 | n/a | self.tipwindow = None |
|---|
| 13 | n/a | self.id = None |
|---|
| 14 | n/a | self.x = self.y = 0 |
|---|
| 15 | n/a | self._id1 = self.button.bind("<Enter>", self.enter) |
|---|
| 16 | n/a | self._id2 = self.button.bind("<Leave>", self.leave) |
|---|
| 17 | n/a | self._id3 = self.button.bind("<ButtonPress>", self.leave) |
|---|
| 18 | n/a | |
|---|
| 19 | n/a | def enter(self, event=None): |
|---|
| 20 | n/a | self.schedule() |
|---|
| 21 | n/a | |
|---|
| 22 | n/a | def leave(self, event=None): |
|---|
| 23 | n/a | self.unschedule() |
|---|
| 24 | n/a | self.hidetip() |
|---|
| 25 | n/a | |
|---|
| 26 | n/a | def schedule(self): |
|---|
| 27 | n/a | self.unschedule() |
|---|
| 28 | n/a | self.id = self.button.after(1500, self.showtip) |
|---|
| 29 | n/a | |
|---|
| 30 | n/a | def unschedule(self): |
|---|
| 31 | n/a | id = self.id |
|---|
| 32 | n/a | self.id = None |
|---|
| 33 | n/a | if id: |
|---|
| 34 | n/a | self.button.after_cancel(id) |
|---|
| 35 | n/a | |
|---|
| 36 | n/a | def showtip(self): |
|---|
| 37 | n/a | if self.tipwindow: |
|---|
| 38 | n/a | return |
|---|
| 39 | n/a | # The tip window must be completely outside the button; |
|---|
| 40 | n/a | # otherwise when the mouse enters the tip window we get |
|---|
| 41 | n/a | # a leave event and it disappears, and then we get an enter |
|---|
| 42 | n/a | # event and it reappears, and so on forever :-( |
|---|
| 43 | n/a | x = self.button.winfo_rootx() + 20 |
|---|
| 44 | n/a | y = self.button.winfo_rooty() + self.button.winfo_height() + 1 |
|---|
| 45 | n/a | self.tipwindow = tw = Toplevel(self.button) |
|---|
| 46 | n/a | tw.wm_overrideredirect(1) |
|---|
| 47 | n/a | tw.wm_geometry("+%d+%d" % (x, y)) |
|---|
| 48 | n/a | self.showcontents() |
|---|
| 49 | n/a | |
|---|
| 50 | n/a | def showcontents(self, text="Your text here"): |
|---|
| 51 | n/a | # Override this in derived class |
|---|
| 52 | n/a | label = Label(self.tipwindow, text=text, justify=LEFT, |
|---|
| 53 | n/a | background="#ffffe0", relief=SOLID, borderwidth=1) |
|---|
| 54 | n/a | label.pack() |
|---|
| 55 | n/a | |
|---|
| 56 | n/a | def hidetip(self): |
|---|
| 57 | n/a | tw = self.tipwindow |
|---|
| 58 | n/a | self.tipwindow = None |
|---|
| 59 | n/a | if tw: |
|---|
| 60 | n/a | tw.destroy() |
|---|
| 61 | n/a | |
|---|
| 62 | n/a | class ToolTip(ToolTipBase): |
|---|
| 63 | n/a | def __init__(self, button, text): |
|---|
| 64 | n/a | ToolTipBase.__init__(self, button) |
|---|
| 65 | n/a | self.text = text |
|---|
| 66 | n/a | def showcontents(self): |
|---|
| 67 | n/a | ToolTipBase.showcontents(self, self.text) |
|---|
| 68 | n/a | |
|---|
| 69 | n/a | class ListboxToolTip(ToolTipBase): |
|---|
| 70 | n/a | def __init__(self, button, items): |
|---|
| 71 | n/a | ToolTipBase.__init__(self, button) |
|---|
| 72 | n/a | self.items = items |
|---|
| 73 | n/a | def showcontents(self): |
|---|
| 74 | n/a | listbox = Listbox(self.tipwindow, background="#ffffe0") |
|---|
| 75 | n/a | listbox.pack() |
|---|
| 76 | n/a | for item in self.items: |
|---|
| 77 | n/a | listbox.insert(END, item) |
|---|
| 78 | n/a | |
|---|
| 79 | n/a | def _tooltip(parent): # htest # |
|---|
| 80 | n/a | top = Toplevel(parent) |
|---|
| 81 | n/a | top.title("Test tooltip") |
|---|
| 82 | n/a | x, y = map(int, parent.geometry().split('+')[1:]) |
|---|
| 83 | n/a | top.geometry("+%d+%d" % (x, y + 150)) |
|---|
| 84 | n/a | label = Label(top, text="Place your mouse over buttons") |
|---|
| 85 | n/a | label.pack() |
|---|
| 86 | n/a | button1 = Button(top, text="Button 1") |
|---|
| 87 | n/a | button2 = Button(top, text="Button 2") |
|---|
| 88 | n/a | button1.pack() |
|---|
| 89 | n/a | button2.pack() |
|---|
| 90 | n/a | ToolTip(button1, "This is tooltip text for button1.") |
|---|
| 91 | n/a | ListboxToolTip(button2, ["This is","multiple line", |
|---|
| 92 | n/a | "tooltip text","for button2"]) |
|---|
| 93 | n/a | |
|---|
| 94 | n/a | if __name__ == '__main__': |
|---|
| 95 | n/a | from idlelib.idle_test.htest import run |
|---|
| 96 | n/a | run(_tooltip) |
|---|