Как записать новое имя после редактирования элемента qlistwidget - PullRequest
0 голосов
/ 05 июня 2019

Я сделал элементы в QListWidget редактируемыми, чтобы при необходимости можно было переименовывать.

Чтобы сделать переименование, пользователь может «дважды щелкнуть» на элементе, в котором он даст QLineEdit, позволяющий редактировать текст, и в настоящее время у меня возникают проблемы с захватом нового имени после QLineEdit.

Пытался использовать сигнал itemDoubleClicked и currentTextChanged, но он, похоже, не возвращает мне новое имя. Например, я пытаюсь переименовать 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_())

Ответы [ 2 ]

0 голосов
/ 05 июня 2019

Подходящим сигналом для этого случая является dataChanged, но этот сигнал выдается не только при изменении текста, но и при изменении других свойств, таких как состояние флажка.В PyQt5 / Qt5 к этому сигналу добавляется аргумент, который указывает, что он позволяет различать, но не относится к PyQt4.

Один из способов получения, если измененная роль соответствует тексту, состоит в сравнении текста переди после изменения, но QListWidgetItem сохраняет только один текст, поэтому для сохранения старого текста должна использоваться другая роль.С этой логикой я реализовал следующее решение:

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_())
0 голосов
/ 05 июня 2019

Я не совсем уверен, что вы планируете делать.Я предлагаю изменить методы активации, например:

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
...