我试图对一个QPolygon进行筛选,然后加载它,但是我得到了一个错误。我已经在Python2和PyQt4上完成了这项工作,但现在我想在Python3和PyQt5上使用它。
我不想读取/加载使用Python2生成的数据!pickle文件只是用来将Qt元素从Python3临时存储到Python3中,比如QPolygons。
我已经为pickle.dump()测试了从1到4的不同协议选项,并尝试使用"fix_imports=True“选项,这在Python3中应该不会有什么不同。
以下是我的简化代码
from PyQt5.QtGui import QPolygon
from PyQt5.QtCore import QPoint
import pickle
file_name = "test_pickle.chip"
with open(file_name, 'wb') as f:
poly = QPolygon((QPoint(1, 1), QPoint(2, 2)))
pickle.dump(poly, f, protocol=2) # , fix_imports=True)
# loading the data again
with open(file_name, 'rb') as f:
elem = pickle.load(f, encoding='bytes') # , fix_imports=True)我收到以下错误消息,但无法对其执行任何操作:
elem = pickle.load(f,=‘bytes’)#,fix_imports=True) TypeError:索引0的类型为'int‘,但应为'QPoint’
有没有什么可以替代泡菜的?提前感谢!
发布于 2019-02-28 23:37:31
您可以使用QDataStream来序列化/反序列化Qt对象:
from PyQt5 import QtCore
from PyQt5.QtGui import QPolygon
from PyQt5.QtCore import QPoint, QFile, QIODevice, QDataStream, QVariant
file_name = "test.dat"
output_file = QFile(file_name)
output_file.open(QIODevice.WriteOnly)
stream_out = QDataStream(output_file)
output_poly = QPolygon((QPoint(1, 6), QPoint(2, 6)))
output_str = QVariant('foo') # Use QVariant for QString
stream_out << output_poly << output_str
output_file.close()
input_file = QFile(file_name)
input_file.open(QIODevice.ReadOnly)
stream_in = QDataStream(input_file)
input_poly = QPolygon()
input_str = QVariant()
stream_in >> input_poly >> input_str
input_file.close()
print(str(output_str.value()))
print(str(input_str.value()))发布于 2019-03-01 00:54:45
通过对文档的一些搜索,可以了解如何通过__reduce__ method实现定制类的定制酸洗。基本上,您返回一个元组,包括要在取消酸选时创建的新对象的构造函数,以及将传递给构造函数的参数元组。然后,您可以选择传递一个state对象(参见__getstate__和__setstate__)和一些迭代器,以添加位置数据和键值数据。
通过将QPolygon子类化,我们可以像这样添加可拾取性:(这可能是可以清理/重构的,但这是我获得的第一个有效的实现)
from PyQt5.QtGui import QPolygon
from PyQt5.QtCore import QPoint
import pickle
class Picklable_QPolygon(QPolygon):
def __reduce__(self):
# constructor, (initargs), state object passed to __setstate__
return type(self), (), self.__getstate__()
#I'm not sure where this gets called other than manually in __reduce__
# but it seemed like the semantically correct way to do it...
def __getstate__(self):
state = [0]
for point in self:
state.append(point.x())
state.append(point.y())
return state
#putPoints seems to omit the `nPoints` arg compared to c++ version.
# this may be a version dependent thing for PyQt. Definitely test that
# what you're getting out is the same as what you put in..
def __setstate__(self, state):
self.putPoints(*state)
poly = Picklable_QPolygon((QPoint(1, 1), QPoint(2, 2)))
s = pickle.dumps(poly)
elem = pickle.loads(s)发布于 2019-03-01 08:50:05
这一定是pyqt5中的错误,因为the documentation states表明支持酸洗QPolygon。因此,请使用您的示例将错误报告发布到pyqt mailing list。
同时,到目前为止,最简单的替代方法是使用QSettings
from PyQt5.QtGui import QPolygon
from PyQt5.QtCore import QSettings, QPoint
file_name = "test_pickle.chip"
poly = QPolygon((QPoint(1, 1), QPoint(2, 2)))
# write object
s = QSettings(file_name, QSettings.IniFormat)
s.setValue('poly', poly)
del s, poly
# read object
s = QSettings(file_name, QSettings.IniFormat)
poly = s.value('poly')
print(poly)
print(poly.point(0), poly.point(1))输出:
<PyQt5.QtGui.QPolygon object at 0x7f871f1f8828>
PyQt5.QtCore.QPoint(1, 1) PyQt5.QtCore.QPoint(2, 2)这可以用于PyQt支持的任何类型的酸洗,以及PyQt可以convert to/from a QVariant的任何其他类型。PyQt还支持QSettings.value()的type参数,该参数可用于显式声明所需的类型。由于QSettings是为存储应用程序配置数据而设计的,因此可以在同一文件中存储任意数量的对象(有点像python的shelve module)。
https://stackoverflow.com/questions/54928431
复制相似问题