2009-07-29 12 views
5

यहाँ परीक्षण का मामला है में है ...Tkinter ताले अजगर जब एक आइकन लोड होने और tk.mainloop एक धागा

import Tkinter as tk 
import thread 
from time import sleep 

if __name__ == '__main__': 
    t = tk.Tk() 
    thread.start_new_thread(t.mainloop,()) 
    # t.iconbitmap('icon.ico') 

    b = tk.Button(text='test', command=exit) 
    b.grid(row=0) 

    while 1: 
     sleep(1) 

इस कोड काम करता है। टी .iconbitmap लाइन और यह ताले uncomment। इसे किसी भी तरह से व्यवस्थित करें; यह बंद हो जाएगा।

जब कोई आइकन मौजूद होता है तो GIL लॉकिंग tk.mainloop को कैसे रोकूं?

लक्ष्य win32 और पायथन 2.6.2 है।

उत्तर

16

मेरा मानना ​​है कि आपको एक अलग थ्रेड पर मुख्य पाश निष्पादित नहीं करना चाहिए। AFAIK, मुख्य लूप को उसी थ्रेड पर निष्पादित किया जाना चाहिए जिसने विजेट बनाया है।

जीयूआई टूलकिट जो मैं परिचित हूं (टिंकर, .NET विंडोज फॉर्म) इस तरह से हैं: आप केवल एक धागे से जीयूआई में हेरफेर कर सकते हैं।

 
self.tk.mainloop(n) 
RuntimeError: Calling Tcl from different appartment 

निम्नलिखित में कोई एक काम करेंगे (बिना किसी अतिरिक्त सूत्र):

if __name__ == '__main__': 
    t = tk.Tk() 
    t.iconbitmap('icon.ico') 

    b = tk.Button(text='test', command=exit) 
    b.grid(row=0) 

    t.mainloop() 

अतिरिक्त धागा के साथ:

def threadmain(): 
    t = tk.Tk() 
    t.iconbitmap('icon.ico') 
    b = tk.Button(text='test', command=exit) 
    b.grid(row=0) 
    t.mainloop() 


if __name__ == '__main__': 
    thread.start_new_thread(threadmain,()) 

    while 1: 
     sleep(1) 

लिनक्स पर, अपना कोड एक अपवाद को जन्म देती है

यदि आपको संवाद करने की आवश्यकता है टिंकर थ्रेड के बाहर से टिंकर के साथ, मेरा सुझाव है कि आप एक टाइमर सेट करें जो काम के लिए कतार की जांच करता है।

यहाँ एक उदाहरण है:

import Tkinter as tk 
import thread 
from time import sleep 
import Queue 

request_queue = Queue.Queue() 
result_queue = Queue.Queue() 

def submit_to_tkinter(callable, *args, **kwargs): 
    request_queue.put((callable, args, kwargs)) 
    return result_queue.get() 

t = None 
def threadmain(): 
    global t 

    def timertick(): 
     try: 
      callable, args, kwargs = request_queue.get_nowait() 
     except Queue.Empty: 
      pass 
     else: 
      print "something in queue" 
      retval = callable(*args, **kwargs) 
      result_queue.put(retval) 

     t.after(500, timertick) 

    t = tk.Tk() 
    t.configure(width=640, height=480) 
    b = tk.Button(text='test', name='button', command=exit) 
    b.place(x=0, y=0) 
    timertick() 
    t.mainloop() 

def foo(): 
    t.title("Hello world") 

def bar(button_text): 
    t.children["button"].configure(text=button_text) 

def get_button_text(): 
    return t.children["button"]["text"] 

if __name__ == '__main__': 
    thread.start_new_thread(threadmain,()) 

    trigger = 0 
    while 1: 
     trigger += 1 

     if trigger == 3: 
      submit_to_tkinter(foo) 

     if trigger == 5: 
      submit_to_tkinter(bar, "changed") 

     if trigger == 7: 
      print submit_to_tkinter(get_button_text) 

     sleep(1) 
+2

वैसे आप सिर, यह काम करता है पर कील मारा गया है ... लेकिन मैं पर्याप्त जानकारी प्रदान नहीं का सामना करना पड़ा है। मेरा तर्क यह है कि मैं चीजों को टिंकर करने में सक्षम होना चाहता हूं जहां लूपर है ... एसओ के लिए थोड़ा नया होने के नाते, क्या मुझे आपका जवाब स्वीकार करना चाहिए और एक और अधिक verbose सवाल पूछना चाहिए? – burito

+2

हाय, मैंने अपना उत्तर एक सुझाव और कोड उदाहरण के साथ अपडेट किया है जो इसे पूरा करता है। जबकि लूप अब अनुरोध/प्रतिक्रिया कतारों का उपयोग करते हुए टिंकर थ्रेड पर कुछ विधि कॉल करता है। उत्पादन कोड के लिए – codeape

+2

बीटीडब्ल्यू, मैं सुझाव देता हूं कि आप कक्षा में टिंकर खिड़की, धागे और कतारों को समाहित करें। यह अब हमारे पास ग्लोबल्स से बचने के लिए है: request_queue, response_queue और t। आपको कॉल करने योग्य (* args, ** kwargs) के आस-पास कुछ त्रुटि प्रबंधन की भी आवश्यकता है। – codeape

संबंधित मुद्दे