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