John_Alden | 2020-11-18 14:08:31 UTC | #1
I'm using QWebEngineView to display html that's been produced from markdown. Clicking a link causes the loaded web page to replace the entire contents of the QWebEngineView widget. I'd like to launch the page in a separate browser window. Does it have anything I could override to get my hands on the event and do it myself.
martin | 2020-11-18 14:08:39 UTC | #2
Hi @John_Alden welcome to the forum & nice question. This has changed since earlier versions of PyQt so it wasn't so easy to piece it together, but I have a working example.
The key part is the
CustomWebEnginePage class. By creating this custom page class we can intercept the
acceptNavigationRequest signal and decline it for specific types of links (here we're intercepting only NavigationLinkRequested). For these links we create a custom web engine view, set the URL and then display the window. Note that we need to keep a reference to the created window (in
external_windows) so it isn't destroyed. For everything else, we pass through to the handler on the parent class via
class CustomWebEnginePage(QWebEnginePage): """ Custom WebEnginePage to customize how we handle link navigation """ # Store external windows. external_windows =  def acceptNavigationRequest(self, url, _type, isMainFrame): if _type == QWebEnginePage.NavigationTypeLinkClicked: w = QWebEngineView() w.setUrl(url) w.show() # Keep reference to external window, so it isn't cleared up. self.external_windows.append(w) return False return super().acceptNavigationRequest(url, _type, isMainFrame)
To make sure our custom page is used, we need to set it on the browser with
.setPage() (wherever it is created).
self.browser = QWebEngineView() self.browser.setPage(CustomWebEnginePage(self)) self.browser.setUrl(QUrl("http://google.com"))
Note that in this example we're creating multiple external windows (rather than just sending all links to the same one). If you want to do that instead, you can do something like --
class WebEnginePage(QWebEnginePage): # Store second window. external_window = None def acceptNavigationRequest(self, url, _type, isMainFrame): print(url, _type, isMainFrame) if _type == QWebEnginePage.NavigationTypeLinkClicked: if not self.external_window: self.external_window = QWebEngineView() self.external_window.setUrl(url) self.external_window.show() return False return super().acceptNavigationRequest(url, _type, isMainFrame)
Hope that helps!
John_Alden | 2020-11-18 02:55:10 UTC | #3
Thanks very much, Martin. That's exactly what I was looking for. It's working great! Thanks so much for taking the problem on!
martin | 2020-11-19 13:01:09 UTC | #4
Glad it helped @John_Alden -- I've written up a longer guide to this including how to conditionally open windows, and opening links in the system default browser.
To support developers in [[ countryRegion ]] I give a [[ localizedDiscount[couponCode] ]]% discount with the code [[ couponCode ]] — Enjoy!
For [[ activeDiscount.description ]] I'm giving a [[ activeDiscount.discount ]]% discount with the code [[ couponCode ]] — Enjoy!