Python: как использовать элементы ListWidget для хранения и извлечения объектов: Easy

После работы с QListWidget и другими виджетами "листинга" я наконец пришел к тому, что кажется простым решением для хранения и извлечения классов списка элементов (QListWidgetItem). Проблема, которую я представляла себе, заключалась в том, что я думал, что QListWidgetItem можно использовать только для хранения своего имени метки (той, которая используется для отображения в ListWidget). К тому времени, когда QListWidget был заполнен QListWidgetItems, мне пришлось объявить словарь, где каждый ключ был бы именем метки элемента, а значение будет равно самому объекту (опасный подход, поскольку два или более элемента могут иметь одно и то же имя, а словари может иметь только один ключ с тем же именем). Затем, когда элемент будет нажат, я бы захватил метку элемента списка (имя) и просмотрел ключи словаря, чтобы найти соответствующий объект. Все это можно было бы легко избежать, если я объявлю свой собственный класс myItem(), который наследует от QListWidgetItem. Теперь, когда элемент списка нажат, я могу получить объект от него напрямую, как я называю метод.getTime(). Пожалуйста, дайте мне знать, если я упустил или не понял ничего, прежде чем переходить к использованию этого подхода в своем коде.

from PyQt4 import QtGui, QtCore
import sys, os


class myItem(QtGui.QListWidgetItem):
 def __init__(self, name):
 super(myItem, self).__init__()
 self.name=name
 def getTime(self):
 import datetime
 return datetime.datetime.now() 

class Dialog_01(QtGui.QMainWindow):
 def __init__(self):
 super(QtGui.QMainWindow,self).__init__()

 myQWidget = QtGui.QWidget()
 myBoxLayout = QtGui.QVBoxLayout()
 myQWidget.setLayout(myBoxLayout)
 self.setCentralWidget(myQWidget)

 self.listWidget = QtGui.QListWidget()

 self.listWidget.currentItemChanged.connect(self.item_clicked)

 for i in range(12):
 name='Item '+str(i)
 my_item=myItem(name)
 my_item.setText('Item '+str(i))
 self.listWidget.addItem(my_item)

 myBoxLayout.addWidget(self.listWidget)

 def item_clicked(self, arg=None):
 print arg.text(), arg.getTime()


if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 dialog_1 = Dialog_01()
 dialog_1.show()
 dialog_1.resize(480,320)
 sys.exit(app.exec_())
4 ответа

Вы можете установить пользовательские данные QListWidgetItem через QListWidgetItem.setData(self, role, value).

Вы можете указать свои собственные роли и, таким образом, добавить конкретные данные прямо к этому виджету.

Чтобы получить данные, используйте QListWidgetItem.data(self, role) с правильной ролью.


Вот работающая реализация той же концепции (сохранение данных в Qt-элементах). На этот раз с ComboBox:

from PyQt4 import QtGui, QtCore
import sys, os

class MyClass(object):
 def __init__(self):
 super(MyClass, self).__init__()
 self.myAttr=None
 def getTime(self):
 import datetime
 return datetime.datetime.now() 

class Dialog_01(QtGui.QMainWindow):
 def __init__(self):
 super(QtGui.QMainWindow,self).__init__()

 myQWidget = QtGui.QWidget()
 myBoxLayout = QtGui.QVBoxLayout()
 myQWidget.setLayout(myBoxLayout)
 self.setCentralWidget(myQWidget)

 self.ComboBox = QtGui.QComboBox() 
 for i in range(12):
 name='Item '+str(i)
 myObject=MyClass()
 self.ComboBox.addItem( name, myObject )

 self.ComboBox.currentIndexChanged.connect(self.combobox_selected)
 myBoxLayout.addWidget(self.ComboBox)

 def combobox_selected(self, index):
 myObject=self.ComboBox.itemData(index).toPyObject()
 print myObject.getTime()

if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 dialog_1 = Dialog_01()
 dialog_1.show()
 dialog_1.resize(480,320)
 sys.exit(app.exec_())


Я пошел один за другим, пробуя каждый из методов QVariant, который начинается с 'to':

