简体   繁体   English

如何在编辑qlistwidget项后捕获新名称

[英]How to capture the new name after editing qlistwidget item

I have made the items within QListWidget to be editable so that I can perform renaming when needed. 我已经使QListWidget中的项目可以编辑,以便我可以在需要时执行重命名。

To do the renaming, user can 'double-click' on the item in which it will gives a QLineEdit that enables one to edit the text, and currently I am having issue in capturing the new name after the QLineEdit. 要进行重命名,用户可以“双击”它将提供QLineEdit的项目,使其能够编辑文本,目前我在QLineEdit之后捕获新名称时遇到问题。

Tried using itemDoubleClicked and currentTextChanged signal but it does not seems to be returning me the new name. 尝试使用itemDoubleClickedcurrentTextChanged信号,但它似乎没有给我返回新名称。 For example, I am trying to rename Trhee to Three but under rename_item() , it returns me Trhee 例如,我正在尝试将Trhee重命名为Three但在rename_item() ,它会返回Trhee

class Dialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__()
        self.listWidget = QtGui.QListWidget()
        items = ['One', 'Two', 'Trhee']
        for item in items:
            self.listWidget.addItem(item)

        self.listWidget.currentTextChanged.connect(self.rename_item)
        # self.listWidget.itemDoubleClicked.connect(self.rename_item)

        for index in range(self.listWidget.count()):
            item = self.listWidget.item(index)
            item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEditable)
            item.setCheckState(QtCore.Qt.Checked)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.listWidget)

    def rename_item(self):
        prev_item_name = self.listWidget.currentItem()
        print 'before rename: ', prev_item_name.text()

        # Returns me the same value as prev_item_name...
        new_item_name = self.listWidget.currentItem()
        print 'after rename: ', new_item_name.text()


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = Dialog()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

I;m not exactly sure what are you planning to do. 我不确定你打算做什么。 My suggestion is to change activation methods, so for example: 我的建议是更改激活方法,例如:

self.listWidget.itemDoubleClicked.connect(self.previous_name)
self.listWidget.itemChanged.connect(self.current_name)

def previous_name(self):
        prev_item_name = self.listWidget.currentItem()
        print ('before rename: ', prev_item_name.text())

def current_name(self):
        try:
            new_item_name = self.listWidget.currentItem()
            print ('after rename: ', new_item_name.text())
        except:
            pass

The appropriate signal for this case is dataChanged but this signal is not only issued when the text is modified, but when other properties, such as the checkbox status, are modified. 此情况的适当信号是dataChanged,但此信号不仅在修改文本时发出,而且在修改其他属性(如复选框状态)时发出。 In PyQt5 / Qt5 is added to that signal an argument that indicates that it allows to distinguish but is not the case of PyQt4. 在PyQt5 / Qt5中添加了一个参数,表明它允许区分但不是PyQt4的情况。

One way to obtain if the modified role corresponds to the text is to compare the text before and after the change, but the QListWidgetItem only saves one text so another role must be used to save the old text. 获取修改后的角色是否与文本对应的一种方法是比较更改前后的文本,但QListWidgetItem只保存一个文本,因此必须使用另一个角色来保存旧文本。 With this logic I have implemented the following solution: 通过这种逻辑,我实现了以下解决方案:

from PyQt4 import QtCore, QtGui


class ListWidget(QtGui.QListWidget):
    textItemChanged = QtCore.pyqtSignal(QtGui.QListWidgetItem)

    OLDTEXTROLE = QtCore.Qt.UserRole + 1000

    def __init__(self, parent=None):
        super(ListWidget, self).__init__(parent)
        self.model().dataChanged.connect(self.on_data_changed)

    @QtCore.pyqtSlot(QtCore.QModelIndex, QtCore.QModelIndex)
    def on_data_changed(self, topLeft, bottomRight):
        if topLeft == bottomRight:
            it = self.itemFromIndex(topLeft)
            old_text = it.data(ListWidget.OLDTEXTROLE)
            if old_text is None:
                it.setData(ListWidget.OLDTEXTROLE, "")
            if old_text == it.text():
                return
            self.textItemChanged.emit(it)
            it.setData(ListWidget.OLDTEXTROLE, it.text())


class Dialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Dialog, self).__init__()
        self.listWidget = ListWidget()
        items = ["One", "Two", "Trhee"]
        for item in items:
            self.listWidget.addItem(item)

        for index in range(self.listWidget.count()):
            item = self.listWidget.item(index)
            item.setFlags(
                item.flags()
                | QtCore.Qt.ItemIsUserCheckable
                | QtCore.Qt.ItemIsEditable
            )
            item.setCheckState(QtCore.Qt.Checked)

        self.listWidget.textItemChanged.connect(self.on_text_item_changed)

        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.listWidget)

    @QtCore.pyqtSlot(QtGui.QListWidgetItem)
    def on_text_item_changed(self, it):
        current_text = it.text()
        old_text = it.data(ListWidget.OLDTEXTROLE)
        print("old_text: {}, current_text: {}".format(old_text, current_text))


if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)
    window = Dialog()
    window.setGeometry(600, 100, 300, 200)
    window.show()
    sys.exit(app.exec_())

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

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