PySide——Python圖形化界面入門教程(五)
——QListWidget
翻譯自:http://pythoncentral.io/pyside-pyqt-tutorial-the-qlistwidget/
Qt具有簡潔和方便的幾個部件,用來作單列表選擇,我們稱之為列表框。最靈活的方法是使用一個是Qlistview,它提供了一個必須由程序員定義UI視圖、高度靈活的列表模式;一個簡單的方法是使用QListWidget,它具有一個預先定義的基於項目的模型,用來處理常見的列表框。我們本節從簡單的QListWidget開始。
QListWidget
QListWidget的構造器同許多QWidget的子類一樣,擁有一個可選的parent參數:
self.list = QListWidget(self)
填充QListWidget
為QListWidget添加項目非常容易。如果項目是純文本,你可以單獨的添加他們:
1 for i in range(10): 2 self.list.addItem('Item %s' % (i + 1))
或者一起添加他們:
1 items = ['Item %s' % (i + 1) 2 for i in range(10)] 3 self.list.addItems(items)
你還可以使用QListWidgetItem類更復雜的列表項目。QListWidgetItem可以被單獨的創建,然后再使用列表的addItem方法添加。
item = QListWidgetItem()
list.addItem(item)
更復雜的QListWidget項目
或者,它還可以直接使用list參數來創建,這樣他會自動的被添加到list。
item = QListWidgetItem(list)
項目可以使用setText方法來添加文本,使用setIcon方法添加圖標QIcon:
item.setText('I am an item')
item.setIcon(some_QIcon)
同樣也可以在構造器中寫明文本或圖標:
item = QListWidgetItem('A Text-Only Item') item = QListWidgetItem(some_QIcon, 'An item with text and an icon')
當然, 上面的每個構造器也可選的接受parent參數。
使用QListWidget
QListWidget提供一些方便的信號來響應用戶輸入。最重要的是currentItemChanged信號,它是當用戶改變選擇的項目時發出;它連接的槽接收兩個參數,current和previous,表示現在和之前選擇的QListWidgetItem項。同樣它也有對應的信號,當用戶單擊、雙擊、激活或按下一個項、改變選擇的項目集時。
為獲得當前選擇的項,你也可以使用currentItemChanged信號傳來的參數,或使用QListWidget的currentItem方法。
對QIcon的注解
你可以通過添加一個圖標來改變QListWidgetItem,所以有必要了解一下QIcon了。這有許多構造QIcon的方法,如:
- 提供文件名:
icon = QIcon('/some/path/to/icon.png')
. - 使用主題圖標:
icon = QIcon.fromTheme('document-open')
. - 通過
QPixMap
:icon = QIcon(some_pixmap)
還有許多其他的。注意:基於文件的創建方法支持許多類型,但並不是所有類型,你可以通過使用QImageReader().supportedImageFormats()
來查看你的平台和版本支持哪些。在作者的系統上,它返回了:

