天天看點

PyQt4 QTreeView的簡單樹

簡單的樹結構,目前的殘留問題是無法自動調整QTreeView的寬度

1、建立檔案夾,任意英文名字,比如Main

建立py檔案,内容如下:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'GUI.ui'
#
# Created: Mon Jan 08 19:54:27 2018
#      by: PyQt4 UI code generator 4.11.1
#
# WARNING! All changes made in this file will be lost!
import os
import sys
import locale
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtCore, QtGui
from PyQt4 import QtCore, QtGui
# try:
#     import simpletreemodel_rc3
# except ImportError:
#     import simpletreemodel_rc2
class TreeItem(object):
    def __init__(self, data, parent=None):
        self.parentItem = parent
        self.itemData = data
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def child(self, row):
        return self.childItems[row]

    def childCount(self):
        return len(self.childItems)

    def columnCount(self):
        return len(self.itemData)

    def data(self, column):
        try:
            return self.itemData[column]
        except IndexError:
            return None

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)

        return 0


class TreeModel(QtCore.QAbstractItemModel):

    def __init__(self, data, parent=None):
        # app = QApplication(sys.argv)
        # mycode = locale.getpreferredencoding()
        # code = QTextCodec.codecForName(mycode)
        # QTextCodec.setCodecForLocale(code)
        # QTextCodec.setCodecForTr(code)
        # QTextCodec.setCodecForCStrings(code)
        super(TreeModel, self).__init__(parent)
        self.checkLisk = []
        self.rootItem = TreeItem(["Name"])
        self.setupModelData(data.split('\n'), self.rootItem)

    def columnCount(self, parent):
        if parent.isValid():
            return parent.internalPointer().columnCount()
        else:
            return self.rootItem.columnCount()

    def data(self, index, role):
        if not index.isValid():
            return None

        item = index.internalPointer()

        if role == QtCore.Qt.CheckStateRole:  # 被選中項是checkbox
            # if item.parent() == self.rootItem:  # 如果是根的話,直接傳回
            #     return None
            # if item.childCount() > 0:  # 如果是有子項的話,直接傳回,這個可以根據需要調整。當需要成組選擇的時候,必須保留
            #     return None
            if index.column() == 0:
                for x in self.checkLisk:  # 檢查該項是否在checkList中,如果在将其設為選中狀态
                    if x == index:
                        return QtCore.Qt.Checked
                else:
                    return QtCore.Qt.Unchecked
        if role != QtCore.Qt.DisplayRole:
            return None
        return item.data(index.column())

    def setData(self, index, value, role=QtCore.Qt.EditRole):
        if role == QtCore.Qt.CheckStateRole and index.column() == 0:
            if value == QtCore.Qt.Unchecked:  # 撤銷選中的情況
                self.checkLisk.remove(index)  # 将節點的index從checklist中移除
                self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                          index, index)
            else:  # 選中的情況
                self.checkLisk.append(index)  # 将節點的index加到checklist中
                self.emit(QtCore.SIGNAL("dataChanged(QModelIndex,QModelIndex)"),
                          index, index)
            return True

    def flags(self, index):
        if not index.isValid():
            return QtCore.Qt.NoItemFlags
        result = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
        if index.column() == 0:  # 隻讓第一列顯示checkbox
            result |= QtCore.Qt.ItemIsUserCheckable
        return result

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self.rootItem.data(section)

        return None

    def index(self, row, column, parent):
        if not self.hasIndex(row, column, parent):
            return QtCore.QModelIndex()

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        childItem = parentItem.child(row)
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QtCore.QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QtCore.QModelIndex()

        childItem = index.internalPointer()
        parentItem = childItem.parent()

        if parentItem == self.rootItem:
            return QtCore.QModelIndex()

        return self.createIndex(parentItem.row(), 0, parentItem)

    def rowCount(self, parent):
        if parent.column() > 0:
            return 0

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        return parentItem.childCount()

    def setupModelData(self, lines, parent):
        parents = [parent]
        indentations = [0]

        number = 0

        while number < len(lines):
            position = 0
            while position < len(lines[number]):
                if lines[number][position] != ' ':
                    break
                position += 1

            lineData = lines[number][position:]

            if lineData:
                # Read the column data from the rest of the line.
                columnData = [s for s in lineData.split('\t') if s]

                if position > indentations[-1]:
                    # The last child of the current parent is now the new
                    # parent unless the current parent has no children.

                    if parents[-1].childCount() > 0:
                        parents.append(parents[-1].child(parents[-1].childCount() - 1))
                        indentations.append(position)

                else:
                    while position < indentations[-1] and len(parents) > 0:
                        parents.pop()
                        indentations.pop()

                # Append a new item to the current parent's list of children.
                parents[-1].appendChild(TreeItem(columnData, parents[-1]))

            number += 1
      

