PyQt4: объединить textChanged и editFinished для QLineEdit

Есть ли способ объединить textChanged и editingFinished для QLineEdit? Проблема в том, что editingFinished испускается, даже если я перемещаю курсор только от QLineEdit без каких-либо изменений. В то время как я хочу излучать сигнал только тогда, когда любые изменения были выполнены после того, как я закончил редактирование.

Я могу представить только, чтобы хранить где-то текущий текст, сравнивать введенный текст с ним и делать что-то, только если он отличается. Но мне интересно, есть ли какое-либо решение, чисто основанное на обработке сигналов.

EDIT: В конце концов мне пришлось сохранить текущий текст и сравнить его с новым текстом, а не следовать предлагаемому решению. Я понял, что в моем приложении "1.2345" и "1.23" будет тот же текст, но, тем не менее, я должен обновить некоторые другие значения в этом случае и так далее. Я очень ценю подробный ответ и комментарии от @Avaris и @ekhumoro, и соглашусь с ним, поскольку он, кажется, разрешает первоначально опубликованную проблему.

Ответ 1

Edit

Для внесения изменений вручную:

class MyLineEdit(QtGui.QLineEdit):
    textModified = QtCore.pyqtSignal(str, str) # (before, after)

    def __init__(self, contents='', parent=None):
        super(MyLineEdit, self).__init__(contents, parent)
        self.returnPressed.connect(self.checkText)
        self._before = contents

    def focusInEvent(self, event):
        if event.reason() != QtCore.Qt.PopupFocusReason:
            self._before = self.text()
        super(MyLineEdit, self).focusInEvent(event)

    def focusOutEvent(self, event):
        if event.reason() != QtCore.Qt.PopupFocusReason:
            self.checkText()
        super(MyLineEdit, self).focusOutEvent(event)

    def checkText(self):
        if self._before != self.text():
            self._before = self.text()
            self.textModified.emit(self._before, self.text())

Изменить 2

Для всех изменений (программных и ручных):

class MyLineEdit(QtGui.QLineEdit):
    textModified = QtCore.pyqtSignal(str, str) # (before, after)

    def __init__(self, contents='', parent=None):
        super(MyLineEdit, self).__init__(contents, parent)
        self.editingFinished.connect(self.checkText)
        self.textChanged.connect(lambda: self.checkText())
        self.returnPressed.connect(lambda: self.checkText(True))
        self._before = contents

    def checkText(self, _return=False):
        if (not self.hasFocus() or _return) and self._before != self.text():
            self._before = self.text()
            self.textModified.emit(self._before, self.text())

Изменить 3

Для захвата пользователем только текстовых изменений:

class MyLineEdit(QtGui.QLineEdit):
    textModified = QtCore.pyqtSignal(str, str) # (before, after)

    def __init__(self, contents='', parent=None):
        super(MyLineEdit, self).__init__(contents, parent)
        self.editingFinished.connect(self.__handleEditingFinished)
        self.textChanged.connect(self.__handleTextChanged)
        self._before = contents

    def __handleTextChanged(self, text):
        if not self.hasFocus():
            self._before = text

    def __handleEditingFinished(self):
        before, after = self._before, self.text()
        if before != after:
            self._before = after
            self.textModified.emit(before, after)

Ответ 2

Если вы просто хотите определить, были ли сделаны какие-либо изменения (в отличие от того, отличается ли текст от того, как он был запущен), вы можете использовать modified свойство QLineEdit с сигналом editingFinished:

    self.edit = QtGui.QLineEdit(self)
    self.edit.editingFinished.connect(self.handleEditingFinished)
    ...

def handleEditingFinished(self):
    if self.edit.isModified():
        # do interesting stuff ...
        print 'Editing Finished'
    self.edit.setModified(False)