1 [PySide.QtCore.QByteArray('bmp'), 2 PySide.QtCore.QByteArray('gif'), 3 PySide.QtCore.QByteArray('ico'), 4 PySide.QtCore.QByteArray('jpeg'), 5 PySide.QtCore.QByteArray('jpg'), 6 PySide.QtCore.QByteArray('mng'), 7 PySide.QtCore.QByteArray('pbm'), 8 PySide.QtCore.QByteArray('pgm'), 9 PySide.QtCore.QByteArray('png'), 10 PySide.QtCore.QByteArray('ppm'), 11 PySide.QtCore.QByteArray('svg'), 12 PySide.QtCore.QByteArray('svgz'), 13 PySide.QtCore.QByteArray('tga'), 14 PySide.QtCore.QByteArray('tif'), 15 PySide.QtCore.QByteArray('tiff'), 16 PySide.QtCore.QByteArray('xbm'),
基於主題的創建方法有時候會出問題,當在Windows和OS X還有使用Gnome或KDE的Linux應該沒問題,但是如果使用不太常見的桌面環境,像OpenBox或XFCE,Qt或許不能找到你的圖標,所以會只有文本。
一個QListWidget例子
我們來創建一個簡單的列表widget來顯示文件夾中的文件名和為圖片顯示一個極小的圖標。因為這里的項非常簡單,足以用QListWidgetItem來創建,我們將從QListWidget繼承。
第一步,我們需要知道安裝的版本都支持什么類型的圖片,這樣我們的列表控件才能辨別什么是合法的圖片。我們可以使用上面提到的方法,QImageReader().supportedImageFormats()。我們將他們返回前全部轉化成字符串:
1 def supported_image_extensions(): 2 ''' Get the image file extensions that can be read. ''' 3 formats = QImageReader().supportedImageFormats() 4 # Convert the QByteArrays to strings 5 return [str(fmt) for fmt in formats]
現在我們可以創建我們的圖片列表widget了,起一個望名知義的名字——ImageFileWidget。它將繼承自QListWidget,還像所有的QWidget一樣有一個可選的parent參數,此外,它要求一個dirpath參數:
1 class ImageFileList(QListWidget): 2 ''' A specialized QListWidget that displays the list 3 of all image files in a given directory. ''' 4 def __init__(self, dirpath, parent=None): 5 QListWidget.__init__(self, parent)
我們需要知道給出的文件夾中都有哪些圖片。這里給出一個_images方法,這個方法會返回指定目錄中所有合法圖片的文件名。它利用了glob模塊的glob函數,它允許對文件和路徑進行shell風格的模式匹配。

1 def _images(self): 2 ''' Return a list of file-names of all 3 supported images in self._dirpath. ''' 4 5 # Start with an empty list 6 images = [] 7 8 # Find the matching files for each valid 9 # extension and add them to the images list. 10 for extension in supported_image_extensions(): 11 pattern = os.path.join(self._dirpath, 12 '*.%s' % extension) 13 images.extend(glob(pattern)) 14 15 return images
現在我們獲得了文件夾中的圖片文件,再將他們添加到QListWidget就簡單了。每一個文件名,我們創建一個以列表為其parent的QListWidgetItem,並將其文件名設置成本文,用圖片創建的QIcon設置其圖標。

1 def _populate(self): 2 ''' Fill the list with images from the 3 current directory in self._dirpath. ''' 4 5 # In case we're repopulating, clear the list 6 self.clear() 7 8 # Create a list item for each image file, 9 # setting the text and icon appropriately 10 for image in self._images(): 11 item = QListWidgetItem(self) 12 item.setText(image) 13 item.setIcon(QIcon(image))
最后,我們添加一個方法來設置目錄,它每次調用都會重新填充列表。
1 def setDirpath(self, dirpath): 2 ''' Set the current image directory and refresh the list. ''' 3 self._dirpath = dirpath 4 self._populate()
ImageFileList類的代碼如下:

1 class ImageFileList(QListWidget): 2 ''' A specialized QListWidget that displays the 3 list of all image files in a given directory. ''' 4 5 def __init__(self, dirpath, parent=None): 6 QListWidget.__init__(self, parent) 7 self.setDirpath(dirpath) 8 9 10 def setDirpath(self, dirpath): 11 ''' Set the current image directory and refresh the list. ''' 12 self._dirpath = dirpath 13 self._populate() 14 15 16 def _images(self): 17 ''' Return a list of filenames of all 18 supported images in self._dirpath. ''' 19 20 # Start with an empty list 21 images = [] 22 23 # Find the matching files for each valid 24 # extension and add them to the images list 25 for extension in supported_image_extensions(): 26 pattern = os.path.join(self._dirpath, 27 '*.%s' % extension) 28 images.extend(glob(pattern)) 29 30 return images 31 32 33 def _populate(self): 34 ''' Fill the list with images from the 35 current directory in self._dirpath. ''' 36 37 # In case we're repopulating, clear the list 38 self.clear() 39 40 # Create a list item for each image file, 41 # setting the text and icon appropriately 42 for image in self._images(): 43 item = QListWidgetItem(self) 44 item.setText(image) 45 item.setIcon(QIcon(image))
現在把我們的ImageFileList放到一個簡單窗口里來看看它是否工作。我們將創建一個QWidget來作為窗口,使用QVBoxLayout布局,添加ImageFileList,並且包含一個可以顯示當前選定項的記錄widget。我們將使用ImageFileList的currentItemChanged信號來保持他們同步。
我們將創建一個QApplication對象,使用sys.argv[1],以列表形式傳遞圖片文件路徑給它。
app = QApplication([])
然后,創建我們的窗口,設置尺寸並添加布局:
1 win = QWidget() 2 win.setWindowTitle('Image List') 3 win.setMinimumSize(600, 400) 4 layout = QVBoxLayout() 5 win.setLayout(layout)
接下來,傳遞給ImageFileList圖片文件夾路徑和我們的窗口。
first = ImageFileList(sys.argv[1], win)
添加記錄widget
entry = QLineEdit(win)
將widget添加到布局中去:
layout.addWidget(first)
layout.addWidget(entry)
接下來,我們需要創建一個在當前項被改變時會調用的槽函數。它有兩個參數,curr和prev,分別表示當前選定的項和上一個選定的項。它還需要設置記錄當前選定的項:
def on_item_changed(curr, prev): entry.setText(curr.text())
別忘了和信號連接起來:
lst.currentItemChanged.connect(on_item_changed)
剩下的就是顯示窗口和運行app了,最后代碼如下:

1 if __name__ == '__main__': 2 # The app doesn't receive sys.argv, because we're using 3 # sys.argv[1] to receive the image directory 4 app = QApplication([]) 5 6 # Create a window, set its size, and give it a layout 7 win = QWidget() 8 win.setWindowTitle('Image List') 9 win.setMinimumSize(600, 400) 10 layout = QVBoxLayout() 11 win.setLayout(layout) 12 13 # Create one of our ImageFileList objects using the image 14 # directory passed in from the command line 15 lst = ImageFileList(sys.argv[1], win) 16 17 layout.addWidget(lst) 18 19 entry = QLineEdit(win) 20 21 layout.addWidget(entry) 22 23 def on_item_changed(curr, prev): 24 entry.setText(curr.text()) 25 26 lst.currentItemChanged.connect(on_item_changed) 27 28 win.show() 29 app.exec_()
運行這個例子需要你有一個具有圖片的文件夾;原文作者使用了/usr/share/icons
作為例子,你需要選擇自己的文件夾。
python imagelist.py /usr/share/icons/nuoveXT2/48x48/devices
應有些朋友的要求,給出一個運行的截圖。另外需要注意自行import一些庫才可以運行。
顯然,QListWidget是非常簡單的widget,不需要提供更多的選項;這就會有許多它不能適應的應用場景。對於難以適應的場景,你或許需要使用QListView,我們在下節討論它。
By Ascii0x03
轉載請注明出處:http://www.cnblogs.com/ascii0x03/p/5502286.html