简体   繁体   English

Python-从QSQLRelationalTableModel / QTableView删除选定的行

[英]Python - Deleting a selected row from a QSQLRelationalTableModel / QTableView

I have a QTableView class, and a QSQLRelationalTableModel class for displaying data from within an SQLITE database. 我有一个QTableView类和一个QSQLRelationalTableModel类,用于显示SQLITE数据库中的数据。

I have subclassed these myself as I need to overwrite various methods within the PyQt classes. 我自己将这些子类化,因为我需要覆盖PyQt类中的各种方法。

I am trying to implement a 'Delete Row' function which will then automatically redraw the TableView. 我正在尝试实现“删除行”功能,然后该功能将自动重绘TableView。

Unfortunately I'm at a loss. 不幸的是我很茫然。 I have overwritten the data() method within the model, as I need to modify the data that's returned for some columns. 我已经覆盖了模型中的data()方法,因为我需要修改为某些列返回的数据。 When I delete a row, this data() method obviously then has nothing to return for that row, which throws type errors (It's expecting to return data for a missing row). 当我删除一行时,此data()方法显然对于该行没有任何要返回的内容,这将引发类型错误(期望为缺少的行返回数据)。 For the moment I have it sat in a try/except block (I know that's bad practice), and to return "Deleted" if it doesn't work. 目前,我将其放在try / except块中(我知道这是不好的做法),如果不起作用,则返回“已删除”。

Here is my complete model: 这是我完整的模型:

class PayRateTableModel(QtSql.QSqlRelationalTableModel):
    def __init__(self,master):
        QtSql.QSqlRelationalTableModel.__init__(self,db=master.db)
        self.header_labels = ['ID','From','To','Day Rate','Night Rate', 'Description']
        self.editable_columns = [1,2,3,4,5]
        self.setTable('payrates')
        self.setEditStrategy(QtSql.QSqlRelationalTableModel.OnRowChange)
        self.select()

    def columnCount(self,master,parent=QtCore.QModelIndex()):
        return 6

    def flags(self, index):
        flags=super(self.__class__, self).flags(index)
        if index.column() not in self.editable_columns:
            flags ^= QtCore.Qt.ItemIsEditable
        return flags

    def headerData(self, p_int, Qt_Orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole and Qt_Orientation == QtCore.Qt.Horizontal:
            return self.header_labels[p_int]
        return QtCore.QAbstractTableModel.headerData(self,p_int, Qt_Orientation,role)

    def data(self, index, role):
        row=index.row()
        col=index.column()
        data = super(PayRateTableModel, self).data(index, role)
        if role==QtCore.Qt.TextAlignmentRole:
            return QtCore.Qt.AlignCenter
        elif role==QtCore.Qt.FontRole:
            f=QtGui.QFont
            return f
        elif role==QtCore.Qt.ForegroundRole and index.column() not in self.editable_columns:
            return QtGui.QColor(150,150,150)
        try:
            if (col in [1,2]) and (role==QtCore.Qt.DisplayRole) and data:
                data=super(PayRateTableModel, self).data(index,role)
                year=data[:4]
                month=data[5:7]
                day=data[8:10]
                data=QtCore.QDate(int(year),int(month),int(day)).toString("dd/MM/yyyy")
                return data
            elif col in [3,4] and role ==QtCore.Qt.DisplayRole:
                data=super(PayRateTableModel, self).data(index,role)
                return '%.4f' % data
        except:
            return "Deleted"

        return super(PayRateTableModel, self).data(index,role)

Here is my TableView 这是我的TableView

class PayRateTableView(QtWidgets.QTableView):
    """ Display table of editable pay rates"""
    def __init__(self, master):
        QtWidgets.QTableView.__init__(self)
        self.hideColumn(0)
        self.setSortingEnabled(True)
        self.model = PayRateTableModel(master)
        self.sortmodel=DateSortProxyModel()
        self.sortmodel.setSourceModel(self.model)
        self.setModel(self.sortmodel)
        self.sortByColumn(1,QtCore.Qt.AscendingOrder)
        self.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        self.resizeRowsToContents()
        self.resizeColumnsToContents()
        self.setAlternatingRowColors(True)
        self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        self.setItemDelegateForColumn(1, CalendarDelegate(master))
        self.setItemDelegateForColumn(2, CalendarDelegate(master))
        self.setItemDelegateForColumn(3, PayRateDelegate(master))
        self.setItemDelegateForColumn(4, PayRateDelegate(master))
        self.vhead=self.verticalHeader()
        self.vhead.setVisible(False)
        self.vhead.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.vhead.customContextMenuRequested.connect(self.contextMenuEvent)
    def sizeHintForRow(self, p_int):
        return 20

    def contextMenuEvent(self, event):
        index = self.currentIndex()
        menu=QtWidgets.QMenu(self)
        menu.popup(QtGui.QCursor.pos())
        deleteAction = menu.addAction("Delete Row")
        action = menu.exec_(self.mapToGlobal(event.pos()))
        if action == deleteAction:
            self.model.removeRow(index.row())
            self.model.submitAll()

This actually works but although it deletes the data, it leaves half a row at the top of the table like this (Row 3 has just been deleted): 这实际上是可行的,但是尽管删除了数据,但它在表的顶部留了一半行,如下所示(行3刚刚被删除):

QTableView的屏幕截图,其中删除了一行

Any changes I make that seem to successfully delete the row, make the app quit with a "Processed finished with exit code 11" which I cannot find any detailed explanation (Platform specific, I'm using PyCharm on Mac OS and Python 3.6) 我所做的任何更改似乎都成功删除了该行,使应用程序退出并显示“处理完成,退出代码为11”,我找不到任何详细说明(特定于平台,我在Mac OS和Python 3.6上使用PyCharm)

Thanks 谢谢

As it turns out, I seem to have figured it out. 事实证明,我似乎已经明白了。 Kind of. 的种类。 Although it's not a direct answer per se, I changed the deletion method from a context menu to a toolbar icon. 尽管这并不是直接的答案,但我将删除方法从上下文菜单更改为工具栏图标。 Select row, click toolbar icon, invoke the following Class method: 选择行,单击工具栏图标,调用以下Class方法:

def deletePayRate(self):
    index = self.currentIndex()
    deleteconfirmation = QtWidgets.QMessageBox.critical(self.parent(), "Delete row", "Really delete the selected Pay Rate?", QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
    if deleteconfirmation == QtWidgets.QMessageBox.Yes:
        self.model.removeRow(index.row())
        self.model.submitAll()
        return
    else:
        return

Simple but it works. 很简单,但是有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM