Отличное решение! Спасибо!

тоящее время я ищу способ создания настольных приложений с графическим интерфейсом на Python и HTML / CSS / JS с использованием PyQt5QWebEngineView.

В моем небольшом демонстрационном приложении я используюQWebChannel опубликовать PythonQObject на стороне JavaScript, так что данные могут быть переданы и передавать туда и обратно. Совместное использование и подключение слотов и сигналов пока работает нормально.

У меня трудности, хотя с синхронизацией простых (свойства) значений. Из того, что я прочитал, путь заключается в том, чтобы реализовать pyqtProperty в совместно используемом объекте QObject с помощью декорированных функций получения и установки с дополнительным сигналом, генерируемым в установщике, который используется для уведомления JavaScript при изменении значения. Код ниже показывает, что и до сих пор это работает нормально:

import sys
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal 
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage


class HelloWorldHtmlApp(QWebEngineView):
    html = '''
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8"/>        
        <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
        <script>
        var backend;
        new QWebChannel(qt.webChannelTransport, function (channel) {
            backend = channel.objects.backend;
        });
        </script>
    </head>
    <body> <h2>HTML loaded.</h2> </body>
    </html>
    '''

    def __init__(self):
        super().__init__()

        # setup a page with my html
        my_page = QWebEnginePage(self)
        my_page.setHtml(self.html)
        self.setPage(my_page)

        # setup channel
        self.channel = QWebChannel()
        self.backend = self.Backend(self)
        self.channel.registerObject('backend', self.backend)
        self.page().setWebChannel(self.channel)

    class Backend(QObject):
        """ Container for stuff visible to the JavaScript side. """
        foo_changed = pyqtSignal(str)

        def __init__(self, htmlapp):
            super().__init__()
            self.htmlapp = htmlapp
            self._foo = "Hello World"

        @pyqtSlot()
        def debug(self):
            self.foo = "I modified foo!"

        @pyqtProperty(str, notify=foo_changed)
        def foo(self):            
            return self._foo

        @foo.setter
        def foo(self, new_foo):            
            self._foo = new_foo
            self.foo_changed.emit(new_foo)


if __name__ == "__main__":
    app = QApplication.instance() or QApplication(sys.argv)
    view = HelloWorldHtmlApp()
    view.show()
    app.exec_()

Начиная это с подключенным отладчиком, я могу вызватьbackend.debug() слот в консоли JavaScript, что приводит к значениюbackend.foo будучи "я изменил Foo!" впоследствии это означает, что код Python успешно изменил переменную JavaScript.

Это довольно утомительно, хотя. Для каждого значения, которым я хотел бы поделиться, я должен был бы

создать внутреннюю переменную (здесьself._foo)создать функцию получениясоздать функцию установкисоздать сигнал вQObjectтелоиспускать этот сигнал явно в функции установщика

Есть ли более простой способ добиться этого? В идеале какое-то однострочное объявление? Может быть, с помощью класса или функции, чтобы упаковать все это? Как бы мне связать это сQObject позже? Я думаю о чем-то вроде

# in __init__
self.foo = SyncedProperty(str)

Это возможно? Спасибо за ваши идеи!

Ответы на вопрос(1)

Ваш ответ на вопрос