在PyQt中覆盖createWindow函数

时间:2012-11-30 11:06:30

标签: qt webkit pyqt

我正在尝试处理PyQt webkit中的createWindow方法。执行此操作时,PyQt为方法提供QWebPage.WebWindowType(或c ++中的QWebPage::WebWindowType)。我只需要一个创建新窗口的URL,所以我不知道如何处理这个类。文档也没有很好地解释它:http://doc.qt.digia.com/qt/qwebpage.html#WebWindowType-enum

我正在尝试将其与我的“Tab”类集成:

class Tab(QtGui.QWidget):
    """
    Contains the variables and methods needed to open the Qt
    based user interface and the event bus to allow interaction.
    """
    def __init__(self, url, window):
        """
        Set the up the following:
          1) Initialise the Qt user interface.
          2) Set margins.
          3) Initialise the cookie jar.
          4) Set the default URL.
          5) Set the history buttons to disabled (there is not history yet).
          5) Hide the tools menu.
          6) Create the GUI event bus.
          7) Set keyboard bindings.
        """
        self.window = window
        QtGui.QWidget.__init__(self)
        self.ui = Ui_Browser()
        self.ui.setupUi(self)

        l = self.layout()
        l.setMargin(0)
        self.ui.horizontalLayout.setMargin(0)

        try:
            self.ui.webView.page().networkAccessManager().setCookieJar(self.window.cookies)
        except:
            pass

        self.ui.webView.setUrl(url)
        self.ui.url.setText(url.toString())

        self.ui.back.setEnabled(False)
        self.ui.forward.setEnabled(False)

        self.ui.toolsBox.hide()
        self.ui.tools.setChecked(False)

        QtCore.QObject.connect(self.ui.back, QtCore.SIGNAL("clicked()"), self.back)
        QtCore.QObject.connect(self.ui.forward, QtCore.SIGNAL("clicked()"), self.forward)
        QtCore.QObject.connect(self.ui.refresh, QtCore.SIGNAL("clicked()"), self.refresh)
        QtCore.QObject.connect(self.ui.url, QtCore.SIGNAL("returnPressed()"), self.url)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("linkClicked (const QUrl&)"), self.navigate)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("urlChanged (const QUrl&)"), self.navigate)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("titleChanged(const QString&)"), self.title)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadStarted()"), self.showProgressBar)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadProgress(int)"), self.setProgressBar)
        QtCore.QObject.connect(self.ui.webView, QtCore.SIGNAL("loadFinished(bool)"), self.hideProgressBar)
        QtCore.QObject.connect(self.ui.toolPrint, QtCore.SIGNAL("clicked()"), self.printPage)
        self.ui.webView.createWindow = self.createWindow

        QtGui.QShortcut(QtGui.QKeySequence("Backspace"), self, self.back)
        QtGui.QShortcut(QtGui.QKeySequence("F5"), self, self.refresh)
        QtGui.QShortcut(QtGui.QKeySequence("Ctrl+p"), self, self.printPage)

    def url(self):
        """
        Go to URL entered.
        """
        self.setHistory()
        url = self.ui.url.text()
        if not str(url).startswith("http://"):
            url = "http://" + url
        self.ui.webView.setUrl(QtCore.QUrl(url))

    def navigate(self, url):
        """
        Navigate to page requested.
        """
        self.setHistory()
        self.ui.url.setText(url.toString())

    def refresh(self):
        """
        Refresh the page.
        """
        self.ui.webView.setUrl(QtCore.QUrl(self.ui.webView.url()))

    def back(self):
        """
        Enable the back button.
        """
        page = self.ui.webView.page()
        history = page.history()
        history.back()
        if history.canGoBack():
            self.ui.back.setEnabled(True)
        else:
            self.ui.back.setEnabled(False)

    def forward(self):
        """
        Enable the forward button.
        """
        page = self.ui.webView.page()
        history = page.history()
        history.forward()
        if history.canGoForward():
            self.ui.forward.setEnabled(True)
        else:
            self.ui.forward.setEnabled(False)

    def title(self, title):
        """
        Change the title of the window.
        """
        self.window.tabs.setTabText(self.window.tabs.indexOf(self), title) or (self.window.setWindowTitle(title) if self.isThisFocused() else "New Tab")

    def createWindow(self, WebWindowType):
        """
        Overide the default behaviour.
        """
        tab = Tab(QtCore.QUrl("about:blank"), self.window)
        print(mode)
        if mode == QtWebKit.QWebPage.WebModalDialog:
            tab.ui.webView.setWindowModality(QtCore.Qt.ApplicationModal)
        self.window.tabs.setCurrentIndex(self.window.tabs.addTab(tab, ""))

    def isThisFocused(self):
        """
        Return whether this tab is focused or not.
        """
        if self.window.tabs.currentWidget() == self:
            return True
        return False

    def setHistory(self):
        """
        Check history and update buttons.
        """
        page = self.ui.webView.page()
        history = page.history()
        if history.canGoBack():
            self.ui.back.setEnabled(True)
        else:
            self.ui.back.setEnabled(False)
        if history.canGoForward():
            self.ui.forward.setEnabled(True)
        else:
            self.ui.forward.setEnabled(False)

    def showProgressBar(self):
        """
        We're loading a page, show the load progress bar.
        """
        self.ui.progress.show()

    def setProgressBar(self, percent):
        """
        Set the percentage of the progress bar.
        """
        self.ui.progress.setValue(percent)

    def hideProgressBar(self, bool):
        """
        We've finished loading the page, there is no need for the progress bar.
        """
        self.ui.progress.hide()

    def printPage(self):
        """
        Use Qt's goodness to print the page.
        """
        previewer = QtGui.QPrintPreviewDialog(paintRequested=self.ui.webView.print_)
        previewer.exec_()

