【问题标题】:Prevent Tkinter window to pop up once is called only once防止 Tkinter 窗口弹出一次只调用一次
【发布时间】:2021-04-30 02:51:29
【问题描述】:

我在一个名为“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' ?
  • 您应该只使用Tk 来创建主窗口——其次您应该使用Toplevel。你应该只使用一个mainloop()。如果你有两个mainloop,那么一些 tkinter 的变量可能工作不正常并且它们可能有错误的值。

标签: python class tkinter toplevel gtkbutton


【解决方案1】:

您可以禁用按钮

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() 而不是第二个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, text="New Window")
    label.pack()
    
    button_close = tk.Button(top_window, text = "Close", command=top_window.destroy)
    button_close.pack()
        
# --- main ---

window = tk.Tk()

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

window.mainloop()

PEP 8 -- Style Guid for Python Code

【讨论】:

    【解决方案2】:

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

    customer.py

    from tkinter import *
    
    __all__ = ['main']
    
    class OFFLINE():
        ...
    
    class _SingletonWin(Toplevel):
        _instance = None
    
        def __init__(self, master=None, *args, **kw):
            super().__init__(master, *args, **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() 时,只会显示一个顶层实例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-16
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多