I'm building a browser using PyQt5. It's a rather huge code, but this is the main problem I'm facing. The code is this:
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QMainWindow
app = QApplication(sys.argv)
web = QWebEngineView()
file = open("example.html", "r")
html = file.read()
web.setHtml(html)
file.close()
web.show()
sys.exit(app.exec_())
The problem is that the rendering is rather strange.Image of the rendering is here.
The contents of the example.html file:
<!DOCTYPE html>
<head><title>JS Example</title></head>
<h1>JS example</h1>
<p><button type = 'button' onclick = "document.getElementById('tobeshown').style.display='block'">Show hidden parts of this page</button></p>
<p id = 'tobeshown' style = "display:none">
Peekaboo!
</p>
<p>
<button type = 'button' onclick="document.getElementById('tobeshown').style.display='none'">Hide it!</button>
</p>
</body>
</html>
The expected output(this is in Mozilla Firefox browser): here
Can anyone tell me why the PyQt5 rendering engine produces those symbols at the top? And what can I do to resolve it? Thank you very much.
So the problem is not WebEngine's rendering but instead Python's reading of a file. Changing the file's encoding to UTF-8 solved the problem for me.
Related
Following this post and the mathjax 3 documentation, I am trying to render a simple html with Mathjax content in PyQt5 using a local copy of the mathjax repo.
The main directory contains the notebook from which the following code is executed, a "mathjax" folder containing the content of the repo (especially the es5 folder). Notice that I tried with 2 paths to the js (comment toward the top) :
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtCore import QUrl
import os
# <script type="text/javascript" src="file:///Users/mocquin/.../mathjax/es5/tex-chtml-full.js">
pageSource = """
<html><head>
<script type="text/javascript" src="./mathjax/es5/tex-chtml-full.js">
</script></head>
<body>
<p><mathjax style="font-size:2.3em">$$u = \int_{-\infty}^{\infty}(awesome)\cdot du$$</mathjax></p>
</body></html>
"""
app = QApplication(sys.argv)
webView = QWebEngineView()
webView.setHtml(pageSource, baseUrl=QUrl(os.path.abspath('')))
webView.show()
sys.exit(app.exec_())
But this only renders the content without the "latex parsing"
What am I missing so that the mathjax is indeed linked to the html ?
The problem with your example is that you aren't using the correct format for the src path and base url. The src path must be a plain relative path, and the base url should be a backslash-terminated absolute path to the directory containing the mathjax directory.
Assuming the mathjax directory is in the same directory as the python script, the following should work correctly (at least, it does for me):
import sys, os
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
pageSource = """
<html><head>
<script type="text/javascript" async src="mathjax/es5/tex-chtml-full.js"></script>
</head><body>
<p><mathjax style="font-size:2.3em">$$u = \int_{-\infty}^{\infty}(awesome)\cdot du$$</mathjax></p>
</body></html>
"""
baseurl = QUrl.fromLocalFile(os.path.dirname(os.path.abspath(__file__)) + '/')
print(f'BASEURL: {baseurl.toString()!r}') # BASEURL: 'file:///home/tmp/test/'
app = QApplication(sys.argv)
webView = QWebEngineView()
webView.setHtml(pageSource, baseUrl=baseurl)
webView.show()
sys.exit(app.exec_())
I wrote a python test program like this to show openstreetmap:
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
import sys
def mainPyQt5():
url = 'file:///./index.html'
app = QApplication(sys.argv)
browser = QWebEngineView()
browser.load(QUrl(url))
browser.show()
sys.exit(app.exec_())
mainPyQt5()
index.html fetched by QWebEngineView simply calls openstreetmap:
<title>OSM and Leaflet</title>
<link rel = "stylesheet" href = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css"/>
<div id = "map" style = "width: 900px; height: 580px"></div><script src = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<script>
// Creating map options
var mapOptions = {
center: [45.641174, 9.114828],
zoom: 10
}
// Creating a map object
var map = new L.map('map', mapOptions);
// Creating a Layer object
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
// Adding layer to the map
map.addLayer(layer);
</script>
If I fetch index.html with a ordinary browser the map is shown as expected but if I call the simple python program using QWebEngineView no tiles are downloaded from openstreetmap. If I replace openstreetmap with maps.stamen.com everything is fine both with a browser or the python script.
By default QtWebEngine does not set default headers like popular browsers do. In this case the openstreetmap server needs to know the "Accept-Language" to produce the maps since for example the names of the cities will depend on the language to filter non-browser traffic. The solution is to implement a QWebEngineUrlRequestInterceptor that adds that header:
import os.path
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Interceptor(QWebEngineUrlRequestInterceptor):
def interceptRequest(self, info):
info.setHttpHeader(b"Accept-Language", b"en-US,en;q=0.9,es;q=0.8,de;q=0.7")
def mainPyQt5():
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
filename = os.path.join(CURRENT_DIR, "index.html")
app = QApplication(sys.argv)
browser = QWebEngineView()
interceptor = Interceptor()
browser.page().profile().setUrlRequestInterceptor(interceptor)
browser.load(QUrl.fromLocalFile(filename))
browser.show()
sys.exit(app.exec_())
if __name__ == "__main__":
mainPyQt5()
I am trying to display a video file inside a PySide2 app I'm writing. That app uses a QWebEngineView and loads a local html file that contains a <video> tag, pointing to a local mov or mp4 file. Somehow I can see the player, but it doesn't load the file.
I've put this little html test page together which loads fine in Chrome, but not in my app. Note that in this file I'm using an online mp4 file, but I've tried both, local and online files, mov and mp4.
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<video width="320" height="240" controls>
<source src="https://archive.org/download/VideoTestFiles/1280X72025FpsPhotoJpeg75.mp4" type="video/mp4" >
</video>
</body>
In my PySide2 app, I'm loading the page like follows:
import os, sys
from PySide2 import QtWidgets
from PySide2.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
from PySide2.QtCore import QUrl
app = QtWidgets.QApplication(sys.argv)
view = QWebEngineView()
path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "test.html")
view.load(QUrl.fromLocalFile(path))
view.show()
sys.exit(app.exec_())
I have also tried the following settings, none of which seem to help:
view.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)
view.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
view.settings().setAttribute(QWebEngineSettings.AllowRunningInsecureContent, True)
view.settings().setAttribute(QWebEngineSettings.LocalContentCanAccessFileUrls, True)
view.settings().setAttribute(QWebEngineSettings.LocalContentCanAccessRemoteUrls, True)
Any help appreciated!
Edit:
I just realized: while there is no error in Chrome console, there is an error being displayed in the Python console after closing the app:
[9476:13164:1017/182854.157:ERROR:media_internals.cc(102)] Cannot get RenderProcessHost
Python 3.6 PYQT 5.12.1
I am ready to show the style I need by pyqt5 and I knew that the QTextEdit in pyqt5 can display the html code pretty good (I have some experience in web development), so I decided to use html/css to show my style . However , it may have some problem in showing the code in css . What can I do to let it can show the css/javascript ? If it can‘t , can recommend other methods to modify the style?
It can show some style like width = "100" height = "100" when I code it in the html but not css and some can't display like border-radius:50%;. It won't get any effect when I code the style in css . By the way , I've imported CSS code.
The CSS code do nothing in QTextEdit (but it is ok in html)
.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class WINDOW(QMainWindow):
def __init__(self):
super().__init__()
self.init()
def init(self):
w_width,w_height,w_x,w_y = 700,640,700,200
self.set_size_pos(w_width,w_height,w_x,w_y);
self.set_message_textedit()
self.message_textedit.setHtml(self.get_html())
self.show()
def set_size_pos(self,width,height,x,y):
'''
set window's width , height and position
'''
self.resize(width,height)
self.move(x,y)
def set_message_textedit(self):
self.message_textedit = QTextEdit(self)
self.message_textedit.setFont(QFont("Microsoft YaHei",12))
self.message_textedit.resize(680,420)
self.message_textedit.move(10,50)
self.message_textedit.setReadOnly(True)
def get_html(self):
html = ""
with open("./chat-style/chat.html","r",encoding = "utf-8") as f:
html = f.read()
return html
if __name__ == '__main__':
app = QApplication(sys.argv)
test = WINDOW()
sys.exit(app.exec_())
.html
<!doctype html>
<html lange="zh-CN">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="./chat.css">
<script src = "chat.js"></script>
</head>
<body>
<img class = "tx" src="E:\study\assiataant\picture\icon.jpg">
<div>Welcome ~ Don!</div>
</body>
</html>
.css
.tx
{
border-radius:50%;
width: 30;
height: 30;
}
QTextEdit only supports CSS 2.1 as indicated by the docs:
All CSS 2.1 selector classes are supported except pseudo-class selectors such as :first-child, :visited and :hover.
But border-radius was introduced in CSS3. So you can not use it unfortunately. I recommend you read the following link so that you know the allowed tags.
Another alternative is to use QWebEngineView that supports these tags:
*.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
view = QtWebEngineWidgets.QWebEngineView()
file = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"chat-style/chat.html"
)
view.load(QtCore.QUrl.fromLocalFile(file))
self.setCentralWidget(view)
self.resize(640, 480)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
If you do not have QWebEngineView installed, you must install it with the following command:
python -m pip install PyQtWebEngine
I'm trying to open a simple html file (something like this)
<html>
<body>
<h1>hello</h1>
</body>
</html>
which does not have any embedded or external JavaScript, inside QtWebEngine using this code
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
class Browser(QWebEngineView):
def __init__(self):
self.view = QWebEngineView.__init__(self)
self.setWindowTitle("Loading ...")
self.titleChanged.connect(self.adjustTitle)
def adjustTitle(self):
self.setWindowTitle(self.title())
if __name__ == "__main__":
app = QApplication(sys.argv)
view = Browser()
view.showMaximized()
url = QUrl.fromLocalFile("simple.html")
view.setUrl(url)
sys.exit(app.exec_())
But when i run it the following error appears in the console
js: Uncaught ReferenceError: jstProcess is not defined
What is jstProcess and how can i define it? (The code works fine if I load some remote resource like bing.com)
Your eg works for me
if give a fully qualified file name for simple as
'/home/me/simple.htm' . Or if simple.htm is in same directory
where I am running the python I do
import sys,os
fname = os.getcwd()+ '/simple.html'
url = QUrl.fromLocalFile(fname)
This is with the pyqt that comes with Debian that I am running
under python 2.