鱼C论坛

 找回密码
 立即注册
查看: 3012|回复: 22

[已解决]tkinter: 函数中Tk()一个对象为什么在Application类中不能quit()?好像是作用域的问题

[复制链接]
发表于 2021-7-9 21:08:25 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Wirror 于 2021-7-9 21:12 编辑

class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('Form3')
        self.master.geometry('399x111')
        self.master.resizable(0,0)
        self.createWidgets()

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.orderVar = StringVar(value='')
        self.order = Entry(self.top, textvariable=self.orderVar, font=('宋体',9))
        self.order.place(relx=0.261, rely=0.36, relwidth=0.464, relheight=0.225)

        self.style.configure('Label1.TLabel',anchor='w', font=('宋体',9))
        self.Label1 = Label(self.top, text='口令', style='Label1.TLabel')
        self.Label1.place(relx=0.08, rely=0.432, relwidth=0.143, relheight=0.225)

        self.style.configure('Command1.TButton',font=('宋体',9))
        self.Command1 = Button(self.top, text='进入', command=self.Command1_Cmd, style='Command1.TButton')
        self.Command1.place(relx=0.782, rely=0.36, relwidth=0.183, relheight=0.225)


class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command1_Cmd(self, event=None):

        if self.order.get() == '12345':
            ruler_window.quit()
        else:
            pass


def gotoruler():
    ruler_window = Tk()
    ruler_window.attributes("-topmost", -1)
    Application(ruler_window).mainloop()
最佳答案
2021-7-10 11:06:16
Wirror 发表于 2021-7-10 11:00
明白了,可是如果想在1.py打开2.py写的窗口怎么实现呢?主函数只能有一个


把你之前代码最后改成这样试试看:
class Application(Application_ui):

    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command1_Cmd(self, event=None):

        if self.order.get() == '12345':
            ruler_window.quit()
            starter()
        else:
            pass

ruler_window = 0
def gotoruler():
    global ruler_window
    ruler_window = Tk()
    ruler_window.attributes("-topmost", -1)
    Application(ruler_window).mainloop()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-7-9 21:13:03 | 显示全部楼层


试试在 if 条件前面试着加上 print(self.order.get()) 调试下代码打印结果 是否符合 if 条件

另外是否有报错?有报错尽量附带报错信息~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:15:26 | 显示全部楼层

get的结果是12345

Twilight6 发表于 2021-7-9 21:13
试试在 if 条件前面试着加上 print(self.order.get()) 调试下代码打印结果 是否符合 if 条件

另外是 ...


Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:\Users\Administrator\PycharmProjects\pythonProject\管理软件\ruler.py", line 60, in Command1_Cmd
    ruler_window.quit()
NameError: name 'ruler_window' is not defined
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 21:20:37 | 显示全部楼层
本帖最后由 Twilight6 于 2021-7-9 21:21 编辑
Wirror 发表于 2021-7-9 21:15
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:%users\Administrato ...



报错是说 ruler_window 未定义, ruler_window 是函数内的局部变量,所以你把代码
ruler_window.quit()

改成这样试试看:
Application_ui.quit()

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:26:34 | 显示全部楼层
Twilight6 发表于 2021-7-9 21:20
报错是说 ruler_window 未定义, ruler_window 是函数内的局部变量,所以你把代码

TypeError: quit() missing 1 required positional argument: 'self'
少了个参数,如果用self.quit()呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:27:09 | 显示全部楼层
Wirror 发表于 2021-7-9 21:26
TypeError: quit() missing 1 required positional argument: 'self'
少了个参数,如果用self.quit()呢 ...

用self.quit()窗口并没有关闭
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 21:28:05 | 显示全部楼层
Wirror 发表于 2021-7-9 21:26
TypeError: quit() missing 1 required positional argument: 'self'
少了个参数,如果用self.quit()呢 ...




看下你完整报错,带上前面几行,你的代码不完整,我不能实时调试,那么报错就尽量发完整些~

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:28:43 | 显示全部楼层
Twilight6 发表于 2021-7-9 21:28
看下你完整报错,带上前面几行

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "C:\Users\Administrator\PycharmProjects\pythonProject\管理软件\ruler.py", line 60, in Command1_Cmd
    Application_ui.quit()
TypeError: quit() missing 1 required positional argument: 'self'
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 21:31:31 | 显示全部楼层
Wirror 发表于 2021-7-9 21:28
Exception in Tkinter callback
Traceback (most recent call last):
  File "C:%users\Administrator\ ...



