代码之家  ›  专栏  ›  技术社区  ›  dukeeloo

防止在程序化文本更新后从QLineEdit编辑已完成的信号

  •  0
  • dukeeloo  · 技术社区  · 7 月前

    我在PyQt6中使用QLineEdit。我需要以编程方式设置文本,而不触发 editingFinished 信号。 正如预期的那样, 编辑已完成 不是由以下因素直接触发的 setText . 然而,它使QLineEdit处于以下状态: 编辑已完成 当小部件稍后获得和失去焦点时触发,即使在此期间没有其他文本更改。 如果QLineEdit第二次获得和失去焦点(没有文本更改) 编辑已完成 未被触发。 我正在寻找一种方法,将QLineEdit置于第一次失焦后的状态,但不会触发 编辑已完成 . 使用 blockSignals(True) 虽然以编程方式设置文本不起作用,因为稍后小部件失去焦点时仍会发出信号。 尝试使用重置内部状态 setModified(False) 似乎也不是正确的选择。 对QLineEdit进行子分类,并使用标志以不同的方式处理程序和用户更改可能会奏效,但与仅在QLineEdit忘记textChange(如果是通过程序完成的)时恢复状态相比,这似乎是不必要和复杂的。

    我如何才能可靠地抑制 编辑已完成 在程序化文本更新后发出信号,同时保持用户编辑的正常行为?

    下面是一个示例:要再现不希望的行为,请单击setTextButton,然后单击QLineEdit,然后单击QSpinBox,使QLineEdit失去焦点。

    import sys
    from PyQt6.QtWidgets import QApplication,QWidget,QVBoxLayout,QPushButton,QLineEdit,QSpinBox
    
    class Foo(QWidget):
    
        def __init__(self):
            super().__init__()
            lay = QVBoxLayout(self)  
            
            self.s=QSpinBox()
            self.s.setValue(0)
            lay.addWidget(self.s)
            self.le=QLineEdit('text')
            self.le.editingFinished.connect(self.editingFinished)
            lay.addWidget(self.le)
            b=QPushButton('setText')
            b.clicked.connect(self.clicked)
            lay.addWidget(b)
            
        def editingFinished(self):
            # increment spinBox to show that editingFinished has been called
            self.s.setValue(self.s.value()+1)
            
        def clicked(self):
            # set text programmatically
            # triggers textChanged but not editingFinished
            self.le.setText(self.le.text()+'+') # editingFinished will called later if the control gains and looses focus, even without any additional text changes!
            # self.le.setModified(False)
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mainWindow = Foo()
        mainWindow.show()
        sys.exit(app.exec())
    
    1 回复  |  直到 7 月前
        1
  •  1
  •   mugiseyebrows    7 月前

    您可以使用 QLineEdit.textEdited 处理来自用户的文本更改的信号,但它是在每次按键时发出的,而不是在失去焦点时发出的。在失去焦点的情况下,您可以存储编辑状态并在稍后使用它 editingFinished 处理程序。

    import sys
    from PyQt6.QtWidgets import QApplication,QWidget,QVBoxLayout,QPushButton,QLineEdit,QSpinBox
    from PyQt6.QtCore import pyqtSignal
    
    class LineEdit(QLineEdit):
        userEditingFinished = pyqtSignal(str)
    
        def __init__(self, parent = None):
            super().__init__(parent)
            self._edited = False
            self.editingFinished.connect(self.onEditingFinished)
            self.textEdited.connect(self.onTextEdited)
    
        def onTextEdited(self):
            self._edited = True
    
        def onEditingFinished(self):
            if self._edited:
                self.userEditingFinished.emit(self.text())
            self._edited = False
    
    class Foo(QWidget):
    
        def __init__(self):
            super().__init__()
            layout = QVBoxLayout(self)  
            
            self.spinBox = QSpinBox()
            self.spinBox.setValue(0)
            layout.addWidget(self.spinBox)
            self.lineEdit = LineEdit('text')
            self.lineEdit.userEditingFinished.connect(self.onUserEditingFinished)
    
            layout.addWidget(self.lineEdit)
            button = QPushButton('setText')
            button.clicked.connect(self.onButtonClicked)
            layout.addWidget(button)
            
        def onUserEditingFinished(self, text):
            self.spinBox.setValue(self.spinBox.value()+1)
            
        def onButtonClicked(self):
            self.lineEdit.setText(self.lineEdit.text()+'+')
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mainWindow = Foo()
        mainWindow.show()
        sys.exit(app.exec())