Как Вы выполняете свой собственный код вместе с циклом событий Tkinter?

110
задан Bill the Lizard 16 September 2012 в 15:55
поделиться

3 ответа

Используйте after метод на эти Tk объект:

from tkinter import *

root = Tk()

def task():
    print("hello")
    root.after(2000, task)  # reschedule event in 2 seconds

root.after(2000, task)
root.mainloop()

Вот объявление и документация для after метод:

def after(self, ms, func=None, *args):
    """Call function once after given time.

    MS specifies the time in milliseconds. FUNC gives the
    function which shall be called. Additional parameters
    are given as parameters to the function call.  Return
    identifier to cancel scheduling with after_cancel."""
131
ответ дан nbro 24 November 2019 в 03:14
поделиться

Другая опция состоит в том, чтобы позволить tkinter выполниться на отдельном потоке. Один способ сделать его похож на это:

import Tkinter
import threading

class MyTkApp(threading.Thread):
    def __init__(self):
        self.root=Tkinter.Tk()
        self.s = Tkinter.StringVar()
        self.s.set('Foo')
        l = Tkinter.Label(self.root,textvariable=self.s)
        l.pack()
        threading.Thread.__init__(self)

    def run(self):
        self.root.mainloop()


app = MyTkApp()
app.start()

# Now the app should be running and the value shown on the label
# can be changed by changing the member variable s.
# Like this:
# app.s.set('Bar')

Быть осторожным, хотя, многопоточное программирование трудно и действительно легко выстрелить Вашему сам в ногу. Например, необходимо быть осторожными при замене членских переменных демонстрационного класса выше, таким образом, Вы не прерываете циклом событий Tkinter.

5
ответ дан 24 November 2019 в 03:14
поделиться

Решение , опубликованное Бьорном , приводит к появлению сообщения «RuntimeError: Calling Tcl from different appartment» на моем компьютере (RedHat Enterprise 5, python 2.6.1). Бьорн мог не получить это сообщение, поскольку, согласно в одном месте, которое я проверил , неправильная обработка потоков с помощью Tkinter непредсказуема и зависит от платформы.

Проблема заключается в том, что app.start ( ) считается ссылкой на Tk, поскольку приложение содержит элементы Tk. Я исправил это, заменив app.start () на self.start () внутри __ init __ . Я также сделал так, что все ссылки Tk находятся либо внутри функции , которая вызывает mainloop () , либо внутри функций , которые вызываются функцией, вызывающей mainloop () (очевидно, это критично, чтобы избежать ошибки "разные апартаменты").

Наконец, я добавил обработчик протокола с обратным вызовом, так как без этого программа завершается с ошибкой, когда окно Tk закрывается с помощью пользователь.

Пересмотренный код выглядит следующим образом:

# Run tkinter code in another thread

import tkinter as tk
import threading

class App(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.start()

    def callback(self):
        self.root.quit()

    def run(self):
        self.root = tk.Tk()
        self.root.protocol("WM_DELETE_WINDOW", self.callback)

        label = tk.Label(self.root, text="Hello World")
        label.pack()

        self.root.mainloop()


app = App()
print('Now we can continue running code while mainloop runs!')

for i in range(100000):
    print(i)
51
ответ дан 24 November 2019 в 03:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: