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
在我的应用程序中,我使用 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"
时没有任何反应,我的元素的不透明度没有改变。
如果您
你的情况是:
您也可以检查
解释:
正如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