Archive for the '技术' Category

CSS中背景图片定位方法

九 15 2009 Published by under web

图片定位可以使用光影魔术手,和Photoshop来查看.
在CSS中,背景图片的定位方位有3种:

1)关键字:background-position: top right;

2)像素:background-position: 0px 0px;

3)百分比:background-position: 0% 0%;

上面这三句语句,都将图片定位在背景的左上角,表面上看效果是一样的,实际上第三种定位机制与前两种完全不同。

前两种定位,都是将背景图片左上角的原点,放置在规定的位置。请看下面这张图,规定的位置是“20px 10px”和”60px 50px”,都是图片的原点在那个位置上,图中用X表示。

bg2008050701

但是第三种定位,也就是百分比定位,不是这样。它的放置规则是,图片本身(x%,y%)的那个点,与背景区域的(x%,y%)的那个点重合。比如,如果放置位置是“20% 10%”,实际结果如下图,可以看到这个点是在图片本身的“20% 10%”的位置上。

bg2008050702

下面是一个有趣的例子。

背景图片是四个边长为100px的方块叠在一起:

bg2008050703

请问怎样才能将其横过来:

bg2008050704

答案是,在网页中先设置四个div区域:

    <div class="box1">
    </div>

    <div class="box2"">
    </div>

    <div class="box3">
    </div>

    <div class="box4">
    </div>

然后,这样编写CSS:

.box1, .box2, .box3, .box4 {
float:left;
width:100px;
height:100px;
position:relative;
background: #F3F2E2 url(1234.png) no-repeat;
}

.box1 {
background-position:0% 0%;
}

.box2 {
background-position:0% 33.33333%;
}

.box3 {
background-position:0% 66.66666%;
}

.box4 {
background-position:0% 100%;
}

最后的效果。可以看到第二和第三个方块的设置,并不是一般想象中的“0% 25%”和“0% 75%”。

不过说实话,这个例子用像素设置法更容易一些。使用百分比设置的主要优势在于,当页面缩放的时候,背景图片也会跟着一起缩放

No responses yet

域名泛解析

九 10 2009 Published by under web

现在我们要在一个空间放置多个二级域名,废话少说,直接进入主题.
例子:

1、http://blog.vouov.com/
2、http://music.google.cn/

以上这种形式的域名具体是怎么实现的呢?就PHP程序中涉及到得简单说一下
一、要做一个域名泛解析,就是说将 *.domain.com 解析到你的空间[服务器]上
二、要做一个服务器的泛解析,就apache来讲,要在apache的配置文件http.conf(具体的环境具体的文件名,自己注意下)中(直接添加到该配置文件的最后即可)

<VirtualHost *:80>
ServerAdmin  yuminglong@yeah.net
DocumentRoot /www/vouov
ServerName vouov.com
ServerAlias *.vouov.com
</VirtualHost>

三、rewrite 重写路径

RewriteEngine on
RewriteCond %{HTTP_HOST} ^[a-z0-9-]+.vouov.com$
RewriteRule ^/?$ /%{HTTP_HOST}
RewriteRule ^/([a-z0-9-]+).vouov.com/?$ /rewrite.php?u=$1 [L]

#含义是 例如test.vouov.com,将隐式打开的是www.vouov.com/rewrite.php?u=test这个页面
#注意:将这些放到一个.htaccess文件,然后放到网站根目录即可
#必须保证apache配置文件中的重写应用要打开,一般的空间供应商已默认打开这个模块了.如果没有打开按以下方法打开
1、去掉LoadModule rewrite_module modules/mod_rewrite.so前面出现的#号,即去掉注释
2、AllowOverride none改为AllowOverride All,在http.conf文件中搜索即可找到,修改即可
#rewrite更多规则可以参考apache文档

除了应用重写规则,我们也可以在PHP程序中来处理这些事情,

//二级域名
if(!isset($_GET['do']) &amp;&amp; $_SCONFIG['allowdomain']) {
$hostarr = explode(’.’, $_SERVER['HTTP_HOST']);
$domainrootarr = explode(’.’, $_SCONFIG['domainroot']);
if(count($hostarr) &gt; 2 &amp;&amp; count($hostarr) &gt; count($domainrootarr) &amp;&amp; $hostarr[0] != ‘www’ &amp;&amp; !isholddomain($hostarr[0])) {
showmessage(’enter_the_space’, $_SCONFIG['siteallurl'].’space.php?domain=’.$hostarr[0], 0);
}
}

注意:
第一步和第二步提到的泛解析问题,要注意的是如果我们做了真的做了 *.vouov.com的泛解析,那么任何二级域名,例如blog.vouov.com,就是之前我们做过的二级域名都将受到重写规则的影响,譬如我们之前的二级域名blog是解析到/www/vouov/blog目录的,那么做过以上三步之后,打开blog.vouov.com,实际打开的也是vouov.com/rewrite.php?u=blog,所以我们最好在重写规则中来修改blog的重写或者是在第二步中修改服务器的泛解析,将第二步中的ServerAlias *.vouov.com改为我们想要的二级域名
以上几种方法就是比较常用的二级域名实现.不要一直看,还不快动手试试.

No responses yet

session id 基础UUID

九 09 2009 Published by under 安全

首先UUID是通用唯一识别码 (Universally Unique Identifier, UUID),是一个软件建构的标准,亦为自由软件基金会 (Open Software Foundation, OSF) 的组织在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部份。一组 UUID,系由一串 16 字节(亦称 16 字节,或 128 位元)的16进位数字所构成,是故UUID理论上的总数为216 x 8=2128,约等于3.4 x 1038。也就是说若每奈秒产生1兆个UUID,要花100亿年才会将所有UUID用完。具体的可以参照(http://zh.wikipedia.org/wiki/UUID),在java中有一个这样的基础模块java.util.UUID .
UUID的版本

UUID具有多个版本,每个版本的算法不同,应用范围也不同。

首先是一个特例--Nil UUID--通常我们不会用到它,它是由全为0的数字组成,如下:

00000000-0000-0000-0000-000000000000

UUID Version 1:基于时间的UUID

基于时间的UUID通过计算当前时间戳、随机数和机器MAC地址得到。由于在算法中使用了MAC地址,这个版本的UUID可以保证在全球范围的唯一性。但与此同时,使用MAC地址会带来安全性问题,这就是这个版本UUID受到批评的地方。如果应用只是在局域网中使用,也可以使用退化的算法,以IP地址来代替MAC地址--Java的UUID往往是这样实现的(当然也考虑了获取MAC的难度)。

UUID Version 2:DCE安全的UUID

DCE(Distributed Computing Environment)安全的UUID和基于时间的UUID算法相同,但会把时间戳的前4位置换为POSIX的UID或GID。这个版本的UUID在实际中较少用到。

UUID Version 3:基于名字的UUID(MD5)

基于名字的UUID通过计算名字和名字空间的MD5散列值得到。这个版本的UUID保证了:相同名字空间中不同名字生成的UUID的唯一性;不同名字空间中的UUID的唯一性;相同名字空间中相同名字的UUID重复生成是相同的。

UUID Version 4:随机UUID

根据随机数,或者伪随机数生成UUID。这种UUID产生重复的概率是可以计算出来的,但随机的东西就像是买彩票:你指望它发财是不可能的,但狗屎运通常会在不经意中到来。

UUID Version 5:基于名字的UUID(SHA1)

和版本3的UUID算法类似,只是散列值计算使用SHA1(Secure Hash Algorithm 1)算法。

UUID的应用

从UUID的不同版本可以看出,Version 1/2适合应用于分布式计算环境下,具有高度的唯一性;Version 3/5适合于一定范围内名字唯一,且需要或可能会重复生成UUID的环境下;至于Version 4,我个人的建议是最好不用(虽然它是最简单最方便的)。

通常我们建议使用UUID来标识对象或持久化数据,但以下情况最好不使用UUID:

* 映射类型的对象。比如只有代码及名称的代码表。
* 人工维护的非系统生成对象。比如系统中的部分基础数据。

对于具有名称不可重复的自然特性的对象,最好使用Version 3/5的UUID。比如系统中的用户。如果用户的UUID是Version 1的,如果你不小心删除了再重建用户,你会发现人还是那个人,用户已经不是那个用户了。(虽然标记为删除状态也是一种解决方案,但会带来实现上的复杂性。)

One response so far

pyqt 4与google map结合应用

九 09 2009 Published by under python,工具

最近学习pyqt,在网上搜索到了做Google map的,发现那个使用图片作为显示的,感觉那样很不方便,所以想以HTML显示.运用pyqt4的QWebView显示
第一步申请Google map api key,然后进行开发.
第二步,写个运用Google map api进行解析的工具 GoogleMapsUtil.py.代码如下:

import urllib

GMap_KEY_ID = 'YOUR GOOGLE MAP API KEY'

def getGMapsGEO(qaddr):
     geo_url = 'http://maps.google.com/maps/geo?'+urllib.urlencode({'q':qaddr})+'&amp;output=csv&amp;key='+GMap_KEY_ID
     gdata = urllib.urlopen(geo_url)
     gdataArray = gdata.read().split(',')
     return gdataArray

def getGMapsStaticUrl(Latitudes, Longitudes, zoom=14, width=512, height=512):
     #print "--"+str(Latitudes)+"--"+str(Longitudes)+"--"+str(zoom)
     map_url = 'http://maps.google.com/staticmap?center='+str(Latitudes)+','+str(Longitudes)+'&amp;zoom='+str(zoom)+
         '&amp;size='+str(width)+'x'+str(height)+'&amp;maptype=mobile&amp;key='+GMap_KEY_ID+'&amp;sensor=false'
     return map_url

第三步,用qt designer拉出界面,然后转化为python代码,Ui_GoogleMaps.py 代码如下:

from PyQt4 import QtCore, QtGui

class Ui_DialogGoogleMaps(object):
    def setupUi(self, DialogGoogleMaps):
        DialogGoogleMaps.setObjectName("DialogGoogleMaps")
        DialogGoogleMaps.resize(773, 588)
        self.inputAddress = QtGui.QLineEdit(DialogGoogleMaps)
        self.inputAddress.setGeometry(QtCore.QRect(40, 30, 371, 20))
        self.inputAddress.setObjectName("inputAddress")
        self.labelAddress = QtGui.QLabel(DialogGoogleMaps)
        self.labelAddress.setGeometry(QtCore.QRect(10, 30, 31, 16))
        self.labelAddress.setObjectName("labelAddress")
        self.groupBoxMapCtrl = QtGui.QGroupBox(DialogGoogleMaps)
        self.groupBoxMapCtrl.setGeometry(QtCore.QRect(530, 40, 211, 121))
        self.groupBoxMapCtrl.setObjectName("groupBoxMapCtrl")
        self.ButtonUp = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonUp.setGeometry(QtCore.QRect(90, 10, 31, 31))
        self.ButtonUp.setObjectName("ButtonUp")
        self.ButtonDown = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonDown.setGeometry(QtCore.QRect(90, 90, 31, 31))
        self.ButtonDown.setObjectName("ButtonDown")
        self.ButtonLeft = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonLeft.setGeometry(QtCore.QRect(30, 50, 31, 31))
        self.ButtonLeft.setObjectName("ButtonLeft")
        self.ButtonRight = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonRight.setGeometry(QtCore.QRect(150, 50, 31, 31))
        self.ButtonRight.setObjectName("ButtonRight")
        self.ButtonZoom = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonZoom.setGeometry(QtCore.QRect(70, 50, 31, 31))
        self.ButtonZoom.setObjectName("ButtonZoom")
        self.ButtonNarrow = QtGui.QPushButton(self.groupBoxMapCtrl)
        self.ButtonNarrow.setGeometry(QtCore.QRect(110, 50, 31, 31))
        self.ButtonNarrow.setObjectName("ButtonNarrow")
        self.MapView = QtWebKit.QWebView(DialogGoogleMaps)
        self.MapView.setGeometry(QtCore.QRect(10, 60, 512, 512))
        self.MapView.setUrl(QtCore.QUrl("http://maps.google.com/staticmap?center=32.0583650,118.7964680&zoom=14&size=512x512&maptype=mobile&markers=32.0583650,118.7964680&key=ABQIAAAApIB1Ubv-TkAKBJ37W0Hh2RS1AC4DxUbsxJ-9A5H8anlW8PhTrBQW71UJo3SK1Lm1LK_DZxfeCJessA&sensor=false"))
        self.MapView.setObjectName("MapView")
        self.BtnSearch = QtGui.QPushButton(DialogGoogleMaps)
        self.BtnSearch.setGeometry(QtCore.QRect(440, 30, 75, 23))
        self.BtnSearch.setObjectName("BtnSearch")
        self.ListAddress = QtGui.QListWidget(DialogGoogleMaps)
        self.ListAddress.setGeometry(QtCore.QRect(530, 200, 211, 371))
        self.ListAddress.setFrameShape(QtGui.QFrame.StyledPanel)
        self.ListAddress.setObjectName("ListAddress")
        QtGui.QListWidgetItem(self.ListAddress)
        QtGui.QListWidgetItem(self.ListAddress)
        self.label = QtGui.QLabel(DialogGoogleMaps)
        self.label.setGeometry(QtCore.QRect(530, 180, 54, 14))
        self.label.setObjectName("label")

        self.retranslateUi(DialogGoogleMaps)
        QtCore.QMetaObject.connectSlotsByName(DialogGoogleMaps)

    def retranslateUi(self, DialogGoogleMaps):
        DialogGoogleMaps.setWindowTitle(QtGui.QApplication.translate("DialogGoogleMaps", "Google maps应用程序", None, QtGui.QApplication.UnicodeUTF8))
        self.labelAddress.setText(QtGui.QApplication.translate("DialogGoogleMaps", "地址:", None, QtGui.QApplication.UnicodeUTF8))
        self.groupBoxMapCtrl.setTitle(QtGui.QApplication.translate("DialogGoogleMaps", "地图控制", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonUp.setText(QtGui.QApplication.translate("DialogGoogleMaps", "上", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonDown.setText(QtGui.QApplication.translate("DialogGoogleMaps", "下", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonLeft.setText(QtGui.QApplication.translate("DialogGoogleMaps", "左", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonRight.setText(QtGui.QApplication.translate("DialogGoogleMaps", "右", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonZoom.setText(QtGui.QApplication.translate("DialogGoogleMaps", "大", None, QtGui.QApplication.UnicodeUTF8))
        self.ButtonNarrow.setText(QtGui.QApplication.translate("DialogGoogleMaps", "小", None, QtGui.QApplication.UnicodeUTF8))
        self.BtnSearch.setText(QtGui.QApplication.translate("DialogGoogleMaps", "搜索", None, QtGui.QApplication.UnicodeUTF8))
        self.ListAddress.setSortingEnabled(False)
        __sortingEnabled = self.ListAddress.isSortingEnabled()
        self.ListAddress.setSortingEnabled(False)
        self.ListAddress.item(0).setText(QtGui.QApplication.translate("DialogGoogleMaps", "结果1", None, QtGui.QApplication.UnicodeUTF8))
        self.ListAddress.item(1).setText(QtGui.QApplication.translate("DialogGoogleMaps", "新建项目", None, QtGui.QApplication.UnicodeUTF8))
        self.ListAddress.setSortingEnabled(__sortingEnabled)
        self.label.setText(QtGui.QApplication.translate("DialogGoogleMaps", "搜索结果:", None, QtGui.QApplication.UnicodeUTF8))

from PyQt4 import QtWebKit

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    DialogGoogleMaps = QtGui.QDialog()
    ui = Ui_DialogGoogleMaps()
    ui.setupUi(DialogGoogleMaps)
    DialogGoogleMaps.show()
    sys.exit(app.exec_())

第四步:写界面的动作插槽,GoogleMapsExec.py,代码如下:

# -*- coding: utf-8 -*-

"""
Module implementing GoogleMapsExec.
"""
from PyQt4 import QtCore, QtGui
from PyQt4.QtGui import QDialog
from PyQt4.QtCore import pyqtSignature

from Ui_GoogleMaps import Ui_DialogGoogleMaps

import GoogleMapsUtil

class GoogleMapsExec(QDialog, Ui_DialogGoogleMaps):
    """
    Class documentation goes here.
    """
    jindu = 32.058365
    weidu = 118.796468
    zoom = 14
    def __init__(self, parent = None):
        """
        Constructor
        """
        QDialog.__init__(self, parent)
        self.setupUi(self)

    @pyqtSignature("")
    def on_ButtonUp_clicked(self):
        """
        Slot documentation goes here.
        """
        self.jindu =self.jindu-0.01
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_ButtonDown_clicked(self):
        """
        Slot documentation goes here.
        """
        self.jindu = self.jindu+0.01
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_ButtonLeft_clicked(self):
        """
        Slot documentation goes here.
        """
        self.weidu = self.weidu-0.01
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_ButtonRight_clicked(self):
        """
        Slot documentation goes here.
        """
        self.weidu = self.weidu+0.01
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_ButtonZoom_clicked(self):
        """
        Slot documentation goes here.
        """
        if self.zoom < 18:
             self.zoom = self.zoom+1
        else:
            return
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_ButtonNarrow_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        if self.zoom > 0:
             self.zoom = self.zoom-1
        else:
            return
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))

    @pyqtSignature("")
    def on_BtnSearch_clicked(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        qaddr = self.inputAddress.text().toUtf8()
        center = GoogleMapsUtil.getGMapsGEO(qaddr)
        self.jindu = float(center[2])
        self.weidu = float(center[3])
        self.zoom = 14
        GmapUrl = GoogleMapsUtil.getGMapsStaticUrl(self.jindu, self.weidu, self.zoom)
        self.MapView.setUrl(QtCore.QUrl(GmapUrl))
        #QtGui.QListWidgetItem(self.ListAddress)
        #self.ListAddress.item(2).setText(QtGui.QApplication.translate("DialogGoogleMaps", "结果3", None, QtGui.QApplication.UnicodeUTF8))

    @pyqtSignature("QListWidgetItem*")
    def on_ListAddress_itemClicked(self, item):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        pass

    @pyqtSignature("")
    def on_ListAddress_itemSelectionChanged(self):
        """
        Slot documentation goes here.
        """
        # TODO: not implemented yet
        pass

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    DialogGoogleMaps = GoogleMapsExec()
    DialogGoogleMaps.show()
    sys.exit(app.exec_())

第五步:这样你运行一下就可以看到最终的成果了.如图.呵呵:

可以在地址框里输入查询的地址,这个程序还没有完善好.怕自己忘记先记录下来吧.等有时间在加以完善.源代码在我的附件里.呵呵

googlemapsapp_pyqt4.zip

No responses yet

pyqt通过qtwebkit嵌入显示html与js

九 09 2009 Published by under python

透过Python体验QtWebKit快速开发

转载:http://blog.linux.org.tw/~jserv/archives/002026.html
稍早写过一篇文章[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("""
&lt;script&gt;function message() { return "Clicked!"; }&lt;/script&gt;
&lt;h1&gt;QtWebKit + Python sample program&lt;/h1&gt;
&lt;input type="button" value="Click JavaScript!"
onClick="alert('1 ' + message())"/&gt;
&lt;input type="button" value="Click Python!"
onClick="python.alert('1 ' +
python.message())"/&gt;
&lt;br /&gt;
&lt;iframe src="http://www.google.com/"
width="750" height="500"
scrolling="no"
frameborder="0"
align="center"&gt;&lt;/iframe&gt;
""")

我们定义的class继承自QtWebKit中的class QWebView,在初始化时,即呼叫resize(), show(), setHTML()等method。此外,与其说上述程式列表为Python程式语言,不如说就是HTML网页原始码。熟悉网页程式设计者,一眼就可发现 我们在两个input button上建立Javascript事件关联,其中一个呼叫alert() method来显示对话框,而另一个则比较特别:

onClick="python.alert('1 ' +
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 &amp;)")
@pyqtSignature("QString")
def alert(self, msg):
self.emit(SIGNAL('contentChanged(const QString &amp;)'), 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 &amp;)"),
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 &amp;)"),
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授权发行,本范例也是如此。
由jserv发表于May 21, 2008 10:01 PM

No responses yet

Eric4的中文设置

九 09 2009 Published by under python,工具

下载了中文包eric4-i18n-zh_CN.GB2312-4.3.6.zip,解压后,安装一闪,在Interface的语言设置里却没有中文选项。不用说没有安装成功.
上 网所了一下资料,手动将i18n目录下的eric4_zh_CN.GB2312.qm和eric4_zh_CN.GB2312.ts拷贝到 C:Python25Libsite-packageseric4i18n,然后在Interface的语言设置里有中文选项了.选中 ->应用->重启.然后就是以中文启动了.下面提供Eric4的中文包下载

eric4-i18n-zh_CN.GB2312-4.3.6.zip

2 responses so far

« Prev