2011-05-07 91 views
4

我不知道關於Qt的第一件事,但我試圖做一個厚臉皮,並從別處借用代碼(http://lateral.netmanagers.com.ar/weblog/posts/BB901.html#disqus_thread)。 ;)如何正確關閉PyQt的QtApplication?

我有一個問題。當我第一次運行test()時,一切都會順利進行。但是,當我第二次運行它時,會出現討厭的段錯誤。我懷疑問題是我沒有正確地結束qt的東西。我應該怎樣改變這個程序使它多次工作?提前致謝!

from PyQt4 import QtCore, QtGui, QtWebKit 
import logging 

logging.basicConfig(level=logging.DEBUG) 

class Capturer(object): 
    """A class to capture webpages as images""" 

    def __init__(self, url, filename, app): 
     self.url = url 
     self.app = app 
     self.filename = filename 
     self.saw_initial_layout = False 
     self.saw_document_complete = False 

    def loadFinishedSlot(self): 
     self.saw_document_complete = True 
     if self.saw_initial_layout and self.saw_document_complete: 
      self.doCapture() 

    def initialLayoutSlot(self): 
     self.saw_initial_layout = True 
     if self.saw_initial_layout and self.saw_document_complete: 
      self.doCapture() 

    def capture(self): 
     """Captures url as an image to the file specified""" 
     self.wb = QtWebKit.QWebPage() 
     self.wb.mainFrame().setScrollBarPolicy(
      QtCore.Qt.Horizontal, QtCore.Qt.ScrollBarAlwaysOff) 
     self.wb.mainFrame().setScrollBarPolicy(
      QtCore.Qt.Vertical, QtCore.Qt.ScrollBarAlwaysOff) 
     self.wb.loadFinished.connect(self.loadFinishedSlot) 
     self.wb.mainFrame().initialLayoutCompleted.connect(
      self.initialLayoutSlot) 
     logging.debug("Load %s", self.url) 
     self.wb.mainFrame().load(QtCore.QUrl(self.url)) 

    def doCapture(self): 
     logging.debug("Beginning capture") 
     self.wb.setViewportSize(self.wb.mainFrame().contentsSize()) 
     img = QtGui.QImage(self.wb.viewportSize(), QtGui.QImage.Format_ARGB32) 
     painter = QtGui.QPainter(img) 
     self.wb.mainFrame().render(painter) 
     painter.end() 
     img.save(self.filename) 
     self.app.quit() 

def test(): 
    """Run a simple capture""" 
    app = QtGui.QApplication([]) 
    c = Capturer("http://www.google.com", "google.png", app) 
    c.capture() 
    logging.debug("About to run exec_") 
    app.exec_() 

DEBUG:root:Load http://www.google.com 
QObject::connect: Cannot connect (null)::configurationAdded(QNetworkConfiguration) to QNetworkConfigurationManager::configurationAdded(QNetworkConfiguration) 
QObject::connect: Cannot connect (null)::configurationRemoved(QNetworkConfiguration) to QNetworkConfigurationManager::configurationRemoved(QNetworkConfiguration) 
QObject::connect: Cannot connect (null)::configurationUpdateComplete() to QNetworkConfigurationManager::updateCompleted() 
QObject::connect: Cannot connect (null)::onlineStateChanged(bool) to QNetworkConfigurationManager::onlineStateChanged(bool) 
QObject::connect: Cannot connect (null)::configurationChanged(QNetworkConfiguration) to QNetworkConfigurationManager::configurationChanged(QNetworkConfiguration) 

Process Python segmentation fault (this last line is comes from emacs) 
+0

所以你想通過複製他人的工作來編寫代碼,而你卻不明白你到底在拷貝什麼? – dassouki 2011-05-07 23:02:01

+0

當爲特定目的專門提供代碼時,借用GPL代碼來處理小腳本是非常合理的。這與使用庫非常相似,只是庫不起作用,我試圖找出如何解決它。 – 2011-05-07 23:30:13

+0

我跑了它,它工作正常。 (在添加進口後,你遺漏了。) – Nathan 2011-05-08 00:26:27

回答

1

QApplication應該只能初始化一次! 只要你願意,它可以被儘可能多的Capture實例使用,但你應該在主循環中啓動它們。 請參閱:https://doc.qt.io/qt-4.8/qapplication.html

您也可以在「app.exec_」之後嘗試「del app」,但我不確定結果。 (你原來的代碼運行正常我的系統上)

我會轉而使用的WebKit的urllib:

import urllib 

class Capturer: 
    def capture(self, s_url, s_filename): 
     s_file_out, httpmessage = urllib.urlretrieve(s_url, s_filename, self.report) 

    def report(self, i_count, i_chunk, i_size): 
     print('retrived %5d of %5d bytes' % (i_count * i_chunk, i_size)) 

def test(): 
    c = Capturer() 
    c.capture("http://www.google.com/google.png", "google1.png") 
    c.capture("http://www.google.com/google.png", "google2.png") 

if __name__ == '__main__': 
    test() 
2

你需要處理的QApplication的測試功能外,有點像單(它實際上適合在這裏)。你可以做的是檢查QtCore.qApp是否是某個東西(或者QApplication.instance()返回None或其他東西),然後才創建你的qApp,否則使用全局的東西。

由於PyQt將應用程序存儲在某個地方,它不會在你的test()函數後被銷燬。

如果你想確保它的處理正確,只需爲它設置一個懶惰的初始化單例。

+0

我試圖多次調用GUI時遇到了這個問題。解決方案是隻創建一次QApplication並將其傳遞給GUI啓動。 – derchambers 2015-11-19 23:38:28