我正在使用PyQt5和Python 3来显示通过串口从嵌入式设备接收的一些数据。库PySerial用于处理串行通信。由于PySerial的read函数的返回类型是bytes
,我使用一个线程以bytes
类型发出接收的数据。有趣的是,字节b'\x00'
和之后的所有字节在发送 - 接收周期中都会丢失。但是,如果发射信号的类型设置为QByteArray
,则会正确发送和接收数据。
以下是重现问题的MWE:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtWidgets
class Example(QtWidgets.QWidget):
new_bytes = QtCore.pyqtSignal(bytes)
new_qba = QtCore.pyqtSignal('QByteArray')
bytes_to_emit = b'\x01\x00\x02'
def __init__(self, parent=None):
super(Example, self).__init__()
self.init_ui()
self.setWindowTitle('Emit Bytes Bug')
def init_ui(self):
emit_label = QtWidgets.QLabel('Data to emit')
data_label = QtWidgets.QLabel(self.bytes_to_emit.hex())
emit_bytes_button = QtWidgets.QPushButton('Emit bytes')
emit_qba_button = QtWidgets.QPushButton('Emit QByteArray')
self.rev_bytes_edit = QtWidgets.QLineEdit()
self.rev_qba_edit = QtWidgets.QLineEdit()
clear_button = QtWidgets.QPushButton('Clear receive')
grid_layout = QtWidgets.QGridLayout()
grid_layout.addWidget(emit_label, 0, 0)
grid_layout.addWidget(data_label, 0, 1)
grid_layout.addWidget(emit_bytes_button, 1, 0)
grid_layout.addWidget(self.rev_bytes_edit, 1, 1)
grid_layout.addWidget(emit_qba_button, 2, 0)
grid_layout.addWidget(self.rev_qba_edit, 2, 1)
grid_layout.addWidget(clear_button, 3, 0)
self.setLayout(grid_layout)
emit_bytes_button.clicked.connect(self.on_bytes_button)
emit_qba_button.clicked.connect(self.on_qba_button)
self.new_bytes.connect(self.update_byte_receive)
self.new_qba.connect(self.update_qba_receive)
clear_button.clicked.connect(self.on_clear_button)
def update_byte_receive(self, data):
data_str = data.hex()
self.rev_bytes_edit.insert(data_str)
def update_qba_receive(self, data):
tmp_bytes = bytes(data)
data_str = tmp_bytes.hex()
self.rev_qba_edit.insert(data_str)
def on_bytes_button(self):
self.new_bytes.emit(self.bytes_to_emit)
def on_qba_button(self):
self.new_qba.emit(self.bytes_to_emit)
def on_clear_button(self):
self.rev_bytes_edit.clear()
self.rev_qba_edit.clear()
def main():
app = QtWidgets.QApplication(sys.argv)
form = Example()
form.show()
app.exec_()
if __name__ == '__main__':
main()
要发出的数据是b'\x01\x00\x02'
,点击“发送字节”即可。按钮将发出' bytes'中的数据。在按钮右侧的lineedit中键入并显示接收的数据。同样,点击发送QByteArray'按钮将以QByteArray
类型发出数据,并在按钮的相应lineedit上显示接收的数据。 '清除接收'按钮只是清除lineedits。
虽然我已经知道了替代工作解决方案,即使用QByteArray
类型发出字节信号,我想知道当发出信号时哪种信号类型是首选的。如果需要发出的数据已经在bytes
类型,那么使用Python 3的本机bytes
类型会更快吗?或者PyQt5的QByteArray
更接近底层的C ++代码?任何建议都将不胜感激。
Python3版本:3.5
PyQt5版本:5.7
提前致谢
答案 0 :(得分:0)
您可能需要查看Signals and Slots
的PyQt文档当发出信号时,如果可能,任何参数都将转换为C ++类型。
和Python Strings, Qt Strings and Unicode
对于Python v3,默认情况下会进行以下转换。
如果
Qt
需要char *
(或const
版本),那么PyQt5
将接受仅包含ASCII字符的str
,bytes
,QByteArray
, 或者实现buffer
协议的Python对象。如果
Qt
需要char
(或const
版本),那么PyQt5
将接受与char *
相同的类型,并且还需要那一个 提供了角色。如果
Qt
需要signed char *
或unsigned char *
(或const
版本),那么PyQt5
将接受bytes
如果
Qt
需要signed char
或unsigned char
(或const
版本),那么PyQt5
将接受bytes
长度为1。如果
Qt
期望QString
,那么PyQt5
将接受str
,bytes
只包含ASCII
个字符,QByteArray
或None
。如果
Qt
期望QByteArray
,那么PyQt5
也会接受bytes
。如果
Qt
期望QByteArray
,则PyQt5
也会接受仅包含str
个字符的Latin-1
。
正如您所看到的,有C++/Qt
种PyQt
种类型bytes
将愉快地转换为QByteArray
个对象。它如何知道您想要new_bytes
?它没有。
如果您在调试器中停止代码并查看QString
信号,您将看到信号已被赋予C
类型(至少这是在python2下发生的情况)。 7在我的系统上)。如果您熟悉x/00
字符串的工作方式,则无论缓冲区大小如何,您都会知道字节C++
表示字符串的结尾。这就是你的输出在`x / 00。
无论哪种方式,python对象都需要转换为QtCore.pyqtSignal('QByteArray')
类型。使用PyQt
声明信号会明确告诉class Question extends Model
{
public function answers()
{
return $this->hasMany('App\Answer');
}
}
您想要哪种类型。