Запуск формы Tkinter в отдельном потоке
Я написал короткий модуль, которому можно передать изображение, и просто создает окно Tkinter и отображает его. Проблема, с которой я сталкиваюсь, заключается в том, что даже когда я создаю экземпляр и вызываю метод, который отображает изображение в отдельном потоке, основная программа не продолжит работу, пока окно Tkinter не будет закрыто.
Вот мой модуль:
import Image, ImageTk
import Tkinter
class Viewer(Tkinter.Tk):
def __init__(self,parent):
Tkinter.Tk.__init__(self,parent)
self.parent = parent
self.initialize()
def initialize(self):
self.grid()
def show(self,img):
self.to_display = ImageTk.PhotoImage(img)
self.label_image = Tkinter.Label(self,image=self.to_display)
self.label_image.grid(column = 0, row = 0, sticky = "NSEW")
self.mainloop()
Кажется, что он работает нормально, за исключением того, что когда я вызываю его из моей тестовой программы, подобной той, что приведена ниже, она, похоже, не позволяет продолжить выполнение моей тестовой программы, даже если она запущена в другом потоке.
import Image
from viewer import Viewer
import threading
def showimage(im):
view = Viewer(None)
view.show(im)
if __name__ == "__main__":
im = Image.open("gaben.jpg")
t = threading.Thread(showimage(im))
t.start()
print "Program keeps going..."
Я думаю, что, возможно, моя проблема в том, что я должен создать новый поток внутри самого модуля, но я хотел просто попытаться сделать его простым, так как я новичок в Python.
В любом случае, заранее спасибо за любую помощь.
редактировать: для ясности, я просто пытаюсь создать модуль, который будет отображать изображение в окне Tkinter, чтобы я мог использовать этот модуль в любое время, когда я хочу отобразить изображение. Проблема, с которой я сталкиваюсь, заключается в том, что когда программа использует этот модуль, она не может возобновить работу, пока окно Tkinter не будет закрыто.
4 ответа
Судя по вашим комментариям, вам вообще не нужен графический интерфейс. Просто запишите изображение на диск и вызовите внешнего зрителя.
На большинстве систем должна быть возможность запустить средство просмотра по умолчанию, используя что-то вроде этого:
import subprocess
subprocess.Popen("yourimage.png")
Tkinter не является поточно-ориентированным, и общее мнение состоит в том, что Tkinter не работает в неосновном потоке. Если вы переписываете свой код так, что Tkinter запускается в основном потоке, вы можете заставить своих работников работать в других потоках.
Основное предостережение заключается в том, что рабочие не могут взаимодействовать с виджетами Tkinter. Они должны будут записывать данные в очередь, и ваш основной поток графического интерфейса должен будет опросить эту очередь.
Если все, что вы делаете, это показывает изображения, вам, вероятно, вообще не нужна многопоточность. Потоки полезны только тогда, когда у вас есть длительный процесс, который в противном случае заблокировал бы графический интерфейс. Tkinter может легко обрабатывать сотни изображений и окон без единого пота.
Я попытался запустить tkinter из отдельного потока, не очень хорошая идея, он зависает. Есть одно решение, которое сработало. Запустите графический интерфейс в главном потоке и отправьте события в основной интерфейс. Это похожий пример, он просто показывает метку.
import Tkinter as t
global root;
root = t.Tk()
root.title("Control center")
root.mainloop()
def new_window(*args):
global root
print "new window"
window = t.Toplevel(root)
label = t.Label(window, text="my new window")
label.pack(side="top", fill="both", padx=10, pady=10)
window.mainloop()
root.bind("<<newwin>>",new_window)
#this can be run in another thread
root.event_generate("<<newwin>>",when="tail")
Из того, что я могу сказать, Tkinter не любит играть в других темах. Смотрите этот пост... Мне нужна небольшая помощь с Python, Tkinter и Threading
Обходной путь - создать (возможно скрытый) верхний уровень в вашем основном потоке, создать отдельный поток для открытия изображений и т. Д. - и использовать общую очередь для отправки сообщений обратно в поток Tk.
Требуется ли использовать Tkinter для вашего проекта? Мне нравится Ткинтер. Это "быстро и грязно". - но есть (много) случаев, когда другие наборы GUI - путь.