Двустороннее связывание данных с виджетом QScintilla и пользовательской моделью - PullRequest
0 голосов
/ 29 апреля 2020

Я использую виджет QScintilla в качестве редактора кода, и я хотел бы синхронизировать c с пользовательским EditorModel. Вот двусторонняя привязка, которая работает, когда модель обновляется каждый раз, когда вводится новый символ:

class EditorModel(QObject):
    code_changed = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self._code = ""

    @pyqtProperty(str, notify=code_changed)
    def code(self):
        return self._code

    @code.setter
    def code(self, code):
        if self._code != code:
            self._code = code
            self.code_changed.emit(code)

class Editor(Qsci.QsciScintilla):
    def __init__(self, parent=None):
        ...
        self.textChanged.connect(lambda : self.model.code = self.text())
        self.model.code_changed.connect(self.on_code_changed)
        ...

    @QtCore.pyqtSlot(str)
    def on_code_changed(self, code):
        if code != self.text():
            self.setText(code)

Но производительность очень низкая, когда текст длинный.

Единственный Компромисс, который я нашел, заключается в обновлении модели только в геттере:

class EditorModel(QObject):
    code_changed = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self._code = ""
        self._code_updater = None

    def set_code_updater(self, func):
        self._code_updater = func

    @pyqtProperty(str, notify=code_changed)
    def code(self):
        if self._code_updater is not None:
            self._code = self._code_updater()
        return self._code

    @code.setter
    def code(self, code):
        if self._code != code:
            self._code = code
            self.code_changed.emit(code)

class Editor(Qsci.QsciScintilla):
    def __init__(self, parent=None):
        ...
        self.model.set_code_updater(self.text) # no more textChanged.connect
        self.model.code_changed.connect(self.on_code_changed)
        ...

    @QtCore.pyqtSlot(str)
    def on_code_changed(self, code):
        if code != self.text():
            self.setText(code)

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

...