Skip to main content
 首页 » 编程设计

python之从 pickle 文件加载和修改 tkinter gui

2024年08月30日35虾米姐

我在从 pickle 文件加载 GUI 界面时遇到了一些问题。

我能够做我想做的事,但它并没有完全按照我的预期工作,我不确定这是正确的方法。

这是基本gui的简化示例(您不必真正阅读并深入理解它,这不是主要问题):

tableRel = {} 
master = Tk() 
tableOrders = pickle.load(open(r"\\VIERNES7-3\Documentos c\sharedTableOrders.p","rb")) 
 
 
count = 0 
lOfKeys = tableOrders.keys() 
numOfTables = len(lOfKeys) 
for rowN in range((numOfTables /10)+1):  
        for colN in range(10): 
            if count == numOfTables: 
                break 
            tableN = (colN+1)+(10*(rowN)) 
 
 
            f = Frame(master,height=600,width=200, bd=1, relief=SUNKEN) 
            f.grid(row=rowN, column=colN, pady=15, padx= 0) 
            Label(f, text="Mesa: " + str(lOfKeys[count])).pack(side = TOP) 
 
            scrollbar = Scrollbar(f, orient=VERTICAL) 
            listbox = Listbox(f, yscrollcommand=scrollbar.set, width=19) 
 
            tableRel[listbox] = lOfKeys[count] 
 
            scrollbar.config(command=listbox.yview) 
            scrollbar.pack(side=RIGHT, fill=Y) 
            listbox.pack(side=TOP) 
            listbox.bind("<Double-Button-1>", hideOrder) 
            listbox.bind("<Return>", hideOrder) 
 
            index = 0 
            listbox.delete(0, END) 
            for y in tableOrders[lOfKeys[count]]["orders"]: 
                #print tableOrders[x] 
                if (y["kitchen"] == "si" or y["category"] != "Bebidas") and y["ready"] == "no": 
                    listbox.insert(END, y["name"]) 
                    #ordersByIndex[index] = y["name"] 
                    if y["canceled"] == "si": 
                        listbox.itemconfig(index, bg="red") 
                    #tablesByIndex[index] = x              
                    index += 1 
 
 
            count += 1 
 
 
loadFile() 
mainloop() 

现在这是我感到困惑的部分,我没有正确理解无限循环的 mainloop() 的概念。

它一遍又一遍到底做了什么?

让我烦恼的是,如果我在文件的任何地方放置一个打印语句,它不会一遍又一遍地打印,所以它不会重新执行文件的代码。

我基本上要实现的是,在一段时间后,gui 会重新加载,如果 picker 文件发生变化,gui 就会更新。

我能够通过将我的代码放在一个函数中(我们称它为 updateGUI)并执行 master.after(5000, updateGUI) 来实现这一点。

这似乎不是最好的解决方案,因为一切都会突然改变(列表框中的选定选项和滚动),但我想这一切都可以通过记住状态并强加它来解决。

但我想知道是否有某种方法可以利用主循环并在文件发生更改时使 gui“更新”(它不必查找文件中的更改,它必须每 10 次更新一次秒左右,然后重新绘制屏幕。)

我已经尝试过 update 和 update_idletasks 但似乎都没有重新加载 pickle 并根据 pickle 中的新信息重新绘制它。

请您参考如下方法:

主循环是您的根小部件监听和响应输入和其他事件的地方,例如鼠标点击、按键和来自操作系统的信号。通过使用 after,您是利用主循环每 n 秒调用您的更新过程。

您还可以做的是跟踪界面空闲的时间(没有鼠标或键盘事件)。如果它处于空闲状态并且有更改要显示,您可以立即更新它。如果它不空闲,给用户一个指示符和一种手动触发更新的方法,直到它再次空闲。这样,用户的工作就不会因更新而中断。

这是一个根据鼠标移动或击键重置的计时器的简单示例。

import Tkinter as tk 
 
class App(): 
    def __init__(self, tick): 
        self.tick = tick 
        self.idle_time = 0 
 
        self.root = tk.Tk() 
        frame = tk.Frame(self.root, width=100, height=100) 
        frame.bind_all("<Motion>", self.reset_idle) 
        frame.bind_all("<Key>", self.reset_idle) 
        frame.pack() 
 
        self.root.after(self.tick, self.update_timer) 
        self.root.mainloop() 
 
    def update_timer(self): 
        print('Idle for %sms' % self.idle_time) 
        self.idle_time += self.tick 
        self.root.after(self.tick, self.update_timer) 
 
    def reset_idle(self, event): 
        self.idle_time = 0 
 
app = App(1000)