报错附近,代码缩进是不是有些问题,你拷贝发我看看

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:32:52 | 显示全部楼层
Twilight6 发表于 2021-7-9 21:31
报错附近,代码缩进是不是有些问题,你拷贝发我看看

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from modify import *
import os, sys
try:
    from tkinter import *
except ImportError:  #Python 2.x
    PythonVersion = 2
    from Tkinter import *
    from tkFont import Font
    from ttk import *
    #Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
    from tkMessageBox import *
    #Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
    #import tkFileDialog
    #import tkSimpleDialog
else:  #Python 3.x
    PythonVersion = 3
    from tkinter.font import Font
    from tkinter.ttk import *
    from tkinter.messagebox import *
    #import tkinter.filedialog as tkFileDialog
    #import tkinter.simpledialog as tkSimpleDialog    #askstring()

class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('Form3')
        self.master.geometry('399x111')
        self.master.resizable(0,0)
        self.createWidgets()

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.orderVar = StringVar(value='')
        self.order = Entry(self.top, textvariable=self.orderVar, font=('宋体',9))
        self.order.place(relx=0.261, rely=0.36, relwidth=0.464, relheight=0.225)

        self.style.configure('Label1.TLabel',anchor='w', font=('宋体',9))
        self.Label1 = Label(self.top, text='口令', style='Label1.TLabel')
        self.Label1.place(relx=0.08, rely=0.432, relwidth=0.143, relheight=0.225)

        self.style.configure('Command1.TButton',font=('宋体',9))
        self.Command1 = Button(self.top, text='进入', command=self.Command1_Cmd, style='Command1.TButton')
        self.Command1.place(relx=0.782, rely=0.36, relwidth=0.183, relheight=0.225)


class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command1_Cmd(self, event=None):

        if self.order.get() == '12345':
            Application_ui.quit()
            starter()
        else:
            pass


def gotoruler():
    ruler_window = Tk()
    ruler_window.attributes("-topmost", -1)
    Application(ruler_window).mainloop()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 21:37:27 | 显示全部楼层
Wirror 发表于 2021-7-9 21:32
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from modify import *



试试这里改成这样:
class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)
        self.master = master

    def Command1_Cmd(self, event=None):

        if self.order.get() == '12345':
            self.master.quit()
            starter()
        else:
            pass


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 21:41:03 | 显示全部楼层
本帖最后由 Wirror 于 2021-7-9 21:46 编辑
Twilight6 发表于 2021-7-9 21:37
试试这里改成这样:


窗口还是没关掉
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 21:53:14 | 显示全部楼层
Wirror 发表于 2021-7-9 21:41
窗口还是没关掉



搞不懂了,呃

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 22:00:42 | 显示全部楼层
本帖最后由 Wirror 于 2021-7-9 22:03 编辑


我还有一个文件如果在主函数里Tk()一个对象窗口就可以在Application类里quit掉
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from people import *
from Main_Window import *
from tkinter import *
import tkinter.messagebox
import os, sys
try:
    from tkinter import *
except ImportError:  #Python 2.x
    PythonVersion = 2
    from Tkinter import *
    from tkFont import Font
    from ttk import *
    #Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
    from tkMessageBox import *
    #Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
    #import tkFileDialog
    #import tkSimpleDialog
else:  #Python 3.x
    PythonVersion = 3
    from tkinter.font import Font
    from tkinter.ttk import *
    from tkinter.messagebox import *
    #import tkinter.filedialog as tkFileDialog
    #import tkinter.simpledialog as tkSimpleDialog    #askstring()

