第15.23節 PyQt(Python+Qt)入門學習:Model/View架構中QListView視圖配套Model的開發使用

一、概述

QListView理論上可以和所有QAbstractItemModel派生的類如QStringListModel、QDirModel、QFileSystemModel、QStandardItemModel等對接,但QListView實際上能展示的數據僅一列,對於複雜的樹形層次使用Model使用QListView來展現意義不大。本節通過幾個簡單代碼案例來闡述QListView/Model開發的過程。

二、QListView/QStringListModel

2.1、QStringListModel介紹

QStringListModel是Qt提供的一個已經實現QAbstractItemModel相關接口的Model,適合於展示一系列字符串的簡單視圖如QListView對象和QComboBox對象。

QStringListModel提供了所有可編輯模型的標準函數,將字符串列表中的數據存儲爲一個一列多行的模型。

使用index(int row, int column = 0, QModelIndex parent = QModelIndex())函數獲取與項對應的模型索引,使用flags(QModelIndex index)獲取項標誌;使用data()函數讀取項數據,並使用setData()寫入項數據,使用rowCount()函數訪問模型數據的行數。

該模型可以用現有的字符串列表來構造,或者可以用setStringList()函數來設置字符串。字符串也可以用insertRows()函數以通常的方式插入,並用removeRows()刪除。字符串列表的內容可以使用stringList()函數檢索。

2.2、使用QStringListModel作爲QListView的Model

使用QStringListModel作爲QListView的Model的方法非常簡單,先創建QStringListModel實例對象,如果數據未存儲到Model中則將數據存儲到Model,然後再將QListView對象的Model設置爲剛創建的Model實例。步驟如下:

2.2.1、 創建QStringListModel實例對象

實例對象創建有兩種方法:

  • 創建無數據的Model
    語法爲:QStringListModel(QObject parent = None)
  • 創建Model同時初始化數據
    語法爲:QStringListModel(strings,QObject parent = None)
    其中strings爲要展示的字符串列表數據。
2.2.2、初始化model中的數據

如果創建的model中無數據,可以通過幾種方法初始化model中的數據:

  • 使用setStringList(str)方法完成初始化,示例代碼:
self.model1.setStringList(["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"])
  • 使用insertRows()、index()、setData()方法組合實現
    insertRows是在model中插入空的數據記錄,只是佔據了數據位置,但沒有實際的數據,需要通過setData來生成實際存儲的數據。這種組合方法沒有多大實際價值,具體方法的參數及含義在此不進行詳細介紹。

  • 使用視圖的setModel(model)方法將model和view建立連接

2.2.3、示例代碼及運行截圖

本示例代碼使用先創建對象再使用setStringList方法初始化數據:

 def initStringListModel(self):
        strList = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"]
        self.model = QStringListModel()
        self.model.setStringList(strList )
        self.listView.setModel(self.model)

運行截圖:
在這裏插入圖片描述

三、QListView/QFileSystemModel

3.1、概述

QFileSystemModel提供了將本地文件系統中指定目錄文件結構樹形文件列表的進行存儲的model類,它提供對本地文件系統的訪問,提供重命名和刪除文件和目錄以及創建新目錄的功能。在最簡單的情況下,它可以作爲瀏覽器或過濾器的一部分與適當的顯示部件一起使用。

雖然QListView是單層次的視圖,QFileSystemModel是樹形層次的model,但還是可以在QListView中使用類似QFileSystemModel這種樹狀層次數據Model。只是視圖展示時只會展示最頂層的數據,因此實際意義不大。

3.2、使用QFileSystemModel作爲QListView的Model

使用QFileSystemModel來作爲QListView的model非常簡單,只有三步就可以實現:

  1. 創建QFileSystemModel對象

  2. 使用setRootPath設置QFileSystemModel對應文件的目錄路徑

  3. 使用視圖的setModel(model)方法將model和view建立連接

