QWebView - main GUI thread stops to respond after trying to load a page
-
The problem can be solved by not using an extra eventloop. Why do you have to wait synchronously for loadFinished anyways?
If you can't find any other way to get your software to work without the extra eventloop, atleast that might be a point to start debugging. Maybe you can build a wrapper around QEventloop to make sure you don't create more than one extra eventloop and to make sure the eventloop ends after a certain timeout interval.
Here's a "link to a thread":http://qt-project.org/forums/viewthread/24109/ that discussed a similar problem.
-
well, the reason I have to wait synchronously for loadFinished is this:
I am building a web robot, that travels on a website and performs stuff there, so when I load a certain page I want to wait that it finished to load before I can do whatever I want on that page ( I need all the elements to be there for sure).
so I have created a wait_load function that after load started I start an eventloop, also start a timer for timeout that exits the eventloop if more then 60 seconds or so passed. the other condition to exit the eventloop is that a pageload event has fired.
the code looks like that:@def waitLoad(self, timeout):
retry = 1
max_retries = 15
while True:
self.timer.start(timeout * 1000)
self.eloop.exec_()
if self.readyState == True:
return True
else:#retry loading page
retry = retry + 1
if retry > max_retries:
return False
self.webView.stop()
self.wait(5)
self.prepareLoad()
self.webView.reload()
return Truedef wait(self, waittime):
self.timer.start(waittime * 1000)
self.eloop.exec_()def loadFinished(self, ok):
self.timer.stop()
self.eloop.exit()
if ok:
self.readyState = Truedef timerTimeout(self):
self.eloop.exit()@ -
You don't need an eventloop to do that. Just connect your robots startWork function to the loadFinished signal. The timeout signal could be connected to a tryReload function or a loadNextPage function.
I'm noticing you're using python. I'm not sure if connect for signals and slots is available there, but since it's such a crucial feature of Qt it most certainly is.
-
do you mean that I do not need an eventloop to wait for the page to finish loading ?
-
Sometimes event loop loops infinitely when using network requests (I don't know why tho). Therefore I suggest to use event loop "manually" to process events as long as you are really need to.
@
SomeProcess process;
process.start();QEventLoop loop;
while (process.isRunning())
loop.processEvents();process.getResults();
@ -
before I started using QEventLoop, I manualy processed events using QApplication.processEvents(), that made the same bug, GUI thread hangs...
So I tried QEventLoop, but same bug happened.
You think eventloop.processEvents is different ? -
[quote author="NirBlinder" date="1371026555"]do you mean that I do not need an eventloop to wait for the page to finish loading ?[/quote]
You don't need an extra eventloop. Your application (QApplication or QCoreApplication) already has a running eventloop, so there's no need for a second one. You don't need to wait synchronously for the signal loadFinished. Just connect to the loadFinished signal and thats it.
Maybe I'm missing something, but from the use case you described there's no need for the extra degree of complexity you're adding with the second eventloop or the processEvent calls.
-
That is interesting , as I remember if I dump the eventloop, the webpage doesn't build itself, items are not painted at all, but maybe I am doing something wrong... ?
-
Do you call something like this anywhere in you app?
@
QApplication app;
app.exec();
@In what context is the QWebView running (main thread of GUI application, QProcess, ...)?
-
My application is currently running in main thread of GUI application.
its constructor looks something like this:@class MyBrowser(QApplication):
def init(self):
super(MyBrowser, self).init(None)
self.webView = QWebView()
self.page = WebPage(self.webView)
self.page.setUserAgent()
self.webView.setPage(self.page)
self.timer = QTimer()
self.timer.setSingleShot(True)
self.timer.timeout.connect(self.timerTimeout)
self.timeoutReached = False
self.webView.showMaximized()
self.readyState = False
self.webView.loadFinished.connect(self.loadFinished)
self.eloop = QEventLoop()@and what I do is creating an instance of it:
@myBrowser = MyBrowser()@
and then something like:
@myBrowser.load("http://www,google.com")
myBrowser.waitLoad(60)
myBrowser.load(someotherpage)
myBrowser.someCustomFunction()@
and so on...So I do not use
@myBrowser.exec()@because there is no real user handling the browser.
Is that understood ?
Is that the right approach ? -
Ah ok so thats why you have no running eventloop and thus add your own.
Since I haven't used Qt with Python I can't really comment on that, but from the c++ perspective it seems weird. Maybe you should post a question in the "Language Bindings subsection ":http://qt-project.org/forums/viewforum/15/ of this forum. -
Ok thank you anyway , I will try that .
Maybe I will switch to QT with C++, I heard its more stable.Thank you for the help , I appreciate it.