首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将更改的数据延迟加载到QColumnView中(使用PyQt)?

如何将更改的数据延迟加载到QColumnView中(使用PyQt)?
EN

Stack Overflow用户
提问于 2015-09-02 20:40:54
回答 2查看 1.7K关注 0票数 1

我有一个要填充的QColumnView的分层数据源。数据源使用REST接口从服务器加载数据。

假设层次结构如下所示:

代码语言:javascript
复制
Car_Manufacturer -> Car_Type -> Specific_Model -> Motor_Type

我必须使用QColumnView来显示它(因为它是客户的要求)。行为应该是这样的:

当程序启动时,它从服务器加载Car_Manufacturer。当单击其中一个Car_Manufacturer项时,将从服务器加载所选Car_ManufacturerCar_Type项并显示在新列中。当再次单击Car_Manufacturer时,必须再次从服务器获取数据,并且必须更新列。单击Car_Type时,必须从服务器查询此Car_ManufacturerCar_typeSpecific_Model项,并将其加载到新列中...诸若此类。

数据源有这样的api:

代码语言:javascript
复制
datasource.get_manufacturers(hierarchy)  # hierarchy = []
datasource.get_car_type(hierarchy)  # hierarchy = [manufacturer, ]
datasource.get_specific_model(hierarchy)  # hierarchy = [manufacturer, car_type]
datasource.get_motor_type(hierarchy)  # hierarchy = [manufacturer, car_type, specific_model ]

其中分层结构中的每个元素都是该项的字符串键表示。当一个项目被点击时,它必须通过当前项目的层次结构通知控制器这一点。

当使用数据源单击某项时,如何让QColumnView更新该项的子项?当添加或删除新的层次结构层时,这如何保持灵活性?

EN

回答 2

Stack Overflow用户

发布于 2015-09-10 23:29:31

下面是一个实现自定义DirModel的示例。延迟调用方法_create_children应该返回一个实现AbstractTreeItem的实例列表。

代码语言:javascript
复制
import sys
import os
import abc
from PyQt4.QtCore import QAbstractItemModel, QModelIndex, Qt, QVariant
from PyQt4.QtGui import QColumnView, QApplication


class TreeModel(QAbstractItemModel):

    def __init__(self, root, parent=None):
        super(TreeModel, self).__init__(parent)
        self._root_item = root
        self._header = self._root_item.header()

    def columnCount(self, parent=None):
        if parent and parent.isValid():
            return parent.internalPointer().column_count()
        else:
            return len(self._header)

    def data(self, index, role):
        if not index.isValid():
            return QVariant()
        item = index.internalPointer()
        if role == Qt.DisplayRole:
            return item.data(index.column())
        if role == Qt.UserRole:
            if item:
                return item.person
        return QVariant()

    def headerData(self, column, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            try:
                return QVariant(self._header[column])
            except IndexError:
                pass
        return QVariant()

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QModelIndex()
        if not parent.isValid():
            parent_item = self._root_item
        else:
            parent_item = parent.internalPointer()
        child_item = parent_item.child_at(row)
        if child_item:
            return self.createIndex(row, column, child_item)
        else:
            return QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()
        child_item = index.internalPointer()
        if not child_item:
            return QModelIndex()
        parent_item = child_item.parent()
        if parent_item == self._root_item:
            return QModelIndex()
        return self.createIndex(parent_item.row(), 0, parent_item)

    def rowCount(self, parent=QModelIndex()):
        if parent.column() > 0:
            return 0
        if not parent.isValid():
            parent_item = self._root_item
        else:
            parent_item = parent.internalPointer()
        return parent_item.child_count()



class AbstractTreeItem(object):

    __metaclass__ = abc.ABCMeta

    def __init__(self, parent=None):
        self._children = None
        self._parent = parent

    @abc.abstractmethod
    def header(self):
        #return ["name"]
        raise NotImplementedError(self.header)

    @abc.abstractmethod
    def column_count(self):
        #return 1
        raise NotImplementedError(self.column_count)

    def parent(self):
        return self._parent

    @abc.abstractmethod
    def _create_children(self):
        # subclass this method
        return []

    def row(self):
        if self._parent:
            return self._parent._children.index(self)
        return 0

    @property
    def children(self):
        if self._children is None:
            self._children = self._create_children()
        return self._children

    def child_at(self, row):
        return self.children[row]

    @abc.abstractmethod
    def data(self, column):
        #return ""
        raise NotImplementedError(self.data)

    def child_count(self):
        count = len(self.children)
        return count



class DirPathModel(AbstractTreeItem):

    def __init__(self, root="/", parent=None):
        super(DirPathModel, self).__init__(parent)
        self._root = root

    def _create_children(self):
        print "walking into", self._root
        children = []
        try:
            entries = os.listdir(self._root)
        except OSError:
            # no permission etc
            entries = []
        for name in entries:
            fn = os.path.join(self._root, name)
            if os.path.isdir(fn):
                children.append(self.__class__(fn, self))
        return children

    def data(self, column):
        #assert column == 0
        return os.path.basename(self._root)

    def header(self):
        return ["name"]

    def column_count(self):
        return 1


def main():
    app = QApplication(sys.argv)
    view = QColumnView()
    view.setWindowTitle("Dynamic Column view test")
    view.resize(1024, 768)
    root = DirPathModel("/")
    model = TreeModel(root)
    view.setModel(model)
    view.show()
    return app.exec_()


if __name__ == "__main__":
    sys.exit(main() or 0)
票数 3
EN

Stack Overflow用户

发布于 2015-09-10 00:19:19

由于您不能一次带来所有数据和filter it out,因此您必须根据用户从QColumnView执行的任何has selected修改项目模型(addingremoving rows)。

有多种方法可以删除这些项:

  • 您可以使用所选列的索引,并删除此列中“左侧”的所有项。
  • 您可以删除其父项(或祖项)与所做选择相匹配的项

无论你选择哪种方式,你都必须以某种方式反映项目之间的关系。或者从QAbstractItemModel实现,我认为这将是一种过度的杀伤力。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32353458

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档