Python Browser Based Gui
IE (Trind)

comtypes

import wx
from wx.lib import iewin
#from comtypes.gen import MSHTML #modified
import comtypes.client # modified

class MyFrame(wx.Frame):
    def __init__(self):
        """Init IEHtmlWindow and set ourselves as event sink"""
        wx.Frame.__init__(self, None, title="IEHtmlWindow")
        self.ie = iewin.IEHtmlWindow(self)
        self.ie.AddEventSink(self)
        self.ie.Navigate("http://localhost/phpdev/test.html") # your URL here
    def DocumentComplete(self, this, pDisp, URL):
        """
        Called when the HTML document finishes loading.
        If we were waiting on any actions to perform
        when the document was complete, we execute them here.
        """
        MSHTML=comtypes.client.GetModule('mshtml.tlb') # modified
        element = self.ie.ctrl.Document.getElementById("my_element")
        element3 = element.QueryInterface(MSHTML.IHTMLElement3)
        element3.contentEditable = "true"
        pass
app = wx.App(False)
MyFrame().Show()
app.MainLoop()
OS Default

python的webbrowser模块和SendKeys模块
今天工作的时候突然遇到个问题,就尝试着按照领导所说要天马行空的想东西,于是那点scrapy的代码逐渐忘了的差不多了,想到用迅雷去下载一些东西,迅雷不知道怎么回事,但知道一点,他监控计算机浏览器,那么我想下载什么东西的时候,可以去获得一个遵循迅雷协议的地址,使用webbrowser模块打开这个地址就能调用迅雷做我自己的事情了。

import webbrowserwebbrowser.open('http://www.google.com.hk/')我用的是windows操作系统,关于这个模块,其实有更简单,更原始的提供给我们使用:

?if sys.platform[:3] == "win":
class WindowsDefault(BaseBrowser):
def open(self, url, new=0, autoraise=1):
try:
os.startfile(url)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True

_tryorder = []
_browsers = {}

# First try to use the default Windows browser
register("windows-default", WindowsDefault)

# Detect some common Windows browsers, fallback to IE
iexplore = os.path.join(os.environ.get("PROGRAMFILES", "C:\\Program Files"),
"Internet Explorer\\IEXPLORE.EXE")
for browser in ("firefox", "firebird", "seamonkey", "mozilla",
"netscape", "opera", iexplore):
if _iscommand(browser):
register(browser, None, BackgroundBrowser(browser))
操作系统不一样,在这里将有区别了,其实最有用的就一句,os.startfile(url),也能获得刚才我们使用webbrower模块open的效果,只不过推荐是使用webbrower的,因为他更具有兼容性。

想到这里,在加上键盘操作模块,SendKeys,在加上鼠标模拟操作,嗯,一定可以做出相当不错的东西。

wxpython 监听Activex事件

http://blog.csdn.net/xugangjava/article/details/7633766

最近在wxpython中嵌入Office Activex 可以用ActivexWarper来实现
不过py2exe打包的时候很麻烦,因为引用了mfc的dll,经常是RunTime Error
只好换成ActiveXCtrl

BaseViewer就是一个wxPanel
这个Office控件里面有很多的事件 需要用到,下面是控件的makepy的导出片段

class _DEDOfficeEvents:  
    """Event interface for Edraw Office Viewer Component"""
    CLSID = CLSID_Sink = IID('{321F8EAC-5B6C-40FD-8B04-289FEF4C28A5}')  
    coclass_clsid = IID('{7677E74E-5831-4C9E-A2DD-9B1EF9DF2DB4}')  
    _public_methods_ = [] # For COM Server support  
    _dispid_to_func_ = {  
               27 : "OnSlideSelectionChanged",  
               28 : "OnColorSchemeChanged",  
               14 : "OnDownloadFileComplete",  
               26 : "OnSlideShowNextSlide",  
                3 : "OnBeforeDocumentOpened",  
               17 : "OnSheetActivate",  
                5 : "OnBeforeDocumentClosed",  
               20 : "OnSheetChange",  
                8 : "OnWindowBeforeDoubleClick",  
                7 : "OnWindowBeforeRightClick",  
               16 : "OnIESecurityReminder",  
               23 : "OnSlideShowBegin",  
               13 : "OnBeforeDownloadFile",  
                4 : "OnDocumentOpened",  
               24 : "OnSlideShowEnd",  
               19 : "OnSheetCalculate",  
               18 : "OnSheetDeactivate",  
               12 : "OnWindowDeactivate",  
                1 : "OnNotifyCtrlReady",  
               25 : "OnSlideShowNextBuild",  
               10 : "OnDocumentBeforePrint",  
               22 : "OnPresentationNewSlide",  
                2 : "OnNewDocument",  
               29 : "OnSlideShowNextClick",  
                6 : "OnBeforeDocumentSaved",  
               11 : "OnWindowActivate",  
               21 : "OnWorkbookNewSheet",  
               15 : "OnUploadComplete",  
                9 : "OnWindowSelectionChange",  
        }  
 
    def __init__(self, oobj = None):  
        if oobj is None:  
            self._olecp = None  
        else:  
            import win32com.server.util  
            from win32com.server.policy import EventHandlerPolicy  
            cpc=oobj._oleobj_.QueryInterface(pythoncom.IID_IConnectionPointContainer)  
            cp=cpc.FindConnectionPoint(self.CLSID_Sink)  
            cookie=cp.Advise(win32com.server.util.wrap(self, usePolicy=EventHandlerPolicy))  
            self._olecp,self._olecp_cookie = cp,cookie  
    def __del__(self):  
        try:  
            self.close()  
        except pythoncom.com_error:  
            pass  
    def close(self):  
        if self._olecp is not None:  
            cp,cookie,self._olecp,self._olecp_cookie = self._olecp,self._olecp_cookie,None,None  
            cp.Unadvise(cookie)  
    def _query_interface_(self, iid):  
        import win32com.server.util  
        if iid==self.CLSID_Sink: return win32com.server.util.wrap(self)

如果我们要监听OnBeforeDocuemtnOpened
下面是我的的窗口的代码,BaseViewer就是一个wxPanel,定义一个BeforeDocuemtnOpened
那么在文档打开前就会执行BeforeDocuemtnOpened方法,
ActievxCtrl初始化源代码里面有 self.AddEventSink(self) ,所以控件会在OfficeViewer里找对应的Event调用

########################################################################  
 
class OfficeViewer(BaseViewer):  
 
    def __init__(self,parent=None,filename='',dir=BaseViewer.EDITOR_DIR):  
        BaseViewer.__init__(self,dir,parent)  
        sizer = wx.BoxSizer(wx.VERTICAL)  
        self.officeAtx=ActiveXCtrl(self,'EDOFFICE.EDOfficeCtrl.1',-1)  
 
        sizer.Add(self.officeAtx, 1, wx.EXPAND)  
        self.SetSizer(sizer)  
 
        self.officeAtx.AddEventSink(self)  
        self.officeAtx=self.officeAtx.ctrl  
 
        self.temp=''  
        self.filename=filename  
        self.dir=dir  
 
    def BeforeDocumentOpened(self):  
 
        """禁止打印命令"""  
        MessageBox('Before Open')  
        self.officeAtx.DisableFileCommand(0x00000200,True)
Chrome/Safari (Webkit)

http://sourceforge.net/projects/wxwebkit/

QtWebkit

http://blog.linux.org.tw/~jserv/archives/002026.html

Jserv's blog
« 「我愛 Git」簡報上線 | 回到主頁面 | 以 ptrace 系統呼叫來追蹤/修改行程 »
May 21, 2008

透過 Python 體驗 QtWebKit 快速開發
稍早寫過一篇文章 [QtWebKit: 將 Web 2.0 技術帶入行動通訊的系統設計],談及 Trolltech 對於 Qt Framework 與 WebKit 的整合,提供獨到的設計,不僅可很容易在應用程式中嵌入 WebKit 所帶來的 Web 2.0 網路服務外,還可作無接縫 (seamless) 的整合。不過前文並未解說整合細節,這裡就帶出具體而微的範例,體驗 QtWebKit 的技術突破與先進的特徵,恰好下個月要出席 [PycTW2008],那麼程式語言選用 Python 作為練習。

日前 Trolltech 正式釋出 Qt 4.4,業已整合 QtWebKit,與 Qt framework 銜接的 [PyQt] 日前也推出 v4.4.2,即可透過 Python 來釋放 QtWebKit 的威力。Qt framework 一向最為人知的賣點就是 "signals-slots" 機制,自然在 PyQt 也少不了,而且還透過 [SIP] Python 模組,免去了許多語言層面的繁文縟節。首先,要存取 PyQt 的模組很容易,只要如此宣告:
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
在這個範例,筆者設想的操作情境為,展示如何透過 WebKit 顯示 HTML element 與 JavaScript,以及透過 iframe tag 嵌入 Google 首頁,在使用者互動的部份,透過 Javascript 建立對話框,並試著與 Python 的程式通訊。於是,我們建立一個 class 來專門描繪網頁,程式碼如下:

class BrowserScreen(QWebView):
    def __init__(self):
        QWebView.__init__(self)
 
        self.resize(800, 600)
        self.show()
        self.setHtml("""
           <script>function message() { return "Clicked!"; }</script>
           <h1>QtWebKit + Python sample program</h1>
           <input type="button" value="Click JavaScript!" 
                  onClick="alert('[javascript] ' + message())"/>
           <input type="button" value="Click Python!" 
                  onClick="python.alert('[python] ' +
                                        python.message())"/>
           <br />
           <iframe src="http://www.google.com/"
                   width="750" height="500"
                   scrolling="no"
                   frameborder="0"
                   align="center"></iframe>
        """)

我們定義的 class 繼承自 QtWebKit 中的 class QWebView,在初始化時,即呼叫 resize(), show(), setHTML() 等 method。此外,與其說上述程式列表為 Python 程式語言,不如說就是 HTML 網頁原始碼。熟悉網頁程式設計者,一眼就可發現我們在兩個 input button 上建立 Javascript 事件關聯,其中一個呼叫 alert() method 來顯示對話框,而另一個則比較特別:
onClick="python.alert('[python] ' +
python.message())
這邊的 "python.alert" 與 "python.message" 就使用了 PyQt + QtWebKit 的專有功能,意思是按下 button 時,會呼叫 python 物件的 message method,而這個 "python" 物件可動態在欲嵌入 WebKit 的 Python 程式中傳入物件,當然,可有頗多變化。筆者這裡僅作字串回傳顯示的動作,不過即使如此,還是有兩項技術細節要思考:
QtWebKit 的 class QWebView,其最主要的目標是走訪 HTML 個別 element 並描繪網頁,也就是內部維護著 DOM (Document Object Model),包含我們剛剛看見的那兩個 input button 也在其中
Javascript (或 ECMAscript) 內部有自己的字串與物件表示,Python 也有字串,而 Qt framework 更有 class QString,那麼,該如何建立起彼此的關聯呢?至少,在筆者設計的情境中,就得考慮字串與物件遊走於這三方所需面對的議題
實際上,得面對的問題不只如此,不過 QtWebKit + PyQt 都幫我們處理掉,所以,筆者只要另行提供 Python 物件並交予 QtWebKit 即可。以下是傳入到 WebKit 的物件相關的 Python 程式碼:
class PythonJS(QObject):
pyqtSignals = ("contentChanged(const QString &)")
@pyqtSignature("QString")
def alert(self, msg):
self.emit(SIGNAL('contentChanged(const QString &)'), msg)

@pyqtSignature("", result="QString")
def message(self):
return "Click!"
這個名為 PythonJS 的 class,繼承自 class QObject。透過 PyQt,我們宣告一個自訂的 signal: "contentChanged(const QString &)",這不需要額外的 moc compiler 即可有對應的 metadata 關聯。剛剛在 class BrowserScreen 的 HTML 程式列表中,所提及的 "python.alert" method 就定義於此,筆者依據 Qt 的 Signals-Slot 機制,去 emit 出 "contentChanged(const QString &)" 這個 signal,並將 alert() method 後方的字串 (const QString & 型態) 一併傳出,也可見到 PyQt 中宣告 msg 參數型態為 "QString"。同樣,PythonJS::message method 也是如此,依據上方的執行順序來看,會先呼叫 PythonJS::message() 在將傳回的 QString 字串透過 QtWebKit 內部的轉換,變成 JavaScript 的字串並作物件的合成動作 (即 "'[python] ' + python.message()" 陳述),並將得到的 JavaScript 字串傳遞給 QtWebKit 外部的 Python 物件,呼叫 PythonJS::alert() method,當然,這時候要將 JavaScript 字串轉變成 Pthon 可處理的 QString 字串。

