This question sounds familiar.
First I would ask myself why do I have two line edit boxes that are interrelated.
Assuming this is a good idea in your case, when do you want to "sync" the entries? While typing? When the control loses focus? When enter is pressed?
I found QLineEdit lacking and added the concept of "accept". I wanted to ignore typing and only sent a notification when the enter key was pressed or if the QLineEdit lost focus. When this happens my modified QLineEdit emits a valuechanged signal.
class LineEdit(QLineEdit):
"""QLineEdit with revert on focus out and valuechanged signal.
valuechanged differs from textChanged in that the value does
not change until the enter/return key is pressed. If I lose
focus before enter/return is pressed I perform the selected
revert action
"""
# Instance variables
revert: bool # Action taken when control loses focus
_value: str # Accepted text
# This acts like an ivar but must be declared here. Why?
valuechanged = Signal(str)
def __init__(self, *args, revert=True, **kv_args):
super().__init__(*args, **kv_args)
self._value = ''
self.revert = revert
def event(self, ev):
"""Override QLineEdit event method.
Intercept tab key press. When tab pressed accept the text and
navigate to the next control. Also capture return key pressed
since processing is the same as tab key. Capture focus out
event and revert to last accepted text
"""
if ev.type() == QEvent.KeyPress:
if ev.key() in (int(Qt.Key_Tab), int(Qt.Key_Return)):
self._accepttext()
elif ev.type() == QEvent.FocusOut:
self._focusout()
return super().event(ev)
def _focusout(self):
"""Called when control loses focus. Based on revert mode
either revert the last accepted text, or treat as if return
was pressed"""
if self._value != self.text():
if self.revert:
self.setText(self._value)
else:
self._accepttext()
def _accepttext(self):
"""Called when changed text is accepted. Emit valuechanged signal"""
self._value = self.text()
self.valuechanged.emit(self._value)
def clear(self):
"""Set to no display"""
self.value = ''
@property
def value(self):
"""Accepted text"""
return self._value
@value.setter
def value(self, value):
self._value = value
self.setText(value)
Once you how notification should work, it comes down to either using one of the available signals, or subclassing QLineEdit to act the way you want. Eventually you will call a function that updates the controls. Depending on how they are related this may be the same function for both, or separate functions for each. You will have to implement some kind of lock to prevent the A callback changing B from calling the B callback. For this I use a common variable in the callback functions.
def a_changed()
if not lockedout
lockedout = True
# set value of B
lockedout = False
def b_changed()
if not lockedout
lockedout = True
# set value of A
lockedout = False