1 个答案:

答案 0 :(得分:0)

createWindow函数用于处理打开新窗口的请求(例如javascript window.open()调用)。

默认情况下,createWindow不执行任何操作,因此必须在子类中重新实现它。

此外,要使用javascript,web-settings必须指定javascript程序为allowed to open new windows

这是一个演示脚本,演示了如何使用createWindow

from PyQt4 import QtGui, QtCore, QtWebKit

class Browser(QtWebKit.QWebView):
    _windows = set()

    @classmethod
    def _removeWindow(cls, window):
        if window in cls._windows:
            cls._windows.remove(window)

    @classmethod
    def newWindow(cls):
        window = cls()
        cls._windows.add(window)
        return window

    def __init__(self, parent=None):
        QtWebKit.QWebView.__init__(self, parent)
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
        self.settings().setAttribute(
            QtWebKit.QWebSettings.JavascriptEnabled, True)
        self.settings().setAttribute(
            QtWebKit.QWebSettings.JavascriptCanOpenWindows, True)

    def closeEvent(self, event):
        self._removeWindow(self)
        event.accept()

    def createWindow(self, mode):
        window = self.newWindow()
        if mode == QtWebKit.QWebPage.WebModalDialog:
            window.setWindowModality(QtCore.Qt.ApplicationModal)
        window.show()
        return window

html = """
<html>
<head>
<title>Test Page</title>
<script type="text/javascript"><!--
var url = 'https://www.google.com'
var count = 0
function newWindow() {
    count += 1;
    window.open(url, 'testwindow' + count, 'width=640,height=480');
}
--></script>
</head>
<body>
<input type="button" value="New Window" onclick="newWindow()" />
<p><a href="https://www.google.com">Test Link</a></p>
</body>
</html>"""

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    browser = Browser()
    browser.setHtml(html)
    browser.show()
    sys.exit(app.exec_())

NB :必须将引用保留到任何新创建的窗口;否则几乎肯定会导致分段错误。

修改

只是为了澄清:

createWindow函数旨在处理外部请求以打开新的浏览器窗口(例如javascript window.open()调用,如上面的例子)。请注意createWindow虚拟功能。这意味着如果它在QWebViewQWebPage的子类中被覆盖,则重新实现的函数可以由Qt在内部调用 。如果您需要从javascript代码调用自己的creatWindow函数,这显然至关重要。

因此,如果您希望网页上的javascript程序能够创建和打开浏览器窗口类的实例,那么子类 QWebView并重新实现其createWindow功能(如上例所示)。

完全不需要createWindow功能来创建和显示QWebView(例如添加新标签页)。 QWebView只是一个用于显示网页的容器,并且像任何其他小部件一样被创建和显示。