PyQt5 如何使用 JavaScript 个模块

PyQt5 How To Use JavaScript Modules

在我的应用程序中,我使用 PyQt5 创建了一个 window 并加载了一个 HTML 源。我想在需要使用 JavaScript 模块的项目中使用 ThreeJS。但是我似乎没有让模块在我的设置中工作:

这很好用:<script src="js/main.js"></script>

这不是:<script type="module" src="js/main.js"></script>

这里有什么问题?我是否需要在 PyQt5 中做一些额外的事情来启用 JavaScript 模块。

没有JavaScript模块,ThreeJS很难用,请问如何解决?

编辑:这是我正在使用的 PyQt5 代码:

import sys
import os
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import *

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()
        config_name = 'data_files/init.html'
        if getattr(sys, 'frozen', False):
            application_path = os.path.dirname(sys.executable)
        elif __file__:
            application_path = os.path.dirname(__file__)
        config_path = os.path.join(application_path, config_name)
        self.browser.load(QUrl().fromLocalFile(config_path))
        self.setCentralWidget(self.browser)
        self.showMaximized()


app = QApplication(sys.argv)
QApplication.setApplicationName('v0.1')
window = MainWindow()
app.exec_()

这是html:

<body>
    <script src="js/main.js"></script>
    <div id="myText" style="opacity:0">Hello World</div>
</body>¨

这是javaScript:

window.addEventListener("load", () => {
    document.getElementById("myText").style.opacity = "1"
})

JavaScript 仅在脚本不是模块时有效,当使用 type="module" 时没有任何反应,我的元素的不透明度没有改变。

如果您 到您的项目,您会看到 JavaScript 个错误..

你的情况是:

您也可以检查 您的问题。

解释:

正如the docs指出的那样:

You need to pay attention to local testing — if you try to load the HTML file locally (i.e. with a file:// URL), you'll run into CORS errors due to JavaScript module security requirements. You need to do your testing through a server.

如果您使用本地文件,则无法访问这些模块,因此您会收到错误消息:

js: Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

解决方案:

在这种情况下有 2 个选项:

1。本地服务器

实现服务器,例如使用 aiohttp + qasync:

import asyncio
import functools
import os
from pathlib import Path
import sys

from aiohttp import web

from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWebEngineWidgets import QWebEngineView

import qasync
from qasync import QApplication


application_path = (
    Path(sys.executable).resolve().parent
    if getattr(sys, "frozen", False)
    else Path(__file__).resolve().parent
)


class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()

        config_name = "/data_files/init.html"
        url = QUrl("http://localhost:4000")
        url.setPath(config_name)
        self.browser.load(url)
        self.setCentralWidget(self.browser)
        self.showMaximized()


async def main():
    def close_future(future, loop):
        loop.call_later(10, future.cancel)
        future.cancel()

    loop = asyncio.get_event_loop()
    future = asyncio.Future()

    qt_app = QApplication.instance()
    if hasattr(qt_app, "aboutToQuit"):
        getattr(qt_app, "aboutToQuit").connect(
            functools.partial(close_future, future, loop)
        )

    app = web.Application()
    app.router.add_static("/", application_path, show_index=True)
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, "localhost", 4000)
    await site.start()

    view = MainWindow()
    view.show()

    await future
    await runner.cleanup()
    return True


if __name__ == "__main__":
    try:
        qasync.run(main())
    except asyncio.exceptions.CancelledError:
        sys.exit(0)

2。自定义 QWebEngineUrlSchemeHandler

import sys
import os
from PyQt5.QtCore import QCoreApplication, QUrl, QFile, QFileInfo, QMimeDatabase
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtWebEngineCore import (
    QWebEngineUrlScheme,
    QWebEngineUrlSchemeHandler,
    QWebEngineUrlRequestJob,
)
from PyQt5.QtWebEngineWidgets import QWebEngineView


application_path = (
    os.path.dirname(sys.executable)
    if getattr(sys, "frozen", False)
    else os.path.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 MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.browser = QWebEngineView()
        self.scheme_handler = QtSchemeHandler()
        self.browser.page().profile().installUrlSchemeHandler(
            b"qt", self.scheme_handler
        )
        filename = "/data_files/init.html"
        url = QUrl("qt://main")
        url.setPath(filename)
        self.browser.load(url)
        self.setCentralWidget(self.browser)


if __name__ == "__main__":

    scheme = QWebEngineUrlScheme(b"qt")
    scheme.setFlags(QWebEngineUrlScheme.CorsEnabled)
    QWebEngineUrlScheme.registerScheme(scheme)
    app = QApplication(sys.argv)
    QApplication.setApplicationName("v0.1")
    window = MainWindow()
    window.show()
    app.exec_()

文件结构:

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