2009-07-08 19 views
10

मेरे पास तारों की एक सूची है और उन प्रत्येक स्ट्रिंग के लिए मेनू प्रविष्टि बनाना चाहते हैं। जब उपयोगकर्ता किसी एक प्रविष्टि पर क्लिक करता है, तो हमेशा एक ही फ़ंक्शन को स्ट्रिंग के साथ तर्क के रूप में बुलाया जाएगा। कुछ की कोशिश कर रहा है और अनुसंधान के बाद मैं कुछ इस तरह के साथ आया था: "आइटम 3" के बजाय इसी एक:तारों की सूची से पीईक्यूटी मेनू बनाएं

import sys 
from PyQt4 import QtGui, QtCore 

class MainWindow(QtGui.QMainWindow): 
    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 
     self.menubar = self.menuBar() 
     menuitems = ["Item 1","Item 2","Item 3"] 
     menu = self.menubar.addMenu('&Stuff') 
     for item in menuitems: 
      entry = menu.addAction(item) 
      self.connect(entry,QtCore.SIGNAL('triggered()'), lambda: self.doStuff(item)) 
      menu.addAction(entry) 
     print "init done" 

    def doStuff(self, item): 
     print item 

app = QtGui.QApplication(sys.argv) 
main = MainWindow() 
main.show() 
sys.exit(app.exec_()) 

अब समस्या यह है कि मेनू आइटम में से प्रत्येक के एक ही आउटपुट प्रिंट होगा है। मैं इस बारे में किसी भी विचार के लिए आभारी हूं कि मैं यह अधिकार कैसे प्राप्त कर सकता हूं। धन्यवाद।

उत्तर

23

आप पूरे हो रहे हैं जो अक्सर अजगर में शायद नहीं पूरी तरह pedantically-सही ढंग से करने के लिए (के लिए भेजा गया है ;-) "scoping समस्या" के रूप में - बाध्यकारी कॉल-समय में देर से (शाब्दिक देखने है) जबकि आप इसे जल्दी (डीफ-टाइम पर) पसंद करेंगे। तो अब है जहां:

for item in menuitems: 
     entry = menu.addAction(item) 
     self.connect(entry,QtCore.SIGNAL('triggered()'), lambda: self.doStuff(item)) 

ऐसा करें:

for item in menuitems: 
     entry = menu.addAction(item) 
     self.connect(entry,QtCore.SIGNAL('triggered()'), lambda item=item: self.doStuff(item)) 

इस "अनुमान" बंधन, मूलभूत मूल्यों के बाद से (item यहाँ के रूप में) डीईएफ़ समय एक ही बार में एक सब के लिए गणना की हो । (उदाहरण के लिए एक डबल लैम्ब्डा) नेस्टिंग समारोह में से एक स्तर को जोड़ने से भी काम करता है, लेकिन यह यहाँ एक overkill का एक सा -!)

आप वैकल्पिक रूप से functools.partial(self.doStuff, item) इस्तेमाल कर सकते हैं (बेशक के शीर्ष पर एक import functools के साथ) जो एक और ठीक समाधान है , लेकिन मुझे लगता है कि मैं सबसे सरल (और सबसे आम) "तर्क के लिए नकली डिफ़ॉल्ट-मूल्य" idiom के लिए जाना होगा।

+1

@Alex: +1 !!! यह सब सुबह मुझे परेशान कर रहा है! लैम्ब्डा एक्स = एक्स: func (x) एफटीडब्ल्यू :) –

+0

उत्कृष्ट जवाब! यह नए कनेक्शन सिंटैक्स के साथ भी काम करता है: 'entry.triggered.connect (lambda item = item: self.doStuff (item))' – Leistungsabfall

2

यह काम करना चाहिए, लेकिन मुझे पूरा यकीन है कि एक बेहतर तरीका था जिसे मैं अभी याद नहीं कर सकता।

def do_stuff_caller(self, item): 
    return lambda: self.doStuff(item) 

... 
self.connect(entry, QtCore.SIGNAL('triggered()'), self.do_stuff_caller(item)) 

संपादित: छोटा संस्करण, कि अभी भी मैं क्या सोच रहा हूँ ... या हो सकता है यह किसी अन्य भाषा में था नहीं है? :)

(lambda x: lambda self.do_stuff(x))(item)
संबंधित मुद्दे