0

필자가 작성한 프로그램에서 저의 일부 정보를 기반으로 공유 드라이브에 대한 특정 보고서를 찾기 위해 도우미 기능으로 시작했습니다. 나는 다른 직원에게 배포 할 수 있도록 GUI를 제공하기로 결정했으며, tkinterthreading을 구현하려는 첫 번째 시도에서 몇 가지 오류가 발생했습니다.스레드의 최고 수준을 삭제하면 루트가 잠 깁니다.

나는 오래된 단서에 대해 알고 있습니다. "한가지 문제가 있었는데 스레드를 사용했는데 이제는 두 가지 문제가 있습니다." 스레드는, 적어도, 첫 번째 문제를 해결 않았다 - 이제 두 번째 ....

내 약화 코드 것은 : root 열고 채울 수

class GetReport(threading.Thread): 
    def __init__(self,root): 
     threading.Thread.__init__(self) 

     # this is just a hack to get the StringVar in the new thread, HELP! 
     self.date = root.getvar('date') 
     self.store = root.getvar('store') 
     self.report = root.getvar('report') 
     # this is just a hack to get the StringVar in the new thread, HELP! 

     self.top = Toplevel(root) 
     ttk.Label(self.top,text="Fooing the Bars into Bazes").pack() 
     self.top.withdraw() 
    def run(self): 
     self.top.deiconify() 
     # a function call that takes a long time 
     self.top.destroy() #this crashes the program 

def main(): 
    root = Tk() 
    date,store,report = StringVar(),StringVar(),StringVar() 

    ##### 
    ## labels and Entries go here that define and modify those StringVar 
    ##### 

    def launchThread(rpt): 
     report.set(rpt) 

     # this is just a hack to get the StringVar in the new thread, HELP! 
     root.setvar('date',date.get()) 
     root.setvar('store',store.get()) 
     root.setvar('report',report.get()) 
     # this is just a hack to get the StringVar in the new thread, HELP! 

     reportgetter = GetReport(root) 
     reportgetter.start() 

    ttk.Button(root,text="Lottery Summary", 
       command=lambda: launchThread('L')).grid(row=1,column=3) 

    root.mainloop() 

내 예상 출력은 레이블, 항목 및 버튼 (이 중 일부는이 예제에서 숨겨 짐)이 있습니다. 각 버튼은 항목에서 데이터를 가져 와서 launchThread 기능으로 보내면 필요한 서류를 작성하는 데 필요한 정보와 막대를 수행하는 새로운 스레드가 만들어집니다.

그 스레드는 기본적으로 사용자에게 작동 중임을 알리는 Toplevel을 시작합니다. 당신이 일을 끝낼 때, (그것의 run 기능을 종료 이후) 스레드가 종료

무엇에 실제로 일어나고있는 것은 실 것입니다 동안 (내가 .PDF를 엽니 다 ShellExecute을 사용하고 있습니다) 최상위 레벨이 닫히고 내가 요청한 서류가 열립니다 서류가 열리면 파이썬이 응답하지 않아 "처리가 끝나야"합니다.

답변

-1

Tkinter는 주 스레드가 아닌 다른 스레드의 명령을 받아 들일 수 없기 때문에 다른 스레드의 Tk에 액세스 할 수 없으므로 스레드에서 TopLevel을 시작하는 것이 설계 상 실패하게됩니다. 이 문제를 해결하려면 .is_alive 스레드 방법을 사용하십시오.

+0

이것은 좋은 해결책이 아닙니다. 이벤트 루프 내부에 무한 루프를 추가하는 것이므로 거의 항상 피해야합니다. 대신 매초마다 실행되도록 애니메이션 루프를 설정하여 스레드가 활성 상태인지 확인합니다. –

+0

@BryanOakley 수락 할 수 있음을 입증하는 답변을 추가 할 수 있습니까? 이것은 소량의 연구와 시행 착오 끝에 나온 해결책이었습니다. –

0

내가 아는 한 모든 GUI 요소를 변경하기 위해 스레딩을 사용할 수 없습니다. Toplevel 창을 파괴하는 것.

모든 Tkinter 코드는 프로그램의 메인 루프에서 수행해야합니다.

+0

안녕하세요 James. 이것은 1 개월 전에 제가 제기 한 질문이었습니다. 그 이후로 해결했지만 분명히 답변을 게시하지 않았습니다. 제가 제 코드를 참고하고 제가 정확히 무엇을했는지 기억하게하십시오. –

+0

비슷한 문제가 생겨서 방금 정렬되었습니다. 그것은 당신을 도울지도 모릅니다. 그러나 여기 있습니다. http://stackoverflow.com/questions/21668538/closing-a-topvel-window-from-a-seperate-thread-using-threading –

+0

도움을 주셔서 감사합니다. 내 문제는 아래에있는 코드로 해결되었으며, 'after'는 내 코드가 완료되기까지 다양한 시간이 걸리기 때문에 잘 작동하지 않습니다. 생각에 감사드립니다! –

관련 문제