使用 PyQt5 渲染 Markdown
Render Markdown with PyQt5
如何在我的 PyQt5 应用程序中呈现降价文件?
Here 我读到我应该使用 QWebEngineView 而不是 QTextEdit,因为 QTextEdit 无法呈现外部图像。
有人在评论中引用了 this 示例。然而,它是一个完整的 Markdown 文本编辑器,并且另外用 C++ 编写。我试图将需要的部分翻译成 Python 但我不太明白它是如何工作的。我只需要一个最小的例子。
我现在拥有的是:
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
import sys
app = QApplication(sys.argv)
web_widget = QWebEngineView()
webChannel = QWebChannel() # ?
page = QWebEnginePage() # ?
web_widget.setPage(page) # ?
my_url = QUrl("/index.html")
web_widget.load(my_url)
# now somehow replace the placeholder in the loaded html page with file contents?
file_url = QUrl("file.md")
# help
web_widget.show()
app.exec_()
QTextEdit 自 Qt 5.14 以来可以呈现降价,但正如 OP 指出的那样,它有一个限制:它无法呈现远程图像。因此,另一种方法是使用 QWebEngineView + js 库,如 markdown.js 和 marked.js,如官方示例所示。您还可以使用 QNetworkAccessManager 下载远程.md 文件。
import os.path
import sys
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTextCodec, QUrl
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtWidgets import QApplication
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class Document(QObject):
textChanged = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.m_text = ""
def get_text(self):
return self.m_text
def set_text(self, text):
if self.m_text == text:
return
self.m_text = text
self.textChanged.emit(self.m_text)
text = pyqtProperty(str, fget=get_text, fset=set_text, notify=textChanged)
class DownloadManager(QObject):
finished = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._manager = QNetworkAccessManager()
self.manager.finished.connect(self.handle_finished)
@property
def manager(self):
return self._manager
def start_download(self, url):
self.manager.get(QNetworkRequest(url))
def handle_finished(self, reply):
if reply.error() != QNetworkReply.NoError:
print("error: ", reply.errorString())
return
codec = QTextCodec.codecForName("UTF-8")
raw_data = codec.toUnicode(reply.readAll())
self.finished.emit(raw_data)
def main():
app = QApplication(sys.argv)
filename = os.path.join(CURRENT_DIR, "index.html")
document = Document()
download_manager = DownloadManager()
channel = QWebChannel()
channel.registerObject("content", document)
# remote file
markdown_url = QUrl.fromUserInput(
"https://raw.githubusercontent.com/eyllanesc/Whosebug/master/README.md"
)
# local file
# markdown_url = QUrl.fromUserInput(/path/of/markdown.md)
download_manager.finished.connect(document.set_text)
download_manager.start_download(markdown_url)
view = QWebEngineView()
view.page().setWebChannel(channel)
url = QUrl.fromLocalFile(filename)
view.load(url)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
index.html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="3rdparty/markdown.css">
<script src="3rdparty/marked.js"></script>
<script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
<script>
'use strict';
var placeholder = document.getElementById('placeholder');
var updateText = function(text) {
placeholder.innerHTML = marked(text);
}
new QWebChannel(qt.webChannelTransport,
function(channel) {
var content = channel.objects.content;
updateText(content.text);
content.textChanged.connect(updateText);
}
);
</script>
</body>
</html>
├── 3rdparty
│ ├── markdown.css
│ ├── MARKDOWN-LICENSE.txt
│ ├── marked.js
│ ├── MARKED-LICENSE.txt
│ └── qt_attribution.json
├── index.html
└── main.py
注意:3rdparty文件夹中的文件在the official Qt repository.
如何在我的 PyQt5 应用程序中呈现降价文件?
Here 我读到我应该使用 QWebEngineView 而不是 QTextEdit,因为 QTextEdit 无法呈现外部图像。
有人在评论中引用了 this 示例。然而,它是一个完整的 Markdown 文本编辑器,并且另外用 C++ 编写。我试图将需要的部分翻译成 Python 但我不太明白它是如何工作的。我只需要一个最小的例子。
我现在拥有的是:
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
import sys
app = QApplication(sys.argv)
web_widget = QWebEngineView()
webChannel = QWebChannel() # ?
page = QWebEnginePage() # ?
web_widget.setPage(page) # ?
my_url = QUrl("/index.html")
web_widget.load(my_url)
# now somehow replace the placeholder in the loaded html page with file contents?
file_url = QUrl("file.md")
# help
web_widget.show()
app.exec_()
QTextEdit 自 Qt 5.14 以来可以呈现降价,但正如 OP 指出的那样,它有一个限制:它无法呈现远程图像。因此,另一种方法是使用 QWebEngineView + js 库,如 markdown.js 和 marked.js,如官方示例所示。您还可以使用 QNetworkAccessManager 下载远程.md 文件。
import os.path
import sys
from PyQt5.QtCore import pyqtProperty, pyqtSignal, QObject, QTextCodec, QUrl
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QNetworkRequest
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PyQt5.QtWidgets import QApplication
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class Document(QObject):
textChanged = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self.m_text = ""
def get_text(self):
return self.m_text
def set_text(self, text):
if self.m_text == text:
return
self.m_text = text
self.textChanged.emit(self.m_text)
text = pyqtProperty(str, fget=get_text, fset=set_text, notify=textChanged)
class DownloadManager(QObject):
finished = pyqtSignal(str)
def __init__(self, parent=None):
super().__init__(parent)
self._manager = QNetworkAccessManager()
self.manager.finished.connect(self.handle_finished)
@property
def manager(self):
return self._manager
def start_download(self, url):
self.manager.get(QNetworkRequest(url))
def handle_finished(self, reply):
if reply.error() != QNetworkReply.NoError:
print("error: ", reply.errorString())
return
codec = QTextCodec.codecForName("UTF-8")
raw_data = codec.toUnicode(reply.readAll())
self.finished.emit(raw_data)
def main():
app = QApplication(sys.argv)
filename = os.path.join(CURRENT_DIR, "index.html")
document = Document()
download_manager = DownloadManager()
channel = QWebChannel()
channel.registerObject("content", document)
# remote file
markdown_url = QUrl.fromUserInput(
"https://raw.githubusercontent.com/eyllanesc/Whosebug/master/README.md"
)
# local file
# markdown_url = QUrl.fromUserInput(/path/of/markdown.md)
download_manager.finished.connect(document.set_text)
download_manager.start_download(markdown_url)
view = QWebEngineView()
view.page().setWebChannel(channel)
url = QUrl.fromLocalFile(filename)
view.load(url)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
index.html
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
<link rel="stylesheet" type="text/css" href="3rdparty/markdown.css">
<script src="3rdparty/marked.js"></script>
<script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
<script>
'use strict';
var placeholder = document.getElementById('placeholder');
var updateText = function(text) {
placeholder.innerHTML = marked(text);
}
new QWebChannel(qt.webChannelTransport,
function(channel) {
var content = channel.objects.content;
updateText(content.text);
content.textChanged.connect(updateText);
}
);
</script>
</body>
</html>
├── 3rdparty
│ ├── markdown.css
│ ├── MARKDOWN-LICENSE.txt
│ ├── marked.js
│ ├── MARKED-LICENSE.txt
│ └── qt_attribution.json
├── index.html
└── main.py
注意:3rdparty文件夹中的文件在the official Qt repository.