【问题标题】:PyQt window closes after launchPyQt 窗口在启动后关闭
【发布时间】:2016-05-12 18:24:33
【问题描述】:

我正在尝试使用 QPushButton 来调用打开 QWebView 新实例的函数。有效,但一旦窗口打开,它就会再次关闭。 我读过这篇文章 - PyQt window closes immediately after opening,但我不明白如何引用窗口以使其保持打开状态。

import sys
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.QtWebKit import QWebSettings
from PyQt4.QtNetwork import QNetworkAccessManager
from PyQt4.QtNetwork import *



UA_STRING = """Test Test Test""" 
vidurl = ("empty")

def web1():

    class YWebPage(QtWebKit.QWebPage):
        def __init__(self):
            super(QtWebKit.QWebPage, self).__init__()

        def userAgentForUrl(self, url):
            return UA_STRING


    class Browser(QtGui.QMainWindow): # "Browser" window


        def __init__(self):
            QtGui.QMainWindow.__init__(self)
            self.resize(800,600) # Viewport size
            self.centralwidget = QtGui.QWidget(self)
            self.html = QtWebKit.QWebView()


        def browse(self):
            self.webView = QtWebKit.QWebView()
            self.yPage = YWebPage()
            self.webView.setPage(self.yPage)
            self.webView.load(QtCore.QUrl(vidurl)) # Video URL
            self.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled,True) # Enables flash player
            self.webView.show()

    x = Browser()
    # QNetworkProxy.setApplicationProxy(QNetworkProxy(QNetworkProxy.HttpProxy, "proxy.example.com", 8080)) # Proxy setting
    x.browse()



def main(): # Dialog window

    app = QtGui.QApplication(sys.argv)

    w = QtGui.QWidget()

    w.resize(200, 450)
    w.setFixedSize(200, 350)
    w.move(300, 300)
    w.setWindowTitle('U-bot 0.1')

    # Setup GUI

    # Start Button
    w.__button = QtGui.QPushButton(w)
    w.__button.clicked.connect(lambda: web1())

    # Text area
    w.__qle = QtGui.QLineEdit(w)
    w.__qle.setText ("http://")
    vidurl = w.__qle.text # Get video url from user

    # Images
    pixmap1 = QtGui.QPixmap("ubot.png")
    lbl1 = QtGui.QLabel(w)
    lbl1.resize(200, 150)
    lbl1.setPixmap(pixmap1)
    lbl1.setScaledContents(True)

    w.__button.setText('Start')
    layout = QtGui.QVBoxLayout()
    layout.addStretch(1)

    layout.addWidget(w.__qle)
    layout.addWidget(w.__button)


    w.setLayout(layout)
    w.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
    app.exec_()

【问题讨论】:

    标签: python pyqt4


    【解决方案1】:

    创建一个MainWindow 类来保存打开的浏览器列表,每次打开浏览器时,只需将其添加到列表中即可。当浏览器窗口关闭时,它会从列表中删除自己,请参阅closeEvent

    import sys
    from PyQt4 import QtCore, QtGui, QtWebKit
    from PyQt4.QtWebKit import QWebSettings
    from PyQt4.QtNetwork import QNetworkAccessManager
    from PyQt4.QtNetwork import *
    
    
    UA_STRING = """Test Test Test""" 
    vidurl = ("empty")
    
    class YWebPage(QtWebKit.QWebPage):
        def __init__(self):
            super(YWebPage, self).__init__()
    
        def userAgentForUrl(self, url):
            return UA_STRING
    
    
    class Browser(QtGui.QMainWindow): # "Browser" window
        def __init__(self, main, url):
            QtGui.QMainWindow.__init__(self)
            self.main = main
            self.resize(800,600) # Viewport size
            self.webView = QtWebKit.QWebView()
            self.setCentralWidget(self.webView)
            self.yPage = YWebPage()
            self.webView.setPage(self.yPage)
            self.webView.load(QtCore.QUrl(url)) # Video URL
            self.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True) # Enables flash player
    
        def closeEvent(self, event):
            self.main.browsers.remove(self)
            super(Browser, self).closeEvent(event)
    
    
    class MainWindow(QtGui.QWidget):
        def __init__(self):
            super(MainWindow, self).__init__()
            self.browsers = []
    
            self.resize(200, 450)
            self.setFixedSize(200, 350)
            self.move(300, 300)
            self.setWindowTitle('U-bot 0.1')
    
            # Setup GUI
    
            # Start Button
            self.__button = QtGui.QPushButton('Start')
            self.__button.clicked.connect(self.open)
    
            # Text area
            self.__qle = QtGui.QLineEdit()
            self.__qle.setText("http://")
    
            # Images
            pixmap1 = QtGui.QPixmap("ubot.png")
            lbl1 = QtGui.QLabel()
            lbl1.resize(200, 150)
            lbl1.setPixmap(pixmap1)
            lbl1.setScaledContents(True)
    
            layout = QtGui.QVBoxLayout()
            layout.addStretch(1)
    
            layout.addWidget(self.__qle)
            layout.addWidget(self.__button)
    
            self.setLayout(layout)
    
        def open(self):
            b = Browser(self, self.__qle.text())
            b.show()
            self.browsers.append(b)
    
    
    def main():
        app = QtGui.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    • 这个问题的完美答案。窗口关闭的原因是它丢失了它在执行后不再有参考。调用该函数,弹出一个窗口,然后在函数完成后将其从内存中清除。当您使用self 将其链接到现有类时,您可以避免这种情况。这个答案更好,因为它将新窗口附加到列表对象。我认为这是保持代码整洁的绝佳解决方案。
    • 感谢您的回复。
    【解决方案2】:

    要保留对 QObject 的引用,您可以将变量保留在范围内,或者将其添加为另一个 QObject 的子变量,该变量已在范围内。

    对于QWidget,父级也应该是QWidget,因此,在您的情况下,您需要将w 作为所有QMainWindows 的父级。

    def web1(parent):
        ...
        class Browser(QtGui.QMainWindow): # "Browser" window
            def __init__(self, parent):
                QtGui.QMainWindow.__init__(self, parent)
                ...
    
    def main():
        ...
        w.__button.clicked.connect(lambda: web1(w))
    

    这也避免了手动维护打开的窗口列表,因为对象层次结构可以为您做到这一点。

    PS:子窗口显示为顶层窗口,而不是在w 窗口内,因为QMainWindow(和QDialog)默认设置了Qt::Window 标志。

    【讨论】:

    • 谢谢,同意了。
    • “要保留对 QObject 的引用,您可以将变量保留在范围内”是我所需要知道的。对我来说,这点小知识很受用 - 我添加了一行代码,将对象保持在脚本的范围内,我的 QWidget 窗口保持活动状态,而不是像以前那样立即消失。
    猜你喜欢
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多