文字列のリストからのPyQtメニューを作成します。
-
11-09-2019 - |
質問
私は、文字列のリストを持っており、それらの文字列のそれぞれのメニュー項目を作成します。ユーザーがエントリの1をクリックすると、常に同じ関数は、引数として文字列で呼び出されなければなりません。
:いくつかしようと研究の後、私はこのような何かを思い付きました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」の代わりに、対応する1:さて問題は、メニューの各項目は、同じ出力を印刷することです。私はこの権利を得ることができる方法についてのアイデアを感謝します。おかげます。
解決
あなたは、多くの場合、そうでないかもしれない完全にpedantically-正しく(と呼ばれているもの;-)「スコープの問題」としてPythonで開催している - 結合は、あなたがそれを希望しながら、通話時に遅く(字句参照)があります早期(DEF-時)。だからここであなたが今持ってます:
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
ここでは1など)のデフォルト値はDEF-時に一度、すべてのために計算されますから、結合「予想し」。ネスト機能の1つのレベル(例えば、二重ラムダ)を追加すると、あまりにも動作しますが、それはここでやり過ぎのビットだ - !)
あなたは、代わりに別の細かなソリューションです(もちろんの上部に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)
所属していません StackOverflow