微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Tkinter按钮上为文本描述添加悬停功能?

如何解决如何在Tkinter按钮上为文本描述添加悬停功能?

我想在Tkinter按钮上添加一个悬停功能,如果用户将鼠标悬停在该按钮上,则会显示说明文字。我还想为该描述添加一些延迟,以免造成干扰。

我可以尝试将按钮的"<Enter>""<Leave>"绑定到一个函数上,并在应用程序的某个角落显示一些“标签”。但是这种方法可能不是最优雅的。

解决方法

以下是使用Pmw(Python大型小部件)作为工具提示的小片段。

首先安装它:

pip install Pmw

然后是以下代码段,以了解Pmw可以做什么:

from tkinter import *
import Pmw

root = Tk()

Pmw.initialise(root) #initializing it in the root window

l = Label(root,text='Random Text')
l.pack()

b = Button(root,text='Hover me')
b.pack()

tooltip_1 = Pmw.Balloon(root) #Calling the tooltip
tooltip_1.bind(b,'This is the hover Text\nHope you get an idea of whats going on here.') #binding it and assigning a text to it

root.mainloop()

希望这给您一个更好的主意。请记住,Pmw可能会在以后将py转换为exe时造成混乱(如果有任何意图)。 tho中有一个解决方法。

欢呼

,

使用tkinter可以很容易地做到这一点。通过将EnterLeave事件添加到要向其添加工具提示的任何内容,我们可以轻松地显示/隐藏所需的任何内容。在我的示例中,我使用了简化的tk.Toplevel,因此我们可以使用简单的淡入淡出动画,并且工具提示将不会局限于根窗口。

enter image description here

#widgets.py

import tkinter as tk,tkinter.ttk as ttk
from typing import Union

Widget = Union[tk.Widget,ttk.Widget]

class ToolTip(tk.Toplevel):
    #amount to adjust fade by on every animation frame
    FADE_INC:float = .07
    #amount of milliseconds to wait before next animation state
    FADE_MS :int   = 20
    
    def __init__(self,master,**kwargs):
        tk.Toplevel.__init__(self,master)
        #make window invisible,on the top,and strip all window decorations/features
        self.attributes('-alpha','-topmost',True)
        self.overrideredirect(1)
        #style and create label. you can override style with kwargs
        style = dict(bd=2,relief='raised',font='courier 10 bold',bg='#FFFF99',anchor='w')
        self.label = tk.Label(self,**{**style,**kwargs})
        self.label.grid(row=0,column=0,sticky='w')
        #used to determine if an opposing fade is already in progress
        self.fout:bool = False
        
    def bind(self,target:Widget,text:str,**kwargs):
        #bind Enter(mouseOver) and Leave(mouseOut) events to the target of this tooltip
        target.bind('<Enter>',lambda e: self.fadein(0,text,e))
        target.bind('<Leave>',lambda e: self.fadeout(1-ToolTip.FADE_INC,e))
        
    def fadein(self,alpha:float,text:str=None,event:tk.Event=None):
        #if event and text then this call came from target
        #~ we can consider this a "fresh/new" call
        if event and text:
            #if we are in the middle of fading out jump to end of fade
            if self.fout:
                self.attributes('-alpha',0)
                #indicate that we are fading in
                self.fout = False
            #assign text to label
            self.label.configure(text=f'{text:^{len(text)+2}}')
            #update so the proceeding geometry will be correct
            self.update()
            #x and y offsets
            offset_x = event.widget.winfo_width()+2
            offset_y = int((event.widget.winfo_height()-self.label.winfo_height())/2)
            #get geometry
            w = self.label.winfo_width()
            h = self.label.winfo_height()
            x = event.widget.winfo_rootx()+offset_x
            y = event.widget.winfo_rooty()+offset_y
            #apply geometry
            self.geometry(f'{w}x{h}+{x}+{y}')
               
        #if we aren't fading out,fade in
        if not self.fout:
            self.attributes('-alpha',alpha)
        
            if alpha < 1:
                self.after(ToolTip.FADE_MS,lambda: self.fadein(min(alpha+ToolTip.FADE_INC,1)))

    def fadeout(self,event:tk.Event=None):
        #if event then this call came from target 
        #~ we can consider this a "fresh/new" call
        if event:
            #indicate that we are fading out
            self.fout = True
        
        #if we aren't fading in,fade out        
        if self.fout:
            self.attributes('-alpha',alpha)
        
            if alpha > 0:
                self.after(ToolTip.FADE_MS,lambda: self.fadeout(max(alpha-ToolTip.FADE_INC,0)))

#main.py ~ EXAMPLE USAGE OOP

import tkinter as tk
from widgets import ToolTip


class Root(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        
        #instantiate ToolTip
        tt = ToolTip(self)
        
        #create first button and bind a tooltip to it
        btn = tk.Button(self,text='hover')
        btn.grid(column=0,row=0)
        tt.bind(btn,'first button is hovered')
        
        #create second button and bind a tooltip to it
        btn2 = tk.Button(self,text='hover2')
        btn2.grid(column=1,row=0)
        tt.bind(btn2,'second button is hovered')
        

if __name__ == "__main__":
    root = Root()
    root.title("ToolTip Example")
    root.mainloop()

#main.py ~ EXAMPLE USAGE PROCEDURAL

import tkinter as tk 
from widgets import ToolTip      


if __name__ == "__main__":
    root = tk.Tk()
    root.title("ToolTip Example")
    
    #instantiate ToolTip
    tt = ToolTip(root)
    
    #create first button and bind a tooltip to it
    btn = tk.Button(root,text='hover')
    btn.grid(column=0,row=0)
    tt.bind(btn,'first button is hovered')
    
    #create second button and bind a tooltip to it
    btn2 = tk.Button(root,text='hover2')
    btn2.grid(column=1,row=0)
    tt.bind(btn2,'second button is hovered')
    
    root.mainloop()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。