在下面的代碼片段(在convert函式中)中,狀態標簽在運行之前沒有設定為“處理中” time_consuming_func。而是在函式之后更新。我使用標簽來指示程式正在執行耗時的功能,因此這違背了擁有狀態標簽的目的。
我注意到如果我self.status.set("Processing")在標簽更新之后放置一個斷點。
我該怎么做才能正確更改狀態標簽,即在time_consuming_func?
import os
import time
import tkinter as tk
from tkinter import filedialog as fd
from tkinter import ttk
from tkinter.messagebox import showerror
from typing import Any, Tuple
WINDOW_SIZE = "550x300"
FILETYPES = (("All files", "*.*"),)
def time_consuming_func():
time.sleep(10)
print("DONE")
class NotebookTab(ttk.Frame):
def __init__(
self,
master: ttk.Notebook,
io_callbacks: Tuple[Any, Any],
**kwargs: Any,
) -> None:
if kwargs:
super().__init__(master, **kwargs)
else:
super().__init__(master)
self.ipath = tk.StringVar(self)
self.opath = tk.StringVar(self)
self.status = tk.StringVar(self, value="Idle")
assert len(io_callbacks) == 2
self.input_callback: Any = io_callbacks[0]
self.output_callback: Any = io_callbacks[1]
self.create_widgets()
def open_input(self) -> None:
if self.input_callback == fd.askopenfilename:
_input = self.input_callback(filetypes=FILETYPES)
else:
_input = self.input_callback()
if _input:
path = os.path.abspath(_input)
self.ipath.set(path)
def open_output(self) -> None:
if self.output_callback == fd.asksaveasfilename:
_output = self.output_callback(filetypes=FILETYPES)
else:
_output = self.output_callback()
if _output:
path = os.path.abspath(_output)
self.opath.set(path)
def convert(self) -> None:
inpath = self.ipath.get()
outpath = self.opath.get()
self.status.set("Processing")
#import pdb; pdb.set_trace()
try:
time_consuming_func()
# Set status to done and clear boxes
#self.status.set("Idle")
self.ipath.set("")
self.opath.set("")
except Exception:
self.status.set("ERROR")
showerror(
title="Error",
message="An unexpected error occurred."
"Close window or press OK to view traceback",
)
raise
def create_widgets(self) -> None:
statuslbl = tk.Label(self, text="Status:")
statuslbl.place(relx=0.7, rely=0.7, anchor="e")
self.statusval = tk.Label(self, textvariable=self.status)
self.statusval.place(relx=0.85, rely=0.7, anchor="e")
inputpath = tk.Entry(self, textvariable=self.ipath)
inputpath.update()
inputpath.focus_set()
inputpath.place(y=10, x=10, relwidth=0.70, height=20)
outputpath = tk.Entry(self, textvariable=self.opath)
outputpath.update()
outputpath.focus_set()
outputpath.place(y=50, x=10, relwidth=0.70, height=20)
# Buttons
open_input_button = ttk.Button(self, text="Input", command=self.open_input)
open_output_button = ttk.Button(self, text="Output", command=self.open_output)
convert_button = ttk.Button(self, text="Convert", command=self.convert)
open_input_button.pack(anchor="e", padx=20, pady=10)
open_output_button.pack(anchor="e", padx=20, pady=10)
convert_button.place(relx=0.3, rely=0.7, anchor=tk.CENTER)
def main() -> None:
# Root window
root = tk.Tk()
root.title("Converter")
root.resizable(True, True)
root.geometry(WINDOW_SIZE)
tab_parent = ttk.Notebook(root)
file_tab = NotebookTab(
tab_parent,
(fd.askopenfilename, fd.asksaveasfilename),
)
dir_tab = NotebookTab(
tab_parent,
(fd.askdirectory, fd.askdirectory),
)
tab_parent.add(file_tab, text="File")
tab_parent.add(dir_tab, text="Directory")
tab_parent.pack(expand=1, fill="both")
root.mainloop()
if __name__ == "__main__":
main()
uj5u.com熱心網友回復:
熟悉執行緒的概念。我在第 8 行和第 65 行進行了更改。但是,這意味著您的 GUI 在啟動執行緒后是被動的,這會帶來一些風險。
import os
import time
import tkinter as tk
from tkinter import filedialog as fd
from tkinter import ttk
from tkinter.messagebox import showerror
from typing import Any, Tuple
from threading import Thread
WINDOW_SIZE = "550x300"
FILETYPES = (("All files", "*.*"),)
def time_consuming_func():
time.sleep(10)
print("DONE")
class NotebookTab(ttk.Frame):
def __init__(
self,
master: ttk.Notebook,
io_callbacks: Tuple[Any, Any],
**kwargs: Any,
) -> None:
if kwargs:
super().__init__(master, **kwargs)
else:
super().__init__(master)
self.ipath = tk.StringVar(self)
self.opath = tk.StringVar(self)
self.status = tk.StringVar(self, value="Idle")
assert len(io_callbacks) == 2
self.input_callback: Any = io_callbacks[0]
self.output_callback: Any = io_callbacks[1]
self.create_widgets()
def open_input(self) -> None:
if self.input_callback == fd.askopenfilename:
_input = self.input_callback(filetypes=FILETYPES)
else:
_input = self.input_callback()
if _input:
path = os.path.abspath(_input)
self.ipath.set(path)
def open_output(self) -> None:
if self.output_callback == fd.asksaveasfilename:
_output = self.output_callback(filetypes=FILETYPES)
else:
_output = self.output_callback()
if _output:
path = os.path.abspath(_output)
self.opath.set(path)
def convert(self) -> None:
inpath = self.ipath.get()
outpath = self.opath.get()
self.status.set("Processing")
#import pdb; pdb.set_trace()
try:
t = Thread(target=time_consuming_func)
t.start()
# time_consuming_func()
# Set status to done and clear boxes
#self.status.set("Idle")
self.ipath.set("")
self.opath.set("")
except Exception:
self.status.set("ERROR")
showerror(
title="Error",
message="An unexpected error occurred."
"Close window or press OK to view traceback",
)
raise
def create_widgets(self) -> None:
statuslbl = tk.Label(self, text="Status:")
statuslbl.place(relx=0.7, rely=0.7, anchor="e")
self.statusval = tk.Label(self, textvariable=self.status)
self.statusval.place(relx=0.85, rely=0.7, anchor="e")
inputpath = tk.Entry(self, textvariable=self.ipath)
inputpath.update()
inputpath.focus_set()
inputpath.place(y=10, x=10, relwidth=0.70, height=20)
outputpath = tk.Entry(self, textvariable=self.opath)
outputpath.update()
outputpath.focus_set()
outputpath.place(y=50, x=10, relwidth=0.70, height=20)
# Buttons
open_input_button = ttk.Button(self, text="Input", command=self.open_input)
open_output_button = ttk.Button(self, text="Output", command=self.open_output)
convert_button = ttk.Button(self, text="Convert", command=self.convert)
open_input_button.pack(anchor="e", padx=20, pady=10)
open_output_button.pack(anchor="e", padx=20, pady=10)
convert_button.place(relx=0.3, rely=0.7, anchor=tk.CENTER)
def main() -> None:
# Root window
root = tk.Tk()
root.title("Converter")
root.resizable(True, True)
root.geometry(WINDOW_SIZE)
tab_parent = ttk.Notebook(root)
file_tab = NotebookTab(
tab_parent,
(fd.askopenfilename, fd.asksaveasfilename),
)
dir_tab = NotebookTab(
tab_parent,
(fd.askdirectory, fd.askdirectory),
)
tab_parent.add(file_tab, text="File")
tab_parent.add(dir_tab, text="Directory")
tab_parent.pack(expand=1, fill="both")
root.mainloop()
if __name__ == "__main__":
main()
編輯
如果您希望在啟動執行緒之前執行部分代碼,并在其他部分完成后執行,我建議將部分(例如清除條目)放在您的time_consuming_func(). 您還有其他選擇,例如從執行緒獲取回傳并處理它們,這有點復雜。
uj5u.com熱心網友回復:
您可以self.update()在嘗試之前添加,并且在convert函式中除外。
問題是什么時候self.status.set()執行,它完美地完成了它的作業,但是你使用time.sleep(10)了導致整個python解釋器延遲的問題,這可以通過使用.after方法來解決。
self.update()之所以有效,是因為它在執行之前更新了視窗time.sleep(),因此更新了整個視窗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/435631.html
上一篇:輸入正確資料后保存按鈕不起作用?