class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('登录')
        self.master.geometry('900x471')
        self.master.resizable(0,0)
        self.createWidgets()

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.style.configure('Quit.TButton',font=('宋体',9))
        self.Quit = Button(self.top, text='退出', command=self.Quit_Cmd, style='Quit.TButton')
        self.Quit.place(relx=0.764, rely=0.696, relwidth=0.126, relheight=0.087)

        self.style.configure('Ok.TButton',font=('宋体',9))
        self.Ok = Button(self.top, text='登录', command=self.Ok_Cmd, style='Ok.TButton')
        self.Ok.place(relx=0.613, rely=0.696, relwidth=0.126, relheight=0.087)

        self.PassWordVar = StringVar(value='')
        self.PassWord = Entry(self.top, show='*', textvariable=self.PassWordVar, font=('宋体',9))
        self.PassWord.place(relx=0.596, rely=0.425, relwidth=0.339, relheight=0.07)

        self.WorkNumberVar = StringVar(value='')
        self.WorkNumber = Entry(self.top, textvariable=self.WorkNumberVar, font=('宋体',9))
        self.WorkNumber.place(relx=0.596, rely=0.306, relwidth=0.339, relheight=0.07)

        self.style.configure('Label2.TLabel',anchor='center', background='#3399FF', font=('宋体',14))
        self.Label2 = Label(self.top, text='', style='Label2.TLabel')
        self.Label2.place(relx=0.329, rely=0.934, relwidth=0.294, relheight=0.053)

        self.style.configure('Label1.TLabel',anchor='center', foreground='#FF8000', background='#00FFFF', font=('宋体',48))
        self.Label1 = Label(self.top, text='', style='Label1.TLabel')
        self.Label1.place(relx=0.142, rely=0.374, relwidth=0.196, relheight=0.221)

        self.style.configure('L3.TLabel',anchor='w', font=('宋体',18))
        self.L3 = Label(self.top, text='工号', style='L3.TLabel')
        self.L3.place(relx=0.516, rely=0.306, relwidth=0.072, relheight=0.07)

        self.style.configure('Label3.TLabel',anchor='w', font=('宋体',18))
        self.Label3 = Label(self.top, text='密码', style='Label3.TLabel')
        self.Label3.place(relx=0.516, rely=0.425, relwidth=0.072, relheight=0.07)

        self.style.configure('set.TButton',font=('宋体',9))
        self.set = Button(self.top, text='注册用户', command=self.set_Cmd, style='set.TButton')
        self.set.place(relx=0.853, rely=0.849, relwidth=0.108, relheight=0.046)
class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Quit_Cmd(self, event=None):
        top.quit()
    def show(self, event=None):
        top.update()
        top.deiconify()
    def Ok_Cmd(self, event=None):
        if self.PassWord.get() == '12345':
            top.withdraw()# 这里可以正常关闭

            main_window()

            top.quit()
        else:
            self.PassWord.delete(0, END)
            tkinter.messagebox.askokcancel\
                (title = '密码错误',message='密码错误!')
    def set_Cmd(self, event=None):
        people_set()

if __name__ == "__main__":
    top = Tk()
    Application(top).mainloop()
    try: top.destroy()
    except: pass
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-9 22:11:09 | 显示全部楼层

我还有一个文件,如果函数是主函数就可以

#!/usr/bin/env python
#-*- coding:utf-8 -*-
from people import *
from Main_Window import *
from tkinter import *
import tkinter.messagebox
import os, sys
try:
    from tkinter import *
except ImportError:  #Python 2.x
    PythonVersion = 2
    from Tkinter import *
    from tkFont import Font
    from ttk import *
    #Usage:showinfo/warning/error,askquestion/okcancel/yesno/retrycancel
    from tkMessageBox import *
    #Usage:f=tkFileDialog.askopenfilename(initialdir='E:/Python')
    #import tkFileDialog
    #import tkSimpleDialog
else:  #Python 3.x
    PythonVersion = 3
    from tkinter.font import Font
    from tkinter.ttk import *
    from tkinter.messagebox import *
    #import tkinter.filedialog as tkFileDialog
    #import tkinter.simpledialog as tkSimpleDialog    #askstring()

