簡體   English   中英

如何從 python 中的 Model 中刪除項目

[英]How do i remove items from Model in python

如何從我的自定義 QAbstractTableModel 中正確刪除項目? 我需要將其更改為 QStandardItemModel 嗎?

這是之前的:

在此處輸入圖像描述

這是之后......它留下了空行,並且選擇似乎也沒有清除。

在此處輸入圖像描述

import os
import sys
from PySide import QtCore, QtGui
import random


class CustomJobs(object):

    def __init__(self, **kwargs):
        super(CustomJobs, self).__init__()

        # instance properties
        self.name = ''
        self.status = ''

        # initialize attribute values
        for k, v in kwargs.items():
            if hasattr(self, k):
                setattr(self, k, v)


class PlayblastTableModel(QtCore.QAbstractTableModel):

    HEADERS = ['Name', 'Status']

    def __init__(self):
        super(PlayblastTableModel, self).__init__()
        self.items = []

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if orientation == QtCore.Qt.Horizontal:
            if role == QtCore.Qt.DisplayRole:
                return self.HEADERS[section]
        return None

    def columnCount(self, parent=QtCore.QModelIndex()):
        return len(self.HEADERS)

    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.items)

    def addItem(self, *items):
        self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount() + len(items) - 1)
        for item in items:
            assert isinstance(item, CustomJobs)
            self.items.append(item)
        self.endInsertRows()

    def removeItems(self, items):
        self.beginRemoveRows(QtCore.QModelIndex(), self.rowCount(), self.rowCount())
        self.items = [x for x in self.items if x not in items]
        self.endRemoveRows()

    def clear(self):
        self.beginRemoveRows(QtCore.QModelIndex(), 0, self.rowCount())
        self.items = []
        self.endRemoveRows()

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return

        row = index.row()
        col = index.column()

        if 0 <= row < self.rowCount():
            item = self.items[row]

            if role == QtCore.Qt.DisplayRole:
                if col == 0:
                    return item.name
                elif col == 1:
                    return item.status.title()
            elif role == QtCore.Qt.UserRole:
                return item

        return None


class CustomJobsQueue(QtGui.QWidget):
    '''
    Description:
        Widget that manages the Jobs Queue
    '''
    def __init__(self):
        super(CustomJobsQueue, self).__init__()
        self.resize(400,600)

        # controls
        self.uiAddNewJob = QtGui.QPushButton('Add')
        self.uiRemoveSelectedJobs = QtGui.QPushButton('Remove')

        self.playblastJobModel = PlayblastTableModel()
        self.uiJobTableView = QtGui.QTableView()
        self.uiJobTableView.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.uiJobTableView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.uiJobTableView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.uiJobTableView.setModel(self.playblastJobModel)

        self.jobSelection = self.uiJobTableView.selectionModel()

        # sub layouts
        self.jobQueueToolsLayout = QtGui.QHBoxLayout()
        self.jobQueueToolsLayout.addWidget(self.uiAddNewJob)
        self.jobQueueToolsLayout.addWidget(self.uiRemoveSelectedJobs)
        self.jobQueueToolsLayout.addStretch()

        # layout
        self.mainLayout = QtGui.QVBoxLayout()
        self.mainLayout.addLayout(self.jobQueueToolsLayout)
        self.mainLayout.addWidget(self.uiJobTableView)
        self.setLayout(self.mainLayout)

        # connections
        self.uiAddNewJob.clicked.connect(self.addNewJob)
        self.uiRemoveSelectedJobs.clicked.connect(self.removeSelectedJobs)


    # methods
    def addNewJob(self):
        name = random.choice(['Kevin','Suzie','Melissa'])
        status = random.choice(['error','warning','successa'])
        job = CustomJobs(name=name, status=status)
        self.playblastJobModel.addItem(job)

    def removeSelectedJobs(self):
        jobs = self.getSelectedJobs()
        self.playblastJobModel.removeItems(jobs)

    def getSelectedJobs(self):
        jobs = [x.data(QtCore.Qt.UserRole) for x in self.jobSelection.selectedRows()]
        return jobs


def main():
    app = QtGui.QApplication(sys.argv)
    window = CustomJobsQueue()
    window.show()
    app.exec_()


if __name__ == '__main__':
    main()

這種行為的原因是您在beginRemoveRows()中使用了錯誤的行:您應該使用要刪除的行號,並且由於您使用的是rowCount() ,因此行索引無效。

    def removeItems(self, items):
        self.beginRemoveRows(QtCore.QModelIndex(), self.rowCount() - 1, self.rowCount() - 1)
        self.items = [x for x in self.items if x not in items]
        self.endRemoveRows()

為了更正確,您應該刪除 model 中的實際行。 在您的簡單情況下,這並不重要,但如果您的 model 變得更復雜,請記住這一點。

    def removeItems(self, items):
        removeRows = []
        for row, item in enumerate(self.items):
            if item in items:
                removeRows.append(row)
        for row in sorted(removeRows, reverse=True):
            self.beginRemoveRows(QtCore.QModelIndex(), row, row)
            self.items.pop(row)
            self.endRemoveRows()

for 循環中行順序顛倒的原因是,出於列表一致性的原因,行刪除應始終從底部開始。 如果您想在保留當前選擇的同時任意刪除行以防刪除的項目未被選中,這可能很重要。

也就是說,正如評論中已經建議的那樣,如果您不需要特定的行為和實現,則不需要創建 QAbstractItemModel (或任何抽象模型)子類,因為 QStandardItemModel 通常就足夠了,因為它已經提供了所有必需的功能(包括拖放支持,如果您不知道 Qt 數據 model 的工作原理,這可能會相當復雜)。
好吧,除非是出於學習目的,顯然。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM