我正在基于tkinter的Python中编写GUI库,并且正在设计和构建所有小部件,但是我来到了PopUp菜单。 由于tkinter会选择系统菜单并且无法自定义,因此我编写了以下代码来制作一个框架,在其中可以放置自定义按钮并用作弹出窗口。
from tkinter import *
root = Tk()
w = Label(root, text="Right-click to display menu", width=40, height=20)
w.place(x=0)
def function1():
print('function1 activated')
# create a menu
f = Frame(root,width=80,height=60,background='green')
b2 = Button(f,text='function',command=function1)
b2.pack()
def open_popup(event):
try:
f.place(x=event.x, y=event.y)
root.after(1)
f.focus_set()
w.bind_all("<Button-1>",close_popup)
except:
print("Can't open popup menu")
def close_popup(event):
try:
f.place_forget()
root.after(1)
w.unbind_all("<Button-1>")
except:
print("Can't close popup menu")
w.bind("<Button-3>", open_popup)
b = Button(root, text="Quit", command=root.destroy)
b.pack()
root.mainloop()
一切正常,如果单击鼠标右键,将显示弹出菜单,如果单击其他所有部分,则弹出菜单将消失。
问题是,由于当我按下弹出菜单的按钮时bind_all
,function1
无法运行,并且事件处理程序将关闭弹出窗口。我仅尝试使用bind
,但是这次function1
运行并且事件处理程序未激活。
反正我能做到吗? 谢谢
答案 0 :(得分:0)
我将使用跟踪变量来完成此操作。
我们可以先将None
分配给f
,以检查当前是否设置了f
。
如果f
不为None,则创建边框和按钮。然后,当激活该功能时,我们可以运行功能并破坏按钮所在的框架。这也破坏了按钮,然后将f
设置回None
以便下次使用。
看看下面重新制作的示例。 如果您有任何问题,请告诉我。
from tkinter import *
root = Tk()
w = Label(root, text="Right-click to display menu", width=40, height=20)
w.place(x=0)
f = None # Tracking F to see if it is None or not.
def function1():
global f
print('function1 activated')
# add this to the end of the function to destroy the frame and reset f
if f != None:
f.destroy()
f = None
def open_popup(event):
global f
# if f is None then create frame and button else don't
if f == None:
f = Frame(root,width=80,height=60,background='green')
f.place(x=event.x, y=event.y)
b2 = Button(f,text='function',command=function1)
b2.pack()
else:
print("Can't open popup menu")
w.bind("<Button-3>", open_popup)
b = Button(root, text="Quit", command=root.destroy)
b.pack()
root.mainloop()
答案 1 :(得分:0)
我找到了一种无需过多修改代码即可完成此操作的方法,跟踪变量的想法很好,但不能解决所有问题,而此代码确实可以解决。
from tkinter import *
root = Tk()
w = Label(root, text="Right-click to display menu", width=40, height=20)
w.pack()
def function1():
print('function1 activated')
try:
f.place_forget()
except:
pass
# create a menu
f = Frame(root,width=80,height=60,background='green')
b2 = Button(f,text='function',command=function1)
b2.place(x=0,y=5)
def open_popup(event):
try:
f.place(x=event.x, y=event.y)
root.after(1)
f.focus_set()
except:
pass
def close_popup(event):
try:
f.place_forget()
root.after(1)
w.unbind_all("<Button-1>")
except:
pass
def enable_depopup(event):
w.bind_all("<Button-1>",close_popup)
def disable_depopup(event):
w.unbind_all("<Button-1>")
w.bind("<Button-3>", open_popup)
w.bind("<Motion>", enable_depopup)
f.bind("<Motion>", disable_depopup)
b = Button(root, text="Quit", command=root.destroy)
b.pack()
root.mainloop()
通过这种方式,每当我将鼠标移到父窗口上时,鼠标的<Button-1>
就会被绑定以关闭弹出菜单。
然后做一个技巧,那就是将菜单的按钮向下放置几个像素,这使鼠标通过弹出框到达该按钮,并禁用<Button-1>
绑定,让我单击该按钮。
该按钮的功能激活了框架的place_forget
方法,因此一切正常。