- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想要一个带有进度条和一些条目、标签和按钮小部件的顶级窗口/对话框。我希望从 main_window 窗口更新对话框。 main_window 完成工作,我需要将其反射(reflect)在对话框中。我希望主窗口保持事件状态,以便您可以停止该过程。我还希望能够在对话框中停止该过程。
如果不使用多处理和线程,我就无法让它工作。似乎我以错误的方式解决这个问题,还是我?另外,我是多处理和线程的新手,所以我希望无论如何我都做对了。如果有人知道更好的方法来做到这一点,请告诉我。
下面是我尝试做我想做的事情,它有效,但这是正确的方法吗?
我的第一次尝试:
import tkinter as tk
import tkinter.ttk as ttk
from time import sleep
from queue import Empty
from threading import Thread
from multiprocessing import Process, Queue
HIDE = -1
STOP = -2
BREAK = -3
PAUSE = -4
RESUME = -5
class App(tk.Tk):
def __init__(self, **kwargs):
title = kwargs.pop('title', '')
theme = kwargs.pop('theme', 'clam')
geometry = kwargs.pop('geometry', None)
exit_callback = kwargs.pop('exit_callback', None)
super().__init__(**kwargs)
self.title(title)
self.style = ttk.Style()
self.style.theme_use(theme)
if geometry:
self.geometry(geometry)
if exit_callback:
self.protocol('WM_DELETE_WINDOW', exit_callback)
def main_window(out_que, in_que, maximum):
def worker():
if app.running:
return
app.running = True
app.finished = False
for count in range(0, maximum + 1):
try:
message = in_que.get_nowait()
if message:
if message == PAUSE:
message = in_que.get()
if message == BREAK:
break
elif message == STOP:
app.destroy()
except Empty:
pass
sleep(0.1) # Simulate work.
out_que.put(count)
app.running = False
app.finished = True
start_btn.config(state=tk.NORMAL)
def app_stop():
out_que.put(STOP)
app.destroy()
def test_stop():
if app.running:
out_que.put(HIDE)
elif app.finished:
out_que.put(HIDE)
in_que.get()
stop_btn.config(state=tk.DISABLED)
start_btn.config(state=tk.NORMAL)
def test_start():
while not in_que.empty():
in_que.get()
stop_btn.config(state=tk.NORMAL)
start_btn.config(state=tk.DISABLED)
thread = Thread(target=worker, daemon=True)
thread.daemon = True
thread.start()
app = App(title='Main Window', theme='alt', geometry='350x150', exit_callback=app_stop)
app.running = False
app.finished = True
app.rowconfigure(0, weight=1)
app.rowconfigure(1, weight=1)
app.columnconfigure(0, weight=1)
start_btn = ttk.Button(app, text='Start Test', command=test_start)
start_btn.grid(padx=10, pady=5, sticky=tk.NSEW)
stop_btn = ttk.Button(app, text='Stop Test', state=tk.DISABLED, command=test_stop)
stop_btn.grid(padx=10, pady=5, sticky=tk.NSEW)
app.mainloop()
def progress_window(in_que, out_que, maximum):
def hide():
out_que.put(BREAK)
pause_btn.config(text='Pause')
app.withdraw()
def pause():
if progress_bar['value'] < progress_bar['maximum']:
text = pause_btn.cget('text')
text = 'Resume' if text == 'Pause' else 'Pause'
pause_btn.config(text=text)
out_que.put(PAUSE)
else:
pause_btn.config(text='Pause')
def worker():
while True:
data = in_que.get()
print(data)
if data == HIDE:
hide()
elif data == STOP:
app.destroy()
out_que.put(STOP)
break
elif not data:
app.deiconify()
progress_bar["value"] = 0
else:
progress_bar["value"] = data
app.update_idletasks()
app = App(title='Progress', theme='clam', geometry='350x150', exit_callback=hide)
app.rowconfigure(0, weight=1)
app.rowconfigure(1, weight=1)
app.columnconfigure(0, weight=1)
app.columnconfigure(1, weight=1)
progress_bar = ttk.Progressbar(app, orient=tk.HORIZONTAL, mode='determinate')
progress_bar["maximum"] = maximum
progress_bar.grid(padx=10, sticky=tk.EW, columnspan=1000)
pause_btn = ttk.Button(app, text='Pause', command=pause)
pause_btn.grid()
cancel_btn = ttk.Button(app, text='Cancel', command=hide)
cancel_btn.grid(row=1, column=1)
thread = Thread(target=worker)
thread.daemon = True
thread.start()
app.withdraw()
app.mainloop()
if __name__ == '__main__':
jobs = []
que1 = Queue()
que2 = Queue()
process = 50 # The maximum amount of work to process, # items.
for target in (main_window, progress_window):
p = Process(target=target, args=(que1, que2, process))
jobs.append(p)
p.start()
for j in jobs:
j.join()
import tkinter as tk
import tkinter.ttk as ttk
from time import sleep
from queue import Empty
from threading import Thread
from multiprocessing import Queue
HIDE = -1
STOP = -2
DONE = -3
BREAK = -4
PAUSE = -5
class App(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.running = False
self.finished = True
self.app_que = Queue()
self.dialog_que = Queue()
self.process_items = 50
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.columnconfigure(0, weight=1)
self.title('Main Window')
self.geometry('350x150')
self.style = ttk.Style()
self.style.theme_use('clam')
wdg = self.start_btn = ttk.Button(self, text='Start Test', command=self.test_start)
wdg.grid(padx=10, pady=5, sticky=tk.NSEW)
wdg = self.stop_btn = ttk.Button(self, text='Stop Test', state=tk.DISABLED, command=self.test_stop)
wdg.grid(padx=10, pady=5, sticky=tk.NSEW)
self.dlg = ProgressDialog(self, title='Progress', geometry='350x150', process=self.process_items)
self.dlg.app_que = self.app_que
self.dlg.dialog_que = self.dialog_que
self.protocol('WM_DELETE_WINDOW', self.app_stop)
thread = Thread(target=self.dlg.worker, daemon=True)
thread.start()
def worker(self):
self.dlg.cancel_btn.config(text='Cancel')
self.dlg.pause_btn.config(state=tk.NORMAL)
for count in range(0, self.process_items + 1):
try:
message = self.app_que.get_nowait()
if message:
if message == PAUSE:
message = self.app_que.get()
if message == BREAK:
self.stop_btn.config(state=tk.DISABLED)
break
elif message == STOP:
self.destroy()
except Empty:
pass
sleep(0.1) # Simulate work.
self.dialog_que.put(count)
self.dialog_que.put(DONE)
self.dlg.cancel_btn.config(text='Close')
self.finished = True
self.start_btn.config(state=tk.NORMAL)
self.stop_btn.config(state=tk.DISABLED)
def app_stop(self):
self.dialog_que.put(STOP)
self.destroy()
def test_stop(self):
if self.running or self.finished:
self.dialog_que.put(HIDE)
self.stop_btn.config(state=tk.DISABLED)
self.start_btn.config(state=tk.NORMAL)
def test_start(self):
while not self.app_que.empty():
self.app_que.get()
thread = Thread(target=self.worker, daemon=True)
thread.start()
self.stop_btn.config(state=tk.NORMAL)
self.start_btn.config(state=tk.DISABLED)
self.dlg.deiconify()
class ProgressDialog(tk.Toplevel):
def __init__(self, parent, *args, **kwargs):
title = kwargs.pop('title', '')
process = kwargs.pop('process', 0)
geometry = kwargs.pop('geometry', None)
super().__init__(parent, *args, **kwargs)
self.withdraw()
self.app_que = None
self.dialog_que = None
self.rowconfigure(0, weight=1)
self.rowconfigure(1, weight=1)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=1)
self.title(title)
if geometry:
self.geometry(geometry)
wdg = self.progress_bar = ttk.Progressbar(self, orient=tk.HORIZONTAL, mode='determinate')
wdg["value"] = 0
wdg["maximum"] = process
wdg.grid(padx=10, sticky=tk.EW, columnspan=1000)
wdg = self.pause_btn = ttk.Button(self, text='Pause', command=self.pause)
wdg.grid()
wdg = self.cancel_btn = ttk.Button(self, text='Cancel', command=self.hide)
wdg.grid(row=1, column=1)
self.protocol('WM_DELETE_WINDOW', self.hide)
def worker(self):
while True:
message = self.dialog_que.get()
print(message)
if message == HIDE:
self.hide()
elif message == STOP:
self.app_que.put(DONE)
break
elif message == DONE:
self.pause_btn.config(state=tk.DISABLED)
else:
self.progress_bar["value"] = message
def hide(self):
self.app_que.put(BREAK)
self.pause_btn.config(text='Pause')
self.withdraw()
def pause(self):
if self.progress_bar['value'] < self.progress_bar['maximum']:
text = self.pause_btn.cget('text')
text = 'Resume' if text == 'Pause' else 'Pause'
self.pause_btn.config(text=text)
self.app_que.put(PAUSE)
else:
self.pause_btn.config(text='Pause')
if __name__ == '__main__':
app = App()
app.mainloop()
最佳答案
如果您不想使用 thread
,也许你可以试试 asyncio
.我不知道我的代码是否正确,但它在我的 PC 上运行良好。
欢迎指出我代码中的错误,我真的不知道这是否是一个好的做法。
import tkinter as tk
from tkinter import ttk
import asyncio, time
import warnings
class App(tk.Tk):
def __init__(self):
super(App, self).__init__()
self.start_btn = ttk.Button(self, text="Start Test", command=self.test_start)
self.start_btn.pack(padx=10, pady=5, fill="both", expand=True)
self.stop_btn = ttk.Button(self, text="Stop Test", command=self.test_stop, state=tk.DISABLED)
self.stop_btn.pack(padx=10, pady=5, fill="both", expand=True)
self.test_window = tk.Toplevel()
self.test_window.progressbar = ttk.Progressbar(self.test_window, orient=tk.HORIZONTAL)
self.test_window.progressbar.grid(padx=10, pady=5, sticky=tk.NSEW, columnspan=2, column=0, row=0)
self.test_window.switch_btn = ttk.Button(self.test_window, text="Pause", command=self.switch)
self.test_window.switch_btn.grid(padx=10, pady=5, sticky=tk.NSEW, column=0, row=1)
self.test_window.cancel_btn = ttk.Button(self.test_window, text="Cancel", command=self.test_cancel)
self.test_window.cancel_btn.grid(padx=10, pady=5, sticky=tk.NSEW, column=1, row=1)
self.test_window.withdraw()
def test_start(self):
self.stop_btn['state'] = tk.NORMAL
self.test_window.deiconify()
self.test_window.after(0, self.work)
def work(self):
async def async_work(): # define a async task
try:
await asyncio.sleep(3) # could be another async work.
except asyncio.CancelledError:
print("cancel or stop")
raise # if don't raise the error ,it won't cancel
async def progressbar_add():
self.task = asyncio.create_task(async_work())
timeout = 0
while True: # wait the async task finish
done, pending = await asyncio.wait({self.task}, timeout=timeout)
self.test_window.update()
if self.task in done:
self.test_window.progressbar['value'] += 10 # if finished, value += 10
print(self.test_window.progressbar['value'])
await self.task
break
if self.test_window.progressbar['value'] >= 100:
return
asyncio.run(progressbar_add())
self.test_window.after(0, self.work)
def test_stop(self):
self.test_window.progressbar['value'] = 0
self.stop_btn['state'] = tk.DISABLED
try:
all_tasks = asyncio.Task.all_tasks()
for task in all_tasks:
task.cancel()
except RuntimeError: # if you have cancel the task it will raise RuntimeError
pass
def switch(self):
if self.test_window.switch_btn['text'] == 'Pause':
self.test_window.switch_btn['text'] = 'Resume'
try:
all_tasks = asyncio.Task.all_tasks()
for task in all_tasks:
task.cancel()
except RuntimeError: # if you have cancel the task it will raise RuntimeError
pass
else:
self.test_window.switch_btn['text'] = 'Pause'
return self.work()
def test_cancel(self):
# self.test_window.progressbar['value'] = 0
print(self.test_window.progressbar['value'])
self.test_window.withdraw()
self.task.cancel()
app = App()
app.mainloop()
asyncio.run(async)
.它是在Python 3.7中添加的。需要使用
get_event_loop()
和
run_until_complete()
.(@Saad指出)
关于python - Tkinter 进度条如何在模型对话框中正确实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61897484/
可不可以命名为MVVM模型?因为View通过查看模型数据。 View 是否应该只与 ViewModelData 交互?我确实在某处读到正确的 MVVM 模型应该在 ViewModel 而不是 Mode
我正在阅读有关设计模式的文章,虽然作者们都认为观察者模式很酷,但在设计方面,每个人都在谈论 MVC。 我有点困惑,MVC 图不是循环的,代码流具有闭合拓扑不是很自然吗?为什么没有人谈论这种模式: mo
我正在开发一个 Sticky Notes 项目并在 WPF 中做 UI,显然将 MVVM 作为我的架构设计选择。我正在重新考虑我的模型、 View 和 View 模型应该是什么。 我有一个名为 Not
不要混淆:How can I convert List to Hashtable in C#? 我有一个模型列表,我想将它们组织成一个哈希表,以枚举作为键,模型列表(具有枚举的值)作为值。 publi
我只是花了一些时间阅读这些术语(我不经常使用它们,因为我们没有任何 MVC 应用程序,我通常只说“模型”),但我觉得根据上下文,这些意味着不同的东西: 实体 这很简单,它是数据库中的一行: 2) In
我想知道你们中是否有人知道一些很好的教程来解释大型应用程序的 MVVM。我发现关于 MVVM 的每个教程都只是基础知识解释(如何实现模型、 View 模型和 View ),但我对在应用程序页面之间传递
我想realm.delete() 我的 Realm 中除了一个模型之外的所有模型。有什么办法可以不列出所有这些吗? 也许是一种遍历 Realm 中当前存在的所有类型的方法? 最佳答案 您可以从您的 R
我正在尝试使用 alias 指令模拟一个 Eloquent 模型,如下所示: $transporter = \Mockery::mock('alias:' . Transporter::class)
我正在使用 stargazer 创建我的 plm 汇总表。 library(plm) library(pglm) data("Unions", package = "pglm") anb1 <- pl
我读了几篇与 ASP.NET 分层架构相关的文章和问题,但是读得太多后我有点困惑。 UI 层是在 ASP.NET MVC 中开发的,对于数据访问,我在项目中使用 EF。 我想通过一个例子来描述我的问题
我收到此消息错误: Inceptionv3.mlmodel: unable to read document 我下载了最新版本的 xcode。 9.4 版测试版 (9Q1004a) 最佳答案 您没有
(同样,一个 MVC 验证问题。我知道,我知道......) 我想使用 AutoMapper ( http://automapper.codeplex.com/ ) 来验证我的创建 View 中不在我
需要澄清一件事,现在我正在处理一个流程,其中我有两个 View 模型,一个依赖于另一个 View 模型,为了处理这件事,我尝试在我的基本 Activity 中注入(inject)两个 View 模型,
如果 WPF MVVM 应该没有代码,为什么在使用 ICommand 时,是否需要在 Window.xaml.cs 代码中实例化 DataContext 属性?我已经并排观看并关注了 YouTube
当我第一次听说 ASP.NET MVC 时,我认为这意味着应用程序由三个部分组成:模型、 View 和 Controller 。 然后我读到 NerdDinner并学习了存储库和 View 模型的方法
Platform : ubuntu 16.04 Python version: 3.5.2 mmdnn version : 0.2.5 Source framework with version :
我正在学习本教程:https://www.raywenderlich.com/160728/object-oriented-programming-swift ...并尝试对代码进行一些个人调整,看看
我正试图围绕 AngularJS。我很喜欢它,但一个核心概念似乎在逃避我——模型在哪里? 例如,如果我有一个显示多个交易列表的应用程序。一个列表向服务器查询匹配某些条件的分页事务集,另一个列表使用不同
我在为某个应用程序找出最佳方法时遇到了麻烦。我不太习惯取代旧 TLA(三层架构)的新架构,所以这就是我的来源。 在为我的应用程序(POCO 类,对吧??)设计模型和 DAL 时,我有以下疑问: 我的模
我有两个模型:Person 和 Department。每个人可以在一个部门工作。部门可以由多人管理。我不确定如何在 Django 模型中构建这种关系。 这是我不成功的尝试之一 [models.py]:
我是一名优秀的程序员,十分优秀!