撰寫了以上兩個 class,程式幾乎完成了,只要將兩者整合起來即可,為了增加視覺上的比較效果,筆者透過 Qt 4.4 提供的 System Tray (在 X11/FreeDesktop 的術語為 "Notification Area") 來作訊息顯示的動作。所以修改了 class BrowserScreen,追加兩個 method,程式碼如下:
class BrowserScreen(QWebView):
def init(self):
QWebView.init(self)

self.createTrayIcon()

self.trayIcon.show()

def createTrayIcon(self):
self.trayIcon = QSystemTrayIcon(self)
self.trayIcon.setIcon(QIcon("images/trash.svg"))

def showMessage(self, msg):
self.trayIcon.showMessage("This is Python", msg,
QSystemTrayIcon.MessageIcon(0), 15 * 1000)
BrowserScreen::createTrayIcon() method 透過 class QSystemTrayIcon 要求系統配置 system tray,筆者設定了 SVG 圖檔 (向量繪圖,所以不需要考慮顯示端的空間尺寸),而 BrowserScreen::showMessage() method 看似不相關,僅是顯示訊息的動作,稍後,我們可透過 Qt 的 Signals-Slots,將 QtWebKit 中的 DOM/JavaScript 事件與此 method 給予 "connect" 起來。

最後一個部份,就是畫龍點睛了,以下是 main 程式列表:
if name=='main':
import sys

app = QApplication(sys.argv)

browser = BrowserScreen()
pjs = PythonJS()
browser.page().mainFrame().addToJavaScriptWindowObject("python", pjs)

QObject.connect(pjs, SIGNAL("contentChanged(const QString &)"),
browser.showMessage)

sys.exit(app.exec_())
重點當然是從前面兩個 class 建立 Python 物件,也就是 "browser" 與 "pjs",整個程式最巧妙之處,就在於以下這行:
browser.page().mainFrame().addToJavaScriptWindowObject(
"python", pjs)
這也是 QtWebKit 技術的「火力展示」,原來前面的 HTML 列表的 JavaScript 程式的 "python" 物件,就是甫建立的 "pjs" 物件,而下一行也充滿著驚喜:
QObject.connect(pjs, SIGNAL("contentChanged(const QString &)"),
browser.showMessage)
class PythonJS 所生的物件 "pjs" 裡頭的 signal "contentChanged" 被連結 (connect) 到 class BrowserScreen 所生的物件 "browser" 裡頭的 slot "showMessage",原本只是平淡無奇的 PyQt 敘述,但因為 "pjs" 物件被傳入 QtWebKit,WebKit 所描繪的網頁 (範例即 Google 首頁) 有完整的 DOM/JavaScript,依據之前的 HTML 程式列表,已建立這兩者的關聯,如今,再將 PyQt 的事件一舉打通。是此,Python/PyQt - QtWebKit - DOM/JavaScript 的關聯就建立了,咱們來體驗看看,以下是操作時的圖例:

在 system tray 多了一個綠色、類似資源回收桶的圖樣,而主畫面就如預期,就是 QtWebKit。是的,寫 UI 就是這麼簡單,只要 HTML tag 加上 iframe,頓時有聲有色,為了要證明這不是紙老虎,咱們按一下左方的 "Click Javascript!" input button,會得到下方螢幕輸出:

這就是 Javascript 裡頭呼叫 alert() method,展示了 QtWebKit 的基本能力,最後我們看看剛剛張羅許久的展示,當按下 "Click Python!" input button 後…

注意到 system tray 下方彈跳出黃色對話訊息,別小看這個,這可是歷經 Python/PyQt - QtWebKit - DOM/JavaScript 等部份,顯示於我們眼前的。我們也可發現,QtWebKit 要與桌面整合並產生有效的互動,只需要上述這一些程式碼即可,透過 Python 體驗 QtWebKit 快速開發,看來很棒呢。

取得上述程式碼加上 SVG 圖檔: [pyqtwebkit-sample.tar.bz2],因為 Qt framework 與 PyQt 都以 GNU GPL 授權發行,本範例也是如此。

Expose Python Class to QtWebkit JS

Exposing Qt Classes to QtWebKit
On the PyQt mailing list, Christophe asked for examples that show Qt objects being added to QtWebKit for use with JavaScript.
A simple example of this can be found on Mario Boikov's blog: Calling Python from JavaScript in PyQt's QWebkit.
The following code is an extreme example of this which uses a wrapper class to expose the QFile class and its open() and readAll() methods to JavaScript.

Toggle line numbers

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
 
js = \
"""
QFile = function(path)
{
    var name = _QFile_factory.createQFile(path);
    document.getElementById("name").innerText = name;
    return _wrapper;
}
"""
 
html = \
"""<html>
<head>
  <title>JavaScript Qt Wrapper Test</title>
  <script type="text/javascript">
    function readFile()
    {
        var file1 = QFile("/home/user/temp.txt");       # <- put a path to a text file here
        var file2 = QFile("qtwrappertest.py");          # <- refer to this script or some other text file here
        var area1 = document.getElementById("contents1");
        var area2 = document.getElementById("contents2");
        file1.open(1);
        file2.open(1);
        area1.innerText = file1.readAll;
        area2.innerText = file2.readAll;
        file1.close();
        file2.close();
    }
  </script>
</head>
<body>
  <h1>JavaScript Qt Wrapper Test</h1>
  <p id="name"></p>
  <pre id="contents1">
     [Click the button to show the contents of a file.]
  </pre>
  <pre id="contents2">
     [Click the button to show the contents of a file.]
  </pre>
  <input type="button" onclick="readFile()" value="Click me">
</body>
</html>
"""
 
class FileWrapper(QObject):
 
    def __init__(self, path):
 
        QObject.__init__(self)
        self.file = QFile(path)
 
    @pyqtSignature("open(int)")
    def open(self, flags):
 
        return self.file.open(QIODevice.OpenModeFlag(flags))
 
    def readAll(self):
 
        return str(self.file.readAll())
 
    readAll = pyqtProperty("QString", readAll)
 
    @pyqtSignature("close()")
    def close(self):
 
        self.file.close()
 
class Browser(QWebView):
 
    def __init__(self, parent = None):
 
        QWebView.__init__(self, parent)
        self.connect(self, SIGNAL("loadFinished(bool)"), self.prepareJavaScript)
 
    def prepareJavaScript(self, ready):
 
        if not ready:
            return
 
        self.page().mainFrame().addToJavaScriptWindowObject("_QFile_factory", self)
        self.page().mainFrame().evaluateJavaScript(js)
 
    @pyqtSignature("createQFile(QString)")
    def createQFile(self, path):
 
        self.page().mainFrame().addToJavaScriptWindowObject("_wrapper", FileWrapper(path))
        return "_wrapper"
 
if __name__ == "__main__":
 
    app = QApplication(sys.argv)
    browser = Browser()
    browser.setHtml(html)
    browser.show()
    sys.exit(app.exec_())
QtWebkit with Plugin

http://www.th7.cn/Program/Python/2011-07-07/28856.shtml

PyQt写的浏览单web页面的browser

2012年12月22日联系商易上海电子商务网站建设,了解更多

PyQt写的浏览单web页面的browser - 代码分享 - 开源中国社区

巫云
PyQt写的浏览单web页面的browser
巫云 公布于 2011年06月13日 16时, 6评/2080阅
分享到
新浪微博腾讯微博
收藏+7
踩 顶 0
借判别人代码批改的,模仿了简单的浏览器道理

共同窗习,共同进步。
标签: QT Python Web PyQt
代码片段(3)

    view source
    print001     #!/usr/bin/env python
    002      
    003     import sys
    004      
    005     PyQt4 import QtCoreQtGui
    006     browser import Ui_HttpWidget
    007      
    008     class httpWidgetQtGui.QWidget):
    009         def __init__selfparent=None):
    010             superhttpWidgetself).__init__parent011             self.ui = Ui_HttpWidget()
    012             self.ui.setupUiself013              
    014             L = self.layout()
    015             L.setMargin0016             self.ui.horizontalLayout.setMargin5017              
    018             url = ""http://google.com""
    019             self.ui.url.setTexturl020              
    021             self.ui.webView.setUrlQtCore.QUrlurl))
    022              
    023             self.ui.back.setEnabledFalse024             self.ui.next.setEnabledFalse025              
    026             QtCore.QObject.connectself.ui.backQtCore.SIGNAL"clicked()"),\
    027                             self.back028             QtCore.QObject.connectself.ui.nextQtCore.SIGNAL"clicked()"),\
    029                             self.next030             QtCore.QObject.connectself.ui.urlQtCore.SIGNAL"returnPressed()"),\
    031                             self.url_changed032             QtCore.QObject.connectself.ui.webViewQtCore.SIGNAL"linkClicked(const QUrl&)"),\
    033                             self.link_clicked034             QtCore.QObject.connectself.ui.webViewQtCore.SIGNAL"urlChanged(const QUrl&)"),\
    035                             self.link_clicked036             QtCore.QObject.connectself.ui.webViewQtCore.SIGNAL"loadProgress(int)"),\
    037                             self.load_progress038             QtCore.QObject.connectself.ui.webViewQtCore.SIGNAL"titleChanged(const QString&)"),\
    039                             self.title_changed040             QtCore.QObject.connectself.ui.reloadQtCore.SIGNAL"clicked()"),\
    041                             self.reload_page042             QtCore.QObject.connectself.ui.stopQtCore.SIGNAL"clicked()"),\
    043                             self.stop_page044              
    045             QtCore.QMetaObject.connectSlotsByNameself046              
    047         def url_changedself):
    048             page = self.ui.webView.page()
    049             history = page.history()
    050             if history.canGoBack():
    051                 self.ui.back.setEnabledTrue052             else:
    053                 self.ui.back.setEnabledFalse054                  
    055             if history.canGoForward():
    056                 self.ui.next.setEnabledTrue057             else:
    058                 self.ui.next.setEnabledFalse059                  
    060             url = self.ui.url.text()
    061             self.ui.webView.setUrlQtCore.QUrlurl))
    062              
    063         def stop_pageself):
    064             self.ui.webView.stop()
    065              
    066         def title_changedselftitle):
    067             self.setWindowTitletitle068              
    069         def reload_pageself):
    070             self.ui.webView.setUrlQtCore.QUrlself.ui.url.text()))
    071              
    072         def link_clickedselfurl):
    073             page = self.ui.webView.page()       
    074             self.__setHistButtonStatepageself.ui.backself.ui.next075                  
    076             self.ui.url.setTexturl.toString())
    077              
    078         def load_progressselfload):
    079             if load == 100:
    080                 self.ui.stop.setEnabledFalse081             else:
    082                 self.ui.stop.setEnabledTrue083                  
    084         def backself):
    085             page = self.ui.webView.page()
    086             self.__setHistButtonStatepageself.ui.backNone087             history = page.history()
    088             history.back()
    089                  
    090         def nextself):
    091             page = self.ui.webView.page()
    092             history = page.history()
    093             history.forward()
    094              
    095             self.__setHistButtonStatepageNoneself.ui.next096                
    097control the navigator buttons enability
    098         def __setHistButtonStateselfpagebacknext):
    099             history = page.history()
    100              
    101             if back is not None:
    102                 if history.canGoBack():
    103                     back.setEnabledTrue104                 else:
    105                     back.setEnabledFalse106                  
    107             if next is not None:
    108                 if history.canGoForward():
    109                     next.setEnabledTrue110                 else:
    111                     next.setEnabledFalse112              
    113                  
    114     if __name__ == "__main__":
    115         app = QtGui.QApplicationsys.argv116         myapp = httpWidget()
    117         myapp.show()
    118         sys.exitapp.exec_())
    119      
    120      
    121      
    122             
 
    [代码] QtDesigner生成的界面代码
 
    01     # -*- coding: utf-8 -*-
    02      
    03Form implementation generated reading ui file ""httpWidget.ui""
    0405Created: Mon Jun 13 15:26:37 2011
    06by: PyQt4 UI code generator 4.8.4
    0708WARNING! All changes made in this file will be lost!
    09      
    10     PyQt4 import QtCoreQtGui
    11      
    12     try:
    13         _Utf8 = QtCore.QString.Utf8
    14     except AttributeError:
    15         _Utf8 = lambda s: s
    16      
    17     class Ui_HttpWidgetobject):
    18         def setupUiselfHttpWidget):
    19             HttpWidget.setObjectName_Utf8"HttpWidget"))
    20             HttpWidget.resize63633621             self.verticalLayout = QtGui.QVBoxLayoutHttpWidget22             self.verticalLayout.setObjectName_Utf8"verticalLayout"))
    23             self.horizontalLayout = QtGui.QHBoxLayout()
    24             self.horizontalLayout.setObjectName_Utf8"horizontalLayout"))
    25             self.back = QtGui.QPushButtonHttpWidget26             icon = QtGui.QIcon()
    27             icon.addPixmapQtGui.QPixmap_Utf8"back.png")), QtGui.QIcon.NormalQtGui.QIcon.Off28             self.back.setIconicon29             self.back.setObjectName_Utf8"back"))
    30             self.horizontalLayout.addWidgetself.back31             self.next = QtGui.QPushButtonHttpWidget32             self.next.setEnabledTrue33             self.next.setLayoutDirectionQtCore.Qt.RightToLeft34             icon1 = QtGui.QIcon()
    35             icon1.addPixmapQtGui.QPixmap_Utf8"next.png")), QtGui.QIcon.NormalQtGui.QIcon.Off36             self.next.setIconicon137             self.next.setObjectName_Utf8"next"))
    38             self.horizontalLayout.addWidgetself.next39             self.stop = QtGui.QPushButtonHttpWidget40             icon2 = QtGui.QIcon()
    41             icon2.addPixmapQtGui.QPixmap_Utf8"stop.png")), QtGui.QIcon.NormalQtGui.QIcon.Off42             self.stop.setIconicon243             self.stop.setObjectName_Utf8"stop"))
    44             self.horizontalLayout.addWidgetself.stop45             self.reload = QtGui.QPushButtonHttpWidget46             icon3 = QtGui.QIcon()
    47             icon3.addPixmapQtGui.QPixmap_Utf8"reload.png")), QtGui.QIcon.NormalQtGui.QIcon.Off48             self.reload.setIconicon349             self.reload.setObjectName_Utf8"reload"))
    50             self.horizontalLayout.addWidgetself.reload51             self.url = QtGui.QLineEditHttpWidget52             self.url.setObjectName_Utf8"url"))
    53             self.horizontalLayout.addWidgetself.url54             self.verticalLayout.addLayoutself.horizontalLayout55             self.webView = QtWebKit.QWebViewHttpWidget56             self.webView.setUrlQtCore.QUrl_Utf8"about:blank")))
    57             self.webView.setObjectName_Utf8"webView"))
    58             self.verticalLayout.addWidgetself.webView59      
    60             self.retranslateUiHttpWidget61             QtCore.QMetaObject.connectSlotsByNameHttpWidget62      
    63         def retranslateUiselfHttpWidget):
    64             HttpWidget.setWindowTitleQtGui.QApplication.translate"HttpWidget""Form"NoneQtGui.QApplication.UnicodeUTF8))
    65             self.back.setToolTipQtGui.QApplication.translate"HttpWidget""Back"NoneQtGui.QApplication.UnicodeUTF8))
    66             self.back.setTextQtGui.QApplication.translate"HttpWidget""Back"NoneQtGui.QApplication.UnicodeUTF8))
    67             self.next.setToolTipQtGui.QApplication.translate"HttpWidget""Next"NoneQtGui.QApplication.UnicodeUTF8))
    68             self.next.setTextQtGui.QApplication.translate"HttpWidget""    Next"NoneQtGui.QApplication.UnicodeUTF8))
    69             self.stop.setToolTipQtGui.QApplication.translate"HttpWidget""Stop"NoneQtGui.QApplication.UnicodeUTF8))
    70             self.stop.setTextQtGui.QApplication.translate"HttpWidget""Stop"NoneQtGui.QApplication.UnicodeUTF8))
    71             self.reload.setToolTipQtGui.QApplication.translate"HttpWidget""Reload"NoneQtGui.QApplication.UnicodeUTF8))
    72             self.reload.setTextQtGui.QApplication.translate"HttpWidget""Reload"NoneQtGui.QApplication.UnicodeUTF8))
    73      
    74     PyQt4 import QtWebKit

