[PyQt]PySide2 教程 #8: 列表、表格、树,ListWidget, TableWidget, TreeWidget

#PYTHON3 #QT #PYSISE2 #TUTORIAL #WIDGET #ITEM

有什麼顯示方式比樹狀、清單、表格更清晰呢?

Photo by Adi Goldstein on Unsplash

Python是個非常適合處理文字以及資料的語言,再資料的呈獻方式中最一目了然且簡單的不外乎就是表格、清單以及樹狀圖了。Qt中,我們可以使用ListWidget, TableWidget, TreeWidget來呈現我們的data。

OverView

Item Widget是以Item為主體,每一種Widget都有自己的WidgetItem、以及相同的且類似的函式。

例如:

  • QListWidget中的item類型都是QListWidgetItem
  • 新增物件則是使用 addItem()
  • Item 通常會有data, text, Icon 等屬性

ListWidget

ListWidget可以除了可以條列式的顯示文字以外,也可以在項目中加入圖片,我們也可以對QListWidgetItem做個人化的處理,修改內部參數甚至是StyleSheet來修改外觀。

ListWidgetItem

這邊我們新增一個CreateItem的方法來建立獨立的Item,並設定文字、圖片、對齊等屬性。

from PySide2.QtWidgets import QListWidgetItem, QListView
def create_item(self, name, icon, parent):
    """Create a standard list widget item, for option panel.
    Args:
    name: Name of option button
    icon: Icon name of option button
    parent: The QListWidget
    Returns:
    item: created option button
    """
    item = QListWidgetItem(parent)
    item.setText(name)
    item.setIcon(QIcon(icon))
    item.setStatusTip(name)
    item.setTextAlignment(Qt.AlignLeft)
    item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
    return item

接下來,設定ListWidget本體的屬性並且用List的方式將物件都加入ListWidget中。

# Setup ListWidget
self._list_items.append(self.create_item('Play', './media/play.png'
, self._window.tool_list))
self._list_items.append(self.create_item('Pause','./media/pause.png', self._window.tool_list))
self._list_items.append(self.create_item('Stop', './media/stop.ico'
, self._window.tool_list))
self._window.tool_list.setCurrentRow(0)
self._window.tool_list.setViewMode(QListView.ListMode)
self._window.tool_list.setSpacing(1)
self._window.tool_list.setItemAlignment(QtCore.Qt.AlignCenter)
self._window.tool_list.setEnabled(True)

此外我們也可以用 IconMode的方式來做顯示

self._window.tool_list.setViewMode(QListView.IconMode)

Result

QListWidget Example

TableWidget

TableWidget非常適合用在顯示表格式的檔案,包括csv, DB, Excel等資料。讓我們用TableWidget來顯示一個類csv的data吧!

Data

我們的data如下:

data_list = list()
data = 'Name Job Level Attack Defense DPS\n' \
       'Arey Newbie 5 30 10 0.3\n' \
       'Alice Witch 30 150 32 1.0\n' \
       'Moly Knight 42 200 70 1.7\n' \
       'Cathy Ranger 35 170 41 2.0\n' \
for row in data.split('\n'):
col = row.split(' ')
data_list.append(col)

About Table

表格物件有幾個屬性需要了解,第一個就是表頭,其分為rowHeader以及columnHeader。表個中的每個格子皆為一個QtableWidgetItem,其最主要的屬性就是定位用的row, col還有外觀以及顯示的屬性,包括文字、顏色、圖示等等。

TableWidgetItem

同樣的我們建立一個,Cell的creator

from PySide2.QtWidgets import QTableWidgetItem, QHeaderView
def create_cell(self, data: str):
    """Create data cell on UI."""
    cell = QTableWidgetItem(data)
    cell.setFont(QFont('Free Mono', 11))
    cell.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
    return cell

TableWidget

接下來設定Table的本體屬性。
有一些比較複雜的設定,像section的縮放模式我使用 QHeaderView.Strech,另外,也將捲動條給隱藏( horizontalScrollBar().setVisible(False)

注意:不要忘記設定 setRowCountsetColumnCount不然表格會顯示不出來唷!

table = self._window.data_table
table.verticalHeader().setDefaultSectionSize(18)
table.verticalHeader().setDefaultAlignment(Qt.AlignCenter)
table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
table.verticalScrollBar().setVisible(False)
table.horizontalScrollBar().setVisible(False)header_data = data_list.pop(0)
table.setColumnCount(len(header_data))
table.setRowCount(len(data_list))# 設定Header內容
for idx, data in enumerate(header_data):
    header = self.create_cell(data)
    table.setHorizontalHeaderItem(idx, header)# 建立Cell 並加入table之中
for row_num, row in enumerate(data_list):
    for col_num, col_data in enumerate(row):
        item = self.create_cell(col_data)
        item.setToolTip('row{},Col{}'.format(row_num, col_num))
        table.setItem(row_num, col_num, item)

Result

TableWidget Example

TreeWidget

TreeWidget可以說是list與table的結合與延伸,除了有Header欄位,同時也是條列式的顯示。而最核心的當然就是多層次的顯示及縮小展開功能。

Root & Child

TreeWidget的分支有分為root以及child兩個階層,而child底下還可以有child,但root只會再最上層並且宣告時要指定parent的TreeWidget為何。

from PySide2.QtGui import QFont, QColor
from PySide2.QtWidgets import QTreeWidgetItemdef create_root(self, parent, name, value):
    """Create root item of the tree"""
    root = QTreeWidgetItem(parent)
    root.setText(0, name)
    root.setText(1, value)
    root.setTextColor(0, QColor('#ffffff'))
    root.setTextColor(1, QColor('#ffffff'))
    root.setBackgroundColor(0, QColor('#0066cc'))
    root.setBackgroundColor(1, QColor('#0066cc'))
    return root

def create_child(self, name, value):
    """Create child item of the tree"""
    root = QTreeWidgetItem()
    root.setText(0, name)
    root.setText(1, value)
    root.setTextColor(0, QColor('#0066cc'))
    root.setTextColor(1, QColor('#0066cc'))
    root.setBackgroundColor(0, QColor('#ccffff'))
    root.setBackgroundColor(1, QColor('#ccffff'))
    return root

TreeWidget

TreeWidget也有header可以設定,其可以是QLabel也可以是QTreeWidgetItem的類別。

  • 這邊我們利用文章最上面的勇者資料來當作我們的素材
# Setup TreeWidget
tree = self._window.hero_tree
tree.setIndentation(5)
tree.setColumnCount(2)
tree.setFont(QFont('Free Mono', 11))
header = QTreeWidgetItem(['Name', 'Value'])
tree.setHeaderItem(header)

for hero in data_list:
    hero_root = self.create_root(tree, header_data[0], hero[0])
for idx in range(1, len(hero)):
    hero_attr = self.create_child(header_data[idx], hero[idx])
    hero_root.addChild(hero_attr)

Result

TreeWidget Example

Source Code

完整代碼請看 : Item Widget

結論

ItemWidget對於資料顯示非常實用,同時還有其他互動式介面會用到的設計方法,這部份我們後面的教學會提到唷,請大家期待一下吧!另外,肯定友人提到非常類似的Model模式的viewWidget物件,主要以顯示為主,優點在於可以導入model的物件,例如:用QDirFileSystemModel來製作file browser等等。

下一篇 : PySide #9: 容器物件! DockWidget, ToolBox, StackWidget