class Application_ui(Frame):
    #这个类仅实现界面生成功能,具体事件处理代码在子类Application中。
    def __init__(self, master=None):
        Frame.__init__(self, master)
        self.master.title('登录')
        self.master.geometry('900x471')
        self.master.resizable(0,0)
        self.createWidgets()

    def createWidgets(self):
        self.top = self.winfo_toplevel()

        self.style = Style()

        self.style.configure('Quit.TButton',font=('宋体',9))
        self.Quit = Button(self.top, text='退出', command=self.Quit_Cmd, style='Quit.TButton')
        self.Quit.place(relx=0.764, rely=0.696, relwidth=0.126, relheight=0.087)

        self.style.configure('Ok.TButton',font=('宋体',9))
        self.Ok = Button(self.top, text='登录', command=self.Ok_Cmd, style='Ok.TButton')
        self.Ok.place(relx=0.613, rely=0.696, relwidth=0.126, relheight=0.087)

        self.PassWordVar = StringVar(value='')
        self.PassWord = Entry(self.top, show='*', textvariable=self.PassWordVar, font=('宋体',9))
        self.PassWord.place(relx=0.596, rely=0.425, relwidth=0.339, relheight=0.07)

        self.WorkNumberVar = StringVar(value='')
        self.WorkNumber = Entry(self.top, textvariable=self.WorkNumberVar, font=('宋体',9))
        self.WorkNumber.place(relx=0.596, rely=0.306, relwidth=0.339, relheight=0.07)

        self.style.configure('Label2.TLabel',anchor='center', background='#3399FF', font=('宋体',14))
        self.Label2 = Label(self.top, text='北京自选科贸有限公司', style='Label2.TLabel')
        self.Label2.place(relx=0.329, rely=0.934, relwidth=0.294, relheight=0.053)

        self.style.configure('Label1.TLabel',anchor='center', foreground='#FF8000', background='#00FFFF', font=('宋体',48))
        self.Label1 = Label(self.top, text='自选', style='Label1.TLabel')
        self.Label1.place(relx=0.142, rely=0.374, relwidth=0.196, relheight=0.221)

        self.style.configure('L3.TLabel',anchor='w', font=('宋体',18))
        self.L3 = Label(self.top, text='工号', style='L3.TLabel')
        self.L3.place(relx=0.516, rely=0.306, relwidth=0.072, relheight=0.07)

        self.style.configure('Label3.TLabel',anchor='w', font=('宋体',18))
        self.Label3 = Label(self.top, text='密码', style='Label3.TLabel')
        self.Label3.place(relx=0.516, rely=0.425, relwidth=0.072, relheight=0.07)

        self.style.configure('set.TButton',font=('宋体',9))
        self.set = Button(self.top, text='注册用户', command=self.set_Cmd, style='set.TButton')
        self.set.place(relx=0.853, rely=0.849, relwidth=0.108, relheight=0.046)
class Application(Application_ui):
    #这个类实现具体的事件处理回调函数。界面生成代码在Application_ui中。
    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Quit_Cmd(self, event=None):
        top.quit()
    def show(self, event=None):
        top.update()
        top.deiconify()
    def Ok_Cmd(self, event=None):
        if self.PassWord.get() == '12345':
            top.withdraw()

            main_window()

            top.quit()
# 这里在类里面可以调用主函数的tk对象
        else:
            self.PassWord.delete(0, END)
            tkinter.messagebox.askokcancel\
                (title = '密码错误',message='密码错误!')
    def set_Cmd(self, event=None):
        people_set()

if __name__ == "__main__":
    top = Tk()
    Application(top).mainloop()
    try: top.destroy()
    except: pass

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-9 22:34:11 | 显示全部楼层
Wirror 发表于 2021-7-9 22:11
我还有一个文件,如果函数是主函数就可以

#!/usr/bin/env python



那我好像明白了,你先前代码的调用是如何调用的?是不是直接 gotoruler()?

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-10 10:43:46 | 显示全部楼层
Twilight6 发表于 2021-7-9 22:34
那我好像明白了,你先前代码的调用是如何调用的?是不是直接 gotoruler()?

对对
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-10 10:49:45 | 显示全部楼层



gotoruler 中创建的变量属于局部变量,你 gotoruler 函数一执行结束就导致变量被内存回收机制给回收了

所以导致你先前的窗口无法 quit,你不把他封装成函数,放在全局正常执行试试看,应该就没问题了

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-7-10 11:00:52 | 显示全部楼层
本帖最后由 Wirror 于 2021-7-10 11:03 编辑
Twilight6 发表于 2021-7-10 10:49
gotoruler 中创建的变量属于局部变量,你 gotoruler 函数一执行结束就导致变量被内存回收机制给回收 ...


明白了,可是如果想在1.py打开2.py写的窗口怎么实现呢?主函数只能有一个
得先from 2 import *
然后在用里面的函数啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-7-10 11:06:16 | 显示全部楼层    本楼为最佳答案   
Wirror 发表于 2021-7-10 11:00
明白了,可是如果想在1.py打开2.py写的窗口怎么实现呢?主函数只能有一个


把你之前代码最后改成这样试试看:
class Application(Application_ui):

    def __init__(self, master=None):
        Application_ui.__init__(self, master)

    def Command1_Cmd(self, event=None):

        if self.order.get() == '12345':
            ruler_window.quit()
            starter()
        else:
            pass

ruler_window = 0
def gotoruler():
    global ruler_window
    ruler_window = Tk()
    ruler_window.attributes("-topmost", -1)
    Application(ruler_window).mainloop()
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-14 18:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表