как остановить окно tkinter, которое не взаимодействует во время выполнения функции "тяжелые вычисления" - PullRequest
0 голосов
/ 26 апреля 2019

У меня есть окно tkinter, в котором есть некоторые виджеты, с которыми пользователь может взаимодействовать, и когда невозможно взаимодействовать с функцией, которая занимает немного времени для запуска всего окна. И я хочу изменить это

Я слышал, что вы можете решить эту проблему, реализовав многопроцессорную обработку для функции, но я не совсем понимаю, как ее реализовать.

мой код выглядит примерно так:

import tkinter as tk
from tkinter import *


def functionthattakessometime():

    while True:
         print("haa")

root=tk.Tk()

b=Button(root,text="print haha",command=functionthattakessometime)

a=Button(root,text="do nothing")

b.pack()

root.mainloop()

Вы не можете нажать окно "ничего не делать" после того, как вы нажали кнопку "печать, ха-ха", и я хочу изменить это так что вы можете нажать кнопку «ничего не делать» даже после нажатия кнопки «печать ха-ха».

1 Ответ

3 голосов
/ 26 апреля 2019

Библиотека threading - это то, что вам нужно.

Вот простой пример того, как он будет работать с вашим кодом.

import tkinter as tk
import threading


root = tk.Tk()
allow_print = True


def function_that_takes_sometime():
    while allow_print:
        print("haha")


def start_thread():
    global allow_print
    allow_print = True
    thread = threading.Thread(target=function_that_takes_sometime)
    thread.start()


def stop_thread():
    global allow_print
    allow_print = False


tk.Button(root, text="print haha", command=start_thread).pack()
tk.Button(root, text="Stop print", command=stop_thread).pack()

root.mainloop()

Это сказало, что я изменил бы несколько вещей.

Сначала я удалил бы from tkinter import *, так как вы никогда не должны импортировать tkinter дважды, и лучше просто использовать import tkinter as tk, потому что это предотвращает перезапись любых методов в случае аварии.

Во-вторых, я бы построил это в классе, чтобы мы могли избежать глобальных переменных.

Вот версия ООП:

import tkinter as tk
import threading


class Main(tk.Tk):
    def __init__(self):
        super().__init__()
        self.allow_print = True
        tk.Button(self, text="print haha", command=self.start_thread).pack()
        tk.Button(self, text="Stop print", command=self.stop_thread).pack()

    def function_that_takes_sometime(self):
        while self.allow_print:
            print("haha")

    def start_thread(self):
        self.allow_print = True
        thread = threading.Thread(target=self.function_that_takes_sometime)
        thread.start()

    def stop_thread(self):
        self.allow_print = False


Main().mainloop()

И чтобы еще больше упростить это, потому что часто многопоточность излишня, мы можем использовать метод after(), чтобы управлять циклом и не влиять на основной цикл.

import tkinter as tk


class Main(tk.Tk):
    def __init__(self):
        super().__init__()
        self.allow_print = True
        tk.Button(self, text="print haha", command=self.function_that_takes_sometime).pack()
        tk.Button(self, text="Stop print", command=self.stop_print).pack()

    def function_that_takes_sometime(self):
        if self.allow_print:
            print("haha")
            self.after(1000, self.function_that_takes_sometime)

    def stop_print(self):
        self.allow_print = False


Main().mainloop()
...