'how to communicate qt with react in tsx?
I know that there is a solution can communicate qt with js, and it work right.
but I want use react in tsx to develop the frontend webpage, and the previous solution failed at this.
the backend code
#./main.py
import os
from PySide6.QtWidgets import QApplication, QGridLayout, QMainWindow, QTextEdit, QWidget
from PySide6.QtCore import QUrl, Slot, QObject
from PySide6.QtWebEngineWidgets import QWebEngineView
class WebFunction(QObject):
@Slot(result=str)
def sayHello(self):
print("hello world!")
return "hello world!"
class Webview(QMainWindow):
def __init__(self,url):
super().__init__()
self.resize(800,600)
self.browser = QWebEngineView(self)
self.inspector = QWebEngineView(self)
self.inspector.page().setInspectedPage(self.browser.page())
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
lay = QGridLayout(self.central_widget)
lay.addWidget(self.browser, 0, 0, 1, 1)
lay.addWidget(self.inspector, 0, 1, 1, 1)
self.browser.setUrl(QUrl.fromLocalFile(os.path.abspath(url)))
if __name__ == '__main__':
import sys
url = "./html/build/index.html"
app = QApplication(sys.argv)
w = Webview(url)
w.show()
sys.exit(app.exec())
the frontend code
// ./html/src/app.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { queryByTitle } from '@testing-library/dom';
import QWebChannel from './qwebchannel/qwebchannel'
function App() {
document.addEventListener('DOMContentLoaded',event => {
const getBackend = new Promise((resolve, reject) => {
console.log(qt)
new QWebChannel.QWebChannel(qt.webChannelTransport,
(channel) => resolve(channel.objects.backend));
})
})
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
<button onClick={()=>console.log('hi')}>123</button>
</header>
</div>
);
}
export default App;
I use the follow command to create a react project:
$npm create-react-app html --template typescript
and the command $./html npm run build to build the production file
and I got a error message said that:
PS C:\Users\Administrator\PycharmProjects\self_control_demon\test\webengine\html> npm run build
> [email protected] build C:\Users\Administrator\PycharmProjects\self_control_demon\test\webengine\html
> react-scripts build
Creating an optimized production build...
Failed to compile.
TS2304: Cannot find name 'qt'.
11 | document.addEventListener('DOMContentLoaded',event => {
12 | const getBackend = new Promise((resolve, reject) => {
> 13 | console.log(qt)
| ^^
14 | new QWebChannel.QWebChannel(qt.webChannelTransport,
15 | (channel) => resolve(channel.objects.backend));
16 | })
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `react-scripts build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2021-12-19T08_37_48_870Z-debug.log
which means that the variable qt doesn't exist, and now I'm confused,how to communicate qt with react in tsx?
Solution 1:[1]
The actual problem is that qt was not declared and will be created by v8 at runtime. So just declare it.
declare global {
interface Window {
qt: any;
}
}
This will dismiss the compile error. For the react side code, we could do it like this:
import React, { useEffect } from "react";
import logo from "./logo.svg";
import "./App.css";
import { QWebChannel } from "qwebchannel";
declare global {
interface Window {
myObj: any;
qt: any;
}
}
window.myObj = window.myObj || {};
function App() {
useEffect(() => {
new QWebChannel(window.qt.webChannelTransport, function (channel) {
window.myObj = channel.objects.myObj;
});
}, []);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | W.Perrin |