2、建立GUI.py,代碼如下

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'GUI.ui'
#
# Created: Mon Jan 08 19:54:27 2018
#      by: PyQt4 UI code generator 4.11.1
#
# WARNING! All changes made in this file will be lost!
import os
import sys
import locale
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import QtCore, QtGui
from treeCaseList import TreeModel
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)



class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        super(TreeModel)
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.CaseList = QtGui.QTreeView(self.centralwidget)
        self.initCaseList()
        self.CaseList.setModel(self.model)
        self.CaseList.setGeometry(QtCore.QRect(0, 10, 230, 471))
        self.CaseList.setObjectName(_fromUtf8("CaseList"))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)
        self.toolBar = QtGui.QToolBar(MainWindow)
        self.toolBar.setObjectName(_fromUtf8("toolBar"))
        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
        self.toolBar.addSeparator()
        self.retranslateUi(MainWindow)
        QtCore.QObject.connect(self.CaseList, QtCore.SIGNAL(_fromUtf8("activated(QModelIndex)")), self.CaseList.update)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar", None))

    def initCaseList(self):
        tcPath = "D:\demo" # 定義樹形父節點路徑
        names = locals()
        treeTopNum = 1  # 定義樹形父節點個數
        treeValue = 1
        CaseArray = []
        line = ''
        list = os.listdir(tcPath)  # 列出檔案夾下所有的目錄與檔案
        for i in range(0, len(list)):
            path = os.path.join(tcPath, list[i])
            if os.path.isdir(path):
                if line[-2:] == ' \t':
                    line = line[:-2]  # 去除父節點最後的那個tab符号
                line = line + list[i] + '\n' + ' ' + '\t'
                treeValue += 1
                # 遞歸檔案夾,找到case名稱,放在子節點,initial和release不能放,因為這裡沒有處理二級檔案夾,同名的不做處理。
                # 如果需要做,那就要區分到測試套檔案夾名稱
                for listView in os.walk(path):
                    if 'testcase' in listView[0]:
                        for listCase in listView[2]:
                            if ('initial.tcl' not in listCase) and ('release.tcl' not in listCase):
                                line = line + listCase + '\n' + ' ' + '\t'
        # print line
        self.model = TreeModel(u'%s' % line)
        self.CaseList.setModel(self.model)
      

3、建立Main.py,代碼如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import PyQt4
from PyQt4 import QtGui
import sys
from GUI import Ui_MainWindow


#GUItmp***.ui轉換的py檔案名,也就相當于子產品。
#​Ui_MainWindow為GUItmp界面的類,打開該py檔案即可看到
class MyWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.ui = Ui_MainWindow() #這裡需要注意self.ui已經将Ui_MainWindow類執行個體 #化,是以繼承了該類的所有屬性,後面更改設定屬性都用self.ui“冠名”
        self.ui.setupUi(self)
# =======================我是注釋========================
# 這個類的下面就可以編寫(def)自己的函數,如按鈕的功能等
# def。。。
# ​=======================注釋完畢========================
def main():
    app = QtGui.QApplication(sys.argv)
    w = MyWindow()
    w.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()      

4、運作Main.py即可。