2012-05-11 2 views
5

이미지를 전달할 수있는 간단한 모듈을 작성하고 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..." 

나는 아마 내 문제는 내가 모듈 자체 내에서 새로운 쓰레드를 생성해야한다,하지만 난 파이썬에 새로운 오전 나는, 그냥 시도하고 간단하게하고 싶은 것을 생각합니다.

어쨌든 사전에 도움을 청하십시오.

편집 : 명확성을 위해, 나는 이미지를 표시하고 싶을 때마다이 모듈을 사용할 수 있도록 Tkinter 창에 이미지를 표시하는 모듈을 만들려고합니다. 내가 가지고있는 문제는 프로그램이이 모듈을 사용할 때마다 Tkinter 창이 닫힐 때까지 다시 시작할 수 없다는 것입니다.

답변

5

귀하의 의견은 마치 GUI가 필요없는 것처럼 들립니다. 이미지를 디스크에 쓰고 외부 뷰어를 호출하기 만하면됩니다.

대부분의 시스템은이 같은 것을 사용하여 기본 뷰어를 실행 할 수 있어야한다 : 나는 별도의 스레드에서 Tkinter를 실행하는 것을 시도했다

import subprocess 

subprocess.Popen("yourimage.png") 
2

Tkinter는 다른 스레드에서 재생하는 것을 좋아하지 않습니다. 이 게시물을 참조하십시오 ... I Need a little help with Python, Tkinter and threading

해결 방법은 주 스레드에서 최고 레벨 (가능하면 숨김)을 생성하고 이미지를 열려면 별도의 스레드를 생성 한 다음 공유 대기열을 사용하여 메시지를 다시 Tk로 보냅니다. 실.

프로젝트에 Tkinter를 사용해야합니까? 나는 Tkinter를 좋아한다. 그것은 "빠르고 더러운"것입니다. - 그러나 다른 GUI 키트가 갈 길은 (많은) 경우가 있습니다.

+1

답변의 첫 부분은 좋지만 다른 툴킷을 사용해 보려는 조언 때문에 upvote 할 수 없습니다. Tkinter는이 질문에 관한 유형에 완벽하게 적합합니다. –

10

Tkinter는 스레드로부터 안전하지 않으며, Tkinter가 비 메인 스레드에서 작동하지 않는다는 일반적인 합의가 있습니다. Tkinter가 주 스레드에서 실행되도록 코드를 다시 작성하면 작업자가 다른 스레드에서 실행하게 할 수 있습니다.

주요주의 사항은 작업자가 Tkinter 위젯과 상호 작용할 수 없다는 것입니다. 그들은 대기열에 데이터를 써야하며 기본 GUI 스레드는 해당 대기열을 폴링해야합니다.

이미지를 표시하고있는 중이라면 스레딩이 필요하지 않을 수도 있습니다. 스레딩은 GUI를 차단하는 장기 실행 프로세스가있는 경우에만 유용합니다. Tkinter는 땀을 흘리지 않고도 수백 개의 이미지와 창을 쉽게 처리 할 수 ​​있습니다.

+0

조언 해 주셔서 감사합니다. 위의 예와 같이 뷰어 모듈에서 self.mainloop()을 실행하면 윈도우가 닫힐 때까지 내 실제 프로그램이 계속 실행되지 않는다는 것을 알았다. 이 줄을 프로그램에두면 똑같은 일을합니다 (예 : view.mainloop()). 이 줄을 별도의 스레드에 배치하면 문제가 해결 될 수 있다고 생각했습니다. 당신은 스레딩없이이 작업을 수행 할 수 있어야한다고 말하고 있는데, mainloop()없이 윈도우를 표시하는 방법이 있다는 것을 의미합니까? – ballsatballsdotballs

+0

@ballsdotballs : 대화 형 GUI를 만들려면'mainloop'을 호출해야합니다. 매우 본질적으로 이벤트 루프를 실행하고 있기 때문에 스레드가 필요하지 않을 가능성이 높습니다. 'mainloop'을 호출 한 후에는 "당신의 실제 프로그램을 계속 사용하지 않을 것입니다."그러나 이것이 작동하도록 설계된 방법입니다. 루프를 설정하면 프로그램이 이벤트에 응답합니다. 'mainloop'은 거의 언제나 애플리케이션 시작 로직의 마지막 줄입니다. –

+0

문제는 단지 이미지를 표시하는 모듈을 작성하기 만하면되는 것이라고 생각합니다. 사용자가 이미지를 닫을 때까지 기다리지 않고이 모듈을 사용한 후 프로그램을 계속 실행하는 방법이 필요합니다. 이것을하기 위해 Tkinter를 사용할 방법이 없다는 것을 의미합니까? – ballsatballsdotballs

3

은, 좋은 생각, 그것은 정지. 한 가지 해결책이 있습니다. 메인 스레드에서 GUI를 실행하고 메인 GUI로 이벤트를 보냅니다. 이것은 비슷한 예이며, 레이블 만 보여줍니다.

관련 문제