I have a PyQt4 class that displays a html form and fetches the input, thanks to previous questions here (an older one is here).
Now I want to exit the main loop, do something else and restart the main loop with a different html form later. The problem is, that my event handles do not work in the second execution of the main loop. What am I doing wrong?
The problem seems to be that the class MyWebPage does not work properly when app.exec_() is called the second time, as the form is not submitted.
Here is my code which runs, but does not submit the second form:
import sys
from urllib import unquote_plus
from PyQt4 import QtCore, QtGui, QtWebKit
class MyWebPage(QtWebKit.QWebPage):
formSubmitted = QtCore.pyqtSignal(QtCore.QUrl)
def acceptNavigationRequest(self, frame, req, nav_type):
if nav_type == QtWebKit.QWebPage.NavigationTypeFormSubmitted:
self.formSubmitted.emit(req.url())
return super(MyWebPage, self).acceptNavigationRequest(frame, req, nav_type)
class PsyTML(QtGui.QWidget):
def __init__(self):
super(PsyTML, self).__init__()
self.elements = {}
self.view = QtWebKit.QWebView(self)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.view)
layout.setContentsMargins(0, 0, 0, 0)
self.view.setPage(MyWebPage())
self.view.page().formSubmitted.connect(self.handleFormSubmitted)
def viewPsyTML(self, html):
self.view.setHtml(html)
self.show()
def handleFormSubmitted(self, url):
elements = self.elements
self.close()
for key, value in url.encodedQueryItems():
key = unquote_plus(bytes(key)).decode('utf8')
value = unquote_plus(bytes(value)).decode('utf8')
elements[key] = value
# do stuff with elements...
for item in elements.iteritems():
print '"%s" = "%s"' % item
QtGui.qApp.quit()
# setup the html form
html = """
<form action="" method="get">
Like it?
<input type="radio" name="like" value="yes"/> Yes
<input type="radio" name="like" value="no" /> No
<br/><input type="text" name="text" value="" />
<input type="submit" name="submit" value="Send"/>
</form>
"""
html2 = """
<form action="" method="get">
Choose wisely?
<input type="radio" name="choose" value="A"/> Yes
<input type="radio" name="choose" value="B" /> No
<br/><input type="text" name="text" value="" />
<input type="submit" name="submit" value="Send"/>
</form>
"""
def main():
app = QtGui.QApplication(sys.argv)
intro = PsyTML()
intro.viewPsyTML(html)
# now, the html form is displayed nicely and the form elemtns returned
app.exec_()
# do something else here
# in the secomd run, the form is not submitted.
intro.viewPsyTML(html2)
app.exec_()
if __name__ == "__main__":
main()
I am workinh with Python 2.
The current structure of your program needs to be changed.
Firstly, the
mainfunction should be kept as simple as possible. It should just create an application object and a main window, and then run the event loop. After that, everything should be structured around signals/events and their handlers.Currently, there is only one central event: form submission. This happens asynchronously, so the application has to save its current state and then wait passively for each form to be completed, before it can move on to the next task.
EDIT
Now that your spec is clearer, one way to achieve what you want is to use a
QDialog, which has its own event loop.Here’s a revised version of your script that is hopefully closer to what you want: