使用 pyside 克隆 QtWebKit Fancy Browser
这两天算真正接触 QtWebKit 的功能,实在是强大无比,加上 pyside 可以快速实现浏览器的很多功能。在网上找了 pyside + QtWebKit 的例子程序,其实能找到的例子很少。所以就借着克隆Qt自带的Fancy Browser 作为一个起点,写个pyside + QtWebKit的浏览器程序。
目前的状况:
- 实现了界面菜单的功能:调用Javascript进行图片翻转,a元素的高亮显示。增加高亮操作的取消功能。
- 修复Javascript执行无法立即返回的BUG。
- 初步实现网页保存为图片的功能。
1 #coding:utf8 2 3 import sys 4 from PySide import QtCore 5 from PySide import QtGui 6 from PySide import QtWebKit 7 from PySide import QtNetwork 8 from pprint import pprint 9 from PySide.QtGui import QImage 10 from PySide.QtGui import QPainter 11 from PySide.QtCore import QFile, QIODevice 12 13 class Mainwin(QtGui.QMainWindow): 14 def __init__(self, parent= None): 15 super(Mainwin, self).__init__( parent) 16 17 QtNetwork.QNetworkProxyFactory.setUseSystemConfiguration(True) 18 19 splitter = self.splitter = QtGui.QSplitter(self) 20 21 self.view = QtWebKit.QWebView(splitter) 22 #self.view.load("about:blank") 23 self.view.load("http://www.baidu.com") 24 self.view.loadStarted.connect(self.adjustLocation) 25 self.view.titleChanged.connect(self.adjustTitle) 26 self.view.loadProgress.connect(self.setProgress) 27 self.view.loadFinished.connect(self.adjustLocation) 28 29 self.locationEdit = QtGui.QLineEdit(self) 30 self.locationEdit.setSizePolicy(QtGui.QSizePolicy.Expanding, 31 self.locationEdit.sizePolicy().verticalPolicy()) 32 self.locationEdit.returnPressed.connect(self.changeLocation) 33 34 toolBar = self.addToolBar("Navigation") 35 toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Back)) 36 toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Forward)) 37 toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Reload)) 38 toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Stop)) 39 act = QtGui.QAction(self) 40 toolBar.addAction(act) 41 act.triggered.connect(self.loadPage) 42 toolBar.addWidget(self.locationEdit) 43 44 viewMenu = self.menuBar().addMenu("&View") 45 viewSourceAction = QtGui.QAction("Page Source", self) 46 viewSourceAction.triggered.connect(self.viewSource) 47 viewMenu.addAction(viewSourceAction) 48 49 savePageAction = QtGui.QAction("Save page as image", self) 50 savePageAction.triggered.connect(self.savePage) 51 viewMenu.addAction(savePageAction) 52 53 effectMenu = self.menuBar().addMenu("&Effect") 54 highlightLinkAction = QtGui.QAction("Highlight all links", self) 55 highlightLinkAction.setCheckable(True); 56 highlightLinkAction.toggled.connect(self.highlightAllLinks) 57 effectMenu.addAction(highlightLinkAction); 58 59 rotateImageAction = QtGui.QAction("Turn images upside down", self) 60 rotateImageAction.setCheckable(True); 61 rotateImageAction.toggled.connect(self.turnUpDownImages) 62 effectMenu.addAction(rotateImageAction) 63 64 # listview = QtGui.QListView() 65 # splitter.addWidget(listview) 66 # treeview = QtGui.QTreeView() 67 # splitter.addWidget(treeview) 68 textedit = QtGui.QTextEdit() 69 splitter.addWidget(textedit) 70 71 splitter.addWidget(self.view) 72 73 self.setCentralWidget(splitter) 74 75 sb = self.createStatusbar() 76 self.setStatusBar(sb) 77 page = self.view.page() 78 page.linkHovered.connect(self.linkHovered) 79 #act.connect(sb.showMessage) 80 frame = page.mainFrame() 81 frame.loadFinished.connect(self.load_finished) 82 83 def loadPage(self): 84 self.view.load("http://localhost") 85 86 def load_finished(self): 87 file = QFile("jquery.min.js"); 88 file.open(QIODevice.ReadOnly | QIODevice.Text); 89 jQuery = file.readAll().data(); 90 file.close(); 91 self.view.page().mainFrame().evaluateJavaScript(jQuery) 92 93 def linkHovered(self, p): 94 sb = self.statusBar() 95 sb.showMessage(p) 96 97 def viewSource(self): 98 accessManager = self.view.page().networkAccessManager() 99 request = QtNetwork.QNetworkRequest(self.view.url()) 100 reply = accessManager.get(request) 101 reply.finished.connect(self.slotSourceDownloaded) 102 103 def savePage(self): 104 size = self.view.page().mainFrame().contentsSize() 105 image = QImage(size, QImage.Format_ARGB32_Premultiplied) 106 image.fill(QtCore.Qt.transparent) 107 p = QPainter(image) 108 p.setRenderHint(QPainter.Antialiasing, 1) 109 p.setRenderHint(QPainter.TextAntialiasing, 1) 110 p.setRenderHint(QPainter.SmoothPixmapTransform, 1) 111 self.view.page().setViewportSize(self.view.page().mainFrame().contentsSize()) 112 self.view.page().mainFrame().render(p) 113 p.end(); 114 image.save("capture.png") 115 116 def turnUpDownImages(self, checked): 117 print checked 118 if (checked): 119 code = "$('img').each( function () { $(this).css('-webkit-transition', '-webkit-transform 1s'); $(this).css('-webkit-transform', 'rotate(180deg)') } ); null" 120 else: 121 code = "$('img').each( function () { $(this).css('-webkit-transition', '-webkit-transform 1s'); $(this).css('-webkit-transform', 'rotate(0deg)') } ); null" 122 self.view.page().mainFrame().evaluateJavaScript(code) 123 124 def highlightAllLinks(self, checked): 125 if checked: 126 code = "$('a').each( function () { $(this).css('background-color', 'yellow') }); null"; 127 else: 128 code = "$('a').each( function () { $(this).css('background-color', '') } ); null"; 129 self.view.page().mainFrame().evaluateJavaScript(code); 130 131 def slotSourceDownloaded(self): 132 reply = self.sender() 133 self.textEdit = QtGui.QTextEdit(None) 134 self.textEdit.setAttribute(QtCore.Qt.WA_DeleteOnClose) 135 self.textEdit.show() 136 self.textEdit.setPlainText(QtCore.QTextStream(reply).readAll()) 137 self.textEdit.resize(600, 400) 138 reply.deleteLater() 139 140 def createStatusbar(self): 141 sb = self.statusBar() 142 sb.progress = QtGui.QProgressBar() 143 sb.addPermanentWidget(sb.progress) 144 return sb 145 146 def adjustTitle(self): 147 self.setWindowTitle(self.view.title()) 148 149 def adjustLocation(self): 150 self.locationEdit.setText(self.view.url().toString()) 151 152 def changeLocation(self): 153 url = QtCore.QUrl.fromUserInput(self.locationEdit.text()) 154 self.view.load(url) 155 self.view.setFocus() 156 157 def setProgress(self, progress): 158 self.statusBar().progress.setValue(progress) 159 160 161 def main(): 162 app = QtGui.QApplication(sys.argv) 163 mw = Mainwin() 164 mw.show() 165 app.exec_() 166 167 168 if __name__ == "__main__": 169 main()
参考链接: