【问题标题】:Self Made Tkinter Popup Menu Python自制 Tkinter 弹出菜单 Python
【发布时间】:2018-07-30 09:43:50
【问题描述】:

我正在基于 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 运行并且事件处理程序没有激活。

反正我能做到吗? 谢谢

【问题讨论】:

    标签: python events tkinter popup


    【解决方案1】:

    我会使用跟踪变量来做到这一点。

    我们可以先将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()
    

    【讨论】:

    • 我之前尝试过非常类似的方法,但是当我在另一个地方点击时弹出菜单并没有消失,它只在点击框架按钮f时消失,所以我有绑定close_popup 事件处理程序的同样问题。
    • 好的,所以我用一个小技巧解决了自己的问题。我会发布回复。
    【解决方案2】:

    我找到了一种不需要修改太多代码的方法,跟踪变量的想法很好,但并不能解决所有问题,而这段代码可以。

    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()
    

    这样,每当我将鼠标移到父窗口上时,鼠标的&lt;Button-1&gt;就会被绑定关闭弹出菜单。 并做一个技巧,就是将菜单的按钮向下放置几个像素,这让鼠标通过弹出框到达按钮并禁用&lt;Button-1&gt; 绑定让我单击按钮。 按钮的功能激活了框架的place_forget方法,所以一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 2015-07-15
      • 2011-06-13
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      相关资源
      最近更新 更多