Setting and getting “data” from PyQt widget items?

2020-06-18 09:47发布

问题:

This is not so much a question as it is a request for an explanation. I'm following Mark Summerfield's "Rapid GUI Programming with Python and Qt", and I must've missed something because I cannot make sense of the following mechanism to link together a real "instance_item" which I am using and is full of various types of data, and a "widget_item" which represents it in a QTreeWidget model for convenience.

Setting:

widget_item.setData(0, Qt.UserRole, QVariant(long(id(instance_item))))

Getting

widget_item.data(0, Qt.UserRole).toLongLong()[0]

Stuff like toLongLong() doesn't seem "Pythonic" at all, and why are we invoking Qt.UserRole and QVariant? are the "setData" and "data" functions part of the Qt framework or is it a more general Python command?

回答1:

There are at least 2 better solutions. In order of increasing pythonicity:

1) You don't need quite so much data type packing

widget_item.setData(0, Qt.UserRole, QVariant(instance_item))
widget_item.data(0, Qt.UserRole).toPyObject()

2) There is an alternate API to PyQt4 where QVariant is done away with, and the conversion to-from QVariant happens transparently. To enable it, you need to add the following lines before any PyQt4 import statements:

import sip
sip.setapi('QVariant', 2)

Then, your code looks like this:

widget_item.setData(0, Qt.UserRole, instance_item)
widget_item.data(0, Qt.UserRole)  # original python object

Note that there is also an option sip.setapi('QString', 2) where QString is done away with, and you can use unicode instead.



回答2:

All of these methods -- setData(), data(), toLongLong() are all part of Qt and were originally intended to be used in C++, where they make a lot more sense. I'm not really sure what the author is trying to do here, but if you find yourself doing something terribly un-pythonic, there is probably a better way:

## The setter:
widget_item.instance_item = instance_item

## The getter:
instance_item = widget_item.instance_item

The Qt docs can't recommend this, of course, because there are no dynamic attribute assignments in C++. There are a few very specific instances when you may have to deal with QVariant and other such nonsense (for example, when dealing with databases via QtSQL), but they are quite rare.