Display message when hovering over something with mouse cursor in Python

前端 未结 7 786
走了就别回头了
走了就别回头了 2020-12-01 10:57

I have a GUI made with TKinter in Python. I would like to be able to display a message when my mouse cursor goes, for example, on top of a label or button. The purpose of th

7条回答
  •  温柔的废话
    2020-12-01 11:25

    The best way I have found to create a popup help window is to use the tix.Balloon. I have modified it below to make it look better and show an example (note the use of tix.Tk):

    import tkinter as tk
    import tkinter.tix as tix
    
    
    class Balloon(tix.Balloon):
    
        # A modified tix popup balloon (to change the default delay, bg and wraplength)
    
        init_after = 1250  # Milliseconds
        wraplength = 300  # Pixels
    
        def __init__(self, master):
            bg = root.cget("bg")
            # Call the parent
            super().__init__(master, initwait=self.init_after)
            # Change background colour
            for i in self.subwidgets_all():
                i.config(bg=bg)
            # Modify the balloon label
            self.message.config(wraplength=self.wraplength)
    
    
    root = tix.Tk()
    
    l = tk.Label(root, text="\n".join(["text"] * 5))
    l.pack()
    
    b = Balloon(root.winfo_toplevel())
    b.bind_widget(l, balloonmsg="Some random text")
    
    root.mainloop()
    


    OLD ANSWER:

    Here is an example using and as @bryanoakley suggested with a toplevel (with overridedirect set to true). Use the hover_timer class for easy use of this. This needs the widget and help-text (with an optional delay argument - default 0.5s) and can be easily called just by initiating the class and then cancelling it.

    import threading, time
    from tkinter import *
    
    class hover_window (Toplevel):
    
        def __init__ (self, coords, text):
            super ().__init__ ()
            self.geometry ("+%d+%d" % (coords [0], coords [1]))
            self.config (bg = "white")
            Label (self, text = text, bg = "white", relief = "ridge", borderwidth = 3, wraplength = 400, justify = "left").grid ()
            self.overrideredirect (True)
            self.update ()
            self.bind ("", lambda event: self.destroy ())
    
    class hover_timer:
    
        def __init__ (self, widget, text, delay = 2):
            self.wind, self.cancel_var, self.widget, self.text, self.active, self.delay = None, False, widget, text, False, delay
            threading.Thread (target = self.start_timer).start ()
    
        def start_timer (self):
            self.active = True
            time.sleep (self.delay)
            if not self.cancel_var: self.wind = hover_window ((self.widget.winfo_rootx (), self.widget.winfo_rooty () + self.widget.winfo_height () + 20), self.text)
            self.active = False
    
        def delayed_stop (self):
            while self.active: time.sleep (0.05)
            if self.wind:
                self.wind.destroy ()
                self.wind = None
    
        def cancel (self):
            self.cancel_var = True
            if not self.wind: threading.Thread (target = self.delayed_stop).start ()
            else:
                self.wind.destroy ()
                self.wind = None
    
    def start_help (event):
        # Create a new help timer
        global h
        h = hover_timer (l, "This is some additional information.", 0.5)
    
    def end_help (event):
        # If therre is one, end the help timer
        if h: h.cancel ()
    
    if __name__ == "__main__":
    
        # Create the tkinter window
        root = Tk ()
        root.title ("Hover example")
    
        # Help class not created yet
        h = None
    
        # Padding round label
        Frame (root, width = 50).grid (row = 1, column = 0)
        Frame (root, height = 50).grid (row = 0, column = 1)
        Frame (root, width = 50).grid (row = 1, column = 2)
        Frame (root, height = 50).grid (row = 2, column = 1)
    
        # Setup the label
        l = Label (root, text = "Hover over me for information.", font = ("sans", 32))
        l.grid (row = 1, column = 1)
        l.bind ("", start_help)
        l.bind ("", end_help)
    
        # Tkinter mainloop
        root.mainloop ()
    

提交回复
热议问题