'toBool', 'toByteArray', 'toChar', 'toDate', 'toDateTime', '********', 'toEasingCurve', 'toFloat', 'toHash', 'toInt', 'toLine', 'toLineF', 'toList', 'toLocale', 'toLongLong', 'toMap', 'toModelIndex', 'toPoint', 'toPointF', 'toPyObject', 'toReal', 'toRect', 'toRectF', 'toRegExp', 'toSize', 'toSizeF', 'toString', 'toStringList', 'toTime', '******', 'toULongLong', 'toUrl', 'toUuid'

и я обнаружил, что toPyObject() возвращает точно тот же объект (в примере ниже это экземпляр MyClass()), который хранится в элементе списка во время его создания, используя:

myObject=MyClass() 
 my_item.setData(QtCore.Qt.UserRole, myObject)

Вот код, который работает для меня. Пожалуйста, поправьте меня, если я ошибаюсь.

from PyQt4 import QtGui, QtCore
import sys, os

class MyClass(object):
 def __init__(self):
 super(MyClass, self).__init__()
 def getTime(self):
 import datetime
 return datetime.datetime.now() 

class Dialog_01(QtGui.QMainWindow):
 def __init__(self):
 super(QtGui.QMainWindow,self).__init__()

 myQWidget = QtGui.QWidget()
 myBoxLayout = QtGui.QVBoxLayout()
 myQWidget.setLayout(myBoxLayout)
 self.setCentralWidget(myQWidget)

 self.listWidget = QtGui.QListWidget()

 self.listWidget.currentItemChanged.connect(self.item_clicked)

 for i in range(12):
 name='Item '+str(i)
 my_item=QtGui.QListWidgetItem()
 my_item.setText('Item '+str(i))
 self.listWidget.addItem(my_item)

 myObject=MyClass() 
 my_item.setData(QtCore.Qt.UserRole, myObject)

 myBoxLayout.addWidget(self.listWidget)

 Button_01 = QtGui.QPushButton("Get Items")
 Button_01.clicked.connect(self.getListItemsFromQListWidget) 
 myBoxLayout.addWidget(Button_01)

 def item_clicked(self, arg=None):
 myObject = arg.data(QtCore.Qt.UserRole)
 print myObject.toPyObject().getTime()

 def getListItemsFromQListWidget(self):
 for i in range(self.listWidget.count()):
 print self.listWidget.item(i).data(QtCore.Qt.UserRole).toPyObject().getTime()

if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 dialog_1 = Dialog_01()
 dialog_1.show()
 dialog_1.resize(480,320)
 sys.exit(app.exec_())


Благодарю! Вот попытка. Сначала присваиваем myObject:

my_item.setData (QtCore.Qt.UserRole, myObject)

Затем, щелкнув, верните его с помощью:

myObject = arg.data(QtCore.Qt.UserRole)

Полученный myObject на item_clicked есть. Где ошибка?

from PyQt4 import QtGui, QtCore
import sys, os


class MyClass(object):
 def __init__(self):
 super(MyClass, self).__init__()
 def getTime(self):
 import datetime
 return datetime.datetime.now() 


class Dialog_01(QtGui.QMainWindow):
 def __init__(self):
 super(QtGui.QMainWindow,self).__init__()

 myQWidget = QtGui.QWidget()
 myBoxLayout = QtGui.QVBoxLayout()
 myQWidget.setLayout(myBoxLayout)
 self.setCentralWidget(myQWidget)

 self.listWidget = QtGui.QListWidget()

 self.listWidget.currentItemChanged.connect(self.item_clicked)

 for i in range(12):
 name='Item '+str(i)
 my_item=QtGui.QListWidgetItem()
 my_item.setText('Item '+str(i))
 self.listWidget.addItem(my_item)

 myObject=MyClass()
 my_item.setData (QtCore.Qt.UserRole, myObject)

 myBoxLayout.addWidget(self.listWidget)

 def item_clicked(self, arg=None):
 myObject = arg.data(QtCore.Qt.UserRole)
 print dir(myObject)

if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 dialog_1 = Dialog_01()
 dialog_1.show()
 dialog_1.resize(480,320)
 sys.exit(app.exec_())

licensed under cc by-sa 3.0 with attribution.