Неопределенный индикатор выполнения во время работы функции - PullRequest
0 голосов
/ 25 мая 2018

У меня есть графический интерфейс, который имеет две кнопки и индикатор выполнения, размещенный в одном столбце.Каждая кнопка вызывает свою функцию, выполнение которой занимает некоторое время.Я хочу, чтобы индикатор выполнения перемещался, когда кто-то нажимал на любую из двух кнопок, и продолжал двигаться (неопределенно), пока функция не завершится, а затем остановится.Я знаю, что мне нужно использовать многопоточность, но я не могу правильно понять код!

Код

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()

1 Ответ

0 голосов
/ 26 мая 2018

Я добавил потоки в ваш код.Я предполагаю, что вы не хотите, чтобы какая-либо из кнопок была нажимаемой во время выполнения функции.Если вам это не нужно, просто избавьтесь от петель 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...