[图片] TM截图.jpg

为QT的Webkit 编写插件 - Braincol - 博客园

为QT的Webkit 编写插件

为了容许的QWebView加载插件,必须使能QWebView的Javascript和Plugins属性,使能办法为:

QWebSettings::globalSettings()->setAttribute(QWebSettings::JavascriptEnabled,true);
QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled,true);

或者

//这里假设webView是QWebView的对象:QWebView *webView;
webView->settings()->setAttribute(QWebSettings::JavascriptEnabled,true);
webView->settings()->setAttribute(QWebSettings::PluginsEnabled,true);

然后为QWebView添加插件工厂,这个插件工厂中包含了QWebView中所有可用的插件库,当然这个插件工厂中包含哪些插件得由我们法度员来定。添加插件工厂的办法为:

//为QWebView添加插件工厂,即告诉QWebView有哪些插件可用。

//这里的 WebkitPluginFactory 是Qt的虚类 QWebPluginFactory 的实现类,后面会讲到这个类。

webView->page()->setPluginFactory(new WebkitPluginFactory(this));

下面我们就来实现这个插件工厂类WebkitPluginFactory, 首要须要实现的就是 QWebPluginFactory 中的两个虚函数:

virtual QObject *create(const QString &mimeType, const QUrl &url,

const QStringList &argumentNames,const QStringList & argumentValues )const = 0;

virtual QList<Plugin> plugins () const = 0;

plugins() 办法为获取所有可用的插件列表, create() 办法例按照mimeType等参数来决意创建响应的插件。下面给出这个类的实现代码:

webkitpluginfactory.h :

ifndef WEBKITPLUGINFACTORY_Hdefine WEBKITPLUGINFACTORY_Hinclude <QWebPluginFactory>
 
    #include <QUrl>
 
    #include "webkitplugininterface.h"
 
    class WebkitPluginFactory : public QWebPluginFactory
 
    {
 
        Q_OBJECT
 
    public:
 
        WebkitPluginFactoryQObject *parent = 0);
 
        QObject *createconst QString & mimeTypeconst QUrl & urlconst QStringList & argumentNamesconst QStringList & argumentValuesconst;
 
        QList<QWebPluginFactory::Plugin> plugins () const;
 
    private:
 
        // 插件列表
 
        mutable QList<QList<QWebPluginFactory::Plugin> > pluginslist;
 
        //插件接口,这个接口是我们自定义的插件的赞成接口。
 
        //这个接口在后面会讲到。
 
        mutable QList<WebKitPluginInterface *> interfaces;
 
    };
 
    #endif // WEBKITPLUGINFACTORY_H
 
    webkitpluginfactory.cpp :
 
    #include "webkitpluginfactory.h"include <QPluginLoader>
 
    #include <QDebug>
 
    #include <QDir>
 
    WebkitPluginFactory::WebkitPluginFactoryQObject *parent) :
 
            QWebPluginFactory()
 
    {
 
        qDebug()<<"debug : WebkitPluginFactory";
 
    }
 
    QList<QWebPluginFactory::Plugin> WebkitPluginFactory::plugins () const
 
    {
 
        //const char * s=getenv("BROWSER_PLUGIN_DIR");
 
        const char *s = "/home/nxx/FlashPlugin-build-desktop";
 
        static bool isFirst=true;
 
        static QList<QWebPluginFactory::Plugin> plugins;
 
        if(!isFirst{
 
            return plugins;
 
        }
 
        isFirst=false;
 
        plugins.clear();
 
        QString spath;
 
        ifsspath=s;
 
        else
 
            spath=".";
 
        QDir dirspath);
 
        QStringList filters;
 
        QString abspath=dir.absolutePath();
 
        qDebug()<<abspath;
 
        //获取指定目次下的所有插件,linux下是插件库的后缀为so,windows下则是dll,
 
        filters<<"lib*.so";
 
        QStringList files=dir.entryListfilters);
 
        qDebug()<<"files: "<<files;
 
        foreachQString filefiles{
 
            qDebug()<<QLibrary::isLibraryfile);
 
            file=dir.filePathfile);
 
            qDebug()<<"path: "<<file;
 
            QPluginLoader loaderfile);
 
            QObject * obj= loader.instance();
 
            ifobj==0qDebug()<<"error: "<<loader.errorString();
 
            //下面是载入自定义的接口,只有如许才干支撑动态插件创建,若是固定死了,将晦气于扩大
 
            WebKitPluginInterface * interface= qobject_cast<WebKitPluginInterface*> (obj);
 
            ifinterface==0{
 
                qDebug()<<"ignore error when loading so" ;
 
                continue;
 
            }
 
            qDebug()<<"load plugins: "<<interface->plugins().at0).name;
 
            plugins.appendinterface->plugins());
 
            pluginslist.appendinterface->plugins());
 
            interfaces.appendinterface);
 
        }
 
        ifplugins.isEmpty()){
 
            qDebug()<<"no plugins is loaded!";
 
        }
 
        return plugins;
 
    }
 
    QObject * WebkitPluginFactory::createconst QString & mimeTypeconst QUrl & urlconst QStringList &                argumentNamesconst QStringList & argumentValuesconst
 
    {
 
        forint i=0;i<pluginslist.size();i++)
 
        {
 
            forint j=0;j< pluginslist[i].size();j++)
 
            {
 
                foreachQWebPluginFactory::MimeType mtpluginslist[i][j].mimeTypes{
 
                    ifmt.name == mimeType//更具MIME类型,创建响应的插件实例
 
                        return interfaces[i]->
 
                                createmimeTypeurlargumentNamesargumentValues);
 
                }
 
            }
 
        }
 
        return NULL; //若是没有,直接返回NULL,webkit会进行处理惩罚的
 
    }
 
    下面就可以开端编写插件库。起首我们定义插件的同一接口,然后每个插件类只需实现该接口就行了,如许有利于扩大插件库。
 
    自定义的插件接口:
 
    webkitplugininterface.h :
 
    #ifndef WEBKITPLUGININTERFACE_Hdefine WEBKITPLUGININTERFACE_Hinclude <QWebPluginFactory>
 
    class WebKitPluginInterface
 
    {
 
    public:
 
        virtual ~WebKitPluginInterface(){};
 
        virtual QList<QWebPluginFactory::Plugin> plugins()const =0;
 
        virtual QObject *createconst QString &mimeTypeconst QUrl &urlconst QStringList &argumentNamesconst QStringList &argumentValuesconst =0;
 
    };
 
    //声明WebKitPluginInterface为一个接口
 
    Q_DECLARE_INTERFACEWebKitPluginInterface"com.plugin.uvchip.www/1.0")
 
    #endif // WEBKITPLUGININTERFACE_H
 
    上方的那段代码中的Q_DECLARE_INTERFACE() 是在定义接口是必须添加声明。下面是Qt对这个宏的申明:
 
        Q_DECLARE_INTERFACEClassNameIdentifierThis macro associates the given Identifiera string literalto the interface class called ClassName. The Identifier must be unique. 
 
    下面我们开端实现这个接口:
    我们将flashplugin编译成库,如许就可以供插件工厂WebkitPluginFactory加载接见了。
 
    flashplugin.h :
 
    #ifndef FLASHPLUGIN_Hdefine FLASHPLUGIN_Hif definedFLASHPLUGIN_LIBRARY)
 
    #  define FLASHPLUGINSHARED_EXPORT Q_DECL_EXPORTelsedefine FLASHPLUGINSHARED_EXPORT Q_DECL_IMPORTendifinclude "webkitplugininterface.h"include <QtPlugin>
 
    class FLASHPLUGINSHARED_EXPORT FlashPlugin : public QObjectpublic WebKitPluginInterface  {
 
            Q_OBJECT
 
            Q_INTERFACESWebKitPluginInterface//声明WebKitPluginInterface是一个接口
 
        public:
 
            FlashPlugin(): WebKitPluginInterface(){};
 
            ~FlashPlugin(){};
 
            QList<QWebPluginFactory::Plugin> plugins()const ;
 
            QObject *createconst QString &mimeTypeconst QUrl &urlconst QStringList &argumentNamesconst QStringList &argumentValuesconst ;
 
    };
 
    #endif // FLASHPLUGIN_H
 
    flashplugin.cpp :
 
    #include "flashplugin.h"include <QTextEdit>
 
    #include <QUrl>
 
    #include <QDebug>
 
    QList<QWebPluginFactory::Plugin> FlashPlugin::plugins()const
 
    {
 
        QWebPluginFactory::MimeType mimeType;
 
        mimeType.name="application/x-shockwave-flash";
 
        mimeType.description=QObject::tr"flash");
 
        mimeType.fileExtensions.append".flv");
 
        mimeType.fileExtensions.append".f4v");
 
        mimeType.fileExtensions.append".swf");
 
        QList<QWebPluginFactory::MimeType> mimeTypes;
 
        mimeTypes.appendmimeType);
 
        QWebPluginFactory::Plugin plugin;
 
        plugin.name=QObject::tr"External Video viewer plugin");
 
        plugin.description=QObject::tr"Use vlc to open video files !!!");
 
        plugin.mimeTypes=mimeTypes;
 
        QList<QWebPluginFactory::Plugin> plugins ;
 
        plugins.appendplugin);
 
        return plugins;
 
    }
 
    QObject *FlashPlugin::createconst QString &mimeTypeconst QUrl &urlconst QStringList &argumentNamesconst QStringList &argumentValuesconst
 
    {
 
        QTextEdit * edit= new QTextEdit();
 
        edit->setObjectName"我是插件");
 
        edit->setPlainTextmimeType + " :  " + url.toString() +"\n\n"
 
             +QString::Utf8"这里底本是须要adobeFlash插件的,")+"\n"
 
             +QString::Utf8"但如今调换成了我们自定义的插件(QTextEdit插件了)。") );
 
        Q_UNUSEDargumentNames);
 
        Q_UNUSEDargumentValues);
 
        qDebug()<<"create flash plugin";
 
        return edit;
 
    }
 
    //Q_EXPORT_PLUGIN2()必不成少,
 
    //只有如许FlashPlugin插件类才为外部可见,插件名为WebkitPluginFlash
 
    Q_EXPORT_PLUGIN2WebkitPluginFlashFlashPlugin

Q_EXPORT_PLUGIN2 在Qt帮助文档中的申明如下:

Q_EXPORT_PLUGIN2 ( PluginName, ClassName )
This macro exports the plugin class ClassName for the plugin specified by PluginName. The value of PluginName should correspond to the TARGET specified in the plugin""s project file.

There should be exactly one occurrence of this macro in the source code for a Qt plugin, and it should be used where the implementation is written rather than in a header file.

Q_EXPORT_PLUGIN2(WebkitPluginFlash, FlashPlugin) 中的WebkitPluginFlash为编译之后生成的库的名字,这里的生成的库的完全名字为:libWebkitFlashPlugin.so, FlashPlugin 是插件类名。

如今只要把生成的libWebkitFlashPlugin.so插件库拷贝到webkitpluginfactory插件工厂能搜到的目次下就行了(本例中我在webkitpluginfactory.cpp中指定的地位为 const char *s = "/home/nxx/FlashPlugin-build-desktop";)。

上方的插件库和前面的工厂类,QWebView对象组合在一路就可以实现:

当用QWebView打开包含了须要 mimeType.name="application/x-shockwave-flash" 类型的插件的网页的时辰,就会调用到我们自定义的flashplugin插件了。

结果如下:

pluginView

Reference:
http://www.sunnybtoc.com/page/M0/S820/820143.html

Webkit Application

http://www.sunnybtoc.com/page/M0/S531/531605.html
http://www.mysjtu.com/page/M0/S531/531605.html

#coding:utf-8
 
import sys
from pprint import pprint
#import xml.etree.cElementTree as ElementTree
from PySide import QtCore
from PySide import QtGui
from PySide import QtWebKit
from PySide import QtNetwork
 
class MyWebView(QtWebKit.QWebView):
    def createWindow(self, p):
        pprint(p)
 
    def link_clicked(self, url):
        pprint(url)
 
