一半君的总结纸

听话只听一半君

QListView QTableView 和 QTreeView 备忘录

这几个view是用在model view 模式里的,比对应的widget的那三种功能多一些,可以更细致的达到想要的效果,但是代码长一些

model view的QxxxView有三种用法

  • 默认用法(使用Qt自带model)
  • 使用QxxxView 再加入custom model
  • 使用QxxxView 再加入custom model以及custom delegate

下面的例子里有些是lz写的,有些是大神博客里抄来的,见底部连接

默认用法

  • QListView 举例

    qlistview

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    data = ['row1', 'row2', 'row3']
    
    
    class MyList(QListView):
    
        def __init__(self, data, parent=None):
            super(MyList, self).__init__(parent)
    
            vertical_headers = []
    
            # The follwing code could be put into main window class
            # Create an empty model for the list's data
            # using the listview as parent
            model = QStandardItemModel(self)
            for d in data:
                item = QStandardItem(d)
                item.setCheckable(True)
                model.appendRow(item)
    
            self.setModel(model)
    
    
    def main(args):
        app = QApplication(args)
        my_list = MyList(data)
        my_list.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main(sys.argv)
    
    
  • QTableView 举例

    qtableview

    
    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    
    class Window(QMainWindow):
    
        'This time I try to put the table populating code in main ui'
    
        def __init__(self, parent=None):
            super(Window, self).__init__(parent)
    
            self.model = QStandardItemModel(5, 3)
            table = QTableView()
            table.setModel(self.model)
    
            for n, key in enumerate(sorted(data.keys())):
                self.model.setHorizontalHeaderItem(n, QStandardItem(key))
                for m, value in enumerate(data[key]):
                    index = self.model.index(m, n)
                    self.model.setData(index, value)
            self.setCentralWidget(table)
            self.resize(350, 220)
    
    
    def main(args):
        app = QApplication(args)
        window = Window()
        window.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main(sys.argv)
    
    
    
  • QTreeView
    例1:用QFileSystemModel 举例

    qtreeview1

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    
    class Window(QMainWindow):
    
        'This time I try to put the table populating code in main ui'
    
        def __init__(self, parent=None):
            super(Window, self).__init__(parent)
    
            self.model = QFileSystemModel()
            self.model.setRootPath(QDir.currentPath())
            tree = QTreeView()
            tree.setModel(self.model)
    
            self.setCentralWidget(tree)
            self.resize(350, 220)
    
    
    def main(args):
        app = QApplication(args)
        window = Window()
        window.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main(sys.argv)
    
    

    例2:用QStandardItemModel 举例

    qtreeview2

    import sys
    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    
    data = {'level1': ['1', '2', '3'],
            'level2': ['4', '5', '6'],
            'level3': ['7', '8', '9']}
    
    
    class Window(QMainWindow):
    
        'This time I try to put the table populating code in main ui'
    
        def __init__(self, parent=None):
            super(Window, self).__init__(parent)
    
            self.model = QStandardItemModel()
            # self.model.setRootPath(QDir.currentPath())
            tree = QTreeView()
            tree.setModel(self.model)
    
            for n, key in enumerate(sorted(data.keys())):
                parent = QStandardItem(key)
                for m, item in enumerate(data[key]):
                    child = QStandardItem(item)
                    parent.appendRow([child])
                self.model.appendRow(parent)
    
            # expand third container
            index = self.model.indexFromItem(parent)
            tree.expand(index)
    
            # select last row
            selmod = tree.selectionModel()
            index2 = self.model.indexFromItem(child)
            selmod.select(
                index2, QItemSelectionModel.Select | QItemSelectionModel.Rows)
    
            self.model.setHeaderData(0, Qt.Horizontal, "Tree View")
    
            self.setCentralWidget(tree)
            self.resize(350, 220)
    
    
    def main(args):
        app = QApplication(args)
        window = Window()
        window.show()
        sys.exit(app.exec_())
    
    if __name__ == "__main__":
        main(sys.argv)
    
    

用法2 使用Custom Model

