2014-12-01 3 views
1

멀티 프로세싱을 사용하는 파이썬의 새로운 인스턴스에서 tkinter 폼을 시작하는 클래스를 생성하려고합니다.파이썬 2.7, 멀티 프로세싱 및 Tkinter

제 질문은 이것입니다 : Tkinter 클래스 객체를 다중 처리 함수로 전달하는 권장 방법은 무엇입니까? 일반적으로 다중 처리 풀에 객체를 전달할 때 객체를 문자열로 변환해야합니다. 이게 내가 그 반을 절어 야한다는 것을 의미합니까? 이 작업을 수행하는 더 좋은 방법이 있습니까?

나는 스레딩을 사용하지 않을 수 있습니다 내가 스레드 안전하지 않습니다 사용해야하는 파이썬 패키지의 일부 .. :(

샘플 코드로 인해 :

import Tkinter as Tk 

######################################################################## 
class TkinterApp(object): 
    """""" 

    #---------------------------------------------------------------------- 
    def __init__(self, parent): 
     """Constructor""" 

     self.root = parent 
     self.root.title("Main frame") 
     self.frame = Tk.Frame(parent) 
     self.frame.pack() 

     btn = Tk.Button(self.frame, text="Close Frame", command=self.hide) 
     btn.pack() 

    #---------------------------------------------------------------------- 
    def hide(self): 
     """""" 
     self.root.withdraw() 

시스템 사양 :

  • 윈도우 7
  • 파이썬 2.7.5 32 비트

모든 제안이나 피드백을 환영합니다!

+2

프로세스 경계에서 위젯을 전달할 수 없습니다. –

+0

그 냄새. 내 생각이 간다. –

답변

0

나뿐만 아니라 문제 풀의 외부 Tkinter의 인스턴스를 생성하고, 클래스 인스턴스가 발생하고 별도의 프로세스에서 함수를 호출하지 않은 감사드립니다. "간단한"예제는 다음과 같습니다.

from multiprocessing import Process 
import time 

try: 
    import Tkinter as tk ## Python 2.x 
except: 
    import tkinter as tk ## Python 3.x 

class ProgressBar(): 
    def __init__(self, root): 
     self.root=root 
     self.root.geometry("75x50+900+100") 
     self.ctr=25 

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

    def start_countdown(self): 
     """ a separate process in a separate GUI 
     """ 
     self.root.withdraw() 
     self.top_count=tk.Toplevel(self.root) 
     self.top_count.geometry("75x50+750+50") 
     self.label_ctr = tk.IntVar() 
     self.label_ctr.set(self.ctr) 
     label = tk.Label(self.top_count, textvariable=self.label_ctr) 
     label.pack() 
     if self.ctr > 0: 
      self.top_count.after(750, self.update) 

    def start_running(self): 
     """ create the progress bar widget 
     """ 
     self.top=tk.Toplevel(self.root, takefocus=True) 
     self.top.title("Progress Bar") 
     self.top.geometry("+700+200") 
     canvas = tk.Canvas(self.top, width=261, height=60, bg='lightgray') 
     canvas.pack() 

     rc2 = canvas.create_rectangle(15, 20, 243, 50, outline='blue', \ 
             fill='lightblue') 
     rc1 = canvas.create_rectangle(24, 20, 34, 50, outline='white', \ 
             fill='blue') 

     total=100 
     x = 5 
     while self.ctr:  ## move the small rectangle +5 or -5 units 
      total += x 
      if total > 311: 
       x = -5 
      elif total < 100: 
       x = 5 
      time.sleep(0.2) 
      canvas.move(rc1, x, 0) 
      canvas.update() 

    def update(self): 
     self.ctr -= 1 
     self.label_ctr.set(self.ctr) 

     if self.ctr > 0: 
      self.top_count.after(750, self.update) 
     else: 
      ## sleep to allow any remaining after() to execute 
      ## can also use self.root.after_cancel(id) 
      self.top_count.after(500, self.root.destroy) ## destroy root when zero is reached 

root = tk.Tk() 

PB=ProgressBar(root) 
pr1=Process(target=PB.start_countdown(), args=()) 
pr1.start() 

pr2=Process(target=PB.start_running(), args=()) 
pr2.start() 

## start mainloop in a separate process as a function of the class 
## don't know if this is really necessary or not 
## the theory is, it is detached from the other 2 processes and so 
## can react to both independently 
## also the mainloop() process can be killed=shut down properly 
pr3=Process(target=PB.mainloop(), args=()) 
pr3.start() 

## safety clean up 
pr1.terminate() 
pr2.terminate() 
pr3.terminate() 
+0

나는 그것을 줄 것이다, 고마워. 루트 객체 인 tk.Tk()는 새 프로세스에서 호출해야합니까 아니면 중요하지 않습니까? –

+0

이 경우에는 클래스 속성이고 두 함수가 모두 클래스의 멤버이므로 중요하지 않습니다. 나는 당신이 호출 된 함수에 전달할 수도 있지만 복잡한 프로그램에서는이를 테스트하지 않았다고 생각한다. 어쨌든 둘 이상의 Tk() 인스턴스는 필요 없지만 많은 Toplevel을 사용하여 함수에 전달할 수 있습니다. –

+0

'pr1 = Process (target = PB.start_countdown(), args =())')는 당신이 원하는 것을 수행하지 않는다 : PB.start_countdown()은'None'을 리턴한다. – Zelta

관련 문제