防止 Tkinter 窗口弹出一次只调用一次

问题描述

我在名为“customer.py”的文件中有一个带有标签和条目的小型测试 Tkinter 窗口 我用一个超级简单的 tkinter 窗口创建了另一个文件“button_test.py”,只有一个按钮可以调用“customer.py”

按钮调用“customer.py”没有问题,但是如果我一遍又一遍地单击按钮。不断弹出同一个窗口。我可能可以在那里添加一些条件,但我想知道是否有更好的方法来防止这种情况。我看到“Tk TopLevel”也会发生这种情况

感谢您的帮助和时间同志。

customer.py

from tkinter import *


class OFFLINE():
    def __init__(self,window):
        self.win = window
        self.win.title("Emails")
        
        frame = LabelFrame(self.win,text = 'CUSTOMER informatION')
        frame.grid(column = 0,row = 0,)    
        
        Label(frame,text = "Case Number").grid(column = 0,row = 1)
        self.Case_Box = Entry(frame).grid(column = 1,row = 1)
        
        Label(frame,text = "Customer Name").grid(column = 0,row = 2)
        self.name_Box = Entry(frame).grid(column = 1,row = 2)
        
        Label(frame,text = "Phone number").grid(column = 0,row = 3)
        self.phone_Box = Entry(frame).grid(column = 1,row = 3)

        Label(frame,text = "Email").grid(column = 0,row =4)
        self.email_Box = Entry(frame).grid(column =1,row = 4)
        
        
        
def main():
    root = Tk()
    application = OFFLINE(root)
    root.mainloop()
    
if __name__ == '__main__':
    main()

button_test.py

import customer
from tkinter import *

offline = customer

window = Tk()

button = Button(window,text = "Click Me",command =offline.main)


button.pack()

window.mainloop()

解决方法

您可以禁用按钮

button['state'] = 'disabled'

然后启用它

button['state'] = 'normal'

或者你可以使用 .grab_set() 来制作 modal 窗口,第一个窗口不会得到键/鼠标事件。


最少的工作代码

from tkinter import *

def set_disabled():
    button1['state'] = 'disabled'

def set_normal():
    button1['state'] = 'normal'
    
window = Tk()

button1 = Button(window,text = "Click Me",command=set_disabled)
button1.pack()

button2 = Button(window,text = "Next Me",command=set_normal)
button2.pack()

window.mainloop()

编辑:

第二个窗口的示例。

它展示了如何用 Toplevel() 代替 od second Tk() 而没有第二个 `mainloop()

import tkinter as tk   # PEP8: `import *` is not preferred

# --- functions ---

def close_window():
    top_window.destroy()
    
    button_open['state'] = 'normal'
    
def open_window():
    global top_window  # to keep value in external variable
    global button_close  # to keep value in external variable
    
    button_open['state'] = 'disabled'

    top_window = tk.Toplevel(window)
    
    label = tk.Label(top_window,text="New Window")
    label.pack()
    
    button_close = tk.Button(top_window,text = "Close",command=close_window)
    button_close.pack()
        
# --- main ---

window = tk.Tk()

button_open = tk.Button(window,text="Open",command=open_window)
button_open.pack()

window.mainloop()

编辑:

使用 grab_set() 制作窗口 modal 的示例

import tkinter as tk   # PEP8: `import *` is not preferred

# --- functions ---

def open_window():

    top_window = tk.Toplevel(window)
    top_window.grab_set()
    
    label = tk.Label(top_window,command=top_window.destroy)
    button_close.pack()
        
# --- main ---

window = tk.Tk()

button_open = tk.Button(window,command=open_window)
button_open.pack()

window.mainloop()

PEP 8 -- Style Guid for Python Code

,

您可以模拟单例功能使用如下类:

customer.py

from tkinter import *

__all__ = ['main']

class OFFLINE():
    ...

class _SingletonWin(Toplevel):
    _instance = None

    def __init__(self,master=None,*args,**kw):
        super().__init__(master,**kw)
        self.form = OFFLINE(self)
        self.protocol("WM_DELETE_WINDOW",self.on_destroy)

    @classmethod
    def on_destroy(cls):
        if cls._instance:
            cls._instance.destroy()
            cls._instance = None

    @classmethod
    def get_instance(cls):
        if cls._instance is None:
            cls._instance = cls()
        return cls._instance

def main():
    return _SingletonWin.get_instance()

然后每当调用 main() 时,只会显示顶层的一个实例。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...