2011-12-25 7 views
1

У меня проблемы с классом, который реализует __getitem__ и __setitem__.Извлечение данных из QModelIndex вызывает бесконечный цикл

Экземпляры этого класса являются бэкэндом данных QAbstractListModel. Я возвращаю эти экземпляры в реализации модели data(index), когда role==Qt.UserRole, чтобы иметь возможность доступа к объекту за пределами модели.

Один из сценариев, где я хочу это сделать, - это когда пользователь нажимает на любой элемент в QListView, который использует мою модель для отображения данных. Проблема в том, что моя программа запускается в бесконечном цикле (в пределах __getattr__), как только я пытаюсь извлечь данные из индекса, на который пользователь нажал.

Ниже приведен полный фрагмент кода для копирования/вставки, который воспроизводит описанное поведение. Программа будет зацикливаться на линии index.data(Qt.UserRole) от testfunc.

Я где-то пропустил точку или столкнулся с ошибкой в ​​PySide?

#!/usr/bin/python 

from PySide.QtCore import QAbstractListModel, Qt, QObject 
from PySide.QtGui import QApplication, QListView 

import sys 

############################################################################### 

class TestObject(QObject): 
    def __init__(self, parent=None): 
     """Creates new instance of TestObject. 
     @param parent Qt parent.""" 
     super(TestObject, self).__init__(parent) 
     self._data = {} 

    def __getitem__(self, key): 
     """Gets an item from self._data""" 
     if key in self._data.keys(): 
      return self._data[key] 

    def __setitem__(self, key, value): 
     """Sets the value for key.""" 
     self._data[key] = value 

############################################################################### 

class TestModel(QAbstractListModel): 
    def __init__(self, parent=None): 
     """Creates a new instance of TestModel. 
     @param parent Qt parent.""" 
     super(TestModel, self).__init__(parent) 
     self._objects = [] 
     for i in range(5): 
      obj = TestObject(self) 
      obj[i] = str(i) 
      self._objects.append(obj) 

    def rowCount(self, parent): 
     """Returns the amount of datasets.""" 
     return len(self._objects) 

    def columnCount(self): 
     """Returns the amount of columns, which is 1.""" 
     return 1 

    def data(self, index, role=Qt.DisplayRole): 
     """Returns the data for the given model index""" 
     if index.isValid(): 
      obj = self._objects[index.row()] 
      if role == Qt.DisplayRole: 
       return str(obj) 
      elif role == Qt.UserRole: 
       return obj 
     return None 

############################################################################### 

def testfunc(index): 
    """Does something with index.""" 
    print "getting..." 
    index.data(Qt.UserRole) 
    print "never getting here :/" 

############################################################################### 

if __name__ == "__main__": 
    app = QApplication(sys.argv) 
    view = QListView() 
    view.setModel(TestModel()) 
    view.clicked.connect(testfunc) 
    view.show() 
    app.exec_() 
+0

Похоже, ошибка в PySide. Он отлично работает с PyQt4. –

+0

Хорошо, получилось: '__getitem__' нужно поднять' IndexError() ', когда ключ недействителен. Сейчас работает – Chris

+0

А, интересно. Я все еще не понимаю, почему. Что вызывает '__getitem__' на' TestObject'? –

ответ

0

__getitem__ необходимо поднять IndexError() на недействительный ключ

0

Кажется, что PySide пытается перебрать вами объекты (не могу сказать, почему). Как сказано в комментарии, вам нужно поднять IndexError в __getitem__, чтобы остановить эту итерацию внутри PySide.

Информация о __getitem__ и итерации по объекту: https://stackoverflow.com/a/926645/812662