杰拉斯的博客

完美解决PyQt中QWebView链接点击失效问题

杰拉斯 杰拉斯 | 时间:2013-12-17, Tue | 53,381 views
前端开发, 编程算法 

最近在尝试使用Python和PyQt做毕业设计中。。

一边感叹Qt的强大一边纠结资料的缺乏,特别是PyQt的资料就更少了,有一些容易遇到但又比较不好在网上查询到的问题我将在接下来的博文中总结一下。

在Qt中,在一个窗口中嵌入一个WebView是非常简单的(由于QWebView继承于QWidget,甚至将其作为一个窗口显示都是可以的):

import sys
from PyQt4.Qt import *
from PyQt4.QtWebKit import *

class WebView(QWebView):
	def __init__(self):
		super(WebView, self).__init__()
		self.load(QUrl('http://www.qq.com'))
		self.show()

if __name__ == '__main__':
	app = QApplication(sys.argv)
	webView = WebView()
	sys.exit(app.exec_())

看起来真特么的方便快捷,但随便点一点就会发现,target="_blank"的链接的点击均没有效果,网上查询了一下资料,很容易就找到一种方法:

调用QWebPage的setLinkDelegationPolicy方法,将其设置为QWebPage.DelegateAllLinks,就可以通过接收linkClicked信号来代理链接点击事件:

import sys
from PyQt4.Qt import *
from PyQt4.QtWebKit import *

class WebView(QWebView):
	def __init__(self):
		super(WebView, self).__init__()
		self.load(QUrl('http://www.qq.com'))
		self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
		self.page().linkClicked.connect(self.linkClicked)
		self.show()

	def linkClicked(self, url):
		self.load(url)

if __name__ == '__main__':
	app = QApplication(sys.argv)
	webView = WebView()
	sys.exit(app.exec_())

终于有反应了。。

噢卖瓜的,怎么所有的链接都是在本页打开了?!只有一个QUrl类型参数怎么确定这个链接是要在本页打开还是新窗口打开啊?!(╯‵□′)╯︵┻━┻

继续默默而淡定地寻找解决方案。。终于功夫不负有心人:

可以重写QWebPage的acceptNavigationRequest方法,通过这个方法的参数进行判断并对不同类型的链接点击做出处理:

import sys
from WebPage import *
from PyQt4.Qt import *
from PyQt4.QtWebKit import *

class WebView(QWebView):
	def __init__(self):
		super(WebView, self).__init__()
		self.setPage(WebPage())
		self.load(QUrl('http://www.qq.com'))
		self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
		self.page().linkClicked.connect(self.linkClicked)
		self.show()

	def linkClicked(self, url):
		self.load(url)

if __name__ == '__main__':
	app = QApplication(sys.argv)
	webView = WebView()
	sys.exit(app.exec_())
import webbrowser
from PyQt4.QtWebKit import *

class WebPage(QWebPage):
	def __init__(self):
		super(WebPage, self).__init__()

	def acceptNavigationRequest(self, frame, request, type):
		if(type == QWebPage.NavigationTypeLinkClicked):
			if(frame == self.mainFrame()):
				self.view().load(request.url())
			else:
				webbrowser.open(request.url().toString())
				return False
		return QWebPage.acceptNavigationRequest(self, frame, request, type)

如需转载请注明出处:杰拉斯的博客

10 条评论 »

  1. 开始研究PyQt了

  2. kiscore kiscore

    非常好,帮到我了!谢谢

  3. Tinkxid Tinkxid

    谢谢你提供的方法 但是我今天测试了一下 发现运行结束后会出现意外停止工作的对话框,不知道怎么处理 如果不调用WebPage(),就没事

  4. nameamtf nameamtf

    您好!冒昧打扰!
    我不懂python,刚学ruby,不知可否将如上代码专为ruby代码?
    多谢!

    1. 木有学过 Ruby 哦。。

  5. 世界线 世界线

    请问如果是pyqt5,这个程序该怎么写呢?链接点击后还是没反应

    1. 抱歉,PyQt5 我没有研究过哦。

  6. Charles Charles

    请问你解决这个问题了嘛

    1. 解决了呀,文章即是解决方案。