tkinter 如何退出,具体是在多线程下面如何退出

2018-09-19 19:36:37 +08:00
 qile1

弄了一个 windown10 后台循环读文件程序。程序运行后最小化到桌面右下角。在右下角图标上面有 3 个功能菜单,一个显示“配置参数”界面,一个显示“运行列表”界面,一个退出按钮

“配置参数”界面可以正常显示关闭。 “运行列表”界面关闭后,点击桌面右下角退出按钮后,程序退出隔一会儿会报错,报错内容如下:

Exception ignored in: <bound method Variable.__del__ of <tkinter.StringVar object at 0x03DFAEF0>>
Traceback (most recent call last):
  File "C:\Users\85447\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 329, in __del__
    if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
RuntimeError: main thread is not in main loop
Tcl_AsyncDelete: async handler deleted by the wrong thread

此段代码可能是产生报错原因

instrserial_button = Entry(self, textvariable=self.dec_name_dict[dish], width=15,
                                           bg='white',state='readonly')#.grid(row=j, column=3)

使用 sysTrayIcon 做的桌面右下角图标,主要代码摘抄这里

def showRegSet_sys(sysTrayIcon):
    try:
        title = u'reg instrserial(NET)'
        w1hd2 = win32gui.FindWindow(0, title)
        # w1hd = 0
        print ("w1hd2",w1hd2)
        if w1hd2 ==0:
            #print ("w1hd==0")
            Regroot = Tk()
            # decroot.wm_attributes('-topmost',1)
            Regroot.geometry("400x300")
            app2 = regWindow(Regroot)
            def on_focus_out(event):
                if event.widget == Regroot:
                    Regroot.destroy()
                    # Regroot.quit
            Regroot.bind("<FocusOut>", on_focus_out)
            Regroot.mainloop()
        else:
            win32gui.SetForegroundWindow(w1hd2)
    except Exception as E:
        pass
        print(E)
class regWindow(Frame):#弹出桌面框显示类
    """定义一个 window 类,window 的父类是 frame,这样 window 就用了 frames 的属性和功能"""
    def __init__(self,master=NONE):
        #__int()__这里是一个构造函数
        Frame.__init__(self,master)
        self.master=master
        # self.reg_instr = p_query(
        #     """SELECT  instrid,instrserial,instrsn,register_dt,install_dt FROM lab_instrument1 order by instrid """)
        self.reg_instr = [(1, '230', '1mvpwtpkdv'), (2, '500', 'yxc3juy5p3')]
        self.initwindow()
        # self.initwindow2()

    def initwindow(self):#tkinter 模块添加按钮,相对于长提多了如下部分代码
        #设置窗体标题
        self.master.title("reg instrserial(NET)")
        self.sv = StringVar()
        self.sv2 = StringVar()
        self.pack(side="top", fill="x")
        # dishes=[("1","23"),("2","gsdf"),("3","fdgsrd"),("4","dfg")]
        self.order = {}
        self.add_buttons = {}
        self.instrserial_button_dict={}
        self.price_labels = {}
        self.order_labels = {}
        self.state_dict = {}
        self.svv2 = {}
        self.svv = {}
        self.dec_name_dict = {}
        j = 2
        self.en6 = StringVar()
        nianling2 = Entry(self, width=25, bg='white', state='readonly', textvariable=self.en6).grid(row=j-1, column=1,  columnspan=2)
        self.en6.set("uuu")
        Button_chaxun = Button(self, text='关闭', command=self.clinet_exit).grid(row=j-1, column=4)
        # Button_chaxun = Button(self, text='关闭 2', command=self.master.quit).grid(row=j - 1, column=3)
        for dish in self.reg_instr:

            self.svv[dish[0]] = StringVar()
            self.dec_name_dict[dish[0]] = StringVar()
        Label(self, text="ID").grid(row=j, column=1)
        Label(self, text="码").grid(row=j, column=2)
        for i in self.reg_instr:
            j += 2
            print("j:",j)
            # dish, price = dish_data[0], dish_data[1].encode('latin-1').decode('gbk')
            instrid, instrserial, instrsn = i
            dish = i[0]
            name = i[1].encode('latin-1').decode('gbk')
            self.state_dict[dish] = 'normal'
            self.svv2[dish] = dish
            self.dec_name_dict[dish].set(name)
            sn_code = 10
            if sn_code > 0:
                b = Entry(self, width=15, bg='white', state='readonly')#.grid(row=j, column=2)
                instrserial_button = Entry(self, textvariable=self.dec_name_dict[dish], width=15,
                                           bg='white',state='readonly')#.grid(row=j, column=3)
            else:
                pass
                # b = Entry(self, width=15, bg='white', state='readonly')
                # b = Entry(self, textvariable=self.svv[dish], validate="focusout", width=15, bg='white', state=self.state_dict[dish],
                #           validatecommand=lambda d=self.svv[dish], k=dish: self.add_dish_to_order(d, self.state_dict[dish], k))
                # instrserial_button = Entry(self, textvariable=self.dec_name_dict[dish], validate="focusout", width=15,
                #                        bg='white',state=self.state_dict[dish],
                #                        validatecommand=lambda d=self.dec_name_dict[dish],instrid=dish, k=name: self.add_dec_name(d,instrid,k))#.grid(row=j, column=3)
            # # b['state']  = 'readonly'svv2[dish]
            # #  print(dish)
            self.add_buttons[dish] = b
            self.add_buttons[dish].grid(row=j, column=2)
            self.instrserial_button_dict[dish]=instrserial_button
            self.instrserial_button_dict[dish].grid(row=j, column=3)

    def add_dish_to_order(self, d, dish, i):
        return True

    def add_dec_name(self, d, instrid, i):
        return True

    def clinet_exit(self):
        # self.master.deiconify()
        # print('showRegSet()')
        self.master.destroy()


menu_options = (('显示(S)', None,showDecSet),
                ('other', None, (('解码注册', None, showRegSet_sys),
                                 ))
               )
               

参考代码在这里 https://paste.ubuntu.com/p/VzTV26tcvc/

4452 次点击
所在节点    Python
1 条回复
qile1
2018-09-20 22:51:08 +08:00
Regroot.destroy() 已经销毁了,为啥还会提示 main thread is not in main loop

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/490944

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX