第15.28節 PyQt(Python+Qt)入門學習:Model/View架構中的便利類QTableWidget詳解

一、引言

表格部件爲應用程序提供標準的表格顯示工具,在表格內可以管理基於行和列的數據項,表格中的最大數據項數爲總行數和總列數的乘積,另外在表格中可以設置水平和垂直標題。

表格部件對應類爲QTableWidget ,QTableWidget 表格部件中的項類型爲QTableWidgetItem類。QTableWidget 從QTableView派生的子類,內置默認模型,如果表格展現的應用需要使用自己的數據模型,則應使用QTableView類,而不是QTableWidget 類。

二、QTableWidget的屬性

2.1、概述

除了從父類繼承的屬性外,在Designer中QTableWidget只有兩個屬性,就是行數rowCount和列數columnCount,另外還有一部分就是用於設置表頭的屬性。如圖:
在這裏插入圖片描述

2.2、行數rowCount

QTableWidget的rowCount屬性保存表格部件中的行數,在QTableWidget創建時如果沒有指定行數,則缺省行數爲0,QTableWidget創建後可以通過 setRowCount方法調整行數。

要獲取當前表格部件中的行數,可以通過rowCount()方法獲取,要設置表格部件的行數,可以通過setRowCount(int rows)調整表格的行數,如果參數rows小於現在表格中的實際行數,則表格中超出參數的行數數據會丟棄,就算是後面將行數或列數恢復也不能恢複相關數據。

2.3、列數columnCount

columnCount屬性保存表格部件中的列數,相關屬性和操作方法和rowCount類似。在QTableWidget創建時如果沒有指定列數,則缺省列數爲0,QTableWidget創建後可以通過 setColumnCount方法調整。

columnCount可以通過columnCount()方法獲取,通過setColumnCount(int columns)設置。

2.4、表頭及屬性

QTableWidget的表頭包括橫表頭和豎表頭,如下:
在這裏插入圖片描述
上面的“列1”、“列2”、“列3”爲橫表頭,“行1”、“行2”、“行3”爲豎表頭。橫表頭可通過方法setHorizontalHeaderLabels來設置,豎表頭可以通過setVerticalHeaderLabels來設置。這是創建表頭的最簡單方法,它們將爲表的列和行提供簡單的文本標題。

下面代碼爲上圖設置表頭的示例代碼:

        self.tableWidget.setVerticalHeaderLabels(['行1','行2','行3'])
        self.tableWidget.setHorizontalHeaderLabels(['列1','列2','列3'])

除了上述簡單方法外,還可以從表格部件的項創建更復雜的表頭,相關方法在下面介紹QTableWidget的方法時再介紹。

除了設置表頭文字外,表頭還有相關屬性設置,QTableWidget的表頭屬性是直接繼承自QTableView的表頭屬性,相關屬性的介紹請參考《PyQt(Python+Qt)學習隨筆:QTableView的標題表頭相關屬性》。

三、QTableWidget的項QTableWidgetItem

3.1、概述

QTableWidgetItem類爲QTableWidget類的項實例類,用於保存表格部件的信息。項的內容可包含文本、圖標或複選框等。

默認情況下,QTableWidgetItem項是可用、可編輯、可選擇和可選中的,並且可以用作拖放操作的源和拖放目標。如果要改變相關設置,可以通過使用setFlags()來更改每個項的標誌(關於項的標記請參考《PyQt(Python+Qt)學習隨筆:Model中項的標記flags取值及枚舉類型Qt.ItemFlag》)。

QTableWidgetItem的方法分爲構造方法、位置相關方法、數據及展現內容相關、操作相關四類。

3.2、構造方法

QTableWidgetItem的構造方法有4個:

  1. QTableWidgetItem(int type = Type):構建一個空項
  2. QTableWidgetItem( str text,int type = Type):構建一個帶文本的項
  3. QTableWidgetItem( QIcon icon, str text, int type = Type) :構建一個帶圖標和文本的項
  4. QTableWidgetItem( QTableWidgetItem other):從other複製項的內容構建一個新項

3.3、位置相關方法

QTableWidgetItem項在QTableWidget中的位置包括三個屬性來決定,就是表格部件對象、行和列,由於這三個屬性決定了項在界面的哪個組件的哪個地方,因此老猿將相關方法歸類爲位置相關方法。QTableWidgetItem項方法中:

  • QTableWidget tableWidget():返回項所在的表格部件實例,如果項沒有插入到樹型部件中,則返回None
  • int row() :返回項所在表格的行,注意是從0開始計數
  • int column():返回項所在表格的列,注意是從0開始計數

3.4、數據和展現相關方法

在部件中的數據有多種屬性,包括文本數據、圖標、複選狀態、工具欄提示toolTip、whatsThis幫助、狀態提示statusTip等,在Qt中將這些稱爲同一個項的不同角色數據(關於數據的角色請參考《PyQt學習隨筆:Model/View中諸如DisplayRole的數據角色及含義》)。這些數據爲呈現數據的不同狀態情況,因此老猿將與此相關的方法歸類爲數據和展現相關方法。不同角色的數據在Qt中可以通過data和setData方法帶角色參數統一訪問,也可以通過各自不同的方法不帶角色去訪問。

3.4.1、項數據的data和setData訪問方法

部件中的項數據可以通過項的data( int role) 方法獲取項中指定列指定角色的數據,也可以通過setData(int role, QVariant value)方法設置指定角色的數據爲value。例如項的文本可以通過data方法和setData方法使用Qt.DisplayRole、Qt.EditRole這兩種角色去訪問。

關於數據的角色請參考《PyQt學習隨筆:Model/View中諸如DisplayRole的數據角色及含義》。

注意:
  • role雖然是整數,但實際上是枚舉類型 Qt.ItemDataRole
  • QVariant 表示任何PyQt的數據類型,所以value的類型沒有約束
示例代碼:
   
 		item.setData(QtCore.Qt.DecorationRole,QtGui.QIcon('.\\icon\\'+str(row+1)+'.gif'))#設置圖標
        item.setData(QtCore.Qt.CheckStateRole, row%3) #設置複選狀態
        item.setData(QtCore.Qt.TextAlignmentRole,col % 3)  #設置文本對齊方式
        
3.4.2、項文本數據訪問的text和setText方法

項的文本可以通過data方法和setData方法使用Qt.DisplayRole、Qt.EditRole這兩種角色去訪問,除了這個方法外,還可以通過text() 和setText( str value)方法去訪問。

  • text():獲取項的文本數據
  • setText( str value):設置項的文本數據爲value,注意沒有返回值
3.4.3、項文本對齊方式訪問的textAlignment和setTextAlignment方法

項中的文本可以設置水平和垂直對齊方式,相關對齊方式的訪問方法調用方式如下:

  • int textAlignment() :返回對齊方式,返回類型是枚舉類型Qt.Alignment,實際上是整數
  • setTextAlignment(int alignment):設置對齊方式,無返回值
注:

對齊方式是一個Qt.Alignment枚舉類型的組合,具體取值及含義請參考《PyQt(Python+Qt)學習隨筆:QListView的itemAlignment屬性》。

3.4.4、項中圖標訪問的icon和setIcon方法

可以通過icon()來訪問項的圖標,通過setIcon( QIcon icon)來設置項的圖標。

如下面代碼將頂的圖標設置爲指定文件:

item.setIcon(QtGui.QIcon(r'F:\小圖標\動物\動物-025.gif'))
3.4.5、項複選狀態訪問方法

項可以單獨設置複選狀態,如圖所有項都設置了複選狀態,每行的複選狀態不同:
在這裏插入圖片描述
項的複選狀態可以通過checkState()來獲取,如果要改變項的複選狀態可以調用setCheckState(Qt.CheckState state)來實施。

注意:

3.4.6、項提示信息相關操作方法

提示信息包括工具欄提示、狀態欄提示和whatsThis提示:

  • 通過toolTip(int column)、setToolTip(int column, str toolTip)來操作toolTip
  • 通過statusTip(int column)、setStatusTip(int column, str statusTip)來操作statusTip
  • 通過whatsThis(int column)、setWhatsThis(int column, str whatsThis)來操作whatsThis

關於這三個提示信息的區別請參考《PyQt(Python+Qt)學習隨筆:Qt Designer中部件的toolTip、toolTipDuration、statusTip、whatsThis屬性》。

3.4.7、sizeHint相關方法

關於QTableWidgetItem項的sizeHint屬性,Qt中的文檔說明非常簡單,作用也沒有展開說明,僅介紹QTableWidgetItem中sizeHint爲項的缺省大小,如果沒有設置則根據項的數據自動計算項的大小。

爲此老猿做了大量測試和驗證,最終確認了QTableWidgetItem項的sizeHint的作用,QTableWidgetItem的sizeHint在項對應QHeadView表頭的sectionResizeMode值爲ResizeToContents時,作爲計算項大小的一個因素:

  1. 判斷項是否設置了sizeHint,如果沒有設置則按項的內容計算項大小,確保項的內容在對應表頭方向完整顯示;
  2. 如果項設置了sizeHint,則取sizeHint的值作爲項的大小。

具體請參考《PyQt學習隨筆:QTableWidget項sizeHint的作用以及與QHeadView的sectionResizeMode、ResizeToContents的關係》和《PyQt(Python+Qt)學習隨筆:QTableWidget表格部件中行高和列寬的計算方式》。

項的sizeHint相關訪問方法及調用語法如下:
  • QSize sizeHint()
  • setSizeHint( QSize size)

3.5、項操作相關方法

QTableWidget中項操作相關的屬性包括是否可用、是否可選中、是否可編輯、是否可複選、是否選中、是否複選等,這些屬性的設置與影響界面上項的操作,所以老猿將其歸類項操作相關方法。這些項操作相關方法所有Model/View相關類涉及項操作都是一樣的。由於複選狀態同時是項的展現狀態,在前面數據和展現相關方法中已經介紹相關方法。

3.5.1、項標記相關方法

項的標記用於標記項是否可操作,由多個屬性位組合而成,具體項標記的取值及含義請參考《PyQt(Python+Qt)學習隨筆:Model中項的標記flags取值及枚舉類型Qt.ItemFlag》。

項標記的訪問方法及調用語法如下:

  • Qt.ItemFlags flags()
  • setFlags(Qt.ItemFlags flags)

3.5.2、項是否選中相關方法

項是否被用戶選中可以通過isSelected方法獲取,如果要通過代碼設置項的選中狀態,則調用setSelected方法,相關調用語法如下:

  • bool isSelected()
  • setSelected(bool select)

四、QTableWidget的主要方法

除了從父類繼承的方法外,QTableWidget的方法老猿將其歸納爲構造方法、部件狀態訪問方法、項操作方法、項查找和定位方法、表頭操作方法五大類。

4.1、構造方法

QTableWidget有2個構造方法:

  • QTableWidget(QWidget parent = None) :創建一個0行0列的QTableWidget實例
  • QTableWidget(int rows, int columns, QWidget parent = None):創建一個rows行columns列的QTableWidget實例

這兩個構造方法的區別就是後者指定了部件的行數和列數,而前者行數和列數爲0,需要在實例構建後再另外去指定行數和列數。參數parent 一般傳部件所在窗口,不傳也沒關係。

注:

這裏的構造方法是沿用C++的說法,Python中的構造方法是__init__。

4.2、部件狀態訪問方法

老猿將部件中反映部件當前情況的一些方法歸類爲部件狀態訪問方法,包括部件的行數、列數、當前項、當前行、當前列等屬性訪問方法。由於部件行數和列數的訪問方法在部件屬性中已經介紹了,在此不重複介紹。

4.2.1、當前項訪問方法

當前項是指當前鼠標和鍵盤焦點所在項,在項可以進行選擇操作時,當前項可以是選中狀態,也可以是未選中狀態,選中項也不一定是當前項。與當前項相關的方法包括:

  • QTableWidgetItem currentItem() :返回當前項對應項對象,如果沒有當前項則返回None
  • setCurrentItem(QTableWidgetItem item):設置當前項
  • setCurrentItem(QTableWidgetItem item, QItemSelectionModel.SelectionFlags command):設置當前項
  • setCurrentCell(int row, int column):設置當前項
  • setCurrentCell(int row, int column, QItemSelectionModel.SelectionFlags command):設置當前項
注意:
  1. 後面4個方法都是設置當前項,方法名爲setCurrentItem的參數是QTableWidgetItem實例,方法名爲setCurrentCell的參數是行和列,即這兩類方法依據的項定位方法不同
  2. 參數中帶command參數的,要求除了將當前項改爲參數確認的項之外,還要求有額外的響應,具體響應由command參數確認。關於QItemSelectionModel.SelectionFlags 請參考《PyQt(Python+Qt)學習隨筆:Mode/View中的枚舉類QItemSelectionModel.SelectionFlag取值及含義》;
  3. 如果當前項沒有,則currentItem()方法返回None。

4.2.2、當前行和列訪問方法

當前項所在的行和列,既可以通過當前項的QTableWidgetItem實例對象的行號(row()方法)和列號(column()方法)獲取,也可以直接通過QTableWidget獲取。調用語法如下:

  • int currentColumn()
  • int currentRow()
    如果部件沒有當前項,則上述兩個方法返回-1。

4.3、部件中的項操作方法

部件中的項操作包括設置項、刪除項、編輯項等。

4.3.1、設置項setItem方法

setItem用於在表格部件QTableWidget創建後,設定指定行和指定列的項爲一個QTableWidgetItem實例對象。調用語法如下:
setItem(int row, int column, QTableWidgetItem item)

注意:
  • 該方法沒有返回值,但會觸發itemChanged信號
  • 在使用setItem之前,需要確保表格部件的行數和列數已經設置,且參數 row和column在行數和列數的範圍內,否則設置不會成功,這也意味着表格部件的行數和列數不能隨着項的增加自動增加,必須預定義好
示例代碼:
        for row in range(5):
            for col in range(3):
                item = QtWidgets.QTableWidgetItem(f"({row},{col})" )

                self.tableWidget.setItem(row,col,item)

4.3.2、觸發編輯項的editItem方法

QTableWidget提供了觸發項編輯的方法,調用語法如下:
editItem(QTableWidgetItem item)

注意:
  • editItem方法生效必須設置項的標記flags爲可編輯
  • editItem一次只能觸發一個項進行編輯,一旦退出編輯狀態(如改變焦點),除非再次調用editItem或設置editTriggers觸發編輯或打開永久編輯器否則對應項不能再編輯
  • 連續多次調用editItem,中間沒有觸發事件處理,則只有第一次調用生效,後續調用無效

4.3.3、openPersistentEditor打開持久編輯器

上面介紹editItem時說明了editItem只能觸發一次編輯,可以說進入臨時編輯狀態,一旦退出編輯除非再通過相關方式觸發編輯否則項不可再編輯。與此相對應,與QTreeWidget類似,QTableWidget還提供了一種一旦打開編輯狀態就可以隨時再次編輯,除非顯示關閉編輯狀態,這種方式就是打開持久編輯器。調用方法如下:

openPersistentEditor(QTableWidgetItem item)

該方法沒有返回值。

4.3.4、從表格中取並移除項的takeItem方法

takeItem方法是從表格部件中取一個項返回並從部件中刪除該項,調用語法如下:
QTableWidgetItem takeItem(int row, int column)

4.3.5、項排序

項排序是指針對錶格部件中的數據行進行排序,調用語法如下:
sortItems(int column, Qt.SortOrder order = Qt.AscendingOrder)
排序依據參數column指定列進行。Qt.SortOrder爲枚舉類,有兩個常量值,分別爲:AscendingOrder升序,對應數值爲0,DescendingOrder爲降序,對應數值爲1。

4.4、部件中項的查找和定位方法

項的查找和定位方法主要是查找特定的項和項的位置屬性。

4.4.1、搜索項

在表格部件中,可以根據文本以及匹配模式來搜索滿足條件的項,調用語法:
list[QTableWidgetItem] findItems( str text, Qt.MatchFlags flags)

返回值爲所有滿足條件的項構成的列表,如果沒有找到匹配項,返回空列表。
Qt.MatchFlags的取值及含義請參考《PyQt(Python+Qt)學習隨筆:Model/View中的枚舉類 Qt.MatchFlag的取值及含義》。

4.4.2、訪問選中項

在表格部件根據選擇模式的設置,只要選擇模式不是NoSelection(關於選擇模式繼承自QAbstractItemView,請參考《PyQt(Python+Qt)學習隨筆:QAbstractItemView的selectionMode屬性》),則可以通過操作選中部件中的項。選中的項可以通過方法selectedItems()方法返回,其返回值爲一個列表,列表中的每個元素是一個選中的QTableWidget項實例。

調用語法:

list[QTableWidgetItem] selectedItems()

4.4.3、獲取指定行和列的項

根據行和列可以獲取對應位置的項,調用語法如下:
QTableWidgetItem item(int row, int column)

如果對應位置沒有項,則返回None。

4.4.4、獲取指定位置的項

QTableWidget的itemAt方法通過視口內的座標點獲取對應座標位置的項,相關調用方法如下:

  • QTreeWidgetItem itemAt( QPoint p)
  • QTreeWidgetItem itemAt(int x, int y)

通過該方法可以獲取到視口上對應座標所在的項,如果對應座標位置無項則返回None。

4.4.5、獲取指定項的行和列

QTableWidget中可以根據項實例去定位項的行和列位置,調用方法如下:

  • int column( QTableWidgetItem item)
  • int row( QTableWidgetItem item)

如果對應項在QTableWidget表格部件中不存在,則返回-1。

4.4.5、獲取指定邏輯行或列對應的界面可見行號和列號

4.4.5.1、相關概念

關於邏輯行、列和可見行、列的概念,在QTableWidget中沒有介紹,老猿查了比較多的資料,並經過驗證,最終才搞清楚相關概念。這裏有幾個關鍵點要說明一下:

  1. 邏輯行和邏輯列是指項本身在部件中存儲數據的行和列,也是通過QTableWidgetItem項方法row()和column()返回的值
  2. 界面可見行和列是指在部件上的行號和列號,從部件中第一行和第一列數據開始到指定邏輯行或邏輯列在部件內的序號,但隱藏行和列(這裏的隱藏包括通過表頭方法hideSection實現、數據在視口外、在可以手工調整行和列大小時將其大小調整到最小不可見)也必須參與在內。這個地方是個坑,說是可見行和可見列,但實際上隱藏未展現的和在視口外的數據都是參與行號和列號的計數
  3. 僅當部件中的行或列通過表頭的moveSection交換了行或列數據所在的位置時纔出現邏輯行列和可見行列不一致的情況
4.4.5.2、可見行和列相關方法

要獲取表格部件中的可見行號和列號,調用方法:

  • int visualColumn(int logicalColumn)
  • int visualRow(int logicalRow)
4.4.5.3、小結
  1. 表格部件QTableWidget的項設置方法(setItem)所使用的行和列是項的邏輯行號和列號,表示數據在表格部件的存儲位置,表格部件中絕大多數方法所使用的行和列都是邏輯行和列。
  2. 僅當表格部件的表頭使用moveSection方法纔會導致表格部件的邏輯行列號可能和可見行列號不一致,行和列的隱藏以及超出視口都不會導致邏輯行列號可能和可見行列號不一致;
  3. 由於隱藏數據也在可見行列中計數,因此這兒的可見行列其實是不準確的,visualColumn和visualRow這兩個方法在使用上需要注意。
4.4.6、獲取項所在矩形位置的visualItemRect方法

QTableWidget的visualItemRect方法返回參數對應項佔用視口位置的矩形數據,調用語法如下:
QRect visualItemRect( QTableWidgetItem item)

注意:
1、該方法在item對應項在視口中不可見(即需要滾動纔可見)時同樣會返回對應的矩形數據,只不過在視口左上角左邊或上邊的數據對應的橫座標或縱座標爲負數;
2、如果項對應行或列被通過表頭方法hideSection隱藏了,則返回的矩形爲一個空矩形(無座標、長寬數據的矩形)。

案例:

在這裏插入圖片描述
上圖中的QTableWidget部件中第一行數據已經通過hideSection進行了隱藏,第1列數據滾動到視口左邊外去了,此時輸出所有行第一列的可視矩形,輸出結果如下:

    (0,0): PyQt5.QtCore.QRect()
    (1,0): PyQt5.QtCore.QRect(-76, 0, 99, 19)
    (2,0): PyQt5.QtCore.QRect(-76, 20, 99, 19)
    (3,0): PyQt5.QtCore.QRect(-76, 40, 99, 19)
    (4,0): PyQt5.QtCore.QRect(-76, 60, 99, 19)
    (5,0): PyQt5.QtCore.QRect(-76, 80, 99, 19)
    (6,0): PyQt5.QtCore.QRect(-76, 100, 99, 19)
    (7,0): PyQt5.QtCore.QRect(-76, 120, 99, 19)

