Given a project structure like:
my_project
main.py
www/
index.html
scripts/
jquery-1.9.1.min.js
main.py looks like:
import sys from os.path import dirname, join #from PySide.QtCore import QApplication from PySide.QtCore import QObject, Slot, Signal from PySide.QtGui import QApplication from PySide.QtWebKit import QWebView, QWebSettings from PySide.QtNetwork import QNetworkRequest web = None myPage = None myFrame = None class Hub(QObject): def __init__(self): super(Hub, self).__init__() @Slot(str) def connect(self, config): print config self.on_client_event.emit("Howdy!") @Slot(str) def disconnect(self, config): print config on_client_event = Signal(str) on_actor_event = Signal(str) on_connect = Signal(str) on_disconnect = Signal(str) myHub = Hub() class HTMLApplication(object): def show(self): #It is IMPERATIVE that all forward slashes are scrubbed out, otherwise QTWebKit seems to be # easily confused kickOffHTML = join(dirname(__file__).replace('\\', '/'), "www/index.html").replace('\\', '/') #This is basically a browser instance self.web = QWebView() #Unlikely to matter but prefer to be waiting for callback then try to catch # it in time. self.web.loadFinished.connect(self.onLoad) self.web.load(kickOffHTML) self.web.show() def onLoad(self): if getattr(self, "myHub", False) == False: self.myHub = Hub() #This is the body of a web browser tab self.myPage = self.web.page() self.myPage.settings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True) #This is the actual context/frame a webpage is running in. # Other frames could include iframes or such. self.myFrame = self.myPage.mainFrame() # ATTENTION here's the magic that sets a bridge between Python to HTML self.myFrame.addToJavaScriptWindowObject("my_hub", myHub) #Tell the HTML side, we are open for business self.myFrame.evaluateJavaScript("ApplicationIsReady()") #Kickoff the QT environment app = QApplication(sys.argv) myWebApp = HTMLApplication() myWebApp.show() sys.exit(app.exec_()) |
and index.html looks like:
<html>
<head>
<!-- Oh hell no, I can access anything on my computer via this -->
<script src="./scripts/jquery-1.9.1.min.js"></script>
<script language="javascript" type="text/javascript">
function callback(){
console.log("callback!");
alert("called!");
}
function sendStuff() {
console.log("sendStuff!");
my_hub.connect("hello?");
}
function ApplicationIsReady(){
console.log("ApplicationIsReady!");
my_hub.on_client_event.connect(callback);
}
</script>
</head>
<body>
Tell the hub to connect
<button onclick=sendStuff()>No, click me!</button>
</body>
<script>
alert(typeof jQuery);
</script>
</html> |
Basically class Hub is a bridge/interface pattern between Python and the HTML Javascript engines. It’s probably best to pass things between the two as JSON as that’s a language both sides are readily prepared to deal with.
Stuff I didn’t deal with yet: The Main window title ( self.web.setWindowTitle), setting a window Icon ( no clue on this one ).
Otherwise this gives me an OS agnostic UI, I can leverage my HTML skillset without having to learn QML or QT Designer’s UI interface, and I can hopefully recycle some logic. Additionally I can go full fledged with the bridge logic, split it between the two, or shove all the complexity into JS and have basic Python endpoints exposed.


