2015-07-24 7 views
0

Я хочу сделать TreeView где элементы верхнего уровня охватывают все столбцы (например, они имеют одну строку), в то время как дети охватывают несколько столбцов (например, у них есть несколько строк.)охватывающих несколько столбцов, используя QTreeView и QAbstractItemModel

Я пытался выполнить это с помощью QTreeView.setFirstColumnSpanned. Тем не менее, я не могу понять, где/когда называть это (и, возможно, я начну с совершенно неправильных действий).

Я подумал, может быть, я мог бы сделать функцию на мой взгляд, которая будет называться после заполнения представления, для проверки любых элементов, которые должны обновлять их интервалы.

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

Я также попытался реализовав InsertRows в моей модели и/or rowsInserted в моем представлении, но они никогда не вызываются.

Вот очень упрощенный вариант того, что я делаю:

class MyModel(QtCore.QAbstractItemModel): 
    def __init__(self, top_level_nodes): 
     QtCore.QAbstractItemModel.__init__(self) 
     self.top_level_nodes = top_level_nodes 
     self.columns = 5 

    def columnCount(self, parent): 
     return self.columns 

    def rowCount(self, parent): 
     total = len(self.top_level_nodes) 
     for node in self.top_level_nodes: 
      total += len(node.subnodes) 
     return total 

    def data(self, index, role): 

     if not index.isValid(): 
      return QtCore.QVariant() 

     if role == QtCore.Qt.DisplayRole: 
      obj = index.internalPointer() 
      return obj.name 

     return QtCore.QVariant() 

    def index(self, row, column, parent): 
     if not parent.isValid(): 
      if row > (len(self.top_level_nodes) - 1): 
       return QtCore.QModelIndex() 

      return self.createIndex(row, column, self.top_level_nodes[row]) 

     return QtCore.QModelIndex() 

    def parent(self, index): 
     if not index.isValid(): 
      return QtCore.QModelIndex() 

     node = index.internalPointer() 
     if node.parent is None: 
      return QtCore.QModelIndex() 

     else: 
      return self.createIndex(node.parent.row, 0, node.parent) 

class FakeEntry(object): 
    def __init__(self, name, row, children=[]): 
     self.parent = None 
     self.row = row 
     self.name = 'foo' 
     self.subnodes = children 

class MainWindow(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 

     self.resize(800, 600) 

     self.layout = QtGui.QVBoxLayout(self) 
     self.tree_view = QtGui.QTreeView(self) 
     self.layout.addWidget(self.tree_view) 

     entry = FakeEntry('foo', 0, children=[]) 
     self.model = MyModel([entry]) 
     self.tree_view.setModel(self.model) 

def main(): 
    app = QtGui.QApplication(sys.argv) 
    frame = MainWindow() 
    frame.show() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

Этот код работает отлично. Что мне нужно знать:

Как я могу создать запись, созданную FakeEntry, для всех 5 столбцов вместо создания 5 одинаковых ячеек?

Другие вопросы:

  • Могу ли я переописать QAbstractItemModel.insertRows или QTreeView.rowsInserted? Есть ли «трюк» для этого, что мне не хватает, что заставляет мой код забрать реализацию по умолчанию?
  • Что на самом деле обрабатывает создание строк/столбцов в представлении, как только модель заполнена данными и прикреплена к виду?

ответ

1

Это работает для меня, если я добавить вызов setFirstColumnSpanned после setModel() вызова в MainWindow.__init__().

class MainWindow(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 

     self.resize(800, 600) 

     self.layout = QtGui.QVBoxLayout(self) 
     self.tree_view = QtGui.QTreeView(self) 
     self.layout.addWidget(self.tree_view) 

     entry = FakeEntry('foo', 0, children=[]) 
     self.model = MyModel([entry]) 
     self.tree_view.setModel(self.model) 
     self.tree_view.setFirstColumnSpanned(0, QtCore.QModelIndex(), True) 

Я считаю, что представление отслеживает натянутые столбцы внутри, отдельно от модели. Но он будет сбросить информацию о промежутке всякий раз, когда вызывается setModel(). Итак, вы должны позвонить setFirstColumnSpanned() после звонка setModel() на просмотр. Если ваша модель делает ленивую загрузку с fetchMore(), вам нужно будет каким-то образом сообщить, что она должна обновлять промежутки после того, как модель загрузила новые данные.

WRT Что на самом деле привело к созданию строк/столбцов в представлении, я думаю об этом как о партнерстве между моделью и представлением. Когда представление имеет набор моделей, он начинает задавать различные вопросы модели. Для самого верхнего родительского элемента (недопустимый индекс), сколько столбцов есть? Круто, есть 5. Сколько там строк? Хорошо, 1. Только из этой информации заголовок представления может начать настраивать себя. В определенный момент представление выполняет итерацию по строкам, столбцам и дочерним элементам в модели и запрашивает каждый индекс для своих данных по очереди для каждой роли данных. Затем он может начать создавать делегаты для отображения этих данных в соответствующем месте в представлении.

+0

Да, это полностью работает. Благодаря!! – almaghest

Смежные вопросы