ttk 菜单不会取消发布
ttk Menu wont unpost
我想制作一个简单的弹出消息,当鼠标进入时显示选项的名称,并在鼠标离开时隐藏。
这个图标是按钮内的图像,我已经能够在使用菜单小部件输入按钮时显示消息,但是当鼠标离开按钮时它不会取消发布,除非有点击。
我试过删除级联,但是还是一样,不同的是那个时候他的菜单没有文字。
我也尝试 .destroy()
菜单对象,但它什么也没做。
from tkinter import *
from tkinter import ttk
from pyautogui import position
Raiz = Tk()
Raiz.title("Mi app")
Ancho = Raiz.winfo_screenwidth()
Alto = Raiz.winfo_screenheight()
Raiz.geometry("{}x{}".format(Ancho, Alto))
Raiz.config(bg="#F4F4F4")
def Despliega(Texto):
global MenuDesplegable
MenuDesplegable = Menu(master=None, tearoff=0, activebackground='#F0F0F0')
MenuDesplegable.add_cascade(label=Texto)
MenuDesplegable.post(position().x, position().y)
def Repliega():
global MenuDesplegable
#MenuDesplegable.delete(0) -- dosen't work
#MenuDesplegable.unpost() -- dosen't work
#MenuDesplegable.destroy() -- dosen't work
Raiz.columnconfigure(0, weight=1)
BarraMenu = Frame(Raiz, bg="light grey", height=50, width="{}".format(Ancho),
bd="4", relief="groove")
BarraMenu.grid(row=0, column=0, sticky="nsew")
I_Abrir = PhotoImage(file="Abrir.png")
B_Abrir = Button(BarraMenu, bg="light grey", image=I_Abrir, bd=0)
B_Abrir.grid(row=0, column=0, padx=10)
B_Abrir.bind('<Enter>', lambda event: Despliega('Abrir'))
B_Abrir.bind('<Leave>', lambda event: Repliega())
I_Nuevo = PhotoImage(file="Nuevo.png")
B_Nuevo = Button(BarraMenu, bg="light grey", image=I_Nuevo, bd=0)
B_Nuevo.grid(row=0, column=1, padx=10)
B_Nuevo.bind('<Enter>', lambda event: Despliega('Nuevo'))
B_Nuevo.bind('<Leave>', lambda event: Repliega())
Raiz.mainloop()
如果有人能理解为什么它不像我描述的那样工作,那就太好了。
另外,如果有人知道用一点延迟显示消息的方法,请告诉我。
显然Windows无法识别取消发布命令(更多信息:https://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm#M45 & https://wiki.tcl-lang.org/page/How+do+you+unpost+a+menu)
我提出的解决方案如下:
def Despliega(Texto):
global MenuDesplegable
MenuDesplegable = Label(master=None, bg="#F4F4F4", text=str(Texto),relief='ridge', bd=3, width=len(Texto)+2)
x = Raiz.winfo_pointerx()
y = Raiz.winfo_pointery()
abs_coord_x = Raiz.winfo_pointerx() - Raiz.winfo_rootx()
abs_coord_y = Raiz.winfo_pointery() - Raiz.winfo_rooty()
MenuDesplegable.place(x = abs_coord_x, y = abs_coord_y)
def Repliega():
global MenuDesplegable
MenuDesplegable.destroy()
这个拖曳方法在光标进入其中一个按钮时在鼠标位置放置一个Tkinter.Label
,并在它离开按钮时销毁它。
效果很好,但是当鼠标放在 Label 上时它会做一些很少的事情。
您可以创建一个 class 将小部件和消息作为参数,然后应用于需要该信息的任何小部件。
import tkinter as tk
root = tk.Tk()
class CreateToolTip:
def __init__(self, widget, text='widget info'):
self.waittime = 100 #500 #miliseconds
self.wraplength = 180 #pixels
self.widget = widget
self.text = text
self.widget.bind("<Enter>", self.enter)
self.widget.bind("<Leave>", self.leave)
self.widget.bind("<ButtonPress>", self.leave)
self.id = None
self.tw = None
def enter(self, event=None):
self.schedule()
def leave(self, event=None):
self.unschedule()
self.hidetip()
def schedule(self):
self.unschedule()
self.id = self.widget.after(self.waittime, self.showtip)
def unschedule(self):
id = self.id
self.id = None
if id:
self.widget.after_cancel(id)
def showtip(self, event=None):
x = y = 0
x, y, cx, cy = self.widget.bbox("insert")
x += self.widget.winfo_rootx() + 25
y += self.widget.winfo_rooty() + 40
# creates a toplevel window
self.tw = tk.Toplevel(self.widget)
# Leaves only the label and removes the app window
self.tw.wm_overrideredirect(True)
self.tw.wm_geometry("+%d+%d" % (x, y))
label = tk.Label(self.tw, text=self.text, justify='left',
background="#ffffff", relief='solid', borderwidth=1,
wraplength = self.wraplength)
label.pack(ipadx=1)
def hidetip(self):
tw = self.tw
self.tw= None
if tw:
tw.destroy()
a = tk.Button(root,text="Something")
a.pack()
CreateToolTip(a,"This is something button")
b = tk.Button(root,text="Another")
b.pack()
CreateToolTip(b,"This is another button")
root.mainloop()
我想制作一个简单的弹出消息,当鼠标进入时显示选项的名称,并在鼠标离开时隐藏。
这个图标是按钮内的图像,我已经能够在使用菜单小部件输入按钮时显示消息,但是当鼠标离开按钮时它不会取消发布,除非有点击。
我试过删除级联,但是还是一样,不同的是那个时候他的菜单没有文字。
我也尝试 .destroy()
菜单对象,但它什么也没做。
from tkinter import *
from tkinter import ttk
from pyautogui import position
Raiz = Tk()
Raiz.title("Mi app")
Ancho = Raiz.winfo_screenwidth()
Alto = Raiz.winfo_screenheight()
Raiz.geometry("{}x{}".format(Ancho, Alto))
Raiz.config(bg="#F4F4F4")
def Despliega(Texto):
global MenuDesplegable
MenuDesplegable = Menu(master=None, tearoff=0, activebackground='#F0F0F0')
MenuDesplegable.add_cascade(label=Texto)
MenuDesplegable.post(position().x, position().y)
def Repliega():
global MenuDesplegable
#MenuDesplegable.delete(0) -- dosen't work
#MenuDesplegable.unpost() -- dosen't work
#MenuDesplegable.destroy() -- dosen't work
Raiz.columnconfigure(0, weight=1)
BarraMenu = Frame(Raiz, bg="light grey", height=50, width="{}".format(Ancho),
bd="4", relief="groove")
BarraMenu.grid(row=0, column=0, sticky="nsew")
I_Abrir = PhotoImage(file="Abrir.png")
B_Abrir = Button(BarraMenu, bg="light grey", image=I_Abrir, bd=0)
B_Abrir.grid(row=0, column=0, padx=10)
B_Abrir.bind('<Enter>', lambda event: Despliega('Abrir'))
B_Abrir.bind('<Leave>', lambda event: Repliega())
I_Nuevo = PhotoImage(file="Nuevo.png")
B_Nuevo = Button(BarraMenu, bg="light grey", image=I_Nuevo, bd=0)
B_Nuevo.grid(row=0, column=1, padx=10)
B_Nuevo.bind('<Enter>', lambda event: Despliega('Nuevo'))
B_Nuevo.bind('<Leave>', lambda event: Repliega())
Raiz.mainloop()
如果有人能理解为什么它不像我描述的那样工作,那就太好了。 另外,如果有人知道用一点延迟显示消息的方法,请告诉我。
显然Windows无法识别取消发布命令(更多信息:https://www.tcl.tk/man/tcl8.6/TkCmd/menu.htm#M45 & https://wiki.tcl-lang.org/page/How+do+you+unpost+a+menu)
我提出的解决方案如下:
def Despliega(Texto):
global MenuDesplegable
MenuDesplegable = Label(master=None, bg="#F4F4F4", text=str(Texto),relief='ridge', bd=3, width=len(Texto)+2)
x = Raiz.winfo_pointerx()
y = Raiz.winfo_pointery()
abs_coord_x = Raiz.winfo_pointerx() - Raiz.winfo_rootx()
abs_coord_y = Raiz.winfo_pointery() - Raiz.winfo_rooty()
MenuDesplegable.place(x = abs_coord_x, y = abs_coord_y)
def Repliega():
global MenuDesplegable
MenuDesplegable.destroy()
这个拖曳方法在光标进入其中一个按钮时在鼠标位置放置一个Tkinter.Label
,并在它离开按钮时销毁它。
效果很好,但是当鼠标放在 Label 上时它会做一些很少的事情。
您可以创建一个 class 将小部件和消息作为参数,然后应用于需要该信息的任何小部件。
import tkinter as tk
root = tk.Tk()
class CreateToolTip:
def __init__(self, widget, text='widget info'):
self.waittime = 100 #500 #miliseconds
self.wraplength = 180 #pixels
self.widget = widget
self.text = text
self.widget.bind("<Enter>", self.enter)
self.widget.bind("<Leave>", self.leave)
self.widget.bind("<ButtonPress>", self.leave)
self.id = None
self.tw = None
def enter(self, event=None):
self.schedule()
def leave(self, event=None):
self.unschedule()
self.hidetip()
def schedule(self):
self.unschedule()
self.id = self.widget.after(self.waittime, self.showtip)
def unschedule(self):
id = self.id
self.id = None
if id:
self.widget.after_cancel(id)
def showtip(self, event=None):
x = y = 0
x, y, cx, cy = self.widget.bbox("insert")
x += self.widget.winfo_rootx() + 25
y += self.widget.winfo_rooty() + 40
# creates a toplevel window
self.tw = tk.Toplevel(self.widget)
# Leaves only the label and removes the app window
self.tw.wm_overrideredirect(True)
self.tw.wm_geometry("+%d+%d" % (x, y))
label = tk.Label(self.tw, text=self.text, justify='left',
background="#ffffff", relief='solid', borderwidth=1,
wraplength = self.wraplength)
label.pack(ipadx=1)
def hidetip(self):
tw = self.tw
self.tw= None
if tw:
tw.destroy()
a = tk.Button(root,text="Something")
a.pack()
CreateToolTip(a,"This is something button")
b = tk.Button(root,text="Another")
b.pack()
CreateToolTip(b,"This is another button")
root.mainloop()