- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我不明白下面示例代码的输出 found here .当前线程和工作线程具有相同的地址,这怎么可能?
from PySide import QtCore
class Master(QtCore.QObject):
command = QtCore.Signal(str)
def __init__(self):
QtCore.QObject.__init__(self)
class Worker(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
def do_something(self, text):
print('in thread {} message {}'.format(QtCore.QThread.currentThread(), text))
if __name__ == '__main__':
app = QtCore.QCoreApplication([])
print(QtCore.QThread.currentThread())
# give us a thread and start it
thread = QtCore.QThread()
thread.start()
print(thread)
# create a worker and move it to our extra thread
worker = Worker()
worker.moveToThread(thread)
# create a master object and connect it to the worker
master = Master()
master.command.connect(worker.do_something)
# call a method of the worker directly (will be executed in the actual thread)
worker.do_something('in main thread')
# communicate via signals, will execute the method now in the extra thread
master.command.emit('in worker thread')
# start the application and kill it after 1 second
QtCore.QTimer.singleShot(1000, app.quit)
app.exec_()
# don't forget to terminate the extra thread
thread.quit()
输出:
<PySide.QtCore.QThread object at 0x0000000002537688>
<PySide.QtCore.QThread object at 0x0000000002537688>
in thread <PySide.QtCore.QThread object at 0x00000000025377C8> message in main thread
in thread <PySide.QtCore.QThread object at 0x0000000002537688> message in worker thread
最佳答案
没有“包装器被重用”,只是旧包装器对象(已删除)恰好与新包装器对象位于同一内存地址。
PySide 使用shiboken
库将QObject
包装成Python 对象。 shiboken documentation说如下:
As any python binding, |project|-based bindings uses reference counting to handle the life of the wrapper object (the Python object that contains the C++ object, do not confuse with the wrapped C++ object). When a reference count reaches zero, the wrapper is deleted by Python garbage collector and tries to delete the wrapped instance, but sometimes the wrapped C++ object is already deleted, or maybe the C++ object should not be freed after the Python wrapper go out of scope and die, because C++ is already taking care of the wrapped instance.
除此之外,CPython malloc 实现(以及许多其他常见的 malloc)often reuse the memory address that belonged to just deleted object , 随后创建的对象,导致常见的陷阱:
>>> {} is {}
False
>>> id({}) == id({})
True
因此,事件对象的地址/ID 总是不同的;曾经存在然后死亡的对象的地址只是一种好奇。
在第一种情况下,两个词典的引用都被保留,因此从技术上讲,它们的 id
是不同的,而在第二种情况下,左侧词典很快被删除左边的 id 被调用,然后才创建右边的字典,并分配在相同的内存地址。
然而,它有点复杂。当您调用 currentThread()
时,如果旧包装器仍然存在(意味着它具有在 python 端引用它),在这种情况下返回旧包装器:因此,
QtCore.QThread.currentThread() is QtCore.QThread.currentThread()
永远是真的!
现在,你得到2个地址的原因
in thread <PySide.QtCore.QThread object at 0x00000000028EB888> message in main thread
in thread <PySide.QtCore.QThread object at 0x00000000028EB8C8> message in worker thread
again 不一定与 wrapper “未被重复使用”或被持有无关;取而代之的是,在其间创建的一些其他对象可能会发生同样的效果,其引用被保留——也就是说,人们不应该认为包装对象一定会保持事件状态。
但是,如果您持有对 2 个不同的 QThread
对象的引用,则它们的 id()
在其生命周期内将是不同的。
总而言之,您不应该依赖 shiboken 包装器对象的地址来做任何有用的事情;相反,如果您自己持有 Python 代码中的引用,则 is
测试很有用
请注意,如果设置了 QObject
的 __str__
将打印它们的 objectName
;因此,您可以通过以下操作轻松理解输出:
app = QtCore.QCoreApplication([])
QtCore.QThread.currentThread().setObjectName('main thread')
thread = QtCore.QThread()
thread.start()
thread.setObjectName('worker thread')
并且使用更清晰的打印
:
print('in thread: "{}" - message: "{}"'
.format(QtCore.QThread.currentThread().objectName(), text))
消息将是:
in thread: "main thread" - message: "in main thread"
in thread: "worker thread" - message: "in worker thread"
还有一种方法可以fetch the address of the underlying C++ object , 使用 shiboken模块;这对于调试其他东西也很方便;唉,Ubuntu 14.10 默认情况下根本没有安装 Python 库,或者任何与 shiboken 相关的包;经过无数次回答后,我终于设法手动安装了它。
结果比我想象的更可怕:
app = QtCore.QCoreApplication([])
print(QtCore.QCoreApplication.instance().thread())
obj = QtCore.QObject()
print(obj.thread())
del obj
print(QtCore.QThread.currentThread())
打印:
<PySide.QtCore.QThread object at 0x7fb4a1149cc8>
<PySide.QtCore.QThread object at 0x7fb4a1149cc8>
<PySide.QtCore.QThread object at 0x7fb4a1149d08>
是的,在我删除QObject之后线程包装器的地址改变了!因此,让我们从 Shiboken.shiboken
导入 dump
:
from Shiboken.shiboken import dump
def info(obj):
print(id(obj))
print(dump(obj))
app = QtCore.QCoreApplication([])
info(QtCore.QCoreApplication.instance().thread())
obj = QtCore.QObject()
info(obj.thread())
del obj
info(QtCore.QCoreApplication.instance().thread())
输出是
140323585370568
C++ address....... PySide.QtCore.QThread/0xe3d880
hasOwnership...... 0
containsCppWrapper 0
validCppObject.... 1
wasCreatedByPython 0
parent............ <PySide.QtCore.QCoreApplication object at 0x7f9fa175a948>
140323585370568
C++ address....... PySide.QtCore.QThread/0xe3d880
hasOwnership...... 0
containsCppWrapper 0
validCppObject.... 1
wasCreatedByPython 0
parent............ <PySide.QtCore.QObject object at 0x7f9fa175aa48>
140323585370696
C++ address....... PySide.QtCore.QThread/0xe3d880
hasOwnership...... 0
containsCppWrapper 0
validCppObject.... 1
wasCreatedByPython 0
也就是说,shiboken 生成了 last 对象,我们将其 thread()
方法称为线程的 parent。每当 that 对象被删除时(也就是最后调用 .thread()
的对象),包装器也会被删除。确实是非常可疑的行为;我不确定这是否是一个错误,但这证明了信任包装对象的 id
是根本不值得信任的。
关于python - 在 pyside 中使用 Qt 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29027813/
我想更新小部件的值,但为了防止无限循环,我需要防止调用此小部件的回调函数 .valueChanged信号。 以下示例完全按预期工作: Qt = PySide class MainWindow(Acto
使用以下代码,在尝试发出信号时出现错误(“PySide.QtCore.Signal”对象没有属性“emit”): #!/usr/bin/env python from PySide import Qt
我是 Python 新手。我同时安装了 Python 2.7 和 Python 3。我刚刚尝试通过 Homebrew 安装 PySide 并收到此消息: PySide package successf
是否可以使用 PySide 中的 Web 类之一加载包含按钮的本地 html/JS 文件,并将这些按钮连接到 PySide 插槽? 最佳答案 您可以使用 QtWebKit 将 QObject 导出到
我一直在寻找一个工作示例,该示例如何在使用 QT 设计器创建的 pyside 中嵌入 matplotlib 图,同时将逻辑保存在单独的文件中。我知道网上有很多例子,但没有一个真正使用 QT 设计器,然
我想我可以通过将\PySide 文件夹附加到我的环境的“搜索路径”来添加 PySide 库,但智能感知似乎没有发现任何东西。不过,它正在使用我的其他图书馆。有什么建议吗? 注意:我已经安装了 PTVS
我正在设计一个 Pyside Qt 应用程序,我想切换 QtCore.Qt.WindowStaysOnTopHint我的主窗口中的窗口标志。使用此代码设置此提示工作正常: self.setWindow
你如何在 PySide 中禁用声子? 我正在尝试使用 QWebpage 并且我不希望 phonon 启动,因为我正在编写的应用程序是服务器端应用程序,并且不需要媒体。我尝试了一些东西,但没有找到任何真
本文为大家分享了pyside pyqt实现鼠标右键菜单功能的具体代码,供大家参考,具体内容如下 在三维软件中使用pyside/pyqt编写gui界面时,为了艺术家使用操作的简洁,以及方便,经常会使
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我试图在 PySide 的单独线程中运行一个长任务,以便主线程可以继续处理 GUI 事件。我已经阅读了执行此操作的正确方法: 将任务封装在 QObject 子类中,其中工作在 run() 方法中完成,
我想知道如何根据最大标签的最大宽度/高度截断QLabel中的文本。 输入的文本可以是任意长度,但是为了保持整洁的布局,我想截断长字符串以填充最大空间(小部件的最大宽度/高度)。 例如。: 'A ve
我有一个界面,屏幕顶部有 4 个按钮,下面有 QFrame。我想根据按下的按钮更改 QFrame 中的布局。例如,如果按下 Button_1 显示一个 TextEdit Widget,如果按下 But
我想制作一个小部件的角。在 PyQt 中,我用样式表解决了这个问题,效果很好。我想在 PySide 中做同样的事情,但由于某些原因它不起作用。 这是我的代码: TitelWidget = QtGui.
我是 python 和 pyside 的新手。我将尝试成功运行以下代码。但现在我希望程序在显示窗口后等待用户无法使用它的定义时间,然后升级状态栏。我会尝试 sleep() 但不知道它必须以正确的方式放
我从 example of Zetcode 开始学习 PySide并尝试编写具有两个窗口的应用程序:“布局 View ”的父级“示意图 View ”,每个窗口都有菜单栏。启动时应该只是原理图窗口,布局
我从 example of Zetcode 开始学习 PySide并尝试编写具有两个窗口的应用程序:“布局 View ”的父级“示意图 View ”,每个窗口都有菜单栏。启动时应该只是原理图窗口,布局
我正在尝试通过 pyside 设置 QGridLayout 小部件的背景图像(位于与应用程序相同的文件夹中),但无济于事我已经查看了有关样式表的所有图、文档和论坛帖子,但仍然我不知道我做错了什么。 f
我有一个带有 5 个按钮的布局,我充当“菜单”,因此您单击一个按钮,会显示一个 View ,单击另一个按钮,会显示另一个 View 。我需要找出单击了哪个按钮,以便我可以根据按下的按钮执行某些操作。类
基本上我想要的是: 在主窗口中显示一个小部件,其中包含打开 QFileDialog 的按钮 选择文件后,包含按钮的小部件应切换到新的小部件,该新小部件会显示一些基于文件内容的可视化效果。 在下面的代码
我是一名优秀的程序员,十分优秀!