class Mainwin(QtGui.QMainWindow):
 
    def __init__(self, title = "Test"):
        super(Mainwin, self).__init__()
        self.setWindowTitle(title)
 
        splitter = self.splitter = QtGui.QSplitter(self)
 
        stacker = self.stacker = QtGui.QStackedWidget(self)
 
        self.view = MyWebView(stacker)
        tw = self.tw = QtGui.QTreeWidget(self)
 
        splitter.addWidget(tw)
        splitter.addWidget(stacker)
 
        self.setCentralWidget(splitter)
        stacker.addWidget(self.view)
 
        self.view2 = MyWebView(stacker)
        stacker.addWidget(self.view2)
 
        self.menubar = self.createMenus()
        self.setMenuBar(self.menubar)
 
        self.locationEdit = QtGui.QLineEdit(self)
        self.locationEdit.setSizePolicy(QtGui.QSizePolicy.Expanding,
            self.locationEdit.sizePolicy().verticalPolicy())
        self.locationEdit.returnPressed.connect(self.onChangeLocation)
 
        self.createToolbar()
 
        self.statusbar = self.createStatusBar()
        self.setStatusBar(self.statusbar)
        self.view.loadProgress.connect(self.statusbar.progress.setValue)
 
        self.view.linkClicked.connect(self.change_location_to)
        self.view.urlChanged.connect(self.adjustLocation)
 
        self.view.page().linkHovered.connect(self.onLinkHovered)
        self.view2.page().linkHovered.connect(self.onLinkHovered)
 
        #self.view.loadFinished.connect(self.pageLoaded)
        #self.view2.loadFinished.connect(self.pageLoaded)
        self.layout()
 
    def createMenus(self):
        mb = QtGui.QMenuBar()
        fm = mb.addMenu("&File")
        act_open = fm.addAction("&Open")
        act_load = fm.addAction("&Load")
        act_exit = fm.addAction("E&xit")
        act_open.triggered.connect(self.OnOpenFile)
        act_load.triggered.connect(self.OnLoadUrl)
        act_exit.triggered.connect(self.close)
        act_exit.setShortcut("Ctrl+Q")
 
        viewMenu = mb.addMenu("&View")
        self.act_xml = act_viewXml = QtGui.QAction(
            self.style().standardIcon(
                        QtGui.QStyle.SP_DirOpenIcon),
                                               "View Xml", self)
        act_viewXml.triggered.connect(self.printDocument)
        viewMenu.addAction(act_viewXml)
 
        menu_ctl = mb.addMenu("&Ctrl")
        act_hide_show = menu_ctl.addAction("&Show hidden window")
        act_hide_show.setCheckable(True)
        #act_hide_show.setChecked(True)
        act_hide_show.toggled.connect(self.onShowView2)
 
        edit = mb.addMenu("&Edit")
        act_back = edit.addAction("&Back")
        act_back.triggered.connect(self.view.back)
        act_forward = edit.addAction("&Forward")
        act_forward.triggered.connect(self.view.forward)
        hl = mb.addMenu("&Help")
        self.act_help = hl.addAction("&About Qt")
        return mb
 
    def createToolbar(self):
        toolBar = self.addToolBar("Navigation")
        toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Back))
        toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Forward))
        toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Reload))
        toolBar.addAction(self.view.pageAction(QtWebKit.QWebPage.Stop))
        act_link = QtGui.QAction(
            self.style().standardIcon(
                        QtGui.QStyle.SP_DirLinkIcon),
                        "Load", self
        )
        act_link.triggered.connect(self.onLoadHome)
        toolBar.addAction(act_link)
        toolBar.addAction(self.act_xml)
        toolBar.addWidget(self.locationEdit)
 
    def createStatusBar(self):
        sb = QtGui.QStatusBar()
        sb.progress = QtGui.QProgressBar()
        sb.addPermanentWidget(sb.progress)
        return sb
 
    def printDocument(self):
        document = self.view.page().mainFrame().documentElement()
        if not document.isNull():
            h3_tag = document.find
 
    def loopElement(self, element, level = 0):
        e = element.firstChild()
        while not e.isNull():
            print "  " * level, e.localName()
            self.loopElement(e, level+1)
            e = e.nextSibling()
 
    def pageLoaded(self):
        document = self.view2.page().mainFrame().documentElement()
        print document.tagName()
        self.loopElement(document)
 
    def adjustLocation(self):
        self.locationEdit.setText(self.view.url().toString())
 
    def change_location_to(self, location):
        self.view.load(location)
        self.view.setFocus()
 
    def onLoadHome(self):
        self.view.load("file:///C:/versions/pyside_t/src/webkit_learn/dna%20-%20PubMed%20result.htm")
 
    def onChangeLocation(self):
        url = QtCore.QUrl.fromUserInput(self.locationEdit.text())
        self.view.load(url)
        self.view2.load(url)
        self.view.setFocus()
 
    def onShowView2(self, p):
        if p:
            self.stacker.setCurrentIndex(1)
        else:
            self.stacker.setCurrentIndex(0)
 
    def onLinkHovered(self, p):
        if p:
            self.statusbar.showMessage(p, 0)
        else:
            self.statusbar.showMessage(p)
 
    def OnLoadUrl(self):
        self.view.load("http://localhost")
 
    def OnOpenFile(self):
        t = QtGui.QFileDialog.getOpenFileName(self, "Open file dialog", "/", "All files(*.*)")
        if t[0] != "":
            print "you selected", t[0]
 
def main():
    app = QtGui.QApplication(sys.argv)
    mw = Mainwin("Test title")
    mw.show()
 
    QtNetwork.QNetworkProxyFactory.setUseSystemConfiguration(True)
 
    mw.act_help.triggered.connect(app.aboutQt)
    app.exec_()
 
if __name__ == "__main__":
    main()
7
2
11:16 AM
3657次查看
 
分类:Python 标签:Python
 
刚学PyQt4,发现Python的库实在太强大了,50行代码就能写出一个浏览器…
 
支持JavaScriptCSSAcid3浏览器兼容性测试能跑41分(IE 65分),地址如果没输全的话,会自动在前面加上http://。
 
参考了这篇文章:http://ogc-daily.blogspot.com/2009/04/pyqt-part-7.html
 
界面:
 
源代码如下(需要安装PyQt4):
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
 
class MyBrowser(QWidget):
 
    def __init__(self, parent = None):
        super(MyBrowser, self).__init__(parent)
        self.createLayout()
        self.createConnection()
 
    def search(self):
        address = str(self.addressBar.text())
        if address:
            if address.find('://') == -1:
                address = 'http://' + address
            url = QUrl(address)
            self.webView.load(url)
 
    def createLayout(self):
        self.setWindowTitle("keakon's browser")
 
        self.addressBar = QLineEdit()
        self.goButton = QPushButton("&GO")
        bl = QHBoxLayout()
        bl.addWidget(self.addressBar)
        bl.addWidget(self.goButton)
 
        self.webView = QWebView()
 
        layout = QVBoxLayout()
        layout.addLayout(bl)
        layout.addWidget(self.webView)
 
        self.setLayout(layout)
 
    def createConnection(self):
        self.connect(self.addressBar, SIGNAL('returnPressed()'), self.search)
        self.connect(self.addressBar, SIGNAL('returnPressed()'), self.addressBar, SLOT('selectAll()'))
        self.connect(self.goButton, SIGNAL('clicked()'), self.search)
        self.connect(self.goButton, SIGNAL('clicked()'), self.addressBar, SLOT('selectAll()'))
 
app = QApplication(sys.argv)
 
browser = MyBrowser()
browser.show()
 
sys.exit(app.exec_())

http://www.keakon.net/2009/07/02/%E7%94%A8PyQt4%E6%89%93%E9%80%A0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E6%B5%8F%E8%A7%88%E5%99%A8
http://acid3.acidtests.org/

Reference:
!!!
A C++ QtWebView based multi-tab browser - Eazy Browser (亿简浏览器)
https://code.google.com/p/okgo/source/browse/trunk/Eazy/webview.cpp?spec=svn20&r=20

Firefox (Gecko)
Middleware

python-Pyjamas

wxPython and thread
http://bbs.chinaunix.net/thread-822546-1-1.html