如何在委托 PyQt 中实现按钮

How to implement buttons in a delegate PyQt

我正在制作一个翻译文本的程序(见截图)

我有三个classes

class 用于显示编辑项目的 window :

class StyleDelegate(QStyledItemDelegate):
        def __init__(self, parent=None):
            super(StyleDelegate, self).__init__()
        def createEditor(self, widget, style, index):
            self.mainWidget = QWidget(widget)
            self.line = QLineEdit() # line for input text 
            self.delButton= QPushButton('❌')  # button for delete current item
            self.trnButton = QPushButton('➕')  # button for make translation text in another QListView
            self.qhbLayout = QHBoxLayout()
            self.qhbLayout.addWidget(self.line)
            self.qhbLayout.addWidget(self.delButton)
            self.qhbLayout.addWidget(self.trnButton)
            self.mainWidget.setLayout(self.qhbLayout)
            return self.mainWidget
        # there is still a lot of code in this place

class用于存储、添加、删除和编辑数据:

    class TranslateListModel(QAbstractListModel):
        def __init__(self, parent=None):
            super(TranslateListModel, self).__init__()
            self.words = ['1', '2', '3', '4']

        def removeItem(self, index):
            self.beginRemoveRows(index, index.row(), index.row())
            del self.words[index.row()]
            self.endRemoveRows()
            return True
        # there is still a lot of code in this place

程序的主要class:

class QTranslate(QtWidgets.QDialog, log.Ui_Dialog):
     def __init__(self):
        super().__init__()
        self.originalModel = TranslateListModel() 
        self.translateModel = TranslateListModel() 

        self.styleDelegate = StyleDelegate()

        self.originalLV.setModel(self.originalModel) 
        #QListView from Ui_Dialog

        self.translateLV.setModel(self.translateModel)
        #QListView from Ui_Dialog

        self.originalLV.setItemDelegate(self.styleDelegate)
        self.translateLV.setItemDelegate(self.styleDelegate)
    # there is still a lot of code in this place

如何使用 QStyledItemDelegate 实现按钮以删除当前项目并更改另一个 QListView 中的翻译?我无法在 StyleDelegate class 之外访问这些按钮以将它们与 TranslateListModel class.

的方法相关联

一个可能的解决方案是为委托创建信号并将它们连接到将删除或添加项目的函数,然后在单击按钮时发出这些信号:

class StyleDelegate(QStyledItemDelegate):
    deleteRequested = QtCore.pyqtSignal(int)
    translateRequested = QtCore.pyqtSignal(int)

    def __init__(self, parent=None):
        super(StyleDelegate, self).__init__()
    def createEditor(self, widget, style, index):
        # note: I removed the "self" references as they're unnecessary
        mainWidget = QWidget(widget)
        line = QLineEdit()
        delButton= QPushButton('❌')
        trnButton = QPushButton('➕')
        qhbLayout = QHBoxLayout()
        qhbLayout.addWidget(line)
        qhbLayout.addWidget(delButton)
        qhbLayout.addWidget(trnButton)
        mainWidget.setLayout(qhbLayout)
        delButton.clicked.connect(
            lambda _, row=index.row(): self.deleteRequested.emit(row))
        trnButton.clicked.connect(
            lambda _, row=index.row(): self.translateRequested.emit(row))
        return mainWidget


class QTranslate(QtWidgets.QDialog, log.Ui_Dialog):
    def __init__(self):
        # ...
        self.originalLV.setItemDelegate(self.styleDelegate)
        self.styleDelegate.deleteRequested.connect(self.deleteRow)
        self.styleDelegate.translateRequested.connect(self.translateRow)

    def deleteRow(self, row):
        # ...

    def translateRow(self, row):
        # ...

请注意,您应该始终为每个视图使用一个唯一委托实例,如documentation中所述:

Warning: You should not share the same instance of a delegate between views. Doing so can cause incorrect or unintuitive editing behavior since each view connected to a given delegate may receive the closeEditor() signal, and attempt to access, modify or close an editor that has already been closed.