QAbstratctTableModel-removeRows [英] QAbstratctTableModel - removeRows

查看:442
本文介绍了QAbstratctTableModel-removeRows的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码快完成了.这是交易:

它是python和PySide.我有一个QAbstractTableModel和QTableView.

我无法正确删除行.我认为问题出在行索引的某个地方,我删除了其中之一...

这是我使用的按钮委托:

class ButtonDelegate(QItemDelegate):

    def __init__(self, parent):
        QItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):

        widget = QWidget()
        layout = QHBoxLayout()
        widget.setLayout(layout)
        btn = QPushButton("X")
        btn.clicked.connect(partial(self.parent().cellButtonClicked, index))
        layout.addWidget(btn)
        layout.setContentsMargins(2,2,2,2)

        if not self.parent().indexWidget(index):
            self.parent().setIndexWidget(index, widget)

这是cellButtonClicked方法,它在表格视图下:

class Table(QTableView):

def __init__(self, *args, **kwargs):
    QTableView.__init__(self, *args, **kwargs)

    self.setItemDelegateForColumn(6, ButtonDelegate(self))
    self.setItemDelegateForColumn(0, EmptyDelegate(self))

    self.setSortingEnabled(True)

def cellButtonClicked(self, index,  *args):

    model = self.model()
    model.removeRow(index.row())

这是模型removeRow方法:

def removeRow(self, row, parent = QtCore.QModelIndex()):

    self.beginRemoveRows(parent, row, row)

    array = []
    for i in range(7):
        if i == 0:
            array.append(self.index(row, i).data())
        else:
            array.append(str(self.index(row, i).data()))

    self.cycles.remove(array)

    self.endRemoveRows()

    # update custom node in maya. 
    self.getData()

我认为主要是因为问题是,当我删除一行时,它不会更新模型的索引.因此,当我再次单击任何删除按钮时,它开始于带有索引的removeRow(),该索引不再与模型的rowCount匹配,因此无法构建要从模型数据中删除的数组.

有意义吗?如果您需要更多代码,请告诉我您需要什么.

解决方案

之所以引起此问题,是因为您在创建每个委托时都设置了行的值,因此不会更新其值.

一个可能的解决方案是使用lambda函数传递与临时QModelIndex关联的QPersistenModelIndex,但是我已经看到在创建选择项时出现了意外情况,因此我将其称为clearSelection(). /p>

不必连接到cellButtonClicked插槽,因为您可以使用QModelIndex或QPersistenModelIndex直接访问模型.

class ButtonDelegate(QItemDelegate):
    def __init__(self, parent):
        QItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):
        widget = QWidget()
        layout = QHBoxLayout()
        widget.setLayout(layout)
        btn = QPushButton("X")
        ix = QPersistentModelIndex(index)
        btn.clicked.connect(lambda ix = ix : self.onClicked(ix))
        layout.addWidget(btn)
        layout.setContentsMargins(2,2,2,2)
        if not self.parent().indexWidget(index):
            self.parent().setIndexWidget(index, widget)

    def onClicked(self, ix):
        model = ix.model()
        model.removeRow(ix.row())
        self.parent().clearSelection()

另一种选择是通过editorEvent处理单击的事件,因为提供的QModelIndex具有更新的值,如下所示:

class ButtonDelegate(QStyledItemDelegate):
    def __init__(self, parent):
        QStyledItemDelegate.__init__(self, parent)
        self.state = QStyle.State_Enabled

    def paint(self, painter, option, index):
        button = QStyleOptionButton()
        button.rect = self.adjustRect(option.rect)
        button.text = "X"
        button.state = self.state
        QApplication.style().drawControl(QStyle.CE_PushButton, button, painter)

    def editorEvent(self, event, model, option, index):
        if event.type() == QEvent.Type.MouseButtonPress:
            self.state = QStyle.State_On
            return True
        elif event.type() == QEvent.Type.MouseButtonRelease:
            r = self.adjustRect(option.rect)
            if r.contains(event.pos()):
                model.removeRow(index.row())
            self.state = QStyle.State_Enabled
        return True

    @staticmethod
    def adjustRect(rect):
        r = QRect(rect)
        margin = QPoint(2, 2)
        r.translate(margin)
        r.setSize(r.size()-2*QSize(margin.x(), margin.y()))
        return r

除此之外,没有必要遍历data(),我们可以直接删除该行:

def removeRow(self, row, parent=QModelIndex()):
    self.beginRemoveRows(parent, row, row)
    self.cycles.remove(self.cycles[row])
    self.endRemoveRows()
    self.getData()

