问题描述
限时送ChatGPT账号..我有一个 GUI,它有两个按钮和一个堆叠在单列上的进度条.每个按钮调用一个不同的函数,这需要一些时间来执行.我希望进度条在有人单击两个按钮中的任何一个时移动并继续移动(不确定)直到功能完成然后停止.我知道我需要使用多线程,但我似乎无法正确编写代码!
I have a GUI which has two buttons and a progressbar stacked on a single column. Each button calls a different function which takes some time to execute. I want the progress bar to move when someone clicks any of the two buttons and keep moving (indeterminately) until the function finishes and then stop. I know I need to use multi-threading but I can't seem to get the code right!
代码
from tkinter import Tk
import time
from tkinter import *
from tkinter import Button
from tkinter import Frame
from tkinter import ttk
import threading
def sample_function():
time.sleep(2) # SAMPLE FUNCTION BEING CALLED
def prepare_clicked():
sample_function()
def social_clicked():
sample_function()
def anomaly_clicked():
sample_function()
window = Toplevel() # Tried using Tk but I am using image to design each buttons through the button config in my actual code and tk throws error
topFrame = Frame(window)
topFrame.pack()
prepare_btn = Button(topFrame, command=prepare_clicked,text='Button1')
anomaly_btn = Button(topFrame,command=anomaly_clicked,text='Button2')
social_btn = Button(topFrame, command=social_clicked,text='Button3')
processing_bar = ttk.Progressbar(topFrame, orient='horizontal', mode='indeterminate')
window.rowconfigure((0,1), weight=1) # make buttons stretch when
window.columnconfigure((0,3), weight=1) # when window is resized
prepare_btn.grid(row=0, column=1, columnspan=1, sticky='EWNS')
anomaly_btn.grid(row=1, column=1, columnspan=1, sticky='EWNS')
social_btn.grid(row=2, column=1, columnspan=1, sticky='EWNS')
processing_bar.grid(row=3, column=1, columnspan=1, sticky='EWNS')
window.mainloop()
推荐答案
我已将线程添加到您的代码中.我假设您不希望任何按钮在功能进行中时可按下.如果您不需要它,只需去掉 run_function
中改变 <code>btn['state'] 的 for
循环.我还修复了行 &列配置代码,以便小部件展开 &当用户调整窗口大小时收缩.我摆脱了邪恶的明星"导入.
I've added threading to your code. I assume you don't want any of the buttons to be pressable while a function is in progress. If you don't need that, just get rid of the for
loops in run_function
that change btn['state']
. I've also fixed the row & column configuration code so that the widgets expand & contract when the user resizes the window. And I got rid of the evil "star" import.
import tkinter as tk
from tkinter import ttk
import time
from threading import Thread
def sample_function():
time.sleep(2)
def run_function(name, func):
# Disable all buttons
for btn in buttons:
btn['state'] = 'disabled'
processing_bar.start(interval=10)
print(name, 'started')
func()
processing_bar.stop()
print(name, 'stopped')
# Enable all buttons
for btn in buttons:
btn['state'] = 'normal'
def run_thread(name, func):
Thread(target=run_function, args=(name, func)).start()
def prepare_clicked():
run_thread('prepare', sample_function)
def social_clicked():
run_thread('social', sample_function)
def anomaly_clicked():
run_thread('anomaly', sample_function)
window = tk.Tk()
#window = tk.Toplevel()
topFrame = tk.Frame(window)
# Tell the Frame to fill the whole window
topFrame.pack(fill=tk.BOTH, expand=1)
# Make the Frame grid contents expand & contract with the window
topFrame.columnconfigure(0, weight=1)
for i in range(4):
topFrame.rowconfigure(i, weight=1)
prepare_btn = tk.Button(topFrame, command=prepare_clicked, text='Button1')
anomaly_btn = tk.Button(topFrame,command=anomaly_clicked, text='Button2')
social_btn = tk.Button(topFrame, command=social_clicked, text='Button3')
buttons = [prepare_btn, anomaly_btn, social_btn]
processing_bar = ttk.Progressbar(topFrame, orient='horizontal', mode='indeterminate')
prepare_btn.grid(row=0, column=0, columnspan=1, sticky='EWNS')
anomaly_btn.grid(row=1, column=0, columnspan=1, sticky='EWNS')
social_btn.grid(row=2, column=0, columnspan=1, sticky='EWNS')
processing_bar.grid(row=3, column=0, columnspan=1, sticky='EWNS')
window.mainloop()
<小时>
更新
这是新的改进版本,带有一个按顺序运行所有功能的全部"按钮.享受!
Here's the new improved version, with an 'All' button that runs all the functions, in order. Enjoy!
import tkinter as tk
from tkinter import ttk
import time
from threading import Thread
def prepare_func():
print('prepare started')
time.sleep(2)
print('prepare stopped')
def anomaly_func():
print('anomaly started')
time.sleep(2)
print('anomaly stopped')
def social_func():
print('social started')
time.sleep(2)
print('social stopped')
def all_func():
print('all started')
show_and_run(prepare_func, buttons['Prepare'])
show_and_run(anomaly_func, buttons['Anomaly'])
show_and_run(social_func, buttons['Social'])
print('all stopped')
def show_and_run(func, btn):
# Save current button color and change it to green
oldcolor = btn['bg']
btn['bg'] = 'green'
# Call the function
func()
# Restore original button color
btn['bg'] = oldcolor
def run_function(func, btn):
# Disable all buttons
for b in buttons.values():
b['state'] = 'disabled'
processing_bar.start(interval=10)
show_and_run(func, btn)
processing_bar.stop()
# Enable all buttons
for b in buttons.values():
b['state'] = 'normal'
def clicked(func, btn):
Thread(target=run_function, args=(func, btn)).start()
window = tk.Tk()
#window = tk.Toplevel()
topFrame = tk.Frame(window)
# Tell the Frame to fill the whole window
topFrame.pack(fill=tk.BOTH, expand=1)
# Make the Frame grid contents expand & contract with the window
topFrame.columnconfigure(0, weight=1)
for i in range(4):
topFrame.rowconfigure(i, weight=1)
button_data = (
('Prepare', prepare_func),
('Anomaly', anomaly_func),
('Social', social_func),
('All', all_func),
)
# Make all the buttons and save them in a dict
buttons = {}
for row, (name, func) in enumerate(button_data):
btn = tk.Button(topFrame, text=name)
btn.config(command=lambda f=func, b=btn: clicked(f, b))
btn.grid(row=row, column=0, columnspan=1, sticky='EWNS')
buttons[name] = btn
row += 1
processing_bar = ttk.Progressbar(topFrame,
orient='horizontal', mode='indeterminate')
processing_bar.grid(row=row, column=0, columnspan=1, sticky='EWNS')
window.mainloop()
这篇关于功能运行时不确定进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论