[PyQt] QWebEnginePage.LifecycleState doesn't work as expected in PyQt while the official C++ lifecyle example works

Phil Thompson phil at riverbankcomputing.com
Sat Apr 18 12:33:06 BST 2020


On 17/04/2020 17:31, Coiby Xu wrote:
> Hi all,
> 
> QT 5.14 introduced the QWebEnginePage.LifecycleState API. While playing
> with this API to try to suspend inactive browser tabs after certain 
> time,
> I noticed an issue. Re-focusing on an inactive tab for the first time
> won't show the HTML content and a blank page is shown instead. But Web
> Inspector shows HTML source was already there and I can even to select
> an invisible element somewhere in the page to inspect it.
> Only switching to another tab then switching back will make the page 
> shown.
> 
> But the official WebEngine Lifecycle Example[1] which can be downloaded 
> via [2]
> doesn't have this problem. The chosen tab will show the rendered page
> immediately.
> 
> I wonder if this problem is caused by PyQt or I just miss something. I 
> also
> output the chosen tab's life-cycle state in my code which shows the tab 
> is
> indeed in LifecycleState.Active again.
> 
>  Discard tab#1, its lifecyclestate is LifecycleState.Discarded now
>  Discard tab#2, its lifecyclestate is LifecycleState.Discarded now
>  Tab#1 active, its lifecyle state is LifecycleState.Active now
>  Tab#2 active, its lifecyle state is LifecycleState.Active now
> 
> The following is my full code for suspending 2/3 inactive tabs,
> 
> import sys
> from time import sleep
> from PyQt5.QtCore import *
> from PyQt5.QtWidgets import *
> from PyQt5.QtWebEngineWidgets import *
> import functools
> 
> qurl = QUrl("http://example.com/")
> 
> def discard_tab(webs, tab):
>     for i, web in enumerate(webs):
>         # skip the current tab
>         if i == tab.currentIndex():
>             continue
>         page = web.page()
>         page.setLifecycleState(QWebEnginePage.LifecycleState.Discarded)
>         state = str(page.lifecycleState())
>         print("Discard tab#{}, its lifecyclestate is {} now".format(i, 
> state))
> 
> @pyqtSlot(int)
> def current_tab(i):
>     page = webs[i].page()
>     state = str(page.lifecycleState())
>     print("Tab#{} active, its lifecyle state is {} now".format(i, 
> state))
> 
> webs = []
> app = QApplication(sys.argv)
> tab = QTabWidget()
> 
> def main():
>     for i in range(3):
>         web = QWebEngineView()
>         web.load(qurl)
>         i = tab.addTab(web, "load")
>         web.loadFinished.connect(lambda _, i=i, web=web:
>                                  tab.setTabText(i, web.page().title()))
>         webs.append(web)
> 
>     tab.show()
> 
>     # trigger current_tab for chosen tab
>     tab.currentChanged.connect(current_tab)
> 
>     # put all invisible tabs into LifecycleState.Dsicarded state after 
> 2s
>     timerCallback = functools.partial(discard_tab, webs=webs, tab=tab)
>     timer = QTimer()
>     timer.timeout.connect(timerCallback)
>     timer.setSingleShot(True)
>     timer.start(2000)
>     sys.exit(app.exec_())
> 
> 
> if __name__ == '__main__':
>     main()
> 
> [1] https://doc.qt.io/qt-5/qtwebengine-webengine-lifecycle-example.html
> [2 
> ]https://github.com/qt/qtwebengine/tree/5.14.2/examples/webengine/lifecycle

The only way I can determine if there is a PyQt-specific problem is to 
compare it with a C++ equivalent of the above code that behaves 
differently.

Phil


More information about the PyQt mailing list