python-pyqt:将多个信号连接到pyqt中的同一函数的正确方法(QSignalMapper不适用)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python-pyqt:将多个信号连接到pyqt中的同一函数的正确方法(QSignalMapper不适用),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2759字,纯文字阅读大概需要4分钟。
内容图文
![python-pyqt:将多个信号连接到pyqt中的同一函数的正确方法(QSignalMapper不适用)](/upload/InfoBanner/zyjiaocheng/663/49f7925ee4d3431da2fee2a10cfc20c5.jpg)
>我已经准备好许多关于如何将多个信号连接到python和pyqt中的同一事件处理程序的文章.例如,将多个按钮或组合框连接到同一功能.
>许多示例显示了如何使用QSignalMapper进行此操作,但是不适用于信号带有参数的情况,例如combobox.currentIndexChanged
>许多人建议可以用lambda制成.我同意,这是一个干净漂亮的解决方案,但是没有人提及lambda创建一个闭包,该闭包包含一个引用-因此无法删除被引用的对象.你好,内存泄漏!
证明:
from PyQt4 import QtGui, QtCore
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget, self).__init__()
# create and set the layout
lay_main = QtGui.QHBoxLayout()
self.setLayout(lay_main)
# create two comboboxes and connect them to a single handler with lambda
combobox = QtGui.QComboBox()
combobox.addItems('Nol Adyn Dwa Tri'.split())
combobox.currentIndexChanged.connect(lambda ind: self.on_selected('1', ind))
lay_main.addWidget(combobox)
combobox = QtGui.QComboBox()
combobox.addItems('Nol Adyn Dwa Tri'.split())
combobox.currentIndexChanged.connect(lambda ind: self.on_selected('2', ind))
lay_main.addWidget(combobox)
# let the handler show which combobox was selected with which value
def on_selected(self, cb, index):
print '! combobox ', cb, ' index ', index
def __del__(self):
print 'deleted'
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
wdg = Widget()
wdg.show()
wdg = None
sys.exit(app.exec_())
尽管我们清除了引用,但未删除该小部件.删除与lambda的连接-它将正确删除.
因此,问题是:在不泄漏内存的情况下,将具有参数的多个信号连接到单个处理程序的正确方法是什么?
解决方法:
不能删除对象是不正确的,因为信号连接在闭包中保留了引用. Qt在删除对象时会自动删除所有信号连接,这反过来又会删除python端对lambda的引用.
但这意味着您不能总是仅依靠Python来删除对象.每个PyQt对象都有两部分:Qt C部分和Python包装器部分.这两个部分都必须删除-有时以特定顺序删除(取决于Qt或Python当前是否拥有该对象的所有权).除此之外,还有Python垃圾收集器的各种变化因素(尤其是在解释器关闭的短时间内).
无论如何,在您的特定示例中,简单的解决方法是:
# wdg = None
wdg.deleteLater()
这计划删除对象,因此需要运行事件循环才能生效.在您的示例中,这还将自动退出应用程序(因为该对象是最后关闭的窗口).
为了更清楚地了解正在发生的事情,您还可以尝试以下操作:
#wdg = None
wdg.deleteLater()
app.exec_()
# Python part is still alive here...
print(wdg)
# but the Qt part has already gone
print(wdg.objectName())
输出:
<__main__.Widget object at 0x7fa953688510>
Traceback (most recent call last):
File "test.py", line 45, in <module>
print(wdg.objectName())
RuntimeError: wrapped C/C++ object of type Widget has been deleted
deleted
编辑:
这是另一个调试示例,希望可以使其更加清晰:
wdg = Widget()
wdg.show()
wdg.deleteLater()
print 'wdg.deleteLater called'
del wdg
print 'del widget executed'
wd2 = Widget()
wd2.show()
print 'starting event-loop'
app.exec_()
输出:
$python2 test.py
wdg.deleteLater called
del widget executed
starting event-loop
deleted
内容总结
以上是互联网集市为您收集整理的python-pyqt:将多个信号连接到pyqt中的同一函数的正确方法(QSignalMapper不适用)全部内容,希望文章能够帮你解决python-pyqt:将多个信号连接到pyqt中的同一函数的正确方法(QSignalMapper不适用)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。