PyQt/Pyside - 动态创建和连接 - 捕获 lambda 中的函数和参数

f.r*_*ues 0 python lambda pyqt pyside getattr

我正在尝试重新创建 Windows 记事本。

\n\n

我目前正在搞乱QMenuBar

\n\n

我制作了一本字典,其中包含以下模式的所有菜单和操作:

\n\n
menus = {'File':[['New', 'Ctrl+n'],\n                 ['Open', 'Ctrl+o'],\n                 ['Save', 'Ctrl+s'],\n                 ['Save as...', None],\n                 'Separator', \n                 # and so on\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后我迭代该字典,并成功创建菜单和操作并将它们存储在第二个字典中。

\n\n

现在我正在尝试连接每个action[new, open, save, \xe2\x80\xa6] to a instance method of the same name.

\n\n

我这样做是这样的:

\n\n
for action in menus[m]:\n    action = menu.addAction(action[0])\n\n    if action[1]:\n        action.setShortcut(QKeySequence(action[1]))\n\n    if isinstance(action, QAction):\n        fname = action[0].lower() \n        # and some other string manipulations\n        func = getattr(self,fname)\n        action.triggered.connect(lambda arg=action: func(arg))\n
Run Code Online (Sandbox Code Playgroud)\n\n

它连接成功,但如果我尝试使用任何操作,它不会执行任何操作。

\n\n

我以前曾使用 lambda 函数连接操作,但这是我第一次使用getattr() and lambda together.

\n

f.r*_*ues 5

发现我的错误:

问题是func每次迭代都会被覆盖menus

通过更改修复它:

action.triggered.connect(lambda arg=action:func(arg))
Run Code Online (Sandbox Code Playgroud)

action.triggered.connect(lambda f=func,arg=a:f(arg))
Run Code Online (Sandbox Code Playgroud)

后者之所以有效,是因为funclambda 中的默认参数会立即获取对存储的引用。