3.3、示例代碼

    def initDirModel(self):
        self.model = QtWidgets.QFileSystemModel()
        self.model.setRootPath(r"c:\temp")#監視目錄異動
        self.listView.setModel(self.model)
        self.listView.setRootIndex(self.model.index(r"c:\temp"))()))#切換顯示目錄

運行截圖:
在這裏插入圖片描述

四、QListView/QStandardItemModel

4.1、概述

QStandardItemModel是Model/View架構中用於存儲自定義數據的通用Model,它提供了一種經典的基於項的方法來處理模型,模型中的項類型必須是QStandardItem類或其派生子類。

QStandardItemModel實現QAbstractItemModel定義的接口,這意味着該模型可以用於在任何支持該接口的視圖(例如QListView、QTableView和QTreeView,以及自己的自定義視圖)中提供數據。爲了實現性能和靈活性,需要對從QAbstractItemModel模型派生子類,以提供對不同類型的數據存儲的支持,例如,QDirModel爲底層文件系統提供一個模型接口。

4.2、使用QStandardItemModel作爲QListView的Model

由於QStandardItemModel是一個通用的Model,使用它作爲視圖的Model實現起來比類似QFileSystemModel等便利化專用化的Model要稍微複雜,其複雜主要是數據初始化方面。具體實現步驟如下:

  1. 創建Model對象
    可以使用QStandardItemModel(parent: QObject = None)、QStandardItemModel(int rowCount, int columnCount, parent: QObject = None)來創建Model對象。

  2. 初始化數據
    初始化數據時,需要每個數據創建一個QStandardItem或其派生類的對象,並將其加入到Model中去。QStandardItem類有四個構造方法QStandardItem()、QStandardItem(str text)、QStandardItem(QIcon icon, str text)、QStandardItem(int rows, int columns = 1),分別用於創建單個空項、一個帶數據的項、一個帶圖標和數據的項、多個空項,對於空項還需要使用setText(QVariant value, int role = Qt.UserRole + 1)等方法設置項存儲的數據。

  3. 使用視圖的setModel(model)方法將model和view建立連接

4.3、 一個完整的初始化方法代碼及運行截圖

    def initStandItemModel(self):
        self.model = QStandardItemModel()
        strList = ["item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9", "item10"]
        row = 0
        for itemStr in strList:
            item = StandardItem(itemStr)
            self.model.setItem(row, 0, item)
            row += 1
        self.listView.setModel(self.model)

運行截圖:
在這裏插入圖片描述

五、QListView與多列Model及使用QListView的modelColumn屬性

5.1、概述

QListView的modelColumn屬性用於控制視圖中展現model中哪一列數據,缺省值爲0,即展現第一列數據。

可以通過modelColumn()、setModelColumn(int column)來訪問和設置該屬性。但Qt Designer中該屬性值只能爲0,無法設置爲非0,這是因爲QListView只顯示一列數據,一般情況下如果使用的Model沒有多列數據的話,是無需設置modelColumn屬性,但並不是不能使用多列數據的Model。如上面第三部分使用QFileSystemModel與QListView配合使用。

5.2、使用多列模式初始化

下面是一個使用QStandardItemModel創建的一個6行5列的Model與QListView配合使用的初始化代碼:

    def initMultiColumnModel(self):
        self.model = QStandardItemModel()
        for row in range(6):
            for col in range(5):
                item = StandardItem("row: {row},col: {col}".format(row=row + 1, col=col + 1))
        self.listView.setModel(self.model)

如使用QFileSystemModel來測試,發現可以通過setModelColumn來調整顯示的數據內容,然後又改成了QStandardItemModel,使用model的setItem方法來設置多列數據,也可以使用setModelColumn來調整顯示數據。

5.3、多列模式動態調整顯示數據列

多列模式的Model初始化後顯示的是第一列數據,如果要調整顯示其他列的數據,可以通過setModelColumn來調整顯示列。

六、支持列表中展示圖標的兩種方法

在視圖中的項不但可以展示文字,也可以展示圖標和複選框,同時可以指定項是否可以拖拽、選擇、編輯。有兩種方法支持在項中展示圖標。

6.1、使用QStandardItem(QIcon icon, str text)創建項

下面的代碼支持將指定目錄的圖象文件的文件名和圖象在視圖中展示:

    def initIconModel(self):
        self.model = QStandardItemModel()

        ICon1 = QStandardItem(QIcon(r"F:\學習\python\資源\圖像文件\add.png"),'add.png')
        ICon2 = QStandardItem(QIcon(r"F:\學習\python\資源\圖像文件\application_windows_add.png"), 'application_windows_add.png')
        ICon3 = QStandardItem(QIcon(r"F:\學習\python\資源\圖像文件\save.png"), 'save.png')
        ICon4 = QStandardItem(QIcon(r"F:\學習\python\資源\圖像文件\search.png"), 'search.png')
        ICon5 = QStandardItem(QIcon(r"F:\學習\python\資源\圖像文件\stop.gif"), 'stop.gif')

        self.model.appendRow(ICon1)
        self.model.appendRow(ICon2)
        self.model.appendRow(ICon3)
        self.model.appendRow(ICon4)
        self.model.appendRow(ICon5)
        self.listView.setModel(self.model)

運行後的界面初始化截圖如下:
在這裏插入圖片描述

6.2、使用QStandardItem()創建空項後通過setData指定圖標文件爲Qt.DecorationRole角色的數據

使用項的setData( QtCore.QVariant(icon), Qt.DecorationRole)方法,對應數據角色使用 Qt.DecorationRole。示例代碼:

    def initIconModel(self):
        self.model = QStandardItemModel()
        ICon1 = QStandardItem('add.png')
        ICon1.setData(QtCore.QVariant(QIcon(r"F:\學習\python\資源\圖像文件\add.png")),Qt.DecorationRole)
        ICon2 = QStandardItem('save.png')
        ICon2.setData(QtCore.QVariant(QIcon(r"F:\學習\python\資源\圖像文件\save.png") ),Qt.DecorationRole)
        self.model.appendRow(ICon1)
        self.model.appendRow(ICon2)
        self.listView.setModel(self.model)

運行截圖:
在這裏插入圖片描述
其實還有個類似的方法,就是使用model的setData( QModelIndex,QtCore.QVariant(icon), Qt.DecorationRole)方法,當選擇操作時要更改圖標文件可以使用這種方法。只要在方法中獲取到modelIndex就可以調用該方法。

七、支持獲取變更數據的方法

在QListView視圖中數據如果發生變化,可以通過QStandardItemModel的信號itemChanged連接一個自定義槽函數來獲取變動的數據。
1、定義一個槽函數itemChanged

 def itemChanged(self,item):
        print(f"itemChanged,row={item.row()},column={item.column()}")

2、在構造方法中建立信號和槽的連接

self.model.itemChanged[QStandardItem ].connect(self.itemChanged)

這樣只要觸發了項的編輯就會發出該信號從而知道變動的數據項。

八、小結

本節通過案例詳細介紹了QListView/Model編程的幾個要點,包括QListView與不同model的配合步驟、多列Model中數據展示列的控制、給展示數據加上圖標、獲取變更數據項的方法等內容。

後記

另外老猿關於PyQt的付費專欄《使用PyQt開發圖形界面Python應用》只需要9.9元,該部分與第十五章的內容基本對應,但同樣內容在付費專欄上總體來說更詳細、案例更多。本節內容在付費專欄的《第十八章、QListView/Model開發》。如果有興趣也願意支持老猿的讀者,歡迎購買付費專欄。

最後感謝各位支持,你們的支持是我持續學習和更新的動力!

老猿Python,跟老猿學Python!

發佈了623 篇原創文章 · 獲贊 3419 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章