root.destroy()来自外部模块?

时间:2015-12-07 17:00:38

标签: python user-interface tkinter

有没有办法在点击创建根目录的文件外的模块中的注销按钮时以某种方式销毁root?例如,

def logout(self):
    self.destroy()
    root.destroy()

包含在名为Menu.py的文件中。

root = Tk()
root.title("GUI")
root.geometry('{}x{}'.format(300, 180))
lf = LoginFrame(root)
root.mainloop()

包含在名为Client.py的文件中。

我得到追溯:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Pat\AppData\Local\Programs\Python\Python35-32\lib\tkinter\__init__.py", line 1549, in __call__
    return self.func(*args)
  File "C:\Users\Pat\Documents\GitHub\DunderMifflinSales\Menu.py", line 68, in logout
    root.destroy()
NameError: name 'root' is not defined

我想使用logout函数彻底销毁所有tkinter实例。如果我在注销时排除root.destroy(),则只删除GUI的一半菜单。

我附上了我的所有代码供参考:

Client.py:

import socket
from tkinter import *
import tkinter.messagebox as tm
from tkinter import ttk
import Menu

serverName = 'localhost'
serverPort = 12000
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

class LoginFrame(Frame):

    def __init__(self, master):
        super().__init__(master)

        self.label_1 = Label(self, text="Username")
        self.label_2 = Label(self, text="Password")

        self.entry_1 = Entry(self)
        self.entry_2 = Entry(self, show="*")

        self.label_1.grid(row=0, sticky=E)
        self.label_2.grid(row=1, sticky=E)
        self.entry_1.grid(row=0, column=1)
        self.entry_2.grid(row=1, column=1)

        self.logbtn = Button(self, text="Login", command = self._login_btn_clicked)
        self.logbtn.grid(columnspan=2)

        self.pack()

    def _login_btn_clicked(self):

        username = self.entry_1.get()
        clientSocket.sendto(username.encode('UTF-8'),(serverName, serverPort))

        password = self.entry_2.get()
        clientSocket.sendto(password.encode('UTF-8'),(serverName, serverPort))

        message, address = clientSocket.recvfrom(1024)
        message = message.decode('UTF-8')

        if message == "200 OK":
            mf = Menu.MenuFrame(root)
            mf.pack(fill="both", expand=True)

        else:
            tm.showinfo(message, "Login error")

root = Tk()
root.title("GUI")
root.geometry('{}x{}'.format(300, 180))
lf = LoginFrame(root)
root.mainloop()

Menu.py:

from tkinter import *
from tkinter import ttk
import socket

serverName = 'localhost'
serverPort = 12000
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

class MenuFrame(Frame):

    def __init__(self, master):
        super().__init__(master)

        message = "GET name, sales"
        clientSocket.sendto(message.encode('UTF-8'),(serverName, serverPort))

        name, address = clientSocket.recvfrom(1024)
        name = name.decode('UTF-8')

        # sales2 is the number of sales coming from the server
        sales2, address = clientSocket.recvfrom(1024)
        sales2 = sales2.decode('UTF-8')

        # sales is the variable that will show up in the gui
        self.sales = StringVar()
        # moreSales is the user input
        self.moreSales = StringVar()
        self.sales.set(sales2)

        mainframe = ttk.Frame(self, padding="3 3 12 12")
        mainframe.grid(column = 0, row = 0, sticky = (N, W, E, S))
        mainframe.columnconfigure(0, weight = 1)
        mainframe.rowconfigure(0, weight = 1)

        welcome = "Welcome, " + name

        sales_entry = ttk.Entry(mainframe, width = 7, textvariable = self.moreSales)

        ttk.Label(mainframe, text = welcome).grid(column = 2, row = 1, sticky = W)

        ttk.Label(mainframe, text = "Current Sales:").grid(column = 1, row = 2, sticky = W)
        ttk.Label(mainframe, textvariable = self.sales).grid(column = 2, row = 2, sticky = (E))
        ttk.Label(mainframe, text = "sales").grid(column = 3, row = 2, sticky = W)

        ttk.Label(mainframe, text = "Add Sales").grid(column = 1, row = 3, sticky = W)
        sales_entry.grid(column = 2, row = 3, sticky = (W, E))
        ttk.Button(mainframe, text = "Add", command = self.add).grid(column = 3, row = 3, sticky = W)

        ttk.Button(mainframe, text = "Log Out", command = self.logout).grid(column = 2, row = 4, sticky = W)

    def add(self):

        try:
            value1 = int(self.sales.get())
            value2 = int(self.moreSales.get())
            self.sales.set(value1 + value2)


        except ValueError:
            pass

    def logout(self):

        message = self.sales.get()
        clientSocket.sendto(message.encode('UTF-8'),(serverName, serverPort))

        self.destroy()
        root.destroy()

3 个答案:

答案 0 :(得分:1)

执行所需操作的唯一方法是使logout中的函数Menu.py访问根对象。您可以通过至少几种方式来实现(这取决于您的应用程序的结构)。这是一个例子。

a.py(您的Menu.py

root = None

def logout():
    print(root)
    root.destroy()
    root.quit()

b.py(您的Client.py

import a
import tkinter as tk

root = tk.Tk()
a.root = root # Setting the global variable of the module a to this root

close = tk.Button(root, command=a.logout, text="Close")
close.pack()

root.mainloop()

答案 1 :(得分:0)

Windows引用了他们的父级。使用小部件的winfo_toplevel method来获取它。

答案 2 :(得分:-1)

您尝试在Menu.py内使用Client.py的根窗口,但您尚未导入它。试试这个而不是root.destroy()

Menu.root.destroy()