Issues with Importing and Calling JavaScript Functions in Qt WebEngineView from Python

44 Views Asked by At

Problem Description:

I found this example in this post which there is a QWebEngineView in Python (main.py) that loads an HTML file (init.html) with embedded JavaScript files (utils.js and main.js). I want to import functions from utils.js into main.js and vice versa. Additionally, I need to be able to call JavaScript functions from the Python side.

The problem arises when importing something from utils.js to main.js; I can't call any functions in main.js from the Python side. I'll get Uncaught ReferenceError: main is not defined error when calling main function in main.js from python.

main.py:

import sys
from os.path import dirname
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineCore import *
from PyQt5.QtWebEngineWidgets import *


application_path = (dirname(sys.executable) if getattr(sys, "frozen", False) else dirname(__file__))


class QtSchemeHandler(QWebEngineUrlSchemeHandler):
    def requestStarted(self, job):
        request_method = job.requestMethod()
        if request_method != b"GET":
            job.fail(QWebEngineUrlRequestJob.RequestDenied)
            return

        request_url = job.requestUrl()
        request_path = request_url.path()
        file = QFile(application_path + request_path)
        file.setParent(job)
        job.destroyed.connect(file.deleteLater)
        if not file.exists() or file.size() == 0:
            print(f"resource '{request_path}' not found or is empty")
            job.fail(QWebEngineUrlRequestJob.UrlNotFound)
            return

        file_info = QFileInfo(file)
        mime_database = QMimeDatabase()
        mime_type = mime_database.mimeTypeForFile(file_info)
        job.reply(mime_type.name().encode(), file)



class WebEnginePage(QWebEnginePage):
    def javaScriptConsoleMessage(self, level, message, lineNumber, sourceID):
        print(f"[JS Message] Line-{lineNumber}:", message)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()
        self.browser.setPage(WebEnginePage(self.browser))
        self.scheme_handler = QtSchemeHandler()
        self.browser.page().profile().installUrlSchemeHandler(b"qt", self.scheme_handler)
        url = QUrl("qt://main")
        url.setPath("/data_files/init.html")
        self.browser.load(url)
        self.setCentralWidget(self.browser)
        self.browser.loadFinished.connect(self.onLoad)

    def onLoad(self):
        self.browser.page().runJavaScript('main()')



if __name__ == "__main__":
    scheme = QWebEngineUrlScheme(b"qt")
    scheme.setFlags(QWebEngineUrlScheme.CorsEnabled)
    QWebEngineUrlScheme.registerScheme(scheme)
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

main.js:

import { sayHello } from "./utils.js"

function main(){
    console.log('main')
}

sayHello();

utils.js:

export function sayHello() {
    console.log('Message from utils.js');
}

init.html:

<body>
    <!-- <script src="js/utils.js" type="module"></script> -->
    <script src="js/main.js"></script>
    <h1>Hello World</h1>
</body>

If I uncomment the second line in init.html (importing utils.js directly), the problem is solved, but it requires importing all files in one place, which is not ideal.

What should I do to be able to import functions from utils.js into main.js and vice versa while being able to call JavaScript functions from the Python side?

Project Structure:

├── data_files
│   ├── init.html
│   └── js
│       ├── main.js
│       └── utils.js
└── main.py
0

There are 0 best solutions below