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

Coiby Xu coiby.xu at gmail.com
Fri Apr 17 17:31:11 BST 2020


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


Best regards,
Coiby


More information about the PyQt mailing list