سؤال

لدي قائمة بالسلاسل وأريد إنشاء إدخال قائمة لكل من هذه السلاسل. عندما ينقر المستخدم على أحد الإدخالات، يجب استدعاء نفس الوظيفة دائما بالسلسلة كوسيطة. بعد بعض المحاولة والبحث الذي توصلت إليه بشيء مثل هذا:

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

الآن المشكلة هي أن كل عنصر من عناصر القائمة ستطبع نفس الإخراج: "العنصر 3" بدلا من المقابلة. أنا ممتن لأي أفكار حول كيف يمكنني الحصول على هذا الحق. شكرا.

هل كانت مفيدة؟

المحلول

تلبيت ما تم إحالته في كثير من الأحيان إلى (ربما ليس بالكامل بشكل صحيح - بشكل صحيح ؛-) ك "مشكلة النحافة" في بيثون - التجليد متأخر (البحث المعجمي في وقت المكالمة) أثناء وجودك مبكرا (في Def-Time). فأين لديك الآن:

    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 واحد هنا) الحصول على حساب مرة واحدة للجميع في وقت def الزملاء. إن إضافة مستوى واحد من التعشيش الوظيفة (مثل Lambda مزدوج) يعمل أيضا، لكنه قليل من المبالغة هنا! -)

هل يمكن استخدامها بدلا من ذلك functools.partial(self.doStuff, item) (مع ال import functools في الجزء العلوي من الدورة) وهو حل جيد آخر، لكنني أعتقد أنني سأذهب لأبسط (والأكثر شيوعا) "القيمة الافتراضية المزيفة للحجة".

نصائح أخرى

هذا يجب أن يعمل، لكنني متأكد من أن هناك طريقة أفضل لا أستطيع أن أذكر الآن.

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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top