在下面的链接中,这两个选项均已实现.

Code is almost complete. Here's the deal:

It is python and PySide. I have a QAbstractTableModel and a QTableView.

I cant get deleting rows correctly. I think the problem is somewhere in the indexes of the rows onde I delete one of them...

here is the button delegate I use:

class ButtonDelegate(QItemDelegate):

    def __init__(self, parent):
        QItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):

        widget = QWidget()
        layout = QHBoxLayout()
        widget.setLayout(layout)
        btn = QPushButton("X")
        btn.clicked.connect(partial(self.parent().cellButtonClicked, index))
        layout.addWidget(btn)
        layout.setContentsMargins(2,2,2,2)

        if not self.parent().indexWidget(index):
            self.parent().setIndexWidget(index, widget)

here's the cellButtonClicked method, it is under the table view:

class Table(QTableView):

def __init__(self, *args, **kwargs):
    QTableView.__init__(self, *args, **kwargs)

    self.setItemDelegateForColumn(6, ButtonDelegate(self))
    self.setItemDelegateForColumn(0, EmptyDelegate(self))

    self.setSortingEnabled(True)

def cellButtonClicked(self, index,  *args):

    model = self.model()
    model.removeRow(index.row())

and here is the model removeRow Method:

def removeRow(self, row, parent = QtCore.QModelIndex()):

    self.beginRemoveRows(parent, row, row)

    array = []
    for i in range(7):
        if i == 0:
            array.append(self.index(row, i).data())
        else:
            array.append(str(self.index(row, i).data()))

    self.cycles.remove(array)

    self.endRemoveRows()

    # update custom node in maya. 
    self.getData()

I think that, mainly, the problem is that when I delete a row it does not update the indexes of the model. So when I click again in any delete button it starts de removeRow() with an index the does no match the rowCount of the model anymore, therefore I can't build the array to be removed from the model data.

Did it make sense? if you need more code, tell me what you need.

解决方案

The problem is caused because you have set the value of the row when you have created each delegate, so its value is not updated.

A possible solution is to use a lambda function to pass a QPersistenModelIndex associated with the temporary QModelIndex, but I have seen that there is an unexpected behavior that is creating a selection, so I called clearSelection().

It is not necessary to connect to the cellButtonClicked slot since you can directly access the model using QModelIndex or QPersistenModelIndex.

class ButtonDelegate(QItemDelegate):
    def __init__(self, parent):
        QItemDelegate.__init__(self, parent)

    def paint(self, painter, option, index):
        widget = QWidget()
        layout = QHBoxLayout()
        widget.setLayout(layout)
        btn = QPushButton("X")
        ix = QPersistentModelIndex(index)
        btn.clicked.connect(lambda ix = ix : self.onClicked(ix))
        layout.addWidget(btn)
        layout.setContentsMargins(2,2,2,2)
        if not self.parent().indexWidget(index):
            self.parent().setIndexWidget(index, widget)

    def onClicked(self, ix):
        model = ix.model()
        model.removeRow(ix.row())
        self.parent().clearSelection()

Another option is to handle the clicked events through editorEvent since the provided QModelIndex has updated values as shown below:

class ButtonDelegate(QStyledItemDelegate):
    def __init__(self, parent):
        QStyledItemDelegate.__init__(self, parent)
        self.state = QStyle.State_Enabled

    def paint(self, painter, option, index):
        button = QStyleOptionButton()
        button.rect = self.adjustRect(option.rect)
        button.text = "X"
        button.state = self.state
        QApplication.style().drawControl(QStyle.CE_PushButton, button, painter)

    def editorEvent(self, event, model, option, index):
        if event.type() == QEvent.Type.MouseButtonPress:
            self.state = QStyle.State_On
            return True
        elif event.type() == QEvent.Type.MouseButtonRelease:
            r = self.adjustRect(option.rect)
            if r.contains(event.pos()):
                model.removeRow(index.row())
            self.state = QStyle.State_Enabled
        return True

    @staticmethod
    def adjustRect(rect):
        r = QRect(rect)
        margin = QPoint(2, 2)
        r.translate(margin)
        r.setSize(r.size()-2*QSize(margin.x(), margin.y()))
        return r

In addition to this it is not necessary to iterate through data(), we can delete the row directly:

def removeRow(self, row, parent=QModelIndex()):
    self.beginRemoveRows(parent, row, row)
    self.cycles.remove(self.cycles[row])
    self.endRemoveRows()
    self.getData()

In the following link both options are implemented.

这篇关于QAbstratctTableModel-removeRows的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