2009-07-08 32 views
10

Tôi có danh sách các chuỗi và muốn tạo mục nhập trình đơn cho từng chuỗi đó. Khi người dùng nhấp vào một trong các mục, luôn luôn cùng một chức năng sẽ được gọi với chuỗi như một đối số. Sau khi một số cố gắng và nghiên cứu tôi đã đưa ra một cái gì đó như thế này:Tạo menu PyQt từ danh sách các chuỗi

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

Bây giờ vấn đề là mỗi người trong số các mục trình đơn sẽ in cùng đầu ra: "Khoản 3" thay vì tương ứng với một. Tôi biết ơn vì bất kỳ ý tưởng nào về cách tôi có thể có được quyền này. Cảm ơn.

Trả lời

23

Bạn sẽ gặp những gì đang được thường được gọi (có thể không hoàn toàn vẻ thông thái-đúng ;-) là "vấn đề Phạm vi" bằng Python - các ràng buộc là muộn (tra cứu từ vựng khi có yêu cầu thời gian thực) trong khi bạn muốn nó sớm (tại thời điểm def). Vì vậy, nơi bây giờ bạn có:

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

thử thay vì:

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

này "dự kiến" sự ràng buộc, vì giá trị mặc định (tùy theo từng item tại đây) được tính một lần một cho tất cả cùng def thời gian . Việc thêm một mức hàm làm tổ (ví dụ: một lambda đôi) cũng hoạt động quá, nhưng nó hơi quá mức ở đây! -)

Bạn cũng có thể sử dụng functools.partial(self.doStuff, item) (với số import functools ở đầu khóa học). , nhưng tôi nghĩ rằng tôi muốn đi cho thành ngữ đơn giản nhất (và phổ biến nhất) "giá trị mặc định cho đối số" thành ngữ.

+1

@Alex: +1 !!! Nó đã làm tôi thất vọng cả buổi sáng! lambda x = x: func (x) FTW :) –

+0

Câu trả lời hay! Nó cũng làm việc với cú pháp kết nối mới: 'entry.triggered.connect (lambda item = item: self.doStuff (item))' – Leistungsabfall

2

Điều này sẽ hiệu quả nhưng tôi chắc chắn có một cách tốt hơn mà tôi không thể nhớ lại ngay bây giờ.

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

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

Sửa: phiên bản ngắn hơn, mà vẫn không phải là những gì tôi đang suy nghĩ về ... hoặc có thể nó được trong ngôn ngữ khác? :)

(lambda x: lambda self.do_stuff(x))(item)
Các vấn đề liên quan