TreeView in Python+QT

家住魔仙堡 提交于 2021-02-18 08:37:28

问题


I need to make a treeView with 4 columns with a checkbox in the first column. I have made ​​the tree view, just that I do not put the checkbox in the first column. I tried but it gets me in every position (row, column ) ...........

Here is my code:

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from copy import deepcopy
from cPickle import dumps, load, loads
from cStringIO import StringIO

class myNode(object):
    def __init__(self, name, state, description,otro, parent=None,checked=False):

        self.name = QString(name)
        self.state = QString(state)
        self.description = QString(description)
        self.otro = QString(otro)

        self.parent = parent
        self.children = []

        self.setParent(parent)

    def setParent(self, parent):
        if parent != None:
            self.parent = parent
            self.parent.appendChild(self)
        else:
            self.parent = None

    def appendChild(self, child):
        self.children.append(child)

    def childAtRow(self, row):
        return self.children[row]

    def rowOfChild(self, child):       
        for i, item in enumerate(self.children):
            if item == child:
                return i
        return -1

    def removeChild(self, row):
        value = self.children[row]
        self.children.remove(value)

        return True

    def __len__(self):
        return len(self.children)

class myModel(QAbstractItemModel):

    def __init__(self, parent=None):
        super(myModel, self).__init__(parent)       
        self.treeView = parent

        self.columns = 4
        self.headers = ['Directorio','Peso','Tipo','Modificado']

        # Create items
        self.root = myNode('root', 'on', 'this is root','asd', None)       
        itemA = myNode('itemA', 'on', 'this is item A','dfg', self.root)
        itemB = myNode('itemB', 'on', 'this is item B','fgh', self.root)       
        itemC = myNode('itemC', 'on', 'this is item C','cvb', self.root)

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal and role == Qt.DisplayRole:
            return QVariant(self.headers[section])
        return QVariant()

    def supportedDropActions(self):
        return Qt.CopyAction | Qt.MoveAction

    def flags(self, index):
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable| Qt.ItemIsUserCheckable

    def insertRow(self, row, parent):
        return self.insertRows(row, 1, parent)

    def insertRows(self, row, count, parent):
        self.beginInsertRows(parent, row, (row + (count - 1)))
        self.endInsertRows()
        return True

    def removeRow(self, row, parentIndex):
        return self.removeRows(row, 1, parentIndex)

    def removeRows(self, row, count, parentIndex):
        self.beginRemoveRows(parentIndex, row, row)
        node = self.nodeFromIndex(parentIndex)
        node.removeChild(row)
        self.endRemoveRows()

        return True

    def index(self, row, column, parent):
        node = self.nodeFromIndex(parent)
        return self.createIndex(row, column, node.childAtRow(row))

    def data(self, index, role):

        if role != Qt.DisplayRole:
            return QVariant()

        if not index.isValid():
            return None

        node = self.nodeFromIndex(index)

        if role == Qt.DisplayRole:
            if index.column() == 0:
                return QVariant(node.name)
        if role == Qt.CheckStateRole:
            if node.checked():
                return Qt.Checked
            else:
                return Qt.Unchecked

        if index.column() == 1:
            return QVariant(node.state)

        elif index.column() == 2:
            return QVariant(node.description)

        elif index.column() == 3:
            return QVariant(node.otro)

        else:
            return QVariant()

    def setData(self, index, value, role=Qt.EditRole):

        if index.isValid():
            if role == Qt.CheckStateRole:
                node = index.internalPointer()
                node.setChecked(not node.checked())
                return True
        return False

    def columnCount(self, parent):
        return self.columns

    def rowCount(self, parent):
        node = self.nodeFromIndex(parent)
        if node is None:
            return 0
        return len(node)

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

        node = self.nodeFromIndex(child)

        if node is None:
            return QModelIndex()

        parent = node.parent

        if parent is None:
            return QModelIndex()

        grandparent = parent.parent
        if grandparent is None:
            return QModelIndex()
        row = grandparent.rowOfChild(parent)

        assert row != - 1
        return self.createIndex(row, 0, parent)

    def nodeFromIndex(self, index):
        return index.internalPointer() if index.isValid() else self.root

class myTreeView(QTreeView):

    def __init__(self, parent=None):
        super(myTreeView, self).__init__(parent)

        self.myModel = myModel()
        self.setModel(self.myModel)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(600, 400)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.treeView = myTreeView(self.centralwidget)
        self.treeView.setObjectName("treeView")
        self.horizontalLayout.addWidget(self.treeView)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setGeometry(QRect(0, 0, 600, 22))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QApplication.translate("MainWindow", 
           "MainWindow", None, QApplication.UnicodeUTF8))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

回答1:


There are a few things wrong with your example code.

Firstly, your node class is missing some methods:

class myNode(object):
    def __init__(self, name, state, description, otro, parent=None, checked=False):
        ...

        self.setChecked(checked)

    def checked(self):
        return self._checked

    def setChecked(self, checked=True):
        self._checked = bool(checked)

Secondly, your model's flags method needs to return the correct values:

    def flags(self, index):
        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
        if index.column() == 0:
            return flags | Qt.ItemIsUserCheckable
        return flags

And finally, your model's data method needs to return the correct values:

    def data(self, index, role):

        if not index.isValid():
            return None

        node = self.nodeFromIndex(index)

        if role == Qt.DisplayRole:
            if index.column() == 0:
                return QVariant(node.name)
            if index.column() == 1:
                return QVariant(node.state)
            if index.column() == 2:
                return QVariant(node.description)
            if index.column() == 3:
                return QVariant(node.otro)
        elif role == Qt.CheckStateRole:
            if index.column() == 0:
                if node.checked():
                    return Qt.Checked
                return Qt.Unchecked

        return QVariant()



回答2:


QTreeView determine which cell should have checkbox by the result of QAbstractItemModel::flags function. You should return value with Qt.ItemIsUserCheckable only for first column and without for others:

def flags(self, index):
    if index.column() == 0:
        return Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable                     
    return Qt.ItemIsEnabled | Qt.ItemIsSelectable


来源:https://stackoverflow.com/questions/21209771/treeview-in-pythonqt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!