可以看到第一行第一列因爲隱藏了是個空矩形,其他行的第一列x座標都是負數。

4.4.7、返回選中項範圍的矩形列表

在QTableWidget對項的操作支持選中多個項的情況下,可以通過方法selectedRanges返回選中矩形的列表,通過方法setRangeSelected將指定矩形範圍的項選中或去選中。相關方法調用語法如下:

  • list[QTableWidgetSelectionRange] selectedRanges()
  • setRangeSelected( QTableWidgetSelectionRange range, bool select)
注:
  • QTableWidgetSelectionRange描述一個基於邏輯項位置連續的矩形範圍,其矩形範圍的左上角座標爲該範圍內左上角邏輯項的邏輯行號和列號,右下角爲右下角邏輯項的邏輯行號和列號。注意這裏是指邏輯項而不是可見項
  • 由於選中的項可能不連續,因此selectedRanges返回的可能是多個QTableWidgetSelectionRange矩形的列表,每個矩形內是一個連續的選中範圍

4.5、表頭操作方法

QTableWidget表格部件的表頭包括水平表頭和豎直表頭,水平表頭每節對應表格的一列,豎直表頭對應表格的一行。如圖:
在這裏插入圖片描述
上圖中的“行”+編號的項就是豎直表頭的一個項(也稱爲1節),“列”+編號的項就是水平表頭的一個項(節)。

4.5.1、設置水平表頭的setHorizontalHeaderLabels方法

setHorizontalHeaderLabels用於一次性順序設置水平表頭多個節顯示的文本,調用語法如下:

setHorizontalHeaderLabels( Iterable[str] labels)

4.5.2、設置豎直表頭的setVerticalHeaderLabels

setVerticalHeaderLabels用於一次性順序設置豎直表頭多個節顯示的文本,調用語法如下:
setVerticalHeaderLabels( Iterable[str] labels)

其他的方面與setHorizontalHeaderLabels方法相同。

4.5.3、訪問水平節對應項

前面介紹了,表頭的一個節實際上對應一個項,項的類型與表格部件的項類型相同,都是QTableWidgetItem實例對象。水平節對應項可以通過方法horizontalHeaderItem和setHorizontalHeaderItem方法訪問,調用語法如下:

  • QTableWidgetItem horizontalHeaderItem(int column)
  • setHorizontalHeaderItem(int column, QTableWidgetItem item)

4.5.4、訪問豎直節對應項

類似setHorizontalHeaderItem,QTableWidget提供了verticalHeaderItem、setVerticalHeaderItem方法,調用語法如下:

  • QTableWidgetItem verticalHeaderItem(int row)
  • setVerticalHeaderItem(int row, QTableWidgetItem item)

相關方法使用與訪問水平節類似,在此不重複說明。

4.5.5、從表頭節中取下節對應項

QTableWidget可以取下表頭節對應項並返回,相關方法如下:

  • QTableWidgetItem takeHorizontalHeaderItem(int column)
  • QTableWidgetItem takeVerticalHeaderItem(int row)

對應節的項被取下後,表頭對應節的標籤將自動變更爲節的序號。

4.5.6、表頭屬性相關訪問方法

在Designer中,QTableWidget有如下表頭屬性可以設置:
在這裏插入圖片描述
相關屬性是從QTableView繼承過來的,相關訪問方法請參考《PyQt(Python+Qt)學習隨筆:QTableView的標題表頭相關屬性》。

五、本節小結

QTableWidget表格部件在創建以後,必須設置其包含的行數和列數才能插入項,項的插入通過setItem()進行。表格部件的QTableWidgetItem項是可用、可編輯、可選擇和可選中的,並且可以用作拖放操作的源和拖放目標。項初始化後,可以進行選擇、複選、編輯、排序等操作,除排序外相關操作會觸發對應信號,可以通過信號來獲取操作數據信息。

廣告

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

老猿Python,跟老猿學Python!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章