2012-09-06 3 views
1

이전 questions here (older one is here) 덕분에 HTML 양식을 표시하고 입력을 가져 오는 PyQt4 클래스가 있습니다.PyQt4 : 메인 루프를 다시 시작 하시겠습니까?

이제 주 루프를 종료하고 다른 작업을 수행 한 다음 나중에 다른 html 양식으로 주 루프를 다시 시작하려고합니다. 문제는 내 이벤트 핸들이 주 루프의 두 번째 실행에서 작동하지 않는다는 것입니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

양식이 제출되지 않아 app.exec_()이 두 번째 호출 될 때 클래스 MyWebPage이 제대로 작동하지 않는 것 같습니다.

다음은 실행 내 코드이지만, 두 번째 양식 제출하지 않습니다

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() 

내가 파이썬 2

답변

1

프로그램의 현재 구조를 변경해야와 workinh을 생각합니다.

먼저, main 기능은 가능한 단순하게 유지되어야합니다. 응용 프로그램 개체와 기본 창을 만든 다음 이벤트 루프를 실행해야합니다. 그 후에는 신호/이벤트와 처리기를 중심으로 모든 것이 구조화되어야합니다.

현재 양식 제출은 하나뿐입니다. 이것은 비동기식으로이 발생하므로 응용 프로그램은 현재 상태를 저장 한 다음 각 양식이 완료 될 때까지 수동으로 대기해야 다음 작업으로 넘어갈 수 있습니다.

편집

는 이제 사양이 명확 것을 한 가지 방법은 당신이 원하는 것을 달성하기 위해 자체 이벤트 루프가있는 QDialog을 사용하는 것입니다.

import sys 
from urllib import unquote_plus 

from PyQt4 import QtCore, QtGui, QtWebKit 

class MyWebPage(QtWebKit.QWebPage): 
    formSubmitted = QtCore.pyqtSignal(object) 

    def acceptNavigationRequest(self, frame, req, nav_type): 
     if nav_type == QtWebKit.QWebPage.NavigationTypeFormSubmitted: 
      elements = {} 
      for key, value in req.url().encodedQueryItems(): 
       key = unquote_plus(bytes(key)).decode('utf8') 
       value = unquote_plus(bytes(value)).decode('utf8') 
       elements[key] = value 
      self.formSubmitted.emit(elements) 
     return super(MyWebPage, self).acceptNavigationRequest(frame, req, nav_type) 

class PsyTML(QtGui.QDialog): 
    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.exec_() 

    def handleFormSubmitted(self, elements): 
     self.elements = elements 
     self.accept() 

# 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) 

    # do stuff with elements... 
    for item in intro.elements.iteritems(): 
     print '"%s" = "%s"' % item 

    intro = PsyTML() 
    intro.viewPsyTML(html2) 

if __name__ == "__main__": 
    main() 
+0

감사합니다 (다시) 귀하의 답변에 대한 많은 :

여기 당신이 원하는 무엇을 잘하면 가까운 스크립트의 수정 된 버전입니다. 안타깝게도, 나는'app.exec _()'로 다시 돌아 오기 전에 메인 루프 ('app.exec _()')를 종료하고'main()'으로 돌아와야한다. 이것이 불가능하다고 생각합니까? 아니면 두 가지 응용 프로그램을 만들어야합니까? 문제는 내 실제 작업에서 PyQt4 디스플레이가 다른 프로그램 창 (즉,'pyglet')을 불러 일으키는 더 큰 프로그램 전체에서 다른 시간에 유발 된 하나의 프로그램 부분에 불과하다는 것입니다. – Henrik

+0

@Henrik 전체 프로그램을 필요에 따라 창을 소유하는 단일 Qt 응용 프로그램으로 만드는 것이 더 좋을 것입니다. 또는 표시되는 각 양식에 대한 개별 실행 파일을 시작하고 통신하는 것이 좋습니다. – ephemient

+0

@ephemient 문제는 ​​내가 제공하고자하는 기능은 기존 Python 라이브러리 [PsychoPy] (http://psychopy.org/)의 addon 일뿐입니다. PsychoPy에서 실험을 프로그래밍 할 때 위의 클래스를 사용하여 html 페이지를 표시하려고 할 수 있습니다. 그러나 주요 부분은 사이코 피 (PsychoPy)입니다. 따라서 필자는 메인 루프를 벗어날 수 있어야합니다. – Henrik

관련 문제