Я добавил потоки в ваш код.Я предполагаю, что вы не хотите, чтобы какая-либо из кнопок была нажимаемой во время выполнения функции.Если вам это не нужно, просто избавьтесь от петель for
в run_function
, которые меняют btn['state']
.Я также исправил код конфигурации строк и столбцов, чтобы виджеты расширялись и сжимались, когда пользователь изменял размеры окна.И я избавился от злого "звездного" импорта .
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()
Обновление
Вот новая улучшенная версия, скнопка «Все», которая запускает все функции по порядку.Наслаждайтесь!
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()