2009-07-08 8 views
10

Dizelerim var ve bu dizelerin her biri için bir menü girişi oluşturmak istiyorum. Kullanıcı girişlerden birini tıkladığında, her zaman aynı işlev argüman olarak dizeyle çağrılmalıdır. Bazı çalışıyor ve araştırmadan sonra böyle bir şey ile geldi: "Öğe 3" yerine tekabül birini:Dizeler listesinden PyQt menüsü oluştur

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_()) 

Şimdi problem menü öğelerinin her biri aynı çıktıyı yazdırır olmasıdır. Bu hakkın nasıl elde edilebileceğine dair fikirlere minnettarım. Teşekkürler.

cevap

23

- bağlama geç (anlamsal arama) çağrı zamanda erken isterseniz (def-time). Yani şimdi var burada:

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

yerine deneyin:

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

Bu (burada item biri gibi) varsayılan değerler beri bağlama "beklediğini" def-time bir kerede herkes için hesaplanan olsun . iç içe işlevinin bir seviye ekleme (örneğin çift lambda) de çalışır, ancak burada bir overkill biraz! -)

Sen alternatif olarak elbette üst kısmında bir import functools ile (functools.partial(self.doStuff, item) kullanabilirsiniz) başka güzel çözümdür ama sanırım en basit (ve en yaygın) "argüman için sahte varsayılan değer" deyimine gidecektim.

+1

@Alex: +1 !!! Bütün sabah beni rahatsız ediyor! lambda x = x: func (x) FTW :) –

+0

Mükemmel cevap! Ayrıca yeni bağlantı sözdizimi ile çalışır: "entry.triggered.connect (lambda item = item: self.doStuff (item)) – Leistungsabfall

2

Bu işe yarayacak, ancak şu anda hatırlayamadığım daha iyi bir yol olduğundan eminim.

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

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

Düzenleme: Daha kısa versiyonu hala o ben düşünüyorum ... ya da belki başka bir dilde ne değildir? :) Sık sık belki değil tamamen ukalalıkla-doğru (yönlendirilen ne ;-) "kapsam sorununun" Python buluşacağız

(lambda x: lambda self.do_stuff(x))(item)