用法一般是 QAbstractListModel QAbstractTableModel QAbstractItemModel这里面继承一个,然后reimplement一些method:

  • read only table model 至少需要 data(), rowCount(), columnCount(),
    通常headerData()会加上,但不必须
  • Editable models 除了上面的几个,还需要 flags() 和 setData(),如果还需要添加删除row,或者编辑已有data,那还需要
    insertRows() 和 removeRows()

下面是各种使用情景举例

  • QListView + QAbstractListModel 举例

    QAbstractListModel_eg1

    #!/usr/bin/env python
    
    import sys
    from PyQt4.QtGui import *
    from PyQt4.QtCore import *
    
    
    class MyModel(QAbstractListModel):
    
        def __init__(self, parent=None):
            QAbstractListModel.__init__(self, parent)
            self.__data = ['row1', 'row2', 'row3']
    
        def rowCount(self, parent=QModelIndex()):
            return len(self.__data)
    
        def data(self, index, role):
            if not index.isValid():
                return QVariant()
    
            if index.row() >= len(self.__data):
                return QVariant()
    
            if role == Qt.DisplayRole:
                return QVariant(self.__data[index.row()])
            else:
                return QVariant()
    
    
    class MyWidget(QMainWindow):
    
        def __init__(self, parent=None):
            QWidget.__init__(self, parent)
            self.listView = QListView(self)
            model = MyModel(self)
            self.listView.setModel(model)
            self.setCentralWidget(self.listView)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        widget = MyWidget()
        widget.show()
        sys.exit(app.exec_())
    
    
  • QTableView + QAbstractTableModel 举例

    QAbstractTableModel_eg2

    from PyQt4.QtCore import *
    from PyQt4.QtGui import *
    import sys
    
    my_array = [['00', '01', '02'],
                ['10', '11', '12'],
                ['20', '21', '22']]
    
    
    def main():
        app = QApplication(sys.argv)
        w = MyWindow()
        w.show()
        sys.exit(app.exec_())
    
    
    class MyWindow(QWidget):
    
        def __init__(self, *args):
            QWidget.__init__(self, *args)
    
            tablemodel = MyTableModel(my_array, self)
            tableview = QTableView()
            tableview.setModel(tablemodel)
    
            layout = QVBoxLayout(self)
            layout.addWidget(tableview)
            self.setLayout(layout)
            self.resize(350,150)
    
    
    class MyTableModel(QAbstractTableModel):
    
        def __init__(self, datain, parent=None, *args):
            QAbstractTableModel.__init__(self, parent, *args)
            self.arraydata = datain
    
        def rowCount(self, parent):
            return len(self.arraydata)
    
        def columnCount(self, parent):
            return len(self.arraydata[0])
    
        def data(self, index, role):
            if not index.isValid():
                return QVariant()
            elif role != Qt.DisplayRole:
                return QVariant()
            return QVariant(self.arraydata[index.row()][index.column()])
    
    if __name__ == "__main__":
        main()
    
    
  • QListView + QAbstractItemModel 一般不需要直接用QAbstractItemModel,除非特殊需要. doc里提到 “If you need a model to use with a QListView or a QTableView, you should consider subclassing QAbstractListModel or QAbstractTableModel instead of this class”
    
    

用法3 使用Custom Model + custom delegate

  • QListView
    … 待续

问题 Q&A:
Q:QStandardItemModel , QAbstractItemModel, QAbstractListModel, QAbstractTableModel 这几个我怎么才能知道该用哪个?
A: QAbstractItemModel不能直接用,要自己reimplement 几个function,QStandardItemModel可以直接用,比前者要写的少,后两者顾名思义,如果是list或者table的话,用他们可以少写一些

参考书:
Rapid GUI Programming with Python and Qt 2007

参考:
PySide/PyQT Tutorial: QListView and QStandardItemModel
QStandardItemModel
PyQt custom AbstractItemModel – Trevor van Hoof
A Pythonic Qt List Model Implementation
PyQt練習 – 三次元日誌

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: