PySide——Python圖形化界面入門教程(六)
——QListView和QStandardItemModel
翻譯自:http://pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/
上一個教程中,我們討論了Qt的QListWidget類,它用來實現簡單的單列列表框(list boxes)。然而,我們還需要更加靈活的widget來實現列表,Qt為此提供了QListView
來實現多種多樣的項。它是一個純粹的顯示部件,用來顯示數據模型提供的信息。這樣做將將顯示功能和數據邏輯分離開來;這同時還有一些其他widget可以顯示來自同一模型結構的數據。
這里已經有一些創建好的幾種類型的模型。比如,QStandardItemModel提供了比上一節QListWidget更棒的能力;拿文本和圖標來說,它提供了拖拽的能力、checkable items和其他一些特性。自定義行為可以通過QAbstractlistModel繼承實現——列表數據的通用模型。
PySide的QStandardItemModel
我們首先從討論QListView來開始。QListView可以像其他的QWidget一樣進行實例化——你是不是對每次講一個widget都說這句話感到厭煩了?雖然有些啰嗦,但是讓我們清晰的記得對象模型;PyQt/Pyside最優秀的地方就是它的簡單、好記和繼承性。這就是說,QListView構造器接收一個可選的參數parent:
list = QListView(parent)
現在我們的列表需要一個模型來管理它的數據。以我們的列表作為parent參數創建一個QStandardItemModel:
model = QStandardItemModel(list)
QStandardItemModel還有其他一些構造器,但是和我們的單列列表無關,我們有時間再來討論。
PySide的QStandardItem
創建列表和模型是最簡單的部分;列表的主要任務創建並嵌入模型。例如,我們先創建一個項:
item = QStandardItem()
方便地設置它的文本和圖標:
item.setText('Item text') item.setIcon(some_QIcon)
我們也可以讓項目變成多選的,這將在項目的最左邊添加一個復選框(checkbox)
item.setCheckable(True)
你還可以讓復選框有三種狀態——checked,unchecked,和null,使用
一個簡單的QStandardItem例子
我們現在已經了解了QListView足夠的背景,盡管它還什么都不能做。我們讓QListView成為主窗口來盡可能的簡化,就像其它任何QWidget作為主窗口的例子一樣進行最基本的設置:
1 list = QListView() 2 list.setWindowTitle('Example List') 3 list.setMinimumSize(600, 400)
接下來創建我們的模型:
model = QStandardItemModel(list)
然后我們創建一些QStandardItem來填充我們的模型。就列出我們想要的吃的事物吧,每一個都有一個文本標題和復選框。

1 foods = [ 2 'Cookie dough', # Must be store-bought 3 'Hummus', # Must be homemade 4 'Spaghetti', # Must be saucy 5 'Dal makhani', # Must be spicy 6 'Chocolate whipped cream' # Must be plentiful 7 ] 8 9 for food in foods: 10 # Create an item with a caption 11 item = QStandardItem(food) 12 13 # Add a checkbox to it 14 item.setCheckable(True) 15 16 # Add the item to the model 17 model.appendRow(item)
最后,將模型應用至QListView,顯示窗口運行app。
1 list.setModel(model) 2 list.show() 3 app.exec_()
完整的例子代碼如下:

1 # Create a Qt application 2 app = QApplication(sys.argv) 3 4 # Our main window will be a QListView 5 list = QListView() 6 list.setWindowTitle('Example List') 7 list.setMinimumSize(600, 400) 8 9 # Create an empty model for the list's data 10 model = QStandardItemModel(list) 11 12 # Add some textual items 13 foods = [ 14 'Cookie dough', # Must be store-bought 15 'Hummus', # Must be homemade 16 'Spaghetti', # Must be saucy 17 'Dal makhani', # Must be spicy 18 'Chocolate whipped cream' # Must be plentiful 19 ] 20 21 for food in foods: 22 # create an item with a caption 23 item = QStandardItem(food) 24 25 # add a checkbox to it 26 item.setCheckable(True) 27 28 # Add the item to the model 29 model.appendRow(item) 30 31 # Apply the model to the list view 32 list.setModel(model) 33 34 # Show the window and run the app 35 list.show() 36 app.exec_()
運行的時候看上去像是這樣:
添加簡單的功能
讓我們看看如何讓帶有QStandardItemModel的QListView來與用戶交互。你或許想象每個QStandardItem都像一個QPushButton,當被選擇、編輯、等等的時候都會發出信號。如果你這樣想,就像我一樣,那就錯了!在QStandardItemModel中,有一個更加強大的信號——itemChanged(item)來說明發生了什么。就像你看到的那樣,它把發生變化的項發送給槽,你需要檢查項來知道發生了什么。雖然不完美,但它確是這樣的。
你還可以使用模型的item方法來檢查沒有改變過的項,它返回指定行(從0開始)的項。(同樣可接受單列、多列模型)
這還有許多信號來表現模型結構的改變;它們都是從QAbstractItemModel繼承而來,我們會在討論QAbstractItemModel主題時再來學習它們。現在的例子我們還不需要。
現在我們來讓清單更甜蜜(honey-do,作者還是很幽默的,但是我翻譯不出來^_^)一些。你使用列表登記已經購買了的項,當你完成時,窗口會關閉。首先,改變標題:
list.setWindowTitle('Honey-Do List')
然后,我們需要一個槽來連接模型的itemChanged信號。當然, 我們首先需要使用checkState方法檢查發生變化的項是否被選中,來避免每次遍歷項。如果已經選中了,我們再檢查是否其他的都被選中;如果都被選中了(即你已經都購買了),則退出QApplication。

1 def on_item_changed(item): 2 # If the changed item is not checked, don't bother checking others 3 if not item.checkState(): 4 return 5 6 i = 0 7 8 # loop through the items until you get None, which 9 # means you've passed the end of the list 10 while model.item(i): 11 if not model.item(i).checkState(): 12 return 13 i += 1 14 15 app.quit()
然后,我們將信號和槽連接起來:
model.itemChanged.connect(on_item_changed)
完整的代碼如下所示:

1 # Create a Qt application 2 app = QApplication(sys.argv) 3 4 # Our main window will be a QListView 5 list = QListView() 6 list.setWindowTitle('Honey-Do List') 7 list.setMinimumSize(600, 400) 8 9 # Create an empty model for the list's data 10 model = QStandardItemModel(list) 11 12 # Add some textual items 13 foods = [ 14 'Cookie dough', # Must be store-bought 15 'Hummus', # Must be homemade 16 'Spaghetti', # Must be saucy 17 'Dal makhani', # Must be spicy 18 'Chocolate whipped cream' # Must be plentiful 19 ] 20 21 for food in foods: 22 # Create an item with a caption 23 item = QStandardItem(food) 24 25 # Add a checkbox to it 26 item.setCheckable(True) 27 28 # Add the item to the model 29 model.appendRow(item) 30 31 def on_item_changed(item): 32 # If the changed item is not checked, don't bother checking others 33 if not item.checkState(): 34 return 35 36 # Loop through the items until you get None, which 37 # means you've passed the end of the list 38 i = 0 39 while model.item(i): 40 if not model.item(i).checkState(): 41 return 42 i += 1 43 44 app.quit() 45 46 model.itemChanged.connect(on_item_changed) 47 48 # Apply the model to the list view 49 list.setModel(model) 50 51 # Show the window and run the app 52 list.show() 53 app.exec_()
這是一個QListView的簡單例子。它還可以做更多的事情,但是相同的模型同樣也可以用於其他的widget。下一次,我們將看一些完全不同的東西,一個最讓原作者興奮的部件,QWebView,一個基於WebKit的可以解析HTML/CSS/XML/XSLT頁面的控件。(話雖如此,但是下個教程不在Qt wiki的入門教程之列,所以我就先不進行翻譯了,需要的讀者可以查看原作者的原文http://pythoncentral.io/pyside-pyqt-tutorial-qwebview/)
一些感想:
對於初學者,更多的資料應該還是要參考https://wiki.qt.io/PySide_Tutorials,這一至六的教程就是翻譯的PythonCentral的3至8部分,僅僅起到拋磚引玉的作用。在學習之前,我首先還是喜歡搜索中文的資料,因為畢竟母語接受的快一些。可是搜索中卻發現優秀的中文教程太少了,而英文教程我感覺要清晰的多,能讓我從0基礎開始更好的理解PySide,而不是不知其所以然的簡單操作步驟。正是這個原因,我邊看邊進行了翻譯,希望能幫到更多新手入門。同時也希望出現更多優秀的中文教程,並有更多的人來翻譯優秀的英文官方教程。最后,由於譯者水平十分有限,不周之處還請諒解。
補充:
發現一個優秀的詳細中文系列教程(不過好些是C++),敬佩豆子作者的精神:http://www.devbean.net/2012/08/qt-study-road-2-catelog/
Pyside的官方手冊:http://pyside.github.io/docs/pyside/
By Ascii0x03
轉載請注明出處:http://www.cnblogs.com/ascii0x03/p/5505439.html