如何在Python Qt中获取和设置monaco编辑器的值?
How to get and set the value of monaco editor in Python Qt?
我在 Python Qt (Pyside2) 中使用 QWebEngineView 中的摩纳哥编辑器实例,类似于此处显示的方式:
我可以像在摩纳哥编辑器中一样编辑代码。但是如何调用函数来获取和设置编辑器的当前值呢?
我只看到了 React 示例,但没有看到 Python,所以不确定如何在 Python 中做同样的事情。
使用 Python Qt (Pyside2) 可以做到这一点吗?
编辑:发现这个 link 展示了如何为 Pyside2 做到这一点:
https://www.itdaan.com/tw/66b0f712b22ff6e617b7b493f7c3c841
虽然尝试了这个,但我没有得到名为摩纳哥的名字。我会尽量简化代码。
在这种情况下是使用QtWebChannel在python和javascript之间交换信息,如下所示:
main.py
import json
import os
from PySide2 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class BaseBridge(QtCore.QObject):
initialized = QtCore.Signal()
sendDataChanged = QtCore.Signal(str, str)
def send_to_js(self, name, value):
data = json.dumps(value)
self.sendDataChanged.emit(name, data)
@QtCore.Slot(str, str)
def receive_from_js(self, name, value):
data = json.loads(value)
self.setProperty(name, data)
@QtCore.Slot()
def init(self):
self.initialized.emit()
class EditorBridge(BaseBridge):
valueChanged = QtCore.Signal()
languageChanged = QtCore.Signal()
themeChanged = QtCore.Signal()
def __init__(self, parent=None):
super(EditorBridge, self).__init__(parent)
self._value = ""
self._language = ""
self._theme = ""
def getValue(self):
return self._value
def setValue(self, value):
self._value = value
self.valueChanged.emit()
def getLanguage(self):
return self._language
def setLanguage(self, language):
self._language = language
self.languageChanged.emit()
def getTheme(self):
return self._theme
def setTheme(self, theme):
self._theme = theme
self.themeChanged.emit()
value = QtCore.Property(str, fget=getValue, fset=setValue, notify=valueChanged)
language = QtCore.Property(
str, fget=getLanguage, fset=setLanguage, notify=languageChanged
)
theme = QtCore.Property(str, fget=getTheme, fset=setTheme, notify=themeChanged)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self._view = QtWebEngineWidgets.QWebEngineView()
channel = QtWebChannel.QWebChannel(self)
self.view.page().setWebChannel(channel)
self._bridge = EditorBridge()
channel.registerObject("bridge", self.bridge)
self.setCentralWidget(self.view)
filename = os.path.join(CURRENT_DIR, "index.html")
self.view.load(QtCore.QUrl.fromLocalFile(filename))
self.bridge.initialized.connect(self.handle_initialized)
self.bridge.valueChanged.connect(self.handle_valueChanged)
self.bridge.languageChanged.connect(self.handle_languageChanged)
self.bridge.themeChanged.connect(self.handle_themeChanged)
@property
def view(self):
return self._view
@property
def bridge(self):
return self._bridge
def handle_initialized(self):
print("init")
code = "\n".join(["function x() {", '\tconsole.log("Hello world!");', "}"])
# Do not use self.bridge.value = code or self.bridge.setValue(code)
self.bridge.send_to_js("value", code)
self.bridge.send_to_js("language", "javascript")
self.bridge.send_to_js("theme", "vs-dark")
def handle_valueChanged(self):
print("value:", self.bridge.value)
def handle_languageChanged(self):
print("language:", self.bridge.language)
def handle_themeChanged(self):
print("theme", self.bridge.theme)
if __name__ == "__main__":
import sys
sys.argv.append("--remote-debugging-port=8000")
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
index.js
var bridge = null;
var editor = null;
require.config({ paths: { 'vs': 'monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () {
editor = monaco.editor.create(document.getElementById('container'), {
fontFamily: "Verdana",
});
editor.onDidChangeModelContent((event) => {
sendToPython("value", editor.getModel().getValue())
})
editor.onDidChangeModelLanguage((event) => {
sendToPython("language", event.newLanguage)
})
});
function init() {
sendToPython("value", editor.getModel().getValue());
sendToPython("language", editor.getModel()._languageIdentifier.language);
sendToPython("theme", editor._themeService._theme.themeName);
}
function sendToPython(name, value) {
bridge.receive_from_js(name, JSON.stringify(value));
}
function updateFromPython(name, value) {
var data = JSON.parse(value)
switch (name) {
case "value":
editor.getModel().setValue(data);
break;
case "language":
monaco.editor.setModelLanguage(editor.getModel(), data);
break;
case "theme":
monaco.editor.setTheme(data);
sendToPython("theme", editor._themeService._theme.themeName);
break;
}
}
window.onload = function () {
new QWebChannel(qt.webChannelTransport, function (channel) {
bridge = channel.objects.bridge;
bridge.sendDataChanged.connect(updateFromPython);
bridge.init();
init();
});
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
</head>
<body>
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
<script src="monaco-editor/min/vs/loader.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
├── index.html
├── index.js
├── main.py
└── monaco-editor
├── CHANGELOG.md
├── dev
├── esm
├── LICENSE
├── min
├── min-maps
├── monaco.d.ts
├── package.json
├── README.md
└── ThirdPartyNotices.txt
我在 Python Qt (Pyside2) 中使用 QWebEngineView 中的摩纳哥编辑器实例,类似于此处显示的方式:
我可以像在摩纳哥编辑器中一样编辑代码。但是如何调用函数来获取和设置编辑器的当前值呢?
我只看到了 React 示例,但没有看到 Python,所以不确定如何在 Python 中做同样的事情。
使用 Python Qt (Pyside2) 可以做到这一点吗?
编辑:发现这个 link 展示了如何为 Pyside2 做到这一点: https://www.itdaan.com/tw/66b0f712b22ff6e617b7b493f7c3c841
虽然尝试了这个,但我没有得到名为摩纳哥的名字。我会尽量简化代码。
在这种情况下是使用QtWebChannel在python和javascript之间交换信息,如下所示:
main.py
import json
import os
from PySide2 import QtCore, QtWidgets, QtWebEngineWidgets, QtWebChannel
CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
class BaseBridge(QtCore.QObject):
initialized = QtCore.Signal()
sendDataChanged = QtCore.Signal(str, str)
def send_to_js(self, name, value):
data = json.dumps(value)
self.sendDataChanged.emit(name, data)
@QtCore.Slot(str, str)
def receive_from_js(self, name, value):
data = json.loads(value)
self.setProperty(name, data)
@QtCore.Slot()
def init(self):
self.initialized.emit()
class EditorBridge(BaseBridge):
valueChanged = QtCore.Signal()
languageChanged = QtCore.Signal()
themeChanged = QtCore.Signal()
def __init__(self, parent=None):
super(EditorBridge, self).__init__(parent)
self._value = ""
self._language = ""
self._theme = ""
def getValue(self):
return self._value
def setValue(self, value):
self._value = value
self.valueChanged.emit()
def getLanguage(self):
return self._language
def setLanguage(self, language):
self._language = language
self.languageChanged.emit()
def getTheme(self):
return self._theme
def setTheme(self, theme):
self._theme = theme
self.themeChanged.emit()
value = QtCore.Property(str, fget=getValue, fset=setValue, notify=valueChanged)
language = QtCore.Property(
str, fget=getLanguage, fset=setLanguage, notify=languageChanged
)
theme = QtCore.Property(str, fget=getTheme, fset=setTheme, notify=themeChanged)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self._view = QtWebEngineWidgets.QWebEngineView()
channel = QtWebChannel.QWebChannel(self)
self.view.page().setWebChannel(channel)
self._bridge = EditorBridge()
channel.registerObject("bridge", self.bridge)
self.setCentralWidget(self.view)
filename = os.path.join(CURRENT_DIR, "index.html")
self.view.load(QtCore.QUrl.fromLocalFile(filename))
self.bridge.initialized.connect(self.handle_initialized)
self.bridge.valueChanged.connect(self.handle_valueChanged)
self.bridge.languageChanged.connect(self.handle_languageChanged)
self.bridge.themeChanged.connect(self.handle_themeChanged)
@property
def view(self):
return self._view
@property
def bridge(self):
return self._bridge
def handle_initialized(self):
print("init")
code = "\n".join(["function x() {", '\tconsole.log("Hello world!");', "}"])
# Do not use self.bridge.value = code or self.bridge.setValue(code)
self.bridge.send_to_js("value", code)
self.bridge.send_to_js("language", "javascript")
self.bridge.send_to_js("theme", "vs-dark")
def handle_valueChanged(self):
print("value:", self.bridge.value)
def handle_languageChanged(self):
print("language:", self.bridge.language)
def handle_themeChanged(self):
print("theme", self.bridge.theme)
if __name__ == "__main__":
import sys
sys.argv.append("--remote-debugging-port=8000")
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
index.js
var bridge = null;
var editor = null;
require.config({ paths: { 'vs': 'monaco-editor/min/vs' } });
require(['vs/editor/editor.main'], function () {
editor = monaco.editor.create(document.getElementById('container'), {
fontFamily: "Verdana",
});
editor.onDidChangeModelContent((event) => {
sendToPython("value", editor.getModel().getValue())
})
editor.onDidChangeModelLanguage((event) => {
sendToPython("language", event.newLanguage)
})
});
function init() {
sendToPython("value", editor.getModel().getValue());
sendToPython("language", editor.getModel()._languageIdentifier.language);
sendToPython("theme", editor._themeService._theme.themeName);
}
function sendToPython(name, value) {
bridge.receive_from_js(name, JSON.stringify(value));
}
function updateFromPython(name, value) {
var data = JSON.parse(value)
switch (name) {
case "value":
editor.getModel().setValue(data);
break;
case "language":
monaco.editor.setModelLanguage(editor.getModel(), data);
break;
case "theme":
monaco.editor.setTheme(data);
sendToPython("theme", editor._themeService._theme.themeName);
break;
}
}
window.onload = function () {
new QWebChannel(qt.webChannelTransport, function (channel) {
bridge = channel.objects.bridge;
bridge.sendDataChanged.connect(updateFromPython);
bridge.init();
init();
});
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
</head>
<body>
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
<script src="monaco-editor/min/vs/loader.js"></script>
<script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
├── index.html
├── index.js
├── main.py
└── monaco-editor
├── CHANGELOG.md
├── dev
├── esm
├── LICENSE
├── min
├── min-maps
├── monaco.d.ts
├── package.json
├── README.md
└── ThirdPartyNotices.txt