发送自定义PyQt信号?

2024-09-24 00:32:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在通过制作一个简单的Twitter客户端来练习PyQt和(Q)线程。我有两个线程。

  1. 主/GUI线程。

  2. Twitter fetch线程-每X分钟从Twitter获取数据。

所以,每隔X分钟,我的Twitter线程就会下载一组新的状态更新(Python列表)。我想把这个列表交给Main/GUI线程,这样它就可以用这些状态更新窗口。

我假设我应该使用signal/slot系统将“statuses”Python列表从Twitter线程传输到Main/GUI线程。所以,我的问题有两个:

  1. 如何从Twitter线程发送状态?

  2. 如何在主/GUI线程中接收它们?

据我所知,PyQt默认情况下只能通过信号/插槽发送PyQt对象。我想我应该以某种方式注册一个自定义信号,然后我可以发送,但我发现的文件是非常不清楚的一个新手喜欢我。我订了一本PyQt的书,但再过一周就到不了了,我不想等到那时候。:-)

我在Ubuntu上使用PyQt 4.6-1

更新:

这是不起作用的代码的一个例外。首先,我尝试将信号(“newStatuses”,我刚编好的一个名字)连接到Main/GUI线程中的函数self.update_tweet_list:

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses (statuses)"),
                       self.update_tweet_list)

然后,在Twitter线程中,我这样做:

self.emit(SIGNAL("newStatuses (statuses)"), statuses)

调用此行时,我将收到以下消息:

QObject::connect: Cannot queue arguments of type 'statuses'
(Make sure 'statuses' is registered using qRegisterMetaType().)

我搜索了qRegisterMetaType(),但没有找到任何可以理解的与Python相关的内容。


Tags: self列表信号main状态updateguitwitter
3条回答

回头看看这个question I asked。有一个代码示例可以帮助您找出需要执行的操作。

你所说的注册你的信号让我想到了这个代码(从上面的问题):

class ProcessingThread(threading.Thread, QtCore.QObject):
    __pyqtSignals__ = ( "progressUpdated(str)",
                        "resultsReady(str)")

我在示例中传递字符串,但您应该能够用list替换str

如果结果发现不能传递可变对象,可以像我在示例中那样处理结果(即在线程中设置一个results变量,告诉主线程它们已经准备好了,并让主线程“接收它们”)。

更新:

您得到消息QObject::connect: Cannot queue arguments of type 'statuses',因为您需要定义当您发出信号时将通过的类型参数。要传递的类型是list,而不是statuses

当你连接你的信号时,它应该是这样的:

QtCore.QObject.connect(self.twit_in,
                       QtCore.SIGNAL("newStatuses(list)"),
                       self.update_tweet_list)

当你发出信号时,它应该是这样的:

self.emit(SIGNAL("newStatuses(list)"), statuses)

假设statuses是一个列表。请注意,根据您的情况,您可能需要发送列表的深层副本。

更新2:

好的,使用list作为类型是不正确的。从PyQt4帮助参考:

PyQt Signals and Qt Signals

Qt signals are statically defined as part of a C++ class. They are referenced using the QtCore.SIGNAL() function. This method takes a single string argument that is the name of the signal and its C++ signature. For example::

QtCore.SIGNAL("finished(int)")

The returned value is normally passed to the QtCore.QObject.connect() method.

PyQt allows new signals to be defined dynamically. The act of emitting a PyQt signal implicitly defines it. PyQt v4 signals are also referenced using the QtCore.SIGNAL() function.

The PyQt_PyObject Signal Argument Type

It is possible to pass any Python object as a signal argument by specifying PyQt_PyObject as the type of the argument in the signature. For example::

QtCore.SIGNAL("finished(PyQt_PyObject)")

While this would normally be used for passing objects like lists and dictionaries as signal arguments, it can be used for any Python type. Its advantage when passing, for example, an integer is that the normal conversions from a Python object to a C++ integer and back again are not required.

The reference count of the object being passed is maintained automatically. There is no need for the emitter of a signal to keep a reference to the object after the call to QtCore.QObject.emit(), even if a connection is queued.

你也可以这样做,这是更Python(和可读!)。

# create a signal equivalent to "void someSignal(int, QWidget)"
someSignal = QtCore.pyqtSignal(int, QtGui.QWidget)

# define a slot with the same signature
@QtCore.pyqtSlot(int, QtGui.QWidget)
def someSlot(status, source):
    pass

# connect the signal to the slot
self.someSignal.connect(self.someSlot)

从这个例子来看:

http://doc.qt.digia.com/4.5/qmetatype.html

 int id = QMetaType.type("MyClass");

你可以用Python写下来

from PyQt4 import QtCore    
id = QtCore.QMetaType.type('MyClass')

编辑

从评论中得到的答案是:

self.emit(SIGNAL("newStatuses(PyQt_PyObject)"), statuses)

相关问题 更多 >